1

在有关编译器中使用的中间表示的书籍、文章、幻灯片和教程中,三地址代码 (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

但我必须承认,我不知道如何翻译中间 TAC,因为 MIPS(和许多其他 RISC 处理器)没有能够同时获取两个内存操作数的指令。

所以我的问题是:(1)如何将这种 TAC 转换为 RISC 指令,以及;(2) 为什么现在这么多处理器都是基于 RISC 的,为什么通常使用这种 TAC?它是从处理器过去更多地基于 CISC 并允许从内存中多次提取时遗留下来的吗?

或者

也许我对变量在此类 TAC 上的含义有错误的解释。如果是这样,我应该如何解释 TAC 中的这些变量?

4

1 回答 1

2

如何将这样的 TAC 转换为 RISC 指令

加载(或移入a),加载到其他寄存器,然后将该其他寄存器添加到.t1t0t1bt1

我在这里假设临时变量被分配给同名的寄存器,并且变量保存在内存中,因为这似乎是您所做的假设。你不能假设一般情况下(至少不是第一部分,因为可能有比寄存器更多的临时变量 - 在可能的情况下将变量存储在寄存器中也很常见,但当然你不必这样做),但是问题不是关于寄存器分配的,所以我不会在这里讨论。

为什么现在这么多处理器都是基于 RISC 的,为什么会普遍使用这种 TAC?

当今最常见的处理器架构是 x86、x64 和 ARM,所有这些架构都可以r1 = r2 + r3在一条指令中执行,因此您的前提并不完全准确。但即使是这样,TAC 的主要目标也不是尽可能直接地映射到程序集。

相反,目标是成为编译器在最终生成目标代码之前通常执行的优化和分析的有用格式。通过在 IR 中添加额外的移动来使代码更复杂不会进一步实现该目标,因此没有完成。

于 2018-11-29T15:49:21.693 回答