Steve
Steve

Reputation: 304

exposing internal c++ function to llvm jit'd c++

I'm trying to experiment with llvm right now. I'd like to use languages that can be compiled to llvm bitcode for scripting. I've managed so far to load an llvm bitcode module and call a function defined in it from my 'internal' c++ code. I've next tried to expose a c++ function from my internal code to the jit'd code - so far in this effort I haven't managed to get anything but SEGFAULT.

My code is as follows. I've tried to create a Function and a global mapping in my execution engine that points to a function I'd like to call.

extern "C" void externGuy()
{
   cout << "I'm the extern guy" << endl;
}
void ExposeFunction()
{
   std::vector<Type*> NoArgs(0);
   FunctionType* FT = FunctionType::get(Type::getVoidTy(getGlobalContext()), NoArgs, false);
   Function* fnc = Function::Create(FT, Function::ExternalLinkage, "externGuy", StartModule);
   JIT->addGlobalMapping(fnc, (void*)externGuy);
}
// ... Create module, create execution engine
ExposeFunction();

Is the problem that I can't add a function to the module after its been loaded from bitcode file?

Update: I've refactored my code so that it reads like so instead:

// ... Create module, create execution engine
std::vector<Type*> NoArgs(0);
FunctionType* FT = FunctionType::get(Type::getVoidTy(getGlobalContext()), NoArgs, false);
Function* fnc = Function::Create(FT, Function::ExternalLinkage, "externGuy", m);
fnc->dump();
JIT->addGlobalMapping(fnc, (void*)externGuy);

So instead of segfault I get:

Program used external function 'externGuy' which could not be resolved 

Also, the result of dump() prints:

declare void @externGuy1()

If I change my c++ script bitcode thing to call externGuy1() instead of externGuy() it will suggest to me that I meant to use the externGuy. The addGlobalMapping just doesn't seem to be working for me. I'm not sure what I'm missing here. I also added -fPIC to my compilation command like I saw suggested in another question - I'm honestly not sure if its helped anything but no harm in trying.

Upvotes: 1

Views: 583

Answers (1)

Steve
Steve

Reputation: 304

I finally got this to work. My suspicion is to maybe creating the function, as well as defining it in the script is causing perhaps more than 1 declaration of the functions name and the mapping just wasn't working out. What I did was define the function in the script and then use getFunction to use for mapping instead. Using the dump() method on the function output:

declare void @externGuy() #1

Which is why I think that had something to do with the mapping not working originally. I also remember the Kaleidoscope tutorial saying that getPointerToFunction would do the JIT compiling when its called if it isn't already done so I thought that I would have to do the mapping before this call.

So altogether to get this whole thing working it was as follows:

// Get the function and map it
Function* extrn = m->getFunction("externGuy");
extrn->dump();
JIT->addGlobalMapping(extrn, (void*)&::externGuy);
// Get a pointer to the jit compiled function
Function* mane = m->getFunction("hello");
void* fptr = JIT->getPointerToFunction(mane);
// Make a call to the jit compiled function which contains a call to externGuy
void (*FP)() = (void(*)())(intptr_t)fptr;
FP();

Upvotes: 1

Related Questions