sil文件分析

2023-11-23  本文已影响0人  孙健会员
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'
// 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'

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

image.png

对Teacher进行修改

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

从源码中分析swift_allocObject

image.png
image.png
image.png

该函数有三个参数:

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

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


image.png

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'
上一篇 下一篇

猜你喜欢

热点阅读