Link llvmlite 中的 C
Link C in llvmlite
我正在 Python 中编写编译器,使用 llvmlite
生成中间 LLVM IR。 Lexer 和 parser 已经完成,现在我正在做代码生成。编译器将是动态的和弱类型的,所以我需要在运行时做一些事情,比如分配。为此,我已经在 C 中实现了一些函数,现在我想使用 llvmlite 中的 builder.call
调用这些函数。
我没有找到有关如何执行此操作的文档或示例。
这个函数只是一个简单的例子,真实的要大得多
C:
int some_function(int a)
{
return a + 4;
}
Python:
...
main_ty = ir.FunctionType(ir.IntType(32), [])
func = ir.Function(module, main_ty, 'main')
block = func.append_basic_block('entry')
builder = ir.IRBuilder(block)
# I want to do something like this...
ret = builder.call(some_function, [ir.Constant(ir.IntType(32), 34)]);
...
我可以直接使用 llvmlite 构建器编写函数,但在 C 中会更快、更干净、更容易。欢迎任何帮助!
您可以导入包含运行时的动态库。
llvmlite.binding.load_library_permanently("runtime.so")
然后您可以简单地生成正常的函数调用。
在 LLVM IR 端,您可以只声明具有正确签名(没有主体)的函数,并像任何其他函数一样插入对它们的调用。这就像在 C 中调用另一个文件中定义的函数一样。
从那里开始,您将不得不以某种方式 link 反对您的 C 函数。此处的详细信息取决于您打算如何使用生成的 IR 代码。例如,您可以使用 clang 将其转换为目标文件,然后像任何其他程序一样 link 它。或者您可以使用 llvm JIT,在这种情况下,@Coder3000 的答案(llvmlite.binding.load_library_permanently
)应该可以让 LLVM 解析您的函数调用。
@Coder3000 和@Ismail Badawi 的回答很完美,但是没有code.There 是我的代码
#!/usr/bin/env python
# coding=utf-8
from __future__ import print_function
from ctypes import CFUNCTYPE, c_double,cdll,c_int
import llvmlite.binding as llvm
import llvmlite.ir as ir
llvm.initialize()
llvm.initialize_native_target()
llvm.initialize_native_asmprinter()
#load shared library
llvm.load_library_permanently('./TestLib.so')
# Create some useful types
double = ir.DoubleType()
fnty = ir.FunctionType(double, (double, double))
# Create an empty module...
module = ir.Module("fdadd")
# and declare a function named "fpadd" inside it
func = ir.Function(module, fnty, name="fpadd")
# Now implement the function
block = func.append_basic_block(name="entry")
builder = ir.IRBuilder(block)
a, b = func.args
result = builder.fadd(a, b, name="res")
builder.ret(result)
#function call in llvm ir internal
func2=ir.Function(module,fnty,name="fdadd")
block2=func2.append_basic_block(name="entry")
builder=ir.IRBuilder(block2)
a,b=func2.args
result2=builder.call(func,(a,b))
builder.ret(result2)
# llvm IR call external C++ function
outfunc=ir.Function(module,fnty,name="SampleAddDouble")
#just declare shared library function in module
outaddfunc=ir.Function(module,fnty,name="outadd")
builder=ir.IRBuilder(outaddfunc.append_basic_block(name="entry"))
a,b=outaddfunc.args
outresult=builder.call(outfunc,(a,b))
builder.ret(outresult)
strmod=str(module)
# Print the module IR
print(strmod)
print("-----------------------------------------")
#assembly llvm ir
assmod = llvm.parse_assembly(strmod)
assmod.verify()
print("--parse assembly")
target = llvm.Target.from_default_triple()
target_machine = target.create_target_machine()
engine = llvm.create_mcjit_compiler(assmod, target_machine)
engine.finalize_object()
print(engine)
# Look up the function pointer (a Python int)
#llvm execution engine call llvm IR function(or dsl function)
func_ptr = engine.get_function_address("fpadd")
print('func_ptr is:',func_ptr)
# Run the function via ctypes
cfunc = CFUNCTYPE(c_double, c_double, c_double)(func_ptr)
res = cfunc(1.0, 3.5)
print("fpadd(...) =", res)
#llvm binding layer call shared library function
add_int_addr = llvm.address_of_symbol("SampleAddInt")
print(add_int_addr)
add_int_func=CFUNCTYPE(c_int,c_int,c_int)(add_int_addr)
res2=add_int_func(23,34)
print(res2)
#llvm execution engine call shared library function ,by llvm IR
add_double_addr=engine.get_function_address("outadd")
print(add_double_addr)
add_double_func=CFUNCTYPE(c_double,c_double,c_double)(add_double_addr)
res3=add_double_func(1.21,1.12)
print(res3)
还有 Testlib.cpp
$参考资料https://helloacm.com/calling-c-shared-library-from-python-code-linux-version/
关于这个问题这里是其他参考
-Call C/C++ functions from the ExecutionEngine
-Call Python code from LLVM JIT
-http://eli.thegreenplace.net/2015/calling-back-into-python-from-llvmlite-jited-code/
我正在 Python 中编写编译器,使用 llvmlite
生成中间 LLVM IR。 Lexer 和 parser 已经完成,现在我正在做代码生成。编译器将是动态的和弱类型的,所以我需要在运行时做一些事情,比如分配。为此,我已经在 C 中实现了一些函数,现在我想使用 llvmlite 中的 builder.call
调用这些函数。
我没有找到有关如何执行此操作的文档或示例。
这个函数只是一个简单的例子,真实的要大得多
C:
int some_function(int a)
{
return a + 4;
}
Python:
...
main_ty = ir.FunctionType(ir.IntType(32), [])
func = ir.Function(module, main_ty, 'main')
block = func.append_basic_block('entry')
builder = ir.IRBuilder(block)
# I want to do something like this...
ret = builder.call(some_function, [ir.Constant(ir.IntType(32), 34)]);
...
我可以直接使用 llvmlite 构建器编写函数,但在 C 中会更快、更干净、更容易。欢迎任何帮助!
您可以导入包含运行时的动态库。
llvmlite.binding.load_library_permanently("runtime.so")
然后您可以简单地生成正常的函数调用。
在 LLVM IR 端,您可以只声明具有正确签名(没有主体)的函数,并像任何其他函数一样插入对它们的调用。这就像在 C 中调用另一个文件中定义的函数一样。
从那里开始,您将不得不以某种方式 link 反对您的 C 函数。此处的详细信息取决于您打算如何使用生成的 IR 代码。例如,您可以使用 clang 将其转换为目标文件,然后像任何其他程序一样 link 它。或者您可以使用 llvm JIT,在这种情况下,@Coder3000 的答案(llvmlite.binding.load_library_permanently
)应该可以让 LLVM 解析您的函数调用。
@Coder3000 和@Ismail Badawi 的回答很完美,但是没有code.There 是我的代码
#!/usr/bin/env python
# coding=utf-8
from __future__ import print_function
from ctypes import CFUNCTYPE, c_double,cdll,c_int
import llvmlite.binding as llvm
import llvmlite.ir as ir
llvm.initialize()
llvm.initialize_native_target()
llvm.initialize_native_asmprinter()
#load shared library
llvm.load_library_permanently('./TestLib.so')
# Create some useful types
double = ir.DoubleType()
fnty = ir.FunctionType(double, (double, double))
# Create an empty module...
module = ir.Module("fdadd")
# and declare a function named "fpadd" inside it
func = ir.Function(module, fnty, name="fpadd")
# Now implement the function
block = func.append_basic_block(name="entry")
builder = ir.IRBuilder(block)
a, b = func.args
result = builder.fadd(a, b, name="res")
builder.ret(result)
#function call in llvm ir internal
func2=ir.Function(module,fnty,name="fdadd")
block2=func2.append_basic_block(name="entry")
builder=ir.IRBuilder(block2)
a,b=func2.args
result2=builder.call(func,(a,b))
builder.ret(result2)
# llvm IR call external C++ function
outfunc=ir.Function(module,fnty,name="SampleAddDouble")
#just declare shared library function in module
outaddfunc=ir.Function(module,fnty,name="outadd")
builder=ir.IRBuilder(outaddfunc.append_basic_block(name="entry"))
a,b=outaddfunc.args
outresult=builder.call(outfunc,(a,b))
builder.ret(outresult)
strmod=str(module)
# Print the module IR
print(strmod)
print("-----------------------------------------")
#assembly llvm ir
assmod = llvm.parse_assembly(strmod)
assmod.verify()
print("--parse assembly")
target = llvm.Target.from_default_triple()
target_machine = target.create_target_machine()
engine = llvm.create_mcjit_compiler(assmod, target_machine)
engine.finalize_object()
print(engine)
# Look up the function pointer (a Python int)
#llvm execution engine call llvm IR function(or dsl function)
func_ptr = engine.get_function_address("fpadd")
print('func_ptr is:',func_ptr)
# Run the function via ctypes
cfunc = CFUNCTYPE(c_double, c_double, c_double)(func_ptr)
res = cfunc(1.0, 3.5)
print("fpadd(...) =", res)
#llvm binding layer call shared library function
add_int_addr = llvm.address_of_symbol("SampleAddInt")
print(add_int_addr)
add_int_func=CFUNCTYPE(c_int,c_int,c_int)(add_int_addr)
res2=add_int_func(23,34)
print(res2)
#llvm execution engine call shared library function ,by llvm IR
add_double_addr=engine.get_function_address("outadd")
print(add_double_addr)
add_double_func=CFUNCTYPE(c_double,c_double,c_double)(add_double_addr)
res3=add_double_func(1.21,1.12)
print(res3)
还有 Testlib.cpp $参考资料https://helloacm.com/calling-c-shared-library-from-python-code-linux-version/
关于这个问题这里是其他参考
-Call C/C++ functions from the ExecutionEngine -Call Python code from LLVM JIT -http://eli.thegreenplace.net/2015/calling-back-into-python-from-llvmlite-jited-code/