其他分享
首页 > 其他分享> > 9. 代码生成

9. 代码生成

作者:互联网

9. 代码生成

代码生成的核心问题;

指令选择

为每条中间语言语句选择恰当的目标机指令或指令序列

首先原则是保证语义的一致性

直接为中间语言语句找到语义一致的指令序列模板:

a=b+c

MOV b, R0 // 将b装入R0
ADD R0, c // 将c加到R0
MOV R0, a // 存R0的内容到a

其次要考虑所生成代码的效率

一个丰富目标指令集的机器可以为一个给定的操作提供几种实现方法

假设每条指令在操作数准备好后执行其操作的代价为1

访问一次内存则增加代价1

上述代码执行代价为6

若假设R1和R2中已经分别包含了b和c的值,那么代码如下:

MOV R1, R0 // 将寄存器R1的内容装入寄存器R0
ADD R0, R2 // R2的内容加到R0
MOV R0, a // 存R0的内容到a

代价为4

假设R1和R2中已经包含了b和c的值,并且b的值以后不再需要

ADD R1, R2 // R2的内容加到R1
MOV R1, a // 存R1的内容到a

代价为3

寄存器分配

再分配期间,为程序的某一点选择驻留在寄存器中的一组变量

在随后的指派阶段,挑出变量将要驻留的具体寄存器,即寄存器赋值

指令调度

代码生成过程

寄存器计算机:

结构:

内存:存放溢出的变量

寄存器:进行运算的空间,假设有无限多个

执行引擎:指令的执行

初始时x、y等变量都放到内存中

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FpgnaM13-1642042259498)(…/picture/74.png)]

寄存器机器只支持一种数据类型int

在代码生成的阶段,假设寄存器机器上会有无限多个寄存器

基本块为单位的一种简单代码生成算法

指令选择是可以通过直接对应完成的,所以这个代码生成算法的核心是处理好在基本块范围内如何充分利用寄存器的问题

原则:

直接采用语法树的后序遍历,暴力进行罗列

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ENAiPauM-1642042259501)(…/picture/80.png)]

启发式算法

寄存器描述数组RVALUE,RVALUE[R]描述寄存器R当前存放哪些变量

变量描述数组AVALUE,AVALUE[a]表示变量a的值存放在哪个寄存器中(或不在任何寄存器中)

函数getreg的描述

▪ getreg功能:以 i: x := y op z 或 i: x := y为参数,返回一个伪寄存器

(1) 对于i: x := y op z

若y∈RVALUE[R],且在语句i之后y在基本块中不再被引用,同时也不是基本块出口之后的活跃变量,则返回R;否则,返回一个新的伪寄存器R’

(2) 对于i: x := y

若y∈RVALUE[R],则返回R;否则,返回一个新的伪寄存器R’

(1) 对每个TAC语句 i: x := y op z 或 i: x := y,依次执行下述步骤:

以i为参数,调用getreg(i),返回一个寄存器R,作为存放x现行值的寄存器

利用AVALUE[y]和AVALUE[z],确定出y和z现行值的存放位置

▪ 如果其现行值在寄存器中,则把寄存器取做Ry和Rz;

▪ 如果其现行值不在寄存器中,则在相应指令中仍用y和z表示

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iPL1jnRS-1642042259502)(…/picture/75.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uNxsbEpW-1642042259503)(…/picture/76.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8yZ7izzL-1642042259504)(…/picture/77.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3QzFEM3A-1642042259505)(…/picture/78.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hvTzfKBw-1642042259506)(…/picture/79.png)]

设有以下TAC语句序列组成的基本块,假设在出口处,b和d是活跃的

语句代码寄存器描述变量地址描述
t := a – bMOV a R0; sub R0 bR0包含tt在R0中(a不再在R0)
a := bMOV b R1;R0包含t R1包含a, bt在R0中 a, b在R1中
u := a – cMOV R1 b; sub R1 cR0包含t R1包含ut在R0中 u在R1中
v := t + uadd R0 R1R0包含v R1包含uu在R1中 v在R0中
d := v + uadd R0 R1; MOV R0 dR0包含dd在R0中和内存中

u := a – c | MOV R1 b; sub R1 c | R0包含t R1包含u | t在R0中 u在R1中 |
| v := t + u | add R0 R1 | R0包含v R1包含u | u在R1中 v在R0中 |
| d := v + u | add R0 R1; MOV R0 d | R0包含d | d在R0中和内存中 |

都假定寄存器数目没有上限(采用简易的寄存器分配算法)

标签:代码生成,R0,R1,基本块,指令,寄存器,变量
来源: https://blog.csdn.net/weixin_45360119/article/details/122469202