跳至內容

LLVM

本頁使用了標題或全文手工轉換
維基百科,自由的百科全書
LLVM
原作者Chris Lattner, Vikram Adve
開發者LLVM開發團隊
首次釋出2003年,​22年前​(2003
目前版本21.1.7[1]在維基數據編輯(2025年12月2日)
原始碼庫 編輯維基數據鏈結
程式語言C++
作業系統跨平台
類型編譯器
授權條款帶有LLVM例外的Apache授權條款2.0
網站www.llvm.org

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

它最早以C/C++為實作對象,而目前它已支援包括ActionScriptAdaD語言FortranGLSLHaskellJava位元組碼Objective-CSwiftPythonRubyCrystal英語Crystal (programming language)RustScala[2]Standard ML[3]以及C#[4]等語言。

歷史

[編輯]

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

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

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

自9.0.0版本開始,LLVM使用帶有LLVM額外條款的Apache授權條款2.0進行授權[9]。而從2019年10月開始,LLVM專案的代碼代管正式遷移到了GitHub[10]

描述

[編輯]

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

LLVM還可以在編譯、連結時生成可重定位代碼英語Relocation (computing)(Relocatable Code),甚至在執行時生成二進制機器碼。

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

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

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

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

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

組件

[編輯]

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

前端

[編輯]

LLVM最初被用來取代GCC中的程式碼產生器[17],許多GCC的前端已經可以與其運行,LLVM目前支援AdaC語言C++D語言FortranHaskellJuliaObjective-CRustSwift的編譯,它使用許多的編譯器,有些來自4.0.1及4.2的GCC

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

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

還有其他的元件在不同的開發階段,包含(但不限於)Java位元組碼[21]通用中間語言(CIL)、MacRuby英語MacRuby(Ruby 1.9實現)、Standard ML及新的圖著色暫存器分配器[22]

中間表示

[編輯]

LLVM的核心是中間表示(Intermediate Representation,IR),一種類似組譯的底層語言。IR是一種強型別精簡指令集(RISC),並對目標指令集進行了抽象。例如,目標指令集的函式呼叫慣例被抽象為callret指令加上明確的參數。另外,IR採用無限個數的暫存器,使用如%0%1等形式表達。LLVM支援三種表達形式:人類可讀的組譯格式,適合前端的在主記憶體中的格式和用作序列化的緊密bitcode格式。

例如,一個簡單的Hello World程式可以表達為如下的組譯形式。對IR語言的完整描述請參考LLVM官方文件[23]

@.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英語MLIR (software)[24],它通過採用叫做「方言」的外掛程式架構來幫助建造可重用且可延伸的編譯器下部構造[25]

後端

[編輯]

截至版本16,LLVM已經支援多種後端指令集,包括IA-32x86-64ARMQualcomm HexagonLoongArchM68KMIPSNvidia PTX英語Parallel Thread Execution(在LLVM文件中也稱為NVPTX)、PowerPCAMD TeraScale英語TeraScale (microarchitecture)[26]、新近的AMD GPU(在LLVM文件中也叫做AMDGPU)、SPARCSystemZRISC-Vz/Architecture英語z/ArchitectureXCore英語XMOS

LLVM還支援WebAssembly為其目標,使得編譯後的程式可以在啟用WebAssembly的環境中執行,比如Google Chrome/ChromiumFirefoxMicrosoft EdgeApple Safari或WAVM虛擬機器[27]。合規於LLVM的WebAssembly編譯器,典型的支援多種語言的幾乎不需修改的原始碼,包括:C、C++、D、Rust、Nim、Kotlin和其它一些語言。

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

連結器

[編輯]

lld連結器子專案旨在為LLVM開發一個內建的,平台獨立的連結器[28],去除對所有第三方連結器的依賴。在2017年5月,lld已經支援ELFPE/COFFMach-OWebAssembly。在lld支援不完全的情況下,使用者可以使用其他專案,如GNU ld連結器。 lld支援連結時最佳化。當LLVM連結時最佳化被啟用時,LLVM可以輸出bitcode而不是本機代碼,而本機代碼生成由連結器最佳化處理。

C++標準庫

[編輯]

LLVM專案包含一個C++標準庫的實現(libcxx),具有MIT授權條款UIUC授權條款英語University of Illinois/NCSA Open Source License的雙授權條款。[29]

另見

[編輯]

參考文獻

[編輯]
  1. ^ Release 21.1.7. 2025年12月2日 [2025年12月2日]. 
  2. ^ Reedy, Geoff. Compiling Scala to LLVM. St. Louis, Missouri, United States. 2012-09-24 [2013-02-19]. (原始內容存檔於2020-11-29). 
  3. ^ Standard ML of New Jersey Release Notes Version 2021.1. The MLRISC code generator that we have used for over 25 years has been replaced with one based on the LLVM Libraries. 
    LLVMCodegen. MLton. [26 November 2024]. 
  4. ^ Mono LLVM, [2013-03-10], (原始內容存檔於2020-06-15) 
  5. ^ Adam Treat, mkspecs and patches for LLVM compile of Qt4頁面存檔備份,存於網際網路檔案館
  6. ^ 存档副本. [2011-12-22]. (原始內容存檔於2012-01-17). 
  7. ^ Chris Lattner discusses the name LLVM. [22 December 2011]. (原始內容存檔於2012年1月12日). 
  8. ^ ACM Awards. ACM. [2013-04-28]. (原始內容存檔於2012-04-02). 
  9. ^ LLVM 9.0.0 License. [2020-11-14]. (原始內容存檔於2020-11-11). 
  10. ^ Migration Proposal. [2020-11-14]. (原始內容存檔於2020-11-25). 
  11. ^ LLVM Language Reference Manual. [16 April 2012]. (原始內容存檔於2012-06-11). 
  12. ^ Chris Lattner. A cool use of LLVM at Apple: the OpenGL stack. LLVMdev mailing list. 15 August 2006 [26 October 2008]. (原始內容存檔於2006年11月4日). 
  13. ^ Michael Larabel, "GNOME Shell Works Without GPU Driver Support"頁面存檔備份,存於網際網路檔案館), phoronix, 6 November 2011
  14. ^ V. Makarov. SPEC2000: Comparison of LLVM-2.9 and GCC4.6.1 on x86. [3 October 2011]. (原始內容存檔於2020-08-03). 
  15. ^ V. Makarov. SPEC2000: Comparison of LLVM-2.9 and GCC4.6.1 on x86_64. [3 October 2011]. (原始內容存檔於2020-08-03). 
  16. ^ Michael Larabel. LLVM/Clang 3.2 Compiler Competing With GCC. 27 December 2012 [31 March 2013]. (原始內容存檔於2020-11-30). 
  17. ^ Lattner, Chris; Vikram Adve. Architecture For a Next-Generation GCC. First Annual GCC Developers' Summit. May 2003 [6 September 2009]. (原始內容存檔於2020-07-07). 
  18. ^ Clang 3.8 Release Notes. [August 24, 2016]. (原始內容存檔於2016-10-31). 
  19. ^ Compiling Haskell To LLVM (PDF). [26 June 2008]. (原始內容存檔 (PDF)於2016-08-06). 
  20. ^ LLVM Project Blog: The Glasgow Haskell Compiler and LLVM. [13 August 2010]. (原始內容存檔於2011-06-25). 
  21. ^ Gaël Thomas; et al. VMKit: a substrate for virtual machines. LLVM.org. [2014-09-17]. (原始內容存檔於2020-11-09).  VMKit 目前的開發已經停滯,並且只支援和 LLVM 3.3 協同編譯。對更高版本的 LLVM,需要對原始碼做一些修改。VMKit 在編譯時需要 LLVM 原始碼中的lib, include
  22. ^ Jakob Stoklund Olesen. Register Allocation in LLVM 3 (PDF). 
  23. ^ llvm.org/docs/LangRef.html.
  24. ^ MLIR. mlir.llvm.org. [2022-06-07]. 
  25. ^ Dialects - MLIR. mlir.llvm.org. [2022-06-07]. 
  26. ^ Stellard, Tom. [LLVMdev] RFC: R600, a new backend for AMD GPUs. llvm-dev (郵寄清單). March 26, 2012 [2019-02-18]. (原始內容存檔於2020-12-01). 
  27. ^ WAVM is a WebAssembly virtual machine, designed for use in non-browser applications. 
  28. ^ lld - The LLVM Linker. The LLVM Project. [May 10, 2017]. (原始內容存檔於2020-12-29). 
  29. ^ "libc++" C++ Standard Library. [2020-09-26]. (原始內容存檔於2017-04-29). 

外部連結

[編輯]