#include "irgen/IRGen.h" #include #include "antlr4/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", "缺少语句块")); } // 进入新作用域 scope_storage_.emplace_back(); for (auto* item : ctx->blockItem()) { if (item) { if (VisitBlockItemResult(*item) == BlockFlow::Terminated) { // 当前语法要求 return 为块内最后一条语句;命中后可停止生成。 break; } } } // 退出作用域 scope_storage_.pop_back(); 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->varDecl()) { // 当前先忽略 constDecl 与其它声明形态。 return {}; } if (!in_function_) { // 全局变量处理路径 for (auto* var_def : ctx->varDecl()->varDef()) { if (!var_def) { throw std::runtime_error(FormatError("irgen", "非法变量声明")); } EmitGlobalVariable(var_def); } return {}; } return ctx->varDecl()->accept(this); } std::any IRGenImpl::visitVarDecl(SysYParser::VarDeclContext* ctx) { if (!ctx) { throw std::runtime_error(FormatError("irgen", "缺少变量声明")); } if (!ctx->btype() || !ctx->btype()->INT()) { throw std::runtime_error(FormatError("irgen", "当前仅支持 int 类型变量声明")); } for (auto* var_def : ctx->varDef()) { if (!var_def) { throw std::runtime_error(FormatError("irgen", "非法变量声明")); } if (in_function_) { var_def->accept(this); } else { EmitGlobalVariable(var_def); } } return {}; } // 当前仍是教学用的最小版本,因此这里只支持: // - 局部 int 变量; // - 标量初始化; // - 一个 VarDef 对应一个槽位。 std::any IRGenImpl::visitVarDef(SysYParser::VarDefContext* ctx) { if (!ctx) { throw std::runtime_error(FormatError("irgen", "缺少变量定义")); } if (!ctx->ID()) { throw std::runtime_error(FormatError("irgen", "变量声明缺少名称")); } const std::string name = ctx->ID()->getText(); // 数组语义暂时不支持,先提示 if (!ctx->LBRACK().empty()) { throw std::runtime_error(FormatError("irgen", "暂不支持数组声明和初始化")); } if (storage_map_.find(ctx) != storage_map_.end()) { throw std::runtime_error(FormatError("irgen", "声明重复生成存储槽位")); } // const 变量在 Sema 中可扩展为常量折叠,当前暂时和普通变量一样处理 auto* slot = builder_.CreateAllocaI32(module_.GetContext().NextTemp()); storage_map_[ctx] = slot; // 添加到当前作用域 if (!scope_storage_.empty()) { scope_storage_.back()[name] = slot; } named_storage_[name] = 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 {}; }