2016-03-20 3 views
2

私はLLVM-Cを使用して簡単なプログラムを持っている:LLVMModuleとLLVMExecutionEngineを正しく破棄する方法は?

#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への呼び出しのいずれかをコメントアウトした場合、それをもはやsegfaultsはありません。

C APIを使用してLLVMモジュールと実行エンジンを破壊する正しい方法は何ですか?

+0

:https://lists.freedesktop.org/archives/mesa-dev/2014-May/059352.html LLVMDisposeExecutionEngineが好ましく、また、モジュールを配置し、これだけそれらのいずれかを呼び出しますエンジンが存在する場合はそれを示します。 –

答えて

1

私が記載されたコードには二つの問題、

最初の問題を見ていますし、あなたのクエリがあり、 あなたがLLVMCreateMCJITCompilerForModuleを呼び出したときに、それは以下の、実行エンジンのモジュールリストに供給されたモジュールを追加しましたがExecutionEngineBindingsに同じのカットコードです.cppファイル:あなたがLLVMDisposeExecutionEngineを呼び出したときに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); 

ので、エンジンのリストに記載されているすべてのモジュールを削除していたので、適切な方法を使用すると、実行エンジンを配置する前に、リストからモジュール/秒を削除する必要があります。 LLVMInitializeNativeTarget(前でなければならない

LLVMRemoveModule(engine, mod, &mod, &error); 
LLVMDisposeExecutionEngine(engine); 

及び第二JITがにリンクされていないが、LLVMLinkInMCJITへの呼び出し()は存在しない);(258コードと同じファイル内にExecutionEngineBindings.cppあります)あなたがここで見るものによると

LLVMLinkInMCJIT(); 
LLVMInitializeNativeTarget(); 
関連する問題