編譯過(guò)程
-
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() {
}
}
// 表示最終的坎匿、經(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'
參考
- Swift Intermediate Language (SIL)
- GroffLattner-SILHighLevelIR