refactor(irgen): 完善irgen代码和文档,提升扩展兼容性
This commit is contained in:
@@ -6,7 +6,18 @@
|
||||
#include "ir/IR.h"
|
||||
#include "utils/Log.h"
|
||||
|
||||
void IRGenImpl::GenBlock(SysYParser::BlockContext& block) {
|
||||
namespace {
|
||||
|
||||
std::string GetLValueName(SysYParser::LValueContext& lvalue) {
|
||||
if (!lvalue.ID()) {
|
||||
throw std::runtime_error(FormatError("irgen", "非法左值"));
|
||||
}
|
||||
return lvalue.ID()->getText();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void IRGenImpl::GenBlock(SysYParser::BlockStmtContext& block) {
|
||||
for (auto* item : block.blockItem()) {
|
||||
if (item) {
|
||||
if (GenBlockItem(*item)) {
|
||||
@@ -29,14 +40,21 @@ bool IRGenImpl::GenBlockItem(SysYParser::BlockItemContext& item) {
|
||||
}
|
||||
|
||||
void IRGenImpl::GenDecl(SysYParser::DeclContext& decl) {
|
||||
if (decl.varDecl()) {
|
||||
GenVarDecl(*decl.varDecl());
|
||||
return;
|
||||
if (!decl.btype() || !decl.btype()->INT()) {
|
||||
throw std::runtime_error(FormatError("irgen", "当前仅支持局部 int 变量声明"));
|
||||
}
|
||||
throw std::runtime_error(FormatError("irgen", "暂不支持的声明类型"));
|
||||
auto* var_def = decl.varDef();
|
||||
if (!var_def) {
|
||||
throw std::runtime_error(FormatError("irgen", "非法变量声明"));
|
||||
}
|
||||
GenVarDef(*var_def);
|
||||
}
|
||||
|
||||
void IRGenImpl::GenVarDecl(SysYParser::VarDeclContext& decl) {
|
||||
void IRGenImpl::GenVarDef(SysYParser::VarDefContext& decl) {
|
||||
if (!decl.lValue()) {
|
||||
throw std::runtime_error(FormatError("irgen", "变量声明缺少名称"));
|
||||
}
|
||||
GetLValueName(*decl.lValue());
|
||||
if (storage_map_.find(&decl) != storage_map_.end()) {
|
||||
throw std::runtime_error(FormatError("irgen", "声明重复生成存储槽位"));
|
||||
}
|
||||
@@ -44,8 +62,11 @@ void IRGenImpl::GenVarDecl(SysYParser::VarDeclContext& decl) {
|
||||
storage_map_[&decl] = slot;
|
||||
|
||||
ir::Value* init = nullptr;
|
||||
if (decl.exp()) {
|
||||
init = GenExpr(*decl.exp());
|
||||
if (auto* init_value = decl.initValue()) {
|
||||
if (!init_value->exp()) {
|
||||
throw std::runtime_error(FormatError("irgen", "当前不支持聚合初始化"));
|
||||
}
|
||||
init = GenExpr(*init_value->exp());
|
||||
} else {
|
||||
init = builder_.CreateConstInt(0);
|
||||
}
|
||||
|
||||
@@ -7,49 +7,38 @@
|
||||
#include "utils/Log.h"
|
||||
|
||||
ir::Value* IRGenImpl::GenExpr(SysYParser::ExpContext& expr) {
|
||||
if (!expr.addExp()) {
|
||||
throw std::runtime_error(FormatError("irgen", "非法表达式"));
|
||||
if (auto* paren = dynamic_cast<SysYParser::ParenExpContext*>(&expr)) {
|
||||
return GenExpr(*paren->exp());
|
||||
}
|
||||
return GenAddExpr(*expr.addExp());
|
||||
}
|
||||
|
||||
ir::Value* IRGenImpl::GenAddExpr(SysYParser::AddExpContext& add) {
|
||||
// 当前表达式层次仍是最小实现,直接贴合 addExp -> primary 的语法形状。
|
||||
const auto& terms = add.primary();
|
||||
if (terms.empty()) {
|
||||
throw std::runtime_error(FormatError("irgen", "空加法表达式"));
|
||||
if (auto* number = dynamic_cast<SysYParser::NumberExpContext*>(&expr)) {
|
||||
if (!number->number() || !number->number()->ILITERAL()) {
|
||||
throw std::runtime_error(FormatError("irgen", "当前仅支持整数字面量"));
|
||||
}
|
||||
return builder_.CreateConstInt(std::stoi(number->number()->getText()));
|
||||
}
|
||||
|
||||
ir::Value* acc = GenPrimary(*terms[0]);
|
||||
for (size_t i = 1; i < terms.size(); ++i) {
|
||||
ir::Value* rhs = GenPrimary(*terms[i]);
|
||||
std::string name = module_.GetContext().NextTemp();
|
||||
acc = builder_.CreateBinary(ir::Opcode::Add, acc, rhs, name);
|
||||
}
|
||||
return acc;
|
||||
}
|
||||
|
||||
ir::Value* IRGenImpl::GenPrimary(SysYParser::PrimaryContext& primary) {
|
||||
if (primary.Number()) {
|
||||
return builder_.CreateConstInt(std::stoi(primary.Number()->getText()));
|
||||
}
|
||||
if (primary.Ident()) {
|
||||
auto* decl = sema_.ResolveVarUse(&primary);
|
||||
if (auto* var = dynamic_cast<SysYParser::VarExpContext*>(&expr)) {
|
||||
if (!var->var() || !var->var()->ID()) {
|
||||
throw std::runtime_error(FormatError("irgen", "当前仅支持普通整型变量"));
|
||||
}
|
||||
auto* decl = sema_.ResolveVarUse(var->var());
|
||||
if (!decl) {
|
||||
throw std::runtime_error(
|
||||
FormatError("irgen",
|
||||
"变量使用缺少语义绑定: " + primary.Ident()->getText()));
|
||||
"变量使用缺少语义绑定: " + var->var()->ID()->getText()));
|
||||
}
|
||||
auto it = storage_map_.find(decl);
|
||||
if (it == storage_map_.end()) {
|
||||
throw std::runtime_error(
|
||||
FormatError("irgen",
|
||||
"变量声明缺少存储槽位: " + primary.Ident()->getText()));
|
||||
"变量声明缺少存储槽位: " + var->var()->ID()->getText()));
|
||||
}
|
||||
return builder_.CreateLoad(it->second, module_.GetContext().NextTemp());
|
||||
}
|
||||
if (primary.exp()) {
|
||||
return GenExpr(*primary.exp());
|
||||
if (auto* binary = dynamic_cast<SysYParser::AdditiveExpContext*>(&expr)) {
|
||||
ir::Value* lhs = GenExpr(*binary->exp(0));
|
||||
ir::Value* rhs = GenExpr(*binary->exp(1));
|
||||
return builder_.CreateBinary(ir::Opcode::Add, lhs, rhs,
|
||||
module_.GetContext().NextTemp());
|
||||
}
|
||||
throw std::runtime_error(FormatError("irgen", "暂不支持的表达式形式"));
|
||||
}
|
||||
|
||||
@@ -28,26 +28,31 @@ IRGenImpl::IRGenImpl(ir::Module& module, const SemanticContext& sema)
|
||||
builder_(module.GetContext(), nullptr) {}
|
||||
|
||||
void IRGenImpl::Gen(SysYParser::CompUnitContext& cu) {
|
||||
if (!cu.funcDef()) {
|
||||
throw std::runtime_error(FormatError("irgen", "缺少 main 定义"));
|
||||
auto* func = cu.funcDef();
|
||||
if (func && func->ID() && func->ID()->getText() == "main") {
|
||||
GenFuncDef(*func);
|
||||
return;
|
||||
}
|
||||
GenFuncDef(*cu.funcDef());
|
||||
throw std::runtime_error(FormatError("irgen", "缺少 main 定义"));
|
||||
}
|
||||
|
||||
void IRGenImpl::GenFuncDef(SysYParser::FuncDefContext& func) {
|
||||
if (!func.block()) {
|
||||
if (!func.blockStmt()) {
|
||||
throw std::runtime_error(FormatError("irgen", "函数体为空"));
|
||||
}
|
||||
if (!func.Ident()) {
|
||||
if (!func.ID()) {
|
||||
throw std::runtime_error(FormatError("irgen", "缺少函数名"));
|
||||
}
|
||||
if (!func.funcType() || !func.funcType()->INT()) {
|
||||
throw std::runtime_error(FormatError("irgen", "当前仅支持 int main"));
|
||||
}
|
||||
|
||||
func_ = module_.CreateFunction(
|
||||
func.Ident()->getText(), module_.GetContext().Int32());
|
||||
func.ID()->getText(), module_.GetContext().Int32());
|
||||
builder_.SetInsertPoint(func_->GetEntry());
|
||||
storage_map_.clear();
|
||||
|
||||
GenBlock(*func.block());
|
||||
GenBlock(*func.blockStmt());
|
||||
// 语义正确性主要由 sema 保证,这里只兜底检查 IR 结构是否合法。
|
||||
VerifyFunctionStructure(*func_);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#include "sem/SymbolTable.h"
|
||||
|
||||
void SymbolTable::Add(const std::string& name,
|
||||
SysYParser::VarDeclContext* decl) {
|
||||
SysYParser::VarDefContext* decl) {
|
||||
table_[name] = decl;
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ bool SymbolTable::Contains(const std::string& name) const {
|
||||
return table_.find(name) != table_.end();
|
||||
}
|
||||
|
||||
SysYParser::VarDeclContext* SymbolTable::Lookup(const std::string& name) const {
|
||||
SysYParser::VarDefContext* SymbolTable::Lookup(const std::string& name) const {
|
||||
auto it = table_.find(name);
|
||||
return it == table_.end() ? nullptr : it->second;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user