前言
本文是对2. Intermediate Representation的整理。由于本科时候的《编译原理》学的稀烂,所以无法旁征博引。下面仅仅是将理解的课件内容搬运过来。详见课件对应的课程视频。
由于之前整理过clang&llvm简介。本文仅仅包含,三地址码(3-address code, 3AC)转换成控制流程图(control flow graph, CFG)。
三地址码
三地址码是语言的一种中间表示(intermediate representation, IR)。三地址码由类似于汇编语言的指令序列组成,每个指令最多有三个操作数(operand),并且通常是赋值和二元运算符的组合。例如,t1 := t2 + t3
。(三地址代码拆分了多运算符算术表达式以及控制流语句的嵌套结构,所以适用于目标代码的生成和优化。)
比如将下面的一条语句,转换成3AC形式。
x = (-b + sqrt(b^2 - 4*a*c)) / (2*a)
t1 := b * b
t2 := 4 * a
t3 := t2 * c
t4 := t1 - t3
t5 := sqrt(t4)
t6 := 0 - b
t7 := t5 + t6
t8 := 2 * a
t9 := t7 / t8
x := t9
常用的三地址指令,如下所示。其中
指令 | 指令含义 | 注释 |
---|---|---|
x = y bop z | 二元操作 | bop: binary arithmetic or logical operation |
x = uop y | 一元操作 | uop: unary operation (minus, negation, casting) |
x = y | 赋值操作 | - |
goto L | 无条件跳转 | L: a label to represent a program location |
if x goto L / if x rop y goto L | 有条件跳转 | rop: relational operator (>, <, ==, >=, <=, etc.) |
… | … | … |
这里略去:将真实代码转换成三地址码,解释三地址码指令含义。
控制流程图
思考下,如何使用程序(算法),将下面的3AC转换成CFG。
基本块
在转换之前,我们需要了解基本块的概念。基本块(basic block, BB)是连续的三地址码指令,这个块具有如下性质:
- 必须从第一条指令,进入基本块。
- 必须从最后一条指令,离开基本块。
构建基本块的算法如下:
输入:一个程序P生成的三地址码序列。
输出:程序P的一系列基本块
程序:
(1)找出程序中,将来生成的基本块的第一条指令(我们称之为leaders)。
* 程序P的三地址码的第一条指令,是leader。
* 所有非条件/条件跳转指令的目标位置指令,是leader。
* 所有非条件/条件跳转指令的下一条指令,是leader。
(2)生成程序P的基本块。
如果将程序P看出直线,leaders为不同的切割点。切割出来的(左闭右开)区间便是基本块。
上面的示例三地址码程序,经过该算法,得到的基本块,如下图所示。
基本块的连接
基本块为节点。下面,我们只需要在基本块上添加真确的边,便可以生成控制流程图。连线遵循下面两条规则:
- 基本块之间,存在非条件/条件跳转,需要添加边。
- 顺序相邻的两个块之间,需要添加边。
给基本块节点,添加边之后,如下图所示。即,将三地址码程序转换成控制流程图。