学习编译器Time03 ~ 三地址码
开门见山,本文的中间表示形式采用的是三地址码(Three-adress Code)
什么是三地址吗?
三地址码由类似于汇编语言的指令序列组成,每个指令最多有三个操作数(Operand)
常用的三地址指令
序号 | 指令类型 | 指令形式 | 备注 |
1 | 赋值指令 | x = y op z x = op y | op为运算符 |
2 | 复制指令 | x = y | |
3 | 条件跳转 | if x relop y goto n | relop为关系运算符 |
4 | 非条件跳转 | goto n | 跳转到地址n的指令 |
5 | 参数传递 | param x | 将x设置为参数 |
6 | 过程调用 | call p,n | p为过程的名字 n为过程的参数的个数 |
7 | 过程返回 | return x | |
8 | 数组引用 | x=y[i] | i为数组的偏移地址,而不是下标 |
9 | 数组赋值 | x[i]=y | |
10 | 地址及指针操作 | x=&y x=*y *x=y |
而怎样表示三地址指令呢?
小浩用四元式来表示,例如(op, y, z, x),共四个分量。
第一个分量op为三地址指令的操作符,其余三个分量为操作数。
将上表的三地址指令用四元式表示
x = y op z | ( op , y , z , x) |
x = op y | ( op , y , _ , x) |
x = y | ( = , y , _ , x) |
if x relop y goto n | ( relop , x , y , n) |
goto n | ( goto , _ , _ , n) |
param x | ( param , _ , _ , x) |
call p,n | ( call , p , n , _) |
return x | ( return , _ , _ , x) |
x=y[i] | ( =[] , y , i , x) ps: y为基地址,i为偏移地址 |
x[i]=y | ( []= , y , x , i) |
x=&y | ( & , y , _ , x) |
x=*y | ( =* , y , _ , x) |
*x=y | ( *= , y , _ , x) |
每一个指令只有一个操作符,那么只完成一个动作,这样看来,三地址指令序列唯一确定了运算完成的顺序。
接下来,看一下中间代码生成的例子
while a<b do
if c<5 then
while x>y do
z=x+1;
else x=y;
100到112为指令的编码,从100到112顺序执行。
100: ( j<, a, b, 102 ) | 如果a<b ,那么跳转到102指令,否则继续执行101指令 |
101: ( j , -, -, 112 ) | 该指令为无条件指令,跳转到112 |
102: ( j<, c, 5, 104 ) | 如果c<5 ,那么跳转到104指令,否则继续执行103指令 |
103: ( j , -, - , 110 ) | 该指令为无条件指令,跳转到110 |
104: ( j>, x, y, 106 ) | 如果x>y ,那么跳转到106指令,否则继续执行105指令 |
105: ( j , -, - , 100 ) | 该指令为无条件指令,跳转到100 |
106: ( + , x, 1 , t1 ) | x+1的值赋值给t1 |
107: ( = , t1, - , z ) | t1的值赋值给z,106和107完成了一条语句 |
108: ( j , -, - , 104 ) | 该指令为无条件指令,跳转到104 |
109: ( j , -, - , 100 ) | 该指令为无条件指令,跳转到100 |
110: (= , y, - , x ) | 把y赋值给x,然后执行111指令 |
111: ( j , -, - , 100 ) | 该指令为无条件指令,跳转到100 |
112: | 结束 |
小浩笔记
评论