如何将函数指针转换为LLVM值,以便在我的IR中调用它?

3

我正在开发类JIT工具,以下是代码:

Obj doSomething(Obj o, Selector sel){
    ...
}

我有一个指向这个函数的指针,我的问题是如何将指针包装成LLVM:Value,以便我可以使用IRBuilder.CreateCall将其插入我的IR中。我需要做什么?


对于void类型的函数,该过程在这里有解释。然而,你的情况要复杂得多,因为你需要创建正确的类型,而不仅仅是使用Type::getVoidTy。似乎网上没有任何好的示例展示如何做到这一点。如果可能的话,你可以使用指针(最好是void *)和一个包装函数来简化情况。 - antipattern
2个回答

1
我遇到了类似的问题。我的玩具程序相当于以下C程序,但需要在运行时生成boo()函数:
#include <stdio.h>
typedef int (*callback)(const char*);
static int boo(callback print, const char *str) { return print(str); }
int main() { return boo(puts, "hello world"); }

我相信我的解决方案至少能适用于LLVM 9到14版本,基于对这两个版本的测试。

#include "llvm/ExecutionEngine/Orc/LLJIT.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Verifier.h"
#include "llvm/Support/InitLLVM.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/raw_ostream.h"

int main()
{
  llvm::InitializeNativeTarget();
  llvm::InitializeNativeTargetAsmPrinter();

  auto C = std::make_unique<llvm::LLVMContext>();
  auto M = std::make_unique<llvm::Module>("boomodule", *C);

  const auto ArgType = llvm::Type::getInt8Ty(*C)->getPointerTo();
  std::vector<llvm::Type *> PutsArgs{ArgType};
  llvm::FunctionType *PutsType =
    llvm::FunctionType::get(llvm::Type::getInt32Ty(*C), PutsArgs, false);
  llvm::FunctionType *FT =
    llvm::FunctionType::get(llvm::Type::getInt32Ty(*C),
                            {PutsType->getPointerTo(), ArgType}, false);

  {
    llvm::Function *TheFunction =
      llvm::Function::Create(FT, llvm::Function::ExternalLinkage,
                             "boo", M.get());
    {
      llvm::IRBuilder<> builder(llvm::BasicBlock::Create(*C, "entry",
                                                         TheFunction));
      auto Arg = TheFunction->arg_begin();
      llvm::FunctionCallee FC{PutsType, Arg++};
      builder.CreateRet(builder.CreateCall(FC, Arg));
    }
    assert(!llvm::verifyFunction(*TheFunction, &llvm::errs()));
    // TheFunction->dump();
  }

  llvm::ExitOnError ExitOnErr;
  auto J = ExitOnErr(llvm::orc::LLJITBuilder().create());
  ExitOnErr(J->addIRModule
            (llvm::orc::ThreadSafeModule(std::move(M), std::move(C))));
  auto BooAddr = ExitOnErr(J->lookup("boo"));
  typedef int (*callback)(const char*);
  auto boo =
    reinterpret_cast<int(*)(callback, const char*)>(BooAddr.getAddress());
  return boo(puts, "hello world");
}
// c++ lljit.cc $(llvm-config --cxxflags --ldflags --system-libs --libs core)

我找到了一些其他的例子,其中使用CreateAlloca()来存储和加载函数指针。在我的应用程序中,我将通过参数传递一个函数指针数组给生成的函数。


0

(我理解你的问题是:我有一个指向LLVM函数的C++指针,我需要创建一个对它进行调用的调用,如果我理解错了,请在帖子中或下面的评论中澄清)

大多数LLVM类都派生自llvm::Value,当您执行以下操作时:

llvm::Function *theFunction = llvm::Function::Create(...);

llvm::Functionllvm::Value 的子类,您可以在 CreateCall 中使用它。

Value *result = Builder.CreateCall(theFunction, ...); // This is the call instruction

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接