ch15-ir-backpatch-控制流语句翻译中的地址回填技术

使用标签标记跳转目标

image-20230622145609928

Java Bytecode: 使用地址值作为跳转目标

image-20230622145746213

  • 每条指令占据多少字节,第四条指令编号为3,占据了三个字节,下一个指令编号为6
  • 地址是一个绝对地址
  • 不适用符号化的地址,而是使用实际的绝对地址:处于效率考虑,减少翻译的过程
  • 可以用两次扫描来确定地址,但是效率低下

如何在一趟扫描中生成跳转目标的地址?

难点:如果我要往前跳,不知道具体地址

选择方案依旧为:让布尔表达式B生成跳转指令

image-20230622150236158

B计算不出 B.false 对应的指令地址,B没有S的信息

回填技术

标签地址先不填,等父节点S翻译到S1后再回填

回填 (Backpatching) 技术: 子节点挖坑、祖先节点填坑

  • 子节点暂时不指定跳转指令的目标地址
  • 待祖先节点能够确定目标地址时回头填充

父节点通过综合属性收集子节点中具有相同目标的跳转指令

image-20230622152721058

  • M唯一的作用就是产生

image-20230622152852697

  • B.truelist就是一个集合,将所有去往B.true的指令收集起来
  • makelist是API
  • nextinstr自动加一

image-20230622153252292

  • 第一个gen知道是去往B.true所以加入B.truelist
  • 第二个gen同理

image-20230622153519707

  • 所有去往B.true的指令的集合就是所有去往B1.false的指令的集合

帮子节点填充

image-20230622153752740

  • 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)

image-20230622154644961

image-20230622155219283

image-20230622155316362

空着的goto由if和while这一类的父节点来填充

image-20230622155336961

  • 引入N,

if语句

image-20230622155449711

  • 去往S.next的指令的集合:去B.false的和去S1.next的
  • S回填B.truelist,地址为S1的第一条指令

if-else语句

image-20230622155719893

  • temp是为了合并三个next
  • N.nextlist里只有一条指令,就是N生成的gen(goto-‘’),这一条指令就是去往s.next
  • M1回填B.true,M2回填B.false

while语句

image-20230622155756022

  • 第一个gen是往回跳转,所以可以直接填上
  • S1.next: 回到B.label:begin

其他顺序语法结构

image-20230622160637031

image-20230622160644159

只有 (3) 与 (7) 生成了新的代码, 控制流语句的主要目的是**“控制” 流**(生成goto指令)。

例子

image-20230622160938800

会涉及的语法:

image-20230622160951386

总结

  • 为左部非终结符布尔表达式 B 计算综合属性 B.truelist 与 B.falselist
  • 为左部非终结符赋值语句/产生赋值语句的语句 S/L 计算综合属性 S/L.nextlist
  • 并为已能确定目标地址的跳转指令进行回填 (考虑每个综合属性)