ch15-ir-backpatch-控制流语句翻译中的地址回填技术
使用标签标记跳转目标
Java Bytecode: 使用地址值作为跳转目标
- 每条指令占据多少字节,第四条指令编号为3,占据了三个字节,下一个指令编号为6
- 地址是一个绝对地址
- 不适用符号化的地址,而是使用实际的绝对地址:处于效率考虑,减少翻译的过程
- 可以用两次扫描来确定地址,但是效率低下
如何在一趟扫描中生成跳转目标的地址?
难点:如果我要往前跳,不知道具体地址
选择方案依旧为:让布尔表达式B生成跳转指令
B计算不出 B.false 对应的指令地址,B没有S的信息
回填技术
标签地址先不填,等父节点S翻译到S1后再回填
回填 (Backpatching) 技术: 子节点挖坑、祖先节点填坑
- 子节点暂时不指定跳转指令的目标地址
- 待祖先节点能够确定目标地址时回头填充
父节点通过综合属性收集子节点中具有相同目标的跳转指令
- M唯一的作用就是产生
- B.truelist就是一个集合,将所有去往B.true的指令收集起来
- makelist是API
- nextinstr自动加一
- 第一个gen知道是去往B.true所以加入B.truelist
- 第二个gen同理
- 所有去往B.true的指令的集合就是所有去往B1.false的指令的集合
帮子节点填充
-
merge就是把B1.false和B2.false(都是去往B.false)合并起来,赋值给B.falselist
-
B2为true,因为短路,所以即是去往B.true
-
backpatch就是把所有去往B1.true的指令集合替换为B2的第一条指令的地址值
-
M是获取当前指令的下一条指令(B2的第一条指令)的地址
例子
考试提供生成规则
x < 100 || (x > 200 &&x != y)
空着的goto由if和while这一类的父节点来填充
- 引入N,
if语句
- 去往S.next的指令的集合:去B.false的和去S1.next的
- S回填B.truelist,地址为S1的第一条指令
if-else语句
- temp是为了合并三个next
- N.nextlist里只有一条指令,就是N生成的gen(goto-‘’),这一条指令就是去往s.next
- M1回填B.true,M2回填B.false
while语句
- 第一个gen是往回跳转,所以可以直接填上
- S1.next: 回到B.label:begin
其他顺序语法结构
只有 (3) 与 (7) 生成了新的代码, 控制流语句的主要目的是**“控制” 流**(生成goto指令)。
例子
会涉及的语法:
总结
- 为左部非终结符布尔表达式 B 计算综合属性 B.truelist 与 B.falselist
- 为左部非终结符赋值语句/产生赋值语句的语句 S/L 计算综合属性 S/L.nextlist
- 并为已能确定目标地址的跳转指令进行回填 (考虑每个综合属性)