苹果为swift代码单独写了swiftc来编译前端代码,所以swift在编译时需要对Objetive-C
和Swift
分开编译,整个流程大致示意图
源代码经过clang编译器和swiftc编译器分别编译后生成中间代码,然后由LLVM后端对代码进行一步加工处理生成.o
文件并进行链接,绑定对应的arch最终生成可执行文件
LLVM是一款跨平台编译器基础设施,包含了系列的模块化编译组件和工具链,用于开发编译器前端和后端,在iOS工程中前端中间代码由苹果定制化开发,这里主要是利用了其后端的功能,将IR转换为不同平台的汇编代码.
Clang一个C语言、C++、Objective-C语言的编译器, Objective-C正是采用它来进行编译的
主要流程如下:
Tokenizatioon,从语文学上来将就是检查错别字 通过
-E和
-dump-tokens`命令可以查看替换后的宏模版和词法分析源码clang -cc1 -analyzer-checker-help
和-enable-checker
来开启某些规则,比如除0,越界,typeCastd等clang
的-ccc-print-phases
命令可以看看到基本的流程如下,从backend以后部分为LLVM后端的工作jiodg45@jiodg45s-MacBook-Pro SwiftCompile % clang -ccc-print-phases hello2.m
+- 0: input, "hello2.m", objective-c
+- 1: preprocessor, {0}, objective-c-cpp-output //宏模版替换
+- 2: compiler, {1}, ir //生成中间代码
+- 3: backend, {2}, assembler //汇编
+- 4: assembler, {3}, object //生成可执行.o文件
+- 5: linker, {4}, image //链接镜像文件
6: bind-arch, "x86_64", {5}, image //生成指定架构的文件
Tips: 在Xcode7之后评估提供了一种bitcode技术,及直接发布bitcode(.bc的中间代码,也称IR)
到AppStore,然后由appStore根据用户手机架构生成对应的执行文件以此来减少用户手机空间的占用
Intermediate Representation
,中间代码,它是我们生成的最终代码的完整展示,也是LLVM后端优化器的唯一入口swiftc是apple单独为swift代码开发的一款编译器,相比较clang它有更多的约束来保证swift的代码安全。 比如未初始化的变变量,边界和溢出检查
Objective-C
到swift的api中 sil @fibonacci: $(Swift.Int) -> () {
entry(%limi: $Swift.Int):
源代码和LLVM IR之间存在较大的抽象差距IR不适合进行源代码级分析
CFG缺乏保真度
CFG脱离热通道
CFG和IR下降过程中的重复工作
完全表示程序语义
设计用于代码生成和分析
位于编译器管道的热路径上
源代码和LLVM之间的抽象桥梁
内置不透明地表示SIL Swift标准库下面层的类型和操作,在内置层之上实现用户级界面,同俗来讲就是和机器架构相关的类型在底层进行封装和自动转换
struct Int { var value: Builtin.Int64 }
struct Bool { var value: Builtin.Int1 }
func ==(lhs: Int, rhs: Int) -> Bool {
return Bool(value: Builtin.icmp_eq_Word(lhs.value, rhs.value))
}
entry(%c: $SomeClass):
%foo = class_method %c: $SomeClass, #SomeClass.foo : $(SomeClass) -> ()
apply %foo(%c) : $(SomeClass) -> ()
sil_vtable SomeClass {
#SomeClass.foo : @SomeClass_foo
}
sil @SomeClass_foo: $(SomeClass) -> ()
Addable
协议对应的Int
类型,可以兼容多种类型的Int操作entry(%x: $Int, %y: $Int):
%plus = function_ref @Int_plus : $(Int, Int) -> Int
%z = apply %plus(%x, %y) : $(Int, Int) -> Int
...
sil_witness_table Int: Addable {
#Addable.+ : @Int_plus
}
可以通过swiftc
提供的更多命令来研究SIL
MODES:
-dump-ast Parse and type-check input file(s) and dump AST(s)
-dump-parse Parse input file(s) and dump AST(s)
-dump-pcm Dump debugging information about a precompiled Clang module
-dump-scope-maps <expanded-or-list-of-line:column>
Parse and type-check input file(s) and dump the scope map(s)
-dump-type-info Output YAML dump of fixed-size types from all imported modules
-dump-type-refinement-contexts
Type-check input file(s) and dump type refinement contexts(s)
-emit-assembly Emit assembly file(s) (-S)
-emit-bc Emit LLVM BC file(s)
-emit-executable Emit a linked executable
-emit-imported-modules Emit a list of the imported modules
-emit-irgen Emit LLVM IR file(s) before LLVM optimizations
-emit-ir Emit LLVM IR file(s) after LLVM optimizations
-emit-library Emit a linked library
-emit-object Emit object file(s) (-c)
-emit-pcm Emit a precompiled Clang module from a module map
-emit-sibgen Emit serialized AST + raw SIL file(s)
-emit-sib Emit serialized AST + canonical SIL file(s)
-emit-silgen Emit raw SIL file(s)
-emit-sil Emit canonical SIL file(s)
-emit-supported-features
Emit a JSON file including all supported compiler features
-index-file Produce index data for a source file
-parse Parse input file(s)
-print-ast Parse and type-check input file(s) and pretty print AST(s)
-resolve-imports Parse and resolve imports in input file(s)
-scan-dependencies Scan dependencies of the given Swift sources
-typecheck Parse and type-check input file(s)
https://www.youtube.com/watch?v=Ntj8ab-5cvE