首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从LLVM JIT调用Python代码

从LLVM JIT调用Python代码
EN

Stack Overflow用户
提问于 2013-03-02 00:08:20
回答 2查看 1.1K关注 0票数 6

我用python编写了一种语言lexer/解析器/编译器,以后应该在LLVM (使用llvm-py)中运行。前两个步骤现在非常简单,但是(即使我还没有开始编译任务),当我的代码想调用Python (一般情况下),或者分别与Python/解析器/编译器交互(特别是)时,我发现了一个问题。我主要关心的是,代码应该能够在运行时动态地将额外的代码加载到VM中,因此它必须从VM内部触发Python中的整个lexer/解析器/编译器链。

首先:这是可能的吗?或者VM一旦启动就“不可变”了吗?

如果是的话,我目前看到了3种可能的解决方案(我愿意听取其他建议)

  • VM的“爆发”,使直接调用主进程的Python函数成为可能(可能通过将其注册为LLVM-函数,该函数以某种方式重定向到主进程)。我没有找到关于这个的任何东西,而且我也不确定,这是否是一个好主意(安全等等)。
  • 将运行时(在运行时静态地或动态地)编译到LLVM-Assembly/-IR中。这就要求IR代码能够修改它在其中运行的VM。
  • 将运行时(静态)编译到库中,并将其直接加载到VM中。同样,它必须能够将函数(等等)添加到它运行的VM中。
EN

回答 2

Stack Overflow用户

发布于 2014-02-24 02:32:14

就像Eli说的,没有阻止您调用Python。当您从llvmpy内部调用外部函数时,它实际上只是在进程空间上使用dlopen(),因此如果您从llvmpy内部运行,您已经可以访问所有Python解释器符号,甚至可以与调用ExecutionEngine的活动解释器交互,或者在需要时可以旋转一个新的ExecutionEngine解释器。

为了让您开始,使用我们的评估器创建一个新的C文件。

代码语言:javascript
复制
#include <Python.h>

void python_eval(const char* s)
{
    PyCodeObject* code = (PyCodeObject*) Py_CompileString(s, "example", Py_file_input);

    PyObject* main_module = PyImport_AddModule("__main__");
    PyObject* global_dict = PyModule_GetDict(main_module);
    PyObject* local_dict = PyDict_New();
    PyObject* obj = PyEval_EvalCode(code, global_dict, local_dict);

    PyObject* result = PyObject_Str(obj);

    // Print the result if you want.
    // PyObject_Print(result, stdout, 0);
}

下面是编译它的一个小Makefile:

代码语言:javascript
复制
CC = gcc
LPYTHON = $(shell python-config --includes)
CFLAGS = -shared -fPIC -lpthread $(LPYTHON)

.PHONY: all clean

all:
    $(CC) $(CFLAGS) cbits.c -o cbits.so

clean:
    -rm cbits.c

然后,我们从LLVM常用的样板开始,但是使用ctype将cbits.so共享库的共享对象加载到全局进程空间,这样我们就有了python_eval符号。然后只需创建一个带有函数的简单LLVM模块,使用带有ctype的Python源代码分配一个字符串,并从我们的模块传递指向运行JIT'd函数的ExecutionEngine的指针,该指针依次将Python源传递给调用Python的C-函数,然后返回给LLVM。

代码语言:javascript
复制
import llvm.core as lc
import llvm.ee as le

import ctypes
import inspect

ctypes._dlopen('./cbits.so', ctypes.RTLD_GLOBAL)

pointer = lc.Type.pointer

i32 = lc.Type.int(32)
i64 = lc.Type.int(64)

char_type  = lc.Type.int(8)
string_type = pointer(char_type)

zero = lc.Constant.int(i64, 0)

def build():
    mod = lc.Module.new('call python')
    evalfn = lc.Function.new(mod,
        lc.Type.function(lc.Type.void(),
        [string_type], False), "python_eval")

    funty = lc.Type.function(lc.Type.void(), [string_type])

    fn = lc.Function.new(mod, funty, "call")
    fn_arg0 = fn.args[0]
    fn_arg0.name = "input"

    block = fn.append_basic_block("entry")
    builder = lc.Builder.new(block)

    builder.call(evalfn, [fn_arg0])
    builder.ret_void()

    return fn, mod

def run(fn, mod, buf):

    tm = le.TargetMachine.new(features='', cm=le.CM_JITDEFAULT)
    eb = le.EngineBuilder.new(mod)
    engine = eb.create(tm)

    ptr = ctypes.cast(buf, ctypes.c_voidp)
    ax = le.GenericValue.pointer(ptr.value)

    print 'IR'.center(80, '=')
    print mod

    mod.verify()
    print 'Assembly'.center(80, '=')
    print mod.to_native_assembly()

    print 'Result'.center(80, '=')
    engine.run_function(fn, [ax])

if __name__ == '__main__':
    # If you want to evaluate the source of an existing function
    # source_str = inspect.getsource(mypyfn)

    # If you want to pass a source string
    source_str = "print 'Hello from Python C-API inside of LLVM!'"

    buf = ctypes.create_string_buffer(source_str)
    fn, mod = build()
    run(fn, mod, buf)

您应该输出以下内容:

代码语言:javascript
复制
=======================================IR=======================================
; ModuleID = 'call python'

declare void @python_eval(i8*)

define void @call(i8* %input) {
entry:
  call void @python_eval(i8* %input)
  ret void
}
=====================================Result=====================================
Hello from Python C-API inside of LLVM!
票数 6
EN

Stack Overflow用户

发布于 2013-03-02 13:28:57

您可以从LLVM JIT编辑的代码中调用外部C函数。您还需要些什么?

这些外部函数将在执行过程中找到,这意味着如果将Python链接到VM中,则可以调用Python的can函数。

"VM“可能没有您想象的那么神奇:-)最后,它只是在运行时被发送到一个缓冲区并从那里执行的机器代码。只要该代码能够访问它正在运行的进程中的其他符号,它就可以完成该进程中任何其他代码所能做的任何事情。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15169015

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档