WebAssembly 火了!背后的 LLVM 功不可没!

前面诸多文章中已经重点表达了自己对 WebAssembly 的浓厚兴趣,但是要深入学习 WebAssembly 就不得不说其背后的 LLVM ,这就是本文的主角 。话不多说,直接开始!
1.什么是LLVMLLVM,全称为 Low Level Virtual machine, 是一个用于构建高度优化的编译器(compilers)、优化器(optimizers)和运行时(run-time environments)环境的工具包 。
类 C 语言使用 Clang 前端,组件使用 LLVM 将 C、C++、Objective-C 和 Objective-C++ 代码编译成 LLVM 位码(bitcode),最终编译成目标文件 。

Clang:是一个C语言、C++、Objective-C语言的轻量级编译器,源代码通过BSD协议发布 。Clang支持普通lambda表达式、返回类型的简化处理等诸多特性 。

WebAssembly 火了!背后的 LLVM 功不可没!

文章插图
Image from Jacopo Mangiavacchi via Medium
LLVM 的核心是一个用于以编程方式创建机器本机代码的库 。开发人员使用 API 以称为中间表示或 LLVM IR (LLVM Intermediate Representation)的格式生成指令,然后 LLVM 可以将 IR 编译成独立的二进制文件或对代码执行 JIT(Just-in-Time)编译以在另一个程序的上下文中运行,例如:该语言的解释器或运行时 。
WebAssembly 火了!背后的 LLVM 功不可没!

文章插图
LLVM 标志是一个双足飞龙、龙具有力量、速度和智慧的内涵 。
LLVM 的 API 为开发编程语言中的许多常见结构和模式提供了原语 。例如,几乎每种语言都有函数和全局变量的概念,而且许多语言都有协程和 C 外部函数接口 。LLVM 在其 IR 中将函数和全局变量作为标准元素,并具有创建协程和与 C 库接口的能力 。
WebAssembly 火了!背后的 LLVM 功不可没!

文章插图
 
比如上面的示例中是一个LLVM 的中间表示 (IR) 的示例 。右边是一个简单的C程序,左边是由 Clang 编译器翻译成 LLVM IR 的相同代码 。
目前 LLVM 在 Github 上有 18.8K 的 star、7.1k 的 fork、2800+的代码贡献者 。
2.LLVM:专为可移植性而设计要理解 LLVM,可与 C 语言类比 。C 被描述为一种可移植的高级汇编语言,因为它具有可以紧密映射到系统硬件的结构,并且几乎已被成功移植到各个系统的架构 。 但是 C 作为一种可移植的汇编语言并非为特定目的而设计 。
相比之下,LLVM 的 IR 从一开始就被设计成一个可移植的组件,即通过提供独立于任何特定机器体系结构的原语 。
整数类型不限于底层硬件的最大位宽(例如 32 位或 64 位) 。开发者可以根据需要使用尽可能多的位来创建原始整数类型,如128 位整数,而不必担心制作输出以匹配特定处理器的指令集, LLVM 默认实现 。
LLVM 的架构设计使其更容易支持现在和未来的各种硬件 。例如,IBM 最近贡献代码以支持其 z/OS、linux on Power、以及用于 LLVM 的 C、C++ 和 Fortran 项目的 AIX 架构 。
3.编程语言如何使用 LLVM方式LLVM 最常见的用例是作为语言的提前编译器(AOT,即Ahead-of-Time) 。例如,Clang 提前将 C 和 C++ 编译为本机二进制文件 。
3.1 使用 LLVM 进行即时编译有些情况需要在运行时动态生成代码,而不是提前编译 。例如,Julia 语言对其代码进行 JIT 编译,因为需要快速运行并通过 REP或交互式命令与用户交互 。
Numba 是用于 Python/ target=_blank class=infotextkey>Python 的数学加速包,JIT 将选定的 Python 函数即时编译为机器代码 。部分开发者正在尝试将 LLVM 用作 JIT 的新方法,例如:编译 PostgreSQL 查询,从而将性能提高五倍 。
WebAssembly 火了!背后的 LLVM 功不可没!

文章插图
 
如上图:Numba 使用 LLVM 即时编译数字代码并加速其执行 。JIT 加速的 sum2d 函数完成其执行速度比常规 Python 代码快约 139 倍 。
3.2 使用 LLVM 自动优化代码LLVM 不只是将 IR(Intermediate Representation) 编译为本机代码 。开发者还可以通过编程方式指示它以高度粒度优化代码,一直到链接过程 。优化可能非常激进,包括内联函数、消除无用代码(包括未使用的类型声明和函数参数)以及展开循环等等 。
LLVM的强大之处在于不必开发者关心,LLVM 可以自动处理优化,或者根据开发者指令关闭特定优化等 。
3.3 具有 LLVM 的领域特定语言LLVM 已被用于为许多通用语言生成编译器,也可用于生成高度垂直或专用于问题域的语言 。这是 LLVM 最值得称赞的地方,它降低了创建语言的难度,而且表现良好 。
Emscripten 项目采用 LLVM IR 代码并将其转换为 JAVAScript,理论上允许任何具有 LLVM 后端的语言导出可在浏览器中运行的代码 。


推荐阅读