第六章 中间代码生成

文章目录

  • 三地址码
  • 表达式的翻译
    • 表达式中的运算
    • 数组元素寻址
    • 条件表达式中的短路
    • 回填

三地址码

格式:
x = y op z
三地址码的右边只能有一个操作符
每个三地址码语句包含三个地址:两个是操作数,一个是结果

三地址码的类型:
第六章 中间代码生成_第1张图片
最后三行是函数

注意:只有if、goto语句,不存在while/for等循环语句。
汇编里实现循环通过goto跳转。

变址访问:
第六章 中间代码生成_第2张图片
y表示开始地址,i表示偏移量
注意:在三地址码中,不允许出现x[j] = y[i],这就变成四地址码了。

将x=y+2*2转换成三地址码:
	t1 = 2 * 2
	t2 = y + t1
	x = t2
将如下代码转换成三地址码:
i = 1;
a = 0;
while(i <= 10) {
  a = a + 1;
  i = i + 1;
}
转换结果:
i = 1
a = 0
L1: t1 = (i <= 10)
    if(t1 == 0) goto L2
    t2 = a + 1
    a = t2
    t3 = i + 1
    i = t3
    goto L1
L2

表达式的翻译

表达式中的运算

表达式的三地址码
第六章 中间代码生成_第3张图片

属性code表示对应的三地址码
属性addr表示存在表达式的地址
gen表示三地址指令。
||表示连接

数组元素寻址

一维数组:
Addr(A[i])=base+(i-low)*w=i*w+(base-low*w)
base:分配给数组A的内存块的相对地址,即A[0]的相对地址
low:最低位的索引
w:每个数组元素的宽度


二维数组:
数组模型;
Address(a[i, j]), a: array[low1,…, upper1][low2,…,upper2]

Addr(A[i1, i2])=base+((i1-low1)*n2+i2-low2)*w=(i1*n2+i2)*w+base-(low1*n2+low2)*w
n2=upper2-low2+1

将以上式子写成三地址码:

t1=low1*n2  
t2=t1+low2 
t3=t2*w 
t4=base-t3
t5=i1*n2      
t6=t5+i2       
t7=t6*w
t4[t7]=x   x=t4[t7]

条件表达式中的短路

例子:
第六章 中间代码生成_第4张图片

回填

为什么以及什么是回填(backpatching)?
在为布尔表达式和控制流(flow-of-control)语句生成代码时,我们可能不知道control必须转到的标签(label)。
我们可以通过生成一系列分支语句来解决这个问题,其中跳转的目标暂时未指定。
每个此类语句都将放在goto语句列表中,当可以确定正确的标签时,将填写其标签。
随后填写标签称为回填。

比如,我们不知道跳转到何处时写出的代码可能是这样的:

if (tag == 0) goto 0
goto 0
if (j <= 10) goto o
goto 0

回填就是用正确的Label替代上文中goto 0中的0

回填的步骤:

  1. makeList(i),记住goto目标未确定的语句
  2. merge(p1, p2),如果p1和p2是相同的,就把他们合并
  3. backpatch(p, i),回填

你可能感兴趣的:(编译原理,学习笔记,编译原理(龙书)学习)