iOS LLVM及編譯過程

LLVM概述

  • LLVM 是以 C++ 編寫的架構編譯器(compiler)的框架系統
  • 從如下方面優化任意語言編寫的的程序
    • 編譯時間 compile time
    • 連接時間 link time
    • 運行時間 run time
    • 空閒時間 idle time

傳統編譯器設計

編譯器前端 Frontend

編譯器前端的任務是 解析源代碼前端

  • 檢查代碼正確性
    • 詞法分析
    • 語法分析
    • 語義分析
  • 構建抽象語法樹
  • LLVM的前端還會生成 中間代碼intermediate representationIR

優化器 Optimizer

優化器端的任務是改善代碼的運行時間,例如消除冗餘運算等。c++

編譯器後端 Backend / 代碼生成器CodeGenerator

  • 將代碼映射到目標指令集
  • 生成機器語言
  • 機器相關的代碼優化

iOS的編譯器架構

OCcc++ 使用的編譯器前端是clangSwift使用的是Swift;後端都是LLVM後端

LLVM的設計

傳統的編譯器設計把前端、優化器、後端集成在一塊兒,須要支持新語言或新硬件結構時就必須從新開發一套編譯器。LLVM的設計模式很好的解決了這種不便。設計模式

  • LLVM的編譯器前端會生成通用的中間代碼intermediate respresentation IR
  • 優化器對中間代碼處理不須要改變
  • 須要支持新語言時只須要單獨開發前端
  • 須要支持新架構時只須要單獨編寫後端

Clang

  • LLVM中的一個子項目
  • 基於LLVM的輕量級編譯器
  • 替代GCC,提供更快的編譯速度
  • 負責編譯OCCC++
  • LLVM架構的編譯器前端

編譯流程

打印編譯流程

clang -ccc-print-phases main.m 
複製代碼

  • 0、輸入文件:找到源文件
  • 一、預處理:包括替換宏和導入頭文件
  • 二、編譯階段:詞法分析、語法分析、語義分析,最終生成IR
  • 三、後端:經過一個個Pass去優化,每一個Pass完成一部分功能,最終生成彙編代碼
  • 四、生成目標文件
  • 五、連接:連接須要的動態庫和靜態庫,生成目標文件
  • 六、經過不一樣架構,生成對應的可執行文件

預處理

clang -E main.m
複製代碼

執行後能夠看到頭文件導入以及宏被替換。xcode

詞法分析

預處理後會進行詞法分析,詞法分析會把代碼切片成一個個tokenbash

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
複製代碼

生成中間代碼IR(intermediate representation)

處理完上述步驟,代碼生成器(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文件

  • IR基本語法
@       全局標示
%       局部標示
alloca  開闢空間
align   字節對齊
i32     32位,4字節
store   寫入內存
load    讀取數據
call    調用函數
ret     return
複製代碼

查看未優化的main.ll

優化後的main.ll

bitCode

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
複製代碼

執行可執行文件,能夠看見輸出了正確結果

相關文章
相關標籤/搜索