From 6e5b6d82356c6c17120a211f5ccaa12d980cdde4 Mon Sep 17 00:00:00 2001 From: Pomelo <1807773939@qq.com> Date: Mon, 18 May 2026 20:19:52 +0800 Subject: [PATCH] lab3 --- CMakeLists.txt | 1 - doc/Lab3-指令选择与汇编生成.md | 1 - include/frontend/AntlrDriver.h | 4 +- include/irgen/IRGen.h | 16 +--- src/frontend/AntlrDriver.cpp | 4 +- src/frontend/CMakeLists.txt | 3 +- src/irgen/IRGenDecl.cpp | 12 +-- src/irgen/IRGenDriver.cpp | 2 +- src/irgen/IRGenExp.cpp | 115 +++--------------------- src/irgen/IRGenFunc.cpp | 19 +--- src/irgen/IRGenStmt.cpp | 62 +------------ test_results.txt | 2 +- 12 files changed, 27 insertions(+), 214 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4e8c257..74dcb27 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,3 @@ -include_directories(${PROJECT_SOURCE_DIR}/src/antlr4) cmake_minimum_required(VERSION 3.20) project(compiler LANGUAGES C CXX) diff --git a/doc/Lab3-指令选择与汇编生成.md b/doc/Lab3-指令选择与汇编生成.md index 6446e4c..b79ed4d 100644 --- a/doc/Lab3-指令选择与汇编生成.md +++ b/doc/Lab3-指令选择与汇编生成.md @@ -61,4 +61,3 @@ for test_file in test/test_case/performance/*.sy; do if [ -f "$test_file" ]; 若最终输出 `输出匹配: test/test_case/simple_add.out`,说明当前示例用例 `return a + b` 的完整后端链路已经跑通。 但最终不能只检查 `simple_add`。完成 Lab3 后,应对 `test/test_case` 下全部测试用例逐个回归,确认代码生成结果能够通过统一验证;如有需要,也可以自行编写批量测试脚本统一执行。 - diff --git a/include/frontend/AntlrDriver.h b/include/frontend/AntlrDriver.h index 5403e14..ee22da9 100644 --- a/include/frontend/AntlrDriver.h +++ b/include/frontend/AntlrDriver.h @@ -4,8 +4,8 @@ #include #include -#include "antlr4/SysYLexer.h" -#include "antlr4/SysYParser.h" +#include "SysYLexer.h" +#include "SysYParser.h" #include "antlr4-runtime.h" struct AntlrResult { diff --git a/include/irgen/IRGen.h b/include/irgen/IRGen.h index a445a97..4e13fab 100644 --- a/include/irgen/IRGen.h +++ b/include/irgen/IRGen.h @@ -6,19 +6,14 @@ #include #include #include -#include #include #include -#include "antlr4/SysYBaseVisitor.h" -#include "antlr4/SysYParser.h" +#include "SysYBaseVisitor.h" +#include "SysYParser.h" #include "ir/IR.h" #include "sem/Sema.h" -// 前向声明:语义层可能在未来提供更明确的符号类型,用于把符号唯一标识映射到 IR 对象。 -struct SemanticVarSymbol; -struct SemanticFuncSymbol; - namespace ir { class Module; class Function; @@ -59,10 +54,6 @@ class IRGenImpl final : public SysYBaseVisitor { std::any visitLAndExp(SysYParser::LAndExpContext* ctx) override; std::any visitLOrExp(SysYParser::LOrExpContext* ctx) override; - // 辅助接口:数组下标地址计算与全局变量生成 - ir::Value* EmitArrayIndex(ir::Value* base_ptr, SysYParser::ExpContext* idx_expr); - void EmitGlobalVariable(SysYParser::VarDefContext* ctx); - private: enum class BlockFlow { Continue, @@ -81,10 +72,7 @@ class IRGenImpl final : public SysYBaseVisitor { ir::Value* EvalExpr(SysYParser::ExpContext& expr); ir::Value* EvalCond(SysYParser::CondContext& cond); ir::Value* ToBoolValue(ir::Value* v); - ir::Value* FindInScope(const std::string& name); std::string NextBlockName(); - ir::Function* FindFunctionByName(const std::string& name); - ir::Value* ResolveLValueAddress(SysYParser::LValueContext* ctx); // 预声明 SysY runtime 外部函数。 void DeclareRuntimeFunctions(); diff --git a/src/frontend/AntlrDriver.cpp b/src/frontend/AntlrDriver.cpp index 7a77566..ee3c98c 100644 --- a/src/frontend/AntlrDriver.cpp +++ b/src/frontend/AntlrDriver.cpp @@ -6,8 +6,8 @@ #include #include -#include "antlr4/SysYLexer.h" -#include "antlr4/SysYParser.h" +#include "SysYLexer.h" +#include "SysYParser.h" #include "antlr4-runtime.h" #include "utils/Log.h" diff --git a/src/frontend/CMakeLists.txt b/src/frontend/CMakeLists.txt index 4d8d100..524fcd6 100644 --- a/src/frontend/CMakeLists.txt +++ b/src/frontend/CMakeLists.txt @@ -8,10 +8,9 @@ target_link_libraries(frontend PUBLIC ${ANTLR4_RUNTIME_TARGET} ) -# 自动纳入构建目录中的 Lexer/Parser 生成源码(若存在),同时兼容存储在 src/antlr4 中的已生成代码 +# 自动纳入构建目录中的 Lexer/Parser 生成源码(若存在) file(GLOB_RECURSE ANTLR4_GENERATED_SOURCES CONFIGURE_DEPENDS "${ANTLR4_GENERATED_DIR}/*.cpp" - "${PROJECT_SOURCE_DIR}/src/antlr4/*.cpp" ) if(ANTLR4_GENERATED_SOURCES) target_sources(frontend PRIVATE ${ANTLR4_GENERATED_SOURCES}) diff --git a/src/irgen/IRGenDecl.cpp b/src/irgen/IRGenDecl.cpp index 9c3cfc7..269f6f7 100644 --- a/src/irgen/IRGenDecl.cpp +++ b/src/irgen/IRGenDecl.cpp @@ -4,7 +4,7 @@ #include #include -#include "antlr4/SysYParser.h" +#include "SysYParser.h" #include "ir/IR.h" #include "utils/Log.h" @@ -395,11 +395,7 @@ std::any IRGenImpl::visitVarDecl(SysYParser::VarDeclContext* ctx) { if (!var_def) { throw std::runtime_error(FormatError("irgen", "非法变量声明")); } - if (in_function_) { - var_def->accept(this); - } else { - EmitGlobalVariable(var_def); - } + var_def->accept(this); } current_decl_type_ = nullptr; // 清理 return {}; @@ -551,10 +547,6 @@ std::any IRGenImpl::visitVarDef(SysYParser::VarDefContext* ctx) { slot = CreateEntryAllocaI32(module_.GetContext().NextTemp()); } storage_map_[ctx] = slot; - // 添加到当前作用域 - if (!scope_storage_.empty()) { - scope_storage_.back()[name] = slot; - } named_storage_[name] = slot; ir::Value* init = nullptr; diff --git a/src/irgen/IRGenDriver.cpp b/src/irgen/IRGenDriver.cpp index fbc0eb5..ff94412 100644 --- a/src/irgen/IRGenDriver.cpp +++ b/src/irgen/IRGenDriver.cpp @@ -2,7 +2,7 @@ #include -#include "antlr4/SysYParser.h" +#include "SysYParser.h" #include "ir/IR.h" #include "utils/Log.h" diff --git a/src/irgen/IRGenExp.cpp b/src/irgen/IRGenExp.cpp index 0d2a9b1..f75e9dd 100644 --- a/src/irgen/IRGenExp.cpp +++ b/src/irgen/IRGenExp.cpp @@ -2,7 +2,7 @@ #include -#include "antlr4/SysYParser.h" +#include "SysYParser.h" #include "ir/IR.h" #include "utils/Log.h" @@ -53,14 +53,6 @@ ir::Value* IRGenImpl::ToBoolValue(ir::Value* v) { return builder_.CreateCmp(ir::CmpOp::Ne, v, zero, module_.GetContext().NextTemp()); } -ir::Value* IRGenImpl::FindInScope(const std::string& name) { - for (auto it = scope_storage_.rbegin(); it != scope_storage_.rend(); ++it) { - auto found = it->find(name); - if (found != it->end()) return found->second; - } - return nullptr; -} - std::string IRGenImpl::NextBlockName() { std::string temp = module_.GetContext().NextTemp(); if (!temp.empty() && temp.front() == '%') { @@ -265,36 +257,9 @@ std::any IRGenImpl::visitUnaryExp(SysYParser::UnaryExpContext* ctx) { if (!ctx) { throw std::runtime_error(FormatError("irgen", "非法一元表达式")); } - if (ctx->primaryExp()) { return ctx->primaryExp()->accept(this); } - - if (ctx->ID() && ctx->LPAREN()) { - auto func_name = ctx->ID()->getText(); - ir::Function* callee = FindFunctionByName(func_name); - if (!callee) { - throw std::runtime_error(FormatError("irgen", "函数未定义: " + func_name)); - } - - std::vector args; - if (ctx->funcRParams()) { - for (auto* exp : ctx->funcRParams()->exp()) { - if (!exp) { - throw std::runtime_error(FormatError("irgen", "函数参数缺失")); - } - args.push_back(EvalExpr(*exp)); - } - } - - auto* call = builder_.CreateCall(callee, args, module_.GetContext().NextTemp()); - if (callee->GetType()->IsVoid()) { - // void 类型调用表达式在值上下文下暂时返回 0。 - return static_cast(builder_.CreateConstInt(0)); - } - return static_cast(call); - } - if (ctx->unaryOp() && ctx->unaryExp()) { ir::Value* v = std::any_cast(ctx->unaryExp()->accept(this)); if (ctx->unaryOp()->SUB()) { @@ -489,10 +454,9 @@ std::any IRGenImpl::visitLAndExp(SysYParser::LAndExpContext* ctx) { if (!ctx) { throw std::runtime_error(FormatError("irgen", "非法逻辑与表达式")); } - - if (!ctx->lAndExp()) { - if (ctx->eqExp()) { - return ToBoolValue(std::any_cast(ctx->eqExp()->accept(this))); + if (ctx->lAndExp()) { + if (!ctx->eqExp()) { + throw std::runtime_error(FormatError("irgen", "非法逻辑与表达式")); } // 短路求值:a && b // 使用函数级临时槽位(0=false,1=true),避免 phi 依赖和循环内动态 alloca。 @@ -523,46 +487,19 @@ std::any IRGenImpl::visitLAndExp(SysYParser::LAndExpContext* ctx) { return static_cast( builder_.CreateLoad(slot, module_.GetContext().NextTemp())); } - - if (!ctx->eqExp()) { - throw std::runtime_error(FormatError("irgen", "非法逻辑与表达式")); - } - - auto* lhs = ToBoolValue(std::any_cast(ctx->lAndExp()->accept(this))); - - auto* result_slot = builder_.CreateAllocaI32(module_.GetContext().NextTemp()); - auto* rhs_bb = func_->CreateBlock(NextBlockName()); - auto* false_bb = func_->CreateBlock(NextBlockName()); - auto* merge_bb = func_->CreateBlock(NextBlockName()); - - builder_.CreateCondBr(lhs, rhs_bb, false_bb); - - builder_.SetInsertPoint(rhs_bb); - auto* rhs = ToBoolValue(std::any_cast(ctx->eqExp()->accept(this))); - builder_.CreateStore(rhs, result_slot); - if (!rhs_bb->HasTerminator()) { - builder_.CreateBr(merge_bb); - } - - builder_.SetInsertPoint(false_bb); - builder_.CreateStore(builder_.CreateConstInt(0), result_slot); - if (!false_bb->HasTerminator()) { - builder_.CreateBr(merge_bb); + if (ctx->eqExp()) { + return ToBoolValue(std::any_cast(ctx->eqExp()->accept(this))); } - - builder_.SetInsertPoint(merge_bb); - return static_cast( - builder_.CreateLoad(result_slot, module_.GetContext().NextTemp())); + throw std::runtime_error(FormatError("irgen", "非法逻辑与表达式")); } std::any IRGenImpl::visitLOrExp(SysYParser::LOrExpContext* ctx) { if (!ctx) { throw std::runtime_error(FormatError("irgen", "非法逻辑或表达式")); } - - if (!ctx->lOrExp()) { - if (ctx->lAndExp()) { - return ToBoolValue(std::any_cast(ctx->lAndExp()->accept(this))); + if (ctx->lOrExp()) { + if (!ctx->lAndExp()) { + throw std::runtime_error(FormatError("irgen", "非法逻辑或表达式")); } // 短路求值:a || b if (!short_circuit_slot_) { @@ -597,34 +534,8 @@ std::any IRGenImpl::visitLOrExp(SysYParser::LOrExpContext* ctx) { return static_cast( builder_.CreateLoad(slot, module_.GetContext().NextTemp())); } - - if (!ctx->lAndExp()) { - throw std::runtime_error(FormatError("irgen", "非法逻辑或表达式")); + if (ctx->lAndExp()) { + return ToBoolValue(std::any_cast(ctx->lAndExp()->accept(this))); } - - auto* lhs = ToBoolValue(std::any_cast(ctx->lOrExp()->accept(this))); - - auto* result_slot = builder_.CreateAllocaI32(module_.GetContext().NextTemp()); - auto* true_bb = func_->CreateBlock(NextBlockName()); - auto* rhs_bb = func_->CreateBlock(NextBlockName()); - auto* merge_bb = func_->CreateBlock(NextBlockName()); - - builder_.CreateCondBr(lhs, true_bb, rhs_bb); - - builder_.SetInsertPoint(true_bb); - builder_.CreateStore(builder_.CreateConstInt(1), result_slot); - if (!true_bb->HasTerminator()) { - builder_.CreateBr(merge_bb); - } - - builder_.SetInsertPoint(rhs_bb); - auto* rhs = ToBoolValue(std::any_cast(ctx->lAndExp()->accept(this))); - builder_.CreateStore(rhs, result_slot); - if (!rhs_bb->HasTerminator()) { - builder_.CreateBr(merge_bb); - } - - builder_.SetInsertPoint(merge_bb); - return static_cast( - builder_.CreateLoad(result_slot, module_.GetContext().NextTemp())); + throw std::runtime_error(FormatError("irgen", "非法逻辑或表达式")); } diff --git a/src/irgen/IRGenFunc.cpp b/src/irgen/IRGenFunc.cpp index 6883ba6..e06f81c 100644 --- a/src/irgen/IRGenFunc.cpp +++ b/src/irgen/IRGenFunc.cpp @@ -2,7 +2,7 @@ #include -#include "antlr4/SysYParser.h" +#include "SysYParser.h" #include "ir/IR.h" #include "utils/Log.h" @@ -25,10 +25,7 @@ IRGenImpl::IRGenImpl(ir::Module& module, const SemanticContext& sema) : module_(module), sema_(sema), func_(nullptr), - builder_(module.GetContext(), nullptr) { - // 初始化作用域栈,至少有一个全局作用域(但当前未使用全局变量) - scope_storage_.emplace_back(); -} + builder_(module.GetContext(), nullptr) {} ir::AllocaInst* IRGenImpl::CreateEntryAllocaI32(const std::string& name) { if (!func_) { @@ -241,18 +238,6 @@ std::any IRGenImpl::visitFuncDef(SysYParser::FuncDefContext* ctx) { short_circuit_slot_ = CreateEntryAllocaI32(module_.GetContext().NextTemp()); - // 进入函数参数作用域 - scope_storage_.emplace_back(); - - // 处理参数:为每个参数创建 alloca 并放入符号表 - for (const auto& param_name : param_names) { - auto* alloca = builder_.CreateAllocaI32(module_.GetContext().NextTemp()); - param_slots_.push_back(alloca); - scope_storage_.back()[param_name] = alloca; - named_storage_[param_name] = alloca; - } - - // 生成函数体 ctx->blockStmt()->accept(this); // 入口块只用于静态栈槽分配,末尾统一跳到函数体起始块。 diff --git a/src/irgen/IRGenStmt.cpp b/src/irgen/IRGenStmt.cpp index c321ce9..a8357be 100644 --- a/src/irgen/IRGenStmt.cpp +++ b/src/irgen/IRGenStmt.cpp @@ -2,20 +2,10 @@ #include -#include "antlr4/SysYParser.h" +#include "SysYParser.h" #include "ir/IR.h" #include "utils/Log.h" -static std::string FormatErrorCtx(antlr4::ParserRuleContext* ctx, - const std::string& msg) { - if (ctx && ctx->getStart()) { - return FormatErrorAt("irgen", ctx->getStart()->getLine(), - ctx->getStart()->getCharPositionInLine() + 1, msg); - } - return FormatError("irgen", msg); -} - - // 语句生成当前只实现了最小子集。 // 目前支持: // - return ; @@ -142,27 +132,6 @@ std::any IRGenImpl::visitStmt(SysYParser::StmtContext* ctx) { throw std::runtime_error(FormatError("irgen", "暂不支持的语句类型")); } -ir::Value* IRGenImpl::ResolveLValueAddress(SysYParser::LValueContext* ctx) { - if (!ctx || !ctx->ID()) { - throw std::runtime_error(FormatError("irgen", "非法左值")); - } - const std::string name = ctx->ID()->getText(); - ir::Value* base = FindInScope(name); - if (!base) { - throw std::runtime_error(FormatError("irgen", "变量未声明: " + name)); - } - - if (ctx->LBRACK().empty()) { - return base; - } - - // 到目前为止只支持一维数组,占位实现 - if (ctx->exp().empty()) { - throw std::runtime_error(FormatError("irgen", "数组下标缺失")); - } - return EmitArrayIndex(base, ctx->exp(0)); -} - std::any IRGenImpl::visitReturnStmt(SysYParser::ReturnStmtContext* ctx) { if (!ctx) { @@ -184,32 +153,3 @@ std::any IRGenImpl::visitReturnStmt(SysYParser::ReturnStmtContext* ctx) { builder_.CreateRet(v); return BlockFlow::Terminated; } - -ir::Value* IRGenImpl::EmitArrayIndex(ir::Value* base_ptr, - SysYParser::ExpContext* idx_expr) { - if (!base_ptr) { - throw std::runtime_error(FormatError("irgen", "数组基址为空")); - } - if (!idx_expr) { - throw std::runtime_error(FormatError("irgen", "缺少数组下标表达式")); - } - ir::Value* idx = EvalExpr(*idx_expr); - if (!idx) { - throw std::runtime_error(FormatError("irgen", "数组下标计算失败")); - } - // 当前 IR 仍只支持 i32 / i32*,还未实现真正的 GEP。 - // 这里提供一个占位:直接将基址作为元素地址返回(仅用于结构化接口), - // 具体语义需在后续 IR 指令集扩展后完成。 - // TODO: 实现指针加法/GEP,以支持数组下标访问 - (void)idx; - return base_ptr; -} - -void IRGenImpl::EmitGlobalVariable(SysYParser::VarDefContext* ctx) { - if (!ctx) { - throw std::runtime_error(FormatError("irgen", "缺少全局变量定义")); - } - // GlobalValue 还未完成,暂时抛异常以提醒后续实现。 - throw std::runtime_error(FormatError("irgen", "全局变量生成未实现")); -} - diff --git a/test_results.txt b/test_results.txt index f876263..b046ecd 100644 --- a/test_results.txt +++ b/test_results.txt @@ -1,5 +1,5 @@ 开始批量测试... -测试时间: Fri Apr 24 15:40:32 CST 2026 +测试时间: 2026年 04月 24日 星期五 10:53:20 CST ======================================== 测试目录: test/test_case/functional