编译原理代码生成(new)

合集下载

编译原理目标代码生成

编译原理目标代码生成

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

计算机基础知识点编译原理代码生成

计算机基础知识点编译原理代码生成

计算机基础知识点编译原理代码生成编译原理是计算机科学中非常重要的一门学科,它研究的是如何将高级语言编写的程序转化为机器可以执行的指令序列。

在编译过程中,代码生成是其中一个关键的步骤。

本文将介绍编译原理中的代码生成基础知识点。

一、代码生成概述代码生成是编译过程中的最后一个阶段,它的任务是将中间表示形式(如抽象语法树或中间代码)转化为目标机器代码,使得程序可以在计算机上运行。

代码生成的目标是产生高效且正确的机器指令序列,以最大程度地利用计算机的硬件资源。

代码生成的过程可以分为以下几个步骤:1. 寄存器分配:将变量和临时值分配到计算机的寄存器中,以便在指令中进行操作。

2. 指令选择:根据中间表示的特点和目标机器的指令集,选择适当的机器指令来实现所需的操作。

3. 指令调度:对指令进行重新排序,以减少指令相关性和提高执行效率。

4. 内存分配:将变量和临时值存储到内存中,以便在需要时可以进行访问。

5. 代码优化:对生成的机器指令进行优化,以减少执行时的开销和资源占用。

二、寄存器分配在代码生成的过程中,寄存器分配是一个非常重要的环节。

寄存器是计算机中的一种高速存储设备,可以用于存储和执行指令操作。

在生成的机器代码中,寄存器通常用于存储临时值和计算结果。

寄存器分配的目标是将变量和临时值存储到寄存器中,并进行相应的寄存器的分配和释放。

常见的寄存器分配算法有线性扫描分配算法、图着色分配算法等。

寄存器分配算法的选择通常取决于目标机器的寄存器数量和寄存器之间的互斥关系。

三、指令选择指令选择是代码生成的关键一环,它的任务是根据中间表示和目标机器的指令集,选择合适的机器指令来实现所需的操作。

指令选择的准则通常是从操作数和操作符的角度考虑,以及考虑目标代码的执行效率和可读性。

指令选择的过程中,需要考虑目标机器的指令格式、寻址方式、寄存器约束等因素。

对于一些特殊的操作,如函数调用、跳转指令等,还需要考虑目标代码的控制流程和程序执行的正确性。

8编译原理之讲义代码生成

8编译原理之讲义代码生成
输出
• RISC、CISC; • 可重定向代码、汇编语言
代码生成器设计中的问题
指令选择
•代码生成器将中间表示形式映射为目标
机代码
•映射的复杂性由下列因素决定:
• IR的层次
• 高:用代码模板翻译,但代码质量不高,需优 化
• 低:利用低层次细节生成更高效的代码
• 指令集体系结构本身的特性 • 期望的目标代码质量
方便记忆)
常量#constant56
例子
x=y-z
• LD R1, y
//R1=y
• LD R2, z
//R2=x
• SUB R1, R1, R2
//R1=R1-R2
• ST x, R1
//x=R1
b=a[i]
• LR R1, i
//R1=i
• MUL R1, R1, 8
//R1=R1*8
• LD R2, a(R1)
8.1代码生成器设计中的问题
设计目标:
• 生成代码的正确性(最重要) • 易于实现、测试和维护
输入 输出 指令选择 寄存器分配 计算顺序
代码生成器设计中的问题
输入
• 前端生成的源代码的IR(中间表示形式)及符号表信息 • 中间表示形式的选择
• 四元式、三元式、字节代码、堆栈机代码、后缀表示、抽象 语法树、DAG图、…
//R2=contents(a+contents(R1))
• ST b, R2
//b = R2
程序及指令代价
不同的目的有不同的度量
• 最短编译时间、目标程序大小、运行时间、能耗
不可判定一个目标程序是否最优 指令代价=指令固定代价(设为1)+运算分量寻
址模式代价,例:

编译原理 之 代码生成【VIP专享】

编译原理 之 代码生成【VIP专享】
✓充分利用计算机的寄存器,减少 目标代码中访问存储单元的次数.
1. 代码生成程序的输入
• 中间代码. 线性表示法(后缀 式)、三地址(四元式)等.
• 符号表中的信息. 代码生成根据 符号表中的信息来决定中间代码 中的名字所指示的数据对象的运 行时地址.
• 有时需要作类型检查.
2. 指令选择
✓ 指令选择--寻找一个合适的目标机 指令序列以实现给定的中间表示.
ADD Rj,Ri 其开销为1,结果在Ri中. ② b存放在Ri中,而c在一个存储单元里,并假
定b不再活跃。 ADD c,Ri 其开销为2 ③ 或者 MOV c,Rj ADD Rj,Ri 其开销为3
4. 指令调度•Biblioteka 指令调度——确定程序指令的执行顺序
• 对具有流水线限制的体系结构,这个阶段 是必须的。如:RISC体系结构一个通用的 流水线限制为:从内存中取入寄存器中的 值在随后的某几个周期中是不能用的。在 这几个周期期间,调出不依赖于该取入值 的指令来执行是很重要的。
代码生成器
目标程序目标程序
符号表
图12.1 代码生成器在编译系统中的位置
代码生成器的输入 ➢中间代码 ➢符号表中的信息
目标代码一般有三种形式:
1. 能够立即执行的机器语言代码,所 有地址均已定位,通常位于固定的 存储区域中,编译后可直接运行.
2. 待装配的机器语言模块。当需要执 行时,由连接装入程序把它们和某
✓ 如果目标机不能支持指令集的所有 类型,那么对每一种例外要做特别 处理.
✓ 多数CPU的指令集合具有冗余性, 也即,同一计算可用两个或多个不 同的指令序列完成。指令选择器选 择其中之一以产生最好的代码.
例:“加1”的两种代码生成方 式

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

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

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; }

编译原理与代码生成

编译原理与代码生成

编译原理与代码生成在计算机科学领域中,编译原理是一门研究编程语言如何被转换成可执行代码的学科。

它涉及到编译器的设计和开发,其中一个关键环节就是代码生成。

代码生成是编译过程中的最后一步,它将中间表示形式(如抽象语法树或中间代码)转化为机器代码或目标代码,以便计算机能够直接执行。

代码生成是编译过程中至关重要的一环,其质量直接影响到最终生成的可执行程序的效率和性能。

一个好的代码生成器应该能够生成高效、优化的机器代码,并且具备可移植性。

为了实现这一目标,代码生成器通常需要考虑以下几个方面:1. 寄存器分配:寄存器是现代计算机体系结构中重要的资源之一。

在代码生成阶段,寄存器的分配是一个关键问题。

代码生成器需要决定哪些变量应该存储在寄存器中,哪些应该存储在内存中,并生成相应的指令来进行寄存器的分配和管理。

2. 内存分配:除了寄存器分配外,代码生成器还需要考虑如何进行内存分配。

它需要决定哪些变量应该存储在堆栈上,哪些应该存储在静态数据区,以及如何有效地进行内存的分配和释放。

3. 代码优化:代码生成器还需要考虑一系列的代码优化技术,以提高生成代码的质量和效率。

这些技术包括常见的优化方法,如常量折叠、公共子表达式消除、死代码删除等。

通过应用这些优化技术,代码生成器可以生成更紧凑、更高效的机器代码。

4. 目标代码生成:最后,代码生成器需要将中间表示形式翻译成目标机器能够执行的机器代码。

这一过程中,代码生成器需要根据目标机器的指令集架构和特性来生成相应的机器代码。

同时,为了保证生成的代码的可移植性,代码生成器还需要考虑各种编译器选项和标准。

综上所述,编译原理中的代码生成是编译过程中不可或缺的一部分。

通过合理的寄存器分配、内存分配、代码优化和目标代码生成,代码生成器可以生成高质量、高效率的机器代码。

这对于计算机科学学习者和编译器开发者来说,都是一个重要的课题。

只有深入理解编译原理和代码生成的原理和技术,才能够设计和实现出优秀的编译器和程序。

编译原理之代码生成

编译原理之代码生成

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

编译原理 第十二章 代码生成

编译原理 第十二章 代码生成

第十二章代码生成课前索引【课前思考】在第2章PL/0语言编译程序的实现中,产生的目标代码是一种与机器无关的假想栈式计算机器汇编语言类PCODE,它的执行需要用具体机器配置的语言编写一个解释程序。

本章将介绍的代码生成是把某种高级程序设计语言经过语法语义分析或优化后的中间代码作为输入,将其转换成特定机器的机器语言或汇编语言作为输出,这样的转换程序称为代码生成器,因此,代码生成器的构造与输入的中间代码形式和输出的目标代码的机器结构密切相关。

本章将主要介绍生成具体机器汇编语言为目标代码时需要考虑的一些共同问题和中间语言的选择考虑。

建议学员考虑如何把PL/0语言编译程序的目标代码类PCODE翻译成你所熟悉的具体机器的汇编语言,作为学习代码生成的预习思考。

【学习目标】本章将介绍以具体计算机指令作为目标代码的代码生成器的设计,以一个计算机模型为例介绍一个简单的代码生成器需要考虑的问题,在代码生成时要考虑充分利用寄存器,以减少对内存的存取次数以提高目标程序运行速度,为此,本章将给出寄存器分配的原则,并使用待用信息链表法的代码生成算法,最后给出中间语言的选择需要考虑的问题。

【学习指南】由于代码生成的目标代码与具体计算机的结构有关,如指令格式、字长及寄存器的个数和种类,并与指令的语义和所用操作系统等都密切相关,因此实现非常困难。

通过本章学习,仅为学员初步了解一个高级程序设计语言编译程序目标代码生成需要考虑的问题和解决这些问题的基本原则和方法,为今后应用打下初步基础。

要想真正掌握代码生成技术的细节,最好的方法是实现一个代码生成器,建议学员学习本章后,用第2章PL/0语言的中间代码类PCODE为输入,选择一个自己熟悉的汇编语言为输出,编写一个代码生成器。

【难重点】重点:衡量目标代码的质量主要从占用空间和执行效率两方面考虑,而寄存器的合理分配对解决这两方面的问题起着重要的作用,因此要求学员了解寄存器的分配原则很重要,一个要求执行效率高的编译器对寄存器的分配可能要进行优化。

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

8编译原理之代码生成

8编译原理之代码生成
• 控制流只能从第一个指令进入 • 除了基本块最后一个指令,控制流不会跳转/停机
• 流图中结点是基本块,边指明了哪些基本块 可以跟在一个基本块之后运行
流图可作为优化的基础 • 它指出了基本块之间的控制流 • 可根据流图了解一个值是否会被使用等信息
划分基本块的算法
输入:三地址指令序列 输出:基本块的列表
注意二和三顺序不能错,
• 查看基本块a=a+b,a最终是活跃还是?
流图的构造
流图的顶点是基本块 两个顶点B和C之间有一条有向边,当且仅当基本
块C的第一个指令有可能在B的最后一个指令之后 执行。原因:
• B的结尾指令是一条跳转到C的开头的条件/无条件语 句 • 在原来的序列中,C紧跟在B之后,且B的结尾不是无 条件跳转语句 • B是C的前驱,C是B的后继
下次引用和活跃信息可用于代码生成
• 如果x在i处不活跃,且x占用了一个寄存器, 则该寄存器在i后可用于其它目的。
活跃变量与非活跃变量
⒈变量的定值点和使用点: • 设有四元式:q(w B C A ) • B,C的使用点(q) • A的定值点(q) ⒉活跃变量与非活跃变量 • 【活跃变量】一个变量从某时刻(q)起,到下 一个定义点止,其间若有使用点,则称该变 量在q是活跃的(y),否则称该变量在q是非活 跃的(n)。 • 简单的说,Q活跃就是指Q定义的值被使用过。 q一般为各个行号
静态/栈式数据区分配
基本块相关的代码生成
简单的代码生成算法
窥孔优化
8.1代码生成器设计中的问题
设计目标: • 生成代码的正确性(最重要) • 易于实现、测试和维护 输入 输出
指令选择
寄存器分配 计算顺序

编译原理 代码生成

编译原理 代码生成

3.
重命名临时变量
t := b + c,t——临时变量 u := b +c,u——新临时变量,对t的引用对u的引用, 基本块结果不变 定义临时变量的语句都定义新的临时变量 基本块等价变换,范式基本块
保结构变换(续)
4.
语句交换
t1 := b + c t2 := x + y 两个语句交换位置不影响运算结果 x、y都不是t1,b、c都不是t2 注意:范式基本块允许所有可能的语句交换
/* */ /* 局部数据 */
300: 304:
9.3.2 栈分配
使用相对活动记录起始的偏移
活动记录的地址——栈寄存器,SP
―第一个过程”
MOV #stackstart, SP 第一个过程的代码 HALT
栈分配——函数调用和返回
例9.3
begin prod := 0 i := 1 do begin prod := prod + a[i] * b[i]; i := i + 1 end while i <= 20 end
例9.3(续)
(1) (2) (3) (4) (5) (6) (7) (8) (9) (10) (11) (12)
t1 := 12 + R3 *t1 := 0 MOV #0, 12(R3)
9.4 基本块和流图

9.4.1 基本块,basic block



连续语句序列,执行过程中没有分支 t1 := a * a t2 := a * b t3 := 2 * t2 t4 := t1 + t3 t5 := b * b t6 := t4 + t5 x := y + z:定义x,使用(引用)y、z

编译原理第12章 代码生成

编译原理第12章 代码生成
(Ri)op((Rj)+c)⇒ Ri (Ri)op(M)⇒ Ri (Ri)op((Rj))⇒ Ri
op Ri, *c(Rj) (Ri)op(((Rj)+c))⇒ Ri
模型机主要指令的意义
指令 意义 指令 意义
如CT=0 转X单元。 如CT = 0或CT=1 转X单元。 如CT=1 如CT ≠ 1 如CT=2 如CT=2或CT=1 转X单元。 转X单元。 转X单元。 转X单元。


a)把符号表中变量A的待用信息和活跃信息附加到四元式i上。 b)把符号表中变量A的待用信息栏和活跃信息栏分别置为“非待用” 和“非活跃”。(由于在i中对A的定值只能在i以后的四元式才能引用, 因而对i以前的四元式却说,A是不活跃也不可能是待用的) c)把符号表中B和C的待用信息和活跃信息附加到四元式i上。 d)把符号表中B和C的待用信息栏置为“i”,活跃信息栏置为“活跃”。


(4)给出R,返回。 这样,一旦得到了一个为四元式运算的操作寄存器R,就可以进行代码生成, 而当目标代码生成完成后,则又需修改寄存器的使用信息和地址描述信息。 算法的流程图
开始
G E T R E G 算 法 的 流 程 图
B’=R? N Y 修改C的地址描述 AVALUE[C]:=AVALUE[C]-{R} Y C’=R?
可浮动的机器语言程序




有较大的灵活性,故为许多编译程序所采用,只有 执行连接装入程序本身需耗费一些时间。 目标程序由若干个目的模块组成,各个模块中都包 含目标程序中的一部分代码,且这些代码可在存储 空间进行浮动(即可将它们装入到存储空间的任何位 置)。 此外,在各目的模块中还含有一些连接信息(如本模 块需引用的其它模块中的符号名或子程序入口名)。 对此种形式的目标代码,需经过连接装入程序把它 们和所需的运行子程序的目的模块连接起来之后, 才能投入运行。

编译原理 第4章 new1语义分析和中间代码生成

编译原理  第4章 new1语义分析和中间代码生成

(3) E→(E(1))
(4) E→i
val[TOP]= val[TOP+1]
val[TOP]=lexval (注:lexval为i的整型内 部值)
文法的LR分析表见表3.20。
第4章 语义分析和中间代码生成
扩充分析栈工作的总控程序功能,使其在完成语法 分析的同时也能完成语义分析工作(这时的语法分析栈 已成为语义分析栈);即在用某一个规则进行归约之后, 调用相应的语义子程序完成与所用产生式相应的语义动 作,并将每次工作后的语义值保存在扩充后的“语义值” 栈中。
语义规则的左部符号E、T、F等的属性值的计算由其
各自相应的右部符号决定,这种属性也称为综合属性。 与产生式S→E关联的语义规则是一个函数print(E.val), 其功能是打印E产生式的值。S在语义规则中没有出现, 可以理解为其属性是一个虚属性。
第4章 语义分析和中间代码生成 简单变量类型说明的文法G[D]如下:
(2) 控制流检查,用以保证控制语句有合法的转向点。如C 语言中不允许goto语句转入case语句流;break语句需寻找包含它 的最小switch、while或for语句方可找到转向点,否则出错。 (3) 一致性检查,如在相同作用域中标识符只能说明一次、 case语句的标号不能相同等。
第4章 语义分析和中间代码生成
同,因此很容易将其翻译成四元式形式。
第4章 语义分析和中间代码生成
考虑以下文法G[A]:A→i=E
E→E+E∣E*E∣−E∣(E)∣i 在此,非终结符A代表“赋值句”。 为了实现由表达式到四元式的翻译,需要给文法 加上语义子程序,以便在进行归约的同时执行对应的
语义子程序。
第4章 语义分析和中间代码生成
第4章 语义分析和中间代码生成

编译原理 代码生成2

编译原理 代码生成2
$100(十进制), $0x99(十六进制) 后缀 l , w , b -- 操作数大小,对应 long,
word 和 byte, 如, movl %ebx, %ecx movb %bl, %al
•内存寻址方式
section : disp ( base, index, scale ) 计算方式如下:
代码生成
代码生成
代码生成的输入 -各种中间代码形式
目标代码与目标机器模型 简单的代码生成器 基本块DAG图及代码生成
目标代码
绝对地址目标代码 可重定位的目标
- linker/loader 汇编代码
- assembler
目标机器模型
指令形式 op 源,目的
寻址模式 - 绝对地址:op M, R R op (M)R - 寄存器:op R1,R2 R2 op R1 R2 - 变址:op R1,c(R2) (c+R2) op R1 (c+R2) - 间接变址、间接寄存器 - 直接量 op $C, R R + C R
base + index * scale + disp section/disp/index/scale(包括base) 均可缺省。
section用于实模式下。如, addl (%ebx,%ecx,0x2), %edx
(%ebx+%ecx*0x2)+%edx %edx subl 0x20( %eax,%ecx,0x4), %ebx %ebx - (%eax+%ecx*0x4+0x20) %ebx
NAME
t在R0 t在R0 u在R1 v在R0 u在R1 w在R0
其它语句的代码生成
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

+ +
:=
:=
i +i +
i 1i 1
:= i+
i1
例题2
按一般的代码生成,i = i +1的计算结果保留在 寄存器中,因此这三个i = i +1的计算次序不会 影响最终的结果。结果应该是6。
结果是7的话,一定是 某个i = i +1的结果未保 留在寄存器中。上层 计算对它的引用落在 计算另一个i = i +1的 后面
的寄存器R(可能产生MOV R,M指令,并修改 M的描述 ) 否则,如果x在基本块中不再引用,或者找不到适当的被占用寄存器,选择x的内存单
元作为L。
11.4 一个简单的代码生成器
赋值语句d := (a b) + (a c) + (a c)
编译产生三地址语句序列: t1 := a b t2 := a c t3 := t1 + t2 d := t3 + t2
代码生成
本章内容 一个简单的代码生成算法 涉及存储管理,指令选择,寄存器分配和计算次序选择等基本问题
源程序
中间 前端 代码
代 码 中间 代码
优 化 代码 生成


目标 程序
11.1 代码生成器的设计中的问题
11.1.1 目标程序 可执行目标模块 可重定位目标模块
允许程序模块分别编译 调用其它先前编译好的程序模块
+ +
:=
:=
i +i +
i 1i 1
:= i+
i1
例题2
如果机器有INC指令的话,编译器极可能产生一条INC指令来完成i = i +1 X86/Linux机器上果真是这么做的
+ +
:=
:=
i +i +
i 1i 1
:= i+
i1
例题2
将表达式改成(++i)+((++i)+(++i)), 结果会怎样?
prod := 0 i := 1
B1
t1 := 4* i
t2:= a[t1]
t3 := 4* I
t4 := b[t3]
t5 := t2 * t4 t6 := prod + t5
B2
prod := t6
t7 := i +1
i := t7

if i <= 20 goto B2
11.4 一个简单的代码生成器
例题2
下面的程序在X86/Linux机器上编译后的运行结 果是7,而在SPARC/SUNOS机器上编译后的运 行结果是6。试分析运行结果不同的原因。
main() {
long i;
i = 0; printf("%ld\n", (++i)+(++i)+(++i) ); }
例题2
按一般的代码生成,i = i +1的计算结果保留在 寄存器中,因此这三个i = i +1的计算次序不会 影响最终的结果。结果应该是6。
11.2 目 标 机 器
11.2.1 目标机器的指令系统
选择可作为几种微机代表的寄存器机器
四字节组成一个字,有n个通用寄存器R0,R1, …,Rn-1。
二地址指令 op 源,目的
MOV {源传到目的}
ADD
{源加到目的}
SUB
{目的减去源}
11.2 目 标 机 器
地址模式和它们的汇编语言形式及附加代价
ADD R2, R1
MOV R1, a
代价= 3
11.4 一个简单的代码生成器
依次考虑基本块的每个语句,为其产生代码 假定三地址语句的每种算符都有对应的目标机器算符 假定计算结果留在寄存器中尽可能长的时间,
除非:
该寄存器要用于其它计算,或者 到基本块结束
11.4 一个简单的代码生成器
在没有收集全局信息 前,暂且以基本块为 单位来生成代码
二元运算 需几个R
表达式
表达式
11.2 目 标 机 器
11.2.2 指令的代价
指令代价取成1加上它的源和目的地址模式的附加代价
指令
代价
MOV R0,R1 1
MOV R5,M
2
ADD #1, R3 2
SUB 4(R0), *12(R1) 3
11.2 目 标 机 器
a := b + c, a、b和c都静态分配内存单元
MOV b, R0 ADD c, R0 MOV R0, a
x := y + z if x < 0 goto z 的实现: MOV y, R0 ADD z, R0 MOV R0,x CJ< z
本章要点
代码生成器设计中的主要问题:存储管理、计算次序的选择、寄存器的分配、指 令的选择等。
目标机器几种常用的地址模式和一些常用的指令。 基本块和程序流图。 简单的代码生成算法。
MOV *R1, *R0 ADD *R2, *R0 代价= 2
11.2 目 标 机 器
a := b + c, a、b和c都静态分配内存单元
若R0,R1和R2分别含a,b和c的地址,则
MOV *R1, *R0 ADD *R2, *R0
代价= 2
若R1和R2分别含b和c的值,并且b的值在这个
赋值后不再需要,则
11.4 一个简单的代码生成器
语 句 生成的代码 寄存器描述 名字地址描述
寄存器空
t1 := a b MOV a, R0 R0含t1 SUB b, R0
t2 := a c MOV a, R1 R0含t1 SUB c, R1 R1含t2
t3 := t1+ t2 ADD R1,R0 R0含t3 R1含t2
非正 用条件码来表示计算的结果或装入寄存器的值是负、零还是正
11.4 一个简单的代码生成器
根据寄存器的值是否为下面六个条件之一进行 分支:负、零、正、非负、非零和非正 例如:if x < y goto z 把x减y的值存入寄存器R, 如果R的值为负,则跳到z
11.4 一个简单的代码生成器
用条件码的例子 if x < y goto z 的实现: CMP x, y CJ< z
d := t3 + t2 ADD R1,R0 R0含d
MOV R0, d
t1在R0中
t1在R0中 t2在R1中 t3在R0中 t2在R1中 d在R0中 d 在 R0 和 内 存 中
11.4 一个简单的代码生成器
前三条指令可以修改,使执行代价降低
MOV a, R0 SUB b, R0 MOV a, R1 SUB c, R1 ...
11.1.3 寄存器分配 运算对象处于寄存器中的指令通常比运算对象处于内存的指令要短一些,执行也 快一些
寄存器分配 选择驻留在寄存器中的一组变量
寄存器指派 挑选变量要驻留的具体寄存器
11.1 代码生成器的设计中的问题
11.1.4 计算次序的选择 某种计算次序可能会比其它次序需要较少的寄存器来保存中间结果
例题1
在SPARC/SUNOS上,经某编译器编译,程序的结果 是120。把第10行的abs(1)改成1的话,则程序结果是1 int fact(){
static int i=5; if(i==0) { return(1); } else { i=i-1; return((i+abs(1))*fact());} } main(){ printf("factor of 5 = %d\n", fact()); }
ADD e, R0
MOV R0, d
11.1 代码生成器的设计中的问题
语句序列 a := b + c
d := a + e
的代码如下
MOV b, R0
ADD c, R0
MOV R0, a
MOV a, R0 -- 多余的指令
ADD
e, R0 -- 若a不再使用,第三条也
MOV R0, d -- 多余
11.1 代码生成器的设计中的问题
三地址语句x := y + z(x,y和z都是静态分配) MOV y, R0 /* 把y装入寄存器R0 */ ADD z, R0 /* z加到R0上 */ MOV R0, x /* 把R0存入x中 */
逐个语句地产生代码,常常得到低质量的代码
11.1 代码生成器的设计中的问题
语句序列 a := b + c
d := a + e
的代码如下
MOV b, R0
ADD
c, R0
MOV R0, a
MOV a, R0
ADD
e, R0
MOV R0, d
11.1 代码生成器的设计中的问题
语句序列 a := b + c
d := a + e
的代码如下
MOV b, R0
ADD
c, R0
MOV R0, a
MOV a, R0 -- 多余的指令
:= i+
i1
+ +
:=
:=
i +i +
i 1i 1
例题2
将表达式改成(++i)+((++i)+(++i)), 结果会怎样?
在SPARC/SUNOS机器上的结果仍然是6。 在X86/Linux机器上的结果是9。
:= i+
i1
+ +
:=
:=
i +i +
相关文档
最新文档