【编译原理】第六章 中间代码生成

【编译原理】第六章 中间代码生成第六章中间代码生成中间代码也叫中间语言 Intermediate language 是 源程序的一种内部表示 不依赖目标机的结构 复杂性介于源语言和机器语言之间

大家好,欢迎来到IT知识分享网。

第六章 中间代码生成

1、后缀式

2、图表示法

抽象语法树、DAG图

3、三地址代码

三元式、四元式、间接三元式

后缀式

6.1 声明语句的翻译

6.1.1 类型表达式

各类语句的翻译,包括声明语句、控制语句等。声明语句主要是收集类型等信息。

类型表达式也是一种结构,类型表达式包括以下几种情况:

  1. 基本类型是类型表达式

integer 、real 、char 、boolean 、type_error (出错类型) 、void (无类型)

  1. 可以为类型表达式命名,类型名也是类型表达式
  2. 将类型构造符(type constructor)作用于类型表达式可以构成新的类型表达式

数组构造符array ,若T是类型表达式,则array( I, T)是类型表达式( I是一个整数)。

类型 类型表达式 int[3] array(3,int) int[2][3] array(2, array(3,int) ) 

指针构造符pointer,若T是类型表达式,则pointer ( T ) 是类型表达式,它表示一个指针类型。

笛卡尔乘积构造符x,若T1和T2是类型表达式,则笛卡尔乘积T1xT2 是类型表达式。

函数构造符→ ,若T1、T2、…、Tn 和R是类型表达式,则T1xT2x…xTn→R是类型表达式

记录构造符record ,若有标识符N1、N2、…、Nn 与类型表达式T1 、T2、…、Tn ,则 record( (N1 x T1)x(N2xT2)x…x(NnxTn ))是一个类型表达式。

例如,下列C语言程序片段中

structstype { char[8] name; intscore; }; stype[50] table; stype* p; 

和stype绑定的类型表达式 :

record ( (name x array(8, char)) x (score x integer) )

和table绑定的类型表达式 :

array (50, stype)

和p绑定的类型表达式 :

pointer (stype)

6.1.2 声明语句的翻译

对于声明语句,语义分析的主要任务就是收集标识符的类型等属性信息,并为每一个名字分配一个相对地址,从类型表达式可以知道该类型在运行时刻所需的存储单元数量 称为类型的宽度(width),在编译时刻,可以使用类型的宽度为每一个名字分配一个相对地址,名字的类型相对地址信息保存在相应的符号表记录中。

声明语句的文法动作中enter( name, type, offset):在符号表中为 名字name创建记录,将name的类型设置 为type,相对地址设置为offset。

其中t, w用于暂时存储当前变量的类型和宽度信息。

B表示基本类型

C便是数组类型

T表示表达式类型

D表示声明序列

P表示程序

例1:realx; inti;的翻译
在这里插入图片描述
其中红色表示real x中的变量类型和宽度的传递过程;蓝色虚箭头便是int i的变量类型和宽度传递过程。

例2::数组类型表达式“int[2][3]”的语法制导翻译

在这里插入图片描述
注意其中宽度在传递过程中的变化,最终类型表达式的宽度为24。

6.2 简单赋值语句的翻译

赋值语句的基本文法:

①S→id=E; ②E→E1+E2 ③E→E1*E2 ④E→ -E1 ⑤E→(E1) ⑥E→id 

赋值语句翻译的主要任务是生成对表达式求值的三地址码。

例如:

源程序片段 x = ( a + b ) * c ; 

三地址码 :

t1= a+ b t2 = t1 * c x= t2 

赋值语句对应的SDT为:
在这里插入图片描述
lookup(name):查询符号表 返回name对应的记录;gen(code):生成三地址指令code;newtemp( ):生成一个新的临时变量t, 返回t的地址 。

在增量方法中,gen( )不仅要构造出 一个新的三地址指令,还要将它添加 到至今为止已生成的指令序列之后

在这里插入图片描述
分析过程如上。

6.3 数组引用的翻译

将数组引用翻译成三地址码时要解决的主要问题是 确定数组元素的存放地址,也就是数组元素的寻址。

一维数组

假设每个数组元素的宽度是w,则数组元素a[i]的相对地址是:

base+i x w

其中,base是数组的基地址,i x w 是偏移地址。

二维数组

假设一行的宽度是w1,同一行中每个数组元素的宽度是w2,则 数组元素a[i1] [i2]的相对地址是:

base+i1 x w1+i2 x w2

举例:

假设type(a)= array(3, array(5, array(8, int) ) ), 一个整型变量占用4个字节, 则
在这里插入图片描述
a[i1]是一个二维数组,宽度为5*8*8*4=160;a[i1][i2]为一个一维数组,宽度为8*4=32;a[i1][i2][i3]为一个一维数组,宽度就是一个整型变量长度4。

例1:一维数组

假设type(a)=array(n, int);

源程序片段 c = a[i];

三地址码 :

t1= i* 4 t2= a[ t1] c= t2 

addr(a[i]) = base + i*4

其中t1表示偏移地址,t2表示加上基地址后的实际地址。

数组引用的SDT
在这里插入图片描述
从下往上进行扫描,并逐渐规约出最终地址。
在这里插入图片描述
带有语义动作的SDT如上图所示。

6.4 控制流语句及其SDT

控制流语句的代码结构为:
在这里插入图片描述
其中包含的继承属性为:

S.next:是一个地址,该地址中存放了紧跟在S代码之后的指令 (S的后继指令)的标号

B.true:是一个地址,该地址中 存放了当B为真时控制流转向的 指令的标号

B.false:是一个地址,该地址 中存放了当B为假时控制流转向 的指令的标号

用指令的标号标识一条三地址指令

控制流语句的基本文法及SDT:
在这里插入图片描述
newlabel( ): 生成一个地址;

label(L): 将下一条 三地址指令的标号赋给L

if-then-else语句的SDT
在这里插入图片描述
首先生成B.true和B.false的地址并用临时变量存放,如果下一条地址指令给B.true,则将S代码的下一步执行地址给S1,即执行S1的代码,执行完之后,转向执行S的代码。

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/149878.html

(0)
上一篇 2025-03-21 20:25
下一篇 2025-03-21 20:26

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信