I'm writing a LLVM scripting engine that JIT compiles scripting code in a custom language. My problem is that I'm unable to call external functions (even the C99 erf() function is failing).
For example if I extern "C" the erf function,
extern "C" double erft(double x){
return erf(x);
}
and create a function with external linkage
std::vector<const Type*> Double1(1,Type::getDoubleTy(getGlobalContext()));
FunctionType *FT = FunctionType::get(Type::getDoubleTy(getGlobalContext()),Double1,false);
Function *erft = Function::Create(FT,Function::ExternalLinkage,"erft",TheModule);
get the following error message when running my script with erft(0.0) :
LLVM ERROR: Program used external function 'erft' which could not be resolved!
Doing the mapping manually,
void ExecutionEngine::addGlobalMapping( const GlobalValue * erfF, void * erft);
will get me the following error:
declaration of `void llvm::ExecutionEngine::addGlobalMapping(const llvm::GlobalValue*, void*)' outside of class is not definition
Obviously I'm doing something very wrong. Any help would be much appreciated
The first segment is pretty simple: it creates an LLVM “module.” In LLVM, a module represents a single unit of code that is to be processed together. A module contains things like global variables, function declarations, and implementations. Here we’ve declared a makeLLVMModule()function to do the real work of creating the module.
The first segment is pretty simple: it creates an LLVM “module.” In LLVM, a module represents a single unit of code that is to be processed together. A module contains things like global variables, function declarations, and implementations.
Before we start working on a body for our new function, we need to recall some details of the LLVM IR. The IR, being an abstract assembly language, represents control flow using jumps (we call them branches), both conditional and unconditional. The straight-line sequences of code between branches are called basic blocks, or just blocks.
The llvm-configutility is used to obtain the necessary GCC-compatible compiler flags for linking with LLVM. For this example, we only need the 'core' library. We'll use others once we start adding optimizers and the JIT engine. Next: A More Complicated Function
Assuming you haven't disabled it (by calling EE->DisableSymbolSearching()
) then LLVM will use dlsym()
to find the symbols in the JIT program itself. Depending on your platform, that might mean that you need to build your JIT with -fPIC
, or that it might not be available at all (such as on Windows).
Aside from automatic symbol searching, you can always register the individual functions yourself using EE->addGlobalMapping(GV, &function)
where GV = the llvm::Function* function declaration that matches the native function you're calling. In your case with ertf() that's:
EE->addGlobalMapping(erft, &::erft);
Note that you named the global function erft()
and the local variable erft
, hence the "::". Please pick different names next time!
This might be happening because you forgot to add the "libm" depedency, try using:
[your module]->addLibrary("m");
See here for more information about the Module::addLibrary()
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With