前言
LLVM编译运行在iOS开发中经常用到,对于实现的原理,其实我们在开发中并不关注,但是作为一个程序爱好者来说,对这些信息的基本了解之后,下面先从解释器和编译器开始
解释器
解释器对对应用程序代码进行逐行解读直接进行执行
- 例如python就是脚本语言,实际上就是解释性语言
- 通过
touch hello.py在文件路径中 新建一个.py文件 - 写入执行代码 print("hello");
- 通过 python hello.py 可以直接执行
- 通过python解释器 可以直接解释执行并且输出 hello
编译器
编译器是对应用程序代码进行中间处理成可执行文件然后在进行执行
- 同理创建 hello.c的文件, 需要通过clang 编译成对应的 a.out的可执行文件
- 编译器 hello.c的文件, 需要通过clang 编译成对应的 a.out的可执行文件
- 在执行输出
传统编译器
传统编译器分为Frontend 前端,Optimizer 优化器,Backend 后端,一个流程进行执行,每个流程都是关联的
编译器前端
- 对源代码进行解析,包含词法分析,语法分析,语义分析,通过语义分析可以抽象语法树(Abstract sSyntax Tree)
优化器
- 应用程序代码进行优化,冗余代码,减少编译时间等,例如 Xcode中,BuildSetting中如图
后端
- 也可以称为代码生成器 CodeGenerator
- 变为对应的汇编代码,映射到对应的CPU指令集,生成机器语言
- 也可以对代码进行优化
LLVM
- LLVM是编译器的架构系统,前后端 分离,来优化编译时间,链接时间,运行时间,空闲时间
- LLVM可以生成对应IR代码,用来表示代码的形式
- 可以编写任何程序的前后端
Clang
clang就是LLVM中的一个字子项目,用来编译 C/C++ Objc 语言的编译器,属于编译器前端
编译流程
编译的流程可以通过 clang -ccc-print-phases main.m main.m 是目标文件输出如下
+- 0: input, "main.m", objective-c
+- 1: preprocessor, {0}, objective-c-cpp-output
+- 2: compiler, {1}, ir
+- 3: backend, {2}, assembler
+- 4: assembler, {3}, object
+- 5: linker, {4}, image
6: bind-arch, "x86_64", {5}, image
-
输入文件
-
预处理阶段,包括宏定义的替换,头文件的导入等
-
编译阶段
- 词法分析,生成一个一个token
- 语法分析,生成抽象语法树
- 检测语法是否正确,最终生成IR
-
后端 LLVM会通过一个一个pass去优化,最终生成汇编代码
-
assembler 生成对应的目标文件object
-
链接,链接需要的动态库和静态库生成可执行文件
-
通过不同的架构生成 生成对应的可执行文件
链接和绑定
- 链接 :生成可执行文件的时候,需要链接所需要的库,例如当代码 需要Print的时候 需要链接外部库 libsystem中,在编译期实现
- 绑定: 在运行期中通过libsystem中的地址进行绑定,当程序代码执行到这个过程,通过这个绑定的地址进行调用
LLVM的优点
- 前后端分离
- 优化想过相对比较理想