Swift’s use of SIL

Swift 是一門靜態(tài)語言铜异,在 Swift 中聲明的方法和屬性靜態(tài)編譯期就確定了的,并且Swift具有更靈活的高級特性秸架,協(xié)議,泛型东抹,方法重載,值引用等食茎,所以其與OC運(yùn)行時(shí)動(dòng)態(tài)消息派發(fā)不同附迷,需要支持靜態(tài)派發(fā)以及動(dòng)態(tài)派發(fā),目前的這些特性Clang并不能完全支持壹哺。

因此蘋果另外實(shí)現(xiàn)了一套 Swift() 作為Swift的編譯前端,由于其語言特性管宵,反而有更多的優(yōu)化空間截珍。

其使用SIL作為前端中間表示層,與IR差異很大箩朴,大致體現(xiàn)在:

  • 在編譯期完全確定的調(diào)用關(guān)系會采用靜態(tài)派發(fā)岗喉,即在可執(zhí)行文件中直接指定方法實(shí)現(xiàn)的內(nèi)存地址的指針,在運(yùn)行時(shí)直接通過指針調(diào)用
  • 在編譯期間無法確定最終合適的操作時(shí)炸庞,則會執(zhí)行動(dòng)態(tài)派發(fā)钱床。Swift又不完全同于C++的方式,其除了支持繼承使用的虛函數(shù)表vtable埠居,還加入了支持面向協(xié)議編程的witness table
  • 通過dynamic關(guān)鍵字對方法標(biāo)記查牌,使用OC的運(yùn)行時(shí)機(jī)制
  • 由于支持函數(shù)重載,也就引出了name mangling(名字修飾)機(jī)制纸颜,其目的是給同名的重載函數(shù)不同的簽名
  • ...

1. Clang vs Swift():

Clang

  • Wide abstraction gap between source and LLVM IR
  • IR isn't suitable for source-level analysis
  • CFG lacks fidelity
  • CFG is off the hot path
  • Duplicated effort in CFG and IR lowering
clang.png

Swift

  • Higher-level language
    • Move more of the language into code
    • Protocol-based generics
  • Safe language
    • Uninitialized vars, unreachable code should be compiler errors
    • Bounds and overflow checks
swift.png


2. V-Table

常見的編譯型語言的動(dòng)態(tài)派發(fā)方式绎橘,編譯器層使用一個(gè)表格結(jié)構(gòu)來存儲類型聲明中的每一個(gè)函數(shù)指針。C++中稱之為虛函數(shù)表VTable称鳞,也是其支持多態(tài)的基礎(chǔ)涮较。

在Swift中,擁有繼承關(guān)系的Class采用此種方式冈止,即每一個(gè)類會維護(hù)一個(gè)函數(shù)表,該表會記錄該類中所有的函數(shù)指針:

  1. 由父類繼承而來的方法執(zhí)行地址靶瘸。
  2. 如果子類重寫父類方法毛肋,表中會保存被重載之后的函數(shù)。
  3. 子類新增的函數(shù)會加入到表的末尾屋剑。

然后在程序運(yùn)行期間查表執(zhí)行具體實(shí)現(xiàn)润匙。

3. Protocol Witness Table

因?yàn)閰f(xié)議不一定具有繼承關(guān)系,所以其創(chuàng)建了Protocol Witness Table唉匾。大致實(shí)現(xiàn)為:Swift會為每一個(gè)實(shí)現(xiàn)了該協(xié)議的對象生成一個(gè)大小一致的結(jié)構(gòu)體,這個(gè)結(jié)構(gòu)體被稱為Existenial Container巍膘,它內(nèi)部包含PWT,表中存儲著一組函數(shù)的執(zhí)行地址峡懈,而表中的每一個(gè)條目指向了符合該協(xié)議的類型信息。該結(jié)構(gòu)體中還保留了三個(gè)字長的valueBuffer用來存儲數(shù)據(jù)成員荚恶。

4. SIL

SIL是一種SSA形式的IR磷支,具有高級語義信息谒撼,旨在實(shí)現(xiàn)Swift編程語言雾狈。 SIL適用于以下用例:

  • 一組有保證的高級優(yōu)化,可為運(yùn)行時(shí)和診斷行為提供可預(yù)測的基準(zhǔn)善榛。
  • 診斷數(shù)據(jù)流分析過程可滿足Swift語言要求,例如變量和構(gòu)造函數(shù)的確定性初始化堪澎,代碼可訪問性味滞,開關(guān)覆蓋率樱蛤。
  • 高級優(yōu)化過程剑鞍,包括保留/釋放優(yōu)化,動(dòng)態(tài)方法去虛擬化便脊,閉包內(nèi)聯(lián),將堆分配提升為堆棧分配哪痰,將堆分配提升為SSA寄存器,將標(biāo)量替換為標(biāo)量(將標(biāo)量分配拆分為多個(gè)較小的標(biāo)量)和通用函數(shù)實(shí)例化晌杰。
  • 一種穩(wěn)定的分發(fā)格式跷睦,可用于分發(fā)帶有Swift庫模塊的“易碎”的內(nèi)聯(lián)代碼或通用代碼,并將其優(yōu)化為客戶端二進(jìn)制文件肋演。

與LLVM IR相比,SIL是一種通常與目標(biāo)無關(guān)的格式表示形式爹殊,可用于代碼分發(fā),但它也可以像LLVM一樣表示特定于目標(biāo)的概念梗夸。

  • 完全代表程序語義
  • 專為代碼生成和分析而設(shè)計(jì)
  • 位于編譯器管道的熱路徑上
  • 修復(fù)了源代碼和LLVM之間的抽象鴻溝

在較高的層次上,Swift編譯器遵循嚴(yán)格的管道架構(gòu):

  • Parse模塊從Swift源代碼構(gòu)造AST称簿。
  • Sema模塊對AST進(jìn)行類型檢查惰帽,并使用類型信息對其進(jìn)行注釋父虑。
  • SILGen模塊從AST生成raw SIL
  • 在原始SIL上運(yùn)行一系列“保證的優(yōu)化Pass”和“診斷Pass”士嚎,以執(zhí)行優(yōu)化并發(fā)出特定于語言的診斷信息。即使在-Onone上爵嗅,它們也始終運(yùn)行笨蚁,并生成規(guī)范SIL睹晒。
  • 常規(guī)SIL 優(yōu)化Pass(可選)在規(guī)范的SIL上運(yùn)行括细,以提高生成的可執(zhí)行文件的性能。這些是由優(yōu)化級別啟用和控制的锉试,而不是在-Onone上運(yùn)行览濒。
  • IRGen將規(guī)范SIL降低為LLVM IR拖云。
  • LLVM后端(可選)使用LLVM優(yōu)化应又,運(yùn)行LLVM代碼生成器并產(chǎn)生二進(jìn)制代碼。

5. SILGen

SILGen通過遍歷經(jīng)過類型檢查的Swift AST來生成“原始SIL”丁频。 SILGen發(fā)出的SIL形式具有以下特性:

  • 變量通過加載和存儲可變存儲器位置來表示,而不是采用嚴(yán)格的SSA形式席里。 這類似于前端(如Clang)發(fā)出的初始“alloca”大量的LLVM IR。 但是改基,在最普通的情況下咖为,Swift將變量表示為引用計(jì)數(shù)的“boxes”,可以將其保留躁染,釋放并捕獲到閉包中。
  • 尚未執(zhí)行數(shù)據(jù)流要求我衬,例如最終分配饰恕,函數(shù)返回挠羔,開關(guān)覆蓋率(TBD)等埋嵌。
  • transparent功能優(yōu)化尚未實(shí)現(xiàn)。

這些屬性通過后續(xù)保證的優(yōu)化和診斷遍歷得到解決范舀,這些遍歷始終針對原始SIL運(yùn)行俐银。

6. General Optimization Passes

SIL捕獲特定語言的類型信息,從而可以實(shí)現(xiàn)在LLVM IR上難以執(zhí)行的高級優(yōu)化捶惜。

  • Generic Specialization 分析對泛型函數(shù)的專門調(diào)用,并生成函數(shù)的新的指定版本汽久。然后,它將泛型的所有指定用法重寫為對指定功能的直接調(diào)用景醇。
  • 給定類型的 Witness and VTable Devirtualization 從類的vtable或類型見證表中查找關(guān)聯(lián)的方法,并將間接虛擬調(diào)用替換為對映射函數(shù)的調(diào)用吧寺。
  • Performance Inlining
  • Reference Counting Optimizations
  • Memory Promotion/Optimizations
  • High-level domain specific optimizations Swift編譯器在基礎(chǔ)的Swift容器(例如Array或String)上實(shí)現(xiàn)了高級優(yōu)化散劫。特定于域的優(yōu)化需要在標(biāo)準(zhǔn)庫和優(yōu)化器之間定義接口。更多細(xì)節(jié)可以查看:HighLevelSILOptimizations

如下代碼為swift實(shí)現(xiàn)代碼在SIL下的展現(xiàn)形式:

sil_stage canonical 

import Swift 

//定義SIL函數(shù)使用的類型获搏。

struct Point { 
  var x:Double 
  var y:Double 
} 

class Button { 
  func onClick()
  func onMouseDown()
  func onMouseUp()
} 

//聲明一個(gè)Swift函數(shù)。主體被SIL忽略纬乍。
func taxicabNorm(_ a:Point)-> Double { 
  return a.x + a.y 
} 

//定義SIL函數(shù)裸卫。
//名稱@_T5norms11taxicabNormfT1aV5norms5Point_Sd是 taxicabNorm Swift函數(shù)的錯(cuò)誤名稱。
sil @ _T5norms11taxicabNormfT1aV5norms5Point_Sd:$(Point)-> Double { 
bb0(%0:$ Point):
  // func Swift彼城。+(Double退个,Double)-> Double 
  %1 = function_ref @ _Tsoi1pfTSdSd_Sd 
  %2 = struct_extract%0:$ Point,#Point.x 
  %3 = struct_extract%0:$ Point语盈,#Point.y 
  %4 = apply%1(%2,%3):$(Double代嗤,Double)-> Double 
  return%4:Double 
} 

//定義SIL vtable缠借。匹配動(dòng)態(tài)分派的方法
//標(biāo)識與其已知靜態(tài)類類型的實(shí)現(xiàn)相匹配。
sil_vtable Button { 
  #Button.onClick泼返!1:@ _TC5norms6Button7onClickfS0_FT_T_ 
  #Button.onMouseDown!1:@ _TC5norms6Button11onMouseDownfS0_FT_T_ 
  #Button.onMouseUp渠鸽!1:@ _TC5norms6Button9onMouseUpfS0_FT_T_ 
}


7. Swift’s use of SIL 流程

Two Phases of SIL Passes.png
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市憨奸,隨后出現(xiàn)的幾起案子凿试,更是在濱河造成了極大的恐慌,老刑警劉巖那婉,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異虾啦,居然都是意外死亡痕寓,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進(jìn)店門呻率,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人吐咳,你說我怎么就攤上這事元践。” “怎么了单旁?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長蔫饰。 經(jīng)常有香客問我愉豺,道長,這世上最難降的妖魔是什么蚪拦? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任节腐,我火速辦了婚禮摘盆,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘狼渊。我一直安慰自己,他們只是感情好狈邑,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布蚤认。 她就那樣靜靜地躺著,像睡著了一般砰琢。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上训唱,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天挚冤,我揣著相機(jī)與錄音,去河邊找鬼训挡。 笑死,一個(gè)胖子當(dāng)著我的面吹牛为肮,可吹牛的內(nèi)容都是我干的表悬。 我是一名探鬼主播弥锄,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼温治!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起熬荆,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎累盗,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體符相,經(jīng)...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蠢琳,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了傲须。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,690評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡例衍,死狀恐怖已卸,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情咬最,我是刑警寧澤,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布惑申,位于F島的核電站翅雏,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏望几。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一靴迫、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧玉锌,春花似錦疟羹、人聲如沸主守。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽涎才。三九已至,卻和暖如春涛救,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背检吆。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工程储, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人章鲤。 一個(gè)月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像帚呼,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子煤杀,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,577評論 2 353