表示与程序语义
编译器不必直接把源代码字符改成机器指令。它可以先构造语法树,再生成适合优化的中间表示,最后选择目标指令。中间表示是编译过程中的工作材料,不能仅凭文件后缀判断它处于哪个层次。
LLVM 使用带类型的低层表示,并以静态单赋值形式组织寄存器式的值。内存中的数据结构、磁盘上的 bitcode 和可读文本是同一表示的不同形式,文本形式并不等于某种处理器的汇编。
把复杂表达式拆开
GCC 的 GIMPLE 把复杂表达式拆成较简单的三地址操作,必要时引入临时变量。以无副作用的算术表达式 a + b × c 为例,可以先计算乘积,再把结果交给加法;真实语言中的求值顺序和副作用仍须遵守原语义。
降低可以逐步去掉高层控制结构或词法作用域信息。较高层表示便于保留源程序结构,较低层表示更接近分支、基本操作和目标代码,两者服务于不同阶段。
参考:[1]
构造、检查与优化边界
LLVM 教程通过语法树节点生成指令:先取得左右操作数,再构造加法或乘法等操作。表示中的类型规则约束操作数和结果,供后续分析使用;临时值的可读名称只是调试上的帮助。
能被解析不代表表示正确。LLVM 还检查值的定义能否支配使用等条件。中间表示有利于验证变换,却不会自动证明优化保持了程序语义;产生错误表示仍是编译器缺陷。