# 中间代码表示

1. 需要中间代码表示的原因：实践过程中，推陈出新的语言，不断涌现的指令集，开发成本之间的权衡

2. 中间代码表示将前端和后端分离，不同的源语言、不同的机器可以得到不同的编译优化组合，前端只关注和分析与源语言相关的细节，与目标机器无关

3. 中间代码表示的类型包括后缀表示、语法树、三地址码、静态单赋值形式

4. 后缀表示：将运算符放在操作数之后，不需要括号，便于计算机处理表达式

5. 语法树是一种图形化的中间表示，运算时从叶节点向根节点计算，用于代码的优化

6. 三地址码 TAC, Three-Address Code
   - 最多一个算符
   - 最多三个计算分量
   - 每一个分量代表一个地址
   - 是语法树 / DAG 的一种线性表示

7. 静态单赋值 SSA，便于某些代码优化
   - 所有赋值指令是对不同名字的变量的赋值
   - 同一个变量在不同控制流路径上都被定值

8. 基本块：连续的三地址指令序列，控制流从开始进入，从末尾离开，中间没有停止或分支的可能性

9. 基本块划分算法
   - 确定基本块的第一个指令，即 **首指令**
     - 指令序列的 *第一条三地址指令* 是首指令
     - 任意 *转移指令的目标指令* 是首指令
     - *紧跟一条转移指令的指令* 是首指令
   - 每个首指令对应的基本块包含从它自己开始，直到 *下一条首指令* (不含) 或 *指令序列结尾* 之间的所有指令

10. 流图：节点是一些基本块，从基本块到基本块之间有边当且仅当后者的第一条指令 **可能** 紧跟在前者的最后一条指令之后
    - 有一个从前者的结尾跳转到后者开头的跳转指令
    - 后者紧跟在前者之后，且前者结尾 **没有无条件跳转指令**

11. 流图中的一个节点集合是一个循环，如果满足
    - 集合有唯一的入口节点
    - 任意节点都有一个到达入口节点的非空路径，且路径全部在集合中

12. 不包含其他循环的循环叫做内循环

13. LLVM IR
    - RISC 风格的 **三地址指令** 方式
    - SSA 形式，无限 **虚拟寄存器** 的假设
    - **强类型系统**，每个指令及操作数有自身的类型

14. Light IR
    - 保留必要的核心类，简化核心类的继承关系与成员设计
    - 提供与 LLVM 相同的生成 IR 的接口
