From bb7f42e06e8005808dbe09e537327369feae4988 Mon Sep 17 00:00:00 2001 From: jing <3030349106@qq.com> Date: Mon, 29 Dec 2025 20:30:16 +0800 Subject: [PATCH] =?UTF-8?q?IR=E7=94=9F=E6=88=90=E6=96=87=E4=BB=B6=E5=8D=B3?= =?UTF-8?q?IRGenxx=E8=AE=BE=E8=AE=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/irgen/IRGen.h | 50 +++++++++++++++++++++++++++++++++++++++ src/irgen/IRGenDecl.cpp | 25 ++++++++++++++++++++ src/irgen/IRGenDriver.cpp | 15 ++++++++++++ src/irgen/IRGenExp.cpp | 32 +++++++++++++++++++++++++ src/irgen/IRGenFunc.cpp | 22 +++++++++++++++++ src/irgen/IRGenStmt.cpp | 15 ++++++++++++ src/utils/Log.h | 7 ++++++ 7 files changed, 166 insertions(+) create mode 100644 src/irgen/IRGen.h create mode 100644 src/utils/Log.h diff --git a/src/irgen/IRGen.h b/src/irgen/IRGen.h new file mode 100644 index 0000000..e87fd78 --- /dev/null +++ b/src/irgen/IRGen.h @@ -0,0 +1,50 @@ +// 将 AST 翻译为极简 IR。 +// 这里提供一个可运行的最小 IR 生成骨架,并把实现拆分到 IRGenFunc/IRGenStmt/IRGenExp/IRGenDecl。 +// 同学可以在对应 .cpp 内进一步完善更多语义。 + +#pragma once + +#include +#include +#include +#include + +#include "ir/IR.h" + +namespace ast { +struct CompUnit; +struct Block; +struct VarDecl; +struct Stmt; +struct Expr; +} + +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(); + + 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); + + ir::Module& module_; + ir::Function* func_; + ir::IRBuilder builder_; + std::unordered_map locals_; +}; + +std::unique_ptr GenerateIR(const ast::CompUnit& ast); diff --git a/src/irgen/IRGenDecl.cpp b/src/irgen/IRGenDecl.cpp index 3ff8aec..ba7bae6 100644 --- a/src/irgen/IRGenDecl.cpp +++ b/src/irgen/IRGenDecl.cpp @@ -2,3 +2,28 @@ // - 处理全局变量与局部变量声明 // - 处理数组初始化、空间分配与初值生成等 +#include "irgen/IRGen.h" + +#include + +#include "ast/AstNodes.h" +#include "ir/IR.h" + +void IRGenImpl::GenBlock(const ast::Block& block) { + for (const auto& decl : block.varDecls) { + GenVarDecl(*decl); + } + for (const auto& stmt : block.stmts) { + GenStmt(*stmt); + } +} + +void IRGenImpl::GenVarDecl(const ast::VarDecl& decl) { + ir::Value* init = nullptr; + if (decl.init) { + init = GenExpr(*decl.init); + } else { + init = ir::DefaultContext().GetConstInt(0); + } + locals_[decl.name] = init; +} diff --git a/src/irgen/IRGenDriver.cpp b/src/irgen/IRGenDriver.cpp index ca7d479..d7d1699 100644 --- a/src/irgen/IRGenDriver.cpp +++ b/src/irgen/IRGenDriver.cpp @@ -1,4 +1,19 @@ +// 这是一个“可跑”的最小 IR 生成示例,便于对照/调试。 // IR 生成驱动(Driver): // - 驱动 Visitor 遍历 AST,调度各子模块完成翻译 // - 统一管理模块级翻译入口与上下文(Module/IRBuilder 等) // - 组织函数/语句/表达式/声明等翻译流程 + +#include "irgen/IRGen.h" + +#include + +#include "ast/AstNodes.h" +#include "ir/IR.h" + +std::unique_ptr GenerateIR(const ast::CompUnit& ast) { + auto module = std::make_unique(); + IRGenImpl gen(*module); + gen.Gen(ast); + return module; +} diff --git a/src/irgen/IRGenExp.cpp b/src/irgen/IRGenExp.cpp index 30a9ff0..1a35948 100644 --- a/src/irgen/IRGenExp.cpp +++ b/src/irgen/IRGenExp.cpp @@ -2,3 +2,35 @@ // - 处理算术运算、比较、逻辑运算、函数调用等表达式 // - 生成对应的 IR 指令并返回 SSA 值 +#include "irgen/IRGen.h" + +#include + +#include "ast/AstNodes.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); + } + if (auto var = dynamic_cast(&expr)) { + auto it = locals_.find(var->name); + if (it == locals_.end()) { + throw std::runtime_error("变量未找到: " + var->name); + } + return it->second; + } + if (auto bin = dynamic_cast(&expr)) { + auto* lhs = GenExpr(*bin->lhs); + auto* rhs = GenExpr(*bin->rhs); + 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); + } + } + throw std::runtime_error("不支持的表达式类型"); +} diff --git a/src/irgen/IRGenFunc.cpp b/src/irgen/IRGenFunc.cpp index aa22700..6600a1a 100644 --- a/src/irgen/IRGenFunc.cpp +++ b/src/irgen/IRGenFunc.cpp @@ -2,3 +2,25 @@ // - 处理函数定义、参数列表与返回值翻译 // - 创建并填充对应的 IR Function 对象 +#include "irgen/IRGen.h" + +#include + +#include "ast/AstNodes.h" +#include "ir/IR.h" + +IRGenImpl::IRGenImpl(ir::Module& module) + : module_(module), + func_(module_.CreateFunction("main", ir::Type::Int32())), + builder_(func_->entry()) {} + +void IRGenImpl::Gen(const ast::CompUnit& ast) { + if (!ast.func || !ast.func->body) { + throw std::runtime_error("AST 不完整:缺少 main 定义"); + } + GenBlock(*ast.func->body); +} + +std::unique_ptr IRGenImpl::TakeModule() { + return std::make_unique(std::move(module_)); +} diff --git a/src/irgen/IRGenStmt.cpp b/src/irgen/IRGenStmt.cpp index 63447cf..6e9d189 100644 --- a/src/irgen/IRGenStmt.cpp +++ b/src/irgen/IRGenStmt.cpp @@ -2,3 +2,18 @@ // - 处理 if/while/return 等控制流构造 // - 负责基本块创建、分支跳转与控制流收束 +#include "irgen/IRGen.h" + +#include + +#include "ast/AstNodes.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); + return; + } + throw std::runtime_error("不支持的语句类型"); +} diff --git a/src/utils/Log.h b/src/utils/Log.h new file mode 100644 index 0000000..09d31a7 --- /dev/null +++ b/src/utils/Log.h @@ -0,0 +1,7 @@ +// 轻量日志接口。 +#pragma once + +#include + +#define LOG_INFO(msg) std::cerr << "[info] " << msg << "\n" +#define LOG_ERROR(msg) std::cerr << "[error] " << msg << "\n"