refactor(irgen): 完善irgen代码和文档,提升扩展兼容性

This commit is contained in:
jing
2026-03-17 19:03:49 +08:00
parent a091d9108a
commit f19d23c656
8 changed files with 115 additions and 72 deletions

View File

@@ -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);
}

View File

@@ -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", "暂不支持的表达式形式"));
}

View File

@@ -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_);
}

View File

@@ -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;
}