2016-03-20 7 views
2

ich ein einfaches Programm mit LLVM-C:Wie kann man LLVModule und LLVExecutionEngine korrekt zerstören?

#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; 
} 

Wie ist, Segfaults es innerhalb von 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 

Allerdings, wenn ich entweder den Anruf an LLVMDisposeExecutionEngine oder LLVMDisposeModule, kommentieren Sie es nicht länger segfaults.

Was ist der richtige Weg, um ein LLVM-Modul und eine Ausführungs-Engine mit der C-API zu zerstören?

+0

Nach dem, was Sie hier sehen: https://lists.freedesktop.org/archives/mesa-dev/2014-May/059352.html LLVMDisposeExecutionEngine verfügt auch das Modul, so dass nur einer von ihnen nennen, vorzugsweise der Motor, wenn es existiert. –

Antwort

1

ich zwei Probleme mit kotierten Code sehe,

erste Problem und Ihre Abfrage ist, wenn Sie genannt LLVMCreateMCJITCompilerForModule es Modul der Modulliste des Ausführungs-Engine, unten geliefert hinzugefügt wird der Schnitt-Code für das gleiche in 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); 

so, wenn Sie LLVMDisposeExecutionEngine genannt hatte es alle Module gelöscht, in Motor Liste aufgeführt ist, so ist der richtige Weg ist, müssen Sie Ihr Modul/s aus der Liste entfernen, bevor die Ausführungsmaschine zu entsorgen. (Code ist in der gleichen Datei ExecutionEngineBindings.cpp: 258)

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

und die zweite ist JIT wurde nicht verknüpft in, gibt es keinen Aufruf LLVMLinkInMCJIT ist(), die vor LLVMInitializeNativeTarget sein sollte();

LLVMLinkInMCJIT(); 
LLVMInitializeNativeTarget(); 
Verwandte Themen