2016-04-16 7 views
3

Pythonでコンパイルを書くときに、llvmliteを使用して中間のLLVM IRを生成する。レクサーとパーサーが完成しました。今はコード生成を行っています。コンパイラは動的で弱く型付けされているので、私は実行時に割り当てのような何かをする必要があります。このため、私はすでにC言語でいくつかの関数を実装していますが、今はllvmliteのbuilder.callを使ってこれらの関数を呼び出したいと思います。llvmliteのリンクC

これを行う方法のドキュメントまたは例は見つかりませんでした。

この関数は単なる例ですが、実際の関数は非常に大きいです。

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でそれを行いますどんな助けも歓迎です!

+0

レクサー&パーサーの開発にどのツールを使用しましたか? –

答えて

2

ランタイムを含むダイナミックライブラリをインポートできます。

llvmlite.binding.load_library_permanently("runtime.so") 

通常の関数呼び出しを生成するだけです。

3

LLVM IR側では、正しい署名(および本文なし)で関数を宣言し、他の関数と同様に呼び出しを挿入できます。これは、Cで他のファイルで定義されている関数を呼び出す方法と同じです。

そこから、何らかの形でCの関数にリンクする必要があります。ここでの詳細は、生成されたIRコードをどのように使用するかによって異なります。たとえば、clangを使用してオブジェクトファイルに変換し、他のプログラムと同様にリンクすることができます。または、llvm JITを使用することもできます。その場合、@ Coder3000の答え(llvmlite.binding.load_library_permanently)は、LLVMが関数呼び出しを解決できるようにする必要があります。 Coder3000と@Ismailバダウィの答え@

0

は完璧ですが、何の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 - - http://eli.thegreenplace.net/2015/calling-back-into-python-from-llvmlite-jited-code/

関連する問題