如何调用未知类型的JITed LLVM函数?

时间:2013-04-07 17:05:20

标签: llvm jit llvm-c++-api

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

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运行时处理这些任意函数?

由于

1 个答案:

答案 0 :(得分:2)

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

例如,如果我们从tutorial's section on 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被“假设”为double ()类型,但此处还有LF 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方法调用该函数,该方法接收GenericValue s的向量并返回GenericValue。您仍应查询Function类型,以查找每个GenericValue下的基础类型。