(三)Clang/ LLVM编译流程简述
生活随笔
收集整理的這篇文章主要介紹了
(三)Clang/ LLVM编译流程简述
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
-
LLVM概述
LLVM是構架編譯器(compiler)的框架系統(tǒng),以C++編寫而成,用于優(yōu)化以任意程序語言編寫的程序的編譯時間(compile-time)、鏈接時間(link-time)、運行時間(run-time) 以及空閑時間(idle-time),對開發(fā)者保持開放,并兼容已有腳本。 -
傳統(tǒng)編譯器設計
編譯器不同于解釋器,解釋器可以將高級語言邊轉譯邊執(zhí)行。但是編譯器需要將所有的源代碼編譯成機器代碼之后,然后才能執(zhí)行,所以如圖不管傳統(tǒng)的還是LLVM都一定是源代碼輸入,輸出是機器代碼(也就是0101組合),中間還分前端、優(yōu)化器、后端-
編譯器前端(Frontend)
編譯器前端的任務是解析源代碼。它會進行:詞法分析,語法分析,語義分析, 檢查源代碼是否存在錯誤,然后構建抽象語法樹(Abstract Syntax Tree,AST) ,LLVM的前端還會生成中間代碼(intermediate representation , IR)。 -
優(yōu)化器(Optimizer)
優(yōu)化器負責進行各種優(yōu)化。改善代碼的運行時間,例如消除冗余計算等。 -
后端(Backend) /代碼生成器(CodeGenerator)
將代碼映射到目標指令集。生成機器語言,并且進行機器相關的代碼優(yōu)化 -
iOS的編譯器架構
-
-
LLVM的設計
當編譯器決定支持多種源語言或多種硬件架構時,LLVM最重要的地方就來了。 其他的編譯器如GCC,它方法非常成功,但由于它是作為整體應用程序設計的, 因此它們的用途受到了很大的限制。
LLVM設計的最重要方面是,使用通用的代碼表示形式(IR),它是用來在編譯器中標識代碼的形式(其實就是一種中間代碼)。所以LLVM可以為任何變成語言獨立編寫前端,并且可以為任意硬件架構獨立編寫后端。 -
Clang
Clang是LLVM項目中的一個子項目。它是基于LLVM架構的輕量級編譯器,誕生之初是為了替代GCC,提供更快的編譯速度。它是負責編譯C、C++、Objecte-C語言的編譯器,它屬于整個LLVM架構中的,編譯器前端。 -
編譯流程
首先簡單寫一個demo如下: #import <stdio.h>//#define C 30//typedef int TD_INT_64;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;} 復制代碼-
通過命令打印查看源碼的編譯階段
命令:clang -ccc-print-phases main.m 可以發(fā)現(xiàn)主要分6個步驟- 0:輸入文件:找到源文件。
- 1:預處理階段:這個過程處理包括宏的替換,頭文件的導入。
- 2:編譯階段:進行詞法分析、語法分析、檢測語法是否正確,最終生成IR。
- 3:后端:這里LLVM會通過一個一個的Pass去優(yōu)化,每個Pass做一些事情,最終生成匯編代碼。
- 4:生成目標文件。
- 5:鏈接:鏈接需要的動態(tài)庫和靜態(tài)庫,生成可執(zhí)行文件。
- 6:通過不同的架構,生成對應的可執(zhí)行文件。
-
預處理階段
命令:clang -E main.m 宏在預處理階段會被替換掉,typedef不會被替換掉,所以一般為了安全可以使用,做代碼混淆 -
編譯階段
-
詞法分析
預處理完成后就會進行詞法分析.這里會把代碼切成一個個Token,比如大小括 號,等于號還有字符串等
命令: 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 -
語法分析
詞法分析完成之后就是語法分析,它的任務是驗證語法是否正確。在詞法分析的基礎上將單詞序列組合成各類語法短語,如“程序”,“語句”,“表達式”等等,然后將所有節(jié)點組成抽象語法樹(Abstract Syntax Tree, AST)。語法分析程序判斷源程序在結構上是否正確。
命令: clang -fmodules -fsyntax-only -Xclang -ast-dump main.m- FunctionDecl 函數(shù)
- ParmVarDecl 參數(shù)
- CallExpr 調用一個函數(shù)
- BinaryOperator 運算符
-
生成中間代碼IR
完成以上步驟后就開始生成中間代碼IR了,代碼生成器(Code Generation)會將語法樹自頂向下遍歷逐步翻譯成LLVM IR。通過下面命令可以生成.11的文本文件,查看IR代碼。
命令:clang -S -fobjc-arc -emit-llvm main.m
Objective C代碼在這一步會進行runtime的橋接:property合成,ARC處理等
IR的基本語法:- @ 全局標識
- % 局部標識
- alloca 開辟空間
- align 內存對齊
- i32 32個bit, 4個字節(jié)
- store 寫入內存
- load 讀取數(shù)據(jù)
- call 調用函數(shù)
- ret 返回
LLVM的優(yōu)化級別分別是-O0 -O1 -O2 -O3 -Os(第一個是大寫英文字母O)
優(yōu)化命令:clang -Os -S -fobjc-arc -emit-llvm main.m -o main.ll 一般設置是在target - Build Setting - Optimization Level(優(yōu)化器等級)中設置 Debug情況下默認是不優(yōu)化,Release情況下默認Fastest、Smallest
優(yōu)化后的代碼: -
bitCode
xcode7以后開啟bitcode蘋果會做進一步的優(yōu)化。生成.be的中間代碼。 我們通過優(yōu)化后的IR代碼生成.be代碼
命令:clang -emit-llvm -c main.ll -o main.bc -
生成匯編代碼
最終通過.be或者.ll代碼生成匯編代碼
命令:
clang -S -fobjc-arc main.bc -o main.s
clang -S -fobjc-arc main.ll -o main.s 當然生成的匯編代碼也可以進行優(yōu)化(注意如果生成IR代碼已經(jīng)做過優(yōu)化了此時在優(yōu)化不會再起作用)
命令:clang -Os -S -fobjc-arc main.m -o main.s -
生成目標文件(匯編器)
目標文件的生成,是匯編器以匯編代碼作為輸入,將匯編代碼轉換為機器代碼, 最后輸出目標文件(object file)
命令: clang -fmodules -c main.s -o main.o 可以發(fā)現(xiàn)是個Mach-O文件
通過nm命令,查看下main.o中的符號
命令: xcrun nm -nm main.o 發(fā)現(xiàn)找不到_printf這個方法,應為_printf是從外部的庫引入 -
生成可執(zhí)行文件(鏈接)
連接器把編譯產生的.o文件和(.dylib .a)文件,生成一個mach-o文件。
命令:clang main.o -o main 發(fā)現(xiàn)此時是一個可執(zhí)行的Mach-O文件
再查看鏈接之后的符號 應為OC的特性運行時,動態(tài)庫實在運行時需要使用的時候再加載到內存的,所以編一階段找不到對應的方法
-
-
-
LLVM編譯流程圖
作者:Potato_土豆
鏈接:https://juejin.cn/post/6959865646125416484
來源:稀土掘金
著作權歸作者所有。商業(yè)轉載請聯(lián)系作者獲得授權,非商業(yè)轉載請注明出處。
?
總結
以上是生活随笔為你收集整理的(三)Clang/ LLVM编译流程简述的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 用0和5凑被90整除的max数(洛谷P2
- 下一篇: 【面向对象】面向对象程序设计测试题12-