llvmpy是llvm C ++库的Python包装器,允许简单访问编译器工具。
但是这个库已经不再更新了,只支持LLVM 3.3,不支持更新的版本。
有一篇好文章可以阅读:Let’s Write an LLVM Specializer for Python! (Stephen Diehl)
项目的GitHub地址:numba/llvmlite: A lightweight LLVM python binding for writing JIT compilers
对应版本如下:
llvmlite versions | compatible LLVM versions |
---|---|
0.29.0 - … | 7.0.x, 7.1.x, 8.0.x |
0.27.0 - 0.28.0 | 7.0.x |
0.23.0 - 0.26.0 | 6.0.x |
0.21.0 - 0.22.0 | 5.0.x |
0.17.0 - 0.20.0 | 4.0.x |
0.16.0 - 0.17.0 | 3.9.x |
0.13.0 - 0.15.0 | 3.8.x |
0.9.0 - 0.12.1 | 3.7.x |
0.6.0 - 0.8.0 | 3.6.x |
0.1.0 - 0.5.1 | 3.5.x |
我使用的LLVM版本是3.9,所以我下载0.16.0版本的llvmlite :
apt install libedit-dev
alias llvm-config="llvm-config-3.9"
export LLVM_CONFIG="/usr/bin/llvm-config-3.9"
pip3 install llvmlite==0.16.0
python3 -m llvmlite.tests
现在就可以使用了,示例代码如下:
from __future__ import print_function
from ctypes import CFUNCTYPE, c_double
import llvmlite.binding as llvm
# All these initializations are required for code generation!
llvm.initialize()
llvm.initialize_native_target()
llvm.initialize_native_asmprinter() # yes, even this one
llvm_ir = """
; ModuleID = "examples/ir_fpadd.py"
target triple = "unknown-unknown-unknown"
target datalayout = ""
define double @"fpadd"(double %".1", double %".2")
{
entry:
%"res" = fadd double %".1", %".2"
ret double %"res"
}
"""
def create_execution_engine():
"""
Create an ExecutionEngine suitable for JIT code generation on
the host CPU. The engine is reusable for an arbitrary number of
modules.
"""
# Create a target machine representing the host
target = llvm.Target.from_default_triple()
target_machine = target.create_target_machine()
# And an execution engine with an empty backing module
backing_mod = llvm.parse_assembly("")
engine = llvm.create_mcjit_compiler(backing_mod, target_machine)
return engine
def compile_ir(engine, llvm_ir):
"""
Compile the LLVM IR string with the given engine.
The compiled module object is returned.
"""
# Create a LLVM module object from the IR
mod = llvm.parse_assembly(llvm_ir)
mod.verify()
# Now add the module and make sure it is ready for execution
engine.add_module(mod)
engine.finalize_object()
return mod
engine = create_execution_engine()
mod = compile_ir(engine, llvm_ir)
# Look up the function pointer (a Python int)
func_ptr = engine.get_function_address("fpadd")
# Run the function via ctypes
cfunc = CFUNCTYPE(c_double, c_double, c_double)(func_ptr)
res = cfunc(1.0, 3.5)
print("fpadd(...) =", res)