1

所以...我最近(现在大约 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";
4

0 回答 0