编译原理(7) 中间代码生成
中间代码生成
一、表达式的翻译与控制流的翻译
1. 核心
1.1 大局观
1.2 分工、合作
分工: $B$, $S_1$ 各自负责自己的中间代码生成
合作: $B$ 为 true 或 false 时, 需要跳转到不同的位置(类似
goto label
), 这个位置 $B$ 不知道, 需要父节点(或父父节点..)通过继承属性传递信息
- 当 $B$ 为 true, $S$ 知道应该跳转到哪
- 当 $B$ 为 false, $P$ 知道应该跳转到哪
2. 表达式的翻译
2.1 总览
- 起始符号为第三段的 $P$
2.2 表达式的中间代码翻译
- 综合属性 $\textcolor{green}{E.code}$: 中间代码
- 综合属性 $\textcolor{blue}{E.addr}$: 变量名(包括临时变量)、常量
- LLVM IR
- 因为没有被使用过, 设置优化后会全部删掉
2.3 数组引用的中间代码翻译
- 声明: $\text{int } a[2][3]$
- 数组引用: $x = a[1][2]; a[1][2] = x$
- 需要计算 $a[1][2]$ 相对于数组基地址 $a$ 的偏移地址
- $addr(a[1][2]) = \textcolor{blue}{base} + 1 \times 12 + 2 \times 4$
- 综合属性 $\textcolor{green}{L.array(.base)}$: 数组基地址(即,数组名)
- 综合属性 $\textcolor{red}{L.addr}$: 偏移地址
eg: $c + a[i][j]$
-
为什么要多一个
i64 0
:- %2 指向的是这一整个数组,如果直接对其偏移就会偏移 n 个数组大小的位置
- 因此需要 i64 0,先对其解一层([0])
2.4 控制流语句与布尔表达式的中间代码翻译
继承属性 $\textcolor{blue}{B.true, B.f alse, S.next}$ 指明了控制流跳转目标
- 继承属性 $\textcolor{red}{S.next}$
- $S.next$ 为语句 $S$ 指明了 “跳出” $S$ 的目标
- $P$ “知道” $S.next$ 在哪,会在 $S$ 后面添加标签
- 代表了表达式的翻译, 包括数组引用
if 语句
举例
if-else 语句
举例
while 语句
- 举例
并列语句
2.5 布尔表达式的中间代码翻译
!
||
&&
rel