什么是 LLVM? Swift、Rust、Clang等背后的力量 - infoworld

22-01-08 banq

新的语言,以及对现有语言的改进,在整个开发环境中如雨后春笋般涌现。Mozilla 的 Rust、Apple 的 Swift、Jetbrains 的 Kotlin和许多其他语言为开发人员提供了速度、安全性、便利性、可移植性和强大功能的新选择范围。
为什么是现在这个时候涌现这种现象?
一个重要原因是用于构建语言的新工具——特别是编译器。其中最主要的是LLVM,这是一个开源项目,最初由 Swift 语言创建者 Chris Lattner 作为伊利诺伊大学的一个研究项目开发。
LLVM 不仅可以更轻松地创建新语言,还可以增强现有语言的开发。它提供了用于自动化语言创建任务中许多最吃力不讨好的部分的工具:创建编译器,将输出的代码移植到多个平台和架构,生成特定于架构的优化,例如向量化,以及编写代码来处理常见的语言隐喻,例如exception。它的自由许可意味着它可以作为软件组件自由重用或部署为服务。
使用 LLVM 的语言列表有许多熟悉的名称。Apple 的 Swift 语言使用 LLVM 作为其编译器框架,Rust 使用 LLVM 作为其工具链的核心组件。此外,许多编译器都有一个 LLVM 版本,例如 Clang,C/C++ 编译器(这个名称,“C-lang”),它本身就是一个与 LLVM 密切相关的项目。Mono 是 .NET 实现,可以选择使用 LLVM 后端编译为本机代码。Kotlin,名义上是一种 JVM 语言,正在开发一种名为Kotlin Native的语言版本,它使用 LLVM 编译为机器原生代码。
 

LLVM 定义
LLVM 的核心是一个用于以编程方式创建机器原生代码的库。开发人员使用 API 以称为中间表示或 IR的格式生成指令。然后,LLVM 可以将 IR 编译为独立的二进制文件或对代码执行 JIT(即时)编译,以在另一个程序的上下文中运行,例如该语言的解释器或运行时。
LLVM 的 API 为开发编程语言中的许多常见结构和模式提供了原语。例如,几乎每一种语言都有函数和全局变量的概念,而且许多语言都有协程和 C 外部函数接口。LLVM 将函数和全局变量作为其 IR 中的标准元素,并具有用于创建协程和与 C 库接口的隐喻。
无需花费时间和精力重新发明那些特定的轮子,您可以只使用 LLVM 的实现并专注于您的语言中需要注意的部分。
 

LLVM:专为便携性而设计
要理解 LLVM,考虑与 C 编程语言进行类比可能会有所帮助:C 有时被描述为一种可移植的高级汇编语言,因为它具有可以紧密映射到系统硬件的结构,并且它已被移植到几乎每个系统架构。但是 C 作为一种可移植的汇编语言只是在一定程度上有用。它不是为特定目的而设计的。
相比之下,LLVM 的 IR 从一开始就被设计为可移植的程序集。它实现这种可移植性的一种方法是提供独立于任何特定机器架构的原语。例如,整数类型并不局限于底层硬件的最大位宽(例如 32 位或 64 位)。您可以根据需要使用尽可能多的位创建原始整数类型,例如 128 位整数。您也不必担心制作输出以匹配特定处理器的指令集;LLVM 也会为您解决这个问题。
LLVM 的架构中立设计使得支持现在和未来的各种硬件变得更加容易。例如,IBM 最近贡献了代码来支持其 z/OS、Linux on Power(包括对 IBM 的 MASS 矢量化库的支持)以及用于 LLVM 的 C、C++ 和 Fortran 项目的 AIX 架构。 
如果您想查看 LLVM IR 的实时示例,请访问ELLCC 项目网站并尝试在浏览器中将 C 代码转换为 LLVM IR的实时演示
  

编程语言如何使用 LLVM

  • 使用 LLVM 进行即时编译

有些情况需要在运行时动态生成代码JIT,而不是提前编译,如Julia。
其他人正在尝试使用 LLVM 作为 JIT 的新方法,例如编译 PostgreSQL 查询,从而将性能提高五倍。
  •  使用 LLVM 自动优化代码

LLVM 不只是将 IR 编译为本机机器码。您还可以以编程方式指导它以高度粒度优化代码,一直到链接过程。优化可能非常激进,包括内联函数、消除死代码(包括未使用的类型声明和函数参数)和展开循环。
  • 使用 LLVM 的领域特定语言

LLVM 已用于为许多通用语言生成编译器,但它也可用于生成高度垂直或专属于问题域的语言。在某些方面,这是 LLVM 最闪耀的地方,因为它消除了创建这种语言的许多苦差事,并使其表现良好。
 

LLVM 不做什么
有了 LLVM 提供的所有功能,了解它不做什么也是很有用的。
例如,LLVM 不解析语言的语法。许多工具已经完成了这项工作,例如lex/yaccflex/bisonLark和 ANTLR。无论如何,解析都意味着与编译解耦,因此 LLVM 没有尝试解决任何问题也就不足为奇了。
LLVM 也没有直接解决围绕给定语言的更大的软件文化。安装编译器的二进制文件、管理安装中的包以及升级工具链——您需要自己完成这些工作。
  

有无垃圾回收机制?
最后,也是最重要的,LLVM 仍然没有为其提供原语的语言的公共部分。许多语言都有某种方式的垃圾回收内存管理,要么作为管理内存的主要方式,要么作为RAII(C++ 和 Rust 使用的)等策略的辅助。LLVM 没有为您提供垃圾收集器机制,但它确实提供了实现垃圾收集 的工具,方法是允许使用元数据标记代码,从而更轻松地编写垃圾收集器。
不过,这一切都不能排除 LLVM 最终可能会添加本地机制来实现垃圾收集的可能性。LLVM 发展迅速,每六个月左右发布一次主要版本。由于许多当前语言将 LLVM 置于其开发过程的核心,因此开发速度可能只会加快。
原文点击标题

3