编译复习

编译复习

第一章 绪论

基本概念

低级语言

  • 字位码、机器语言、汇编语言
  • 特点:与特定的及其有关,功效高,但使用复杂、繁琐、费时、易出错

高级语言

  • Fortran、Pascal、C语言等
  • 特点:不依赖具体机器,移植性好,对用户要求低,易使用,易维护

源程序:用汇编语言或高级语言编写的程序称为源程序

目标程序:用目标语言所表示的程序

目标语言:可以是介于源语言和机器语言之间的中间语言,可以是某种机器的机器语言,也可以是某种机器的汇编语言

翻译程序:将源程序转换为目标程序的程序称为翻译程序,它是指各种语言的翻译器,包括汇编程序和编译程序,是汇编程序、编译程序以及各种变换程序的总称

源程序是翻译程序的输入,目标程序是翻译程序的输出。

编译过程

编译的五个基本阶段:词法分析、语法分析、语义分析&生成中间代码、代码优化、生成目标程序

  • 词法分析

    任务:分析和识别单词

    源程序是由字符序列构成的,词法分析扫描源程序(字符串),根据语言的词法规则分析并识别单词,并以某种编码形式输出

  • 语法分析

    任务:根据语法规则(即语言的文法),分析并识别出各种语法成分,如表达式、各种说明、各种语句、过程、函数、程序等,并进行语法正确性检查

  • 语义分析、生成中间代码

    任务:对识别出的各种语法程序进行语义分析、并产生相应的中间代码

    生成中间代码的目的:1.便于做优化处理;2.便于编译程序的移植

  • 代码优化

    任务:为了得到高质量的目标程序

  • 生成目标程序

编译程序构造

屏幕快照 2019-01-04 下午4.34.11.png

整个编译的过程中都要建表查表以及错误处理,所以编译程序中都要包括表格管理和出错处理两部分

遍:对源程序(包括源程序中间形式)从头到尾扫描一次,并做有关的加工处理,生成新的源程序中间形式或目标程序,通常称之为一遍

屏幕快照 2019-01-04 下午4.37.34.png

通常将与源程序有关的编译部分称为前端,包括词法分析、语法分析、语义部分、中间代码生成、代码优化等分析部分;将与目标机有关的部分称为后端,包括目标程序生成,也叫综合部分

第二章 文法语言基础

基础概念

字母表:符号的非空有限集

符号:字母表中的元素

符号串:符号的有穷序列

空符号串:无任何符号的符号串(ε)

最右推导又称为一般推导、规范推导

文法和语言的形式定义

文法的分类:0(短语结构文法)、1(上下文有关文法)、2(上下文无关文法,与BNF表示相等价,可以由下推自动机接受)、3(正则文法,可以由有穷自动机接受)型文法

非形式化、形式化解释

文法四元式:V_n(非终结符号集)、V_t(终结符号集)、P(产生式或规则的集合)、Z(开始符号,又称为识别符号, Z ∈ V n Z\in V_n ZVn

屏幕快照 2019-01-04 下午5.08.12.png

语言:文法产生的所有句子的集合

句子:由终结符组成的字符串(有非终结符的叫句型),句子是特殊的句型

短语:可以大致理解为句子

句柄:最左简单短语

屏幕快照 2019-01-04 下午5.11.20.png

递归文法可用又穷条规则定义无穷语言

左递归文法不能使用自顶向下的方法进行语法分析

语法树与二义性文法

语法树:句子结构的图示表示法,它是一种有向图,由结点和有向边组成。

节点:符号,根节点:识别符号,中间节点:非终结符,叶节点:终结符或非终结符,有向边:表示节点间的派生关系

对句型中最左简单短语(句柄)进行的规约称为规范规约,规范规约与规范推导互为逆过程,通过规范规约或规范推导得到的句型称为规范句型

若对于一个文法的某一句子存在两棵不同的语法树或两个不同的规范推导,则该文法是二义性文法,否则是无二义性文法。

若一个文法的某规范句型的句柄不唯一,则该文法 是二义性的,否则是无二义性的。

有关文法的实用限制

若文法中有如 U : : = U U::=U U::=U的规则,则这就是有害规则,它会引 起二义性。

多余规则

  1. 在推导文法的所有句子中,始终用不到的 规则。即该规则的左部非终结符不出现在任何句型中。
  2. 在推导句子的过程中,一旦使用了该规则,将推不出任何终结符号串。即该规则中含有推不出任何终结符号串的非终结符。

若某文法中无有害规则或多余规则,则称该文法是压缩过的。

第三章 词法分析

词法分析的功能:根据词法规则识别及组合单词,进行词法检查;对数字常数完成字符串到二进制数值的转换;删去空格字符和注解

屏幕快照 2019-01-04 下午7.27.48.png

单词的种类:保留字、标识符、常数、分界符(单分界符、双分界符)

常用的单词内部形式:

  1. 按单词种类分类
  2. 保留字和分界符采用一符一类
  3. 标识符和常数的单词值可为指示字(指针值)

屏幕快照 2019-01-04 下午7.37.09.png

词法规则->状态图->词法分析程序

屏幕快照 2019-01-04 下午8.04.47.png

一个确定的有穷自动机(DFA)M是一个五元式: M = ( S , ∑ , δ , s 0 , Z ) M=(S, \sum ,\delta ,s_0 ,Z) M=(S,,δ,s0,Z)

  • S: 有穷状态集
  • ∑ \sum : 输入字母表
  • δ \delta δ: 映射函数,也称为状态转换函数
  • s 0 s_0 s0: 初始状态
  • Z: 终止状态集

屏幕快照 2019-01-04 下午8.12.28.png

δ \delta δ是一个多值函数,且输入可允许为ε,则有穷自动机是不确定的,即在某个状态下,对于某个输入字符存在多个后继状态,称为非确定的有穷自动机(NFA)

子集法将nfa变为dfa

lex二义性问题的两条原则:最长匹配原则、最优匹配原则

第四章 语法分析

语法分析概述

功能:根据文法规则,从源程序的单词符号串中识别出语法成分,并进行语法检查

自顶向下分析法

  • 问题

    左递归(改右递归)

    回溯

  • 方法

    递归下降子程序法

    LL分析法(下推自动机)

自底向上分析法

  • 问题

    句柄的识别问题

    若两个以上规则的右部有相同的符号串且构成句柄,选哪个候选式?

  • 方法

    算符优先分析法

    LR分析法

自顶向下分析

屏幕快照 2019-01-04 下午9.15.03.png

屏幕快照 2019-01-04 下午9.15.46.png

自顶向下分析方法的特点

  1. 分析过程是带有预测的。即要根据输入符号串中下一 个单词,来预测之后的内容属于什么语法成分,然后用 相应语法成分的文法建立语法树。
  2. 分析过程是一种试探过程,是尽一切办法(选用不同 规则)设法建立语法树的过程。由于是试探过程,故难 免有失败,所以分析过程需进行回溯,因此我们也称这 种方法是带回溯的自顶向下分析方法。
  3. 最左推导可以编出程序来实现,但在实际上价值不大, 效率低,代价高。

消除左递归的方法

  1. 使用扩充的BNF表示来改写文法

    eg. E : : = E + T ∣ T E::=E+T|T E::=E+TT -> E : : = T + T E::=T{+T} E::=T+T

    屏幕快照 2019-01-04 下午9.21.11.png

    屏幕快照 2019-01-04 下午9.21.23.png

  2. 将左递归规则改为右递归规则

    屏幕快照 2019-01-04 下午9.22.56.png

避免回溯

要求文法 F I R S T ( α i ) ⋂ F I R S T ( α j ) = ∅ ( i ̸ = j ) FIRST(\alpha_i) \bigcap FIRST(\alpha_j) = \varnothing (i\not=j) FIRST(αi)FIRST(αj)=(i̸=j)

消除回溯的途径

  1. 改写文法

    对具有多个右部的规则反复提取左因子

    屏幕快照 2019-01-04 下午9.31.44.png

  2. 超前扫描

    当文法不满足避免回溯的条件时,即各选择的首符 号相交时,可以采用超前扫描的方法,即向前侦察各输 入符号串的第二个、第三个符号来确定要选择的目标。

    这种方法是通过向前多看几个符号来确定所选择 的目标,从本质上来讲也有回溯的味道,因此比第一 种方法费时,但是读的仅仅是向前侦察情况,不作任 何语义处理工作。

为了在不采取超前扫描的前提下实现不带回溯的自顶向
下分析,对文法需要满足两个条件:

  • 文法是非左递归的
  • 对文法的任一非终结符,若其规则右部有多个选择时,各选择所推出的终结符号串的首符号集合要两两不相交。

递归子程序法(递归下降分析法):对语法的每一个非终结符都编一个分析程序,当根据文法和当时的输入符号预测到要用某个非终结符去匹配字符串时,就调用该非终结符的分析程序。对应的是最左推导的过程

LL分析法

此过程由分析表、执行程序(总控程序)、符号栈(分析站)三部分组成

屏幕快照 2019-01-04 下午9.46.17.png

屏幕快照 2019-01-04 下午9.48.28.png

屏幕快照 2019-01-04 下午9.48.44.png

屏幕快照 2019-01-04 下午9.48.53.png

屏幕快照 2019-01-04 下午9.49.07.png

屏幕快照 2019-01-04 下午9.49.15.png

屏幕快照 2019-01-04 下午9.51.55.png

屏幕快照 2019-01-04 下午9.51.44.png

自底向上分析

基本算法思想:从输入符号串开始,通过反复查找当前句型的句柄
(最左简单短语),并利用有关规则进行规约。若能规约 为文法的识别符号,则表示分析成功,输入符号串是文法的合法句子;否则有语法错误。

屏幕快照 2019-01-04 下午9.54.28.png

移进-规约分析:设置符号栈,用来纪录分析的历史和现状,并根据所面临的状态,确定下一步动作是移进还是规约。

屏幕快照 2019-01-04 下午9.57.02.png

屏幕快照 2019-01-04 下午9.57.15.png

需要注意的是:1. 栈内符号串+未处理符号串=当前句型;2. 句柄都在栈顶

实际上并未真正解决句柄的识别问题

算符优先分析

  1. 乘除的优先级大于加减;
  2. 同优先级的运算符左大于右;
  3. 括号内的优先级大于括号外。

屏幕快照 2019-01-04 下午10.00.54.png

屏幕快照 2019-01-04 下午10.01.27.png

屏幕快照 2019-01-04 下午10.01.34.png

出错情况:

  1. 相邻终结符之间无优先关系。
  2. 对双目运算符进行规约时,符号栈中无足够项。
  3. 非正常结束状态。

上述过程不一定是严格的最左规约(规范规约),但可以分析二义性文法所产生的语言(二义性文法若按规范分析,其句柄不唯一)

若文法中无形如 U ∷ = . . . V W . . . U∷= ...VW... U=...VW...的规则,这里 V , W ∈ V n V, W\in Vn V,WVn则称G为OG文法,也就是算符文法(算符文法不允许两个非终结符相邻)

屏幕快照 2019-01-04 下午10.06.53.png

算符优先文法(OPG—Operator Precedence Grammar)的定义:设有一OG文法,如果在任意两个终结符之间,至多只有 上述关系中的一种,则称该文法为算符优先文法(OPG)。

屏幕快照 2019-01-04 下午10.12.28.png

屏幕快照 2019-01-04 下午10.12.40.png

素短语:文法G的句型的素短语是一个短语, 它至少包含有一个终结符号,并且除它自身以外不再 包含其它素短语。

屏幕快照 2019-01-04 下午10.15.02.png

屏幕快照 2019-01-04 下午10.17.02.png

LR分析法

从左到右扫描(L)自底向上进行规约(R)(是规范规约,也即最右推导),是自底向上分析方法的高度概括和集中

优点:适合文法类足够大,适用于所有上下文无关文法,分析效率高,报错及时,可以自动生成

缺点:手工实现工作量大

屏幕快照 2019-01-05 上午10.16.55.png

状态栈:放置分析器状态和文法符号

分析表:由两个矩阵组成,其功能室指示分析器的动作,是移进还是规约,根据不同的文法类要采用不同的构造方法

控制程序:执行分析表所规定的动作,对栈进行操作

屏幕快照 2019-01-05 上午11.07.02.png

屏幕快照 2019-01-05 上午11.08.02.png

由分析过程可以看到:

  1. 每次规约总是规约当前句型的句柄,是规范规约! (而算符优先是规约最左素短语)
  2. 分析的每一步栈内符号串均是规范句型的活前缀, 且与输入串的剩余部分构成规范句型。

屏幕快照 2019-01-05 上午11.43.04.png

屏幕快照 2019-01-05 上午11.43.19.png

屏幕快照 2019-01-05 上午11.43.30.png

屏幕快照 2019-01-05 上午11.43.39.png

屏幕快照 2019-01-05 上午11.43.47.png

屏幕快照 2019-01-05 上午11.43.56.png

屏幕快照 2019-01-05 上午11.44.03.png

屏幕快照 2019-01-05 上午11.44.23.png

LR文法

  • 对于一个文法,如果能够构造一张分析表,使得它的每个
    入口均是唯一确定的,则我们将把这个文法称为LR文法。
  • 并非所有的上下文无关文法都是LR文法。但对于多数程 序语言来说,一般都可用LR文法描述。

LR(0)文法

  • LR(0)分析器的特点是不需要向前查看任何输入符号 就能归约。即当栈顶形成句柄,不管下一个输入符号是 什么,都可以立即进行归约而不会发生错误。
  • LR(0)文法过于简单。即使是定义算术表达式这样的 简单文法也不是LR(0)文法,所以没有实用价值!

(规范) LR(1)分析法

若项目集 [ A → α ⋅ B β ] [ A \rightarrow \alpha \cdot B \beta ] [AαBβ]属于 I I I时,则 [ B → ⋅ γ ] [ \mathbf { B } \rightarrow \cdot \gamma ] [Bγ]也属于I。
F I R S T ( β ) FIRST(\beta) FIRST(β)作为用产生式归约的搜索符(称为向前搜索符),即用产生式$ \mathbf { B } \rightarrow \gamma $归约时查看的符号集合(用以代替 SLR(1)分析中的FOLLOW集),并把此搜索符号的集合也 放在相应项目的后面,这种处理方法即为LR(1)分析方法。

LR(1)分析法的特点:

  • 可适用的文法范围最大。
  • 每个SLR(1)文法都是LR(1)文法,但反之不成立!
  • LR(1)项目集的构造对某些项目集的分裂可能使状态数目 剧烈地增长。
    例如对Pascal这样的语言,规范LR(1)表将有几千个状态!

LALR(1)分析

  • 对LR(1)项目集规范族合并同心集,若合并同心集后不产
    生新的冲突,则为LALR(1)项目集。
  • 相应的分析方法即为LALR(1)分析法。

LR分析法总结

  1. 适用文法范围:

    L R ( 0 ) ⊂ S L R ( 1 ) ⊂ L R ( 1 ) ⊂ 无 二 义 文 法 \mathbf { L } \mathbf { R } ( \mathbf { 0 } ) \subset \mathbf { S } \mathbf { L } \mathbf { R } ( \mathbf { 1 } ) \subset \mathbf { L } \mathbf { R } ( \mathbf { 1 } ) \subset 无二义文法 LR(0)SLR(1)LR(1)

  2. 分析表大小:

    LR(0) 和SLR(1) 较小,规范 LR(1)最大,LALR(1)适中。

  3. 报错效率: LALR(1)会迟报(但不会漏报)

第五章

翻译文法和语法制导翻译

翻译的任务是将中缀表达式转换为逆波兰表示

输入文法:未插入动作符号时的文法,由输入文法可以通过推导产生输入序列

翻译文法:插入动作符号的文法,翻译文法可以通过推导产生活动序列(输入序列&动作序列),是上下文无关文法,终结符号级有输入符号和动作符号组成

属性翻译文法

属性分为综合属性和继承属性

屏幕快照 2019-01-05 下午3.22.19.png

屏幕快照 2019-01-05 下午3.22.27.png

@set_table:将声明的变量填入符号表(语义)

屏幕快照 2019-01-05 下午3.35.20.png

L-属性翻译文法是带有下列说明的翻译文法:

  1. 文法中的终结符,非终结符及动作符号都带有属 性,且每个属性都有一个值域。

  2. 非终结符及动作符号的属性可分为继承属性和综 合属性。

  3. 开始符号的继承属性具有指定的初始值。

  4. 输入符号(终结符号)的每个综合属性具有指定
    的初始值。

  5. 属性值的求值规则如下:

    继承属性——体现自顶向下,自左向右的求值特性。

    • 产生式左部非终结符号的继承属性值,取前面产生式右部该符号已有的继承属性值。
    • 产生式右部符号的继承属性值,用该产生式左部符号的继承属性或出现在该符号左部的符号的属性值进行计算。

    综合属性——体现自底向上,自右向左的求值特性。

    • 产生式右部非终结符号的综合属性值,取其下部产生式左部同名非终结符号的综合属性值。
    • 产生式左部非终结符号的综合属性值,用该产生式左部符号的继承属性或某些右部符号的(任意)属性进行计算。
    • 动作符号的综合属性用该符号的继承属性或某些右部符号的(任意)属性进行计算。

    屏幕快照 2019-01-05 下午4.16.10.png

自顶向下语法制导翻译

在翻译文法的基础上可设计其属性翻译文法,以便语义分析过程中生成完整的四元式,完成翻译。

  • 输入符号(操作数)有一综合属性,它是该符号在数据区的 地址。
  • 每个非终结符有一个综合属性,该属性是由它产生的代表该子表达式在数据区中的地址(中间结果)。
  • 动作符号有三个继承属性,它们分别是左右操作数和运算结果在数据区的地址。

输入文法、翻译文法(输入文法+动作符号)、属性翻译文法

第六章 符号表管理技术

概述

在编译过程中,编译程序用来记录源程序中各种名字的特性信息,所以也称为名字特性表。

  • 名字: 程序名、过程名、函数名、用户定义类型名、变量名、常量名、枚举值名、标号名等。

  • 特性信息: 上述名字的种类、类型、维数、参数个数 及目标地址(存储单元地址)等。

建表和查表的必要性(符号表在编译过程中的作用):

源程序中变量要先声明,然后才能引用。

用户通过声明语句,声明各种名字,并给出它们的 类型维数等信息。编译程序在遇到这些声明语句时,应 该将声明中的名字以及信息登录到符号表中,同时编译 程序还要给变量分配存储单元。

存储单元地址也必须登录在符号表中。

当编译程序编译到引用所声明的变量时(赋值或引 用其值),要进行语法语义正确性检查(类型是否符合 要求等)和生成相应的目标程序,这就需要查符号表以 取得相关信息。

非分程序结构语言的符号表组织

非分程序的结构语言:每个可独立进行编译的程序单元是一个不包含有子模块的单一模块。如FORTRAN语言。

基本处理办法:

  1. 子程序、函数名和公共区变量填入全局符号表

  2. 在子程序(函数)声明部分读到标识符时,构造局部符号表

    查本程序单元局部符号表,有无同名

    • 有:重复声明,报错
    • 无:填表
  3. 在语句部分读到标识符,查表

    查本程序单元局部符号表,有无同名

    • 有:已声明过
    • 无:查全局变量表,有——全局量,无——无定义标识符
  4. 程序单元结束:释放该程序单元的局部符号表

  5. 程序执行完成:释放全部符号表

符号表的组织方式

  1. 无序符号表

    按扫描顺序建表,查表要逐项查找

    查表操作的平均长度为 ( n + 1 ) / 2 (n + 1)/2 (n+1)/2

  2. 有序符号表

    符号表按变量名进行字典式排序

    线性查表: ( n + 1 ) / 2 (n + 1) / 2 (n+1)/2

    折半查表: L o g 2 n − 1 \boldsymbol { L } \boldsymbol { o } \boldsymbol { g } _ { 2 } \boldsymbol { n } - \mathbf { 1 } Log2n1

  3. 散列符号表(Hash表)

    符号表地址 = Hash(标识符)

分程序结构语言的符号表组织

分程序的结构语言:模块内可嵌入子模块

标识符的作用域:标识符局部于所定义的模块(最小模块)

第七章 运行时的存储组织及管理

概述

静态存储分配:在编一阶段由编译程序实现对存储空间的管理,和为源程序中的变量分配存储的方法(但并不是所有的数据空间大小都能在编译过程中确定)

动态存储分配:在目标程序运行阶段由目标程序实现对存储空间的组织与管理,和为源程序中的变量分配存储的方法(编译时要生成动态分配的目标指令)

静态存储分配

由于每个变量所需空间的大小在编译时已知,因此可以用简单的方法给变量分配目标地址。

  • 开辟一数据区。(首地址在加载时确定)
  • 按编译顺序给每个模块分配存储
  • 在模块内部按顺序给模块的变量分配存储,一般用相对地址,所占数据区的大小由变量类型确定
  • 目标地址填入变量的符号表中。

这种分配策略要求语言不允许指针或动态分配,不允许递归调用过程。典型的例子是Fortran77。

动态存储分配

由于编译时还不能具体确定某些数据空间的大小,故对它们分配存储空间必须在程序运行时进行。这时,编译程序生成有关存储分配的目标代码,实际上的分配要在目标程序运行时进行。这种分配方式称为动态存储分配。

对于分程序结构,而且允许递归调用的语言,常使用栈式动态存储分配,即使用一个类似于堆栈的“运行栈” 来实现数据区的分配。

分配策略是: 整个数据区为一个堆栈

  1. 当进入一个过程时,在栈顶为其分配一个数据区
  2. 当退出一个过程时,撤消该过程的数据区

一个典型的活动记录可以分为三部分

  1. 局部数据区:存放模块中定义的各个局部变量
  2. 参数区:存放隐式参数(不出现在用户源程序中)和显式参数(出现在用户源程序中)
  3. display区:存放各外层模块活动记录的基地址(看层级,看符号属于哪个作用域)

第八章 源程序的中间形式

波兰表示

一般编译程序都生成中间代码,然后再生成目标代码,主要优点是可移植(与具体目标程序无关),且易于目标代码优化

波兰表示法的优点:

  1. 在不使用括号的情况下可以无二义地说明算术表达式
  2. 波兰表示法更容易转换成机器的汇编语言或机器语言。 操作数出现在紧靠操作符的左边,而操作符在波兰表示中的顺序即为进行计算的顺序
  3. 波兰表示不仅能用来作为算术表达式的中间代码形式, 而且也能作为其它语言结构的中间代码形式

N元表示

在该表示中,每条指令由 n 个域所组成,通常第 一个域表示操作符,其余为操作数。

常用的n元表示是三元式、四元式

抽象机代码

既然是“抽象机”,就是表示它并不是实际的物理目标机器而通常是虚拟的一台“堆栈计算机”。该堆栈式计算机主要由若干寄存器、一个保存程序指令的储存器和一个堆栈式数据及操作存储组成。

寄存器有:

  1. PC —— 程序计数器。
  2. NP —— New指针,指向“堆”的顶部。“堆”用来存
    放由NEW生成的动态数据。
  3. SP —— 运行栈指针,存放所有可按源程序的数据声明
    直接寻址的数据。
  4. BP ——基地址指针,即指向当前活动记录的起始位置
    指针。
  5. 其他(如MP—栈标志指针,EP—极限栈指针等)

屏幕快照 2019-01-05 下午5.41.01.png

第九章 错误处理

正确的源程序:通过编译,生成目标代码。

错误的源程序:通过编译,发现并指出错误。

从编译角度,将错误分为两类:语法错误和语义错误

  • 语法错误:程序结构不符合语法(包括词法)规则的错误

  • 语义错误:程序不符合语义规则或超越具体计算机系统的 限制

错误局部化处理:指当编译程序发现错误后,尽可能将 把错误的影响限制在一个局部的范围,避免错误扩散和影响程序其它部分的分析。

第十章 语义分析和代码生成

语义分析的概念

  1. 上下文有关分析:即标识符的作用域

  2. 类型的一致性检查

  3. 语义处理:

    声明语句:其语义是声明变量的类型等,并不要求做其他的操作。语义分析程序的工作是填符号表,登录名字的特征信息,分配存储。

    执行语句:语义是要做某种操作。 语义处理的任务:按某种操作的目标结构生成中间代码或目标代码。

栈式抽象机及其汇编指令

栈式抽象机:由三个存储器、一个指令寄存器和多个地址寄存器组成

存储器:

  • 数据存储器(存放AR的运行栈)
  • 操作存储器(操作数栈)
  • 指令存储器

屏幕快照 2019-01-05 下午6.43.11.png

声明的处理

编译程序处理声明语句要完成的主要任务为:

  1. 分离出每一个被声明的实体,并把它们的名字填入符号表中
  2. 把被声明实体的有关特性信息尽可能多地填入符号表中

对于已声明的实体,在处理对该实体的引用时要做的事情:

  1. 检查对所声明的实体引用(种类、类型等)是否正确
  2. 根据实体的特征信息,例如类型、所分配的目标代码地址(可能 为数据区单元地址,或目标程序入口地址)生成相应的目标代码

屏幕快照 2019-01-05 下午10.02.06.png

@insert 的功能是:

  1. 检查声明的类型t 和常量表达式的类型s 是否一致,若 不一致,则输出错误信息;
  2. 把名字n,类型t 和常量表达式的值c 填入全局符号表中。

数组变量声明的处理

对于静态数组,即数组的大小在编译时是已知的,编译程 序在处理数组声明时,可建立一个数组模板(又称为数组信息 向量)以便以后的程序中引用该数组元素时,可按照该模板提 供的信息,计算数组元素(下标变量)的存储地址。

对于动态数组,其大小只有在运行时才能最后确定。我们在编译时仅为该模板分配一个空间,而模板本身的内容将在运 行时才能填入。

屏幕快照 2019-01-05 下午10.05.45.png

屏幕快照 2019-01-05 下午10.06.46.png

表达式的处理

分析表达式的主要目的是生成计算该表达式值的代码。通 常的做法是把表达式中的操作数装载(LOAD)到操作数栈(或运行栈)栈顶单元或某个寄存器中,然后执行表达式所指定的操作,而操作的结果保留在栈顶或寄存器中。

过程调用和返回

  1. 传值(call by value) — 值调用

    实现:

    • 调用段(过程语句的目标程序段): 计算实参值 => 操作数栈栈顶
    • 被调用段(过程说明的目标程序段): 从栈顶取得值 => 形参单元

    过程体中对形参的处理:对形参的访问等于对相应实参的访问

    特点: 数据传递是单向的

  2. 传地址(call by reference) — 引用调用

    实现:

    • 调用段:计算实参地址 => 操作数栈栈顶
    • 被调用段:从栈顶取得地址 => 形参单元

    过程体中对形参的处理:通过对形参的间接访问来访问相应的实参

    特点:结果随时送回调用段

  3. 传名(call by name )

    又称名字调用。即把实参名字传给形参。这样在过程体中引用形参时,都相当于对当时实参变量的引用。

    当实参变量为下标变量时,传名和传地址调用的效果可能会完全不同。

    传名参数传递方式,实现比较复杂,其目标程序运行效率较低, 现已很 少采用。

分程序索引表:块头出现的地址

分程序符号表:end出现的位置

第十一章 代码优化

目的:提高目标代码运行效率

  • 时间效率(减少运行时间)
  • 空间效率(减少内存容量)

原则:进行优化必须严格遵循“不能改变原有程序语义”原则

优化的分类:

  • 从优化的层次,与机器是否有关,分为:

    • 独立于机器的优化:即与目标机无关的优化,通常是在中间代码上进行的优化。
    • 与机器有关的优化:充分利用系统资源(指令系统,寄存器资源)。
  • 从优化涉及的范围,又分为:

    • 局部优化:是指在基本块内进行的优化。 循环优化:对循环语句所生成的中间代码序列上所进行的优化。
    • 全局优化:顾名思义,跨越多个基本块的全局范围内的优化。因此它 是指在非线性程序段上(包括多个基本块, GOTO, 循环) 的优化。需要进行全局控制流和数据流分析,比较复杂。

满足以下三个条件的程序段,称为基本块:

  • 只有一个入口和一个出口,且语句为顺序执行的程序段
  • 它使得所有转向该基本块的入口都是该基本块的第一条语句
  • 如果块中任一语句被执行,则该块内的所有语句也将被 执行(无分支),且执行次数一样(无循环)

屏幕快照 2019-01-05 下午10.20.36.png

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值