Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Linking LLVM JIT code to external C++ functions

Tags:

jit

linker

llvm

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

like image 786
anton skvorts Avatar asked Dec 13 '10 04:12

anton skvorts


People also ask

What is an LLVM 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. Here we’ve declared a makeLLVMModule()function to do the real work of creating the module.

What are LLVM segments?

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.

How does the LLVM IR work?

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.

What is LLVM-configutility used for?

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


2 Answers

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!

like image 128
Nick Lewycky Avatar answered Oct 31 '22 16:10

Nick Lewycky


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().

like image 41
Tarantula Avatar answered Oct 31 '22 16:10

Tarantula