From d71eb4576e5dc134d94d64f36a98b6f571933ef9 Mon Sep 17 00:00:00 2001 From: hym816 Date: Sun, 16 Nov 2025 21:04:02 +0800 Subject: [PATCH] =?UTF-8?q?=E3=80=902025-11-16=E3=80=91=E7=8E=B0=E6=9C=89?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=E4=B8=8A=E4=BC=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AssemblyGenerator.cpp | 204 +++ AssemblyGenerator.h | 28 + InstructionEncoder.cpp | 169 ++ InstructionEncoder.h | 61 + ObjectFileGenerator.cpp | 113 ++ ObjectFileGenerator.h | 18 + PrettyPrinter.cpp | 411 +++++ PrettyPrinter.h | 57 + ast.cpp | 809 +++++++++ ast.h | 325 ++++ interpreter.cpp | 364 ++++ interpreter.h | 41 + ir.cpp | 612 +++++++ ir.h | 130 ++ lex.yy.cpp | 2599 ++++++++++++++++++++++++++++ main.cpp | 273 +++ mini_c.l | 210 +++ mini_c.tab.cpp | 3529 +++++++++++++++++++++++++++++++++++++++ mini_c.tab.hpp | 164 ++ mini_c.y | 799 +++++++++ semantic.cpp | 368 ++++ semantic.h | 38 + stack.hh | 8 + symbol.cpp | 5 + symbol.h | 52 + tt.cpp | 6 + type.cpp | 5 + type.h | 126 ++ 28 files changed, 11524 insertions(+) create mode 100644 AssemblyGenerator.cpp create mode 100644 AssemblyGenerator.h create mode 100644 InstructionEncoder.cpp create mode 100644 InstructionEncoder.h create mode 100644 ObjectFileGenerator.cpp create mode 100644 ObjectFileGenerator.h create mode 100644 PrettyPrinter.cpp create mode 100644 PrettyPrinter.h create mode 100644 ast.cpp create mode 100644 ast.h create mode 100644 interpreter.cpp create mode 100644 interpreter.h create mode 100644 ir.cpp create mode 100644 ir.h create mode 100644 lex.yy.cpp create mode 100644 main.cpp create mode 100644 mini_c.l create mode 100644 mini_c.tab.cpp create mode 100644 mini_c.tab.hpp create mode 100644 mini_c.y create mode 100644 semantic.cpp create mode 100644 semantic.h create mode 100644 stack.hh create mode 100644 symbol.cpp create mode 100644 symbol.h create mode 100644 tt.cpp create mode 100644 type.cpp create mode 100644 type.h diff --git a/AssemblyGenerator.cpp b/AssemblyGenerator.cpp new file mode 100644 index 0000000..e554cc5 --- /dev/null +++ b/AssemblyGenerator.cpp @@ -0,0 +1,204 @@ +// AssemblyGenerator.cpp +#include "AssemblyGenerator.h" +#include +#include +#include +#include + +AssemblyGenerator::AssemblyGenerator(const std::vector &quads) + : quads_(quads), stackSize_(0) { + allocateStack(); +} + +void AssemblyGenerator::allocateStack() { + int offset = 0; + + // 1) 给所有源变量(localOffset_)分配空间 + for (auto &q : quads_) { + if (!q.var.empty() && localOffset_.count(q.var) == 0) { + offset += 8; + localOffset_[q.var] = offset; + } + } + + // 2) 给所有临时变量(t1, t2, ...)分配空间 + for (auto &q : quads_) { + if (!q.result.empty() && q.result[0] == 't' + && tempOffset_.count(q.result) == 0) { + offset += 8; + tempOffset_[q.result] = offset; + } + } + + // 16 字节对齐 + stackSize_ = ((offset + 15) / 16) * 16; +} + +std::string AssemblyGenerator::generate() { + std::ostringstream out; + + // 1) 段和全局符号声明 + out << ".text\n"; + out << ".globl _main\n"; + + // 2) 如果首条 IR 是一条 "label main",先输出 _main:,然后 prologue + size_t idx = 0; + if (!quads_.empty() && quads_[0].op == "label" && quads_[0].result == "main") { + out << "_main:\n"; + emitPrologue(out); + idx = 1; + } else { + // 否则也输出 prologue + emitPrologue(out); + } + + // 3) 其余指令 + for (size_t i = idx; i < quads_.size(); ++i) { + emitInstruction(quads_[i], out); + } + + // 4) epilogue + emitEpilogue(out); + return out.str(); +} + +void AssemblyGenerator::emitPrologue(std::ostream &os) const { + os << "\tstp x29, x30, [sp, #-16]! // push FP, LR\n"; + os << "\tmov x29, sp\n"; + if (stackSize_ > 0) { + os << "\tsub sp, sp, #" << stackSize_ << "\n"; + } +} + +void AssemblyGenerator::emitEpilogue(std::ostream &os) const { + if (stackSize_ > 0) { + os << "\tadd sp, sp, #" << stackSize_ << "\n"; + } + os << "\tldp x29, x30, [sp], #16 // pop FP, LR\n"; + os << "\tret\n"; +} + +void AssemblyGenerator::loadOperand(const std::string &name, std::ostream &os) const { + if (!name.empty() && std::isdigit(name[0])) { + // 立即数 + os << "\tmov w9, #" << name << "\n"; + } + else if (localOffset_.count(name)) { + // 局部变量 + os << "\tldr w9, [x29, #-" << localOffset_.at(name) << "]\n"; + } + else if (tempOffset_.count(name)) { + // 临时变量 + os << "\tldr w9, [x29, #-" << tempOffset_.at(name) << "]\n"; + } + else { + // 全局变量 + os << "\tadrp x10, " << name << "\n"; + os << "\tadd x10, x10, :lo12:" << name << "\n"; + os << "\tldr w9, [x10]\n"; + } +} + +void AssemblyGenerator::storeResult(const std::string &name, std::ostream &os) const { + if (localOffset_.count(name)) { + // 局部变量 + os << "\tstr w9, [x29, #-" << localOffset_.at(name) << "]\n"; + } + else if (tempOffset_.count(name)) { + // 临时变量 + os << "\tstr w9, [x29, #-" << tempOffset_.at(name) << "]\n"; + } + else { + // 全局变量 + os << "\tadrp x10, " << name << "\n"; + os << "\tadd x10, x10, :lo12:" << name << "\n"; + os << "\tstr w9, [x10]\n"; + } +} + +void AssemblyGenerator::emitInstruction(const Quad &q, std::ostream &os) const { + using std::string; + + // 标签 + if (q.op == "label") { + // 非 main 的其他标签直接原样输出 + if (q.result != "main") { + os << q.result << ":\n"; + } + return; + } + + // 无条件跳转 + if (q.op == "goto") { + os << "\tb " << q.result << "\n"; + return; + } + + // ifFalse x -> cmp x, #0; beq L + if (q.op == "ifFalse") { + loadOperand(q.arg1, os); + os << "\tcmp w9, #0\n"; + os << "\tbeq " << q.result << "\n"; + return; + } + + // 赋值 = + if (q.op == "=") { + loadOperand(q.arg1, os); + storeResult(q.result, os); + return; + } + + // 二元算术/逻辑运算 + static const std::unordered_map binOpMap = { + { "+", "add" }, { "-", "sub" }, { "*", "mul" }, + { "/", "sdiv" }, { "<<", "lsl" }, { ">>", "lsr" }, + { "&", "and" }, { "|", "orr" }, { "^", "eor" } + }; + if (binOpMap.count(q.op)) { + loadOperand(q.arg1, os); + os << "\tmov w10, w9\n"; + loadOperand(q.arg2, os); + os << "\tmov w11, w9\n"; + os << "\t" << binOpMap.at(q.op) << " w9, w10, w11\n"; + storeResult(q.result, os); + return; + } + + // 比较运算,使用 cset 生成布尔 0/1 + static const std::unordered_map cmpCondMap = { + {"==", "eq"}, {"!=", "ne"}, + {"<", "lt"}, {">", "gt"}, + {"<=", "le"}, {">=", "ge"} + }; + if (cmpCondMap.count(q.op)) { + loadOperand(q.arg1, os); + os << "\tmov w10, w9\n"; + loadOperand(q.arg2, os); + os << "\tmov w11, w9\n"; + os << "\tcmp w10, w11\n"; + os << "\tcset w9, " << cmpCondMap.at(q.op) << "\n"; + storeResult(q.result, os); + return; + } + + // call / param / return + if (q.op == "param") { + return; + } + if (q.op == "call") { + os << "\tbl " << q.arg1 << "\n"; + os << "\tmov w9, w0\n"; + storeResult(q.result, os); + return; + } + if (q.op == "return") { + if (!q.arg1.empty()) { + loadOperand(q.arg1, os); + os << "\tmov w0, w9\n"; + } + return; + } + + std::cerr << "Unhandled IR op: " << q.op << "\n"; +} diff --git a/AssemblyGenerator.h b/AssemblyGenerator.h new file mode 100644 index 0000000..e0efae9 --- /dev/null +++ b/AssemblyGenerator.h @@ -0,0 +1,28 @@ +// AssemblyGenerator.h +#ifndef MINI_C_ASSEMBLY_GENERATOR_H +#define MINI_C_ASSEMBLY_GENERATOR_H + +#include "ir.h" +#include +#include +#include +#include + +class AssemblyGenerator { +public: + explicit AssemblyGenerator(const std::vector &quads); + std::string generate(); +private: + const std::vector &quads_; + std::unordered_map localOffset_; + std::unordered_map tempOffset_; + int stackSize_; + void allocateStack(); + void emitPrologue(std::ostream &os) const; + void emitEpilogue(std::ostream &os) const; + void emitInstruction(const Quad &q, std::ostream &os) const; + void loadOperand(const std::string &name, std::ostream &os) const; + void storeResult(const std::string &name, std::ostream &os) const; +}; + +#endif // MINI_C_ASSEMBLY_GENERATOR_H diff --git a/InstructionEncoder.cpp b/InstructionEncoder.cpp new file mode 100644 index 0000000..7ed7af4 --- /dev/null +++ b/InstructionEncoder.cpp @@ -0,0 +1,169 @@ +// InstructionEncoder.cpp +#include "InstructionEncoder.h" +#include + +// ————————————————————————————————————————————— +// 1) 控制流 +// 无条件跳转 B