LLVM

是一套編譯器基礎設施專案，為自由軟體，以 C++ 寫成，包含一系列模組化的編譯器元件和工具鏈，用來開發編譯器前端和後端。它是為了任意一種程式語言而寫成的程式，利用虛擬技術創造出編譯時期、鏈結時期、執行時期以及 “閒置時期” 的最佳化。

它最早以 C/C++ 為實作物件，而目前它已支援包括 ActionScript、Ada、D 語言、Fortran、GLSL、Haskell、Java 位元組碼、Objective-C、Swift、Python、Ruby、Crystal、Rust、Scala 以及 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 允許靜態編譯程式碼，或者透過即時編譯（JIT）機制將中間表示轉換為機器碼（類似 Java）。

LLVM 支援與語言無關的指令集架構及型別系統。每個指令都處在靜態單賦值形式（SSA）下代表著，每個變數（被稱為具有型別的暫存器）僅被賦值一次，這簡化了變數間相依性的分析。LLVM 允許程式碼被靜態的編譯，包含在傳統的 GCC 系統底下，或是類似 JAVA 等後期編譯才將 IF 編譯成機器碼所使用的即時編譯（JIT）技術。它的型別系統包含基本型別（整數或是浮點數）及五個複合型別（指標、陣列、向量、結構及函式），在 LLVM 具體語言的型別建制可以以結合基本型別來表示，舉例來說，C++ 所使用的 class 可以被表示為結構、函式及函式指標的陣列所組成。

LLVM JIT 編譯器可以最佳化在執行時期時程式所不需要的靜態分支，這在一些部份求值（Partial Evaluation）的案例中相當有效，即當程式有許多選項，而在特定環境下其中多數可被判斷為是不需要。這個特色被使用在 Mac OS X Leopard（v10.5）底下 OpenGL 的管線，當硬體不支援某個功能時依然可以被成功地運作。OpenGL 堆疊下的繪圖程式被編譯為 IR，接著在機器上執行時被編譯，當系統擁有高階 GPU 時，這段程式會進行極少的修改並將傳遞指令給 GPU，當系統擁有低階的 GPU 時，LLVM 將會編譯更多的程式，使這段 GPU 無法執行的指令在本地端的中央處理器執行。LLVM 增進了使用 Intel GMA 晶片等低端機器的效能。一個類似的系統發展於 Gallium3D LLVMpipe，它已被合併到 GNOME，使其可執行在沒有 GPU 的環境。

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

編譯器

LLVM 已經成為多個編譯器和程式碼生成相關子專案的母專案。

3.1 前端

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 bytecode、通用中間語言（CIL）、MacRuby（實現 Ruby 1.9）、Standard ML 及新的 graph coloring 暫存器配置.

3.2 中間表示

LLVM 的核心是中間表示（Intermediate Representation，IR），一種類似彙編的底層語言。IR 是一種強型別的精簡指令集（Reduced Instruction Set Computing，RISC），並對目標指令集進行了抽象。例如，目標指令集的函式呼叫慣例被抽象為 call 和 ret 指令加上明確的引數。另外，IR 採用無限個數的暫存器，使用如 %0，%1 等形式表達。LLVM 支援三種表達形式：人類可讀的彙編，在 C++ 中物件形式和序列化後的 bitcode 形式。

例如，一個簡單的 Hello World 程式可以表達為如下的彙編形式。對 IR 語言的完整描述請參考 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

}

3.3 後端

至 11.0 版本，LLVM 已經支援多種後端指令集，包括 ARM、、MIPS、Nvidia 並行指令集（LLVM 中稱為 NVPTX），PowerPC、AMD TeraScale、、SPARC、SystemZ、RISC-V、WebAssembly、x86、x86-64 和 XCore。

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

3.4 連結器

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

lld 支援連結時最佳化。當 LLVM 連結時最佳化被啟用時，LLVM 可以輸出 bitcode 而不是本機程式碼，而本機程式碼生成由連結器最佳化處理。

3.5 C++ 標準庫

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