3

我正在使用 LLVM 实现 JIT 编译器的前端。我从 LLVM 教程中的 Kaleidoscope 示例开始。我知道如何使用 LLVM C++ API 生成和 JIT LLVM IR。我也知道如何调用 JITed 函数,使用 llvm::ExecutionEngine 的“getPointerToFunction”方法。

getPointerToFunction 返回一个 void* ,然后我必须将其转换为正确的函数类型。例如,在我的编译器中,我有如下所示的单元测试:

void* compiled_func = compiler.get_function("f");   
auto f = reinterpret_cast<int32_t(*)(int32_t)>(compiled_func);
int32_t result = f(10);

问题是我必须事先知道函数签名。在上面的示例中,我有一个函数“f”,它接受一个 32 位整数并返回一个 32 位整数。因为我自己创建了“f”,所以我知道函数类型是什么,所以我可以调用 JIT 函数。但是,一般来说,我不知道用户输入的函数签名是什么(或结构类型是什么)。用户可以创建具有任意参数和返回类型的任意函数,所以我不知道从 LLVM 的 getPointerToFunction 转换 void* 的函数指针类型。我的运行时需要能够调用这些函数(例如,对于 Read-Evaluate-Print 循环)。如何从我的 JIT 运行时处理这些任意函数?

谢谢

4

1 回答 1

2

您可以从中获得的信息不多compiled_func- 正如您所写,它只是一个void*. 但是当你写“一般来说,我不知道函数签名是什么”时,这是不准确的——你刚刚编译了那个函数,所以你应该可以访问 LLVMFunction对象,可以查询它的类型。的确,它是 LLVM IR 类型而不是 C++ 类型,但您通常可以知道哪个转换为哪个。

例如,如果我们从教程的 JITting Kaleidoscope 部分借用代码:

if (Function *LF = F->Codegen()) {
  LF->dump();  // Dump the function for exposition purposes.

  // JIT the function, returning a function pointer.
  void *FPtr = TheExecutionEngine->getPointerToFunction(LF);

  // Cast it to the right type (takes no arguments, returns a double) so we
  // can call it as a native function.
  double (*FP)() = (double (*)())(intptr_t)FPtr;
  fprintf(stderr, "Evaluated to %f\n", FP());
}

那么是的,FPtr被“假定”为 type double (),但这里也LF有 type Function*,所以你可以做类似的事情:

Type* RetTy = LF->getReturnType();
if (RetTy->isDoubleTy()) {
  double (*FP)() = (double (*)())(intptr_t)FPtr;
  fprintf(stderr, "Evaluated to %f\n", FP());
} else if (RetTy->isIntegerTy(32)) {
  int (*FP)() = (int (*)())(intptr_t)FPtr;
  fprintf(stderr, "Evaluated to %d\n", FP());
} else ...

以同样的方式,您可以查询函数的参数类型。

有点麻烦?您可以使用执行引擎通过其方便的runFunction方法调用该函数,该方法接收 s 的向量GenericValue并返回 a GenericValue。您仍然应该查询Function类型以查找每个类型下的基础类型GenericValue应该是什么。

于 2013-04-08T06:41:51.837 回答