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