LLVM 是一個(gè)模塊化和可重用的編譯器和工具鏈技術(shù)的集合渔扎,創(chuàng)始人是 Chris Lattner盹舞,也是Swift之父
Clang 是 LLVM 的子項(xiàng)目像樊,是 C眷唉,C++ 和 Objective-C 編譯器予颤,因?yàn)槎嗄K的復(fù)用,所以提供了驚人的快速編譯冬阳,比 GCC 快3倍蛤虐。
LLVM的子項(xiàng)目
-
LLVM Core
提供了一個(gè)現(xiàn)代的源代碼和目標(biāo)獨(dú)立優(yōu)化器, 以及許多流行的 CPU (甚至是一些不太常見(jiàn)的處理器) 的匯編代碼生成支持。 -
Clang
一個(gè) C/C++/Objective-C 編譯器肝陪,致力于提供令人驚訝的快速編譯驳庭,極其有用的錯(cuò)誤和警告信息,提供一個(gè)可用于構(gòu)建很棒的源代碼級(jí)別的工具氯窍。 -
Dragonegg
GCC 插件饲常,可將 GCC 的優(yōu)化和代碼生成器替換為 LLVM 的相應(yīng)工具。 -
LLDB
基于LLVM提供的庫(kù)和Clang構(gòu)建的優(yōu)秀的本地調(diào)試器狼讨。 -
libc++贝淤、libc++ ABI
符合標(biāo)準(zhǔn)的,高性能的C++標(biāo)準(zhǔn)庫(kù)實(shí)現(xiàn)政供,以及對(duì) C++11 的完整支持播聪。 -
compiler-rt
針對(duì) __fixunsdfdi 和其他目標(biāo)機(jī)器上沒(méi)有一個(gè)核心 IR(intermediate representation) 對(duì)應(yīng)的短原生指令序列時(shí)朽基,提供高度調(diào)優(yōu)過(guò)的底層代碼生成支持。 -
OpenMP
Clang 中對(duì)多平臺(tái)并行編程的runtime支持离陶。 -
Vmkit
基于 LLVM 的 Java 和 .NET 虛擬機(jī)實(shí)現(xiàn)稼虎。 -
Polly
支持高級(jí)別的循環(huán)和數(shù)據(jù)本地化優(yōu)化支持的 LLVM 框架。 -
libclc
OpenCL 標(biāo)準(zhǔn)庫(kù)的實(shí)現(xiàn) -
Klee
基于 LLVM 編譯基礎(chǔ)設(shè)施的符號(hào)化虛擬機(jī) -
SAFECode
內(nèi)存安全的C/C++編譯器 -
lld
Clang/LLVM 內(nèi)置的鏈接器
傳統(tǒng)的編譯器架構(gòu)
Frontend
: 前端, 詞法分析, 語(yǔ)法分析, 語(yǔ)義分析, 生成中間代碼Optimizer
: 優(yōu)化器, 中間代碼優(yōu)化Backend
: 后端, 生成機(jī)器碼
LLVM架構(gòu)
- 不同的前端后端使用統(tǒng)一的中間代碼
LLVM Intermediate Representation (LLVM IR)
- 如果需要支持一種新的編程語(yǔ)言招刨,那么只需要實(shí)現(xiàn)一個(gè)新的前端
- 如果需要支持一種新的硬件設(shè)備霎俩,那么只需要實(shí)現(xiàn)一個(gè)新的后端
-
LLVM
現(xiàn)在被作為實(shí)現(xiàn)各種靜態(tài)和運(yùn)行時(shí)編譯語(yǔ)言的通用基礎(chǔ)結(jié)構(gòu)(GCC家族、Java计济、.NET茸苇、Python、Ruby沦寂、Scheme学密、Haskell、D等)
Clang與LLVM
1. App編譯過(guò)程
文件: main.m
#include <stdio.h>
#define Num 10
int main(int argc, const char * argv[]) {
int a = 10;
int b = 20;
int c = a + b + Num;
return 0
}
在命令行中輸入
通過(guò)命令可看到編譯文件需要經(jīng)歷的幾個(gè)過(guò)程
$ clang -ccc-print-phases main.m
- 預(yù)編譯處理
主要包括宏的替換, 頭文件的導(dǎo)入,也包含如下
“#define”
“#include”
“#indef”
注釋
“#pragma”
查看preprocessor(預(yù)處理)的結(jié)果
$ clang -E main.m
- 詞法分析
編譯器會(huì)將代碼切成一個(gè)個(gè)Token,如下幾類(lèi)
- 關(guān)鍵字:語(yǔ)法中的關(guān)鍵字传藏,if else while for 等腻暮。
- 標(biāo)識(shí)符:變量名
- 字面量:值,數(shù)字毯侦,字符串
- 特殊符號(hào):加減乘除等符號(hào)
$ clang -fmodules -E -Xclang -dump-tokens main.m
- 語(yǔ)法分析
將 token 先按照語(yǔ)法, 組合成語(yǔ)義生成 VarDecl 節(jié)點(diǎn)哭靖,然后將這些節(jié)點(diǎn)按照層級(jí)關(guān)系構(gòu)成抽象語(yǔ)法樹(shù) Abstract Syntax Tree (AST)
$ clang -fmodules -fsyntax-only -Xclang -ast-dump main.m
- LLVM IR中間代碼生成.
- CodeGen 會(huì)負(fù)責(zé)將語(yǔ)法樹(shù)自頂向下遍歷逐步翻譯成 LLVM IR,
IR 是編譯過(guò)程的前端的輸出, 后端的輸入 - 將語(yǔ)法樹(shù)翻譯成 LLVM IR 中間代碼侈离,作為 LLVM Backend 輸入的橋接語(yǔ)言试幽。方便 LLVM Backend 給多語(yǔ)言做相同的優(yōu)化,做到語(yǔ)言無(wú)關(guān)卦碾。
這個(gè)過(guò)程中還會(huì)跟 runtime 橋接
- 各種類(lèi)铺坞,方法,成員變量等的結(jié)構(gòu)體的生成洲胖,并將其放到對(duì)應(yīng)的 Mach-O的section中济榨。
- Non-Fragile ABI 合成 OBJC_IVAR_$_ 偏移值常量。
- ObjCMessageExpr 翻譯成相應(yīng)版本的 objc_msgSend绿映,super 翻譯成 objc_msgSendSuper擒滑。
- strong,weak叉弦,copy丐一,atomic 合成 @property 自動(dòng)實(shí)現(xiàn) setter 和 getter。
- @synthesize 的處理卸奉。
- 生成 block_layout 數(shù)據(jù)結(jié)構(gòu)
- __block 和 __weak
- _block_invoke
- ARC 處理钝诚,插入 objc_storeStrong 和 objc_storeWeak 等 ARC 代碼。ObjCAutoreleasePoolStmt 轉(zhuǎn) objc_autorealeasePoolPush / Pop榄棵。自動(dòng)添加 [super dealloc]凝颇。給每個(gè) ivar 的類(lèi)合成 .cxx_destructor 方法自動(dòng)釋放類(lèi)的成員變量。
-
LLVM IR
有3種表示形式(但本質(zhì)是等價(jià)的疹鳄,就好比水可以有氣體拧略、液體、固體3種形態(tài)) - text:便于閱讀的文本格式瘪弓,類(lèi)似于匯編語(yǔ)言垫蛆,拓展名.ll,
$ clang -S -emit-llvm main.m
會(huì)在當(dāng)前目錄下生成.||文件, 使用SublineText ActionScript語(yǔ)言打開(kāi)顯示
- memory:內(nèi)存格式
- bitcode:二進(jìn)制格式腺怯,拓展名.bc袱饭,
$ clang -c -emit-llvm main.m
- IR輸入到后端, 生成匯編文件
- 生成目標(biāo)文件
- link目標(biāo)文件,生成可執(zhí)行文件
編譯App完整步驟
下面是完整步驟:
* 編譯信息寫(xiě)入輔助文件,創(chuàng)建文件架構(gòu) .app 文件
* 處理文件打包信息
* 執(zhí)行 CocoaPod 編譯前腳本呛占,checkPods Manifest.lock
* 編譯.m文件虑乖,使用 CompileC 和 clang 命令
* 鏈接需要的 Framework
* 編譯 xib
* 拷貝 xib ,資源文件
* 編譯 ImageAssets
* 處理 info.plist
* 執(zhí)行 CocoaPod 腳本
* 拷貝標(biāo)準(zhǔn)庫(kù)
* 創(chuàng)建 .app 文件和簽名
Codegen 機(jī)器碼生成器
問(wèn)題
LLVM編譯一個(gè)源文件的過(guò)程:
預(yù)處理 -> 詞法分析 -> Token -> 語(yǔ)法分析 - > AST樹(shù) -> 代碼生成 -> LLVM IR -> 優(yōu)化 -> 生成匯編代碼 -> Link -> 目標(biāo)文件基于LLVM, 我們可以做什么
a. 做語(yǔ)法樹(shù)分析, 實(shí)現(xiàn)語(yǔ)言轉(zhuǎn)換, 入如OC轉(zhuǎn)Swift, JS 或 其他語(yǔ)言
b. 編寫(xiě)ClangPlugin, 用于代碼的命名規(guī)范, 編寫(xiě)規(guī)范
c. 編寫(xiě)Pass, 代碼混淆優(yōu)化.
參考自 :
戴銘LLVM文章
戴銘segmentfault課
Clang 之路——編寫(xiě)我的第一個(gè) Clang 插件:檢測(cè) ObjC 中的類(lèi)聲明規(guī)范