使用 LLVM c++ API 创建 "class" 定义

Creating a "class" definition using LLVM c++ API

我正在使用 LLVM c++ api 开发自定义前端语言,并且正在向该语言添加“class”定义结构。词法分析器和解析器是用 C++ 编写的,LLVM c++ api 用于生成 IR 代码并编译到不同的机器后端。我已经可以使用自定义前端语言定义函数和变量、调用函数和计算基本算术。

为了在语言中添加“class”定义,我遵循 https://mapping-high-level-constructs-to-llvm-ir.readthedocs.io/en/latest/object-oriented-constructs/classes.html

上的建议

这建议我们创建一个“structtype”来包含class的所有数据成员,并为class的方法单独定义一堆函数(如果我理解link正确)。​​

因此在我的编译器代码中,我定义了一个名为“ClassAST”的 AST 节点,它包含 class 的数据成员的名称和类型以及“[=] 的方法的函数定义集合。 51=]" 在前端语言中定义。 AST节点的c++代码片段如下:

class ClassAST {
public:
  std::vector<std::unique_ptr<FunctionAST>> function_members;
  std::vector<std::unique_ptr<ExprAST>> data_members;
  std::unique_ptr<PrototypeAST> Proto;
  ClassAST(std::unique_ptr<PrototypeAST> Proto,std::vector<std::unique_ptr<FunctionAST>> function_members,
              std::vector<std::unique_ptr<ExprAST>> data_members)
    : Proto(std::move(Proto)),function_members(std::move(function_members)), data_members(std::move(data_members)) {}

  llvm::Type *codegen(IRgen *irgen);
}

在代码片段中,FunctionAST、ExprAST、PrototypeAST 是我为了分别表示函数、表达式和函数原型而定义的其他 AST 节点类型,用于它们的 IR 代码生成。 “IRgen”是一个 class 我定义为包含我的编译器的 llvm::Context、llvm::Module、llvm::IRBuilder 实例。

现在,为了生成 ClassAST 节点的 IR 代码,我定义了“codegen”,函数为

llvm::Type *ClassAST::codegen(IRgen *irgen){
  // create a struct type with all the data_members
  llvm::StructType *class_StructType = llvm::StructType::create(irgen->TheContext);
  class_StructType->setName(Proto->Name);
  std::vector<llvm::Type *> DataTypes;
  for(int i=0;i<data_members.size();i++){
    DataTypes.push_back(llvm::Type::getDoubleTy(irgen->TheContext)); // assume all data types are doubles for now
  }
  class_StructType->setBody(DataTypes);
  // add the type to the symbol table (How to do this?)
  // .. ????? ..
  // codegen the function members
  for (int i=0;i<function_members.size();i++){
    auto RetVal = function_members[i]->codegen(irgen);
    if(!RetVal){
      // Error reading body, remove function.
      LogErrorV(("Error generating code for "+Proto->Name+"."+function_members[i]->Proto->Name).c_str());
    }
  }
  return class_StructType;
}

上面的 codegen(..) 函数成功创建了 class_StructType 以包含适当的 data_member 类型并为定义的 'function_members' 生成 IR 代码并将函数定义添加到'irgen'.

中的 llvm::Module 实例

但是,我不知道如何将 class_StructType 类型添加到 llvm::Module 实例,以便以后的代码可以检索类型并创建 class_StructType 的实例。

有人可以阐明如何将新的 StructType 添加到 llvm:Module 实例吗?(我使用的是最新的 llvm 12.0 api,但更老的 api 11.0 应该没问题。

查看 Module::getTypeByName 的源代码,它在 LLVMContext 实例中查找名称。这意味着你不必将你的类型添加到模块中,名称查找应该可以正常工作,即使是通过 Module 实例。