4

基于万花筒万花筒与 MCJIT教程,我有代码来创建一个模块和函数并使用 MCJIT 调用它。该函数需要一个原型:

auto ft = llvm::FunctionType::get(llvm::Type::getInt32Ty(Context), argTypes, false);

但是,该示例仅涵盖 Double 作为参数和返回值(上面使用了 int)。要进行任何高级操作,您需要传递类和容器之类的东西。

您如何在模块中使用现有的 C++ 类?

当然,你可以链接到任何你想要的库,但是你需要声明函数原型才能使用它们。如果库 API 有类,你如何声明它们?

我想要的是这样的:

auto ft = llvm::FunctionType::get(llvm::Type::getStructTy("class.std::string"), argTypes, false);

其中 class.std::string 已从 string.h 导入。

LLVM API 只有原始类型。您可以定义结构来表示类,但这太难以手动完成(而且不可移植)。

一种方法可能是将类编译为位码并将其读入模块,但我想尽可能避免使用临时文件。另外我不确定如何从模块中提取类型,但应该是可能的。我在我的一个类的头文件上尝试了这个(我将头文件重命名为 cpp 文件,否则 clang 会变成 .gch 预编译的头文件),结果只是一个常数......也许它被优化了?我在cpp文件上试了一下,结果是36000行代码......

然后我找到了这个页面。我应该使用 Clang API 而不是使用 LLVM API,因为 Clang 作为编译器,可以将代码编译成模块。然后我可以将 LLVM API 与导入的模块一起使用。这是正确的方法吗?任何工作的源代码都会受到赞赏,因为它需要很长时间才能使函数调用工作(教程已过时且文档稀缺)。

4

1 回答 1

1

我这样做的方法是将类编译为 LLVM IR,然后链接这两个模块。然后,有两个选项可以从模块中提取类型:

首先,您可以使用llvm::TypeFinder. 您使用它的方式是创建它,然后run()使用模块作为参数调用它。此代码段将打印出模块中的所有类型:

llvm::TypeFinder type_finder;
type_finder.run(module, true);
for (auto t : type_finder) {
  std::cout << t->getName().str() << std::endl;
}

或者,可以使用Module'getIdentifiedStructTypes()方法并以与上述相同的方式迭代结果向量。

于 2021-12-22T02:57:16.543 回答