So... I have recently (~2 weeks now) been diving into LLVM. I have read the docs, walked through the tutorials etc.
I decided to try and take things a bit further, namely bring types into Kaleidoscope tutorial. Immediately I hit a wall when I discovered that MCJIT will only runFunction() on Functions with main style signatures. Now I understand why the tutorial wraps the functions in an anon function...
I have spent a long time trying to get somewhere on this, and to no luck. I can't find any examples of this on the web which seems strange. I have been able to change the ExecutionEngine to use the Interpreter and got perfect results, however this seems kind of pointless, I may as well just write a 'core library' in c++ and call the functions conditionally.
I know I can finaliseObject() and get the function pointer, but it just moves things back one, since I have to cast the function, and while I would know the function signature, I know of no way to dynamically cast a function pointer.
My question is assuming I have an LLVM Function ready to go, added to a module etc. how can I call this function via MCJIT?
Thanks for any help.
Below is my current scratch pad of code.
InitializeNativeTarget();
InitializeNativeTargetAsmPrinter();
LLVMContext context;
IRBuilder<> Builder(context);
std::unique_ptr<Module> Owner(new Module("test", context));
Module *module = Owner.get();
Function* func = cast<Function>(module->getOrInsertFunction("add-test", Type::getInt32Ty(context), Type::getInt32Ty(context), Type::getInt32Ty(context), NULL));
BasicBlock* block = BasicBlock::Create(context, "entry", func);
Builder.SetInsertPoint(block);
Function::arg_iterator args = func->arg_begin();
Argument *arg_l = &*func->arg_begin();
arg_l->setName("arg_l");
Argument *arg_r = &(*++func->arg_begin());
arg_r->setName("arg_r");
Value* add = BinaryOperator::CreateAdd(arg_l, arg_r, "real-add", block);
ReturnInst::Create(context, add, block);
std::string errStr;
ExecutionEngine *EE = EngineBuilder(std::move(Owner)).setErrorStr(&errStr).create();
if (!EE) {
errs() << "Failed to start Execution Engine";
return;
}
EE->finalizeObject();
And now if I get a pointer to the function, Success! it works.
int (*function)(int, int) = (int (*)(int, int))EE->getPointerToFunction(func);
int resi = function(11, 13);
outs() << "Result: " <<resi << "\n";
But If I try and run the function in the EE, then I get "Full-featured argument passing not supported yet!"
std::vector<GenericValue> Args(2);
Args[0].IntVal = APInt(32, 1);
Args[1].IntVal = APInt(32, 2);
GenericValue GV = EE->runFunction(func, Args);
outs() << "Result: " << GV.IntVal << "\n";