编译器到底如何将 AST 转换为汇编指令

问题描述 投票:0回答:1

我或多或少对编译器如何将 AST 转换为机器代码感到困惑。我的假设是一些编译器遍历树并用相应的汇编指令替换每个节点。我正在尝试编写小型编译器,但我仍然需要获得有关这部分是如何完成的更多信息。

例如

// code representation 
int a = 1+2;
// AST representation
     =
    / \
  int  +
   |  / \
   a  1  2

# final assembly after traversing the tree
# Allocate space for variable 'a'
ALLOC a, 4       # Assuming 'int' is 4 bytes

# Evaluate the expression '1 + 2'
LOAD r1, 1       # Load constant 1 into register r1
LOAD r2, 2       # Load constant 2 into register r2
ADD r3, r1, r2   # Add values in registers r1 and r2, store result in r3

# Store the result in variable 'a'
STORE a, r3

我知道我所描述的可能效率低下。然而,将 AST 转换为 IR 语言更加令人困惑。

谢谢!

recursion assembly compiler-construction abstract-syntax-tree
1个回答
0
投票

这并不重要,但我的 AST 会省略/删除

INT
部分,作为声明单独处理,留下 a=1×2 用于代码生成。

最简单的做法是假设一个底层堆栈机,然后对寄存器机进行优化和其他调整。

对于最简单的 a=1+2,我们将从 = 开始,然后评估 lhs 的地址,然后评估 rhs 的值,然后间接存储。

因此,生成的代码将类似于pushaddr a,push 2 push 2,add istore。

您可以看到 lhs 的计算方式与 rhs 不同,因此这是传递给评估器/代码生成器的参数。这个a[i]=b[j]生成a[i]的地址和b[j]的值,然后istore..

变得更复杂,我们还将提供除了 lhs/rhs 之外的仅副作用选项,因此 a+b;例如,不会生成任何实际代码。

Furtee,我们可以通过询问地址或变量来延迟 a= 的 cofe 的生成。这样,我们就可以延迟 Pushaddr a 的代码生成,而是将一个值返回给变量 a 的调用者 (=)。结果代码是序列,然后是push 1,push 2,add,pop/store a - 直接存储到a而不是存储到a的地址。

接下来,我们可以切换到寄存器机器,并将稍后解析的真实或虚假寄存器分配给 resl 寄存器。我们不假设 + 的操作数是堆栈之一,而是查看 1、2 求值返回的值,并假设它们现在位于寄存器中。

我们可以通过这种方式继续渐进式改进。

与 if/while 一起使用的另一种评估方法是评估分支到目标的条件表达式。因此,不是为 i 形成 0 1 结果 < 10, then branching on true/false we might branch more directly on a comparison of i with 10.

我们可以应用很多像这样的小改进。

© www.soinside.com 2019 - 2024. All rights reserved.