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专案