2015-01-01 7 views
9

मैं एक ऐसे प्रोजेक्ट पर काम कर रहा हूं जहां मैं कुछ एलएलवीएम आईआर उत्पन्न करने के लिए क्लैंग का उपयोग करता हूं और फिर जेआईटी-संकलन करता हूं और इसे अपने होस्ट एप्लिकेशन के भीतर से चलाता हूं। जेआईटी कोड मेजबान एप्लिकेशन में कुछ फ़ंक्शन कॉल करता है जो अपवाद फेंक सकता है। मैं उम्मीद करता हूं कि अपवाद को जेआईटी कोड के माध्यम से फेंक दिया जाए और मेजबान आवेदन में वापस लाया जाए। AFAIK यह एलएलवीएम के साथ काम करना चाहिए, लेकिन दुर्भाग्य से मेरा परीक्षण आवेदन हमेशा "int 'के उदाहरण को फेंकने के बाद बुलाया जाता है। मुझे कुछ सरल उदाहरण दें।एलएलवीएम जेआईटी: जेआईटी कोड के माध्यम से सी ++ अपवाद को होस्ट करने के लिए वापस

मैं बजना 3.5 का उपयोग LLVM आईआर में निम्नलिखित साधारण प्रोग्राम को संकलित करने के:

extern void test() ; 

extern "C" void exec(void*) { 
     test(); 
} 

साथ

./clang -O0 -S -emit-llvm test.cpp -c 

परिणाम test.ll

; ModuleID = 'test.cpp' 
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" 
target triple = "x86_64-unknown-linux-gnu" 

; Function Attrs: uwtable 
define void @exec(i8*) #0 { 
    %2 = alloca i8*, align 8 
    store i8* %0, i8** %2, align 8 
    call void @_Z4testv() 
    ret void 
} 

declare void @_Z4testv() #1 

attributes #0 = { uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } 
attributes #1 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } 

!llvm.ident = !{!0} 

!0 = metadata !{metadata !"clang version 3.5.0 (224841)"} 

मेरे मेजबान आवेदन दिखता है इस तरह:

static void test() { 
    throw 1; 
} 

int main(int, const char **) { 
    llvm::InitializeNativeTarget(); 
    llvm::InitializeNativeTargetAsmPrinter(); 
    llvm::InitializeNativeTargetAsmParser(); 

    llvm::LLVMContext &Context = llvm::getGlobalContext(); 
    llvm::SMDiagnostic Err; 
    llvm::Module *Mod = llvm::ParseIRFile("test.ll", Err, Context); 

    llvm::ExecutionEngine* m_EE = llvm::EngineBuilder(Mod) 
      .setEngineKind(llvm::EngineKind::JIT) 
      .create(); 

    llvm::Function* f = Mod->getFunction("_Z4testv"); 
    m_EE->addGlobalMapping(f, reinterpret_cast<void*>(test)); 

    f = Mod->getFunction("exec"); 

    void* poi = m_EE->getPointerToFunction(f); 
    void (*exec)(void*) = reinterpret_cast<void (*)(void*)>(poi); 

    try { 
     exec(NULL); 
    } catch (...) { 
     std::cout << "catched exception" << std::endl; 
    } 

    return 0; 
} 

मैं एलएलवीएम 3.5 का उपयोग करता हूं जिसे मैंने सेमेक के साथ संकलित किया है। मैंने LLVM_ENABLE_EH = ON और LLVM_ENABLE_RTTI = चालू सेट किया है। क्या मुझे एलएलवीएम संकलित करते समय कुछ याद आया या मेरा होस्ट एप्लिकेशन कोड गलत है?

धन्यवाद!

उत्तर

6

आखिर में यह काम करता है और यहां कुछ चीजें हैं जो इस मुद्दे को ठीक करने के लिए आवश्यक हैं।

सबसे पहले यह सुनिश्चित करना महत्वपूर्ण है कि एमसीजेआईटीएच शामिल किया गया है, अन्यथा एमसीजेआईटी शामिल नहीं है। दुर्भाग्यवश एलएलवीएम चुपचाप पुराने जेआईटी कार्यान्वयन पर वापस आ जाता है अगर एमसीजेआईटीएच को शामिल नहीं किया गया है, भले ही एमसीजेआईटी द्वारा स्पष्ट रूप से अनुरोध किया गया हो :

llvm::EngineBuilder factory(Mod); 
factory.setEngineKind(llvm::EngineKind::JIT); 
factory.setUseMCJIT(true); 

केवल एमसीजेआईटी प्रोपर अपवाद हैंडलिंग का समर्थन करता है।

प्रश्न में उदाहरण में मैं

Execution::Engine::addGlobalMapping() 

जो MCJIT साथ काम नहीं करता इस्तेमाल किया।

static void test() { 
    throw 1; 
} 

int main(int, const char **) { 
    llvm::InitializeNativeTarget(); 
    llvm::InitializeNativeTargetAsmPrinter(); 
    llvm::InitializeNativeTargetAsmParser(); 

    llvm::LLVMContext &Context = llvm::getGlobalContext(); 
    llvm::SMDiagnostic Err; 
    llvm::Module *Mod = llvm::ParseIRFile("test.ll", Err, Context); 

    std::unique_ptr<llvm::RTDyldMemoryManager> MemMgr(new llvm::SectionMemoryManager()); 

    // Build engine with JIT 
    std::string err; 
    llvm::EngineBuilder factory(Mod); 
    factory.setErrorStr(&err); 
    factory.setEngineKind(llvm::EngineKind::JIT); 
    factory.setUseMCJIT(true); 
    factory.setMCJITMemoryManager(MemMgr.release()); 
    llvm::ExecutionEngine *m_EE = factory.create(); 

    llvm::sys::DynamicLibrary::AddSymbol("_Z4testv", reinterpret_cast<void*>(test)); 

    llvm::Function* f = Mod->getFunction("exec"); 

    m_EE->finalizeObject(); 

    void* poi = m_EE->getPointerToFunction(f); 
    void (*exec)(void*) = reinterpret_cast<void (*)(void*)>(poi); 

    try { 
     exec(NULL); 
    } catch (int e) { 
     std::cout << "catched " << e << std::endl; 
    } 
    return 0; 
} 

साथ ही आप कर सकते हैं अब भी जोड़कर JIT कोड के लिए डीबग चिह्न मिल:

Opts.JITEmitDebugInfo = true; 
बाहरी समारोह पूरा उदाहरण के बाद के माध्यम से

llvm::sys::DynamicLibrary::AddSymbol() 

reqistered किया जाना चाहिए

संबंधित मुद्दे