将SSA转换为堆栈机

时间:2018-07-14 14:33:36

标签: compiler-construction cil ssa stack-machine

众所周知,如何将代码从SSA表示形式转换为寄存器机器。 (基本上,图形着色寄存器的分配是这种转换的核心。)

但是,从SSA转换到堆栈计算机的一般方法是什么? (在我正在研究的情况下,是CIL字节码。)由于不需要寄存器分配,我希望它会更简单吗?

2 个答案:

答案 0 :(得分:2)

我从事编译器构建已经15年了,所以我可能不记得所有细节了。

基本上,在退出SSA时,您需要在所有块的末尾生成加载/存储指令到虚拟寄存器中,从而在后继块中建立phi节点。这将导致生成许多虚拟寄存器,通常比实际计算机上的可用寄存器高。因此,您可以在局部变量上应用寄存器分配以得出真实的寄存器,从而将那些不合适的值溢出到堆栈中。

对于基于堆栈的计算机,只需不执行最后一步。在编译后的函数中,最终得到的虚拟寄存器数量与phi节点的数量大致相同(该算法实际上并不简单,一个好的出发点是Ron Cytron,Jeane的论文《有效地计算单个静态分配形式和控制依赖图》 Ferrante等人。)这些虚拟寄存器将成为您的局部变量。

从虚拟寄存器(局部变量)读取要由操作使用的值时,首先使用一条指令将其压入堆栈。 Java VM iload index指令就是这样一个示例:它将局部变量加载到索引处并将其值压入堆栈。 (请参见https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-6.html#jvms-6.5.iload) 将值写入局部变量时,可以从堆栈中弹出它。请参见Java VM istore index指令(请参见https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-6.html#jvms-6.5.istore)。

例如,如果在退出SSA之后需要进行编码

local 5 = MUL local[2], local[4]

然后您需要生成如下内容:

ILOAD 4 ILOAD 2 MUL ISTORE 5

对于CIL字节码,您具有等效的ldargstarg操作。

当然,有很多优化空间,以避免多余的负载/存储。

答案 1 :(得分:1)

SSA基本上是一组“逻辑”门,每个门都有多个输入,通常是一个输出。

因此,从本质上讲,您需要将每个门视为一组输入堆栈推,然后由零操作数运算符将堆栈值组合为该门的结果。例如,带有乘法和累加运算符的作为SSA的a + b * c具有对a,b,c的3次推送,其后是MAC_TOS运算符。

如果有一系列这样的门,您可以获取一个早先门的输出,该门已经在堆栈中,并且就像已被推送一样。

因此,SSA计算看起来像是一门n元门,输出从根开始。

您可以按固定顺序遍历树,推送尚未推送的操作数,并在计算完所有操作数后生成门运算符。

因此,SSA图(树):

a 
  \
   * 
b /  \
      +
c     /
  \  /
   -
  /
d

可用于生产

push a
push b
times
push c
push d
subtract
times