LLVM API:正确的创建/处置方式

时间:2014-11-24 11:39:13

标签: llvm dispose

我试图使用LLVM C API实现一个简单的JIT编译器。到目前为止,我在生成IR代码并执行它时没有任何问题,即:直到我开始处理对象并重新创建它们。

我基本上想要做的是在发动机不再使用JIT的资源时清理它们。我基本上试图做的是这样的事情:

while (true)
{
    // Initialize module & builder
    InitializeCore(GetGlobalPassRegistry());
    module = ModuleCreateWithName(some_unique_name);
    builder = CreateBuilder();

    // Initialize target & execution engine
    InitializeNativeTarget();
    engine = CreateExecutionEngineForModule(...);
    passmgr = CreateFunctionPassManagerForModule(module);
    AddTargetData(GetExecutionEngineTargetData(engine), passmgr);
    InitializeFunctionPassManager(passmgr);

    // [... my fancy JIT code ...] --** Will give a serious error the second iteration

    // Destroy
    DisposePassManager(passmgr);
    DisposeExecutionEngine(engine);
    DisposeBuilder(builder);
    // DisposeModule(module); //--> Commented out: Deleted by execution engine

    Shutdown();
}

然而,这似乎没有正常工作:循环的第二次迭代我得到了一个非常糟糕的错误......

总结一下:破坏和重新创建LLVM API的正确方法是什么?

2 个答案:

答案 0 :(得分:3)

将此作为答案发布,因为代码太长。如果可能而没有其他约束,请尝试使用这样的LLVM。我很确定循环中的Shutdown()是罪魁祸首。我也不认为将Builder放在外面也会受到伤害。这很好地反映了我在JIT中使用LLVM的方式。

InitializeCore(GetGlobalPassRegistry());
InitializeNativeTarget();
builder = CreateBuilder();

while (true)
{
    // Initialize module & builder

    module = ModuleCreateWithName(some_unique_name);


    // Initialize target & execution engine
    engine = CreateExecutionEngineForModule(...);
    passmgr = CreateFunctionPassManagerForModule(module);
    AddTargetData(GetExecutionEngineTargetData(engine), passmgr);
    InitializeFunctionPassManager(passmgr);

    // [... my fancy JIT code ...] --** Will give a serious error the second iteration

    // Destroy
    DisposePassManager(passmgr);
    DisposeExecutionEngine(engine);             
}
DisposeBuilder(builder);
Shutdown();

答案 1 :(得分:0)

  /* program init */
LLVMInitializeNativeTarget();
LLVMInitializeNativeAsmPrinter();
LLVMInitializeNativeAsmParser();
LLVMLinkInMCJIT();





    ctx->context = LLVMContextCreate();
    ctx->builder = LLVMCreateBuilderInContext(ctx->context);
    LLVMParseBitcodeInContext2(ctx->context, module_template_buf, &module) // create module

    do IR code creation
    {
        function = LLVMAddFunction(ctx->module, "my_func")
        LLVMAppendBasicBlockInContext(ctx->context, ...
        LLVMBuild...
        ...
    }
    optional optimization
    {
        LLVMPassManagerBuilderRef pass_builder = LLVMPassManagerBuilderCreate();
        LLVMPassManagerBuilderSetOptLevel(pass_builder, 3);
        LLVMPassManagerBuilderSetSizeLevel(pass_builder, 0);
        LLVMPassManagerBuilderUseInlinerWithThreshold(pass_builder, 1000);
        LLVMPassManagerRef function_passes = LLVMCreateFunctionPassManagerForModule(ctx->module);
        LLVMPassManagerRef module_passes = LLVMCreatePassManager();
        LLVMPassManagerBuilderPopulateFunctionPassManager(pass_builder, function_passes);
        LLVMPassManagerBuilderPopulateModulePassManager(pass_builder, module_passes);
        LLVMPassManagerBuilderDispose(pass_builder);
        LLVMInitializeFunctionPassManager(function_passes);
        for (LLVMValueRef value = LLVMGetFirstFunction(ctx->module); value;
             value = LLVMGetNextFunction(value))
        {
            LLVMRunFunctionPassManager(function_passes, value);
        }
        LLVMFinalizeFunctionPassManager(function_passes);
        LLVMRunPassManager(module_passes, ctx->module);
        LLVMDisposePassManager(function_passes);
        LLVMDisposePassManager(module_passes);
    }

    optional for debug
    {
        LLVMVerifyModule(ctx->module, LLVMAbortProcessAction, &error);
        LLVMPrintModule
    }
    if (LLVMCreateJITCompilerForModule(&ctx->engine, ctx->module, 0, &error) != 0)
    my_func = (exec_func_t)(uintptr_t)LLVMGetFunctionAddress(ctx->engine, "my_func");

    LLVMRemoveModule(ctx->engine, ctx->module, &ctx->module, &error);
    LLVMDisposeModule(ctx->module);
    LLVMDisposeBuilder(ctx->builder);

    do
    {
         my_func(...);
    }

    LLVMDisposeExecutionEngine(ctx->engine);
    LLVMContextDispose(ctx->context);



/* program finit */
LLVMShutdown();