解释器和编译器
解释器
:解释器是直接执行用编程语言编写的指令的程序,解释的程序总是需要解释器来运行编译器
:编译器是需要把我们的源代码翻译成机器能够读的懂二进制文件 举例: 下面是一段python代码
print("hello world\n")
只要我们安装了python的环境,就可以执行,这就是解释器的功能。
同样下面是一段c语言的代码:
#include<stdio.h>
int main(int argc,char * argv[]){
printf("hello world\n");
return 0;
}
如果我们需要执行需要先编译:
编译后会生成一个二进制文件a.out,然后才能运行。我们可以在
/usr/bin
目录下找到clang
和python
,编译器和解释器
总结:解释器实际上就是边解释边运行,而编译器需要将我们所有的代码打包成一个可执行的二进制文件。
LLVM
概述:LLVM是构架编译器(compiler)的框架系统,以C++编写而成,用于优化以任意程序语言编写的程序的编译时间(compile-time)、链接时间(link-time)、运行时间(run-time)以及空闲时间(idle-time),对开发者保持开放,并兼容已有脚本。
传统编译器的架构
Frontend(编译前端)
:解析源代码。进行词法分析、语法分析,检查源代码是否存语法错误,然后构建抽象语法数(Abstract Syntax Tree).LLVM前端还会生成中间代码(intermedidate representation)IR.(Optimizer)优化器
:负责进行各种代码优化。改善代码的运行时间Backend(后端)
:将代码映射到目标指令集。生成机器语言,并且进行机器相关的代码优化.
iOS编译架构
Objective -C/C/C++
的前端编译器都是clang
,swift
的的前端编译器是swift
.后端都是LLVM
。
LLVM 的设计
- 当编译器决定支持多种语言多种硬件架构时,LLVM的作用就体现出来了。其他的编译器如GCC也非常成功,但是作为整体应用程序设计,就有很多限制了.
- LLVM最重要的方面是,使用通用的代码表示形式(IR),这样就可以为任何编程语言编写前端,并且可以为任何硬件架构编写后端
编译流程
- 我们新建一个.m文件通过如下命令查看,编译流程
clang -ccc-print-phases main.m
- 0:输入文件:找到源文件
- 1:预处理阶段:这个过程包括宏的替换,头文件的导入。
- 2:编译阶段:进行词法分析、语法分析、检测语法是否正确。最终生成IR。
- 3:后端:这里LLVM会通过一个一个pass(节点)去优化,每个pass去做一些事情,最终生成汇编代码
- 4:生成目标文件
- 5:链接:链接需要的动态库和静态库,生成课执行文件
- 6:通过不同的架构生成对应的课执行文件
预编译
#include <stdio.h>
#define kMachoC 2
int main(int argc, const char * argv[]) {
int a= 1;
int b = 3;
printf("%ld",a+b+kMachoC);
return 0;
}
clang -E main.m
可以看到头文件的导入和和宏的替换
编译阶段
词法分析
clang -fmodules -fsyntax-only -Xclang -dump-tokens main.m
预编译处理完成后会进行
词法分析
,这里会把代码切成一个一个token,比如大小括号,还有字符串等
语法分析
clang -fmodules -fsyntax-only -Xclang -ast-dump main.m
词法分析完成之后就是语法分析,它的任务是验证语法是否正确,在词法分析的基础上将单词序列组合成各类语法短语。如“程序”、“语句”、“表达式”等待,然后将所有的节点组成抽象语法树。然后分析语法是否正确。
生成中间代码
clang -S -fobjc-arc -emit-llvm main.m
执行上面的命令会生成.ll
文件,
IR优化
LLVM的优化级别-O0 -O1 -O2 -O3 -Os
优化命令:
clang -Os -S -fobjc-arc -emit-llvm main.m -o main.ll
优化后的代码:
bitCode
clang -emit-llvm -c main.ll -o main.bc
xcode7之后,开启bitcode之后苹果会做进一步优化,生成.bc的中间代码.
生成汇编代码
通过最终的.bc或者.ll生成汇编代码
clang -S -fobjc-arc main.bc -o main.s
clang -S -fobjc-arc main.ll -o main.s
汇编优化:
clang -Os -S -fobjc-arc main.m -o main.s
生成目标文件
clang -fmodules -c main.s -o main.o
查看目标文件:xcrun nm -nm main.o
external
:表示可以访问的外部文件
生成课执行的文件(链接)
clang main.o -o main
查看链接后的文件:xcrun nm -nm main
_dyld_stub_binder
,表示需要重绑定的符号,也就是printf
函数