编译原理教程第九章目标代码生成
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
简化:基本块中的所有临时变量均看作基本 块出口之后的非活跃变量;所有非临时变 量均看作基本块出口之后的活跃变量。
计算变量待用信息的算法:
(1)开始时,符号表中各变量为“非待用”,变量在出口 之后是否活跃填入活跃信息栏;
(2)从基本块出口到入口由后向前依次处理各个中间代 码。对每一条代码 i: A:=B op C,执行步骤:
类型 直接地址型 寄存器型 变址型 间址型
指令形式
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
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的次数
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 寄存器分配
第9章 目标代码生成
以源程序的中间代码作为输入,产生等 价的目标代码作为输出,如图。
源程序
编译前端
中间 代码
代码优化
中间 代码
代码生成器
目标程序
符号表
代码生成器的输入包括中间代码和符号表中 的信息;
代码生成是把语义分析后或优化后的中间代 码变换成目标代码。
9.1 概述
1. 代码生成器的输入: 源程序的中间表示:如三地址代码; 符号表中的信息:在数据区中的相对地址
生成目标代码 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 )。
2. 目标程序: 绝对机器语言代码; 可再定位机器语言代码; 汇编语言程序。
9.1 概述
代码生成着重考虑两个问题:
如何使生成的目标代码较短; 如何充分利用寄存器,减少目标代码访
问存储单元的次数。
9.2 假想的目标机器模型
采用一个模型作为目标机器:
1、具有多个寄存器,regs可作为累加器或变址 器;具有四种类型的指令形式
例: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
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 简单代码生成器
功能:依次把每条中间代码变换成目标代码, 并且在一个基本块的范围内考虑充分利用 寄存器。
有效利用寄存器,生成更高效的目标代码。 指令的执行代价:指令访问主存单元次数+1 如:
op Ri,Rj 执行代价为1 op Ri,M 执行代价为2 op Ri,*Rj 执行代价为2 op Ri,*M 执行代价为3
对于循环,把可用的几个寄存器固定分配给节省 执行代价最多的那几个变量。
节省代价计算公式: [USE(M,B)+ 2*LIVE(M,B)]
各中间代码对应的目标代码:
序号 中间代码 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
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’ ;否则
寄存器描述和变量地址描述
1、在代码生成过程中,建立寄存器描述数组 RVALUE,动态地记录各reg是空闲的、已分 配给某个变量、或已分配给某几个变量。
2、在代码生成过程中,建立变量地址描述数 组AVALUE,动态地记录各变量现行值的存 放位置:是在某个reg中、在某主存单元中、 或在某reg和主存单元中。
把符号表中变量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
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 待用信息与活跃信息
变量在基本块内的待用信息:从基本块的 出口由后向前扫描,对每个变量建立相应 的待用信息链和活跃变量信息链。
计算变量待用信息的算法:
(1)开始时,符号表中各变量为“非待用”,变量在出口 之后是否活跃填入活跃信息栏;
(2)从基本块出口到入口由后向前依次处理各个中间代 码。对每一条代码 i: A:=B op C,执行步骤:
类型 直接地址型 寄存器型 变址型 间址型
指令形式
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
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的次数
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 寄存器分配
第9章 目标代码生成
以源程序的中间代码作为输入,产生等 价的目标代码作为输出,如图。
源程序
编译前端
中间 代码
代码优化
中间 代码
代码生成器
目标程序
符号表
代码生成器的输入包括中间代码和符号表中 的信息;
代码生成是把语义分析后或优化后的中间代 码变换成目标代码。
9.1 概述
1. 代码生成器的输入: 源程序的中间表示:如三地址代码; 符号表中的信息:在数据区中的相对地址
生成目标代码 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 )。
2. 目标程序: 绝对机器语言代码; 可再定位机器语言代码; 汇编语言程序。
9.1 概述
代码生成着重考虑两个问题:
如何使生成的目标代码较短; 如何充分利用寄存器,减少目标代码访
问存储单元的次数。
9.2 假想的目标机器模型
采用一个模型作为目标机器:
1、具有多个寄存器,regs可作为累加器或变址 器;具有四种类型的指令形式
例: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
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 简单代码生成器
功能:依次把每条中间代码变换成目标代码, 并且在一个基本块的范围内考虑充分利用 寄存器。
有效利用寄存器,生成更高效的目标代码。 指令的执行代价:指令访问主存单元次数+1 如:
op Ri,Rj 执行代价为1 op Ri,M 执行代价为2 op Ri,*Rj 执行代价为2 op Ri,*M 执行代价为3
对于循环,把可用的几个寄存器固定分配给节省 执行代价最多的那几个变量。
节省代价计算公式: [USE(M,B)+ 2*LIVE(M,B)]
各中间代码对应的目标代码:
序号 中间代码 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
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’ ;否则
寄存器描述和变量地址描述
1、在代码生成过程中,建立寄存器描述数组 RVALUE,动态地记录各reg是空闲的、已分 配给某个变量、或已分配给某几个变量。
2、在代码生成过程中,建立变量地址描述数 组AVALUE,动态地记录各变量现行值的存 放位置:是在某个reg中、在某主存单元中、 或在某reg和主存单元中。
把符号表中变量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
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 待用信息与活跃信息
变量在基本块内的待用信息:从基本块的 出口由后向前扫描,对每个变量建立相应 的待用信息链和活跃变量信息链。