From e1c1f2a40dc09d834d7d3f921ec4bb96a7993733 Mon Sep 17 00:00:00 2001 From: jing <3030349106@qq.com> Date: Mon, 29 Dec 2025 20:11:51 +0800 Subject: [PATCH] =?UTF-8?q?IR=E8=AE=BE=E8=AE=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ir/BasicBlock.cpp | 1 + src/ir/Context.cpp | 41 ++++++++++ src/ir/Function.cpp | 8 ++ src/ir/IR.h | 172 +++++++++++++++++++++++++++++++++++++++++ src/ir/IRBuilder.cpp | 26 +++++++ src/ir/IRPrinter.cpp | 65 ++++++++++++++++ src/ir/Instruction.cpp | 11 +++ src/ir/Module.cpp | 13 +++- src/ir/Type.cpp | 13 +++- src/ir/Value.cpp | 8 ++ src/main.cpp | 44 +++++------ src/utils/CLI.cpp | 12 +++ src/utils/CLI.h | 10 +++ src/utils/Log.cpp | 1 + 14 files changed, 400 insertions(+), 25 deletions(-) create mode 100644 src/ir/IR.h create mode 100644 src/utils/CLI.h diff --git a/src/ir/BasicBlock.cpp b/src/ir/BasicBlock.cpp index 822e987..c85d923 100644 --- a/src/ir/BasicBlock.cpp +++ b/src/ir/BasicBlock.cpp @@ -2,3 +2,4 @@ // - 保存指令序列 // - 维护或可计算前驱/后继关系,用于 CFG 分析与优化 +#include "ir/IR.h" diff --git a/src/ir/Context.cpp b/src/ir/Context.cpp index d71a481..d8543e2 100644 --- a/src/ir/Context.cpp +++ b/src/ir/Context.cpp @@ -1,4 +1,45 @@ // IR 上下文: // - 管理类型与常量的创建/复用 // - 保存字符串常量、符号等公共资源(按需要扩展) +#include "ir/IR.h" +#include + +namespace ir { + +Context& DefaultContext() { + static Context ctx; + return ctx; +} + +Context::~Context() = default; + +const std::shared_ptr& Context::Void() { + if (!void_) { + void_ = std::make_shared(Type::Kind::Void); + } + return void_; +} + +const std::shared_ptr& Context::Int32() { + if (!int32_) { + int32_ = std::make_shared(Type::Kind::Int32); + } + return int32_; +} + +ConstantInt* Context::GetConstInt(int v) { + auto it = const_ints_.find(v); + if (it != const_ints_.end()) return it->second.get(); + auto inserted = + const_ints_.emplace(v, std::make_unique(v)).first; + return inserted->second.get(); +} + +std::string Context::NextTemp() { + std::ostringstream oss; + oss << "%t" << temp_index_++; + return oss.str(); +} + +} // namespace ir diff --git a/src/ir/Function.cpp b/src/ir/Function.cpp index 88d2427..34c7b71 100644 --- a/src/ir/Function.cpp +++ b/src/ir/Function.cpp @@ -1,4 +1,12 @@ // IR Function: // - 保存参数列表、基本块列表 // - 记录函数属性/元信息(按需要扩展) +#include "ir/IR.h" +namespace ir { + +Function::Function(std::string name, std::shared_ptr ret_type) + : Value(std::move(ret_type), std::move(name)), + entry_(std::make_unique("entry")) {} + +} // namespace ir diff --git a/src/ir/IR.h b/src/ir/IR.h new file mode 100644 index 0000000..0c6913f --- /dev/null +++ b/src/ir/IR.h @@ -0,0 +1,172 @@ +// 极简 IR 定义:当前只支撑 i32 和加法,演示用。 +// 可在此基础上扩展更多类型/指令 +#pragma once + +#include +#include +#include +#include +#include + +namespace ir { + +class Type; +class ConstantInt; + +// IR 上下文:集中管理类型、常量等共享资源,便于复用与扩展。 +class Context { + public: + ~Context(); + const std::shared_ptr& Void(); + const std::shared_ptr& Int32(); + // 去重创建 i32 常量。 + ConstantInt* GetConstInt(int v); + // 生成临时名称,如 %t0、%t1 ... + std::string NextTemp(); + + private: + std::shared_ptr void_; + std::shared_ptr int32_; + std::unordered_map> const_ints_; + int temp_index_ = 0; +}; + +Context& DefaultContext(); + +class Type { + public: + enum class Kind { Void, Int32 }; + explicit Type(Kind k) : kind_(k) {} + Kind kind() const { return kind_; } + static std::shared_ptr Void(); + static std::shared_ptr Int32(); + + private: + Kind kind_; +}; + +class Value { + public: + Value(std::shared_ptr ty, std::string name) + : type_(std::move(ty)), name_(std::move(name)) {} + virtual ~Value() = default; + const std::shared_ptr& type() const { return type_; } + const std::string& name() const { return name_; } + void set_name(std::string n) { name_ = std::move(n); } + + protected: + std::shared_ptr type_; + std::string name_; +}; + +class ConstantInt : public Value { + public: + explicit ConstantInt(int v); + int value() const { return value_; } + + private: + int value_{}; +}; + +enum class Opcode { Add, Sub, Mul, Ret }; + +class Instruction : public Value { + public: + Instruction(Opcode op, std::shared_ptr ty, std::string name = "") + : Value(std::move(ty), std::move(name)), opcode_(op) {} + Opcode opcode() const { return opcode_; } + + private: + Opcode opcode_; +}; + +class BinaryInst : public Instruction { + public: + BinaryInst(Opcode op, std::shared_ptr ty, Value* lhs, Value* rhs, + std::string name); + Value* lhs() const { return lhs_; } + Value* rhs() const { return rhs_; } + + private: + Value* lhs_; + Value* rhs_; +}; + +class ReturnInst : public Instruction { + public: + explicit ReturnInst(Value* val); + Value* value() const { return value_; } + + private: + Value* value_; +}; + +class BasicBlock { + public: + explicit BasicBlock(std::string name) : name_(std::move(name)) {} + const std::string& name() const { return name_; } + const std::vector>& instructions() const { + return instructions_; + } + template + T* Append(Args&&... args) { + auto inst = std::make_unique(std::forward(args)...); + auto* ptr = inst.get(); + instructions_.push_back(std::move(inst)); + return ptr; + } + + private: + std::string name_; + std::vector> instructions_; +}; + +class Function : public Value { + public: + // 允许显式指定返回类型,便于后续扩展多种函数签名。 + Function(std::string name, std::shared_ptr ret_type); + BasicBlock* entry() { return entry_.get(); } + const BasicBlock* entry() const { return entry_.get(); } + + private: + std::unique_ptr entry_; +}; + +class Module { + public: + // 创建函数时显式传入返回类型,便于在 IRGen 中根据 AST 选择类型。 + Function* CreateFunction(const std::string& name, + std::shared_ptr ret_type); + const std::vector>& functions() const { + return functions_; + } + + private: + std::vector> functions_; +}; + +class IRBuilder { + public: + explicit IRBuilder(BasicBlock* bb) : insertBlock_(bb) {} + void SetInsertPoint(BasicBlock* bb) { insertBlock_ = bb; } + BasicBlock* GetInsertBlock() const { return insertBlock_; } + + // 构造常量、二元运算、返回指令的最小集合。 + ConstantInt* CreateConstInt(int v); + BinaryInst* CreateBinary(Opcode op, Value* lhs, Value* rhs, + const std::string& name); + BinaryInst* CreateAdd(Value* lhs, Value* rhs, const std::string& name) { + return CreateBinary(Opcode::Add, lhs, rhs, name); + } + ReturnInst* CreateRet(Value* v); + + private: + BasicBlock* insertBlock_; +}; + +class IRPrinter { + public: + void Print(const Module& module); +}; + +} // namespace ir diff --git a/src/ir/IRBuilder.cpp b/src/ir/IRBuilder.cpp index 554f2f6..bbad735 100644 --- a/src/ir/IRBuilder.cpp +++ b/src/ir/IRBuilder.cpp @@ -2,3 +2,29 @@ // - 管理插入点(当前基本块/位置) // - 提供创建各类指令的便捷接口,降低 IRGen 复杂度 +#include "ir/IR.h" +#include + +namespace ir { + +ConstantInt* IRBuilder::CreateConstInt(int v) { + // 常量不需要挂在基本块里,由 Context 负责去重与生命周期。 + return DefaultContext().GetConstInt(v); +} + +BinaryInst* IRBuilder::CreateBinary(Opcode op, Value* lhs, Value* rhs, + const std::string& name) { + if (!insertBlock_) { + throw std::runtime_error("IRBuilder 未设置插入点"); + } + return insertBlock_->Append(op, Type::Int32(), lhs, rhs, name); +} + +ReturnInst* IRBuilder::CreateRet(Value* v) { + if (!insertBlock_) { + throw std::runtime_error("IRBuilder 未设置插入点"); + } + return insertBlock_->Append(v); +} + +} // namespace ir diff --git a/src/ir/IRPrinter.cpp b/src/ir/IRPrinter.cpp index fddaf43..ee0f6be 100644 --- a/src/ir/IRPrinter.cpp +++ b/src/ir/IRPrinter.cpp @@ -2,3 +2,68 @@ // - 将 IR 打印为 .ll 风格的文本 // - 支撑调试与测试对比(diff) +#include "ir/IR.h" + +#include +#include + +namespace ir { + +static const char* TypeToString(const Type& ty) { + switch (ty.kind()) { + case Type::Kind::Void: + return "void"; + case Type::Kind::Int32: + return "i32"; + } + throw std::runtime_error("未知类型"); +} + +static const char* OpcodeToString(Opcode op) { + switch (op) { + case Opcode::Add: + return "add"; + case Opcode::Sub: + return "sub"; + case Opcode::Mul: + return "mul"; + case Opcode::Ret: + return "ret"; + } + return "?"; +} + +void IRPrinter::Print(const Module& module) { + for (const auto& func : module.functions()) { + std::cout << "define " << TypeToString(*func->type()) << " @" + << func->name() << "() {\n"; + const auto* bb = func->entry(); + if (!bb) { + std::cout << "}\n"; + continue; + } + for (const auto& instPtr : bb->instructions()) { + const auto* inst = instPtr.get(); + switch (inst->opcode()) { + case Opcode::Add: + case Opcode::Sub: + case Opcode::Mul: { + auto* bin = static_cast(inst); + std::cout << " " << bin->name() << " = " << OpcodeToString(bin->opcode()) + << " " << TypeToString(*bin->lhs()->type()) << " " + << bin->lhs()->name() << ", " << bin->rhs()->name() << "\n"; + break; + } + case Opcode::Ret: { + auto* ret = static_cast(inst); + std::cout << " ret " << TypeToString(*ret->value()->type()) << " " + << ret->value()->name() << "\n"; + break; + } + } + } + std::cout << "}\n"; + } +} + +} // namespace ir diff --git a/src/ir/Instruction.cpp b/src/ir/Instruction.cpp index c8e0e24..82f013e 100644 --- a/src/ir/Instruction.cpp +++ b/src/ir/Instruction.cpp @@ -1,4 +1,15 @@ // IR 指令体系: // - 二元运算/比较、load/store、call、br/condbr、ret、phi、alloca 等 // - 指令操作数与结果类型管理,支持打印与优化 +#include "ir/IR.h" +namespace ir { + +BinaryInst::BinaryInst(Opcode op, std::shared_ptr ty, Value* lhs, + Value* rhs, std::string name) + : Instruction(op, std::move(ty), std::move(name)), lhs_(lhs), rhs_(rhs) {} + +ReturnInst::ReturnInst(Value* val) + : Instruction(Opcode::Ret, Type::Void(), ""), value_(val) {} + +} // namespace ir diff --git a/src/ir/Module.cpp b/src/ir/Module.cpp index 9d7fc51..92ca9df 100644 --- a/src/ir/Module.cpp +++ b/src/ir/Module.cpp @@ -1,4 +1,15 @@ // IR Module: // - 保存全局变量与函数列表 -// - 维护与目标相关的模块级信息(如需要)与符号表 +// - 维护与目标相关的模块级信息(如需要) +#include "ir/IR.h" + +namespace ir { + +Function* Module::CreateFunction(const std::string& name, + std::shared_ptr ret_type) { + functions_.push_back(std::make_unique(name, std::move(ret_type))); + return functions_.back().get(); +} + +} // namespace ir diff --git a/src/ir/Type.cpp b/src/ir/Type.cpp index ac51dba..3ece7f8 100644 --- a/src/ir/Type.cpp +++ b/src/ir/Type.cpp @@ -1,4 +1,13 @@ -// IR 类型系统: -// - i32/f32/void、指针、数组、函数类型等 +// 极简类型系统:仅支持 void 与 i32。 + +// 还应该包含 i32/f32/void、指针、数组、函数类型等 // - 按 SysY 支持范围裁剪并逐步补齐 +#include "ir/IR.h" + +namespace ir { + +std::shared_ptr Type::Void() { return DefaultContext().Void(); } + +std::shared_ptr Type::Int32() { return DefaultContext().Int32(); } +} // namespace ir diff --git a/src/ir/Value.cpp b/src/ir/Value.cpp index bd73cc7..a4510b8 100644 --- a/src/ir/Value.cpp +++ b/src/ir/Value.cpp @@ -1,4 +1,12 @@ // SSA 值体系抽象: // - 常量、参数、指令结果等统一为 Value // - 提供类型信息与使用/被使用关系(按需要实现) +#include "ir/IR.h" +namespace ir { + +ConstantInt::ConstantInt(int v) : Value(Type::Int32(), ""), value_(v) { + set_name(std::to_string(v)); +} + +} // namespace ir diff --git a/src/main.cpp b/src/main.cpp index bfbc3fa..cc0d5e3 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,30 +1,30 @@ +#include #include -#include -static void PrintUsage(const char* argv0) { - std::cerr << "用法: " << (argv0 ? argv0 : "compiler") << " [options]\n"; - std::cerr << "说明: 当前为工程骨架阶段,暂不执行完整编译流程,仅用于验证可编译/可链接。\n"; -} +#include "frontend/AntlrDriver.h" +#include "frontend/AstBuilder.h" +#include "ir/IR.h" +#include "irgen/IRGen.h" +#include "sem/Sema.h" +#include "utils/CLI.h" +#include "ast/AstNodes.h" int main(int argc, char** argv) { - if (argc <= 1) { - PrintUsage(argv[0]); - return 0; - } + try { + auto opts = ParseCLI(argc, argv); + auto antlr = ParseFileWithAntlr(opts.input); + auto ast = BuildAst(antlr.tree); + ast::PrintAST(*ast); // 调试 AST + ast = RunSema(std::move(ast)); + // IR 生成:当前使用 IRGenDriver.cpp 里的最小参考实现, + // 同学们可以在 irgen/ 目录下按提示自行完善或替换实现。 + auto module = GenerateIR(*ast); - std::string input_path = argv[1]; - if (input_path == "-h" || input_path == "--help") { - PrintUsage(argv[0]); - return 0; + ir::IRPrinter printer; + printer.Print(*module); + } catch (const std::exception& ex) { + std::cerr << "error: " << ex.what() << "\n"; + return 1; } - - // TODO: 后续在此接入完整流水线: - // 1) frontend: ANTLR 解析 + AST 构建 - // 2) sem: 语义分析 - // 3) irgen: AST -> IR - // 4) ir passes: 可选优化 - // 5) mir/backend: AArch64 指令选择、寄存器分配、栈帧、汇编输出 - (void)input_path; - return 0; } diff --git a/src/utils/CLI.cpp b/src/utils/CLI.cpp index 6e84a34..d9882db 100644 --- a/src/utils/CLI.cpp +++ b/src/utils/CLI.cpp @@ -3,3 +3,15 @@ // - 解析输出类型(IR/MIR/ASM)与优化级别等选项 // - 将参数传递给 main.cpp 的编译流水线驱动 +#include "utils/CLI.h" + +#include + +CLIOptions ParseCLI(int argc, char** argv) { + if (argc <= 1) { + throw std::runtime_error("用法: compiler "); + } + CLIOptions opt; + opt.input = argv[1]; + return opt; +} diff --git a/src/utils/CLI.h b/src/utils/CLI.h new file mode 100644 index 0000000..f69c583 --- /dev/null +++ b/src/utils/CLI.h @@ -0,0 +1,10 @@ +// 简易命令行解析:仅支持输入文件路径。 +#pragma once + +#include + +struct CLIOptions { + std::string input; +}; + +CLIOptions ParseCLI(int argc, char** argv); diff --git a/src/utils/Log.cpp b/src/utils/Log.cpp index 4cb15da..af90bdc 100644 --- a/src/utils/Log.cpp +++ b/src/utils/Log.cpp @@ -2,3 +2,4 @@ // - 统一输出调试信息、阶段信息与错误信息 // - 提供可配置的日志级别与输出位置(按需要实现) +#include "utils/Log.h"