开发者

LLVM JIT segfaults. What am I doing wrong?

开发者 https://www.devze.com 2022-12-22 16:19 出处:网络
It is probably something basic because I am just starting to learn LLVM.. The following creates a factorial function and tries to git and execute it (I know the generated func is correct because I wa

It is probably something basic because I am just starting to learn LLVM..

The following creates a factorial function and tries to git and execute it (I know the generated func is correct because I was able to static compile and execute it). But I get segmentation fault upon execution of the function (in 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;
}

Edit: The correct way to enable JIT (see the accepted answer below):

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

2.InitializeNativeTarget();


I would bet that the ExecutionEngine pointer is null.... You are missing a call to InitializeNativeTarget, the documentation says:

InitializeNativeTarget - The main program should call this function to initialize the native target corresponding to the host. This is useful for JIT applications to ensure that the target gets linked in correctly.

Since there is no JIT compiler available without calling InitializeNativeTarget, ModuleBuilder selects the interpreter (if available). Probably not what you wanted. You may want to look at my previous post on this subject.


#include "llvm/ExecutionEngine/Interpreter.h"


Including that header (llvm/ExecutionEngine/Interpreter.h) forces a static initialisation of the JIT. Not the best design decision, but at least it works.

0

精彩评论

暂无评论...
验证码 换一张
取 消