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 : 調(diào)用函數(shù)跺撼,并傳入函數(shù)
function_ref : 直接函數(shù)引用調(diào)用
class_method : 通過函數(shù)表來查找實(shí)現(xiàn)調(diào)用
sil_vtable : 類的函數(shù)表
thin : 靜態(tài)的
thick : 動(dòng)態(tài)的,運(yùn)行時(shí)的
cond_br : 三目運(yùn)算 判斷寄存器上的值進(jìn)行跳轉(zhuǎn)
Builtin 將 LLVM IR 的類型和方法直接暴露給 Swift 標(biāo)準(zhǔn)庫扒怖,使用時(shí)沒有額外的運(yùn)行時(shí)負(fù)擔(dān)。

@_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 :初始化函數(shù)地址引用
  %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 : 是經(jīng)過重整修改的(包含碱璃,項(xiàng)目名稱菩鲜、類名淋样、方法名、參數(shù)名稱唆垃、參數(shù)類型)可以通過 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'

讓我們看一下函數(shù)調(diào)用的過程:

  • Teacher()


    image.png
image.png
  • __allocating_init()


    image.png
  • swift_allocObject


    image.png
  • swift_slowAlloc


    image.png

對(duì)Teacher進(jìn)行修改

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

該函數(shù)有三個(gè)參數(shù):

  • HdapMetadata const *metadata:元數(shù)據(jù)類型五芝;
  • requiredSize:所需要的大小辕万;
  • requiredAlignmentMask:對(duì)齊所需要的掩碼与柑,可以從objc的源碼中得知谤辜,其為7,因?yàn)槭?字節(jié)對(duì)齊价捧;

將requiredSize和requiredAlignmentMask傳遞給函數(shù)swift_slowAlloc丑念,該函數(shù)返回了一個(gè)HeapObject類型的指針; reinterpret_cast用來做指針類型的轉(zhuǎn)換结蟋;

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

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


image.png
  • 如果alignMask<=15則直接使用malloc 在堆上申請(qǐng)內(nèi)存嵌屎,否則內(nèi)存對(duì)其后(例如:alignMask = 17推正,對(duì)其后 alignMask = 32)然后分配內(nèi)存。

swift類的初始化流程

  1. 首先會(huì)調(diào)用_allocating_init():該函數(shù)有編譯器生成宝惰;
  2. 對(duì)于純Swift類將會(huì)再調(diào)用swift_allocObject()函數(shù)植榕;
  3. 然后在swift_allocObjec()總會(huì)調(diào)用私有函數(shù)_swift_allocObject;
  4. 然后通過函數(shù)swift_slowAlloc調(diào)用malloc來申請(qǐng)堆區(qū)的內(nèi)存空間尼夺;

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'
  • 析構(gòu)方法
// 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'
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末尊残,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子淤堵,更是在濱河造成了極大的恐慌寝衫,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,490評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件拐邪,死亡現(xiàn)場(chǎng)離奇詭異慰毅,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)扎阶,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,581評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門汹胃,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人东臀,你說我怎么就攤上這事着饥。” “怎么了啡邑?”我有些...
    開封第一講書人閱讀 165,830評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵贱勃,是天一觀的道長井赌。 經(jīng)常有香客問我谤逼,道長,這世上最難降的妖魔是什么仇穗? 我笑而不...
    開封第一講書人閱讀 58,957評(píng)論 1 295
  • 正文 為了忘掉前任流部,我火速辦了婚禮,結(jié)果婚禮上纹坐,老公的妹妹穿的比我還像新娘枝冀。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,974評(píng)論 6 393
  • 文/花漫 我一把揭開白布果漾。 她就那樣靜靜地躺著球切,像睡著了一般。 火紅的嫁衣襯著肌膚如雪绒障。 梳的紋絲不亂的頭發(fā)上吨凑,一...
    開封第一講書人閱讀 51,754評(píng)論 1 307
  • 那天,我揣著相機(jī)與錄音户辱,去河邊找鬼鸵钝。 笑死,一個(gè)胖子當(dāng)著我的面吹牛庐镐,可吹牛的內(nèi)容都是我干的恩商。 我是一名探鬼主播,決...
    沈念sama閱讀 40,464評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼必逆,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼怠堪!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起末患,我...
    開封第一講書人閱讀 39,357評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤研叫,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后璧针,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體嚷炉,經(jīng)...
    沈念sama閱讀 45,847評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,995評(píng)論 3 338
  • 正文 我和宋清朗相戀三年探橱,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了申屹。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,137評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡隧膏,死狀恐怖哗讥,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情胞枕,我是刑警寧澤杆煞,帶...
    沈念sama閱讀 35,819評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站腐泻,受9級(jí)特大地震影響决乎,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜派桩,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,482評(píng)論 3 331
  • 文/蒙蒙 一构诚、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧铆惑,春花似錦范嘱、人聲如沸送膳。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,023評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽叠聋。三九已至,卻和暖如春受裹,著一層夾襖步出監(jiān)牢的瞬間晒奕,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,149評(píng)論 1 272
  • 我被黑心中介騙來泰國打工名斟, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留脑慧,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,409評(píng)論 3 373
  • 正文 我出身青樓砰盐,卻偏偏與公主長得像闷袒,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子岩梳,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,086評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容