如何正确销毁 LLVMModule 和 LLVMExecutionEngine?
How to correctly destroy an LLVMModule and LLVMExecutionEngine?
我有一个使用 LLVM-C 的简单程序:
#define __STDC_LIMIT_MACROS
#define __STDC_CONSTANT_MACROS
#include <llvm-c/Core.h>
#include <llvm-c/ExecutionEngine.h>
#include <llvm-c/Target.h>
#include <llvm-c/Analysis.h>
#include <llvm-c/BitWriter.h>
#include <llvm-c/Linker.h>
#include <stdlib.h>
#include <stdio.h>
int main() {
LLVMInitializeNativeTarget();
LLVMInitializeNativeAsmPrinter();
LLVMInitializeNativeAsmParser();
LLVMContextRef ctx = LLVMGetGlobalContext();
LLVMModuleRef mod = LLVMModuleCreateWithNameInContext("mymodule", ctx);
LLVMTypeRef functype = LLVMFunctionType(LLVMInt32Type(), NULL, 0, 0);
LLVMValueRef func = LLVMAddFunction(mod, "constfunc", functype);
LLVMBasicBlockRef entry = LLVMAppendBasicBlock(func, "entry");
LLVMBuilderRef builder = LLVMCreateBuilder();
LLVMPositionBuilderAtEnd(builder, entry);
LLVMBuildRet(builder, LLVMConstInt(LLVMInt32Type(), 2, 0));
LLVMDisposeBuilder(builder);
char* error = NULL;
LLVMVerifyModule(mod, LLVMAbortProcessAction, &error);
LLVMDisposeMessage(error);
error = NULL;
LLVMExecutionEngineRef engine;
if (LLVMCreateMCJITCompilerForModule (&engine, mod, NULL, 0, &error) != 0) {
fprintf(stderr, "failed to create execution engine\n");
exit(EXIT_FAILURE);
}
int (*func_p)(void) = (int(*)(void)) LLVMGetFunctionAddress(engine, "constfunc");
printf("%d\n", func_p());
LLVMDisposeExecutionEngine(engine);
LLVMDisposeModule(mod);
return 0;
}
照原样,它在 LLVMDisposeModule
:
内部出现段错误
(gdb) run
Starting program: /home/col/llvmtest
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
2
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff668fbcc in llvm::SmallPtrSetImplBase::erase_imp(void const*) () from /usr/local/lib/libLLVM-3.7.1.so
(gdb) bt
#0 0x00007ffff668fbcc in llvm::SmallPtrSetImplBase::erase_imp(void const*) () from /usr/local/lib/libLLVM-3.7.1.so
#1 0x00007ffff5d60f00 in llvm::Module::~Module() () from /usr/local/lib/libLLVM-3.7.1.so
#2 0x00007ffff5c62b5e in LLVMDisposeModule () from /usr/local/lib/libLLVM-3.7.1.so
#3 0x00000000004010cd in main () at llvmtest.c:44
但是,如果我注释掉对 LLVMDisposeExecutionEngine
或 LLVMDisposeModule
的调用,它就不再出现段错误。
使用 C API 销毁 LLVM 模块和执行引擎的正确方法是什么?
我发现列出的代码有两个问题,
第一个问题,你的问题是,
当您调用 LLVMCreateMCJITCompilerForModule 时,它将提供的模块添加到执行引擎的模块列表中,下面是 ExecutionEngineBindings.cpp:196
中相同的剪切代码
std::string Error;
EngineBuilder builder(std::move(Mod));
builder.setEngineKind(EngineKind::JIT)
.setErrorStr(&Error)
.setOptLevel((CodeGenOpt::Level)options.OptLevel)
.setCodeModel(unwrap(options.CodeModel))
.setTargetOptions(targetOptions);
if (options.MCJMM)
builder.setMCJITMemoryManager(
std::unique_ptr<RTDyldMemoryManager>(unwrap(options.MCJMM)));
if (ExecutionEngine *JIT = builder.create()) {
*OutJIT = wrap(JIT);
所以当你调用 LLVMDisposeExecutionEngine 时它已经删除了引擎列表中列出的所有模块,所以正确的方法是你需要在处理执行引擎之前从列表中删除你的 module/s。 (代码在同一个文件中 ExecutionEngineBindings.cpp:258)
LLVMRemoveModule(engine, mod, &mod, &error);
LLVMDisposeExecutionEngine(engine);
其次是 JIT 尚未链接,没有调用 LLVMLinkInMCJIT() 应该在 LLVMInitializeNativeTarget() 之前;
LLVMLinkInMCJIT();
LLVMInitializeNativeTarget();
我有一个使用 LLVM-C 的简单程序:
#define __STDC_LIMIT_MACROS
#define __STDC_CONSTANT_MACROS
#include <llvm-c/Core.h>
#include <llvm-c/ExecutionEngine.h>
#include <llvm-c/Target.h>
#include <llvm-c/Analysis.h>
#include <llvm-c/BitWriter.h>
#include <llvm-c/Linker.h>
#include <stdlib.h>
#include <stdio.h>
int main() {
LLVMInitializeNativeTarget();
LLVMInitializeNativeAsmPrinter();
LLVMInitializeNativeAsmParser();
LLVMContextRef ctx = LLVMGetGlobalContext();
LLVMModuleRef mod = LLVMModuleCreateWithNameInContext("mymodule", ctx);
LLVMTypeRef functype = LLVMFunctionType(LLVMInt32Type(), NULL, 0, 0);
LLVMValueRef func = LLVMAddFunction(mod, "constfunc", functype);
LLVMBasicBlockRef entry = LLVMAppendBasicBlock(func, "entry");
LLVMBuilderRef builder = LLVMCreateBuilder();
LLVMPositionBuilderAtEnd(builder, entry);
LLVMBuildRet(builder, LLVMConstInt(LLVMInt32Type(), 2, 0));
LLVMDisposeBuilder(builder);
char* error = NULL;
LLVMVerifyModule(mod, LLVMAbortProcessAction, &error);
LLVMDisposeMessage(error);
error = NULL;
LLVMExecutionEngineRef engine;
if (LLVMCreateMCJITCompilerForModule (&engine, mod, NULL, 0, &error) != 0) {
fprintf(stderr, "failed to create execution engine\n");
exit(EXIT_FAILURE);
}
int (*func_p)(void) = (int(*)(void)) LLVMGetFunctionAddress(engine, "constfunc");
printf("%d\n", func_p());
LLVMDisposeExecutionEngine(engine);
LLVMDisposeModule(mod);
return 0;
}
照原样,它在 LLVMDisposeModule
:
(gdb) run
Starting program: /home/col/llvmtest
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
2
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff668fbcc in llvm::SmallPtrSetImplBase::erase_imp(void const*) () from /usr/local/lib/libLLVM-3.7.1.so
(gdb) bt
#0 0x00007ffff668fbcc in llvm::SmallPtrSetImplBase::erase_imp(void const*) () from /usr/local/lib/libLLVM-3.7.1.so
#1 0x00007ffff5d60f00 in llvm::Module::~Module() () from /usr/local/lib/libLLVM-3.7.1.so
#2 0x00007ffff5c62b5e in LLVMDisposeModule () from /usr/local/lib/libLLVM-3.7.1.so
#3 0x00000000004010cd in main () at llvmtest.c:44
但是,如果我注释掉对 LLVMDisposeExecutionEngine
或 LLVMDisposeModule
的调用,它就不再出现段错误。
使用 C API 销毁 LLVM 模块和执行引擎的正确方法是什么?
我发现列出的代码有两个问题,
第一个问题,你的问题是, 当您调用 LLVMCreateMCJITCompilerForModule 时,它将提供的模块添加到执行引擎的模块列表中,下面是 ExecutionEngineBindings.cpp:196
中相同的剪切代码std::string Error;
EngineBuilder builder(std::move(Mod));
builder.setEngineKind(EngineKind::JIT)
.setErrorStr(&Error)
.setOptLevel((CodeGenOpt::Level)options.OptLevel)
.setCodeModel(unwrap(options.CodeModel))
.setTargetOptions(targetOptions);
if (options.MCJMM)
builder.setMCJITMemoryManager(
std::unique_ptr<RTDyldMemoryManager>(unwrap(options.MCJMM)));
if (ExecutionEngine *JIT = builder.create()) {
*OutJIT = wrap(JIT);
所以当你调用 LLVMDisposeExecutionEngine 时它已经删除了引擎列表中列出的所有模块,所以正确的方法是你需要在处理执行引擎之前从列表中删除你的 module/s。 (代码在同一个文件中 ExecutionEngineBindings.cpp:258)
LLVMRemoveModule(engine, mod, &mod, &error);
LLVMDisposeExecutionEngine(engine);
其次是 JIT 尚未链接,没有调用 LLVMLinkInMCJIT() 应该在 LLVMInitializeNativeTarget() 之前;
LLVMLinkInMCJIT();
LLVMInitializeNativeTarget();