使用 LLVM c++ API 创建“类”定义
Posted
技术标签:
【中文标题】使用 LLVM c++ API 创建“类”定义【英文标题】:Creating a "class" definition using LLVM c++ API 【发布时间】:2021-02-14 06:49:34 【问题描述】:我正在使用 LLVM c++ api 开发一种自定义前端语言,并向该语言添加“类”定义构造。词法分析器和解析器是用 C++ 编写的,LLVM c++ api 用于生成 IR 代码并编译到不同的机器后端。我已经可以使用自定义前端语言定义函数和变量、调用函数和评估基本算术。
为了给语言添加“类”定义,我遵循https://mapping-high-level-constructs-to-llvm-ir.readthedocs.io/en/latest/object-oriented-constructs/classes.html上的建议
这建议我们创建一个“structtype”来包含该类的所有数据成员,并为该类的方法单独定义一堆函数(如果我正确理解链接的话)。
因此,在我的编译器代码中,我定义了一个名为“ClassAST”的 AST 节点,其中包含类的数据成员的名称和类型以及前面定义的“类”方法的函数定义集合 -结束语。 AST节点的c++代码sn-p如下:
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);
在 sn-p 中,FunctionAST、ExprAST、PrototypeAST 是我定义的其他 AST 节点类型,用于分别表示函数、表达式和函数原型,并用于相同的 IR 代码生成。 “IRgen”是我定义的一个类,其中包含用于我的编译器的 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 应该没问题)。
【问题讨论】:
【参考方案1】:查看Module::getTypeByName
的源代码,它在LLVMContext
实例中查找名称。这意味着您不必将您的类型添加到模块中,并且名称查找应该可以正常工作,即使通过 Module
实例也是如此。
【讨论】:
谢谢@llCapitano!这似乎行得通。我会用类功能做更多的测试,让你知道。最好的问候。以上是关于使用 LLVM c++ API 创建“类”定义的主要内容,如果未能解决你的问题,请参考以下文章