sil文件分析

class Teacher {
    var age : Int = 3
    var name : String = "张三"
}
var t = Teacher()

swiftc -emit-sil main.swift | xcrun swift-demangle
如果编译有问题可以添加:
swiftc -emit-sil main.swift -target x86_64-apple-ios14.0-simulator -sdk $(xcrun --show-sdk-path --sdk iphonesimulator)| xcrun swift-demangle

class Teacher {
  @_hasStorage @_hasInitialValue var age: Int { get set }
  @_hasStorage @_hasInitialValue var name: String { get set }
  @objc deinit
  init()
}

%0 %1 : 寄存器
bb0 bb1 : 代码快
$String : SIL中的String 类型
$*String : SIL里的 String 类型的值地址
sil_global : 全局变量
apply : 调用函数,并传入函数
function_ref : 直接函数引用调用
class_method : 通过函数表来查找实现调用
sil_vtable : 类的函数表
thin : 静态的
thick : 动态的,运行时的
cond_br : 三目运算 判断寄存器上的值进行跳转
Builtin 将 LLVM IR 的类型和方法直接暴露给 Swift 标准库,使用时没有额外的运行时负担。

@_hasStorage @_hasInitialValue var t: Teacher { get set }

// t
sil_global hidden @$s4main1tAA7TeacherCvp : $Teacher

// main
sil @main : $@convention(c) (Int32, UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>) -> Int32 {
bb0(%0 : $Int32, %1 : $UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>):
  alloc_global @$s4main1tAA7TeacherCvp            // id: %2
  %3 = global_addr @$s4main1tAA7TeacherCvp : $*Teacher // user: %7 :拿到全局变量的地址给%3
  %4 = metatype $@thick Teacher.Type              // user: %6 :获取Teacher.Type的元类型给%4
  // function_ref Teacher.__allocating_init()
  %5 = function_ref @$s4main7TeacherCACycfC : $@convention(method) (@thick Teacher.Type) -> @owned Teacher // user: %6 :初始化函数地址引用
  %6 = apply %5(%4) : $@convention(method) (@thick Teacher.Type) -> @owned Teacher // user: %7
  store %6 to %3 : $*Teacher                      // id: %7
  %8 = integer_literal $Builtin.Int32, 0          // user: %9
  %9 = struct $Int32 (%8 : $Builtin.Int32)        // user: %10
  return %9 : $Int32                              // id: %10
} // end sil function 'main'
  • %0 -- %9 在sil中被称为寄存器(虚拟寄存器)
  • s4main1tAA7TeacherCvp : 是经过重整修改的(包含,项目名称、类名、方法名、参数名称、参数类型)可以通过 xcrun swift-demangle 还原


    image.png
// Teacher.__allocating_init()
sil hidden [exact_self_class] @$s4main7TeacherCACycfC : $@convention(method) (@thick Teacher.Type) -> @owned Teacher {
// %0 "$metatype"
bb0(%0 : $@thick Teacher.Type):
  %1 = alloc_ref $Teacher                         // user: %3
  // function_ref Teacher.init()
  %2 = function_ref @$s4main7TeacherCACycfc : $@convention(method) (@owned Teacher) -> @owned Teacher // user: %3
  %3 = apply %2(%1) : $@convention(method) (@owned Teacher) -> @owned Teacher // user: %4
  return %3 : $Teacher                            // id: %4
} // end sil function '$s4main7TeacherCACycfC'

让我们看一下函数调用的过程:

  • Teacher()


    image.png
image.png
  • __allocating_init()


    image.png
  • swift_allocObject


    image.png
  • swift_slowAlloc


    image.png

对Teacher进行修改

class Teacher : NSObject{
    var age : Int = 3
    var name : String = "张三"
}
var t = Teacher()
  • Teacher()


    image.png
  • __allocating_init()


    image.png

从源码中分析swift_allocObject

image.png

image.png

image.png

该函数有三个参数:

  • HdapMetadata const *metadata:元数据类型;
  • requiredSize:所需要的大小;
  • requiredAlignmentMask:对齐所需要的掩码,可以从objc的源码中得知,其为7,因为是8字节对齐;

将requiredSize和requiredAlignmentMask传递给函数swift_slowAlloc,该函数返回了一个HeapObject类型的指针; reinterpret_cast用来做指针类型的转换;

  • new (object) HeapObject(metadata):HeapObject初始化;

那么swift_slowAlloc是用来干什么的呢?


image.png
  • 如果alignMask<=15则直接使用malloc 在堆上申请内存,否则内存对其后(例如:alignMask = 17,对其后 alignMask = 32)然后分配内存。

swift类的初始化流程

  1. 首先会调用_allocating_init():该函数有编译器生成;
  2. 对于纯Swift类将会再调用swift_allocObject()函数;
  3. 然后在swift_allocObjec()总会调用私有函数_swift_allocObject;
  4. 然后通过函数swift_slowAlloc调用malloc来申请堆区的内存空间;

getter/setter方法

// Teacher.age.getter
sil hidden [transparent] @$s4main7TeacherC3ageSivg : $@convention(method) (@guaranteed Teacher) -> Int {
// %0 "self"                                      // users: %2, %1
bb0(%0 : $Teacher):
  debug_value %0 : $Teacher, let, name "self", argno 1, implicit // id: %1
  %2 = ref_element_addr %0 : $Teacher, #Teacher.age // user: %3
  %3 = begin_access [read] [dynamic] %2 : $*Int   // users: %4, %5
  %4 = load %3 : $*Int                            // user: %6
  end_access %3 : $*Int                           // id: %5
  return %4 : $Int                                // id: %6
} // end sil function '$s4main7TeacherC3ageSivg'

// Teacher.age.setter
sil hidden [transparent] @$s4main7TeacherC3ageSivs : $@convention(method) (Int, @guaranteed Teacher) -> () {
// %0 "value"                                     // users: %6, %2
// %1 "self"                                      // users: %4, %3
bb0(%0 : $Int, %1 : $Teacher):
  debug_value %0 : $Int, let, name "value", argno 1, implicit // id: %2
  debug_value %1 : $Teacher, let, name "self", argno 2, implicit // id: %3
  %4 = ref_element_addr %1 : $Teacher, #Teacher.age // user: %5
  %5 = begin_access [modify] [dynamic] %4 : $*Int // users: %6, %7
  store %0 to %5 : $*Int                          // id: %6
  end_access %5 : $*Int                           // id: %7
  %8 = tuple ()                                   // user: %9
  return %8 : $()                                 // id: %9
} // end sil function '$s4main7TeacherC3ageSivs'

// Teacher.name.getter
sil hidden [transparent] @$s4main7TeacherC4nameSSvg : $@convention(method) (@guaranteed Teacher) -> @owned String {
// %0 "self"                                      // users: %2, %1
bb0(%0 : $Teacher):
  debug_value %0 : $Teacher, let, name "self", argno 1, implicit // id: %1
  %2 = ref_element_addr %0 : $Teacher, #Teacher.name // user: %3
  %3 = begin_access [read] [dynamic] %2 : $*String // users: %4, %6
  %4 = load %3 : $*String                         // users: %7, %5
  retain_value %4 : $String                       // id: %5
  end_access %3 : $*String                        // id: %6
  return %4 : $String                             // id: %7
} // end sil function '$s4main7TeacherC4nameSSvg'

// Teacher.name.setter
sil hidden [transparent] @$s4main7TeacherC4nameSSvs : $@convention(method) (@owned String, @guaranteed Teacher) -> () {
// %0 "value"                                     // users: %11, %8, %4, %2
// %1 "self"                                      // users: %5, %3
bb0(%0 : $String, %1 : $Teacher):
  debug_value %0 : $String, let, name "value", argno 1, implicit // id: %2
  debug_value %1 : $Teacher, let, name "self", argno 2, implicit // id: %3
  retain_value %0 : $String                       // id: %4
  %5 = ref_element_addr %1 : $Teacher, #Teacher.name // user: %6
  %6 = begin_access [modify] [dynamic] %5 : $*String // users: %8, %7, %10
  %7 = load %6 : $*String                         // user: %9
  store %0 to %6 : $*String                       // id: %8
  release_value %7 : $String                      // id: %9
  end_access %6 : $*String                        // id: %10
  release_value %0 : $String                      // id: %11
  %12 = tuple ()                                  // user: %13
  return %12 : $()                                // id: %13
} // end sil function '$s4main7TeacherC4nameSSvs'
  • 析构方法
// Teacher.deinit
sil hidden @$s4main7TeacherCfd : $@convention(method) (@guaranteed Teacher) -> @owned Builtin.NativeObject {
// %0 "self"                                      // users: %6, %2, %1
bb0(%0 : $Teacher):
  debug_value %0 : $Teacher, let, name "self", argno 1, implicit // id: %1
  %2 = ref_element_addr %0 : $Teacher, #Teacher.name // user: %3
  %3 = begin_access [deinit] [static] %2 : $*String // users: %5, %4
  destroy_addr %3 : $*String                      // id: %4
  end_access %3 : $*String                        // id: %5
  %6 = unchecked_ref_cast %0 : $Teacher to $Builtin.NativeObject // user: %7
  return %6 : $Builtin.NativeObject               // id: %7
} // end sil function '$s4main7TeacherCfd'

// Teacher.__deallocating_deinit
sil hidden @$s4main7TeacherCfD : $@convention(method) (@owned Teacher) -> () {
// %0 "self"                                      // users: %3, %1
bb0(%0 : $Teacher):
  debug_value %0 : $Teacher, let, name "self", argno 1, implicit // id: %1
  // function_ref Teacher.deinit
  %2 = function_ref @$s4main7TeacherCfd : $@convention(method) (@guaranteed Teacher) -> @owned Builtin.NativeObject // user: %3
  %3 = apply %2(%0) : $@convention(method) (@guaranteed Teacher) -> @owned Builtin.NativeObject // user: %4
  %4 = unchecked_ref_cast %3 : $Builtin.NativeObject to $Teacher // user: %5
  dealloc_ref %4 : $Teacher                       // id: %5
  %6 = tuple ()                                   // user: %7
  return %6 : $()                                 // id: %7
} // end sil function '$s4main7TeacherCfD'
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,080评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,422评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,630评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,554评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,662评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,856评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,014评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,752评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,212评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,541评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,687评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,347评论 4 331
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,973评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,777评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,006评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,406评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,576评论 2 349

推荐阅读更多精彩内容