2

我正在为 Renjin(JVM 的 R)开发字节码编译器,并且正在尝试将我们的中间三地址码 (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。我可以手动考虑这一点,但我'在思考通过算法正确地做到这一点时遇到了麻烦。任何指针?

4

1 回答 1

3

将 3-address 表示转换为 stack 比 stack one 转换为 3-address 更容易。

您的顺序应如下所示:

  1. 形成基本块
  2. 执行 SSA 转换
  3. 在基本块中构建表达式树
  4. 执行寄存器调度(和同时删除 phi)为上一步未消除的寄存器分配局部变量
  5. 发出 JVM 代码 - 寄存器进入变量,表达式树被简单地扩展为堆栈操作
于 2011-12-08T08:18:55.447 回答