llvmlite

用于编写 JIT 编译器的轻量级 LLVM-Python 绑定

llvmlite 为 LLVM 提供 Python 绑定,供 Numba 使用。Numba 之前依赖于 llvmpy

llvmpy 难以维护的原因是

  • 其架构笨重。

  • 最新 LLVM 版本对 C++11 的要求与某些 Python 版本,尤其是在 Windows 下的编译器和运行时 ABI 要求不兼容。

llvmpy 还被证明是 Numba 编译时间中相当大一部分的罪魁祸首,因为它低效的层级和对象封装。在 llvmpy 代码库中解决此问题似乎是一项耗时且不确定的任务。

Numba 开发者决定从头开始编写一个新的绑定,采用完全不同的架构,并以 JIT 编译器的特定要求为中心。

设计理念

虽然 llvmpy 暴露了 LLVM C++ API 的大部分,用于直接调用 LLVM 库,但 llvmlite 采取了完全不同的方法。llvmlite 从 JIT 编译器的需求出发,并将其分为两个解耦的任务

  • 逐函数、逐指令地构建 模块

  • 将模块编译和优化为机器码。

LLVM 模块的构建不调用 LLVM C++ API。相反,它在纯 Python 中构建 LLVM 中间表示 (IR)。这是 IR 层 的作用。

LLVM 模块的编译以文本形式获取 IR,并将其输入到 LLVM 的解析 API 中。然后它返回一个围绕 LLVM C++ 模块对象的轻量级封装。这是 绑定层 的作用。

一旦解析,模块的源代码就无法修改,这失去了 llvmpy 提供的 C++ API 直接映射到 Python 的灵活性,但节省了大量的维护工作。

LLVM 兼容性

尽管最大限度地减少了与 LLVM 的 API 表面,但 llvmlite 仍受 LLVM C++ API 更改的影响,这些更改可能在每个功能发布时发生。因此,每个 llvmlite 版本都针对特定的 LLVM 功能版本,并适用于该版本的所有错误修复版本。

示例:llvmlite 0.12.0 适用于 LLVM 3.8.0 和 3.8.1,但不适用于 LLVM 3.7.0 或 3.9.0。

Numba 的要求决定了支持哪个 LLVM 版本。

API 稳定性

目前,我们保留在每个版本中略微破坏 llvmlite API 的可能性,原因如下:

  • LLVM 行为的变化,例如不同版本之间 IR 的差异。

  • 作为一个年轻的库,llvmlite 在改进或修复现有 API 方面仍有空间。