2010-03-13 11 views
15

यह शायद कुछ बुनियादी क्योंकि मैं सिर्फ LLVM जानने के लिए शुरू कर रहा हूँ ..एलएलवीएम जेआईटी segfaults। मैं क्या गलत कर रहा हूं?

निम्नलिखित एक भाज्य समारोह बनाता है और Git और यह अमल (मुझे पता है क्योंकि मैं और स्थिर संकलन करने में सक्षम था उत्पन्न समारोह सही है की कोशिश करता है इसे निष्पादित करो)। लेकिन मैं विभाजन समारोह के निष्पादन पर गलती मिल (EE- में> runFunction (TheF, args))

#include "llvm/Module.h" 
#include "llvm/Function.h" 
#include "llvm/PassManager.h" 
#include "llvm/CallingConv.h" 
#include "llvm/Analysis/Verifier.h" 
#include "llvm/Assembly/PrintModulePass.h" 
#include "llvm/Support/IRBuilder.h" 
#include "llvm/Support/raw_ostream.h" 
#include "llvm/ExecutionEngine/JIT.h" 
#include "llvm/ExecutionEngine/GenericValue.h" 


using namespace llvm; 


Module* makeLLVMModule() { 
    // Module Construction 
    LLVMContext& ctx = getGlobalContext(); 
    Module* mod = new Module("test", ctx); 
    Constant* c = mod->getOrInsertFunction("fact64", 
    /*ret type*/       IntegerType::get(ctx,64), 
             IntegerType::get(ctx,64), 
    /*varargs terminated with null*/  NULL); 

    Function* fact64 = cast<Function>(c); 
    fact64->setCallingConv(CallingConv::C); 
    /* Arg names */ 
    Function::arg_iterator args = fact64->arg_begin(); 
    Value* x = args++; 
    x->setName("x"); 


    /* Body */ 
    BasicBlock* block = BasicBlock::Create(ctx, "entry", fact64); 
    BasicBlock* xLessThan2Block= BasicBlock::Create(ctx, "xlst2_block", fact64); 
    BasicBlock* elseBlock = BasicBlock::Create(ctx, "else_block", fact64); 
    IRBuilder<> builder(block); 

    Value *One = ConstantInt::get(Type::getInt64Ty(ctx), 1); 
    Value *Two = ConstantInt::get(Type::getInt64Ty(ctx), 2); 

    Value* xLessThan2 = builder.CreateICmpULT(x, Two, "tmp"); 
//builder.CreateCondBr(xLessThan2, xLessThan2Block, cond_false_2); 
    builder.CreateCondBr(xLessThan2, xLessThan2Block, elseBlock); 


    /* Recursion */ 
    builder.SetInsertPoint(elseBlock); 
    Value* xMinus1 = builder.CreateSub(x, One, "tmp"); 
    std::vector<Value*> args1; 
    args1.push_back(xMinus1); 
    Value* recur_1 = builder.CreateCall(fact64, args1.begin(), args1.end(), "tmp"); 
    Value* retVal = builder.CreateBinOp(Instruction::Mul, x, recur_1, "tmp"); 
    builder.CreateRet(retVal); 

    /* x<2 */ 
    builder.SetInsertPoint(xLessThan2Block); 
    builder.CreateRet(One); 
    return mod; 
} 

int main(int argc, char**argv) { 
    long long x; 
    if(argc > 1) 
    x = atol(argv[1]); 
    else 
    x = 4; 

    Module* Mod = makeLLVMModule(); 

    verifyModule(*Mod, PrintMessageAction); 
    PassManager PM; 
    PM.add(createPrintModulePass(&outs())); 
    PM.run(*Mod); 

    // Now we going to create JIT 
    ExecutionEngine *EE = EngineBuilder(Mod).create(); 
    // Call the function with argument x: 
    std::vector<GenericValue> Args(1); 
    Args[0].IntVal = APInt(64, x); 
    Function* TheF = cast<Function>(Mod->getFunction("fact64")) ; 

    /* The following CRASHES.. */ 
    GenericValue GV = EE->runFunction(TheF, Args); 
    outs() << "Result: " << GV.IntVal << "\n"; 
    delete Mod; 
    return 0; 
} 

संपादित करें: JIT सक्षम करने के लिए (नीचे स्वीकार किए जाते हैं जवाब देखें) सही तरीका:

1.#include "llvm/ExecutionEngine/Jit.h"` 

2.InitializeNativeTarget(); 

उत्तर

10

मैं शर्त लगा सकता है कि ExecutionEngine सूचक शून्य है .... आप InitializeNativeTarget के लिए एक कॉल याद कर रहे हैं, प्रलेखन कहते हैं:

InitializeNativeTarget - मुख्य कार्यक्रम इसी देशी लक्ष्य को प्रारंभ करने के लिए इस समारोह फोन करना चाहिए मेजबान के लिए। यह जेआईटी अनुप्रयोगों के लिए यह सुनिश्चित करने के लिए उपयोगी है कि लक्ष्य सही ढंग से जुड़ा हुआ हो।

चूंकि कोई JIT कम्पाइलर InitializeNativeTarget बुला बिना उपलब्ध है, ModuleBuilder दुभाषिया (यदि उपलब्ध हो) का चयन करता है। शायद आप जो चाहते थे वह नहीं। आप look at my previous post on this subject चाहते हैं।

+1

धन्यवाद। बहुत उपयोगी जानकारी। क्या इसका मतलब यह है कि जेआईटी का उपयोग करने के लिए और इंटरपरेटर नहीं, मुझे llvm/ExecutionEngine/Interpreter.h के निष्पादन एंजिन/JIT.h INSTEAD शामिल करना चाहिए? – GabiMe

+1

हां, यदि आप जेआईटी चाहते हैं, तो JIT.h शामिल करें और ExecutionEngine बनाने से पहले InitializeNativeTarget() को कॉल करना सुनिश्चित करें। आप यह सुनिश्चित करने के लिए कि आप एक जेआईटी प्राप्त कर रहे हैं, सुनिश्चित करने के लिए .create() को कॉल करने से पहले EngineBuilder.setEngineKind (EngineKind :: JIT) को भी कॉल करना चाहेंगे। –

+0

मेरी इच्छा है कि मैं इसे और अधिक वोट दे सकता हूं। मैंने इस मुद्दे को शिकार करने में लगभग एक घंटा बिताया। मुझे लगता है कि मुझे थोड़ा बेहतर आरटीएफएम सीखना होगा। :) एक बार फिर धन्यवाद! – HVS

1
#include "llvm/ExecutionEngine/Interpreter.h" 
+0

इसमें शामिल होने पर कोई अंतर्दृष्टि क्यों हल करती है? – tstenner

+0

हां। अच्छा प्रश्न। क्यूं कर ? – GabiMe

2

कि हैडर (llvm/ExecutionEngine/Interpreter.h) सहित JIT की एक स्थिर initialisation बाध्य करती है। सबसे अच्छा डिजाइन निर्णय नहीं है, लेकिन कम से कम यह काम करता है।

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