回填
Last updated
Last updated
先生成基于标号的三地址代码
再遍历三地址码将标号替换为对应索引
继承属性,自顶向下。生成新标号时并向下(右)传递,生成跳转语句时填入。经过(生成)跳转目标时插入生成代码中。
如上图,在B.true时就生成即将跳转的新标号,并填入到goto语句中;当经过预期跳转的目标时将标号插入。
新思路:
综合属性,自底向上。经过(生成)跳转目标时,记录其索引。将跳转目标索引填入到相应跳转语句中。
为布尔表达式和控制流语句生成目标代码,关键问题:某些跳转指令应该跳转到哪里?
基本思想:
翻译过程中,若遇到跳转目标未知的情况,则先生成跳转指令坯,备用。goto __/if ... goto __
将指令坯并向父节点传递(综合属性)
翻译过程中,若遇到某条指令是跳转目标,则记录其索引,备用
当父节点收集齐跳转指令坯及其跳转目标时,将索引填入指令坯
同一列表中跳转指令的目标都相同。
辅助函数:backpatch(p,i)
:将i作为跳转目标插入p的所有指令中。扫描到B.truelist中的跳转目标的索引,则调用该函数将这个索引插入B.truelist的所有指令中。
所以,在文法中需要引入非终结符号(SDT)
M:在适当的时候获取将要生成指令的索引,用M.instr记录跳转目标指令的索引
N:在适当的位置生成跳转指令坯,生成goto指令坯,N.nextlist包含该指令索引
生成指令坯,然后加入相应的list。原来跳转到B.true的指令,现在加入到B.truelist中;原来跳转到B.false的指令,现在加入到B.falselist中。true/false属性的赋值,在回填方案中对应为相应的truelist/falselist的赋值或者merge。
辅助函数:
makelist(i)
:创建一个包含跳转指令(其索引为i)的列表
merge(p1,p2)
:将p1和p2指向的索引列表合并然后返回
虽然break、continue在语法上是一个独立的句子,但是它的代码和外围语句相关。
方法:(break语句)
跟踪外围循环语句S
生成一个跳转指令坯
将这个指令坯的索引加入到S的nextlist中