llvmlite
一个用于编写 JIT 编译器的轻量级 LLVM-Python 绑定
llvmlite 提供了一个 LLVM 的 Python 绑定,供 Numba 使用。Numba 之前依赖于 llvmpy。
Llvmpy 变得难以维护,原因如下:
它具有繁琐的架构。
最新 LLVM 版本的 C++11 要求与某些 Python 版本的编译器和运行时 ABI 要求不兼容,尤其是在 Windows 下。
事实证明,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 方面仍有空间。