LLVM
LLVM是一套編譯器基礎設施項目,為自由軟件,以C++寫成,包含一系列模塊化的編譯器組件和工具鏈,用來開發編譯器前端和後端。它是為了任意一種程式語言而寫成的程式,利用虛擬技術創造出編譯時期、鏈結時期、執行時期以及「閒置時期」的最佳化。
原作者 | Chris Lattner, Vikram Adve |
---|---|
開發者 | LLVM開發團隊 |
首次發布 | 2003 |
當前版本 | 19.1.3[1](2024年10月30日) |
源代碼庫 | |
編程語言 | C++ |
操作系統 | 跨平台 |
類型 | 編譯器 |
許可協議 | 帶有LLVM例外的Apache許可證2.0 |
網站 | www |
它最早以C/C++為實作對象,而目前它已支援包括ActionScript、Ada、D語言、Fortran、GLSL、Haskell、Java字節碼、Objective-C、Swift、Python、Ruby、Crystal、Rust、Scala[2]以及C#[3]等語言。
歷史
LLVM專案的發展起源於2000年伊利諾伊大學厄巴納-香檳分校維克拉姆·艾夫(Vikram Adve)與克里斯·拉特納(Chris Lattner)的研究,他們想要為所有靜態及動態語言創造出動態的編譯技術。LLVM是以BSD授權來發展的開源軟體。2005年,蘋果電腦雇用了克里斯·拉特納及他的團隊為蘋果電腦開發應用程式系統[4],LLVM為現今macOS及iOS開發工具的一部分。
LLVM的命名最早源自於底層虛擬機器(Low Level Virtual Machine)的首字母縮寫[5],由於這個專案的範圍並不侷限於建立一個虛擬機器,這個縮寫導致了廣泛的疑惑。LLVM開始成長之後,成為眾多編譯工具及低階工具技術的統稱,使得這個名字變得更不貼切,開發者因而決定放棄這個縮寫的意涵[6],現今LLVM已單純成為一個系統,適用於LLVM下的所有專案,包含LLVM中介碼(LLVM IR)、LLVM除錯工具、LLVM C++標準函式庫等。
因LLVM對產業的貢獻,計算機協會於2012年將ACM軟件系統獎授與維克拉姆·艾夫、克里斯·拉特納及Evan Cheng[7]。
自9.0.0版本開始,LLVM使用帶有LLVM額外條款的Apache許可證2.0進行授權[8]。而從2019年10月開始,LLVM項目的代碼託管正式遷移到了GitHub[9]。
描述
LLVM提供了一套適合編譯器系統的中間語言(Intermediate Representation,IR),有大量變換和優化都圍繞其實現。經過變換和優化後的中間語言,可以轉換為目標平台相關的匯編語言代碼。LLVM可以和GCC工具鏈一起工作,允許它與為該項目編寫的大量現有編譯器一起使用。LLVM還可以在編譯、鏈接時生成可重定位代碼(Relocatable Code),甚至在運行時生成二進制機器碼。
LLVM的中間語言與具體的語言、指令集、類型系統無關,其中每條指令都是靜態單賦值形式(SSA), 即每個變量只能被賦值一次。這有助於簡化變量之間的依賴分析。LLVM允許靜態編譯代碼,或者通過實時編譯(JIT)機制將中間表示轉換為機器碼(類似Java)。
LLVM支援與語言無關的指令集架構及類型系統[10]。每個指令都處在靜態單賦值形式(SSA)下代表著,每個變數(被稱為具有型別的暫存器)僅被賦值一次,這簡化了變數間相依性的分析。LLVM允許程式碼被靜態的編譯,包含在傳統的GCC系統底下,或是類似JAVA等後期編譯才將IF編譯成機器碼所使用的即時編譯(JIT)技術。它的型別系統包含基本型別(整數或是浮點數)及五個複合型別(指標、數組、向量、結構及函數),在LLVM具體語言的型別建制可以以結合基本型別來表示,舉例來說,C++所使用的class可以被表示為結構、函式及函數指針的陣列所組成。
LLVM JIT編譯器可以最佳化在執行時期時程式所不需要的靜態分支,這在一些部份求值(Partial Evaluation)的案例中相當有效,即當程式有許多選項,而在特定環境下其中多數可被判斷為是不需要。這個特色被使用在Mac OS X Leopard(v10.5)底下OpenGL的管線,當硬體不支援某個功能時依然可以被成功地運作[11]。OpenGL堆棧下的繪圖程式被編譯為IR,接著在機器上執行時被編譯,當系統擁有高階GPU時,這段程式會進行極少的修改並將傳遞指令給GPU,當系統擁有低階的GPU時,LLVM將會編譯更多的程序,使這段GPU無法執行的指令在本地端的中央處理器執行。LLVM增進了使用Intel GMA晶片等低端機器的效能。一個類似的系統發展於Gallium3D LLVMpipe,它已被合併到GNOME,使其可運行在沒有GPU的環境[12]。
根據2011年的一項測試,GCC在執行時期的性能平均比LLVM高10%[13][14]。而2013年測試顯示,LLVM可以編譯出接近GCC相同效能的執行碼[15]。
編譯器
LLVM已經成為多個編譯器和代碼生成相關子項目的母項目。
前端
LLVM最初被用來取代GCC中的程式碼產生器[16],許多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[17]。GCC底下Objective-C的開發已經停滯,而蘋果電腦已經將其支援移至其他的維護分支。
Utrecht Haskell編譯器可以產生LLVM使用的程式碼,但它還在初期的開發階段,並且在許多案例,展示他比起C程式碼產生器擁有更好的效率[18] Glasgow Haskell Compiler(GHC)擁有一個可以運作的LLVM後端,程式執行效能對比起原先的編譯器可以達到30%的加速,它僅比一個由GHC所實現,並擁有多項最佳化技術的編譯器還慢[19]
還有其他的元件在不同的開發階段,包含(但不限於)Java bytecode[20]、通用中間語言(CIL)、MacRuby(實現Ruby 1.9)、Standard ML及新的graph coloring暫存器配置. [來源請求]
中間表示
LLVM的核心是中間表示(Intermediate Representation,IR),一種類似匯編的底層語言。IR是一種強類型的精簡指令集(Reduced Instruction Set Computing,RISC),並對目標指令集進行了抽象。例如,目標指令集的函數調用慣例被抽象為call和ret指令加上明確的參數。另外,IR採用無限個數的暫存器,使用如%0,%1等形式表達。LLVM支持三種表達形式:人類可讀的匯編,在C++中對象形式和序列化後的bitcode形式。
例如,一個簡單的Hello World程序可以表達為如下的匯編形式。對IR語言的完整描述請參考LLVM官方文檔[21]:
@.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
}
後端
至11.0版本,LLVM已經支持多種後端指令集,包括ARM、Qualcomm Hexagon、MIPS、Nvidia並行指令集(LLVM中稱為NVPTX),PowerPC、AMD TeraScale[22]、AMDGPU、SPARC、SystemZ、RISC-V、WebAssembly、x86、x86-64和XCore。
LLVM包含一個專門的MC模塊,將機器指令在文字形式和機器碼形式間相互轉換。在之前LLVM依靠系統或是平台專門的工具鏈將匯編翻譯為機器碼。LLVM機器碼的集成匯編器已經支持絕大多數LLVM的目標平台。
鏈接器
lld鏈接器子項目旨在為LLVM開發一個內置的,平台獨立的鏈接器[23],去除對所有第三方鏈接器的依賴。在2017年5月,lld已經支持ELF、PE/COFF、 和Mach-O。在lld支持不完全的情況下,用戶可以使用其他項目,如GNU ld鏈接器。 lld支持鏈接時優化。當LLVM鏈接時優化被啟用時,LLVM可以輸出bitcode而不是本機代碼,而本機代碼生成由鏈接器優化處理。
C++標準庫
另見
參考文獻
- ^ LLVM 19.1.3. 2024年10月30日 [2024年10月30日].
- ^ Reedy, Geoff. Compiling Scala to LLVM. St. Louis, Missouri, United States. 2012-09-24 [2013-02-19]. (原始內容存檔於2020-11-29).
- ^ Mono LLVM, [2013-03-10], (原始內容存檔於2020-06-15)
- ^ Adam Treat, mkspecs and patches for LLVM compile of Qt4 (頁面存檔備份,存於網際網路檔案館)
- ^ 存档副本. [2011-12-22]. (原始內容存檔於2012-01-17).
- ^ Chris Lattner discusses the name LLVM. [22 December 2011]. (原始內容存檔於2012年1月12日).
- ^ ACM Awards. ACM. [2013-04-28]. (原始內容存檔於2012-04-02).
- ^ LLVM 9.0.0 License. [2020-11-14]. (原始內容存檔於2020-11-11).
- ^ Migration Proposal. [2020-11-14]. (原始內容存檔於2020-11-25).
- ^ LLVM Language Reference Manual. [16 April 2012]. (原始內容存檔於2012-06-11).
- ^ Chris Lattner. A cool use of LLVM at Apple: the OpenGL stack. LLVMdev mailing list. 15 August 2006 [26 October 2008]. (原始內容存檔於2006年11月4日).
- ^ Michael Larabel, "GNOME Shell Works Without GPU Driver Support" (頁面存檔備份,存於網際網路檔案館), phoronix, 6 November 2011
- ^ V. Makarov. SPEC2000: Comparison of LLVM-2.9 and GCC4.6.1 on x86. [3 October 2011]. (原始內容存檔於2020-08-03).
- ^ V. Makarov. SPEC2000: Comparison of LLVM-2.9 and GCC4.6.1 on x86_64. [3 October 2011]. (原始內容存檔於2020-08-03).
- ^ Michael Larabel. LLVM/Clang 3.2 Compiler Competing With GCC. 27 December 2012 [31 March 2013]. (原始內容存檔於2020-11-30).
- ^ Lattner, Chris; Vikram Adve. Architecture For a Next-Generation GCC. First Annual GCC Developers' Summit. May 2003 [6 September 2009]. (原始內容存檔於2020-07-07).
- ^ Clang 3.8 Release Notes. [August 24, 2016]. (原始內容存檔於2016-10-31).
- ^ Compiling Haskell To LLVM (PDF). [26 June 2008]. (原始內容存檔 (PDF)於2016-08-06).
- ^ LLVM Project Blog: The Glasgow Haskell Compiler and LLVM. [13 August 2010]. (原始內容存檔於2011-06-25).
- ^ 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
。 - ^ llvm
.org /docs /LangRef .html. - ^ Stellard, Tom. [LLVMdev] RFC: R600, a new backend for AMD GPUs. llvm-dev (郵件列表). March 26, 2012 [2019-02-18]. (原始內容存檔於2020-12-01).
- ^ lld - The LLVM Linker. The LLVM Project. [May 10, 2017]. (原始內容存檔於2020-12-29).
- ^ "libc++" C++ Standard Library. [2020-09-26]. (原始內容存檔於2017-04-29).
外部連結
- 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專案