我正在为 Renjin(R 代表 JVM)开发字节码编译器,并尝试将中间三地址码 (TAC) 表示形式转换为字节码。我查阅过的所有有关编译器的教科书都讨论了代码生成过程中的寄存器分配,但我还没有找到任何用于在基于堆栈的虚拟机(如 JVM)上生成代码的资源。
简单的 TAC 指令很容易翻译成字节码,但当涉及临时指令时我会有点迷失。有没有人有任何描述这一点的资源指针?
这是一个完整的示例:
原始 R 代码如下所示:
x + sqrt(x * y)
TAC 红外:
0: _t2 := primitive<*>(x, y)
1: _t3 := primitive<sqrt>(_t2)
2: return primitive<+>(x, _t3)
(暂时忽略我们不能总是在编译时解析对原语的函数调用的事实)
生成的 JVM 字节代码(大致)如下所示:
aload_x
dup
aload_y
invokestatic r/primitives/Ops.multiply(Lr/lang/Vector;Lr/lang/Vector;)
invokestatic r/primitives/Ops.sqrt(Lr/lang/Vector;)
invokestatic r/primitives/Ops.plus(Lr/lang/Vector;Lr/lang/Vector;)
areturn
基本上,在程序的顶部,当我到达 TAC 指令 2 时,我已经需要考虑在堆栈开头需要局部变量 x。我可以通过以下方式思考这一点:手动,但我很难通过算法来正确地完成此操作。有什么指点吗?
最佳答案
将 3 地址表示转换为堆栈比将堆栈一转换为 3 地址更容易。
您的顺序应如下:
- 形成基本 block
- 执行 SSA 转换
- 在基本 block 内构建表达式树
- 执行寄存器调度(同时进行 phi 删除),为上一步未消除的寄存器分配局部变量
- 发出 JVM 代码 - 寄存器进入变量,表达式树简单地扩展到堆栈操作
关于compilation - 从三地址代码到 JVM 字节码的代码生成,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8427888/