Swift編譯之SIL(Swift Intermediate Language)

編譯過(guò)程

Swift編譯過(guò)程.jpeg
  • Parse:從.swift構(gòu)造 AST(抽象語(yǔ)法樹(shù))。
  • Sema:對(duì) AST 進(jìn)行語(yǔ)義分析晰房,生成格式正確且類(lèi)型檢查完備的 AST殊者。
  • SILGen:從 AST 生成 raw SIL验夯。
  • IRGen:從 canonical SIL 生成 IR簿姨。
  • LLVM:LLVM Backend 從優(yōu)化后的 IR 生成匯編代碼或者目標(biāo)代碼扁位。

SIL生成

// 將main.swift編譯成SIL
swiftc -emit-sil main.swift > main.sil
// 將main.swift編譯成SIL的同時(shí)還原毫無(wú)規(guī)則的命名
swiftc -emit-sil main.swift | xcrun swift-demangle > main.sil
// UIKit+x86_64
swiftc -emit-sil -target x86_64-apple-ios17.0.1-simulator -sdk $(xcrun --show-sdk-path --sdk iphonesimulator) ViewController.swift | xcrun swift-demangle > ViewController.sil
// UIKit+arm64
swiftc -emit-sil -target arm64-apple-ios17.0.1-simulator -sdk $(xcrun --show-sdk-path --sdk iphonesimulator) ViewController.swift | xcrun swift-demangle > ViewController.sil
// SwiftUI
swiftc -emit-sil ContentView.swift | xcrun swift-demangle > ContentView.sil

SIL常見(jiàn)語(yǔ)法

  • hidden:同一個(gè) Swift 模塊中的對(duì)象可見(jiàn)域仇。
  • load A:從 A 中讀取數(shù)據(jù)寺擂。
  • store A to B:將 A 中的值存儲(chǔ)到 B 中。
  • sil_global:全局變量择镇。
  • alloc_global:開(kāi)辟全局變量的內(nèi)存腻豌。
  • global_addr:獲取全局變量的地址嘱能。
  • alloc_stack/dealloc_stack:開(kāi)辟/銷(xiāo)毀棧區(qū)內(nèi)存空間惹骂。
  • alloc_box/dealloc_box:開(kāi)辟/釋放堆區(qū)內(nèi)存空間对粪。
  • bb0/bb1 ...:標(biāo)記代碼塊衩侥。
  • alloc_ref/dealloc_ref:開(kāi)辟/釋放內(nèi)存。
  • function_ref:獲取直接派發(fā)方法引用地址跪但。
  • class_method:通過(guò)方法表獲取方法引用地址屡久。
  • witness_method:通過(guò) Protocol Witness Table(PWT) 獲取對(duì)應(yīng)的方法引用地址被环。
  • objc_method:獲取 Objective-C 方法引用地址筛欢。
  • apply:調(diào)用方法版姑。
  • return:返回值迟郎。
  • retain_value/release_value:引用計(jì)數(shù) +1/引用計(jì)數(shù) -1宪肖。
  • metatype:獲取元類(lèi)型。
  • begin_access/end_access:開(kāi)始/結(jié)束訪(fǎng)問(wèn)目標(biāo)內(nèi)存娜遵。
  • switch_enum:switch 枚舉魔熏,一般進(jìn)行判空操作蒜绽。
  • pointer_to_address:將原始指針轉(zhuǎn)換為地址躲雅。
  • br lable:將控制權(quán)從當(dāng)前塊轉(zhuǎn)移到其他塊相赁,并將進(jìn)行傳值慰于。
  • $:類(lèi)型標(biāo)識(shí)婆赠。
  • %number:寄存器休里。
  • @方法名:某個(gè)方法的名字妙黍。
  • @_hasStorage:存儲(chǔ)屬性拭嫁。
  • @_hasInitialValue:屬性有初始值做粤。
  • @owned:方法接收者負(fù)責(zé)銷(xiāo)毀返回值。
  • @convention(method):Swift 方法的引用逮刨。
  • @convention(thin):Swift 方法的引用修己,但沒(méi)有特殊的self或者context參數(shù)睬愤。
  • @convention(thick):Swift 方法的引用尤辱,擁有引用計(jì)數(shù)的上下文對(duì)象光督。
  • @convention(c):C 方法的引用结借。
  • @convention(objc_method):Objective-C 方法的引用船老。
  • @convention(block):Objective-C 塊的引用柳畔。
  • @convention(witness_method):協(xié)議方法的引用薪韩。

案例

  • 源代碼捌锭。
import Foundation

protocol SomeProtocol {
    func doSomething()
}

@objc class Person: NSObject, SomeProtocol {
    var name = "zhangsan"

    @objc dynamic func say() {
    }

    func doSomething() {
    }
}

extension Person {
    func drink() {
    }
}
  • SIL岭洲。
// 表示最終的坎匿、經(jīng)過(guò)規(guī)范化的SIL代碼
sil_stage canonical

// 內(nèi)建模塊替蔬,提供了一些底層的內(nèi)建函數(shù)和類(lèi)型承桥,這些函數(shù)和類(lèi)型通常用于Swift編譯器生成的代碼中,執(zhí)行一些特定的低級(jí)操作
import Builtin
// Swift標(biāo)準(zhǔn)庫(kù)的模塊挤巡,提供了Swift語(yǔ)言的核心功能矿卑,包括標(biāo)準(zhǔn)類(lèi)型母廷、集合琴昆、字符串處理等
import Swift
// Swift語(yǔ)言的橋接模塊椎咧,用于處理Swift與其他語(yǔ)言的交互勤讽,例如Objective-C
import SwiftShims

import Foundation

protocol SomeProtocol {
    func doSomething()
}

// 使用@_inheritsConvenienceInitializers注解脚牍,繼承方便的初始化器
// 使用@objc標(biāo)記诸狭,將類(lèi)導(dǎo)出到Objective-C
@_inheritsConvenienceInitializers @objc class Person: NSObject, SomeProtocol {
    // 使用@_hasStorage標(biāo)記驯遇,表示這個(gè)屬性有存儲(chǔ)
    // 使用@_hasInitialValue標(biāo)記叉庐,表示這個(gè)屬性有初始值
    @_hasStorage @_hasInitialValue var name: String { get set }
    // 使用@objc dynamic標(biāo)記陡叠,將方法導(dǎo)出到Objective-C枉阵,并啟用動(dòng)態(tài)派發(fā)
    @objc dynamic func say()
    // 沒(méi)有@objc標(biāo)記的普通方法
    func doSomething()
    // 使用override dynamic標(biāo)記兴溜,覆蓋父類(lèi)的初始化器并啟用動(dòng)態(tài)派發(fā)
    override dynamic init()
    // 使用@objc標(biāo)記的析構(gòu)器拙徽,將析構(gòu)器導(dǎo)出到Objective-C
    @objc deinit
}

extension Person {
    func drink()
}

// 使用sil指令定義一個(gè)名為main的函數(shù)斋攀,程序的入口點(diǎn)
// main
sil @main: $@convention(c) (Int32, UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>) -> Int32 {
    // 定義基本塊bb0淳蔼,它接受兩個(gè)參數(shù)鹉梨,一個(gè)是Int32存皂,另一個(gè)是UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>
    bb0(%0: $Int32, %1: $UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>):
        // 使用integer_literal指令創(chuàng)建一個(gè)Int32類(lèi)型的字面量0
        %2 = integer_literal $Builtin.Int32, 0 // user: %3旦袋,user表示這個(gè)操作數(shù)標(biāo)記了在用戶(hù)級(jí)別上使用了該值疤孕,表示該值在程序的實(shí)際執(zhí)行中被使用了
        // 使用struct指令將上面創(chuàng)建的Int32字面量包裝成Int32結(jié)構(gòu)體
        %3 = struct $Int32(%2: $Builtin.Int32) // user: %4
        // 返回創(chuàng)建的Int32結(jié)構(gòu)體祭阀,結(jié)束main函數(shù)
        return %3: $Int32 // id: %4专控,id表示用于在程序的其他部分引用該值
} // end sil function 'main'

// 使用sil hidden [transparent]指令定義一個(gè)隱藏的伦腐、透明的函數(shù)蔗牡,表示初始化Person類(lèi)的name屬性的表達(dá)式
// sil hidden:表示這個(gè)表達(dá)式是隱藏的辩越,即不對(duì)外部可見(jiàn)
// [transparent]:表示這個(gè)表達(dá)式是透明的黔攒,即不包含額外的控制流或操作
// @variable initialization expression:表示這是一個(gè)變量初始化表達(dá)式
// of main.Person.name:指明這個(gè)表達(dá)式是為Person類(lèi)的name屬性進(jìn)行初始化
// : Swift.String:指定初始化的目標(biāo)類(lèi)型是Swift.String
// : $@convention(thin) () -> @owned String:指定了函數(shù)的調(diào)用約定督惰,這個(gè)表達(dá)式的類(lèi)型是一個(gè)函數(shù)類(lèi)型赏胚,該函數(shù)不接受參數(shù) (())觉阅,返回一個(gè)擁有所有權(quán)的String
// variable initialization expression of Person.name
sil hidden[transparent] @variable initialization expression of main.Person.name: Swift.String: $@convention(thin) () -> @owned String {
    bb0:
        // 使用string_literal指令創(chuàng)建一個(gè)UTF-8字符串字面量"zhangsan"
        %0 = string_literal utf8 "zhangsan" // user: %5
        // 使用integer_literal指令創(chuàng)建一個(gè)Word類(lèi)型的字面量8劫哼,表示UTF-8編碼單元的數(shù)量
        %1 = integer_literal $Builtin.Word, 8 // user: %5
        // 使用integer_literal指令創(chuàng)建一個(gè)Int1類(lèi)型的字面量-1权烧,表示字符串是否為ASCII編碼
        %2 = integer_literal $Builtin.Int1, -1 // user: %5
        // 使用metatype指令獲取String類(lèi)型的元類(lèi)型
        %3 = metatype $@thin String.Type // user: %5
        // 使用function_ref指令引用String.init(_builtinStringLiteral:utf8CodeUnitCount:isASCII:)構(gòu)造函數(shù)
        // 這個(gè)構(gòu)造函數(shù)接受一個(gè)指向UTF-8字符串的原始指針般码、UTF-8編碼單元的數(shù)量侈询、以及一個(gè)表示是否為ASCII的標(biāo)志
        // function_ref String.init(_builtinStringLiteral:utf8CodeUnitCount:isASCII:)
        %4 = function_ref @Swift.String(_builtinStringLiteral: Builtin.RawPointer, utf8CodeUnitCount: Builtin.Word, isASCII: Builtin.Int1) -> Swift.String: $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String // user: %5
        // 使用apply指令調(diào)用上述構(gòu)造函數(shù)
        %5 = apply %4(%0, %1, %2, %3): $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String // user: %6
        // 返回構(gòu)造函數(shù)的結(jié)果,即初始化的字符串
        return %5: $String // id: %6
} // end sil function 'variable initialization expression of main.Person.name : Swift.String'

// String類(lèi)的構(gòu)造函數(shù)init(_builtinStringLiteral:utf8CodeUnitCount:isASCII:)的定義
// sil[always_inline][readonly][_semantics "string.makeUTF8"] :這是關(guān)于方法行為和優(yōu)化的一些指令
// [always_inline]:提示編譯器盡可能內(nèi)聯(lián)這個(gè)方法革为,以提高性能
// [readonly]:表明該方法是只讀的震檩,不對(duì)傳入的參數(shù)進(jìn)行修改
// [_semantics "string.makeUTF8"]:指定了該方法的語(yǔ)義抛虏,這對(duì)編譯器進(jìn)行進(jìn)一步的優(yōu)化和特殊處理
// @Swift.String.init(_builtinStringLiteral: Builtin.RawPointer, utf8CodeUnitCount: Builtin.Word, isASCII: Builtin.Int1) -> Swift.String:指定了這個(gè)方法的Swift類(lèi)型簽名
// String.init(_builtinStringLiteral:utf8CodeUnitCount:isASCII:)
sil[always_inline][readonly][_semantics "string.makeUTF8"] @Swift.String(_builtinStringLiteral: Builtin.RawPointer, utf8CodeUnitCount: Builtin.Word, isASCII: Builtin.Int1) -> Swift.String: $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String

// 使用sil hidden指令定義Person類(lèi)的name屬性的getter方法
// Person.name.getter
sil hidden @main.Person.name.getter: Swift.String: $@convention(method) (@guaranteed Person) -> @owned String {
    // 基本塊bb0,接受一個(gè)Person實(shí)例作為參數(shù)
    // %0 "self"                                      // users: %2, %1
    bb0(%0: $Person):
        // 在調(diào)試中沸毁,為參數(shù)"self"創(chuàng)建一個(gè)調(diào)試值
        debug_value %0: $Person, let, name "self", argno 1, implicit // id: %1
        // 使用ref_element_addr指令獲取Person實(shí)例的name屬性的地址
        %2 = ref_element_addr %0: $Person, #Person.name // user: %3
        // 使用begin_access指令開(kāi)始對(duì)name屬性的讀取訪(fǎng)問(wèn)息尺,dynamic表示動(dòng)態(tài)訪(fǎng)問(wèn)
        %3 = begin_access[read][dynamic] %2: $ * String // users: %4, %6
        // 使用load指令加載name屬性的值
        %4 = load %3: $ * String // users: %7, %5
        // 使用retain_value指令保留加載的字符串值
        retain_value %4: $String // id: %5
        // 使用end_access指令結(jié)束對(duì)name屬性的讀取訪(fǎng)問(wèn)
        end_access %3: $ * String // id: %6
        // 返回加載并保留的字符串值
        return %4: $String // id: %7
} // end sil function 'main.Person.name.getter : Swift.String'

// 使用sil hidden指令定義Person類(lèi)的name屬性的setter方法徐紧,接受一個(gè)String實(shí)例和一個(gè)Person實(shí)例
// Person.name.setter
sil hidden @main.Person.name.setter: Swift.String: $@convention(method) (@owned String, @guaranteed Person) -> Void {
    // 定義基本塊bb0并级,它接受兩個(gè)參數(shù)死遭,一個(gè)是String實(shí)例,另一個(gè)是Person實(shí)例
    // %0 "value"                                     // users: %11, %8, %4, %2
    // %1 "self"                                      // users: %5, %3
    bb0(%0: $String, %1: $Person):
        // 調(diào)試信息至非,標(biāo)記參數(shù)%0為"value"荒椭,參數(shù)%1為"self"
        debug_value %0: $String, let, name "value", argno 1, implicit // id: %2
        debug_value %1: $Person, let, name "self", argno 2, implicit // id: %3
        // 保留String實(shí)例趣惠,增加其引用計(jì)數(shù)
        retain_value %0: $String // id: %4
        // 獲取Person實(shí)例的name屬性地址
        %5 = ref_element_addr %1: $Person, #Person.name // user: %6
        // 開(kāi)始訪(fǎng)問(wèn)name屬性味悄,以便進(jìn)行修改
        %6 = begin_access[modify][dynamic] %5: $ * String // users: %8, %7, %10
        // 加載原始的String實(shí)例
        %7 = load %6: $ * String // user: %9
        // 將新的String實(shí)例存儲(chǔ)到name屬性地址
        store %0 to %6: $ * String // id: %8
        // 釋放原始的String實(shí)例
        release_value %7: $String // id: %9
        // 結(jié)束對(duì)name屬性的訪(fǎng)問(wèn)
        end_access %6: $ * String // id: %10
        // 釋放String實(shí)例,減少其引用計(jì)數(shù)
        release_value %0: $String // id: %11
        // 創(chuàng)建一個(gè)空元組作為返回值
        %12 = tuple() // user: %13
        // 返回空元組
        return %12: $() // id: %13
} // end sil function 'main.Person.name.setter : Swift.String'

// 使用sil hidden指令定義Person類(lèi)的name屬性的modify方法
// sil hidden:表示這個(gè)modify方法是隱藏的涨颜,即不對(duì)外部可見(jiàn)
// @main.Person.name.modify:指明這個(gè)modify方法是Person類(lèi)的name屬性的modify方法
// : Swift.String:指定modify方法的返回類(lèi)型是Swift.String庭瑰,這表示modify方法返回屬性的當(dāng)前值
// : $@yield_once:指定了modify方法的調(diào)用約定见擦,其中@yield_once表示該方法會(huì)產(chǎn)生一次yield modify 方法通常用于實(shí)現(xiàn)屬性的寫(xiě)時(shí)拷貝鲤屡,在獲取屬性時(shí)會(huì)執(zhí)行一些操作酒来,并在修改時(shí)生成一個(gè)拷貝
// @convention(method) (@guaranteed Person) -> @yields @inout String:指定modify方法的簽名堰汉,該方法接受一個(gè)Person實(shí)例作為參數(shù)滴铅,返回一個(gè) String汉匙,并且產(chǎn)生一個(gè)@yield的值噩翠,表示寫(xiě)時(shí)拷貝的結(jié)果 方法使用@inout String表示這是一個(gè)寫(xiě)入操作伤锚,需要返回一個(gè)寫(xiě)入后的值
// Person.name.modify
sil hidden @main.Person.name.modify: Swift.String: $@yield_once @convention(method) (@guaranteed Person) -> @yields @inout String {
    // 定義基本塊bb0屯援,它接受一個(gè)Person實(shí)例作為參數(shù)
    // %0 "self"                                      // users: %2, %1
    bb0(%0: $Person):
        // 調(diào)試信息狞洋,標(biāo)記參數(shù)%0為"self"
        debug_value %0: $Person, let, name "self", argno 1, implicit // id: %1
        // 獲取Person實(shí)例的name屬性地址
        %2 = ref_element_addr %0: $Person, #Person.name // user: %3
        // 開(kāi)始訪(fǎng)問(wèn)name屬性,以便進(jìn)行inout修改
        %3 = begin_access[modify][dynamic] %2: $ * String // users: %5, %8, %4
        // 使用yield指令將對(duì)name屬性的inout訪(fǎng)問(wèn)暫停惕它,并傳遞name屬性的地址
        yield %3: $ * String, resume bb1, unwind bb2 // id: %4

    bb1: // Preds: bb0
        // 結(jié)束對(duì)name屬性的訪(fǎng)問(wèn)
        end_access %3: $ * String // id: %5
        // 創(chuàng)建一個(gè)空元組作為返回值
        %6 = tuple() // user: %7
        return %6: $() // id: %7

    bb2: // Preds: bb0
        // 在異常情況下淹魄,結(jié)束對(duì)name屬性的訪(fǎng)問(wèn)并執(zhí)行unwind
        end_access %3: $ * String // id: %8
        unwind // id: %9
} // end sil function 'main.Person.name.modify : Swift.String'

// 使用sil hidden指令定義Person類(lèi)的say()方法
// Person.say()
sil hidden @main.Person.say() -> Void: $@convention(method) (@guaranteed Person) -> Void {
    // 定義基本塊bb0兆蕉,它接受一個(gè)Person實(shí)例作為參數(shù)
    // %0 "self"                                      // user: %1
    bb0(%0: $Person):
        // 調(diào)試信息虎韵,標(biāo)記參數(shù)%0為"self"
        debug_value %0: $Person, let, name "self", argno 1, implicit // id: %1
        // 創(chuàng)建一個(gè)空元組作為返回值
        %2 = tuple() // user: %3
        // 返回空元組
        return %2: $() // id: %3
} // end sil function 'main.Person.say() -> ()'

// 使用sil private [thunk]指令定義Objective-C中的thunk實(shí)現(xiàn),將@objc修飾的Person.say()映射到Swift中的main.Person.say()方法
// @objc Person.say()
sil private [thunk] @@objc main.Person.say() -> Void: $@convention(objc_method) (Person) -> Void {
    // 定義基本塊bb0缸废,它接受一個(gè)Person實(shí)例作為參數(shù)
    // %0                                             // users: %4, %3, %1
    bb0(%0: $Person):
        // 強(qiáng)引用計(jì)數(shù)+1包蓝,保留Person實(shí)例
        strong_retain %0: $Person // id: %1
        // 引用Swift中的Person.say()方法
        // function_ref Person.say()
        %2 = function_ref @main.Person.say() -> Void: $@convention(method) (@guaranteed Person) -> Void // user: %3
        // 調(diào)用Swift中的Person.say()方法
        %3 = apply %2(%0): $@convention(method) (@guaranteed Person) -> Void // user: %5
        // 強(qiáng)引用計(jì)數(shù)-1,釋放Person實(shí)例
        strong_release %0: $Person // id: %4
        // 返回Swift方法的結(jié)果
        return %3: $() // id: %5
} // end sil function '@objc main.Person.say() -> ()'

// 使用sil hidden指令定義Person類(lèi)的doSomething()方法
// Person.doSomething()
sil hidden @main.Person.doSomething() -> Void: $@convention(method) (@guaranteed Person) -> Void {
    // 定義基本塊bb0企量,它接受一個(gè)Person實(shí)例作為參數(shù)
    // %0 "self"                                      // user: %1
    bb0(%0: $Person):
        // 調(diào)試信息测萎,標(biāo)記參數(shù)%0為"self"
        debug_value %0: $Person, let, name "self", argno 1, implicit // id: %1
        // 創(chuàng)建一個(gè)空元組作為返回值
        %2 = tuple() // user: %3
        // 返回空元組
        return %2: $() // id: %3
} // end sil function 'main.Person.doSomething() -> ()'

// 使用sil hidden指令定義Person類(lèi)的__allocating_init()方法,是一個(gè)指定初始化器
// (@thick Person.Type):表示這個(gè)方法接受一個(gè)Person類(lèi)型的元類(lèi)型參數(shù)硅瞧,即類(lèi)本身的類(lèi)型
// -> @owned Person:表示這個(gè)方法返回一個(gè)擁有所有權(quán)的Person實(shí)例
// Person.__allocating_init()
sil hidden @main.Person.__allocating_init() -> main.Person: $@convention(method) (@thick Person.Type) -> @owned Person {
    // 定義基本塊bb0,它接受一個(gè)Person類(lèi)型的元類(lèi)型作為參數(shù)
    // %0 "$metatype"                                 // user: %1
    bb0(%0: $@thick Person.Type):
        // 將thick元類(lèi)型轉(zhuǎn)換為對(duì)應(yīng)的Objective-C元類(lèi)型
        %1 = thick_to_objc_metatype %0: $@thick Person.Type to $@objc_metatype Person.Type // user: %2
        // 使用alloc_ref_dynamic指令分配Person實(shí)例
        %2 = alloc_ref_dynamic[objc] %1: $@objc_metatype Person.Type, $Person // users: %3, %4
        // 使用objc_method指令調(diào)用Objective-C中的初始化器init
        %3 = objc_method %2: $Person, #Person.init!initializer.foreign: (Person.Type) -> () -> Person, $@convention(objc_method) (@owned Person) -> @owned Person // user: %4
        // 調(diào)用init初始化器
        %4 = apply %3(%2): $@convention(objc_method) (@owned Person) -> @owned Person // user: %5
        // 返回初始化后的Person實(shí)例
        return %4: $Person // id: %5
} // end sil function 'main.Person.__allocating_init() -> main.Person'

// 使用sil shared [transparent] [thunk]指令定義動(dòng)態(tài)初始化器的thunk實(shí)現(xiàn)
// sil shared:表示這個(gè)初始化方法是共享的恕汇,即可能被其他模塊訪(fǎng)問(wèn)
// [transparent]:表示這個(gè)初始化方法是透明的腕唧,即沒(méi)有額外的控制流或操作
// [thunk]:表示這是一個(gè)動(dòng)態(tài)分發(fā)的方法,可能涉及到動(dòng)態(tài)派發(fā)
// @dynamic main.Person.init():指明這個(gè)方法是Person類(lèi)的初始化方法
// -> main.Person:表示這個(gè)初始化方法的返回類(lèi)型是Person類(lèi)的實(shí)例
// dynamic Person.init()
sil shared[transparent][thunk] @dynamic main.Person() -> main.Person: $@convention(method) (@owned Person) -> @owned Person {
    // 定義基本塊bb0拇勃,它接受一個(gè)Person實(shí)例作為參數(shù)
    // %0 "self"                                      // users: %2, %1
    bb0(%0: $Person):
        // 使用objc_method指令調(diào)用Objective-C中的初始化器init
        %1 = objc_method %0: $Person, #Person.init!initializer.foreign: (Person.Type) -> () -> Person, $@convention(objc_method) (@owned Person) -> @owned Person // user: %2
        // 調(diào)用init初始化器
        %2 = apply %1(%0): $@convention(objc_method) (@owned Person) -> @owned Person // user: %3
        // 返回初始化后的Person實(shí)例
        return %2: $Person // id: %3
} // end sil function 'dynamic main.Person.init() -> main.Person'

// 使用sil hidden指令定義Person類(lèi)的init()方法
// Person.init()
sil hidden @main.Person() -> main.Person: $@convention(method) (@owned Person) -> @owned Person {
    // 定義基本塊bb0四苇,它接受一個(gè)Person實(shí)例作為參數(shù)
    // %0 "self"                                      // users: %12, %4, %3, %2
    bb0(%0: $Person):
        // 分配一個(gè)Person實(shí)例的椥⒘瑁空間
        %1 = alloc_stack[lexical] $Person, let, name "self", implicit // users: %20, %13, %3, %21, %22
        // 強(qiáng)引用計(jì)數(shù)+1方咆,保留Person實(shí)例
        strong_retain %0: $Person // id: %2
        // 將Person實(shí)例存儲(chǔ)到棧空間
        store %0 to %1: $ * Person // id: %3
        // 獲取Person實(shí)例的name屬性地址
        %4 = ref_element_addr %0: $Person, #Person.name // user: %11
        // 創(chuàng)建String實(shí)例蟀架,初始化為"zhangsan"
        %5 = string_literal utf8 "zhangsan" // user: %10
        %6 = integer_literal $Builtin.Word, 8 // user: %10
        %7 = integer_literal $Builtin.Int1, -1 // user: %10
        %8 = metatype $@thin String.Type // user: %10
        // 獲取并調(diào)用String.init(_builtinStringLiteral:utf8CodeUnitCount:isASCII:)方法
        // function_ref String.init(_builtinStringLiteral:utf8CodeUnitCount:isASCII:)
        %9 = function_ref @Swift.String(_builtinStringLiteral: Builtin.RawPointer, utf8CodeUnitCount: Builtin.Word, isASCII: Builtin.Int1) -> Swift.String: $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String // user: %10
        %10 = apply %9(%5, %6, %7, %8): $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String // user: %11
        // 將創(chuàng)建的String實(shí)例存儲(chǔ)到name屬性地址
        store %10 to %4: $ * String // id: %11
        // 強(qiáng)引用計(jì)數(shù)-1瓣赂,釋放Person實(shí)例
        strong_release %0: $Person // id: %12
        // 加載棧空間中的Person實(shí)例
        %13 = load %1: $ * Person // user: %14
        // 對(duì)Person實(shí)例進(jìn)行強(qiáng)轉(zhuǎn)換為NSObject
        %14 = upcast %13: $Person to $NSObject // users: %15, %17
        // 調(diào)用NSObject的init方法
        %15 = unchecked_ref_cast %14: $NSObject to $Person // user: %16
        %16 = objc_super_method %15: $Person, #NSObject.init!initializer.foreign: (NSObject.Type) -> () -> NSObject, $@convention(objc_method) (@owned NSObject) -> @owned NSObject // user: %17
        %17 = apply %16(%14): $@convention(objc_method) (@owned NSObject) -> @owned NSObject // user: %18
        // 對(duì)結(jié)果進(jìn)行強(qiáng)轉(zhuǎn)換回Person類(lèi)型
        %18 = unchecked_ref_cast %17: $NSObject to $Person // users: %20, %23, %19
        // 強(qiáng)引用計(jì)數(shù)+1片拍,保留Person實(shí)例
        strong_retain %18: $Person // id: %19
        // 將Person實(shí)例存儲(chǔ)到椈图空間
        store %18 to %1: $ * Person // id: %20
        // 銷(xiāo)毀棧空間中的Person實(shí)例
        destroy_addr %1: $ * Person // id: %21
        // 釋放棸剖。空間
        dealloc_stack %1: $ * Person // id: %22
        // 返回初始化后的Person實(shí)例
        return %18: $Person // id: %23
} // end sil function 'main.Person.init() -> main.Person'

// 使用sil private [thunk]指令定義Objective-C中的thunk實(shí)現(xiàn)苫纤,將@objc修飾的Person.init()映射到Swift中的main.Person.init()方法
// @@objc main.Person.init():指明這個(gè)協(xié)議見(jiàn)證是為Person類(lèi)的Objective-C初始化方法
// @convention(objc_method):表示這是一個(gè)Objective-C方法
// @objc Person.init()
sil private [thunk] @@objc main.Person() -> main.Person: $@convention(objc_method) (@owned Person) -> @owned Person {
    // 定義基本塊bb0,它接受一個(gè)Person實(shí)例作為參數(shù)
    // %0                                             // user: %2
    bb0(%0: $Person):
        // 引用Swift中的Person.init()方法
        // function_ref Person.init()
        %1 = function_ref @main.Person() -> main.Person: $@convention(method) (@owned Person) -> @owned Person // user: %2
        // 調(diào)用并返回對(duì)象
        %2 = apply %1(%0): $@convention(method) (@owned Person) -> @owned Person // user: %3
        return %2: $Person // id: %3
} // end sil function '@objc main.Person.init() -> main.Person'

// 使用sil hidden指令定義Person類(lèi)的__deallocating_deinit方法纲缓,是一個(gè)析構(gòu)器
// Person.__deallocating_deinit
sil hidden @main.Person.__deallocating_deinit: $@convention(method) (@owned Person) -> Void {
    // 定義基本塊bb0卷拘,它接受一個(gè)Person實(shí)例作為參數(shù)
    // %0 "self"                                      // users: %3, %2, %1
    bb0(%0: $Person):
        // 調(diào)試信息,標(biāo)記參數(shù)%0為"self"
        debug_value %0: $Person, let, name "self", argno 1, implicit // id: %1
        // 使用objc_super_method指令調(diào)用NSObject的析構(gòu)器deinit
        %2 = objc_super_method %0: $Person, #NSObject.deinit!deallocator.foreign: (NSObject) -> () -> Void, $@convention(objc_method) (NSObject) -> Void // user: %4
        // 對(duì)Person實(shí)例進(jìn)行強(qiáng)轉(zhuǎn)換為NSObject類(lèi)型
        %3 = upcast %0: $Person to $NSObject // user: %4
        // 調(diào)用NSObject的析構(gòu)器deinit
        %4 = apply %2(%3): $@convention(objc_method) (NSObject) -> Void
        // 創(chuàng)建一個(gè)空元組作為返回值
        %5 = tuple() // user: %6
        // 返回空元組
        return %5: $() // id: %6
} // end sil function 'main.Person.__deallocating_deinit'

// 使用sil hidden @@objc指令定義Objective-C中的實(shí)例變量銷(xiāo)毀方法__ivar_destroyer
// @objc Person.__ivar_destroyer
sil hidden @@objc main.Person.__ivar_destroyer: $@convention(objc_method) (Person) -> Void {
    // 定義基本塊bb0祝高,它接受一個(gè)Person實(shí)例作為參數(shù)
    // %0 "self"                                      // users: %2, %1
    bb0(%0: $Person):
        // 調(diào)試信息栗弟,標(biāo)記參數(shù)%0為"self"
        debug_value %0: $Person, let, name "self", argno 1, implicit // id: %1
        // 獲取Person實(shí)例的name屬性地址
        %2 = ref_element_addr %0: $Person, #Person.name // user: %3
        // 開(kāi)始訪(fǎng)問(wèn)name屬性,指定為deinit操作
        %3 = begin_access[deinit][static] %2: $ * String // users: %5, %4
        // 銷(xiāo)毀name屬性的內(nèi)存
        destroy_addr %3: $ * String // id: %4
        // 結(jié)束對(duì)name屬性的訪(fǎng)問(wèn)
        end_access %3: $ * String // id: %5
        // 創(chuàng)建一個(gè)空元組作為返回值
        %6 = tuple() // user: %7
        // 返回空元組
        return %6: $() // id: %7
} // end sil function '@objc main.Person.__ivar_destroyer'

// 使用sil private [transparent] [thunk]指令定義協(xié)議witness實(shí)現(xiàn)工闺,實(shí)現(xiàn)SomeProtocol協(xié)議的doSomething()方法
// sil private:表示這個(gè)協(xié)議見(jiàn)證是私有的乍赫,即不對(duì)外部可見(jiàn)
// [transparent]:表示這個(gè)協(xié)議見(jiàn)證是透明的瓣蛀,即沒(méi)有額外的控制流或操作
// [thunk]:表示這是一個(gè)動(dòng)態(tài)分發(fā)的協(xié)議見(jiàn)證,可能涉及到動(dòng)態(tài)派發(fā)
// @protocol witness for main.SomeProtocol.doSomething() -> ():指定了這個(gè)協(xié)議見(jiàn)證是為SomeProtocol協(xié)議的doSomething()方法
// in conformance main.Person : main.SomeProtocol in main:指明這個(gè)協(xié)議見(jiàn)證是在Person類(lèi)對(duì)SomeProtocol協(xié)議的遵循中
// @convention(witness_method: SomeProtocol):表示這是一個(gè)協(xié)議方法的見(jiàn)證
// (@in_guaranteed Person):表示這個(gè)方法接受一個(gè)在整個(gè)調(diào)用期間保證有效的Person實(shí)例作為參數(shù)
// -> ():表示這個(gè)方法沒(méi)有返回值
// protocol witness for SomeProtocol.doSomething() in conformance Person
sil private [transparent][thunk] @protocol witness for main.SomeProtocol.doSomething() in conformance main.Person: main.SomeProtocol in main: $@convention(witness_method: SomeProtocol) (@in_guaranteed Person) -> Void {
    // 定義基本塊bb0雷厂,它接受一個(gè)指向Person實(shí)例的指針作為參數(shù)
    // %0                                             // user: %1
    bb0(%0: $ * Person):
        // 加載Person實(shí)例
        %1 = load %0: $ * Person // users: %2, %3
        // 獲取并調(diào)用Person實(shí)例的doSomething()方法
        %2 = class_method %1: $Person, #Person.doSomething: (Person) -> () -> Void, $@convention(method) (@guaranteed Person) -> Void // user: %3
        %3 = apply %2(%1): $@convention(method) (@guaranteed Person) -> Void
        // 創(chuàng)建一個(gè)空元組作為返回值
        %4 = tuple() // user: %5
        // 返回空元組
        return %4: $() // id: %5
} // end sil function 'protocol witness for main.SomeProtocol.doSomething() -> () in conformance main.Person : main.SomeProtocol in main'

// 使用sil hidden指令定義Person類(lèi)的drink()方法
// sil hidden:這表示該函數(shù)是隱藏的惋增,即它不會(huì)在模塊之外可見(jiàn)
// @main.Person.drink():這是函數(shù)的完全限定名稱(chēng),指明了該函數(shù)屬于main模塊中的Person類(lèi)的drink()方法
// -> ():表示函數(shù)的返回類(lèi)型為空元組改鲫,即函數(shù)不返回任何值
// : $@convention(method):這部分指定了函數(shù)的調(diào)用約定器腋,表明這是一個(gè)方法,在Swift中钩杰,方法調(diào)用與函數(shù)調(diào)用有一些不同之處纫塌,例如它們使用隱式的self參數(shù)
// (@guaranteed Person) -> ():這是函數(shù)的參數(shù)列表@guaranteed是一個(gè)生命周期修飾符,表示參數(shù)Person在整個(gè)函數(shù)調(diào)用期間都是有效的Person 是參數(shù)的類(lèi)型讲弄,表示該方法在調(diào)用時(shí)需要一個(gè) Person 實(shí)例
// Person.drink()
sil hidden @main.Person.drink() -> Void: $@convention(method) (@guaranteed Person) -> Void {
    // 定義基本塊bb0措左,它接受一個(gè)Person實(shí)例作為參數(shù)
    // %0 "self"                                      // user: %1
    bb0(%0: $Person):
        // 調(diào)試信息,標(biāo)記參數(shù)%0為"self"
        // implicit表示這是一個(gè)隱式的變量避除,它表示這個(gè)變量并不是由程序員顯式創(chuàng)建的怎披,而是由編譯器生成
        debug_value %0: $Person, let, name "self", argno 1, implicit // id: %1
        // 創(chuàng)建一個(gè)空元組作為返回值
        %2 = tuple() // user: %3
        // 返回空元組
        return %2: $() // id: %3
} // end sil function 'main.Person.drink() -> ()'

// vtable
// Person中的方法
sil_vtable Person {
    #Person.name!getter: (Person) -> () -> String: @main.Person.name.getter: Swift.String // Person.name.getter
    #Person.name!setter: (Person) -> (String) -> Void: @main.Person.name.setter: Swift.String // Person.name.setter
    #Person.name!modify: (Person) -> () -> Void: @main.Person.name.modify: Swift.String // Person.name.modify
    #Person.doSomething: (Person) -> () -> Void: @main.Person.doSomething() -> Void // Person.doSomething()
    #Person.deinit!deallocator: @main.Person.__deallocating_deinit // Person.__deallocating_deinit
}

// witness_table
// hidden:表示這個(gè)協(xié)議見(jiàn)證表是隱藏的,即不對(duì)外部可見(jiàn)瓶摆。
// Person: SomeProtocol:指明這個(gè)協(xié)議見(jiàn)證表是為Person類(lèi)對(duì)SomeProtocol協(xié)議的遵循
// module main:指定了這個(gè)協(xié)議見(jiàn)證表所屬的模塊為main 
sil_witness_table hidden Person: SomeProtocol module main {
    method #SomeProtocol.doSomething: <Self where Self: SomeProtocol>(Self) -> () -> Void: @protocol witness for main.SomeProtocol.doSomething() in conformance main.Person: main.SomeProtocol in main // protocol witness for SomeProtocol.doSomething() in conformance Person
}

// 文件映射關(guān)系
// Mappings from '#fileID' to '#filePath':
//   'main/main.swift' => 'main.swift'

參考

  1. Swift Intermediate Language (SIL)
  2. GroffLattner-SILHighLevelIR
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末凉逛,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子群井,更是在濱河造成了極大的恐慌状飞,老刑警劉巖,帶你破解...
    沈念sama閱讀 210,978評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件书斜,死亡現(xiàn)場(chǎng)離奇詭異诬辈,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)荐吉,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,954評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門(mén)焙糟,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人样屠,你說(shuō)我怎么就攤上這事穿撮。” “怎么了痪欲?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,623評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵悦穿,是天一觀(guān)的道長(zhǎng)。 經(jīng)常有香客問(wèn)我勤揩,道長(zhǎng)咧党,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,324評(píng)論 1 282
  • 正文 為了忘掉前任陨亡,我火速辦了婚禮傍衡,結(jié)果婚禮上深员,老公的妹妹穿的比我還像新娘。我一直安慰自己蛙埂,他們只是感情好倦畅,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,390評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著绣的,像睡著了一般叠赐。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上屡江,一...
    開(kāi)封第一講書(shū)人閱讀 49,741評(píng)論 1 289
  • 那天芭概,我揣著相機(jī)與錄音,去河邊找鬼惩嘉。 笑死罢洲,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的文黎。 我是一名探鬼主播惹苗,決...
    沈念sama閱讀 38,892評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼耸峭!你這毒婦竟也來(lái)了桩蓉?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,655評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤劳闹,失蹤者是張志新(化名)和其女友劉穎院究,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體玷或,經(jīng)...
    沈念sama閱讀 44,104評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡儡首,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評(píng)論 2 325
  • 正文 我和宋清朗相戀三年片任,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了偏友。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,569評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡对供,死狀恐怖位他,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情产场,我是刑警寧澤鹅髓,帶...
    沈念sama閱讀 34,254評(píng)論 4 328
  • 正文 年R本政府宣布,位于F島的核電站京景,受9級(jí)特大地震影響窿冯,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜确徙,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,834評(píng)論 3 312
  • 文/蒙蒙 一醒串、第九天 我趴在偏房一處隱蔽的房頂上張望执桌。 院中可真熱鬧,春花似錦芜赌、人聲如沸仰挣。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,725評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)膘壶。三九已至,卻和暖如春洲愤,著一層夾襖步出監(jiān)牢的瞬間颓芭,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,950評(píng)論 1 264
  • 我被黑心中介騙來(lái)泰國(guó)打工柬赐, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留畜伐,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,260評(píng)論 2 360
  • 正文 我出身青樓躺率,卻偏偏與公主長(zhǎng)得像玛界,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子悼吱,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,446評(píng)論 2 348

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