编译后端:构建可运行程序与中间形式解析
1. 编译后端概述
编译过程通常分为前端和后端,前端负责源代码的分析,后端负责目标代码的合成。后端的工作包括代码生成、汇编和链接,最终将源代码转化为可运行的程序。
1.1 后端编译器结构的多样性
后端编译器的结构不像前端那样统一。即使是针对同一语言和同一机器的编译器,其内部结构也可能有很大差异。不同的编译器可能使用不同的中间形式来表示程序,并且在代码改进方面也有很大不同。例如,简单的编译器或为了编译速度而设计的编译器可能不会进行太多的代码改进;而即时编译器可能不使用单独的链接器。在许多编译器中,代码生成器的大部分或全部可能由一个工具自动生成,该工具以目标机器的形式描述作为输入。
1.2 一种可行的编译阶段划分
下面是一个传统编译器的七阶段结构示例:
- 语言相关阶段 :扫描、解析和语义分析,这些阶段依赖于编程语言。
- 与语言和机器无关阶段 :中间代码生成和机器无关代码改进,这些阶段在一定程度上既不依赖于语言也不依赖于机器。
- 机器相关阶段 :目标代码生成和机器特定代码改进,这些阶段依赖于目标机器。
具体流程如下:
1. 扫描器和解析器驱动一组动作例程来构建语法树。
2. 语义分析器遍历语法树,执行所有静态语义检查,并初始化各种对后端有用的属性。
3. 中间代码生成阶段将语法树的节点分组为基本块,创建控制流图,并在每个基本块内将操作表示为理想化 RISC 机器的指令,使用虚拟寄存器。
4.