diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 373ab50..2cf20cb 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,8 +1,6 @@ # src/ 子目录构建脚本:各子目录独立维护 CMakeLists.txt,并在此聚合链接 add_subdirectory(utils) -add_subdirectory(ast) -add_subdirectory(sem) add_subdirectory(ir) add_subdirectory(frontend) add_subdirectory(irgen) @@ -13,7 +11,6 @@ add_executable(compiler ) target_link_libraries(compiler PRIVATE frontend - sem irgen mir utils diff --git a/src/ast/AstNodes.cpp b/src/ast/AstNodes.cpp deleted file mode 100644 index 380e36e..0000000 --- a/src/ast/AstNodes.cpp +++ /dev/null @@ -1,29 +0,0 @@ - -// AST 节点定义与实现: -// - 表达式、语句、声明、函数、类型等节点 -// - 支持后续阶段在节点上附加信息(类型、符号绑定、常量值等) -#include "ast/AstNodes.h" - -#include - -namespace ast { - -NumberExpr::NumberExpr(int v) : value(v) {} - -VarExpr::VarExpr(std::string n) : name(std::move(n)) {} - -BinaryExpr::BinaryExpr(BinaryOp op, std::shared_ptr lhs, - std::shared_ptr rhs) - : op(op), lhs(std::move(lhs)), rhs(std::move(rhs)) {} - -ReturnStmt::ReturnStmt(std::shared_ptr v) : value(std::move(v)) {} - -VarDecl::VarDecl(std::string n, std::shared_ptr i) - : name(std::move(n)), init(std::move(i)) {} - -FuncDef::FuncDef(std::string n, std::shared_ptr b) - : name(std::move(n)), body(std::move(b)) {} - -CompUnit::CompUnit(std::shared_ptr f) : func(std::move(f)) {} - -} // namespace ast diff --git a/src/ast/AstNodes.h b/src/ast/AstNodes.h deleted file mode 100644 index cfe5908..0000000 --- a/src/ast/AstNodes.h +++ /dev/null @@ -1,70 +0,0 @@ - -#pragma once - -#include -#include -#include -#include - -namespace ast { - -enum class BinaryOp { Add, Sub, Mul, Div }; - -struct Expr { - virtual ~Expr() = default; -}; - -struct NumberExpr : Expr { - int value{}; - explicit NumberExpr(int v); -}; - -struct VarExpr : Expr { - std::string name; - explicit VarExpr(std::string n); -}; - -struct BinaryExpr : Expr { - BinaryOp op; - std::shared_ptr lhs; - std::shared_ptr rhs; - BinaryExpr(BinaryOp op, std::shared_ptr lhs, std::shared_ptr rhs); -}; - -struct Stmt { - virtual ~Stmt() = default; -}; - -struct ReturnStmt : Stmt { - std::shared_ptr value; - explicit ReturnStmt(std::shared_ptr v); -}; - -struct VarDecl { - std::string name; - std::shared_ptr init; // nullptr if no initializer - VarDecl(std::string n, std::shared_ptr i); -}; - -struct Block { - std::vector> varDecls; - std::vector> stmts; -}; - -struct FuncDef { - std::string name; - std::shared_ptr body; - FuncDef(std::string n, std::shared_ptr b); -}; - -struct CompUnit { - std::shared_ptr func; - explicit CompUnit(std::shared_ptr f); -}; - -// 调试打印 -void PrintAST(const CompUnit& cu); -// 导出 AST 为 Graphviz DOT。 -void PrintASTDot(const CompUnit& cu, std::ostream& os); - -} // namespace ast diff --git a/src/ast/AstPrinter.cpp b/src/ast/AstPrinter.cpp deleted file mode 100644 index 89510ba..0000000 --- a/src/ast/AstPrinter.cpp +++ /dev/null @@ -1,198 +0,0 @@ -// 简单 AST 调试打印,便于前端验证。 - -#include "ast/AstNodes.h" - -#include -#include -#include - -namespace ast { - -static void PrintIndent(int depth) { - for (int i = 0; i < depth; ++i) std::cout << " "; -} - -static void PrintLine(int depth, const std::string& text) { - PrintIndent(depth); - std::cout << text << "\n"; -} - -static void DumpExpr(const Expr* expr, int depth) { - if (!expr) { - PrintLine(depth, "NullExpr"); - return; - } - - if (auto num = dynamic_cast(expr)) { - PrintLine(depth, "NumberExpr value=" + std::to_string(num->value)); - return; - } - if (auto var = dynamic_cast(expr)) { - PrintLine(depth, "VarExpr name=" + var->name); - return; - } - if (auto bin = dynamic_cast(expr)) { - const char* op = "?"; - switch (bin->op) { - case BinaryOp::Add: - op = "Add"; - break; - case BinaryOp::Sub: - op = "Sub"; - break; - case BinaryOp::Mul: - op = "Mul"; - break; - case BinaryOp::Div: - op = "Div"; - break; - } - PrintLine(depth, std::string("BinaryExpr op=") + op); - DumpExpr(bin->lhs.get(), depth + 1); - DumpExpr(bin->rhs.get(), depth + 1); - return; - } - - PrintLine(depth, "UnknownExpr"); -} - -void PrintAST(const CompUnit& cu) { - PrintLine(0, "CompUnit"); - if (!cu.func) { - PrintLine(1, ""); - std::cout << "\n"; - return; - } - - PrintLine(1, "FuncDef name=" + cu.func->name); - const auto& body = cu.func->body; - if (!body) { - PrintLine(2, "Block "); - return; - } - - PrintLine(2, "Block"); - for (const auto& decl : body->varDecls) { - PrintLine(3, "VarDecl name=" + decl->name); - if (decl->init) { - PrintLine(4, "Init"); - DumpExpr(decl->init.get(), 5); - } - } - for (const auto& stmt : body->stmts) { - if (auto ret = dynamic_cast(stmt.get())) { - PrintLine(3, "ReturnStmt"); - DumpExpr(ret->value.get(), 4); - } else { - PrintLine(3, "UnknownStmt"); - } - } - std::cout << "\n"; -} - -namespace { - -std::string EscapeDotLabel(const std::string& s) { - std::string out; - out.reserve(s.size()); - for (char c : s) { - if (c == '\\' || c == '"') out.push_back('\\'); - out.push_back(c); - } - return out; -} - -class DotWriter { - public: - explicit DotWriter(std::ostream& os) : os_(os) {} - - int AddNode(const std::string& label) { - int id = next_id_++; - os_ << " n" << id << " [label=\"" << EscapeDotLabel(label) << "\"];\n"; - return id; - } - - void AddEdge(int from, int to) { os_ << " n" << from << " -> n" << to << ";\n"; } - - private: - std::ostream& os_; - int next_id_ = 0; -}; - -int EmitExpr(const Expr* expr, DotWriter& dot) { - if (!expr) return dot.AddNode("NullExpr"); - - if (auto num = dynamic_cast(expr)) { - return dot.AddNode("Number(" + std::to_string(num->value) + ")"); - } - if (auto var = dynamic_cast(expr)) { - return dot.AddNode("Var(" + var->name + ")"); - } - if (auto bin = dynamic_cast(expr)) { - const char* op = "?"; - switch (bin->op) { - case BinaryOp::Add: - op = "Add"; - break; - case BinaryOp::Sub: - op = "Sub"; - break; - case BinaryOp::Mul: - op = "Mul"; - break; - case BinaryOp::Div: - op = "Div"; - break; - } - int id = dot.AddNode(std::string("Binary(") + op + ")"); - int lhs = EmitExpr(bin->lhs.get(), dot); - int rhs = EmitExpr(bin->rhs.get(), dot); - dot.AddEdge(id, lhs); - dot.AddEdge(id, rhs); - return id; - } - return dot.AddNode("UnknownExpr"); -} - -} // namespace - -void PrintASTDot(const CompUnit& cu, std::ostream& os) { - os << "digraph AST {\n"; - os << " rankdir=TB;\n"; - os << " node [shape=box, fontname=\"Courier\"];\n"; - - DotWriter dot(os); - int cu_id = dot.AddNode("CompUnit"); - if (cu.func) { - int func_id = dot.AddNode("FuncDef(" + cu.func->name + ")"); - dot.AddEdge(cu_id, func_id); - if (cu.func->body) { - int block_id = dot.AddNode("Block"); - dot.AddEdge(func_id, block_id); - - for (const auto& decl : cu.func->body->varDecls) { - int decl_id = dot.AddNode("VarDecl(" + decl->name + ")"); - dot.AddEdge(block_id, decl_id); - if (decl->init) { - int init_id = EmitExpr(decl->init.get(), dot); - dot.AddEdge(decl_id, init_id); - } - } - - for (const auto& stmt : cu.func->body->stmts) { - if (auto ret = dynamic_cast(stmt.get())) { - int ret_id = dot.AddNode("Return"); - dot.AddEdge(block_id, ret_id); - int value_id = EmitExpr(ret->value.get(), dot); - dot.AddEdge(ret_id, value_id); - } else { - int stmt_id = dot.AddNode("Stmt"); - dot.AddEdge(block_id, stmt_id); - } - } - } - } - os << "}\n"; -} - -} // namespace ast diff --git a/src/ast/CMakeLists.txt b/src/ast/CMakeLists.txt deleted file mode 100644 index b084694..0000000 --- a/src/ast/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -add_library(ast STATIC - AstNodes.cpp - AstPrinter.cpp -) - -target_link_libraries(ast PUBLIC - build_options -) diff --git a/src/frontend/AstBuilder.cpp b/src/frontend/AstBuilder.cpp deleted file mode 100644 index da6b3d9..0000000 --- a/src/frontend/AstBuilder.cpp +++ /dev/null @@ -1,114 +0,0 @@ -// 将 parse tree 转换为 AST。 -#include "frontend/AstBuilder.h" - -#include -#include -#include -#include -#include - -#include "SysYBaseVisitor.h" -#include "SysYParser.h" -#include "ast/AstNodes.h" -#include "antlr4-runtime.h" - -namespace { - -using ast::BinaryExpr; -using ast::BinaryOp; -using ast::Block; -using ast::CompUnit; -using ast::FuncDef; -using ast::NumberExpr; -using ast::ReturnStmt; -using ast::VarDecl; -using ast::VarExpr; - -template -T Take(std::any&& value) { - if (auto* ptr = std::any_cast(&value)) { - return std::move(*ptr); - } - throw std::runtime_error("AST 构建失败:类型不匹配"); -} - -class Builder : public SysYBaseVisitor { - public: - std::any visitCompUnit(SysYParser::CompUnitContext* ctx) override { - auto func = Take>(visit(ctx->funcDef())); - return std::make_shared(std::move(func)); - } - - std::any visitFuncDef(SysYParser::FuncDefContext* ctx) override { - auto body = Take>(visit(ctx->block())); - return std::make_shared("main", std::move(body)); - } - - std::any visitBlock(SysYParser::BlockContext* ctx) override { - auto block = std::make_shared(); - for (auto stmtCtx : ctx->stmt()) { - if (stmtCtx->varDecl()) { - block->varDecls.emplace_back( - Take>(visit(stmtCtx->varDecl()))); - } else if (stmtCtx->returnStmt()) { - block->stmts.emplace_back( - Take>(visit(stmtCtx->returnStmt()))); - } - } - return block; - } - - std::any visitVarDecl(SysYParser::VarDeclContext* ctx) override { - std::shared_ptr init; - if (ctx->exp()) { - init = Take>(visit(ctx->exp())); - } - return std::make_shared(ctx->Ident()->getText(), std::move(init)); - } - - std::any visitReturnStmt(SysYParser::ReturnStmtContext* ctx) override { - auto expr = Take>(visit(ctx->exp())); - return std::make_shared(std::move(expr)); - } - - std::any visitExp(SysYParser::ExpContext* ctx) override { - return visit(ctx->addExp()); - } - - std::any visitAddExp(SysYParser::AddExpContext* ctx) override { - auto node = Take>(visit(ctx->primary(0))); - for (size_t i = 1; i < ctx->primary().size(); ++i) { - auto rhs = Take>(visit(ctx->primary(i))); - auto opToken = ctx->AddOp(i - 1); - BinaryOp op = BinaryOp::Add; - if (opToken->getText() == "-") op = BinaryOp::Sub; - node = std::make_shared(op, std::move(node), std::move(rhs)); - } - return node; - } - - std::any visitPrimary(SysYParser::PrimaryContext* ctx) override { - if (ctx->Number()) { - std::shared_ptr expr = - std::make_shared(std::stoi(ctx->Number()->getText())); - return expr; - } - if (ctx->Ident()) { - std::shared_ptr expr = - std::make_shared(ctx->Ident()->getText()); - return expr; - } - return visit(ctx->exp()); - } -}; - -} // namespace - -std::shared_ptr BuildAst(antlr4::tree::ParseTree* tree) { - if (!tree) { - throw std::runtime_error("parse tree 为空"); - } - Builder visitor; - auto result = visitor.visit(tree); - return Take>(std::move(result)); -} diff --git a/src/frontend/AstBuilder.h b/src/frontend/AstBuilder.h deleted file mode 100644 index 7607667..0000000 --- a/src/frontend/AstBuilder.h +++ /dev/null @@ -1,16 +0,0 @@ -// 将 ANTLR parse tree 转换为内部 AST。 -#pragma once - -#include - -namespace antlr4 { -namespace tree { -class ParseTree; -} -} // namespace antlr4 - -namespace ast { -struct CompUnit; -} - -std::shared_ptr BuildAst(antlr4::tree::ParseTree* tree); diff --git a/src/frontend/CMakeLists.txt b/src/frontend/CMakeLists.txt index 7f6841d..0b54f5b 100644 --- a/src/frontend/CMakeLists.txt +++ b/src/frontend/CMakeLists.txt @@ -1,11 +1,9 @@ add_library(frontend STATIC AntlrDriver.cpp - AstBuilder.cpp ) target_link_libraries(frontend PUBLIC build_options - ast "${ANTLR4_RUNTIME_TARGET}" ) diff --git a/src/irgen/CMakeLists.txt b/src/irgen/CMakeLists.txt index e711474..8f0f1e1 100644 --- a/src/irgen/CMakeLists.txt +++ b/src/irgen/CMakeLists.txt @@ -8,7 +8,6 @@ add_library(irgen STATIC target_link_libraries(irgen PUBLIC build_options - ast - sem + "${ANTLR4_RUNTIME_TARGET}" ir ) diff --git a/src/irgen/IRGen.h b/src/irgen/IRGen.h index e87fd78..fde34c5 100644 --- a/src/irgen/IRGen.h +++ b/src/irgen/IRGen.h @@ -1,45 +1,44 @@ -// 将 AST 翻译为极简 IR。 -// 这里提供一个可运行的最小 IR 生成骨架,并把实现拆分到 IRGenFunc/IRGenStmt/IRGenExp/IRGenDecl。 -// 同学可以在对应 .cpp 内进一步完善更多语义。 +// 将 ANTLR parse tree 翻译为极简 IR。 +// 实现拆分在 IRGenFunc/IRGenStmt/IRGenExp/IRGenDecl。 #pragma once #include #include #include -#include +#include "SysYParser.h" #include "ir/IR.h" -namespace ast { -struct CompUnit; -struct Block; -struct VarDecl; -struct Stmt; -struct Expr; +namespace antlr4 { +namespace tree { +class ParseTree; } +} // namespace antlr4 namespace ir { class Module; class Function; class IRBuilder; class Value; -class ConstantInt; } -// 最小 IR 生成器的内部实现,接口分散在各 IRGen*.cpp。 class IRGenImpl { public: explicit IRGenImpl(ir::Module& module); - void Gen(const ast::CompUnit& ast); - std::unique_ptr TakeModule(); + void Gen(SysYParser::CompUnitContext& cu); private: - void GenBlock(const ast::Block& block); - void GenVarDecl(const ast::VarDecl& decl); - void GenStmt(const ast::Stmt& stmt); - ir::Value* GenExpr(const ast::Expr& expr); + void GenFuncDef(SysYParser::FuncDefContext& func); + void GenBlock(SysYParser::BlockContext& block); + void GenStmt(SysYParser::StmtContext& stmt); + void GenVarDecl(SysYParser::VarDeclContext& decl); + void GenReturnStmt(SysYParser::ReturnStmtContext& ret); + + ir::Value* GenExpr(SysYParser::ExpContext& expr); + ir::Value* GenAddExpr(SysYParser::AddExpContext& add); + ir::Value* GenPrimary(SysYParser::PrimaryContext& primary); ir::Module& module_; ir::Function* func_; @@ -47,4 +46,4 @@ class IRGenImpl { std::unordered_map locals_; }; -std::unique_ptr GenerateIR(const ast::CompUnit& ast); +std::unique_ptr GenerateIR(antlr4::tree::ParseTree* tree); diff --git a/src/irgen/IRGenDecl.cpp b/src/irgen/IRGenDecl.cpp index 099ea0b..d8e54b2 100644 --- a/src/irgen/IRGenDecl.cpp +++ b/src/irgen/IRGenDecl.cpp @@ -1,39 +1,36 @@ -// 声明翻译模块: -// - 处理全局变量与局部变量声明 -// - 处理数组初始化、空间分配与初值生成等 - #include "irgen/IRGen.h" -#include #include -#include "ast/AstNodes.h" +#include "SysYParser.h" #include "ir/IR.h" -void IRGenImpl::GenBlock(const ast::Block& block) { - // 先为所有局部变量创建栈槽,使 alloca 聚集在入口块前部。 - for (const auto& decl : block.varDecls) { - auto* slot = builder_.CreateAllocaI32(ir::DefaultContext().NextTemp()); - locals_[decl->name] = slot; +void IRGenImpl::GenBlock(SysYParser::BlockContext& block) { + for (auto* stmt : block.stmt()) { + if (stmt && stmt->varDecl()) { + const std::string name = stmt->varDecl()->Ident()->getText(); + auto* slot = builder_.CreateAllocaI32(ir::DefaultContext().NextTemp()); + locals_[name] = slot; + } } - for (const auto& decl : block.varDecls) { - GenVarDecl(*decl); - } - for (const auto& stmt : block.stmts) { - GenStmt(*stmt); + for (auto* stmt : block.stmt()) { + if (stmt) { + GenStmt(*stmt); + } } } -void IRGenImpl::GenVarDecl(const ast::VarDecl& decl) { - auto it = locals_.find(decl.name); +void IRGenImpl::GenVarDecl(SysYParser::VarDeclContext& decl) { + const std::string name = decl.Ident()->getText(); + auto it = locals_.find(name); if (it == locals_.end()) { - throw std::runtime_error("[irgen] 变量栈槽未创建: " + decl.name); + throw std::runtime_error("[irgen] 变量栈槽未创建: " + name); } ir::Value* init = nullptr; - if (decl.init) { - init = GenExpr(*decl.init); + if (decl.exp()) { + init = GenExpr(*decl.exp()); } else { init = ir::DefaultContext().GetConstInt(0); } diff --git a/src/irgen/IRGenDriver.cpp b/src/irgen/IRGenDriver.cpp index d7d1699..2c585f8 100644 --- a/src/irgen/IRGenDriver.cpp +++ b/src/irgen/IRGenDriver.cpp @@ -1,19 +1,24 @@ -// 这是一个“可跑”的最小 IR 生成示例,便于对照/调试。 -// IR 生成驱动(Driver): -// - 驱动 Visitor 遍历 AST,调度各子模块完成翻译 -// - 统一管理模块级翻译入口与上下文(Module/IRBuilder 等) -// - 组织函数/语句/表达式/声明等翻译流程 - #include "irgen/IRGen.h" #include +#include -#include "ast/AstNodes.h" +#include "SysYParser.h" +#include "antlr4-runtime.h" #include "ir/IR.h" -std::unique_ptr GenerateIR(const ast::CompUnit& ast) { +std::unique_ptr GenerateIR(antlr4::tree::ParseTree* tree) { + if (!tree) { + throw std::runtime_error("[irgen] parse tree 为空"); + } + + auto* cu = dynamic_cast(tree); + if (!cu) { + throw std::runtime_error("[irgen] parse tree 根节点不是 compUnit"); + } + auto module = std::make_unique(); IRGenImpl gen(*module); - gen.Gen(ast); + gen.Gen(*cu); return module; } diff --git a/src/irgen/IRGenExp.cpp b/src/irgen/IRGenExp.cpp index 2dfc6aa..3b7c7d4 100644 --- a/src/irgen/IRGenExp.cpp +++ b/src/irgen/IRGenExp.cpp @@ -1,37 +1,46 @@ -// 表达式翻译模块: -// - 处理算术运算、比较、逻辑运算、函数调用等表达式 -// - 生成对应的 IR 指令并返回 SSA 值 - #include "irgen/IRGen.h" #include -#include "ast/AstNodes.h" +#include "SysYParser.h" #include "ir/IR.h" -ir::Value* IRGenImpl::GenExpr(const ast::Expr& expr) { - if (auto num = dynamic_cast(&expr)) { - return ir::DefaultContext().GetConstInt(num->value); +ir::Value* IRGenImpl::GenExpr(SysYParser::ExpContext& expr) { + if (!expr.addExp()) { + throw std::runtime_error("[irgen] 非法表达式"); } - if (auto var = dynamic_cast(&expr)) { - auto it = locals_.find(var->name); - if (it == locals_.end()) { - throw std::runtime_error("[irgen] 变量未找到: " + var->name); - } - std::string name = ir::DefaultContext().NextTemp(); - return builder_.CreateLoad(it->second, name); + return GenAddExpr(*expr.addExp()); +} + +ir::Value* IRGenImpl::GenAddExpr(SysYParser::AddExpContext& add) { + const auto& terms = add.primary(); + if (terms.empty()) { + throw std::runtime_error("[irgen] 空加法表达式"); } - if (auto bin = dynamic_cast(&expr)) { - auto* lhs = GenExpr(*bin->lhs); - auto* rhs = GenExpr(*bin->rhs); + + ir::Value* acc = GenPrimary(*terms[0]); + for (size_t i = 1; i < terms.size(); ++i) { + ir::Value* rhs = GenPrimary(*terms[i]); std::string name = ir::DefaultContext().NextTemp(); - if (bin->op == ast::BinaryOp::Add) { - return builder_.CreateBinary(ir::Opcode::Add, lhs, rhs, name); - } - if (bin->op == ast::BinaryOp::Sub) { - // 当前子集只需要加法,减法复用 add 但保留分支,便于扩展 - return builder_.CreateBinary(ir::Opcode::Add, lhs, rhs, name); + acc = builder_.CreateBinary(ir::Opcode::Add, acc, rhs, name); + } + return acc; +} + +ir::Value* IRGenImpl::GenPrimary(SysYParser::PrimaryContext& primary) { + if (primary.Number()) { + return ir::DefaultContext().GetConstInt(std::stoi(primary.Number()->getText())); + } + if (primary.Ident()) { + const std::string name = primary.Ident()->getText(); + auto it = locals_.find(name); + if (it == locals_.end()) { + throw std::runtime_error("[irgen] 变量未找到: " + name); } + return builder_.CreateLoad(it->second, ir::DefaultContext().NextTemp()); + } + if (primary.exp()) { + return GenExpr(*primary.exp()); } - throw std::runtime_error("[irgen] 暂不支持的表达式类型"); + throw std::runtime_error("[irgen] 暂不支持的 primary 形式"); } diff --git a/src/irgen/IRGenFunc.cpp b/src/irgen/IRGenFunc.cpp index e1b4a24..dfbe25f 100644 --- a/src/irgen/IRGenFunc.cpp +++ b/src/irgen/IRGenFunc.cpp @@ -1,26 +1,28 @@ -// 函数翻译模块: -// - 处理函数定义、参数列表与返回值翻译 -// - 创建并填充对应的 IR Function 对象 - #include "irgen/IRGen.h" #include -#include "ast/AstNodes.h" +#include "SysYParser.h" #include "ir/IR.h" IRGenImpl::IRGenImpl(ir::Module& module) - : module_(module), - func_(module_.CreateFunction("main", ir::Type::Int32())), - builder_(func_->entry()) {} + : module_(module), func_(nullptr), builder_(nullptr) {} -void IRGenImpl::Gen(const ast::CompUnit& ast) { - if (!ast.func || !ast.func->body) { - throw std::runtime_error("[irgen] AST 不完整:缺少 main 定义"); +void IRGenImpl::Gen(SysYParser::CompUnitContext& cu) { + if (!cu.funcDef()) { + throw std::runtime_error("[irgen] 缺少 main 定义"); } - GenBlock(*ast.func->body); + GenFuncDef(*cu.funcDef()); } -std::unique_ptr IRGenImpl::TakeModule() { - return std::make_unique(std::move(module_)); +void IRGenImpl::GenFuncDef(SysYParser::FuncDefContext& func) { + if (!func.block()) { + throw std::runtime_error("[irgen] 函数体为空"); + } + + func_ = module_.CreateFunction("main", ir::Type::Int32()); + builder_.SetInsertPoint(func_->entry()); + locals_.clear(); + + GenBlock(*func.block()); } diff --git a/src/irgen/IRGenStmt.cpp b/src/irgen/IRGenStmt.cpp index 9704f98..bf9a605 100644 --- a/src/irgen/IRGenStmt.cpp +++ b/src/irgen/IRGenStmt.cpp @@ -1,19 +1,26 @@ -// 语句翻译模块: -// - 处理 if/while/return 等控制流构造 -// - 负责基本块创建、分支跳转与控制流收束 - #include "irgen/IRGen.h" #include -#include "ast/AstNodes.h" +#include "SysYParser.h" #include "ir/IR.h" -void IRGenImpl::GenStmt(const ast::Stmt& stmt) { - if (auto ret = dynamic_cast(&stmt)) { - ir::Value* v = GenExpr(*ret->value); - builder_.CreateRet(v); +void IRGenImpl::GenStmt(SysYParser::StmtContext& stmt) { + if (stmt.varDecl()) { + GenVarDecl(*stmt.varDecl()); + return; + } + if (stmt.returnStmt()) { + GenReturnStmt(*stmt.returnStmt()); return; } throw std::runtime_error("[irgen] 暂不支持的语句类型"); } + +void IRGenImpl::GenReturnStmt(SysYParser::ReturnStmtContext& ret) { + if (!ret.exp()) { + throw std::runtime_error("[irgen] return 缺少表达式"); + } + ir::Value* v = GenExpr(*ret.exp()); + builder_.CreateRet(v); +} diff --git a/src/main.cpp b/src/main.cpp index 121dbb6..609ea67 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,17 +1,12 @@ #include -#include #include -#include #include "frontend/AntlrDriver.h" -#include "frontend/AstBuilder.h" #include "ir/IR.h" #include "irgen/IRGen.h" #include "mir/MIR.h" -#include "sem/Sema.h" #include "utils/CLI.h" #include "utils/Log.h" -#include "ast/AstNodes.h" int main(int argc, char** argv) { try { @@ -20,25 +15,15 @@ int main(int argc, char** argv) { PrintHelp(std::cout); return 0; } + auto antlr = ParseFileWithAntlr(opts.input); - auto ast = BuildAst(antlr.tree); bool need_blank_line = false; - if (opts.emit_ast) { - ast::PrintAST(*ast); // 调试 AST + if (opts.emit_parse_tree) { + std::cout << antlr.tree->toStringTree(antlr.parser.get()) << "\n"; need_blank_line = true; } - if (!opts.ast_dot_output.empty()) { - std::ofstream dot_out(opts.ast_dot_output); - if (!dot_out) { - throw std::runtime_error("无法写入 AST DOT 文件: " + opts.ast_dot_output); - } - ast::PrintASTDot(*ast, dot_out); - } - ast = RunSema(std::move(ast)); - // IR 生成:当前使用 IRGenDriver.cpp 里的最小实现, - // 同学们可以在 irgen/ 目录下按提示自行完善或替换实现。 - auto module = GenerateIR(*ast); + auto module = GenerateIR(antlr.tree); if (opts.emit_ir) { ir::IRPrinter printer; if (need_blank_line) { diff --git a/src/sem/Sema.cpp b/src/sem/Sema.cpp index 68e9056..92b960c 100644 --- a/src/sem/Sema.cpp +++ b/src/sem/Sema.cpp @@ -19,14 +19,14 @@ class SemaVisitor { explicit SemaVisitor(SymbolTable& table) : table_(table) {} void CheckBlock(const ast::Block& block) { - for (const auto& decl : block.varDecls) { - table_.Add(decl->name); - if (decl->init) CheckExpr(*decl->init); - } - for (const auto& stmt : block.stmts) { - if (auto ret = dynamic_cast(stmt.get())) { + for (const auto& item : block.items) { + if (auto decl = dynamic_cast(item.get())) { + table_.Add(decl->name); + if (decl->init) CheckExpr(*decl->init); + continue; + } + if (auto ret = dynamic_cast(item.get())) { CheckExpr(*ret->value); - } } } diff --git a/src/utils/CLI.cpp b/src/utils/CLI.cpp index 31742ac..571750e 100644 --- a/src/utils/CLI.cpp +++ b/src/utils/CLI.cpp @@ -15,7 +15,7 @@ CLIOptions ParseCLI(int argc, char** argv) { if (argc <= 1) { throw std::runtime_error( - "用法: compiler [--help] [--emit-ast] [--emit-ir] [--emit-asm] [--ast-dot ] "); + "用法: compiler [--help] [--emit-parse-tree] [--emit-ir] [--emit-asm] "); } for (int i = 1; i < argc; ++i) { @@ -25,27 +25,20 @@ CLIOptions ParseCLI(int argc, char** argv) { return opt; } - if (std::strcmp(arg, "--ast-dot") == 0) { - if (i + 1 >= argc) { - throw std::runtime_error("参数错误: --ast-dot 需要一个输出路径"); - } - opt.ast_dot_output = argv[++i]; - continue; - } - - if (std::strcmp(arg, "--emit-ast") == 0) { + if (std::strcmp(arg, "--emit-parse-tree") == 0) { if (!explicit_emit) { - opt.emit_ast = false; + opt.emit_parse_tree = false; opt.emit_ir = false; + opt.emit_asm = false; explicit_emit = true; } - opt.emit_ast = true; + opt.emit_parse_tree = true; continue; } if (std::strcmp(arg, "--emit-ir") == 0) { if (!explicit_emit) { - opt.emit_ast = false; + opt.emit_parse_tree = false; opt.emit_ir = false; opt.emit_asm = false; explicit_emit = true; @@ -56,7 +49,7 @@ CLIOptions ParseCLI(int argc, char** argv) { if (std::strcmp(arg, "--emit-asm") == 0) { if (!explicit_emit) { - opt.emit_ast = false; + opt.emit_parse_tree = false; opt.emit_ir = false; opt.emit_asm = false; explicit_emit = true; @@ -80,10 +73,9 @@ CLIOptions ParseCLI(int argc, char** argv) { if (opt.input.empty() && !opt.show_help) { throw std::runtime_error("缺少输入文件:请提供 (使用 --help 查看用法)"); } - if (!opt.emit_ast && !opt.emit_ir && !opt.emit_asm && - opt.ast_dot_output.empty()) { + if (!opt.emit_parse_tree && !opt.emit_ir && !opt.emit_asm) { throw std::runtime_error( - "未选择任何输出:请使用 --emit-ast / --emit-ir / --emit-asm(或使用 --ast-dot 导出图)"); + "未选择任何输出:请使用 --emit-parse-tree / --emit-ir / --emit-asm"); } return opt; } diff --git a/src/utils/CLI.h b/src/utils/CLI.h index 10fe377..4b3a781 100644 --- a/src/utils/CLI.h +++ b/src/utils/CLI.h @@ -1,12 +1,11 @@ -// 简易命令行解析:支持帮助、输入文件和 AST DOT 导出。 +// 简易命令行解析:支持帮助、输入文件与输出阶段选择。 #pragma once #include struct CLIOptions { std::string input; - std::string ast_dot_output; - bool emit_ast = true; + bool emit_parse_tree = false; bool emit_ir = true; bool emit_asm = false; bool show_help = false; diff --git a/src/utils/Log.cpp b/src/utils/Log.cpp index b8e3a68..0b8ae78 100644 --- a/src/utils/Log.cpp +++ b/src/utils/Log.cpp @@ -10,18 +10,17 @@ void PrintHelp(std::ostream& os) { os << "SysY Compiler (课程实验最小可运行示例)\n" << "\n" << "用法:\n" - << " compiler [--help] [--emit-ast] [--emit-ir] [--emit-asm] [--ast-dot ] \n" + << " compiler [--help] [--emit-parse-tree] [--emit-ir] [--emit-asm] \n" << "\n" << "选项:\n" << " -h, --help 打印帮助信息并退出\n" - << " --emit-ast 仅在显式模式下启用 AST 文本输出\n" + << " --emit-parse-tree 仅在显式模式下启用 ANTLR 语法树输出\n" << " --emit-ir 仅在显式模式下启用 IR 输出\n" << " --emit-asm 仅在显式模式下启用 AArch64 汇编输出\n" - << " --ast-dot 导出 AST Graphviz DOT 到指定文件\n" << "\n" << "说明:\n" - << " - 默认同时输出 AST 与 IR\n" - << " - 若使用 --emit-ast/--emit-ir/--emit-asm,则仅输出显式选择的阶段\n" + << " - 默认输出 IR\n" + << " - 若使用 --emit-parse-tree/--emit-ir/--emit-asm,则仅输出显式选择的阶段\n" << " - 可使用重定向写入文件:\n" << " compiler --emit-asm test/test_case/simple_add.sy > out.s\n"; }