美文网首页
sil文件分析

sil文件分析

作者: 孙健会员 | 来源:发表于2023-11-23 11:53 被阅读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'
  • %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'

相关文章

  • 生成Swift中间代码的方法

    1、生成语法分析树: 2、生成SIL中间代码文件. 3、生成强制PASS之后的SIL代码,这经常是你想要看到的部分...

  • 逃逸闭包、非逃逸闭包

    在开始逃逸闭包与非逃逸闭包之前,先普及一个知识点,即如果编译成SIL文件: 编译成SIL文件: swift使用的编...

  • swift-获取sil、ast编译中间产物文件

    获取sil文件 从swift文件到可执行文件.o的整个编译过程。 swift编译过程参考[https://trin...

  • SIL认证中有哪些等级?

    SIL认证分为SIL1、SIL2、SIL3、SIL4,其中1级是最低的产品功能安全等级,4是最高的级别。多用于行业...

  • Swift类、对象、属性

    Swift编译简介 SIL介绍 SIL是Swift Intermediate Language的简写,SIL会对S...

  • 002-Swift进阶-编译简介、sil文件的分析

    一、swift编译简介 IOS开发的语言不管是OC还是swift,后端都是通过LLVM进行编译的,如下: 可以看到...

  • Swift - Enum枚举 源码分析

    先附上SIL代码 项目忙,附上个人根据源码的简单总结,日后更新详细分析....

  • 结构体和类的区别

    一、初始化方法不同 swift文件转sil文件命令 结构体成员有默认值时,编译器自动生成 init(age: In...

  • SIL程序员手册

    介绍 本文用来向开发者提供关于SIL实现的信息.关于SIL正式在官方声明可以查看SIL详解.本文为关于内部实行的指...

  • Swift-02:类、对象、属性

    本文主要介绍以下几点 通过SIL来理解对象的创建 Swift类结构分析 存储属性 & 计算属性 延迟存储属性 & ...

网友评论

      本文标题:sil文件分析

      本文链接:https://www.haomeiwen.com/subject/gvtgwdtx.html