所以...我最近(现在大约 2 周)一直在研究 LLVM。我已经阅读了文档,浏览了教程等。
我决定尝试更进一步,即将类型引入 Kaleidoscope 教程。当我发现 MCJIT 只会在具有主要样式签名的函数上运行Function() 时,我立即碰壁了。现在我明白了为什么本教程将函数包装在 anon 函数中......
我花了很长时间试图在这方面取得进展,但没有运气。我在网上找不到任何这样的例子,这看起来很奇怪。我已经能够将 ExecutionEngine 更改为使用 Interpreter 并获得了完美的结果,但这似乎毫无意义,我不妨在 C++ 中编写一个“核心库”并有条件地调用这些函数。
我知道我可以 finaliseObject() 并获取函数指针,但它只是将事情向后移动,因为我必须转换函数,虽然我知道函数签名,但我不知道动态转换函数指针的方法。
我的问题是假设我准备好了一个 LLVM 函数,添加到一个模块等。我如何通过 MCJIT 调用这个函数?
谢谢你的帮助。
以下是我当前的暂存代码。
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();
现在,如果我得到一个指向函数的指针,那就成功了!有用。
int (*function)(int, int) = (int (*)(int, int))EE->getPointerToFunction(func);
int resi = function(11, 13);
outs() << "Result: " <<resi << "\n";
但是,如果我尝试在 EE 中运行该函数,则会得到“尚不支持全功能参数传递!”
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";