使用 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
实例。
我正在使用 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
实例。