[llvm-dev] llvm interpreter does not find function defined by addGlobalMapping

via llvm-dev llvm-dev at lists.llvm.org
Mon Sep 19 05:34:45 PDT 2016


Hi,

I want to use a function defined in c(++)-code from code generated by llvm. For this I use ExecutionEngine.addGlobalMapping(). I started with the JIT execution engine and everything worked, then I switched to the interpreter engine and it stopped working, but only if compiled on a Linux system. More precisely it works if I use

    llvm 3.8.1 + gcc (Linux) + JIT
    llvm 3.8.0 + mingw-gcc (Windows) + JIT
    llvm 3.8.0 + mingw-gcc (Windows) + Interpreter

But it does not work for llvm 3.8.1 + gcc (Linux) + Interpreter. In that case I get the error message "LLVM ERROR: Tried to execute an unknown external function: testFunction." Am I using ExecutionEngine.addGlobalMapping() in the wrong way, even it works in three out of four scenarios?

#include <llvm/Support/TargetSelect.h>
#include <llvm/Analysis/Passes.h>
#include <llvm/Transforms/Scalar.h>
#include <llvm/Transforms/IPO/PassManagerBuilder.h>
#include <llvm/Transforms/IPO.h>
#include <llvm/IR/Verifier.h>
#include <llvm/ExecutionEngine/ExecutionEngine.h>
#include <llvm/ExecutionEngine/Interpreter.h>
#include <llvm/ExecutionEngine/MCJIT.h>
#include <llvm/ExecutionEngine/GenericValue.h>
#include <llvm/IR/LegacyPassManager.h>
#include <llvm/IR/IRBuilder.h>

extern "C" double testFunction(){
  return 42.0;
}

int main() {
  // initialization needed for JIT
  llvm::InitializeNativeTarget();
  llvm::InitializeNativeTargetAsmPrinter();
  llvm::InitializeNativeTargetAsmParser();

  llvm::LLVMContext &context(llvm::getGlobalContext());
  llvm::Module *pModule = new llvm::Module("a module", context);

  // Here the EngineKind-flag decides if JIT or interpreter is used.
  auto pExecutionEngine = llvm::EngineBuilder(std::unique_ptr<llvm::Module>(pModule)
    ).setEngineKind(llvm::EngineKind::Interpreter).create();
  pModule->setDataLayout(pExecutionEngine->getDataLayout());

  // declaration of the c function.
  std::vector<llvm::Type *> noArgTypes;
  llvm::FunctionType* ft = llvm::FunctionType::get(llvm::Type::getDoubleTy(context),noArgTypes, false);
  auto pFunction = llvm::Function::Create(ft, llvm::Function::ExternalLinkage, "testFunction",pModule);
  pExecutionEngine->addGlobalMapping(pFunction,reinterpret_cast<void*>(&testFunction));

  // generation of llvm code
  auto pBlock = llvm::BasicBlock::Create(context, "evaluation");
  llvm::IRBuilder<> builder(context);
  builder.SetInsertPoint(pBlock);

  // code for call of the c function.
  auto pFunction2 = pModule->getFunction("testFunction");
  auto temp = builder.CreateCall(pFunction2, std::vector<llvm::Value*>(), "calltmp");
  builder.CreateRet(temp);

  // generation of the llvm function calling the c function
  llvm::FunctionType* ftWrapper = llvm::FunctionType::get(llvm::Type::getDoubleTy(context),noArgTypes, false);
  auto pWrapperFunction = llvm::Function::Create(ftWrapper, llvm::Function::ExternalLinkage, "AFunction",pModule);
  pWrapperFunction->getBasicBlockList().push_back(pBlock);

  // calling the generated llvm function
  pExecutionEngine->finalizeObject();
  pExecutionEngine->runFunction(pWrapperFunction,std::vector<llvm::GenericValue>());
}

Thanks for any help,
Markus


More information about the llvm-dev mailing list