iOS LLVM編譯流程

LLVM

LLVM是架構(gòu)編譯器(compiler)的框架系統(tǒng)申眼,由C++編寫完成,用于優(yōu)化已任意程序編寫的程序的編譯時(shí)間(compile-time)争拐、鏈接時(shí)間(link-time)辰妙、運(yùn)行時(shí)間(run-time)以及空閑時(shí)間(idle-time),對(duì)開發(fā)者保持開放碉输,并兼容已有腳本

傳統(tǒng)編譯器設(shè)計(jì)

  • 編譯器前端(Frontend):負(fù)責(zé)解析源代碼,它會(huì)進(jìn)行詞法分析亭珍、語法分析敷钾、語義分析和檢查源代碼是否存在錯(cuò)誤,然后構(gòu)建抽象語法樹(Abstract Syntax Tree,AST)肄梨,LLVM會(huì)生成中間代碼(intermediate representation IR)

  • 優(yōu)化器(Optimizer):負(fù)責(zé)進(jìn)行各種優(yōu)化,改善代碼的運(yùn)行時(shí)間众羡,例如消除冗余計(jì)算等

  • 后端(Backend)/代碼生成器(CodeGenerator):將代碼映射到目標(biāo)指令集生成機(jī)器語言纱控,并進(jìn)行機(jī)器相關(guān)的代碼優(yōu)化

傳統(tǒng)編譯器設(shè)計(jì)

iOS的編譯器架構(gòu)

OC/C/C++使用的編譯器前端是Clang,swift前端是Swift舶掖,后端都是LLVMClang會(huì)生成中間代碼(intermediate representation IR)

iOS編譯器架構(gòu)

LLVM設(shè)計(jì)

使用通用的代碼表示形式(IR)眨攘,用來在編譯器中表示代碼的形式,所有LLVM可以為任何編程語言獨(dú)立編寫前端嚣州,并且可以為任意硬件架構(gòu)獨(dú)立編寫后端

LLVM

Clang簡介

Clang是LLVM項(xiàng)目中的子項(xiàng)目鲫售,基于LLVM架構(gòu)的輕量級(jí)編譯器,誕生之初是為了替代GCC该肴,提高更快的編譯速度情竹。它是負(fù)責(zé)編譯C、C++匀哄、Object-C語言的編譯器秦效,在整個(gè)LLVM架構(gòu)中屬于編譯器前端

編譯流程

  • 單獨(dú)新建一個(gè)main.m文件
int test(int a,int b){
    return a + b + 3;
}

int main(int argc, const char * argv[]) {
    int a = test(1, 2);
    printf("%d",a);
    return 0;[圖片上傳中...(image.png-1984f6-1624280414052-0)]

}
  • 通過命令clang -ccc-print-phases main.m
    LLVM編譯流程
//輸入文件:找到源文件
+- 0: input, "main.m", objective-c
//預(yù)處理階段:處理包括宏的替換雏蛮,頭文件的導(dǎo)入
+- 1: preprocessor, {0}, objective-c-cpp-output
//編譯階段:進(jìn)行詞法、語法分析阱州,檢測語法是否正確挑秉,最終生成IR
+- 2: compiler, {1}, ir
//后端:LLVM會(huì)通過一個(gè)一個(gè)的Pass去優(yōu)化,每個(gè)Pass做些事情苔货,最終生成匯編代碼
+- 3: backend, {2}, assembler
//生成目標(biāo)文件
+- 4: assembler, {3}, object
//鏈接:鏈接需要的動(dòng)態(tài)庫和靜態(tài)庫犀概,生成可執(zhí)行文件
+- 5: linker, {4}, image
//通過不同的架構(gòu),生成對(duì)應(yīng)的可執(zhí)行文件
6: bind-arch, "x86_64", {5}, image

1夜惭、預(yù)處理階段

預(yù)處理階段是進(jìn)行宏的替換和頭文件的導(dǎo)入姻灶,我們可以通過下面命令來查看導(dǎo)入和替換情況

//在終端直接查看替換結(jié)果
clang -E main.m

//生成對(duì)應(yīng)的文件查看替換后的源碼
clang -E main.m >> main2.m
  • typedef給數(shù)據(jù)類型取別名時(shí),在預(yù)處理階段不會(huì)被替換
  • define的取的別名在預(yù)處理階段會(huì)被替換诈茧,所有我們可以用這方法來進(jìn)行關(guān)鍵代碼混淆木蹬,例如將關(guān)鍵類和方法用系統(tǒng)類似的名稱取別名

2、編譯階段

編譯階段主要是進(jìn)行:詞法若皱、語法分析和代碼錯(cuò)誤檢查,然后生成中間代碼IR

(1)詞法分析

預(yù)處理完成后就會(huì)進(jìn)行詞法分析尘颓,會(huì)把代碼切成一個(gè)個(gè)Token走触,比如大小括號(hào),等于號(hào)還有字符串等

  • 通過下面命令查看詞法分析后結(jié)果
clang -fmodules -fsyntax-only -Xclang -dump-tokens main.m
詞法分析
  • 如果頭文件找不到疤苹,我們可以通過下面命令指定sdk
clang -isysroot (自己SDK路徑) -fmodules -fsyntax-only -Xclang -dump-tokens main.m

clang -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator14.1.sdk/ -fmodules -fsyntax-only -Xclang -dump-tokens main.m
(2)語法分析

驗(yàn)證語法是否正確互广,在詞法分析的基礎(chǔ)上將單詞序列組合成各類語法短語,如程序卧土、語句惫皱、表達(dá)式等等,然后將所有節(jié)點(diǎn)組成抽象語法樹(Abstract Syntax Tree,AST)尤莺。語法分析程序判斷源程序在結(jié)構(gòu)上是否正確

  • 我們可以通過下面命令查看語法分析的結(jié)果
clang -fmodules -fsyntax-only -Xclang -ast-dump main.m
語法分析
  • 如果導(dǎo)入頭文件找不到媳谁,可以指定SDK
clang -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator14.1.sdk/ -fmodules -fsyntax-only -Xclang -ast-dump main.m

下面是幾個(gè)關(guān)鍵字的含義

  • -FunctionDecl 函數(shù)
  • -ParmVarDecl 參數(shù)
  • -CallExpr 調(diào)用一個(gè)函數(shù)
  • -BinaryOperator 運(yùn)算符
(3)生成中間代碼IR

代碼生成器(Code Generaltion)會(huì)將語法樹自頂向下遍歷逐步翻譯成LLVM IR晴音,OC代碼會(huì)在這一步進(jìn)行runtime的橋接:property合成缔杉,ARC處理等

  • 我們可以通過下面命令生成.ll的文本文件或详,來查看IR代碼
clang -S -fobjc-arc -emit-llvm main.m

IR基本語法
@ 全局標(biāo)識(shí)
% 局部標(biāo)識(shí)
alloca 開辟空間
align 內(nèi)存對(duì)齊
i32 32bit,4個(gè)字節(jié)
store 寫入內(nèi)存
load 讀取數(shù)據(jù)
call 調(diào)用函數(shù)
ret 返回

IR代碼
  • IR文件在OC中是可以進(jìn)行優(yōu)化的拣宏,一般設(shè)置是在target - Build Setting - Optimization Level(優(yōu)化器等級(jí))中設(shè)置勋乾。LLVM的優(yōu)化級(jí)別分別是-O0 -O1 -O2 -O3 -Os(第一個(gè)是大寫英文字母O)嗡善,下面是帶優(yōu)化的生成中間代碼IR的命令
clang -Os -S -fobjc-arc -emit-llvm main.m -o main.ll
優(yōu)化后的IR代碼
  • xcode7以后開啟bitcode各吨,蘋果會(huì)做進(jìn)一步優(yōu)化揭蜒,生成.bc的中間代碼剔桨,我們通過優(yōu)化后的IR代碼生成.bc代碼
clang -emit-llvm -c main.ll -o main.bc
.bc代碼

3瑰谜、后端

LLVM在后端主要是會(huì)通過一個(gè)個(gè)的Pass去優(yōu)化萨脑,每個(gè)Pass做一些事情饺饭,最終生成匯編代碼

  • 我們通過最終的.bc或者.ll代碼生成匯編代碼
clang -S -fobjc-arc main.bc -o main.s 
clang -S -fobjc-arc main.ll -o main.s
  • 生成的匯編代碼也可以進(jìn)行優(yōu)化
clang -Os -S -fobjc-arc main.m -o main.s
匯編代碼main.s

4瘫俊、生成目標(biāo)文件

是匯編器以匯編代碼作為插入军援,將匯編代碼轉(zhuǎn)換為機(jī)器代碼胸哥,最后輸出目標(biāo)文件(object file)

clang -fmodules -c main.s -o main.o
  • 通過nm命令,查看main.o中的符號(hào)
xcrun nm -nm main.o
main.o中的符號(hào)
  • external表示這個(gè)符號(hào)是可以外部訪問
  • _printf函數(shù)是一個(gè)是undefined 银酬、external
  • undefined表示在當(dāng)前文件暫時(shí)找不到符號(hào)_printf

5揩瞪、鏈接

鏈接主要是鏈接需要的動(dòng)態(tài)庫和靜態(tài)庫

  • 靜態(tài)庫和可執(zhí)行文件合并
  • 動(dòng)態(tài)庫是獨(dú)立鏈接

鏈接器會(huì)吧編譯生成的.o文件(.dylib.a)文件李破,生成一個(gè)mach-o文件

clang main.o -o main

查看鏈接后的符號(hào)

xcrun nm -nm main

如下所示嗤攻,其中undefined表示會(huì)在運(yùn)行時(shí)進(jìn)行動(dòng)態(tài)綁定

mach-o文件符號(hào)

6妇菱、綁定

綁定主要是通過不同的架構(gòu)暴区,生成對(duì)應(yīng)的mach-o格式可執(zhí)行文件

總結(jié)

LLVM編譯流程
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末偷俭,一起剝皮案震驚了整個(gè)濱河市缰盏,隨后出現(xiàn)的幾起案子口猜,更是在濱河造成了極大的恐慌济炎,老刑警劉巖辐真,帶你破解...
    沈念sama閱讀 219,490評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件耐床,死亡現(xiàn)場離奇詭異楔脯,居然都是意外死亡,警方通過查閱死者的電腦和手機(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
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼煌恢!你這毒婦竟也來了?” 一聲冷哼從身側(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)容