5.1 简介

编译器的输入是源代码,输出是目标机器代码。编译器前端负责处理与源代码相关的逻辑,例如前面章节所讨论的词法分析、语法分析与类型检查;而编译器后端负责处理与目标代码相关的逻辑,例如目标代码生成、目标代码优化等。而中间代码(IR, Intermediate Representation)便是衔接前、后端的数据结构,因此可以将 IR 理解为编译器前端的输出以及编译器后端的输入。在一个模块化的编译器中,通常情况下 IR 即不会包含与任何源代码相关的信息,也不会包含与特定目标机器相关的信息,因此如果我们有 n 个语言的编译器前端与 m 个目标机器的编译器后端的话,便可以组合得到 n * m 种编译程序,极大地减少了构建编译器的工作量。

可用于 IR(Intermediate Representation) 的数据结构多种多样,例如可以是与编程语言自然结构相似的树状结构,也可以是与目标指令结构相似的三地址代码。事实上,在将源代码翻译成目标机器代码的过程中,编译器可能构造出一系列中间表示,例如编译器可能会先构造出树状结构的 IR, 因为该结构更接近源语言的层次结构,便于进行静态类型检查之类的处理;随后再构造出三地址代码的 IR, 这种结构与机器指令更加相似,适用于机器相关的任务处理,例如寄存器分配、指令选择等。

Go 编译器在完成类型检查之后,首先会生成一颗基于 AST 的 IR Tree 进行函数内联、逃逸分析等操作,然后再生成基于 SSA 的 IR 进行编译。本章介绍生成 IR Tree 的生成逻辑。

最后更新于