Xcode的编译过程

开发者 2024-9-21 06:34:21 66 0 来自 中国
本日我们来对iOS开发的常用工具Xcode的编译流程举行一个简朴的相识和分析
1.png OC:source code > Clang  ->  LLVM -> Backend ->  Executable
Clang做的变乱是词法分析-> token流->语法分析-> AST -> LLVM IR
AST(Abstract Syntax Tree  抽象语法树)
IR(intermediate representation  中央代码)
swift:source code > swiftc  ->  LLVM -> Backend ->  Executable
swiftc:swift AST -> Raw Swift IL -> Canonical Swift IL -> LLVM IR
Raw Swift IL : Swift特有的中央代码
Canonical Swift IL:将Raw Swift IL举行降级简化成更加简便的中央代码版本
swift的编译器前端是swiftc,于Clang相比,LLVM的前端编译过程中,AST和IR之间,多了一层SIL(Swift Intermediate Language),这么做的目的是渴望增补clang编译器的一些缺陷,好比无法实验一些高级分析,可靠的诊断和优化,而 AST 和LLVM IR 都不是合适的选择。因此,SIL应运而生,用来办理现有的缺陷
AST(Abstract Syntax Tree  抽象语法树)

天生AST的过程
词法分析(lexical analysis
也叫扫描器,让源代码的字符流根据构词规范天生token流
tokenize:tokenize就是按照肯定的规则,比方token令牌(通常代表关键字,变量名,语法符号等),将代码分割为一个个的“串”,也就是语法单位)。涉及到词法分析的时间,常会用到tokennize。
语法分析(parse analysis)是编译过程的一个逻辑阶段。语法分析的使命是在词法分析的根本上将单词序列组合成语法树,如“步伐”,“语句”,“表达式”等等.语法分析步伐判定源步伐在结构上是否精确。源步伐的结构由上下文无关文法形貌。
Clang:

AST的转换例子
@property (nonatomic, strong) NSString *haoyuStringS:属性(Property)是Objective-C语言的此中一个特性,它把类对象中的实例变量及其读写方法同一的封装
天生的AST如下:
ObjCPropertyDecl 0x7f96f693a400 <line:13:1, col:41> col:41 haoyuString 'NSString *' readwrite nonatomic strong | |-ObjCMethodDecl 0x7f96f693a478 <col:41> col:41 implicit - haoyuString 'NSString *' | |-ObjCMethodDecl 0x7f96f693a4f8 <col:41> col:41 implicit - setHaoyuString: 'void' | | `-ParmVarDecl 0x7f96f693a578 <col:41> col:41 haoyuString 'NSString *'常见的数据范例声明在AST中表现
NSString *str = @"hahahah"; //oc中赋值代码AST中的表现为:
VarDecl 0x7fd06cc91ae8 <line:24:5, col:22> col:15 str 'NSString *__strong' cinit //声明局部变量 | | | `-ObjCStringLiteral 0x7fd06cc91ba8 <col:21, col:22> 'NSString *' //声明变量范例 | | |  `-StringLiteral 0x7fd06cc91b88 'char [8]' lvalue "hahahah" //右边的字符串有char范例表现String:StringLiteral
NSInteger ,Int:  IntegerLiteral
Float:  FloatingLiteral
Array: ObjCArrayLiteral
Dictionary : ObjCDictionaryLiteral
将源代码天生语法树 AST:
clang -fmodules -fsyntax-only -Xclang -ast-dump main.mSwiftc:

天生AST的方式和Clang类似,这里偏重先容下swiftc编译器的SIL(Swift Intermediate Language )
1.天生的main.swift文件中编写如下代码

import Foundationclass Teacher {    var age: Int = 18    var name: String = "Tom"}var person = Teacher()person.age = 6通过终端进入main.swift地点的文件夹,输入如下指令:
swiftc -emit-sil main.swift  //天生了main.sil文件// 打开`main.sil` 文件,起首看到了Teacher的声明class Teacher {  @_hasStorage @_hasInitialValue var age: Int { get set }  @_hasStorage @_hasInitialValue var name: String { get set }  @objc deinit  init()}@_hasStorage @_hasInitialValue var person: Teacher { get set }// personsil_global hidden @main.person : main.Teacher : $Teacher

  • @_hasStorage表现的是储存属性
  • @_hasInitialValue表现的是具有初始值
  • @sil_global表现的是全局变量
  • 一个析构方法deinit
  • 一个初始化函数init()
这里声明白Teacher类,并界说了一个全局的person属性,属于Teacher类
2.看下main.sil文件中的main 函数

每个步伐的开始都是main函数,swift语言也不例外,但是swift中的main函数被潜伏了,main.swift文件就代表了整个main函数,在文件里写的代码会在main中运行
// main函数,相当于c步伐入口函数int main(int argc, char * argv[])sil @main : $@convention(c) (Int32, UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>) -> Int32 {//%0,%1……在SIL也叫寄存器,这里我们可以明白为我们一样寻常开发的常量,//一旦赋值之后就不可以在修改,如果SIL中还要继承利用,那么就不停的累加数字bb0(%0 : $Int32, %1 : $UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>)://初始化全局变量person  alloc_global是创建一个全局变量  alloc_global @main.person : main.Teacher       // id: %2//创建对之前由alloc_global初始化的全局变量地点的引用//global_addr是拿到全局变量的地点,赋值给%3  %3 = global_addr @main.person : main.Teacher : $*Teacher // users: %7, %8//元范例Teacher//metatype是拿到Teacher的Metaldata赋值给%4  %4 = metatype $@thick Teacher.Type              // user: %6// 方法__allocating_init()的引用//接下来就是将__allocating_init()的函数地点赋值给%5  %5 = function_ref @main.Teacher.__allocating_init() -> main.Teacher : $@convention(method) (@thick Teacher.Type) -> @owned Teacher // user: %6//调用函数__allocating_init,并传入参数元范例Teacher//apply是调用函数,这里是调用%5也就是__allocating_init(),%4是参数,并将返回值给%6  %6 = apply %5(%4) : $@convention(method) (@thick Teacher.Type) -> @owned Teacher // user: %7//将函数__allocating_init的结果存入person的引用//然后将%6的值存储到%3,也就是我们刚刚创建的全局变量的地点  store %6 to %3 : $*Teacher                      // id: %7//开始访问全局变量地点的引用  %8 = begin_access [read] [dynamic] %3 : $*Teacher // users: %9, %11//将内容载入%9  %9 = load %8 : $*Teacher                        // users: %16, %14, %15, %10//引用计数加一  strong_retain %9 : $Teacher                     // id: %10//竣事访问  end_access %8 : $*Teacher                       // id: %11//创建字面量6  %12 = integer_literal $Builtin.Int64, 6         // user: %13//天生Int值6,swift中Int是结构体  %13 = struct $Int (%12 : $Builtin.Int64)        // user: %15//Teacher.age的setter方法  %14 = class_method %9 : $Teacher, #Teacher.age!setter : (Teacher) -> (Int) -> (), $@convention(method) (Int, @guaranteed Teacher) -> () // user: %15//调用setter方法,传入Int值6,和类实例自己  %15 = apply %14(%13, %9) : $@convention(method) (Int, @guaranteed Teacher) -> ()//引用计数减一  strong_release %9 ://创建字面量0  %17 = integer_literal $Builtin.Int32, 0         // user: %18//天生Int值0,swift中Int是结构体  %18 = struct $Int32 (%17 : $Builtin.Int32)      // user: %19//末了将0从main函数中返回出去  return %18 : $Int32                         // id: %16} // end sil function 'main'

  • @main 这里是标示我们当前main.swift的入口函数,SIL中的标示符以 @作为前缀
  • %0,%1……在SIL也叫寄存器,这里我们可以明白为我们一样寻常开发的常量,一旦赋值之后就不可以在修改,如果SIL中还要继承利用,那么就不停的累加数字
  • alloc_global是创建一个全局变量
  • global_addr是拿到全局变量的地点,赋值给%3
  • metatype是拿到Teacher的Metaldata赋值给%4
  • 接下来就是将__allocating_init()的函数地点赋值给%5
  • apply是调用函数,这里是调用%5也就是__allocating_init(),%4是参数,并将返回值给%6
  • 然后将%6的值存储到%3,也就是我们刚刚创建的全局变量的地点
  • 然后是构建Int并return
3. 这内里有些固定搭配

1.初始化一个引用
//初始化全局变量person  alloc_global @main.person : main.Teacher//创建对之前由alloc_global初始化的全局变量地点的引用  %3 = global_addr @main.person : main.Teacher 2.调用一个方法
// 方法__allocating_init()的引用  %5 = function_ref @main.Teacher.__allocating_init() -> main.Teacher : $@convention(method) (@thick Teacher.Type) -> @owned Teacher//调用函数__allocating_init,并传入参数元范例Teacher  %6 = apply %5(%4) : $@convention(method) (@thick Teacher.Type) -> @owned Teacher3.得到swfit的根本范例
//创建字面量6  %12 = integer_literal $Builtin.Int64, 6//天生Int值6,swift中Int是结构体  %13 = struct $Int (%12 : $Builtin.Int64)swiftc命令:

天生可实验文件:swiftc -o main.out main.swift天生抽象语法树的命令(AST):swiftc main.swift -dump-ast天生中央语言(SIL):swiftc main.swift -emit-silLLVM中央表现层(LLVM IR):swiftc main.swift -emit -ir天生汇编语言:swiftc main.swift -emit-assembly
您需要登录后才可以回帖 登录 | 立即注册

Powered by CangBaoKu v1.0 小黑屋藏宝库It社区( 冀ICP备14008649号 )

GMT+8, 2024-12-4 01:29, Processed in 0.174365 second(s), 36 queries.© 2003-2025 cbk Team.

快速回复 返回顶部 返回列表