在有关编译器中使用的中间表示的书籍,文章,幻灯片和教程中,三地址代码(TAC)是常见的代码。我的问题是有关以下TAC的示例
t0 = a
t1 = a + b
a = t2
在此示例中,我们有三行带有两个变量:a和b;和三个临时时间:t0,t1和t2。例如,将此类TAC转换为MIPS组装时,第一个和最后一个很容易如下所示:
lw t0, sp, a.offset
sw t2, sp, a.offset
但是我必须承认,由于MIPS(以及许多其他RISC处理器)没有能够同时提取两个内存操作数的指令,因此我不知道如何转换中间TAC。
所以我的问题是:(1)如何将此类TAC转换为RISC指令;以及(2)为什么当如今有如此多的处理器是基于RISC的处理器时,通常会使用这种TAC?从处理器以前更基于CISC并允许从内存中进行多次提取起,这是否是一种遗产?
OR
对于变量对此类TAC的含义,我可能有错误的解释。如果是这样,我应该如何解释TAC中的此类变量?
答案 0 :(得分:2)
如何将此类TAC转换为RISC指令
将a
加载到t1
中(或将t0
移到t1
中),将b
加载到其他寄存器中,然后将该其他寄存器添加到{ {1}}。
我在这里假设临时变量被分配给相同名称的寄存器,并且变量被保存在内存中,因为这似乎是您所做的假设。您一般不能假设(至少不是第一部分,因为临时数可能比寄存器多-尽可能在寄存器中存储变量也是很常见的,但是当然不必这样做),但是问题不是关于寄存器分配的,所以我在这里不再赘述。
为什么当当今有许多处理器是基于RISC的处理器时,通常会使用这种TAC?
当今最常见的处理器体系结构是x86,x64和ARM,它们全部都可以在一条指令中执行t1
,因此您的前提并不完全准确。但是,即使这样,TAC的主要目标也不是尽可能直接地映射到程序集。
相反,目标是成为编译器通常在最终生成目标代码之前执行的优化和分析的有用格式。通过在IR中添加额外的动作来使代码更加复杂,并不能实现该目标,因此无法实现。