LLVM

LLVM是一套編譯器基礎設施項目，為自由軟體，以C++寫成，包含一系列模塊化的編譯器組件和工具鏈，用來開發編譯器前端和後端。任意一種程式語言通過它實作出來的編譯器，都能利用上它在編譯時期、鏈結時期、執行時期以及「閒置時期」進行的最佳化。

它最早以C/C++為實作對象，而目前它已支援包括ActionScript、Ada、D語言、Fortran、GLSL、Haskell、Java字節碼、Objective-C、Swift、Python、Ruby、Crystal (程式語言)、Rust、Scala、Standard ML以及C#等語言。

## 歷史

LLVM專案的發展起源於2000年伊利諾伊大學厄巴納-香檳分校的維克拉姆·艾夫（Vikram Adve）與克里斯·拉特納（Chris Lattner）的研究，他們想要為所有靜態及動態語言創造出動態的編譯技術。LLVM是以BSD授權來發展的開源軟體。2005年，蘋果電腦雇用了克里斯·拉特納及他的團隊為蘋果電腦開發應用程式系統，LLVM為現今macOS及iOS開發工具的一部分。

LLVM的命名最早源自於底層虛擬機器（Low Level Virtual Machine）的首字母縮寫，由於這個專案的範圍並不侷限於建立一個虛擬機器，這個縮寫導致了廣泛的疑惑。LLVM開始成長之後，成為眾多編譯工具及低階工具技術的統稱，使得這個名字變得更不貼切，開發者因而決定放棄這個縮寫的意涵，現今LLVM已單純成為一個系統，適用於LLVM下的所有專案，包含LLVM中間表示（LLVM IR）、LLVM除錯工具、LLVM C++標準函式庫等。

因LLVM對產業的貢獻，電腦協會於2012年將ACM軟體系統獎授與維克拉姆·艾夫、克里斯·拉特納和Evan Cheng。

自9.0.0版本開始，LLVM使用帶有LLVM額外條款的Apache許可證2.0進行授權。而從2019年10月開始，LLVM項目的代碼託管正式遷移到了GitHub。

## 描述

LLVM提供了一套適合編譯器系統的中間表示（Intermediate Representation，IR），有大量變換和優化都圍繞其實現。經過變換和優化後的中間語言，可以轉換為目標平台相關的彙編語言代碼。LLVM可以和GCC工具鏈一起工作，允許它與為該項目編寫的大量現有編譯器一起使用。

LLVM還可以在編譯、連結時生成重定位（Relocatable Code），甚至在運行時生成二進位機器碼。

LLVM支援與語言無關的指令集架構及類型系統。每個指令都處在靜態單賦值形式（SSA）下代表著，每個變數（被稱為具有型別的暫存器）僅被賦值一次，這簡化了變數間相依性的分析。LLVM允許程式碼遵循傳統GCC系統的方式而被靜態的編譯，或者以類似JAVA等後期編譯的方式，通過即時編譯（JIT）將IF編譯成機器碼。

LLVM的型別系統包含基本型別（整數或是浮點數）及五個複合型別（指標、陣列、向量、結構及函數），具體語言的型別，可以在LLVM中用基本型別的組合來表示，舉例來說，C++所使用的類，可以被表示為結構、函數和函數指針的陣列的混合。

LLVM JIT編譯器可以最佳化程式在執行期之時去除所不需要的靜態分支，這在一些部份求值（Partial Evaluation）的案例中相當有效，即當程式有許多選項，而在特定環境下其中多數可被判斷為是不需要的。這個特色被使用在Mac OS X Leopard（v10.5）底下OpenGL的管線，當硬體不支援某個功能時依然可以被成功地運作。

OpenGL堆棧下的繪圖程式被編譯為中間表示，接著在機器上執行時被編譯，當系統擁有高階GPU時，這段程式會進行極少的修改並將傳遞指令給GPU，當系統擁有低階的GPU時，LLVM將會編譯更多的程序，使這段GPU無法執行的指令在本地端的中央處理器執行。LLVM增進了使用Intel GMA晶片等低端機器的效能。一個類似的系統發展於Gallium3D LLVMpipe，它已被合併到GNOME，使其可運行在沒有GPU的環境。

根據2011年的一項測試，GCC在執行時期的性能平均比LLVM高10%。而2013年測試顯示，LLVM可以編譯出接近GCC相同效能的執行碼。

## 組件

LLVM已經成為多個編譯器和代碼生成相關子項目的母項目。

### 前端

LLVM最初被用來取代GCC中的程式碼產生器，許多GCC的前端已經可以與其運行，LLVM目前支援Ada、C語言、C++、D語言、Fortran、Haskell、Julia、Objective-C、Rust及Swift的編譯，它使用許多的編譯器，有些來自4.0.1及4.2的GCC。

LLVM引發一些人來為許多語言開發新的編譯器，其中一個最引發注意的就是Clang，它是一個新的編譯器，同時支援C、Objective-C以及C++。主要來自蘋果電腦的支持，Clang的目的用以取代GCC系統底下的C/Objective-C編譯器，在當代的系統，他較為容易與集成開發環境（IDE）整合，而且對於線程有更好的支援。Clang從3.8版本開始已經支持OpenMP。GCC底下Objective-C的開發已經停滯，而蘋果電腦已經將其支援移至其他的維護分支。

Utrecht Haskell編譯器可以產生LLVM使用的程式碼，但它還在初期的開發階段，並且在許多案例，展示他比起C程式碼產生器擁有更好的效率Glasgow Haskell Compiler（GHC）擁有一個可以運作的LLVM後端，程式執行效能對比起原先的編譯器可以達到30%的加速，它僅比一個由GHC所實現，並擁有多項最佳化技術的編譯器還慢

還有其他的元件在不同的開發階段，包含（但不限於）Java字節碼、通用中間語言（CIL）、MacRuby（Ruby 1.9實現）、Standard ML及新的圖著色寄存器分配器。

### 中間表示

LLVM的核心是中間表示（Intermediate Representation，IR），一種類似彙編的底層語言。IR是一種強類型的精簡指令集（RISC），並對目標指令集進行了抽象。例如，目標指令集的函數調用慣例被抽象為`call`和`ret`指令加上明確的參數。另外，IR採用無限個數的暫存器，使用如`%0`，`%1`等形式表達。LLVM支持三種表達形式：人類可讀的彙編格式，適合前端的在記憶體中的格式和用作序列化的緊密bitcode格式。

例如，一個簡單的Hello World程序可以表達為如下的彙編形式。對IR語言的完整描述請參考LLVM官方文檔：

```llvm
@.str = internal constant [14 x i8] c"hello, world\0A\00"

declare i32 @printf(i8*, ...)

define i32 @main(i32 %argc, i8** %argv) nounwind {
entry:
    %tmp1 = getelementptr [14 x i8], [14 x i8]* @.str, i32 0, i32 0
    %tmp2 = call i32 (i8*, ...) @printf( i8* %tmp1 ) nounwind
    ret i32 0
}
```

LLVM計劃還介入了另一種類型的中間表示名為MLIR編譯器框架，它通過採用叫做「方言」的插件架構來幫助建造可重用且可擴展的編譯器下部構造。

### 後端

截至版本16，LLVM已經支持多種後端指令集，包括IA-32、x86-64、ARM、Qualcomm Hexagon、LoongArch、M68K、MIPS、Nvidia 並行線程執行（在LLVM文檔中也稱為NVPTX）、PowerPC、AMD TeraScale微架構、新近的AMD GPU（在LLVM文檔中也叫做AMDGPU）、SPARC、SystemZ、RISC-V、z/Architecture和XMOS。

LLVM還支持WebAssembly為其目標，使得編譯後的程序可以在啟用WebAssembly的環境中運行，比如Google Chrome/Chromium、Firefox、Microsoft Edge、Apple Safari或WAVM虛擬機。合規於LLVM的WebAssembly編譯器，典型的支持多種語言的幾乎不需修改的原始碼，包括：C、C++、D、Rust、Nim、Kotlin和其它一些語言。

LLVM包含一個專門的MC模塊，將機器指令在文字形式和機器碼形式間相互轉換。在之前LLVM依靠系統或是平台專門的工具鏈將彙編翻譯為機器碼。LLVM機器碼的集成彙編器已經支持絕大多數LLVM的目標平台。

### 連結器

lld連結器子項目旨在為LLVM開發一個內置的，平台獨立的連結器，去除對所有第三方連結器的依賴。在2017年5月，lld已經支持ELF、PE/COFF、Mach-O和WebAssembly。在lld支持不完全的情況下，使用者可以使用其他項目，如GNU ld連結器。

lld支持連結時優化。當LLVM連結時優化被啟用時，LLVM可以輸出bitcode而不是本機代碼，而本機代碼生成由連結器優化處理。

### C++標準庫

LLVM項目包含一個C++標準庫的實現（libcxx），具有MIT許可證和UIUC許可證的雙許可協議。

## 外部連結

- LLVM計劃官方網站
- LLVM Project Blog
- LLVM: A Compilation Framework for Lifelong Program Analysis & Transformation —a published paper by Chris Lattner and Vikram Adve.
- LLVM Language Reference Manual —describes the LLVM intermediate representation.
- LLVM 2.0 Presentation —Google Tech Talk Presentation on LLVM 2.0
- Discussion of LLVM by John Siracusa at Ars Technica
- LLVM內部結構（The Architecture of Open Source Applications, Volume II - ISBN 9781105571817）
- LLVMLinux專案

## 基本資料

- 作者：Chris Lattner, Vikram Adve
- 開發者：LLVM開發團隊
- 發行日期：2003年
- 軟體版本週期：22.1.8
- 預覽版本：22.1.8
- 作業系統：跨平台
- 類型：編譯器
- 程式語言：C++
- 許可協議：帶有LLVM例外的Apache許可證2.0