汇编语言中间代码生成讲解
07-第7章-中间代码生成-编译原理PDF精讲课件-中国科技大学(共13讲)
中国科学技术大学 计算机科学与技术学院 陈意云
第七章 中间代码生成
记号 分析 流 器 本章内容
–介绍几种常用的中间表示:后缀表示、图形表示 和三地址代码 –用语法制导定义和翻译方案来说明源语言的各种 构造怎样被翻译成中间形式
静态 检查 器
中间 代码 中间 代码 生成 代码 生成 器 器
7.1 中 间 语 言
7.1.2 图形表示 • 语法树是一种图形化的中间表示 • 有向无环图也是一种中间表示
assign a + + a assign +
+ c uminus d uminus c c d d b b (b) DAG (a) 语法树 a = (b + cd) + cd的图形表示
7.1 中 间 语 言
7.1.4 静态单赋值形式 • 一种便于某些代码优化的中间表示 • 和三地址代码的主要区别
– 所有赋值指令都是对不同名字的变量的赋值 – 一个变量在不同路径上都定值的解决办法 if (flag) x = 1; else x = 1; y = x a; 改成 if (flag) x1 = 1; else x2 = 1; x3 = (x1, x2); //由flag的值决定用x1还是x2
E E1 E2 E.nptr = mkNode( ‘’, E1.nptr, E2.nptr) E.nptr = mkUNode( ‘uminus’, E1.nptr) E E1 E (E1) F id E.nptr = E1.nptr E.nptr = mkLeaf (id, id.entry)
符号表实例
7.2 声 明 语 句
• 符号表的特点
–各过程有各自的符号表 –符号表之间有双向链 –构造符号表时需要符号表栈 –构造符号表需要活动记录栈 sort var a:…; x:…; readarray var i:…; exchange quicksort var k, v:…; partition var i, j:…;
编译原理课件-第7章中间代码生成
● example
例2 suppose the function f has been defined in C as in the previous example. Then, the call
f ( 2+3, 4) 请写出the call三地址码。
解: translates to the three-address code begin_args t1 = 2 + 3 arg t1 arg 4 call f
2023/6/1
● If Statements if ( E ) S1 else S2
Three-Address Code :
If语句前的代码 If测试的代码
<code to evaluate E to t1>
条件
if_false t1 goto L1
<code for S1> goto L2
True情况下的代码
(sub, x, 1, t3 ) (asn, t3, x, _ ) (eq, x, 0, t4 ) (if_f, t4, L2, _) (wri, fact, _, _ ) (lab, L1, _ , _ ) halt, _, _, _ )
2023/6/1
例2 请写出TINY program三地址码的三元式表示。
7.4 Code Generation of Procedure and Function Calls 过程 和函数调用的代码生成
2023/6/1
7.1 Intermediate Code and Data Structures for Code Generation 中间代码和用于代码生成的数据结构
{ AddrKind kind; Union
编译原理课件-中间代码生成
Wensheng Li BUPT @ 2008
賦值語句a:=b*-c+b*-c的圖表示法
語法樹表示: assign
dag圖形表示: assign
a
+
a
+
*
*
b uminus b uminus
c
c
* b uminus
c
Wensheng Li BUPT @ 2008
7/75
二、三地址代碼
三地址代碼
賦值語句a:=b*-c+b*-c的三元式表示
Wensheng Li BUPT @ 2008
op
arg1
arg2
(14) uminus
c
(15)
*
b
(14)
(16) uminus
c
(17)
*
b
(16)
(18)
+
(15)
(17)
(19)
:=
a
(18)
12/75
語句x[i]:=y和x:=y[i]的三元式序列
EE1+E2
{ E.place=newtemp; if (E1.type==integer) && (E2.type==integer) { emit(E.place := E1.place + E2.place); E.type=integer; }; else if (E1.type==real) && (E2.type==real) { emit(E.place := E1.place real+ E2.place); E.type=real; }; else if (E1.type==integer) && (E2.type==real) { u=newtemp; emit(u := inttoreal E1.place); emit(E.place := u real+ E2.place); E.type=real; }; else if (E1.type==real) && (E2.type==integer) { u=newtemp; emit(u := inttoreal E2.pace); emit(E.place := E1.place real+ u); E.type=real; }; else E.type=type_error; }
编译原理第七章中间代码生成汇编
*
b
*
b
uminus
c
a= b*-c + b*-c
c abc uminus * bc numinus *+ assign
抽象语法树
• 构造赋值语句语法树的语法制导定义: 产生式
S→id = E E→E1 + E2 E→E1 * E2 E→- E1 E→(E1)
• param x1 • param x2 • …… • param x2 • call p, n n表示实参个数。return y中y为过程返回的一个值
– 形如x = y[i]及x[i] = y的索引赋值。
– 形如x = &y, x = *y和*x = y的地址和指针赋值。象形式。 • 这些语句可以以带有操作符和操作数域的记录 来实现。四元式、三元式及间接三元式是三种 这样的表示。
x = y op z
其中,x、y和z是名字,常量或编译器生成的临时变量 op代表任何操作符(定点运算符、浮点运算符、逻辑运算 符等)
• 像x+y*z这样的表达式要翻译为:
T1 = y * z
T2 = x + T1 其中T1 ,T2为编译时产生的临时变量。
三地址语句的类型
• 三地址语句类似于汇编语言代码。语句可以有 符号标号,而且存在各种控制流语句。
– 临时变量也要填入符号表中。
三元式
• 为了避免把临时变量填入符号表,可以通过计 算临时值语句的位置来引用该临时变量。 • 这样三地址代码的记录只需要三个域op, arg1 和arg。
• 对于单目运算符op, arg1和arg2只需用其一。
编译原理中间代码生成
编译原理中间代码生成在编译原理中,中间代码生成是编译器的重要阶段之一、在这个阶段,编译器将源代码转换成一种中间表示形式,这种中间表示形式通常比源代码抽象得多,同时又比目标代码具体得多。
中间代码既能够方便地进行优化,又能够方便地转换成目标代码。
为什么需要中间代码呢?其一,中间代码可以方便地进行编译器优化。
编译器优化是编译器的一个核心功能,它能够对中间代码进行优化,以产生更高效的目标代码。
在中间代码生成阶段,编译器可以根据源代码特性进行一些优化,例如常量折叠、公共子表达式消除、循环不变式移动等。
其二,中间代码可以方便地进行目标代码生成。
中间代码通常比较高级,比目标代码更具有表达力。
通过中间代码,编译器可以将源代码转换成与目标机器无关的形式,然后再根据目标机器的特性进行进一步的优化和转换,最终生成目标代码。
中间代码生成的过程通常可以分为以下几步:1.词法分析和语法分析:首先需要将源代码转换成抽象语法树。
这个过程涉及到词法分析和语法分析两个步骤。
词法分析将源代码划分成一个个的词法单元,例如标识符、关键字、运算符等等。
语法分析将词法单元组成树状结构,形成抽象语法树。
2.语义分析:在语义分析阶段,编译器会对抽象语法树进行静态语义检查,以确保源代码符合语言的语义规定。
同时,还会进行类型检查和类型推导等操作。
3.中间代码生成:在中间代码生成阶段,编译器会将抽象语法树转换成一种中间表示形式,例如三地址码、四元式、特定的中间代码形式等。
这种中间表示形式通常比较高级,能够方便进行编译器的优化和转换。
4.中间代码优化:中间代码生成的结果通常不是最优的,因为生成中间代码时考虑的主要是功能的正确性,并没有考虑性能的问题。
在中间代码生成之后,编译器会对中间代码进行各种优化,以产生更高效的代码。
例如常量折叠、循环优化、死代码删除等等。
5.中间代码转换:在完成了中间代码的优化之后,编译器还可以对中间代码进行进一步的转换。
这个转换的目的是将中间代码转换成更具体、更低级的形式,例如目标机器的汇编代码。
最新第六章-中间代码生成教学讲义ppt课件
第六章:中间代码生成
❖ 编译器分析综合模型
前端:源程序=》中间代码 (和源语言相关细节)
后端:中间代码=》目标代码 (和目标语言相关细节)
❖ 本章内容
中间代码表示
静态类型检查
中间代码生成
❖ 如何实现?描述用SDD、实现用SDT
所有翻译方案都可以通过生成并遍历抽象语法树来实现
临时名字在生成时一定要被写入符号表
❖ 图6-10:三地址代码及其四元式表示
10
6.2 三地址代码
❖ 三地址语句的实现
三元式
❖ 为了避免临时名字在生成时被写入符号表中,可以通过计算临 时值的语句的位置来引用它
❖ 带有三个域的记录结构:op,arg1,arg2
arg1,arg2指向符号表(对于程序员定义的名字或常量)的指针 或者三元组结构(对于临时变量)的指针
三地址码
❖ 可高可低(通过选择不同的运算符)
高级语言,如C语言
❖C语言灵活通用、可编译成高效机器代码
3
6.2 三地址代码(6.2)
❖ 三地址代码的一般形式
x = y op z 三地址代码是抽象语法树或DAG的线性表示
❖ 图6-8:一个DAG及其对应的三地址代码
7
6.2 三地址代码
❖ 三地址语句的类型(通用)
x = y op z
x = op y
x = y
goto L
if x goto L
if x relop y goto L
x = y[i],x[i] =y
x = &y,x = *y,*x := y
p(x1,x2…xn)
❖ param x1;param x2;…;param xn;
编译原理第七章 中间代码生成(1)
c
++*ad*bce
抽象语法树
由Token序列生成后缀式(1)
(1)初始化: S1和S2为空; (2) 读token: tk=ReadOne(); (3) Switch tk of (i) #: if (S1为空) exit; else while (S1不为空) /*产生剩余操作符的后缀表示*/ {op = pop(S1); (str1, str2)=pop(2); push(S2, str2 + str1+ “op”);} (ii)运算分量: push(tk, S2); goto (2); (iii)运算符: if (S1为空 || tk优先级大于Top(S1)) { push (tk, S1); goto(2);} else { while(tk小于等于Top(S1) && S1不为空)) { op = pop(S1); (str1, str2)=pop(2); push(S2, str2+str1 + “op”); } push(tk, S1); goto (2); }
+ +
a*c + a*c + e
e
+ +
e
* a
c a AST
* c a
* c
* a
DAG c
7.1 常见的中间表示
三地址中间代码
三地址:两个操作分量和一个结果的抽象地址; 为方便起见, 通常用变量名代替抽象地址; 三元式 No. (op, operand1, operand2) 编号 (操作符, 操作分量1, 操作分量2) 其中操作分量可以是变量名(抽象地址)或者编号 四元式 (op, operand1, operand2, result) (操作符, 操作分量1, 操作分量2, 结果) 其中操作分量可以是变量名(抽象地址)或者临时变量 (抽象地址)
编译原理实验三:中间代码生成
编译原理——语义分析成员:杨霞 030802107王日日 030802139方艳丽 030802102实验三:语义分析:生成中间代码一、实验目的通过语法制导或翻译模式生成中间代码。
二、实验内容在自底向上语法分析基础上设计语义规则(语法制导翻译),将源程序翻译为四元式输出.三、实验环境Windows microsoft visual c++ 6.0四.实验原理三地址码的几种常见指令:1.X=Y OP Z 的赋值指令,其中OP 是一个双目运算符或逻辑运算符。
2.X= Y 的复制指令。
3.无条件转移指令 GOTO L 把下一步要执行的带有标号L的三地址指令4.IF X GOTO L 或 IF FALSE X GOTO L的条件转移指令5.IF X RELOP Y GOTO L的条件转移指令。
三地址码四元式实验环境:windows microsoft visual c++语法制导定义:控制流语句的语法制导定义:实验代码分析:struct midcode//四元式结构;{int label;//存放标号;char op;//存放操作符;char arg1;//存放操作数1;char arg2;//存放操作数2;char result;//存放目的操作数(转移标号)}m_midcode[100];如何实现语句的跳转:主要利用了语义规则与规约过程的结合;例如:Label为四元式产生的新标号;Mnew 为四元式中最新的标号;case 9:tab1=t-1;while(tab1--){if(m_midcode[tab1].op=='>'&& (int)(m_midcode[tab1].result)==0){m_midcode[tab1].result=(char)m_midcode[tab1+2].label;/E.true=newlabelm_midcode[tab1+1].result=(char)(m_midcode[tab1+2].label+1);/E.false=newlabeltab2=tab1;for(;tab2<t;tab2++)if(m_midcode[tab2].op=='g'&&(int)m_midcode[tab2].result==0)m_midcode[tab2].result=(char)(mnew-1);//S1.next=s2.next=S.nextbreak ;}实验结果:心得体会:四元式序列是编译原理最后一个实验,最后的实验也要建立在之前两个实验的基础上。
编译原理中的中间代码生成
编译原理中的中间代码生成编译原理是计算机科学的一门重要课程。
在编译器的构造过程中,中间代码生成是其核心部分之一。
它是将源代码翻译为目标代码的重要中间阶段。
中间代码生成的过程涉及到链表、树,生成三元式、四元式等多种中间形式。
本文将介绍中间代码生成的过程和其在编译中的作用。
一、中间代码的概念中间代码是指在源程序和目标程序之间所生成的一系列指令的集合。
目标代码是指机器可执行的二进制代码,而中间代码则是一种可传递、可处理和可修改的编译代码形式。
中间代码属于一种中间状态,它不是源代码也不是目标代码,但可以被转换成目标代码。
中间代码可以基于语法树、语法分析栈、语法分析表进行生成,生成的中间代码需要满足语言语法结构和语义规则。
二、中间代码生成的流程在编译过程中,中间代码生成是指将源代码转换成中间代码的过程。
它是在词法分析、语法分析和语义分析阶段之后完成的。
下面介绍一下中间代码生成的流程。
1.源代码转换为语法树编译器通过词法分析和语法分析将源代码转换成语法树。
语法树是一种树形结构,它记录了源代码中各个语句的组成情况。
2.语法树进行语义分析在语法分析之后,编译器进行语义分析,检查语法树的合法性,然后根据语言的语义规则对语法树进行标注。
标注的内容包括符号表信息、数据类型等。
3.中间代码的生成在语义分析后,编译器进入中间代码的生成阶段,生成语句的中间代码。
中间代码通常采用三元式或四元式等形式。
三元式包含操作符、操作数以及结果的地址,四元式中还包括了类型信息。
4.中间代码优化在中间代码生成的过程中,编译器会尽可能地优化中间代码。
可以对中间代码进行多种优化,如常量合并、变量替换、公共子表达式消除等。
5.中间代码转换为目标代码在中间代码生成后,编译器将中间代码转换为目标代码。
目标代码可以是汇编代码或机器代码等不同形式的二进制代码。
三、中间代码生成优化的意义编译器中间代码优化的目标是提高程序的执行效率和降低其资源消耗。
执行效率的提高可以通过以下方式实现:1.减少内存使用编译器可以通过删除冗余代码、去除死代码和不必要的变量等方式来减少中间代码的内存使用。
编译原理中的中间代码生成
编译原理中的中间代码生成编译原理是计算机科学中非常重要的一门课程,它研究的是将高级语言程序转化为低级语言程序,实现计算机能够理解和运行的目的。
但是高级语言相较于机器语言更为抽象和复杂,所以需要经过多个步骤的处理,其中中间代码生成就是其中的一个重要环节。
中间代码是指一种介于高级语言和机器语言之间的表示方式,它的作用是将高级语言程序转化为更容易被计算机处理的形式,同时它也提供了一种通用的平台,可以将同一份高级语言程序转化为多种低级语言程序,如汇编语言、机器语言等。
如今,多数编译器都采用中间代码进行转化和优化,它不仅可以提高代码执行效率,还可以提高程序的可移植性和可维护性。
那么,中间代码的生成是如何进行的呢?和编译器的其它部分一样,中间代码生成也是经过多个步骤的处理,其中最主要的步骤包括词法分析、语法分析、语义分析和中间代码生成。
词法分析的作用是将源程序的字符序列转换为单词序列。
它依靠的是正则表达式的特性,对源程序进行识别和划分,得到一系列单词。
这些单词包括关键字、标识符、常数、字符等,在很大程度上决定了接下来的语法分析和语义分析。
语法分析是将单词序列转化为抽象语法树的过程,它将程序以树的形式进行表示,更为直观和容易理解。
通过对抽象语法树的遍历,可以得到程序的各种信息,如变量名、函数名、常量、运算符和控制语句等。
对于每个节点,编译器会根据其语义和上下文信息,进行类型检查、错误检测和决策生成等操作,最终得到一个可运行的程序。
语义分析是识别程序中不符合语言规范或逻辑错误的部分,它是整个编译过程中最为复杂的一个环节。
在这个过程中,编译器需要根据程序的上下文信息,判断其意义和合理性,并进行正确的处理。
例如,当编译器遇到一个未定义的变量或函数时,它将会报错并停止编译。
语义分析可以避免很多程序运行时的错误,同时也是编译器优化的重要基础。
当编译器通过词法分析、语法分析和语义分析,得到一个完整、正确的程序后,就可以进行中间代码生成了。
编译原理课件-中间代码生成
(3) E→not E1 { E.true:= E 1.false; E.Codebegin:= E 1.codebegin; E.false:= E 1.true
(翻譯不是最優)
語句 if a<b or c<d and e<f then S1 else S2 的四元式
(1) if a<b goto (7) //轉移至(E.true )
(2) goto (3)
(3) if c<d goto (5)
(4) goto (p+1)
//轉移至(E.false)
(5) if e<f goto (7) (6) goto (p+1) (7)( S1的四元式
不同層次的中間代碼
源語言
中間代碼
(高級語言) (高級)
中間代碼 (中級)
中間代碼 (低級)
float a[10][20]; a[i][j+2];
t1 = a[i, j+2]
t1 = j + 2 t2 = i * 20 t3 = t1 + t2 t4 = 4 * t3 t5 = addr a t6 = t5 + t4 t7 = *t6
語義描述使用的變數和過程:
E.true : “真”鏈, E.false : “假”鏈
E.codebegin : E 的第一個四元式
Nextstat: 下一四元式地址
编译原理第七章中间代码生成
3
循环语句的中间代码生成
循环结构的代码生成方式有多种,并根据循环类型和常量优化代码。
中间代码生成的优化技术
常量合并
把具有相同值的常量合并 为一个。
• 可以节省空间。 • 会改变代码原有结
构,需要小心。
表达式优化
采用数学方法对表达式求 解结果,优化表达式产生 的中间代码。
• 用于优化表达式的 运算过程,提高效
高效的编写代码方法
既要运用科学原理,又要具 备实践经验。而编译原理的 学习可以为我们提供更好的 编写代码方法。
追求突破与创新的开发 者
不断优化自己的编码方式可 以让您编写出更高质量的程 序,使你更好的成为一个有 追求的开发者!
编译原理第七章中间代码 生成
学习了编译原理基础后,我们来进一步了解关于中间代码生成的章节。
课程背景
1 编译器
2 中间代码
将高级语言代码转换成低级语言代码的 程序。
与源代码和目标代码位于中间的代码, 更容易优化和转换。
中间代码生成的定义和作用
定义
中间代码是一种抽象的机器语言,用于编 译过程中的代码转换。化
按照代码的实际运转过程, 进行代码生成顺序的优化。
• 可避免一些冗余工 作,加快程序的执
• 行需要速一度些。优化算法, 不易实现。
总结 and 结论
精通编译原理,写出高 效代码!
各种方法都是在实际生产环 境中总结出来的经验,并根 据实际需要进行选择和判断。
作用
可以用于优化和改变代码结构,同时还可 以提高生成目标代码的速度。
中间代码生成的方法
语法制导的方法
通过语法规则来约束产生 的中间代码,便于生成和 优化代码。
• 可用于处理语法规 则固定的语句。
编译原理系列之九中间代码生成
编译原理系列之九中间代码⽣成
中间代码⽣成
中间代码也与机器⽆关。
常见中间表⽰形式:
1. 逆波兰式:
逆波兰式
中缀表达式转逆波兰式:按照算术表达式的计算顺序根据操作数1、(操作数2)、运算符的顺序化成⼀个部分的后缀式,将这个后缀式在算术表达式中看成⼀个操作数继续按照上⾯⽅法分析。
逆波兰式转中缀表达式:根据逆波兰式的序列从左向右找运算符,找到后从这个运算符开始向前找出紧邻的操作数2、操作数1并化成算术表达式,将这个算术表达式看成⼀个操作数,继续往后寻找操作符,重复以上步骤。
注意:操作数均由⼀个字母表⽰。
1. 抽象语法树AST:
抽象语法树中每⼀个⼦树的根结点都对应⼀种动作或运算,它的所有⼦结点对应该动作或运算的参数或运算数。
参数或运算数也可以是另⼀⼦树,代表另⼀动作或运算。
将AST中相同的⼦树合并,这种改进的AST叫做有向⽆环图DAG;
AST与DAG
1. 三地址码TAC
x=y op z或者四元组的形式(op,y,z,x)
TAC
其他TAC语句
常⽤语句的语法制导翻译 :
语义过程GEN表⽰产⽣⼀个TAC或四元式,并且填⼊TAC或四元式表中。
语义过程Newtemp表⽰⽣成⼀个临时变量,每调⽤⼀次,⽣成⼀新的临时变量。
语义变量E. place,⽤来存放 E 的值的存储位置。
语义变量id.place , id 对应的存储位置。
1. 简单赋值语句的翻译 :
赋值语句
1. 布尔表达式的翻译 :
布尔表达式
拉链与回填:
拉链与回填
=拉链与回填。
6编译原理之中间代码生成
三地址代码(3)
• 指令
–过程调用/返回:
• • • • • param x1 param x2 … param xn call p, n //设置参数
//调用子过程p,n为参数个数
–带下标的复制指令:x=y[i] –地址/指针赋值指令:
• x=&y x=*y *x=y
x[i]=y
• 注意:i表示离开数组位置第i个字节,而不是数组的第i 个元素
–P{D.off=0} D –D T id; {D1.off = D.off + T.width;} D1
记录中的域的处理
• 我们可以为每个记录创建单独的符号表 • 处理时
–首先创建一个新的符号表,压到栈顶; –然后处理对应于字段声明的D,字段都被加入到新 符号表中; –最后根据栈顶的符号表构造record类型表达式; 符号表出栈
新的产生式
• • • • 数组元素L:LL[E] | id[E] 以数组元素为左部的赋值:SL=E; 数组元素作为因子:EL L的代码的功能是计算偏移量,存放于L.addr所指 的临时变量中。
数组元素作为因子
• L的代码只计算了偏移量; • 数组元素的值应该根据偏移量进一步计算即L 的数组基址加上偏移量 • 使用三地址指令x=a[i]
例:if (flag) x=-1; else x = 1; y = x*a • if (flag) x1=-1; else x2 = 1; x3=φ(x1,x2); • y = x3*a • 若控制流经过该条件语句的真分支, φ(x1,x2)的值为x1; 否则,若控制流经过该条件语句的假分支, φ(x1,x2)的值为x2
处理类型转换的SDT
图6.27 在表达式计算中引入类型转换
编译原理第七章 中间代码生成(2)
• GenIR(op, arg1, arg2, temp):
– 生成一个新的四元式,并将其加入已经生成的四 元式列表中;
7.2 表达式的中间代码生成
• 不带括号表达式的四元式 • 带括号表达式的四元式
不带括号表达式的四元式
• 特点:根据运算符的优先级确定计算顺序,生成 的四元式应该将运算顺序体现出来。 • 表达式:a * d + b * c + e • 生成的四元式
int x[10]; (L, 0) person class[10]; (L, 10) person *ptr; (L, 340)
第七章 中间代码生成
7.1 中间代码生成概述 7.2 几种常见的中间表示形式 7.3 表达式的中间代码生成 7.4 原子语句的中间代码生成 7.5 结构语句的中间代码生成 7.6 声明的中间代码生成
带括号表达式四元式生成算法 注意: 任何运算符的优先级都大于 ‘(’;
(1)初始化: S1和S2为空; (2) 读token: tk=ReadOne(); (3) Switch tk of (i) #: if (S1为空) exit; else while (S1不为空) /*产生剩余操作符的后缀表示*/ {op = pop(S1); (a, b)=pop(2); t= NewTemp(dir); GenIR(op, b, a, t); push(S2, t);} (ii)操作数: push(tk, S2); goto (2); ‘(’:push(tk,s1);goto(2); (iii)操作符: if (S1为空 || tk优先级大于Top(S1)) { push (tk, S1); goto(2)} else { while(tk小于等于Top(S1) && Top(S1) ≠ ‘(’ && S1不为空))) { op = pop(S1); (a, b)=pop(2); t= NewTemp(dir); GenIR(op, b, a, t); push(S2, t); } push(tk, S1); goto (2);} } (iv) ‘)’: while (Top(S1) ≠ ‘(’ ) {op = pop(S1); (a, b)=pop(2); t= NewTemp(dir); GenIR(op, b, a, t); push(S2, t);} pop(S1); goto (2);
《中间代码生成》PPT课件
精选ppt
27
program sort(input,output); var a:array[0..10] of integer; x:integer; procedure readarray; var i:integer; begin …a…end; procedure exchange(i,j:integer); begin x:=a[i];a[i]:=a[j];a[j]:=x;end; procedure quicksort(m,n:integer); var k,v:integer; function partition(y,z:integer):integer; var i,j:integer; begin …a… …v… …exchange(i,j)…end; begin … end; begin … end;
精选ppt
16
要关心的问题
类型
基本类型/内部类型(built-in):整型、实 型、双精度型、逻辑型、字符型
用户定义类型——结构描述
作用域——有效范围
一般:说明所在的分程序、过程
精选ppt
17
要关心的问题
类型的作用
引入数据抽象、隐蔽数据的基本表示
用户无需注明字节数
规定可用的运算
offset:已分配空间字节数
精选ppt
22
说明语句的翻译模式 P→MD M→ {offset := 0 }
P→{ offset := 0 } D D→D ; D D→id : T {enter( , T.type, offset );
offset := offset + T.width} T→integer {T.type := integer; T.width := 4} T→real {T.type := real; T.width := 8} T→array[ num ] of T1
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
表达式x + y z翻译成的三地址语句序列是 t1 = y z t2 = x + t1
7.1 中 间 语 言
三地址代码是抽象语法树或dag的一种线性表示
a = (b + cd ) + cd 抽象语法树的代码
t1 = b t2 = c d t3 = t1 + t2 t4 = c d t5 = t3 + t4 a = t5
7.1 中 间 语 言
赋值语句生成三地址代码的属性文法
产生式
语义规则
S id :=E S.code=E.code || gen(id.place‘=‘ E.place)
E E1 +E2 E E1 E2
E.Place = newtemp;
E.Code = E1.code || E2.code || gen(E.place ‘=‘ E1.place ‘+’ E2.place)
E本身。 • 如果E是形式为E1 opE2的表达式,那么E的后
缀表示是E1 E2 op,其中E1和E2分别是E1和 E2的后缀表示。 • 如果E是形式为(E1)的表达式,那么E1的后缀 表示也是E的后缀表示。
7.1 中 间 语 言
• 后缀表示不需要括号 (8 4) + 2 的后缀表示是8 4 2 +
E.Code = E1.code || E2.code || gen(E.place ‘=‘ E1.place ‘*’ E2.place)
第七章 中间代码生成
本章内容
–介绍几种常用的中间表示:后缀表示、图 形表示和三地址代码
–用语法制导定义和翻译方案的方法来说明 程序设计语言的结构怎样被翻译成中间形式
记 代码
代码 生成 器
7.1 中 间 语 言
7.1.1 后缀表示 表达式E的后缀表示可以如下归纳定义 • 如果E是变量或常数,那么E的后缀表示就是
E E1 E2 E.nptr = mknode( ‘’, E1.nptr, E2.nptr)
E E1 E.nptr = mkunode( ‘uminus’, E1.nptr)
E (E1) E.nptr = E1.nptr
F id
E.nptr = mkleaf (id, id.entry)
7.1 中 间 语 言
E本身。
7.1 中 间 语 言
7.1.1 后缀表示 表达式E的后缀表示可以如下归纳定义 • 如果E是变量或常数,那么E的后缀表示就是
E本身。 • 如果E是形式为E1 opE2的表达式,那么E的后
缀表示是E1 E2 op,其中E1和E2分别是E1和 E2的后缀表示。
7.1 中 间 语 言
7.1.1 后缀表示 表达式E的后缀表示可以如下归纳定义 • 如果E是变量或常数,那么E的后缀表示就是
7.1 中 间 语 言
赋值语句生成三地址代码的属性文法
产生式
语义规则
S id :=E S.code=E.code || gen(id.place‘=‘ E.place)
E E1 +E2 E E1 E2
E.Place = newtemp;
E.Code = E1.code || E2.code || gen(E.place ‘=‘ E1.place ‘+’ E2.place) E.Place = newtemp;
• 索引赋值x = y[i]和 x[i] = y
• 地址和指针赋值x = &y,x = y和x = y
7.1 中 间 语 言
赋值语句生成三地址代码的属性文法
产生式
语义规则
S id :=E S.code=E.code || gen(id.place‘=‘ E.place)
E E1 +E2
E E1 E2
7.1 中 间 语 言
• 后缀表示不需要括号 (8 4) + 2 的后缀表示是8 4 2 +
• 后缀表示的最大优点是便于计算机处理表达 式
7.1 中 间 语 言
• 后缀表示不需要括号 (8 4) + 2 的后缀表示是8 4 2 +
• 后缀表示的最大优点是便于计算机处理表达 式
• 后缀表示很容易拓广到含一元算符的表达式
assign
a
+
+
uminus c
d
c
d
b (a) 语法树
a = (b + cd ) + cd的图形表示
7.1 中 间 语 言
7.1.2 图形表示
• 抽象语法树是一种图形化的中间表示
• 有向无环图也是一种中间表示
assign
assign
a
+
a
+
+
+
uminus c
d
uminus
c
d
c
d
b (a) 语法树
assign
a
+
+
uminus
c
d
b
7.1 中 间 语 言
本书常用的三地址语句
• 赋值语句x = y op z, x = op y,
x= y
• 无条件转移goto L
• 条件转移if x relop y goto L
• 过程调用param x 和call p , n
• 过程返回 return y
7.1 中 间 语 言
• 后缀表示不需要括号 (8 4) + 2 的后缀表示是8 4 2 +
• 后缀表示的最大优点是便于计算机处理表达 式
• 后缀表示很容易拓广到含一元算符的表达式 • 后缀表示也可以拓广到表示赋值语句和控制
语句,但很难用栈来描述它的计算
7.1 中 间 语 言
7.1.2 图形表示 • 语法树是一种图形化的中间表示
uminus
7.1 中 间 语 言
三地址代码是语法树或dag的一种线性表示
a = (b + cd ) + cd
语法树的代码 dag的代码
t1 = b t2 = c d t3 = t1 + t2 t4 = c d t5 = t3 + t4 a = t5
t1 = b t2 = c d t3 = t1 + t2 t4 = t3 + t2 a = t4
b (b) dag
a = (b + cd ) + cd的图形表示
7.1 中 间 语 言
构造赋值语句抽象语法树的语法制导定义
产生式
语义规则
S id :=E S.nptr = mknode(‘assign’, mkleaf (id, id.entry), E.nptr)
E E1 +E2 E.nptr = mknode( ‘+’, E1.nptr, E2.nptr)