文档介绍:代码生成
第八章
本章要求
主要内容:目标代码生成的任务,设计目标代码生成器需要考虑的主要问题,简单的代码生成器,Sample语言目标代码生成器的设计
重点掌握:代码生成要考虑的主要问题,寄存器的分配,基本块的代码生成,以及从DAG生成代码
代码生成所处的位置
概述
代码生成器的作用
各种代码的形式
中间代码: 后缀式,三地址代码,四元式
符号表中的项:名字,类型,嵌套深度,偏移量
目标代码:绝对机器代码,可重定位代码,汇编
代码生成器的输出必须是正确和高质量的
产生最优化代码的问题是不可判定的
代码生成器设计中的问题
代码生成器依赖于目标机器和操作系统
要充分发挥目标机器的能力:充分利用目标机器的资源
代码生成器固有的问题
存储管理
指令选择
寄存器分配
计算次序选择
可移植的代码生成器
机器描述
代码生成器的输入
符号表信息
决定中间代码中名字所代表的数据对象的运行地址
偏移量
作用域
可能在动态时刻作为调试信息存在
中间代码
代码生成的很多技术是可以用于不同的中间代码
代码生成前,中间代码记录了足够详细的程序信息
名字的值可以表示为目标机器能够直接操作的数
类型检查已经完成
明显的语义错误已经发现
代码生成器的输出:目标程序
绝对机器语言
可以放在内存中固定地方,并立即执行
小程序、需要迅速编译和执行
可重定位的机器语言
程序可以分为多个目标模块,分别编译
需要连接装配器将一组可重定位模块一起装入执行
需要额外的开销,但灵活:可分别编译子程序和从目标模块中调用其它先前编译好的程序模块
如果目标机器不能自动处理重定位,则编译器必须提供显式的重定位信息给装配程序
汇编语言
代码生成的过程容易
避免了重复汇编器的工作
存储管理
把程序中的名字映射到运行时的目标对象的地址是由前端和代码生成器共同完成的
语言中过程的语义决定了运行时刻名字如何与存储空间相联系
对名字的引用通过符号表
记录了名字在过程数据区的相对地址
所需要的存储空间
运行时活动记录的管理
运行时活动记录的分配和释放作为过程调用和返回序列的一部分
call(调用),return(返回)
halt(暂停),其它语句
存储管理分静态、栈式和堆式存储分配
一个代码生成器的输入
其中,arr,i,j是过程s中定义的数据;buf和n是过程p定义的数据
三地址代码
/*s的代码*/
action1
call p
action2
halt
/*p的代码*/
action3
return
S的活动记录
返回地址
arr
i
j
p的活动记录
返回地址
buf
n
0:
4:
56:
60:
0:
4:
84:
指令地址的决定
通过一个计数器决定每个指令的地址
标号的处理:j: goto i /*j是当前语句的号码*/
如果i小于j
i出现在j之前,目标地址是i对应的三地址代码的第一条指令地址
如果i大于j
i出现在j之后,目标地址此时不可知,可以利用回填的技术解决