编译原理教程第九章目标代码生成

合集下载

编译原理目标代码生成

编译原理目标代码生成

中间代码生成
探讨中间代码的概念、作用和生成方法,包括抽象语法 树、三地址代码等中间表示形式。
代码优化
介绍代码优化的原理和常用技术,如常量折叠、复制传 播、死代码删除等,以提高目标代码的质量。
目标代码生成
详细讲解目标代码生成的过程和方法,包括指令选择、 寄存器分配、汇编语言输出等关键步骤,以及针对不同 目标平台的优化策略。
语义分析
介绍了语义分析的基本任务,如类型 检查、控制流分析、数据流分析等。
中间代码生成
阐述了中间代码的概念、作用及生 成方法,包括抽象语法树、三地址 代码等。
目标代码生成
详细讲解了目标代码生成的过程, 包括指令选择、寄存器分配、优化 等。
对未来编译技术的展望
智能化编译技术
随着人工智能技术的发展,未来编译器可能具备更强的自 主学习能力,能够自动优化代码性能、提高编译效率。
01
指令选择算法
根据目标计算机的指令集和程序语义, 选择最合适的指令来实现程序功能。
02
03
代码优化算法
通过对生成的机器相关代码进行各种 优化(如常量折叠、循环展开等), 提高其执行效率和资源利用率。
06
代码生成器的设计与实现
代码生成器的结构
中间代码生成器
将源程序转换为中间代码形式,便于后续优化和代码生成。
2
编译过程包括词法分析、语法分析、语义分析、 中间代码生成、代码优化和目标代码生成等阶段。
3
编译原理不仅关注如何生成高效的目标代码,还 关注如何提高编译器的可维护性、可移植性和可 扩展性。
目标代码生成的意义
提高程序执行效率
目标代码是计算机直接执行的指令,其执行效率远高于高级语言程序。通过优化目标代码 ,可以提高程序的执行速度。

编译原理 课件第九章

编译原理 课件第九章

上下文语义的合法性检查的依据
在语义分析中,符号表所登记的内容将用于语义检查(如检查 一个名字的使用和原先的说明是否一致)和产生中间代码。通 过符号表中属性记录可进行相应上下文的语义检查。 例如,在一个C语言程序中出现 … int i [3][5]; //定义整型数组i … float i[4][2]; //定义实型数组i,重定义冲突 … int i [3][5]; //定义整型数组i,重定义冲突 … 编译过程首先在符号表中记录了标识符i的属性是3×5个整型元 素的数组,而后在分析第二、第三这两个定义说明时编译系统 可通过符号表检查出标识符i的二次重定义冲突错误。本例还可 以看到不论在后二句中i的其它属性与前一句是否完全相同,只 要标识符名重定义,就将产生重定义冲突的语义错误。
9.1符号表的作用和地位 符号表的作用和地位 9.2符号的主要属性及作用 符号的主要属性及作用 9.3符号表的组织 符号表的组织
9.1 符号表的作用和地位
收集符号属性 上下文语义的合法性检查的依据 作为目标代码生成阶段地址分配的依据
收集符号属性
编译程序扫描说明部分,收集有关标识符的属性,并在符号表 中建立符号的相应属性信息。 例如,编译程序分析到下述两个说明语句 int A; float B[5]; 则在符号表中收集到关于符号A的属性是一个整型变量,关于 符号B的属性是具有5个浮点型元素的一维数组。
9.2 符号的主要属性及作用
符号属性
1 符号名 2 符号的类型 3 符号的存储类别 4 符号的作用域及可视性 5 符号变量的存储分配信息 6 符型的成员信息 (3) 函数及过程的形参
① 符号名 符号表中设置一个符号名域,存放该标识符,该域通 常就是符号表的关键字域。
作为目标代码生成阶段地址分配的依据

编译原理课件-第9章代码生成

编译原理课件-第9章代码生成

● example
例1 请写出C function definition. 三地址码。 int f ( int x, int y ) { return x + y + 1; }
解:This will translate into the following three-address code:
entry f t1 = x + y t2 = t1 + 1 return t2
8.9 A Survey of Code Optimizations Techniques 代码优化技术考察
8.10 Simple Optimizations for the TINY Code Generator TINY代 码生成器的简单优化
8.1 Intermediate Code and Data Structures for Code Generation 中间代码和用于代码生成的数据结构
t2=fact*x
label L1
fact=t2
halt
解:Quadruple implementation for the three-address code
(rd, x , _ , _ ) (gt, x, 0, t1 ) (if_f, t1, L1, _ ) (asn, 1,fact, _ ) (lab, L2, _ , _ ) (mul, fact, x, t2 ) (asn, t2, fact, _ )
8.6 Code Generation in Commercial Compilers: Two Case Studies 商用编译器 中的代码生成:两个案例研究
8.7 TM: A Simple Target Machine TM:简单的目标机器 8.8 Code Generation for the Tiny Language TINY语言的代码生成器

编译原理中的目标代码生成与优化

编译原理中的目标代码生成与优化

编译原理中的目标代码生成与优化编译原理是计算机科学中的一门重要课程,它研究的是将高级程序语言转化为机器语言的过程。

目标代码生成与优化是编译过程中的两个关键环节,本文将就这两个方面展开讨论。

一、目标代码生成目标代码生成是编译过程中的最后一步,它的任务是将中间代码转化为能够在目标机器上执行的机器代码。

目标代码生成的质量直接影响程序的执行效率和占用的存储空间。

1. 寄存器分配在进行目标代码生成之前,我们需要进行寄存器分配。

寄存器分配的目的是将中间代码中的临时变量分配到机器寄存器中,减少内存读写操作,提高程序的运行速度。

常用的寄存器分配算法有线性扫描算法和图着色法。

2. 目标代码生成技术目标代码生成的技术有很多,下面列举几种常见的技术:(1) 直接生成代码:直接将中间代码翻译为目标机器的指令序列。

这种方法简单直接,但生成的目标代码质量一般较低。

(2) 间接生成代码:先将中间代码翻译为一个中间形式,再将中间形式转化为目标机器的指令序列。

这种方法可以进行一些优化,生成的目标代码质量较高。

(3) 使用代码模板:事先定义一些目标机器的指令模板,并根据中间代码的特征选择合适的指令模板来生成目标代码。

这种方法可以充分利用目标机器的特性,生成的目标代码效率较高。

二、目标代码优化目标代码优化是指对生成的目标代码进行一系列的优化,以提高程序的运行效率和减少代码的空间占用。

1. 基本块优化基本块是由顺序执行的指令组成的,没有前驱指令和后继指令的指令序列。

基本块优化的目的是对基本块中的指令进行优化,以减少执行时间和空间开销。

常见的基本块优化技术有死代码删除、常量传播等。

2. 寄存器优化寄存器是计算机中的一块高速存储器,能够提供快速的数据访问速度。

寄存器优化的目的是将变量尽可能地存放在寄存器中,以减少内存读写操作,提高程序的执行效率。

常用的寄存器优化技术有寄存器分配、寄存器重命名等。

3. 循环优化循环是程序中的重要结构之一,对循环进行优化可以显著提高程序的执行效率。

编译原理 目标代码生成 流程代码解析

编译原理 目标代码生成 流程代码解析

N
将栈中元素存到数 组,出栈
目标代码生成流程图:
6
开始 扫描逆波兰式
结束
Y
逆波兰式扫
描完
N
滤掉逆波兰式中 逗号
当前字符串为是否 不为运算分量,逗号
Y
当前字符存入数 组
Y N
当前字符串为是 否不为运算分量
N
当前字符串是 否为运算分量
N是否为寄存器, 用@等字符代表寄存器
MOV
传送字或字节.
算术运算指令
ADD
加法
算术运算指令
SUB
减法
算术运算指令
MUL
无符号乘法
算术运算指令
DIV
无符号除法
……
……
……
5. 实验代码
/******************************************************************************/ #include<iostream> #include<string> #include<stack> using namespace std; string temp1(8,0),temp2(8,0),value1; /******************************************************************************/ bool Ispair(string expre) { bool flag=true; stack<char> s; for(int i=0;i<expre.length();i++) { if(expre[i]=='(') s.push(expre[i]); if(expre[i]==')') { if(s.empty()) { flag=false; return flag; }

2021-2022学年编译原理之目标代码生成(2)

2021-2022学年编译原理之目标代码生成(2)

⑴(> a(y) b(y) t1(y)) ①LD R,a ②GT R,b
⑵(if t1(n) _ _ ) ③FJ R,? ⑨
RDL SEM t1

⑶(+ a(y) b(y) t2(y)) ④LD R,a ⑤ADD R,b t2
⑷(* t2(n) c(y) x(y)) ⑥MUL R,c
x
⑸(el _ _ _ ) ⑦ST R,x ⑧JMP_,? 15
【习题9.5】简要叙述代码生成器(控制器)的过程; 【习题9.6】已知下列语句:
if(a+b<c) x=(a+b)/(c-d)+(a+b); ※ 试分别解答:
⑴ 写出优化的四元式序列; ⑵ 标记变量的活跃信息; ⑶ 描述单寄存器R下的目标代码生成过程。
※ 条件语句的四元式结构:
设 条件语句: if(E)S1 ; else S2 ;
⑹(+ t4(n)t5(n) x(y))


需要随时观察寄存器状态 !
①LD R,a ②ADD R,b
③ST R,t1 ④LD R,c ⑤SUB R,d
⑥MUL R,t1 ⑦ ST R,t3 ⑧LD R,a ⑨SUB R,t3 ⑩ST R,t
11 LD R,t1 12 DIV R,2 13 ADD R,t4

⑹(* a(y) b(y) t3(y))

⑺(- 5 t3(n) x(y))

⑻(ie _ _ _ ) 注 需要及…时处理跳转地址返填 !
①LD R,a ②GT R,b
待返 填1
③FJ R,⑨? ④LD R,a ⑤ADD R,b
⑥MUL R,c ⑦ST R,x ⑧JMP_,1?5 ⑨ LD R,a ⑩MUL R,b

程序设计语言 编译原理(第三版)第9章

程序设计语言 编译原理(第三版)第9章
3.Par T T——为标号
30
9.5 嵌套过程语言的栈式实现
2.Par T T——为过程
⇒在进入T之后,为了建立T自己的display,T必须知道 它直接外层的display。 又P的display 或者正好就是这个外层的display, 或者包含了这个外层display
而由于T的层数是已知的
⇒只要知道P的display,T就可以用它来建立自己的display。 即假定T的层数为1,则T的display乃是由P的display的前1 个单元的内容和SP的现行值所组成。
i b(形参) 1(形参个数) 0
v
u 2 11 返回地址 17 d c v(形参) u(形参) 2(形参个数)
12
11 10 9
返回地址
5 i c 0 0 返回地址 0 x a 0
25
24 23 22
8
7 6 5 4 3 2
21
20 19 18 17
11
返回地址 11
1
0
返回地址
0
25
9.5 嵌套过程语言的栈式实现
31
9.5 嵌套过程语言的栈式实现
2.Par T T——为过程
⇒为了使得过程T工作时能够知道过程P的display,必须在P把 T作为实参传递给Q的时候把P自身的display地址也传过去。 即:过程P中的par T的作用可刻画为建立如下所示的两个相继 临时单元: 第一个临时单元B1:过程T的入口地址; 第二个临时单元B2:现行的display地址。; 然后执行(i+1)[TOP]:=addr(B1) 把第一临时单元B1的地址传给Q
8
9.2 运行时存储器的划分
三、存储分配策略 1.静态存储分配策略

编译原理之代码生成

编译原理之代码生成

03
04
05
1. 语法分析:根据语言 2. 语义分析:对抽象语
的语法规则,将源程序 法树进行语义检查和处
解析成抽象语法树
理,包括类型检查、符
(Abstract Syntax Tree,号表管理等。
AST)。
3. 中间代码生成:根据 抽象语法树和语义分析 结果,生成中间代码。 常见的中间代码形式有 三地址码、静态单赋值 形式(Static Single Assignment,SSA)等。
运行时系统自动管理程序中的内存资源, 通过垃圾回收机制回收不再使用的内存空 间,防止内存泄漏和野指针等问题。
运行时系统对程序性能的影响和优化
性能影响
运行时系统的设计和实现会直接影响程序的性能。例如,垃圾回收算法的选择和实现会 影响内存的回收效率和程序的暂停时间。线程调度策略的选择也会影响程序的并发性能
编译原理是计算机科学的重要分支,对于理解计算机如何执行程序以及如何提高程 序执行效率具有重要意义。
代码生成在编译过程中的作用
代码生成是编译过程的最后阶段, 负责将中间代码或优化后的代码 转换为目标机器上的可执行代码。
代码生成器需要了解目标机器的 指令集、寄存器分配、内存管理 等相关知识,以生成高效且正确
中间代码在编译器中的 作用主要有以下几点
使得编译过程分为相对 独立的前端和后端,降 低了编译器的复杂性。
提供了统一的中间表示, 便于实现不同语言之间 有利于进行各种优化操 的互操作性。 作。
ห้องสมุดไป่ตู้
中间代码生成的算法和步骤
01
02
中间代码生成的主要算 法包括语法分析、语义 分析和中间代码生成三 个步骤。
具体步骤如下
代码生成器的测试和评估方法

编译原理 第9章 语义分析和代码生成(Modified)

编译原理 第9章 语义分析和代码生成(Modified)

➢1、可移植性:如果花很小的代价,就能将一个 程序移植到另一台机器上,那么称该程序是可移植 的。
➢2、可适应性:如果一个程序能够容易地进行修
改就能满足不同的用户和系统的需求,那么称该程
序是可适应的。
精品课件
9.2 中间代码
要将一个给定的编译程序从X机移植到Y机,如果给定 的编译程序已分成前端和后端两部分,而且这两部分之 间定义有良好接口,那么移植的主要工作仅仅是重写现 有编译程序的代码生成程序以产生Y机的代码。一种较 理想的接口形式是抽象机的汇编程序,即能够将源语言 的各种语法结构映射到该抽象机的伪操作上。
17.AND 将栈顶两单元做逻辑与运算,并将结果真或假(1
或0)置于栈顶
18.OR 将栈顶两单元做逻辑或运算,并将结果真或假(1
或0)置于栈顶
19.NOT 将栈顶的逻辑值取反
20.IN 从标准输入设备(键盘)读入一个整型数据,并
入操作数栈
21.OUT 将栈顶单元内容出栈,并输出到标准输出设备(显
示器)
9.3 声明的处理
不同的程序设计语言,声明语句的结构也不一 样。 ➢有的语言类型说明在实体前,有的在实体后。 ➢有的语言要求每一个实体都要用一个独立的声 明语句进行声明(Ada语言即属于此类),有的语 言在一个独立的声明语句中可声明多个类型相 同的实体。
精品课件
9.3 声明的处理
C语言声明语句的类型说明是在实体前,而且,允许 一条声明语句可声明多个类型相同的实体,如“int a,b,c;”。在自左向右扫描和处理C语言声明语句时, 编译器首先知道类型,在扫描到后面的实体后,就可 为该实体建立符号表的记录,并可将类型及其它信息 填入符号表中。
<常量声明>→const <ID>↑n=<常量表达式>↑c,s@插入↓n,c,s <常量表达式>↑c,s→<int constant>↑c,s|<real constant>↑c,s

目标代码生成

目标代码生成
第9章 目标代码生成
编译程序最后一个阶段是目标代码生 成。它通常在语义分析后或者优化后的中 间代码上进行,并将中间代码转化为等价 的目标代码。
本章主要介绍
简单代码生成器的设计和构造方法
9.1 概述
我们知道,编译程序的最终目的是 将源程序翻译成等价的目标程序,为了 达到此目的,编译程序除了对源程序进 行词法分析、语法分析和语义分析外, 还必需将语义分析后或者优化后的中间 代码转换为等价的目标代码。
9.3
简单代码生成器
当翻译一个四元式如A=B op C时, 我们需要知道在基本块中还有哪些四元 式要对变量A、B、C进行引用。 2. 建立每个变量的待用信息和活跃信息 (1)待用信息
9.3

简单代码生成器
A在(i)定值 A在(j)引用
(i) A=T1 (j) T2 =A OP X
(j)为四元式(i)变量A的待用信息
9.3
简单代码生成器
(2) 活跃变量
基本块中所有的非临时变量均看 作基本块出口之后的活跃变量,临时 变量根据其在基本块出口之后是否被 引用来确定它是否为活跃变量。
9.3
简单代码生成器
(3) 计算变量待用信息和活跃信息 的算法:
输入:基本块及其入口语句号和 出口语句号 输出:附加待用信息和活跃信息 的基本块
依次把四元式变换成目标代码, 并在一个基本块内考虑如何充分利用 寄存器。 在设计代码生成器时,为考虑充分 利用寄存器,我们须要考虑下面两点:
9.3
简单代码生成器
1. 给出寄存器的分配原则
(1)把基本块内还要使用的变量的值 尽可能地保存在寄存器中; (2)在基本块内,把不再使用的变量 所占用的寄存器及时释放掉; (3)当到基本块出口时,将变量的值 存放在内存中。

代码优化与目标代码生成(介绍)-编译原理-09-(一)

代码优化与目标代码生成(介绍)-编译原理-09-(一)
B2 (5-8)
(8) if t3 < v goto (5)
B3 (9-12)
(12) if t5 > v goto (9)
B4
(13)
(13) if i ≥ j goto (23)
B5
B6
(22) goto (5)
2019/11/21
(14-22)
(23-30)
17
9.2 局部优化
(1) 合并已知量
关键:确定每个 基本块的入口
2019/11/21
(1) i := m - 1 (2) j := n (3) t1 := 4 * n; (4) v := a[ t1 ] (5) i := i + 1 (6) t2 := 4 * i; (7) t3 := a[ t2 ]; (8) if t3 < v goto (5) (9) j := j - 1 (10) t4 := 4 * j; (11) t5 := a[ t4 ]; (12) if t5 > v goto (9)
a:=4*m; s1:=4+ n*m; for i=1 to n step m do
{ s[i]:=s1; s1:=s1+a}
2
代码优化
代码优化的任务
通过等价的程序变换,获得执行速度快、占 用空间少的程序
2019/11/21
3
代码优化
for i=2 to 10000 do
算法优化
{T=0; for j=2 to i-1 do if i=i/j*j then{ T=1;break} if T=0 then print (i)}
例:顺序查找 与hash算法
有效的数据结 构和算法
领域相关

深入学习:掌握编译原理与目标代码生成

深入学习:掌握编译原理与目标代码生成

深入学习:掌握编译原理与目标代码生成编译原理与目标代码生成是计算机科学与软件工程领域非常重要的一部分。

在这个领域中,我们研究的是将程序代码转换为可执行代码的过程,这涉及到了词法分析、语法分析、语义分析、中间代码生成、代码优化和目标代码生成等一系列的技术和算法。

编译器是实现编译过程的工具,它将高级语言源代码转换为机器可执行的目标代码。

而编译过程中的关键环节即为目标代码生成,它是将中间代码转换为特定硬件平台上可执行的机器代码的过程。

编译原理的研究从上世纪50年代开始,经历了多个阶段的发展。

早期的编译器通过逐行读取源代码,然后将其转换为汇编语言或机器码。

随着计算机硬件的发展和编程语言的演化,编译器的设计和实现也发生了重大变化。

编译原理的核心概念之一是语法分析,它将源代码转换为抽象语法树(AST)。

语法分析器通过识别词法单元(如关键字、标识符、操作符等)来构建AST,并使用上下文无关文法来定义语法结构。

常见的语法分析算法有递归下降分析和LR分析。

语义分析是编译过程中的另一个重要环节,它确保程序在语义上是正确的。

语义分析器会检查源代码中的类型错误、作用域错误、类型转换错误等,并为后续的代码生成阶段提供必要的信息和约束条件。

中间代码生成是编译器的一个重要步骤,它将AST转换为一种中间表示形式,例如三地址码或者虚拟机指令。

中间代码是对源代码的一种抽象表示,它简化了后续代码生成和优化的过程,并为优化算法提供了更好的机会。

代码优化是编译过程中的重要环节,它旨在提高目标代码的性能和效率。

代码优化器使用各种技术和算法,例如常量折叠、循环优化、指令调度等,来改进目标代码的执行效率。

最后一个环节是目标代码生成,它将中间代码转化为特定硬件平台的机器代码。

目标代码生成器需要考虑到硬件平台的特点和限制,并根据目标机器的指令集架构来生成高效的机器代码。

目标代码生成是编译器的最终阶段,它决定了程序的最终执行效果。

一个好的目标代码生成器应该可以充分利用硬件资源,减少指令的数目和执行时间,从而提升程序的性能。

编译原理教程第九章目标代码生成

编译原理教程第九章目标代码生成

9.3.2 代码生成算法
假设基本块中每个中间代码形式为 A=B op C。
对每条中间代码 i:A=B op C依次执行如下步骤:
(1)调用函数GETREG(i:A=B op C); (2)利用地址描述数组AVALUE[B]和AVALUE[C]确定变量B和C的现
行值存放位置B’和C’; (3)如果B’R,则生成目标代码: LD R,B’ op R,C’ ;否则
reg的变量按需要回存到主存单元,固定分 配了reg的变量不须回存到主存单元。
a:=b+c
acde f:c=dae-fd B2
LD R0,d B0
LD R1,b
bcdf
B1
d:=adcd-bef e:=a+f
acdf
b:=d+f e:=a-c B3
cdef
b:=d+c
B4
bcdef
ST R0,d B5 ST R1,b
bcdf
B1
acde
a:=b+c d:=d-b e:=a+f acdef
acdf
f:=a-d B2 cdef
b:=d+f e:=a-c B3
cdefb:=ຫໍສະໝຸດ +cB4bcdef
bdef
分配好寄存器后,就可以生成目标代码。
与简单代码生成器不同之处在于: (1)固定分配了寄存器的变量用相应reg表示; (2)循环前置结点中存值到寄存器; (3)循环出口结点中存值到主存单元; (4)循环中每个基本块的出口,未固定分配
bdef
ST R0,d B6 ST R1,b
5 DAG的目标代码
对基本块中的中间代码序列,按怎样的次 序来生成目标代码?

程序设计语言与编译原理_第九章语义分析和中间代码生成

程序设计语言与编译原理_第九章语义分析和中间代码生成
• 中间语言(复杂性界于源语言和目标语言 之间)的好处:
– 便于进行与机器无关的代码优化工作 – 易于移植 – 使编译程序的结构在逻辑上更为简单明确
Compiler
Compiler
源语言 Front End 中间语 Back End 目标语
程序
言程序
言程序
10
程序设计语言与编译
• 常用的中间语言:
找包含它的最小switch、while或for语句方可找到
转向点,否则出错。
(3) 一致性检查
如在相同作用域中标识符只能说明一次、
case语句的标号不能相同、函数调用参数个数要相同
等。
程序设计语言与编译
常见的语义错误
声明和使用相关的语义错误 –标识符没有声明; –重复声明;
如何检查? –每当遇到新声明的标识符,查符号表
– 后缀式,逆波兰表示 – 图表示: DAG、抽象语法树 – 三地址代码
• 三元式 • 四元式 • 间接三元式
11
程序设计语言与编译
四元式形式: (op,ARG1,ARG2,RESULT) op—运算符 ARG1—第一运算量 ARG2—第二运算量 RESULT—结果
程序设计语言与编译 如: A:=-B*(C+D)
形如x:=y op z的赋值语句,op为二目算术
算符或逻辑算符;
赋值语句x:=op y,op为一元算符,如一元
减uminus, not, 移位及转换算符(如将定点 数转换为浮点数);
赋值语句x:=y;
无条件转移语句 goto L;
16
程序设计语言与编译
条件转移语句 if x relop y goto L 或 if a goto
» 如果当前有效的所有标识符中有相同名字的,则 是重复声明错误;
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

例:A=(B+C)*D+E
中间代码: T1=B+C T2= T1 *D A= T2 +E
(1) LD (2) ADD (3) ST (4) LD (5) MUL (6) ST (7)LD (8)ADD (9)ST
R,B
R,C
R, T1 R, T1 R,D
R, T2 R, T2 R,E
R,A
例:
(1) LD (2) ADD (3) ST (4) LD (5) MUL (6) ST (7)LD (8)ADD (9)ST
R,B
R,C
R, T1 R, T1 R,D
R, T2 R, T2 R,E
R,A
(1) LD
R,B
(2) ADD R,C
优 (5) MUL
R,D
化 (8)ADD
R,E
(9)ST
R,A
为了能够进行上述优化,代码生成器必须了解 一些信息:
9.3.1 待用信息与活跃信息
变量在基本块内的待用信息:从基本块的 出口由后向前扫描,对每个变量建立相应 的待用信息链和活跃变量信息链。
第9章 目标代码生成
以源程序的中间代码作为输入,产生等 价的目标代码作为输出,如图。
源程序
编译前端
中间 代码
代码优化
中间 代码
代码生成器
目标程序
符号表
代码生成器的输入包括中间代码和符号表中 的信息;
代码生成是把语义分析后或优化后的中间代 码变换成目标代码。
9.1 概述
1. 代码生成器的输入: 源程序的中间表示:如三地址代码; 符号表中的信息:在数据区中的相对地址
9.3.2 代码生成算法
假设基本块中每个中间代码形式为 A=B op C。
对每条中间代码 i:A=B op C依次执行如下步骤:
(1)调用函数GETREG(i:A=B op C); (2)利用地址描述数组AVALUE[B]和AVALUE[C]确定变量B和C的现
行值存放位置B’和C’; (3)如果B’R,则生成目标代码: LD R,B’ op R,C’ ;否则
J
X 无条件转移到X单元
CMP A,B 比较A、B单元的值,并根据A<B分别置CT为0
或1或2
J<X
CT=0 则转移
JX
CT=0 或 CT=1 则转移
J=X
CT=1 则转移
JX
CT 1 则转移
J>X
CT=2 则转移
J X
CT=2或 CT=1则转移
9.3 简单代码生成器
功能:依次把每条中间代码变换成目标代码, 并且在一个基本块的范围内考虑充分利用 寄存器。
2. 目标程序: 绝对机器语言代码; 可再定位机器语言代码; 汇编语言程序。
9.1 概述
代码生成着重考虑两个问题:
如何使生成的目标代码较短; 如何充分利用寄存器,减少目标代码访
问存储单元的次数。
9.2 假想的目标机器模型
采用一个模型作为目标机器:
1、具有多个寄存器,regs可作为累加器或变址 器;具有四种类型的指令形式
类型 直接地址型 寄存器型 变址型 间址型
指令形式
op Ri,M op Ri, Rj op Ri,c(Rj) op Ri,*M
op Ri, *Rj
op Ri,*c(Rj)
运算符op包括:ADD、SUB、 MUL、DIV等
2、其它指令的意义:
指令 意义
LD Ri,B (B)Ri
ST Ri,B (Ri) B
生成目标代码 op R,C’ ; 若B’或C’为R,则删除AVALUE[B]或 AVALUE[C]中的R; (4)令AVALUE[A]={R} ,并令RVALUE[R]={A}; (5)如果B和C的现行值在基本块中不再被引用,则释放所占用RK (即,删除RVALUE[RK]中的B或C以及AVALUE[B]中的RK )。
各中间代码对应的目标代码:
序号 中间代码 1 A=B op C
2 A= op B
3 A=B 4 A=B[I]
5 A[I]=B
目标代码 序号 中间代码
LD Ri,B 6 goto X
op Ri,C LD Ri,B
op Ri,Ri LD Ri,B LD Rj,I
LD Ri,B(Rj) LD Ri,B
7 if A rop B goto X
寄存器描述和变量地址描述
1、在代码生成过程中,建立寄存器描述数组 RVALUE,动态地记录各reg是空闲的、已分 配给某个变量、或已分配给某几个变量。
2、在代码生成过程中,建立变量地址描述数 组AVALUE,动态地记录各变量现行值的存 放位置:是在某个reg中、在某主存单元中、 或在某reg和主存单元中。
有效利用寄存器,生成更高效的目标代码。 指令的执行代价:指令访问主存单元次数+1 如:
op Ri,Rj 执行代价为1 op Ri,M 执行代价为2 op Ri,*Rj 执行代价为2 op Ri,*M 执行代价为3
对于循环,把可用的几个寄存器固定分配给节省 执行代价最多的那几个变量。
节省代价计算公式: [USE(M,B)+ 2*LIVE(M,B)]
8 A=P 9 P =A
LD Rj,I
ST Ri,A(Rj)
目标代码 J X’
LD Ri,A CMP Ri,B J rop X’ LD Ri,*P LD Rj,A ST Ri,*P
注:处理完所有代码后,对现行值只在reg中,而在基本块的出口 后是活跃的变量,要用ST指令把值存放到主存单元中。
9.3.3 寄存器分配
BL
其中,USE(M,B)=基本块B中对M定值前引用M的次数; LIVE(M,B)=1(当M在B中被定值且在B的出口之后是活跃的)
0(其他情况)
[USE(MB,) 2 * LIVE(MB,)]
BL
USE(MB,) 基本块B中对M定值前引用M的次数
简化:基本块中的所有临时变量均看作基本 块出口之后的非活跃变量;所有非临时变 量均看作基本块出口之后的活跃变量。
计算变量待用信息的算法:
(1)开始时,符号表Байду номын сангаас各变量为“非待用”,变量在出口 之后是否活跃填入活跃信息栏;
(2)从基本块出口到入口由后向前依次处理各个中间代 码。对每一条代码 i: A:=B op C,执行步骤:
把符号表中变量A的待用和活跃信息附加到中间代码i上; 把符号表中A的待用和活跃信息置为“非待用”、“非活
跃”; 把符号表中变量B.C的待用和活跃信息附加到中间代码i上; 把符号表中B.C的待用信息置为i,活跃信息置为“活跃”。
例 考察基本块 (1)T=A-B (2)U=A-C (3)V=T+U (4)W=V+U
相关文档
最新文档