6.3.1 由中间指令产生汇编代码的主要流程
在这一小节,我们可把关注的焦点放在“如何把某条中间代码翻译成汇编代码”上。UCC编译器的中间代码是如下所示的四元式,包括运算符和3个操作数。
<运算符opcode,目的操作数DST,源操作数SRC1,源操作数SRC2>
当然有些中间代码只需要用到opcode和DST就可以了,例如,无条件跳转指令“goto BB2;”就不需要SRC1和SRC2。为了便于汇编代码的生成,UCC编译器在ucl\X86Linux.tpl中定义了许多汇编指令的模板。在X86平台上,无条件跳转指令的汇编指令为jmp,对应的指令模板如下所示:
//无条件跳转
TEMPLATE(X86_JMP, "jmp %0")
其中,X86_JMP是模板”jmp %0”的编号,通过编号可找到对应的模板。模板中的“%0”充当占位符的作用,代表第0个操作数,即目的操作数DST,在汇编代码生成时,“%0”会被目的操作数DST所替代;而”%1”代表第1个操作数,即源操作数SRC1,“%2”代表第2个操作数,即源操作数SRC2。图6.3.1第29至31行的宏DST、SRC1和SRC2分别表示中间指令inst里的这3个操作数。假设跳转的目标是BB2,则根据模板“jmp %0”,我们可产生汇编指令“jmp BB2”。
下面,我们来举例介绍一下,如何由中间指令的运算符opcode出发,找到对应的汇编指令模板号。在中间代码层次,UCC编译器用ADD来表示加法指令,但在汇编层次,整数加法和浮点数加法对应的汇编指令是不一样的,如图6.3.1第22至25行所示。为了能通过中间代码的运算符ADD,快速地找到对应的汇编指令模板编号,ucl\X86Linux.tpl中的各模板是按一定顺序排列的。例如,当我们要进行两个double类型浮点数的加法运算时,其中间指令里的运算符opcode为ADD,类型为DOUBLE,通过第1至15行的函数TypeCode,我们可得到DOUBLE对应的类型编码为F8。以ADD和F8作为宏参数,通过第27行的宏ASM_CODE(),我们就可得到对应的模板号X86_ADDF8,如图6.3.1第26行所示。
<