LLVM
是以 C++
編寫的架構編譯器(compiler
)的框架系統compile time
link time
run time
idle time
Frontend
編譯器前端的任務是 解析源代碼前端
LLVM
的前端還會生成 中間代碼(intermediate representation
,IR)Optimizer
優化器端的任務是改善代碼的運行時間,例如消除冗餘運算等。c++
Backend
/ 代碼生成器CodeGenerator
OC
、c
、c++
使用的編譯器前端是clang
;Swift
使用的是Swift
;後端都是LLVM
。 後端
傳統的編譯器設計把前端、優化器、後端集成在一塊兒,須要支持新語言或新硬件結構時就必須從新開發一套編譯器。LLVM
的設計模式很好的解決了這種不便。設計模式
LLVM
的編譯器前端會生成通用的中間代碼(intermediate respresentation
IR)LLVM
中的一個子項目LLVM
的輕量級編譯器GCC
,提供更快的編譯速度OC
、C
、C++
LLVM
架構的編譯器前端clang -ccc-print-phases main.m
複製代碼
clang -E main.m
複製代碼
執行後能夠看到頭文件導入以及宏被替換。xcode
預處理後會進行詞法分析,詞法分析會把代碼切片成一個個token
。bash
clang -fmodules -fsyntax-only -Xclang -dump-tokens main.m
複製代碼
執行後能夠看到每一個詞(token
)所在的位置架構
語法分析會驗證語法是否正確,在詞法分析的基礎上把單詞組合成各類語法短語,而後把節點組成抽象的語法樹(Abstract Syntax Tree,AST)框架
clang -fmodules -fsyntax-only -Xclang -ast-dump main.m
複製代碼
若是找不到頭文件,能夠手動導入SDK函數
clang -isysroot SDK路徑 -fmodules -fsyntax-only -Xclang -ast-dump main.m
複製代碼
處理完上述步驟,代碼生成器(Core Generator
)會根據語法樹自頂向下生成LLVM IR
。OC會在這裏進行runtime
的橋接:property
的合成、ARC
處理等。優化
clang -S -fobjc-arc -emit-llvm main.m
複製代碼
LLVM
的優化級別有 -O0
-O1
-O2
-O3
-Os
clang -Os -S -fobjc-arc -emit-llvm main.m
複製代碼
執行指令能夠獲得.ll
文件
@ 全局標示
% 局部標示
alloca 開闢空間
align 字節對齊
i32 32位,4字節
store 寫入內存
load 讀取數據
call 調用函數
ret return
複製代碼
查看未優化的main.ll
優化後的main.ll
xcode7
之後開啓了bitCode
,蘋果對代碼作了進一步優化並生成.bc
文件。經過.ll
文件生成.bc
文件。
clang -emit-llvm -c main.ll -o main.bc
複製代碼
能夠經過.bc
或.ll
文件生成彙編代碼
clang -S -fobjc-arc main.bc -o main.s
clang -S -fobjc-arc main.ll -o main.s
複製代碼
生成彙編代碼的時候也能夠進行優化
clang -Os -S -fobjc-arc main.bc -o main.s
複製代碼
輸入彙編代碼,轉化成機器代碼,最後輸出目標文件。
clang -fmodules -c main.s -o main.o
複製代碼
查看main.o中的符號
xcrun nm -nm main.o
複製代碼
能夠看到print
函數、test
函數、main
函數
_printf
能夠看到 undefined extranal
標示undefined
表明它在當前文件找不到extranal
表明它能夠外部訪問把編譯的.o
文件和dylib.a
文件鏈接,生成mach-o
文件
clang main.o -o main
複製代碼
執行可執行文件,能夠看見輸出了正確結果