1 参考
某百科:
LLVM的命名最早源自于底层虚拟机器(Low Level VirtualMachine)的首字母缩写,由于这个专案的范围并不局限于建立一个虚拟机器,这个缩写导致了广泛的疑惑。LLVM开始成长之后,成为众多编译工具及低阶工具技术的统称,使得这个名字变得更不贴切,开发者因而决定放弃这个缩写的意涵,现今LLVM已单纯成为一个品牌,适用于LLVM下的所有专案,包含LLVM中介码(LLVM IR)、LLVM除错工具、LLVM C++标准函式库等。
某书:
https://www.jianshu.com/p/1367dad95445
开发新的编程语言
https://kaleidoscope-llvm-tutorial-zh-cn.readthedocs.io/zh_CN/latest/https://llvm-tutorial-cn.readthedocs.io/en/latest/index.html
LLVM 文档:https://llvm.org/docs/index.html
众所周知,该领域巨作:龙书,《编译原理》
2 编译过程
众所周知编译有以下过程:
- 词法分析(词法分析 lexical analysis 或 扫描 scanning):得到词素(lexeme)序列,对于每个词素有词法单元(token)为 <token-name, attribute-value>,语法分析使用 token-name,attribute-value 指向符号表中关于词法单元的条目。
- 语法分析(语法分析 syntax-analysis 或 解析 parsing):得到语法树(可以理解为语法树显示了各个运算的指向顺序)
- 语义分析(semantic analysis):检查源程序是否和语言定义的语义一致
- 中间代码生成:生成一种中间表示,该中间表示方便转换成各种目标语言,方便进行机器无关的优化
- 代码优化:机器无关的代码优化
- 代码生成:映射到目标语言,重点部分是合理分配寄存器,以及变量的值
- 机器相关的代码优化:针对硬件进行代码优化
其中根据源程序生成中间代码的部分,称为编译器前端;根据中间代码生成目标语言的代码的部分称为编译器后端。
另外编译器在整个过程中非常重要的功能是符号表管理,记录变量名字、属性相关信息。
3 LLVM 架构
根据我们之前的介绍,这个图片就非常清晰了,LLVM 通过 LLVM IR 解耦了前端和后端,我们需要一个把一个新的高级语言编译,只需要编写相关的前端代码;我们需要增加特定平台的编译支持,只需要添加后端代码即可。
4 编译器矛盾
- 通用性与简单高效:很好理解,如果想要支持很多语言和很多硬件平台,编译器不可能做的非常简单
- 编译速度与程序执行速度:想要提高编译后程序执行速度,意味着我们需要做更深入的优化工作,同时意味着我们的编译时间会变长
5 编译器的优化问题
优化是很重要的编译工作,在芯片、巨型并发计算机结构日趋复杂情况下,带来了改进代码执行方式的机会,没有好的优化复杂的结构及其带来的性能提升没有办法充分利用,甚至会浪费更多。
很多情况下的优化效果无法判断和测量。
优化目标:
- 优化必须是正确的,不能改变源程序语义
- 优化可以很好的提高性能
- 优化所需的时间必须是可接受的
- 所需的工程方面的工作必须可管理:保证编译器的设计和维护费用可管理
优化的一个主要部分是:数据流优化
6 程序设计基础
6.1 静态动态
- 一个语言使用的策略支持编译器静态决定,我们就说使用了一个静态(static)策略,或者说这个问题实在编译时期(compile time) 决定
- 相反,如果这个问题只能在程序运行时期做出决定,则成为动态(dynamic policy)策略,或者说需要在运行时(run time) 决定
6.2 环境与状态
- 环境 environment:名字和内存(地址\区域)之间的映射关系
- 状态 state:内存位置到其值的映射