#include "irgen/IRGen.h" #include #include "SysYParser.h" #include "ir/IR.h" #include "utils/Log.h" namespace { std::string GetLValueName(SysYParser::LValueContext& lvalue) { if (!lvalue.ID()) { throw std::runtime_error(FormatError("irgen", "非法左值")); } return lvalue.ID()->getText(); } } // namespace std::any IRGenImpl::visitBlockStmt(SysYParser::BlockStmtContext* ctx) { if (!ctx) { throw std::runtime_error(FormatError("irgen", "缺少语句块")); } for (auto* item : ctx->blockItem()) { if (item) { if (VisitBlockItemResult(*item) == BlockFlow::Terminated) { // 当前语法要求 return 为块内最后一条语句;命中后可停止生成。 break; } } } return {}; } IRGenImpl::BlockFlow IRGenImpl::VisitBlockItemResult( SysYParser::BlockItemContext& item) { return std::any_cast(item.accept(this)); } std::any IRGenImpl::visitBlockItem(SysYParser::BlockItemContext* ctx) { if (!ctx) { throw std::runtime_error(FormatError("irgen", "缺少块内项")); } if (ctx->decl()) { ctx->decl()->accept(this); return BlockFlow::Continue; } if (ctx->stmt()) { return ctx->stmt()->accept(this); } throw std::runtime_error(FormatError("irgen", "暂不支持的语句或声明")); } // 变量声明的 IR 生成目前也是最小实现: // - 先检查声明的基础类型,当前仅支持局部 int; // - 再把 Decl 中的变量定义交给 visitVarDef 继续处理。 // // 和更完整的版本相比,这里还没有: // - 一个 Decl 中多个变量定义的顺序处理; // - const、数组、全局变量等不同声明形态; // - 更丰富的类型系统。 std::any IRGenImpl::visitDecl(SysYParser::DeclContext* ctx) { if (!ctx) { throw std::runtime_error(FormatError("irgen", "缺少变量声明")); } if (!ctx->btype() || !ctx->btype()->INT()) { throw std::runtime_error(FormatError("irgen", "当前仅支持局部 int 变量声明")); } auto* var_def = ctx->varDef(); if (!var_def) { throw std::runtime_error(FormatError("irgen", "非法变量声明")); } var_def->accept(this); return {}; } // 当前仍是教学用的最小版本,因此这里只支持: // - 局部 int 变量; // - 标量初始化; // - 一个 VarDef 对应一个槽位。 std::any IRGenImpl::visitVarDef(SysYParser::VarDefContext* ctx) { if (!ctx) { throw std::runtime_error(FormatError("irgen", "缺少变量定义")); } if (!ctx->lValue()) { throw std::runtime_error(FormatError("irgen", "变量声明缺少名称")); } GetLValueName(*ctx->lValue()); if (storage_map_.find(ctx) != storage_map_.end()) { throw std::runtime_error(FormatError("irgen", "声明重复生成存储槽位")); } auto* slot = builder_.CreateAllocaI32(module_.GetContext().NextTemp()); storage_map_[ctx] = slot; ir::Value* init = nullptr; if (auto* init_value = ctx->initValue()) { if (!init_value->exp()) { throw std::runtime_error(FormatError("irgen", "当前不支持聚合初始化")); } init = EvalExpr(*init_value->exp()); } else { init = builder_.CreateConstInt(0); } builder_.CreateStore(init, slot); return {}; }