【发布时间】:2018-02-24 22:09:32
【问题描述】:
我有一个带有 funcDef、funcCall、literals 等节点的 AST。我正在研究我的编译器的代码生成器部分,为 x86_64 生成程序集。我的问题是生成 AST 的代码的“正确”(行业标准)方式是什么:是否多次传递,例如计算需要多少局部变量以便使用该值来递减堆栈指针?此外,复杂的 AST,例如一个 funcCall,一个参数是另一个 funcCall 等等,是如何解析为 ASM 的?
将我的 AST 转换为非常简单的 IR(SSA?)是否明智?另外,由于我对代码生成理论一窍不通,有没有什么好书专注于这方面的?
谢谢!
【问题讨论】:
-
没有标准答案。作为编译器编写者,您为编译器设定目标。答案取决于目标。最小、最快、最简单的编译器需要很少的内存,直接从解析器一次性发出代码,但质量不高。最高度优化的编译器使用几种中间形式、辅助数据结构和多次传递。而且它们非常复杂。如果您陈述自己的目标,就有可能为实现目标的合理方法设定界限。
-
@Gene:我正在寻找最简单的解决方案(我这样做是为了学习基础知识)。一次运行的编译器如何可能?如果您在 funcCall 中有一个类似 OP 且 funcCall 作为变量的 AST,那么您需要知道以便能够在父调用之前
movq %rax, rdi,不是吗?再次为愚蠢的问题感到抱歉,我真的只是在努力学习。谢谢! -
对于变量,通常至少有两个阶段——SSA 表单生成和寄存器分配,只有后者关注目标主机细节,因为前者可以与架构无关。组装阶段本身也至少有两次通过,以便以最简单的方式解决向前跳跃的目标。很难更详细地回答您的问题,因为您所问的主题非常广泛,基本上约占编译器设计的三分之二。
-
关于实际代码生成。例如,如果您针对基于 x86 的 Intel 处理器,您可能希望阅读 ia 32 architectures optimization manual
-
你可能想看看 LLVM 工具链。它需要一个 SSA(主要是)IR,并且可以生成所有数量的架构机器代码。
标签: assembly compiler-construction abstract-syntax-tree codegen ssa