作者 | 李彬
整理 | 编程语言 Lab
李彬,编程语言 Lab 程序分析应用专家,南京大学计算机系博士。研究领域是程序分析及验证。
本文以技术文章的方式回顾李老师在 SIG-程序分析 技术沙龙上的分享,回顾视频也已经上传 B 站,欢迎小伙伴们点开观看。
# Intermediate Representation #
根据 Wiki [1] 中的描述,Intermediate Representation 是编译器 / 虚拟机内部用于表示源代码的数据结构,被用来做进一步处理。例如下图中,编译器 Front End 读入源代码产生 IR;Middle End 将 IR 转换为运行效率更高的等价 IR;Back End 转换 IR 到 native code。
编译器内部使用多种 IR。《Engineering a Compiler》 [2] 将 IR 大体分为三类:
Structural IR:使用图结构表示 IR,一般使用该类 IR 进行源到源转换。编译器中这类 IR 有:Concrete Syntax Tree (CST),Abstract Syntax Tree (AST),Directed Acyclic Graph (DAG,用于表达式优化) 等。
Linear IR:类似 abstract machine 的汇编代码,编译器一般使用该类 IR 进行 lowering。编译器中这类 IR 有:three-address code,stack-machine code 等。
Hybrid IR:组合 Structural IR 和 Linear IR,该类 IR 尝试集合 Structural IR 和 Linear IR 的优点,避免它们的缺点。例如,常见的 CFG 中使用 low-level linear IR 表示基本块,使用图表示基本块之间的控制流关系。
当然,除了上述分类方式,也有其他的分类方式,例如 Chow Fred 在《The Challenge of Cross-language Interoperability》[3] 中将 IR 分为 Hierarchical IR 和 Flat IR。Hierarchical IR 类似上述分类中的 Structural IR 和 Hybrid IR,Flat IR 类似 Linear IR。Hierarchical IR 在形式上更接近典型的编程语言,一般被认为更高的抽象层次;Flat IR 通常被指定为更接近编译目标。
IR 在编译器中被设计用来进行进一步的处理,包括:转换、分析 和 优化。一个良好设计的 IR 应该可以被转换到多后端 (instruction set architectures),同时又能被不同的语言前端转换,这样可以简化编译器开发工作量。例如下图中,IR 将 20 个编译器(5 个语言 x 4 个后端)简化为只需要 5 个编译器前端 + 4 个编译器后端。
除了上面的作用外,IR 主要被分析工具和编译器用于分析和优化。下面我展开介绍一下 IR 在其中的应用。