我正按照经典书籍编译器的说明创建编译器静态分析模块。 Ullman等人的原理,技术和工具。
我将AST表示转换为三个地址代码表示进行优化(现在基本上是死代码消除和复制传播)然后我转换成类似的三个地址代码表示(更适合转换为字节码)。
为此,我必须创建时间变量,以便我的代码表示如下所示:
t = IntLit(0)
t1 = left < right
t2 = !t1
cjump if t2 to L0:
t3 = number[right]
v = t3
t4 = left - IntLit(1)
i = t4
j = right
cont01 = True()
L2:
t5 = !cont01
cjump if t5 to L3:
cont02 = True()
L4:
t6 = !cont02
cjump if t6 to L5:
t7 = i + IntLit(1)
i = t7
t8 = number[t7]
Removed dead code: aux03 = t8
t10 = t8 < v
t9 = !t10
t11 = !t9
cjump if t11 to L6:
cont02 = False()
jump L7:
L6:
cont02 = True()
L7:
jump L4:
L5:
cont02 = True()
L8:
t12 = !cont02
cjump if t12 to L9:
t13 = j - IntLit(1)
j = t13
t14 = number[t13]
Removed dead code: aux03 = t14
t16 = v < t14
t15 = !t16
t17 = !t15
cjump if t17 to L10:
cont02 = False()
jump L11:
L10:
cont02 = True()
L11:
jump L8:
L9:
t18 = number[i]
t = t18
t19 = number[j]
number[i] = t19
number[j] = t18
t21 = i + IntLit(1)
t20 = j < t21
t22 = !t20
cjump if t22 to L12:
cont01 = False()
jump L13:
L12:
cont01 = True()
L13:
jump L2:
L3:
t23 = number[i]
number[j] = t23
t24 = number[right]
number[i] = t24
number[right] = t
t25 = i - IntLit(1)
t26 = This().Sort(left,t25)
Removed dead code: nt = t26
t27 = i + IntLit(1)
t28 = This().Sort(t27,right)
Removed dead code: nt = t28
jump L1:
L0:
Removed dead code: nt = IntLit(0)
L1:
return IntLit(0)
我想摆脱代码生成的时间变量,但我看起来不能。请考虑以下方法:
def printing() : Int = {
var i : Int;
var j : Int;
var z : Int;
i = this.printing1();
z = i;
println(z);
return i;
}
我得到以下代码:
t1 = This().printing1()
Removed dead code: i = t1
Removed dead code: z = t1
println(t1)
return t1
我正在做的删除时间变量的方法是提前传播它们的值。在正常情况下,我只需要提前一份。但是,对于复制传播,我可能需要多次这样做。
这应该没有问题,但结合代码消除我无法保证方法调用被分配给非时间变量(请查看上面的代码)。
因此,当只有一个超前发生的时间变量存储方法调用结果时,我显然可以将方法调用复制到它并结束。如果没有,我可以使用POP指令从堆栈中消除结果。但是当出现多次时,我无法复制该指令,因为我会接到多次调用。
我的结论是我需要保留时间变量。
是否有其他策略可以帮助我获得时间变量的芦苇?
答案 0 :(得分:1)
我不知道是否可以使用您当前的内部表示(即AST)删除所有临时变量,但您可以使用寄存器分配算法减少其数量。
按代码查看每次生成一个新的时间变量。这类似于编译器假设(为简单起见)CPU具有无限寄存器时的问题。然后它必须生成实际使用架构所具有的有限数量的寄存器的代码。为了将无限寄存器/变量减少到更小的有限集,使用寄存器分配算法。
您可以在Engineering a Compiler by Keith Cooper书中找到关于主题的整章(13)。
how this is done in real compilers like GCC.
上还有很多信息我想到的是将变量视为寄存器,然后使用寄存器分配算法将其数量减少到最低限度。
这个想法显然只是我的十美分。设计编译器确实是一个非常复杂的问题,需要深入协作来解决您的实际问题。