From 1a48e369e70d4e4b18e859274ad81cb3de693dd3 Mon Sep 17 00:00:00 2001 From: ftt <> Date: Wed, 8 Apr 2026 20:49:13 +0800 Subject: [PATCH 01/30] =?UTF-8?q?=E7=AC=AC=E4=B8=80=E9=98=B6=E6=AE=B5?= =?UTF-8?q?=EF=BC=9A=E6=89=A9=E5=B1=95=20MIR=20=E6=8C=87=E4=BB=A4=E9=9B=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/mir/MIR.h | 152 +++++++++++++++++++++++++++++++++++--- src/mir/Lowering.cpp | 1 + src/mir/MIRBasicBlock.cpp | 3 +- src/mir/MIRInstr.cpp | 14 ++-- src/mir/Register.cpp | 83 ++++++++++++++++++--- 5 files changed, 224 insertions(+), 29 deletions(-) diff --git a/include/mir/MIR.h b/include/mir/MIR.h index 47b8959..273836a 100644 --- a/include/mir/MIR.h +++ b/include/mir/MIR.h @@ -19,41 +19,144 @@ class MIRContext { MIRContext& DefaultContext(); -enum class PhysReg { W0, W8, W9, X29, X30, SP }; +enum class PhysReg { + //W0, W8, W9, X29, X30, SP + // 32位通用寄存器 + W0, W1, W2, W3, W4, W5, W6, W7, // 参数传递/临时 + W8, W9, // 临时寄存器(当前主要使用) + W10, W11, W12, W13, W14, W15, // 临时寄存器(扩展) + W16, W17, // intra-procedure-call 临时 + W18, // 平台预留 + W19, W20, W21, W22, W23, W24, // 被调用者保存(扩展用) + W25, W26, W27, W28, // 被调用者保存 + W29, // 帧指针 (FP) + W30, // 链接寄存器 (LR) + + // 64位版本 + X0, X1, X2, X3, X4, X5, X6, X7, + X8, X9, X10, X11, X12, X13, X14, X15, + X16, X17, X18, + X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, + X29, // FP + X30, // LR + + // 浮点寄存器 (32位) + S0, S1, S2, S3, S4, S5, S6, S7, + S8, S9, S10, S11, S12, S13, S14, S15, + S16, S17, S18, S19, S20, S21, S22, S23, + S24, S25, S26, S27, S28, S29, S30, S31, + + // 特殊寄存器 + SP, // 栈指针 + ZR, // 零寄存器 +}; const char* PhysRegName(PhysReg reg); +// ========== 条件码枚举(用于 BCond 指令)========== +enum class CondCode { + EQ, // 相等 (equal) + NE, // 不等 (not equal) + CS, // 进位设置 (carry set) / 无符号大于等于 + CC, // 进位清除 (carry clear) / 无符号小于 + MI, // 负数 (minus) + PL, // 非负数 (plus) + VS, // 溢出 (overflow set) + VC, // 无溢出 (overflow clear) + HI, // 无符号大于 (higher) + LS, // 无符号小于等于 (lower or same) + GE, // 有符号大于等于 (greater or equal) + LT, // 有符号小于 (less than) + GT, // 有符号大于 (greater than) + LE, // 有符号小于等于 (less or equal) + AL, // 总是 (always) +}; + +const char* CondCodeName(CondCode cc); + +// ========== MIR 指令操作码枚举 ========== enum class Opcode { - Prologue, - Epilogue, - MovImm, - LoadStack, - StoreStack, - AddRR, - Ret, + // ---------- 栈帧相关 ---------- + Prologue, // 函数序言(伪指令) + Epilogue, // 函数尾声(伪指令) + + // ---------- 数据传输 ---------- + MovImm, // 立即数移动到寄存器: MOV w8, #imm + MovReg, // 寄存器之间移动: MOV w8, w9 + LoadStack, // 从栈槽加载: LDR w8, [sp, #offset] + StoreStack, // 存储到栈槽: STR w8, [sp, #offset] + LoadStackPair,// 成对加载: LDP x29, x30, [sp], #16 + StoreStackPair,// 成对存储: STP x29, x30, [sp, #-16]! + + // ---------- 整数算术运算 ---------- + AddRR, // 加法: ADD w8, w8, w9 + AddRI, // 加法(立即数): ADD w8, w8, #imm + SubRR, // 减法: SUB w8, w8, w9 + SubRI, // 减法(立即数): SUB w8, w8, #imm + MulRR, // 乘法: MUL w8, w8, w9 + SDivRR, // 有符号除法: SDIV w8, w8, w9 + UDivRR, // 无符号除法: UDIV w8, w8, w9 + + // ---------- 浮点算术运算 ---------- + FAddRR, // 浮点加法: FADD s0, s0, s1 + FSubRR, // 浮点减法: FSUB s0, s0, s1 + FMulRR, // 浮点乘法: FMUL s0, s0, s1 + FDivRR, // 浮点除法: FDIV s0, s0, s1 + + // ---------- 比较运算 ---------- + CmpRR, // 比较(寄存器): CMP w8, w9 + CmpRI, // 比较(立即数): CMP w8, #imm + FCmpRR, // 浮点比较: FCMP s0, s1 + + // ---------- 类型转换 ---------- + SIToFP, // 有符号整数转浮点: SCVTF s0, w0 + FPToSI, // 浮点转有符号整数: FCVTZS w0, s0 + ZExt, // 零扩展(i1 -> i32): AND w8, w8, #1 + + // ---------- 控制流 ---------- + B, // 无条件跳转: B label + BCond, // 条件跳转: B.EQ label, B.NE label, B.GT label 等 + Call, // 函数调用: BL target + Ret, // 函数返回: RET + + // ---------- 逻辑运算 ---------- + AndRR, // 按位与: AND w8, w8, w9 + OrRR, // 按位或: ORR w8, w8, w9 + EorRR, // 按位异或: EOR w8, w8, w9 + LslRR, // 逻辑左移: LSL w8, w8, w9 + LsrRR, // 逻辑右移: LSR w8, w8, w9 + AsrRR, // 算术右移: ASR w8, w8, w9 + + // ---------- 特殊 ---------- + Nop, // 空操作: NOP }; +// ========== 操作数类 ========== class Operand { public: - enum class Kind { Reg, Imm, FrameIndex }; + enum class Kind { Reg, Imm, FrameIndex, Cond }; static Operand Reg(PhysReg reg); static Operand Imm(int value); static Operand FrameIndex(int index); + static Operand Cond(CondCode cc); Kind GetKind() const { return kind_; } PhysReg GetReg() const { return reg_; } int GetImm() const { return imm_; } int GetFrameIndex() const { return imm_; } + CondCode GetCondCode() const { return cc_; } private: - Operand(Kind kind, PhysReg reg, int imm); + Operand(Kind kind, PhysReg reg, int imm, CondCode cc); Kind kind_; PhysReg reg_; int imm_; + CondCode cc_; }; +// ========== MIR 指令类 ========== class MachineInstr { public: MachineInstr(Opcode opcode, std::vector operands = {}); @@ -66,12 +169,14 @@ class MachineInstr { std::vector operands_; }; +// ========== 栈槽结构 ========== struct FrameSlot { int index = 0; int size = 4; int offset = 0; }; +// ========== MIR 基本块 ========== class MachineBasicBlock { public: explicit MachineBasicBlock(std::string name); @@ -82,35 +187,60 @@ class MachineBasicBlock { MachineInstr& Append(Opcode opcode, std::initializer_list operands = {}); + MachineInstr& Append(Opcode opcode, std::vector operands); + + // 控制流信息 + std::vector& GetSuccessors() { return successors_; } + const std::vector& GetSuccessors() const { return successors_; } + void AddSuccessor(MachineBasicBlock* succ) { successors_.push_back(succ); } private: std::string name_; std::vector instructions_; + std::vector successors_; }; +// ========== MIR 函数 ========== class MachineFunction { public: explicit MachineFunction(std::string name); const std::string& GetName() const { return name_; } + + // 基本块管理 MachineBasicBlock& GetEntry() { return entry_; } const MachineBasicBlock& GetEntry() const { return entry_; } + std::vector>& GetBasicBlocks() { + return basic_blocks_; + } + const std::vector>& GetBasicBlocks() const { + return basic_blocks_; + } + + void AddBasicBlock(std::unique_ptr bb) { + basic_blocks_.push_back(std::move(bb)); + } + + // 栈槽管理 int CreateFrameIndex(int size = 4); FrameSlot& GetFrameSlot(int index); const FrameSlot& GetFrameSlot(int index) const; const std::vector& GetFrameSlots() const { return frame_slots_; } - + + // 栈帧大小 int GetFrameSize() const { return frame_size_; } void SetFrameSize(int size) { frame_size_ = size; } private: std::string name_; MachineBasicBlock entry_; + std::vector> basic_blocks_; std::vector frame_slots_; int frame_size_ = 0; }; +// ========== 后端流程函数 ========== std::unique_ptr LowerToMIR(const ir::Module& module); void RunRegAlloc(MachineFunction& function); void RunFrameLowering(MachineFunction& function); diff --git a/src/mir/Lowering.cpp b/src/mir/Lowering.cpp index 9a18396..5adca7f 100644 --- a/src/mir/Lowering.cpp +++ b/src/mir/Lowering.cpp @@ -6,6 +6,7 @@ #include "ir/IR.h" #include "utils/Log.h" + namespace mir { namespace { diff --git a/src/mir/MIRBasicBlock.cpp b/src/mir/MIRBasicBlock.cpp index d42b4b3..ab0dd57 100644 --- a/src/mir/MIRBasicBlock.cpp +++ b/src/mir/MIRBasicBlock.cpp @@ -9,7 +9,8 @@ MachineBasicBlock::MachineBasicBlock(std::string name) MachineInstr& MachineBasicBlock::Append(Opcode opcode, std::initializer_list operands) { - instructions_.emplace_back(opcode, std::vector(operands)); + //instructions_.emplace_back(opcode, std::vector(operands)); + instructions_.emplace_back(opcode, std::move(operands)); return instructions_.back(); } diff --git a/src/mir/MIRInstr.cpp b/src/mir/MIRInstr.cpp index 0a21a03..34da3d3 100644 --- a/src/mir/MIRInstr.cpp +++ b/src/mir/MIRInstr.cpp @@ -4,17 +4,21 @@ namespace mir { -Operand::Operand(Kind kind, PhysReg reg, int imm) - : kind_(kind), reg_(reg), imm_(imm) {} +Operand::Operand(Kind kind, PhysReg reg, int imm, CondCode cc) + : kind_(kind), reg_(reg), imm_(imm), cc_(cc) {} -Operand Operand::Reg(PhysReg reg) { return Operand(Kind::Reg, reg, 0); } +Operand Operand::Reg(PhysReg reg) { return Operand(Kind::Reg, reg, 0, CondCode::EQ); } Operand Operand::Imm(int value) { - return Operand(Kind::Imm, PhysReg::W0, value); + return Operand(Kind::Imm, PhysReg::W0, value, CondCode::EQ); } Operand Operand::FrameIndex(int index) { - return Operand(Kind::FrameIndex, PhysReg::W0, index); + return Operand(Kind::FrameIndex, PhysReg::W0, index, CondCode::EQ); +} + +Operand Operand::Cond(CondCode cc) { + return Operand(Kind::Cond, PhysReg::W0, 0, cc); } MachineInstr::MachineInstr(Opcode opcode, std::vector operands) diff --git a/src/mir/Register.cpp b/src/mir/Register.cpp index 7530470..5bf605f 100644 --- a/src/mir/Register.cpp +++ b/src/mir/Register.cpp @@ -8,20 +8,79 @@ namespace mir { const char* PhysRegName(PhysReg reg) { switch (reg) { - case PhysReg::W0: - return "w0"; - case PhysReg::W8: - return "w8"; - case PhysReg::W9: - return "w9"; - case PhysReg::X29: - return "x29"; - case PhysReg::X30: - return "x30"; - case PhysReg::SP: - return "sp"; + // 32位寄存器 + case PhysReg::W0: return "w0"; + case PhysReg::W1: return "w1"; + case PhysReg::W2: return "w2"; + case PhysReg::W3: return "w3"; + case PhysReg::W4: return "w4"; + case PhysReg::W5: return "w5"; + case PhysReg::W6: return "w6"; + case PhysReg::W7: return "w7"; + case PhysReg::W8: return "w8"; + case PhysReg::W9: return "w9"; + case PhysReg::W10: return "w10"; + case PhysReg::W11: return "w11"; + case PhysReg::W12: return "w12"; + case PhysReg::W13: return "w13"; + case PhysReg::W14: return "w14"; + case PhysReg::W15: return "w15"; + case PhysReg::W29: return "w29"; + case PhysReg::W30: return "w30"; + + // 64位寄存器 + case PhysReg::X0: return "x0"; + case PhysReg::X1: return "x1"; + case PhysReg::X2: return "x2"; + case PhysReg::X3: return "x3"; + case PhysReg::X4: return "x4"; + case PhysReg::X5: return "x5"; + case PhysReg::X6: return "x6"; + case PhysReg::X7: return "x7"; + case PhysReg::X8: return "x8"; + case PhysReg::X9: return "x9"; + case PhysReg::X29: return "x29"; + case PhysReg::X30: return "x30"; + + // 浮点寄存器 + case PhysReg::S0: return "s0"; + case PhysReg::S1: return "s1"; + case PhysReg::S2: return "s2"; + case PhysReg::S3: return "s3"; + case PhysReg::S4: return "s4"; + case PhysReg::S5: return "s5"; + case PhysReg::S6: return "s6"; + case PhysReg::S7: return "s7"; + + // 特殊寄存器 + case PhysReg::SP: return "sp"; + case PhysReg::ZR: return "xzr"; + + default: return "unknown"; } throw std::runtime_error(FormatError("mir", "未知物理寄存器")); } +const char* CondCodeName(CondCode cc) { + switch (cc) { + case CondCode::EQ: return "eq"; + case CondCode::NE: return "ne"; + case CondCode::CS: return "cs"; + case CondCode::CC: return "cc"; + case CondCode::MI: return "mi"; + case CondCode::PL: return "pl"; + case CondCode::VS: return "vs"; + case CondCode::VC: return "vc"; + case CondCode::HI: return "hi"; + case CondCode::LS: return "ls"; + case CondCode::GE: return "ge"; + case CondCode::LT: return "lt"; + case CondCode::GT: return "gt"; + case CondCode::LE: return "le"; + case CondCode::AL: return "al"; + default: return "unknown"; + } + throw std::runtime_error(FormatError("mir", "未知条件码")); +} + } // namespace mir -- 2.34.1 From f966869fb196b0428e0a0765e67545ce1e4da1ba Mon Sep 17 00:00:00 2001 From: mxr <> Date: Wed, 8 Apr 2026 22:38:36 +0800 Subject: [PATCH 02/30] =?UTF-8?q?feat(mir)=E6=89=A9=E5=B1=95=E6=B1=87?= =?UTF-8?q?=E7=BC=96=E6=8C=87=E4=BB=A4=E7=94=9F=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/mir/AsmPrinter.cpp | 133 +++++++++++++++++++++++++++++++++++++++++ src/mir/RegAlloc.cpp | 4 +- 2 files changed, 135 insertions(+), 2 deletions(-) diff --git a/src/mir/AsmPrinter.cpp b/src/mir/AsmPrinter.cpp index 4d1f65f..089e055 100644 --- a/src/mir/AsmPrinter.cpp +++ b/src/mir/AsmPrinter.cpp @@ -22,6 +22,12 @@ void PrintStackAccess(std::ostream& os, const char* mnemonic, PhysReg reg, << "]\n"; } +void PrintStackPairAccess(std::ostream& os, const char* mnemonic, PhysReg reg0, PhysReg reg1, + int offset) { + os << " " << mnemonic << " " << PhysRegName(reg0) << " " << PhysRegName(reg1) << ", [x29, #" << offset + << "]\n"; +} + } // namespace void PrintAsm(const MachineFunction& function, std::ostream& os) { @@ -50,6 +56,10 @@ void PrintAsm(const MachineFunction& function, std::ostream& os) { os << " mov " << PhysRegName(ops.at(0).GetReg()) << ", #" << ops.at(1).GetImm() << "\n"; break; + case Opcode::MovReg: + os << " mov " << PhysRegName(ops.at(0).GetReg()) + << PhysRegName(ops.at(1).GetReg()) << "\n"; + break; case Opcode::LoadStack: { const auto& slot = GetFrameSlot(function, ops.at(1)); PrintStackAccess(os, "ldur", ops.at(0).GetReg(), slot.offset); @@ -60,14 +70,137 @@ void PrintAsm(const MachineFunction& function, std::ostream& os) { PrintStackAccess(os, "stur", ops.at(0).GetReg(), slot.offset); break; } + case Opcode::LoadStackPair: { + PrintStackPairAccess(os, "ldp", ops.at(0).GetReg(), ops.at(1).GetReg(), 16); + break; + } + case Opcode::StoreStackPair: { + PrintStackPairAccess(os, "stp", ops.at(0).GetReg(), ops.at(1).GetReg(), -16); + break; + } case Opcode::AddRR: os << " add " << PhysRegName(ops.at(0).GetReg()) << ", " << PhysRegName(ops.at(1).GetReg()) << ", " << PhysRegName(ops.at(2).GetReg()) << "\n"; break; + case Opcode::AddRI: + os << " add " << PhysRegName(ops.at(0).GetReg()) << ", " + << PhysRegName(ops.at(1).GetReg()) << ", #" + << ops.at(2).GetImm() << "\n"; + break; + case Opcode::SubRR: + os << " sub " << PhysRegName(ops.at(0).GetReg()) << ", " + << PhysRegName(ops.at(1).GetReg()) << ", " + << PhysRegName(ops.at(2).GetReg()) << "\n"; + break; + case Opcode::SubRI: + os << " sub " << PhysRegName(ops.at(0).GetReg()) << ", " + << PhysRegName(ops.at(1).GetReg()) << ", #" + << ops.at(2).GetImm() << "\n"; + break; + case Opcode::MulRR: + os << " mul " << PhysRegName(ops.at(0).GetReg()) << ", " + << PhysRegName(ops.at(1).GetReg()) << ", " + << PhysRegName(ops.at(2).GetReg()) << "\n"; + break; + case Opcode::SDivRR: + os << " sdiv " << PhysRegName(ops.at(0).GetReg()) << ", " + << PhysRegName(ops.at(1).GetReg()) << ", " + << PhysRegName(ops.at(2).GetReg()) << "\n"; + break; + case Opcode::UDivRR: + os << " udiv " << PhysRegName(ops.at(0).GetReg()) << ", " + << PhysRegName(ops.at(1).GetReg()) << ", " + << PhysRegName(ops.at(2).GetReg()) << "\n"; + break; + case Opcode::FAddRR: + os << " fadd " << PhysRegName(ops.at(0).GetReg()) << ", " + << PhysRegName(ops.at(1).GetReg()) << ", " + << PhysRegName(ops.at(2).GetReg()) << "\n"; + break; + case Opcode::FSubRR: + os << " fsub " << PhysRegName(ops.at(0).GetReg()) << ", " + << PhysRegName(ops.at(1).GetReg()) << ", " + << PhysRegName(ops.at(2).GetReg()) << "\n"; + break; + case Opcode::FMulRR: + os << " fmul " << PhysRegName(ops.at(0).GetReg()) << ", " + << PhysRegName(ops.at(1).GetReg()) << ", " + << PhysRegName(ops.at(2).GetReg()) << "\n"; + break; + case Opcode::FDivRR: + os << " fdiv " << PhysRegName(ops.at(0).GetReg()) << ", " + << PhysRegName(ops.at(1).GetReg()) << ", " + << PhysRegName(ops.at(2).GetReg()) << "\n"; + break; + case Opcode::CmpRR: + os << " cmp " << PhysRegName(ops.at(0).GetReg()) << ", " + << PhysRegName(ops.at(1).GetReg()) << "\n"; + break; + case Opcode::CmpRI: + os << " cmp " << PhysRegName(ops.at(0).GetReg()) << ", #" + << ops.at(1).GetImm() << "\n"; + break; + case Opcode::FCmpRR: + os << " fcmp " << PhysRegName(ops.at(0).GetReg()) << ", " + << PhysRegName(ops.at(1).GetReg()) << "\n"; + break; + case Opcode::SIToFP: + os << " scvtf " << PhysRegName(ops.at(0).GetReg()) << ", " + << PhysRegName(ops.at(1).GetReg()) << "\n"; + break; + case Opcode::FPToSI: + os << " fcvtzs " << PhysRegName(ops.at(0).GetReg()) << ", " + << PhysRegName(ops.at(1).GetReg()) << "\n"; + break; + case Opcode::ZExt: + os << " and " << PhysRegName(ops.at(0).GetReg()) << ", " + << PhysRegName(ops.at(1).GetReg()) << ", #1\n"; + break; + case Opcode::AndRR: + os << " and " << PhysRegName(ops.at(0).GetReg()) << ", " + << PhysRegName(ops.at(1).GetReg()) << ", " + << PhysRegName(ops.at(2).GetReg()) << "\n"; + break; + case Opcode::OrRR: + os << " orr " << PhysRegName(ops.at(0).GetReg()) << ", " + << PhysRegName(ops.at(1).GetReg()) << ", " + << PhysRegName(ops.at(2).GetReg()) << "\n"; + break; + case Opcode::EorRR: + os << " eor " << PhysRegName(ops.at(0).GetReg()) << ", " + << PhysRegName(ops.at(1).GetReg()) << ", " + << PhysRegName(ops.at(2).GetReg()) << "\n"; + break; + case Opcode::LslRR: + os << " lsl " << PhysRegName(ops.at(0).GetReg()) << ", " + << PhysRegName(ops.at(1).GetReg()) << ", " + << PhysRegName(ops.at(2).GetReg()) << "\n"; + break; + case Opcode::LsrRR: + os << " lsr " << PhysRegName(ops.at(0).GetReg()) << ", " + << PhysRegName(ops.at(1).GetReg()) << ", " + << PhysRegName(ops.at(2).GetReg()) << "\n"; + break; + case Opcode::AsrRR: + os << " asr " << PhysRegName(ops.at(0).GetReg()) << ", " + << PhysRegName(ops.at(1).GetReg()) << ", " + << PhysRegName(ops.at(2).GetReg()) << "\n"; + break; + case Opcode::Nop: + os << " nop \n"; + break; + // TODO: 控制流 + case Opcode::B: + break; + case Opcode::BCond: + break; + case Opcode::Call: + break; case Opcode::Ret: os << " ret\n"; break; + } } diff --git a/src/mir/RegAlloc.cpp b/src/mir/RegAlloc.cpp index 5dc5d2b..972eac5 100644 --- a/src/mir/RegAlloc.cpp +++ b/src/mir/RegAlloc.cpp @@ -12,8 +12,8 @@ bool IsAllowedReg(PhysReg reg) { case PhysReg::W0: case PhysReg::W8: case PhysReg::W9: - case PhysReg::X29: - case PhysReg::X30: + case PhysReg::X29: //FP = X29 帧指针 + case PhysReg::X30: //LR = X30 链接寄存器 case PhysReg::SP: return true; } -- 2.34.1 From 6e804e209170a0273b7857197405c2bf52eb990c Mon Sep 17 00:00:00 2001 From: mxr <> Date: Wed, 8 Apr 2026 23:03:44 +0800 Subject: [PATCH 03/30] =?UTF-8?q?test(test)=E6=9B=B4=E6=96=B0=E6=B5=8B?= =?UTF-8?q?=E8=AF=95=E8=84=9A=E6=9C=AC=E5=B9=B6=E7=BB=9F=E4=B8=80=E8=BE=93?= =?UTF-8?q?=E5=87=BA=E7=9B=AE=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/test_compiler.sh | 2 +- scripts/test_mir.sh | 167 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 168 insertions(+), 1 deletion(-) create mode 100755 scripts/test_mir.sh diff --git a/scripts/test_compiler.sh b/scripts/test_compiler.sh index ac98f68..ba6363f 100755 --- a/scripts/test_compiler.sh +++ b/scripts/test_compiler.sh @@ -69,7 +69,7 @@ for test_dir in "${TEST_DIRS[@]}"; do stem=${base%.sy} case "$(basename "$test_dir")" in functional) - out_dir="$RESULT_BASE_DIR/function/ir" + out_dir="$RESULT_BASE_DIR/functional/ir" ;; performance) out_dir="$RESULT_BASE_DIR/performance/ir" diff --git a/scripts/test_mir.sh b/scripts/test_mir.sh new file mode 100755 index 0000000..821cb01 --- /dev/null +++ b/scripts/test_mir.sh @@ -0,0 +1,167 @@ +#!/bin/bash + +# 测试脚本(支持动态输出目录) +# 用法: ./run_tests.sh [--verbose] [--mode <模式>] [<单个测试文件>] +# 模式: parse-tree, ir, asm, run (默认 run) + +COMPILER="./build/bin/compiler" +TEST_SCRIPT="./scripts/verify_asm.sh" +TEST_DIR="test/test_case" +RESULT_FILE="result.txt" +VERBOSE=0 +MODE="run" # 默认模式为完整测试 + +# 解析参数 +while [[ $# -gt 0 ]]; do + case "$1" in + --verbose|-v) + VERBOSE=1 + shift + ;; + --mode) + MODE="$2" + shift 2 + ;; + --emit-parse-tree) + MODE="parse-tree" + shift + ;; + --emit-ir) + MODE="ir" + shift + ;; + --emit-asm) + MODE="asm" + shift + ;; + --run) + MODE="run" + shift + ;; + -*) + echo "未知选项: $1" + exit 1 + ;; + *) + # 非选项参数视为测试文件 + SINGLE_FILE="$1" + shift + ;; + esac +done + +# 检查编译器是否存在 +if [ ! -f "$COMPILER" ]; then + echo "错误: 编译器未找到于 $COMPILER" + echo "请先完成项目构建 (cmake 和 make)" + exit 1 +fi + +# 如果是 run 模式,检查测试脚本是否存在 +if [ "$MODE" = "run" ] && [ ! -f "$TEST_SCRIPT" ]; then + echo "错误: 测试脚本未找到于 $TEST_SCRIPT" + exit 1 +fi + +# 如果指定了单个文件,检查文件是否存在 +if [ -n "$SINGLE_FILE" ] && [ ! -f "$SINGLE_FILE" ]; then + echo "错误: 文件 $SINGLE_FILE 不存在" + exit 1 +fi + +# 清空(或创建)结果文件 +> "$RESULT_FILE" + +# 计数器 +total=0 +passed=0 +failed=0 + +echo "开始测试 (模式: $MODE)..." +echo "输出将保存到 $RESULT_FILE" +echo "------------------------" + +# 确定测试文件列表 +if [ -n "$SINGLE_FILE" ]; then + TEST_FILES=("$SINGLE_FILE") +else + mapfile -t TEST_FILES < <(find "$TEST_DIR" -type f -name "*.sy" | sort) +fi + +# 根据模式执行测试 +for file in "${TEST_FILES[@]}"; do + ((total++)) + if [ $VERBOSE -eq 1 ]; then + echo "测试文件: $file" + else + echo -n "测试 $file ... " + fi + + echo "========== $file ==========" >> "$RESULT_FILE" + + # 根据模式构建命令 + case "$MODE" in + parse-tree) + cmd="$COMPILER --emit-parse-tree \"$file\"" + ;; + ir) + cmd="$COMPILER --emit-ir \"$file\"" + ;; + asm) + cmd="$COMPILER --emit-asm \"$file\"" + ;; + run) + # 根据输入文件所在子目录确定输出目录 + # 提取 test/test_case/ 之后的子目录名(functional 或 performance) + rel_path="${file#$TEST_DIR/}" + subdir=$(echo "$rel_path" | cut -d'/' -f1) + if [[ "$subdir" != "functional" && "$subdir" != "performance" ]]; then + echo "警告: 未知子目录 $subdir,使用默认输出目录" >> "$RESULT_FILE" + out_dir="test/test_result/asm" + else + out_dir="test/test_result/$subdir/asm" + fi + cmd="$TEST_SCRIPT \"$file\" \"$out_dir\" --run" + ;; + *) + echo "未知模式: $MODE" >&2 + exit 1 + ;; + esac + + if [ $VERBOSE -eq 1 ]; then + eval "$cmd" 2>&1 | tee -a "$RESULT_FILE" + result=${PIPESTATUS[0]} + else + eval "$cmd" >> "$RESULT_FILE" 2>&1 + result=$? + fi + + echo "" >> "$RESULT_FILE" + + if [ $result -eq 0 ]; then + if [ $VERBOSE -eq 0 ]; then + echo "通过" + fi + ((passed++)) + else + if [ $VERBOSE -eq 0 ]; then + echo "失败" + else + echo ">>> 测试失败: $file" + fi + ((failed++)) + fi +done + +echo "------------------------" +echo "总计: $total" +echo "通过: $passed" +echo "失败: $failed" +echo "详细输出已保存至 $RESULT_FILE" + +if [ $failed -gt 0 ]; then + exit 1 +else + exit 0 +fi \ No newline at end of file -- 2.34.1 From 653c0919936d329bb6c42739efb42b2435f26da4 Mon Sep 17 00:00:00 2001 From: ftt <> Date: Thu, 9 Apr 2026 13:09:50 +0800 Subject: [PATCH 04/30] =?UTF-8?q?=E5=AE=8C=E6=88=90=E4=BA=8C=E4=B8=89?= =?UTF-8?q?=E5=9B=9B=E9=98=B6=E6=AE=B5=EF=BC=8C=E8=A7=A3=E5=86=B3=E6=94=AF?= =?UTF-8?q?=E6=8C=81=E5=A4=9A=E5=87=BD=E6=95=B0=E9=97=AE=E9=A2=98=E7=AD=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/mir/MIR.h | 58 +++- src/main.cpp | 12 +- src/mir/AsmPrinter.cpp | 436 ++++++++++++++---------- src/mir/FrameLowering.cpp | 107 +++++- src/mir/Lowering.cpp | 680 +++++++++++++++++++++++++++++++++++--- src/mir/MIRInstr.cpp | 16 +- src/mir/RegAlloc.cpp | 56 +++- 7 files changed, 1136 insertions(+), 229 deletions(-) diff --git a/include/mir/MIR.h b/include/mir/MIR.h index 273836a..f44df47 100644 --- a/include/mir/MIR.h +++ b/include/mir/MIR.h @@ -134,26 +134,29 @@ enum class Opcode { // ========== 操作数类 ========== class Operand { public: - enum class Kind { Reg, Imm, FrameIndex, Cond }; + enum class Kind { Reg, Imm, FrameIndex, Cond, Label }; static Operand Reg(PhysReg reg); static Operand Imm(int value); static Operand FrameIndex(int index); static Operand Cond(CondCode cc); + static Operand Label(const std::string& label); Kind GetKind() const { return kind_; } PhysReg GetReg() const { return reg_; } int GetImm() const { return imm_; } int GetFrameIndex() const { return imm_; } CondCode GetCondCode() const { return cc_; } + const std::string& GetLabel() const { return label_; } private: - Operand(Kind kind, PhysReg reg, int imm, CondCode cc); + Operand(Kind kind, PhysReg reg, int imm, CondCode cc, const std::string& label); Kind kind_; PhysReg reg_; int imm_; CondCode cc_; + std::string label_; }; // ========== MIR 指令类 ========== @@ -226,6 +229,7 @@ class MachineFunction { int CreateFrameIndex(int size = 4); FrameSlot& GetFrameSlot(int index); const FrameSlot& GetFrameSlot(int index) const; + std::vector& GetFrameSlots() { return frame_slots_; } const std::vector& GetFrameSlots() const { return frame_slots_; } // 栈帧大小 @@ -240,10 +244,56 @@ class MachineFunction { int frame_size_ = 0; }; +// ========== MIR 模块 ========== +class MachineModule { + public: + MachineModule() = default; + + // 添加 MachineFunction + void AddFunction(std::unique_ptr func) { + functions_.push_back(std::move(func)); + } + + // 获取所有函数 + const std::vector>& GetFunctions() const { + return functions_; + } + + std::vector>& GetFunctions() { + return functions_; + } + + // 根据名称查找函数 + MachineFunction* GetFunction(const std::string& name) { + for (auto& func : functions_) { + if (func->GetName() == name) { + return func.get(); + } + } + return nullptr; + } + + const MachineFunction* GetFunction(const std::string& name) const { + for (const auto& func : functions_) { + if (func->GetName() == name) { + return func.get(); + } + } + return nullptr; + } + + private: + std::vector> functions_; +}; + // ========== 后端流程函数 ========== -std::unique_ptr LowerToMIR(const ir::Module& module); +/* std::unique_ptr LowerToMIR(const ir::Module& module); void RunRegAlloc(MachineFunction& function); void RunFrameLowering(MachineFunction& function); -void PrintAsm(const MachineFunction& function, std::ostream& os); +void PrintAsm(const MachineFunction& function, std::ostream& os); */ +std::unique_ptr LowerToMIR(const ir::Module& module); +void RunRegAlloc(MachineModule& module); +void RunFrameLowering(MachineModule& module); +void PrintAsm(const MachineModule& module, std::ostream& os); } // namespace mir diff --git a/src/main.cpp b/src/main.cpp index 88ed747..c54f087 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -46,13 +46,17 @@ int main(int argc, char** argv) { } if (opts.emit_asm) { - auto machine_func = mir::LowerToMIR(*module); - mir::RunRegAlloc(*machine_func); - mir::RunFrameLowering(*machine_func); + //auto machine_func = mir::LowerToMIR(*module); + auto machine_module = mir::LowerToMIR(*module); + //mir::RunRegAlloc(*machine_func); + mir::RunRegAlloc(*machine_module); + //mir::RunFrameLowering(*machine_func); + mir::RunFrameLowering(*machine_module); if (need_blank_line) { std::cout << "\n"; } - mir::PrintAsm(*machine_func, std::cout); + //mir::PrintAsm(*machine_func, std::cout); + mir::PrintAsm(*machine_module, std::cout); } #else if (opts.emit_ir || opts.emit_asm) { diff --git a/src/mir/AsmPrinter.cpp b/src/mir/AsmPrinter.cpp index 089e055..0be85f8 100644 --- a/src/mir/AsmPrinter.cpp +++ b/src/mir/AsmPrinter.cpp @@ -24,188 +24,284 @@ void PrintStackAccess(std::ostream& os, const char* mnemonic, PhysReg reg, void PrintStackPairAccess(std::ostream& os, const char* mnemonic, PhysReg reg0, PhysReg reg1, int offset) { - os << " " << mnemonic << " " << PhysRegName(reg0) << " " << PhysRegName(reg1) << ", [x29, #" << offset + os << " " << mnemonic << " " << PhysRegName(reg0) << ", " << PhysRegName(reg1) << ", [x29, #" << offset << "]\n"; } -} // namespace +// 打印单个操作数 +void PrintOperand(std::ostream& os, const Operand& op) { + switch (op.GetKind()) { + case Operand::Kind::Reg: + os << PhysRegName(op.GetReg()); + break; + case Operand::Kind::Imm: + os << "#" << op.GetImm(); + break; + case Operand::Kind::FrameIndex: + os << "[sp, #" << op.GetFrameIndex() << "]"; + break; + case Operand::Kind::Cond: + os << CondCodeName(op.GetCondCode()); + break; + case Operand::Kind::Label: + os << op.GetLabel(); + break; + } +} + +// 打印单条指令 +void PrintInstruction(std::ostream& os, const MachineInstr& instr, + const MachineFunction& function) { + const auto& ops = instr.GetOperands(); + + switch (instr.GetOpcode()) { + case Opcode::Prologue: + // Prologue 在 RunFrameLowering 中已经生成具体指令,这里不需要输出 + break; + case Opcode::Epilogue: + // Epilogue 在 RunFrameLowering 中已经生成具体指令,这里不需要输出 + break; + case Opcode::MovImm: + os << " mov " << PhysRegName(ops.at(0).GetReg()) << ", #" + << ops.at(1).GetImm() << "\n"; + break; + case Opcode::MovReg: + os << " mov " << PhysRegName(ops.at(0).GetReg()) << ", " + << PhysRegName(ops.at(1).GetReg()) << "\n"; + break; + case Opcode::LoadStack: { + const auto& slot = GetFrameSlot(function, ops.at(1)); + PrintStackAccess(os, "ldur", ops.at(0).GetReg(), slot.offset); + break; + } + case Opcode::StoreStack: { + const auto& slot = GetFrameSlot(function, ops.at(1)); + PrintStackAccess(os, "stur", ops.at(0).GetReg(), slot.offset); + break; + } + case Opcode::StoreStackPair: + // stp x29, x30, [sp, #-16]! + os << " stp " << PhysRegName(ops.at(0).GetReg()) << ", " + << PhysRegName(ops.at(1).GetReg()) << ", [sp"; + if (ops.size() > 2 && ops.at(2).GetKind() == Operand::Kind::Imm) { + int offset = ops.at(2).GetImm(); + os << ", #" << offset; + } + os << "]!\n"; // 注意添加 ! 表示 pre-index + break; + case Opcode::LoadStackPair: + // ldp x29, x30, [sp], #16 + os << " ldp " << PhysRegName(ops.at(0).GetReg()) << ", " + << PhysRegName(ops.at(1).GetReg()) << ", [sp]"; + if (ops.size() > 2 && ops.at(2).GetKind() == Operand::Kind::Imm) { + int offset = ops.at(2).GetImm(); + os << ", #" << offset; + } + os << "\n"; + break; + case Opcode::AddRR: + os << " add " << PhysRegName(ops.at(0).GetReg()) << ", " + << PhysRegName(ops.at(1).GetReg()) << ", " + << PhysRegName(ops.at(2).GetReg()) << "\n"; + break; + case Opcode::AddRI: + os << " add " << PhysRegName(ops.at(0).GetReg()) << ", " + << PhysRegName(ops.at(1).GetReg()) << ", #" + << ops.at(2).GetImm() << "\n"; + break; + case Opcode::SubRR: + os << " sub " << PhysRegName(ops.at(0).GetReg()) << ", " + << PhysRegName(ops.at(1).GetReg()) << ", " + << PhysRegName(ops.at(2).GetReg()) << "\n"; + break; + case Opcode::SubRI: + os << " sub " << PhysRegName(ops.at(0).GetReg()) << ", " + << PhysRegName(ops.at(1).GetReg()) << ", #" + << ops.at(2).GetImm() << "\n"; + break; + case Opcode::MulRR: + os << " mul " << PhysRegName(ops.at(0).GetReg()) << ", " + << PhysRegName(ops.at(1).GetReg()) << ", " + << PhysRegName(ops.at(2).GetReg()) << "\n"; + break; + case Opcode::SDivRR: + os << " sdiv " << PhysRegName(ops.at(0).GetReg()) << ", " + << PhysRegName(ops.at(1).GetReg()) << ", " + << PhysRegName(ops.at(2).GetReg()) << "\n"; + break; + case Opcode::UDivRR: + os << " udiv " << PhysRegName(ops.at(0).GetReg()) << ", " + << PhysRegName(ops.at(1).GetReg()) << ", " + << PhysRegName(ops.at(2).GetReg()) << "\n"; + break; + case Opcode::FAddRR: + os << " fadd " << PhysRegName(ops.at(0).GetReg()) << ", " + << PhysRegName(ops.at(1).GetReg()) << ", " + << PhysRegName(ops.at(2).GetReg()) << "\n"; + break; + case Opcode::FSubRR: + os << " fsub " << PhysRegName(ops.at(0).GetReg()) << ", " + << PhysRegName(ops.at(1).GetReg()) << ", " + << PhysRegName(ops.at(2).GetReg()) << "\n"; + break; + case Opcode::FMulRR: + os << " fmul " << PhysRegName(ops.at(0).GetReg()) << ", " + << PhysRegName(ops.at(1).GetReg()) << ", " + << PhysRegName(ops.at(2).GetReg()) << "\n"; + break; + case Opcode::FDivRR: + os << " fdiv " << PhysRegName(ops.at(0).GetReg()) << ", " + << PhysRegName(ops.at(1).GetReg()) << ", " + << PhysRegName(ops.at(2).GetReg()) << "\n"; + break; + case Opcode::CmpRR: + os << " cmp " << PhysRegName(ops.at(0).GetReg()) << ", " + << PhysRegName(ops.at(1).GetReg()) << "\n"; + break; + case Opcode::CmpRI: + os << " cmp " << PhysRegName(ops.at(0).GetReg()) << ", #" + << ops.at(1).GetImm() << "\n"; + break; + case Opcode::FCmpRR: + os << " fcmp " << PhysRegName(ops.at(0).GetReg()) << ", " + << PhysRegName(ops.at(1).GetReg()) << "\n"; + break; + case Opcode::SIToFP: + os << " scvtf " << PhysRegName(ops.at(0).GetReg()) << ", " + << PhysRegName(ops.at(1).GetReg()) << "\n"; + break; + case Opcode::FPToSI: + os << " fcvtzs " << PhysRegName(ops.at(0).GetReg()) << ", " + << PhysRegName(ops.at(1).GetReg()) << "\n"; + break; + case Opcode::ZExt: + os << " and " << PhysRegName(ops.at(0).GetReg()) << ", " + << PhysRegName(ops.at(1).GetReg()) << ", #1\n"; + break; + case Opcode::AndRR: + os << " and " << PhysRegName(ops.at(0).GetReg()) << ", " + << PhysRegName(ops.at(1).GetReg()) << ", " + << PhysRegName(ops.at(2).GetReg()) << "\n"; + break; + case Opcode::OrRR: + os << " orr " << PhysRegName(ops.at(0).GetReg()) << ", " + << PhysRegName(ops.at(1).GetReg()) << ", " + << PhysRegName(ops.at(2).GetReg()) << "\n"; + break; + case Opcode::EorRR: + os << " eor " << PhysRegName(ops.at(0).GetReg()) << ", " + << PhysRegName(ops.at(1).GetReg()) << ", " + << PhysRegName(ops.at(2).GetReg()) << "\n"; + break; + case Opcode::LslRR: + os << " lsl " << PhysRegName(ops.at(0).GetReg()) << ", " + << PhysRegName(ops.at(1).GetReg()) << ", " + << PhysRegName(ops.at(2).GetReg()) << "\n"; + break; + case Opcode::LsrRR: + os << " lsr " << PhysRegName(ops.at(0).GetReg()) << ", " + << PhysRegName(ops.at(1).GetReg()) << ", " + << PhysRegName(ops.at(2).GetReg()) << "\n"; + break; + case Opcode::AsrRR: + os << " asr " << PhysRegName(ops.at(0).GetReg()) << ", " + << PhysRegName(ops.at(1).GetReg()) << ", " + << PhysRegName(ops.at(2).GetReg()) << "\n"; + break; + case Opcode::B: + os << " b "; + PrintOperand(os, ops.at(0)); + os << "\n"; + break; + case Opcode::BCond: + os << " b."; + PrintOperand(os, ops.at(0)); + os << " "; + PrintOperand(os, ops.at(1)); + os << "\n"; + break; + case Opcode::Call: + os << " bl "; + PrintOperand(os, ops.at(0)); + os << "\n"; + break; + //case Opcode::Ret: + // os << " ret\n"; + // break; + case Opcode::Ret: { + // 输出函数尾声 + int frameSize = function.GetFrameSize(); + int alignedSize = (frameSize + 15) & ~15; + + if (alignedSize > 0) { + os << " add sp, sp, #" << alignedSize << "\n"; + } + os << " ldp x29, x30, [sp], #16\n"; + os << " ret\n"; + break; + } + case Opcode::Nop: + os << " nop\n"; + break; + default: + os << " // unknown instruction\n"; + break; + } +} +// 打印单个函数(单函数版本) void PrintAsm(const MachineFunction& function, std::ostream& os) { + // 输出函数标签 os << ".text\n"; os << ".global " << function.GetName() << "\n"; os << ".type " << function.GetName() << ", %function\n"; os << function.GetName() << ":\n"; - for (const auto& inst : function.GetEntry().GetInstructions()) { - const auto& ops = inst.GetOperands(); - switch (inst.GetOpcode()) { - case Opcode::Prologue: - os << " stp x29, x30, [sp, #-16]!\n"; - os << " mov x29, sp\n"; - if (function.GetFrameSize() > 0) { - os << " sub sp, sp, #" << function.GetFrameSize() << "\n"; - } - break; - case Opcode::Epilogue: - if (function.GetFrameSize() > 0) { - os << " add sp, sp, #" << function.GetFrameSize() << "\n"; - } - os << " ldp x29, x30, [sp], #16\n"; - break; - case Opcode::MovImm: - os << " mov " << PhysRegName(ops.at(0).GetReg()) << ", #" - << ops.at(1).GetImm() << "\n"; - break; - case Opcode::MovReg: - os << " mov " << PhysRegName(ops.at(0).GetReg()) - << PhysRegName(ops.at(1).GetReg()) << "\n"; - break; - case Opcode::LoadStack: { - const auto& slot = GetFrameSlot(function, ops.at(1)); - PrintStackAccess(os, "ldur", ops.at(0).GetReg(), slot.offset); - break; - } - case Opcode::StoreStack: { - const auto& slot = GetFrameSlot(function, ops.at(1)); - PrintStackAccess(os, "stur", ops.at(0).GetReg(), slot.offset); - break; - } - case Opcode::LoadStackPair: { - PrintStackPairAccess(os, "ldp", ops.at(0).GetReg(), ops.at(1).GetReg(), 16); - break; - } - case Opcode::StoreStackPair: { - PrintStackPairAccess(os, "stp", ops.at(0).GetReg(), ops.at(1).GetReg(), -16); - break; - } - case Opcode::AddRR: - os << " add " << PhysRegName(ops.at(0).GetReg()) << ", " - << PhysRegName(ops.at(1).GetReg()) << ", " - << PhysRegName(ops.at(2).GetReg()) << "\n"; - break; - case Opcode::AddRI: - os << " add " << PhysRegName(ops.at(0).GetReg()) << ", " - << PhysRegName(ops.at(1).GetReg()) << ", #" - << ops.at(2).GetImm() << "\n"; - break; - case Opcode::SubRR: - os << " sub " << PhysRegName(ops.at(0).GetReg()) << ", " - << PhysRegName(ops.at(1).GetReg()) << ", " - << PhysRegName(ops.at(2).GetReg()) << "\n"; - break; - case Opcode::SubRI: - os << " sub " << PhysRegName(ops.at(0).GetReg()) << ", " - << PhysRegName(ops.at(1).GetReg()) << ", #" - << ops.at(2).GetImm() << "\n"; - break; - case Opcode::MulRR: - os << " mul " << PhysRegName(ops.at(0).GetReg()) << ", " - << PhysRegName(ops.at(1).GetReg()) << ", " - << PhysRegName(ops.at(2).GetReg()) << "\n"; - break; - case Opcode::SDivRR: - os << " sdiv " << PhysRegName(ops.at(0).GetReg()) << ", " - << PhysRegName(ops.at(1).GetReg()) << ", " - << PhysRegName(ops.at(2).GetReg()) << "\n"; - break; - case Opcode::UDivRR: - os << " udiv " << PhysRegName(ops.at(0).GetReg()) << ", " - << PhysRegName(ops.at(1).GetReg()) << ", " - << PhysRegName(ops.at(2).GetReg()) << "\n"; - break; - case Opcode::FAddRR: - os << " fadd " << PhysRegName(ops.at(0).GetReg()) << ", " - << PhysRegName(ops.at(1).GetReg()) << ", " - << PhysRegName(ops.at(2).GetReg()) << "\n"; - break; - case Opcode::FSubRR: - os << " fsub " << PhysRegName(ops.at(0).GetReg()) << ", " - << PhysRegName(ops.at(1).GetReg()) << ", " - << PhysRegName(ops.at(2).GetReg()) << "\n"; - break; - case Opcode::FMulRR: - os << " fmul " << PhysRegName(ops.at(0).GetReg()) << ", " - << PhysRegName(ops.at(1).GetReg()) << ", " - << PhysRegName(ops.at(2).GetReg()) << "\n"; - break; - case Opcode::FDivRR: - os << " fdiv " << PhysRegName(ops.at(0).GetReg()) << ", " - << PhysRegName(ops.at(1).GetReg()) << ", " - << PhysRegName(ops.at(2).GetReg()) << "\n"; - break; - case Opcode::CmpRR: - os << " cmp " << PhysRegName(ops.at(0).GetReg()) << ", " - << PhysRegName(ops.at(1).GetReg()) << "\n"; - break; - case Opcode::CmpRI: - os << " cmp " << PhysRegName(ops.at(0).GetReg()) << ", #" - << ops.at(1).GetImm() << "\n"; - break; - case Opcode::FCmpRR: - os << " fcmp " << PhysRegName(ops.at(0).GetReg()) << ", " - << PhysRegName(ops.at(1).GetReg()) << "\n"; - break; - case Opcode::SIToFP: - os << " scvtf " << PhysRegName(ops.at(0).GetReg()) << ", " - << PhysRegName(ops.at(1).GetReg()) << "\n"; - break; - case Opcode::FPToSI: - os << " fcvtzs " << PhysRegName(ops.at(0).GetReg()) << ", " - << PhysRegName(ops.at(1).GetReg()) << "\n"; - break; - case Opcode::ZExt: - os << " and " << PhysRegName(ops.at(0).GetReg()) << ", " - << PhysRegName(ops.at(1).GetReg()) << ", #1\n"; - break; - case Opcode::AndRR: - os << " and " << PhysRegName(ops.at(0).GetReg()) << ", " - << PhysRegName(ops.at(1).GetReg()) << ", " - << PhysRegName(ops.at(2).GetReg()) << "\n"; - break; - case Opcode::OrRR: - os << " orr " << PhysRegName(ops.at(0).GetReg()) << ", " - << PhysRegName(ops.at(1).GetReg()) << ", " - << PhysRegName(ops.at(2).GetReg()) << "\n"; - break; - case Opcode::EorRR: - os << " eor " << PhysRegName(ops.at(0).GetReg()) << ", " - << PhysRegName(ops.at(1).GetReg()) << ", " - << PhysRegName(ops.at(2).GetReg()) << "\n"; - break; - case Opcode::LslRR: - os << " lsl " << PhysRegName(ops.at(0).GetReg()) << ", " - << PhysRegName(ops.at(1).GetReg()) << ", " - << PhysRegName(ops.at(2).GetReg()) << "\n"; - break; - case Opcode::LsrRR: - os << " lsr " << PhysRegName(ops.at(0).GetReg()) << ", " - << PhysRegName(ops.at(1).GetReg()) << ", " - << PhysRegName(ops.at(2).GetReg()) << "\n"; - break; - case Opcode::AsrRR: - os << " asr " << PhysRegName(ops.at(0).GetReg()) << ", " - << PhysRegName(ops.at(1).GetReg()) << ", " - << PhysRegName(ops.at(2).GetReg()) << "\n"; - break; - case Opcode::Nop: - os << " nop \n"; - break; - // TODO: 控制流 - case Opcode::B: - break; - case Opcode::BCond: - break; - case Opcode::Call: - break; - case Opcode::Ret: - os << " ret\n"; - break; - + // 计算栈帧大小 + int frameSize = function.GetFrameSize(); + int alignedSize = (frameSize + 15) & ~15; // 16 字节对齐 + + // ========== 函数序言 ========== + os << " stp x29, x30, [sp, #-16]!\n"; // 保存 FP/LR,sp -= 16 + os << " mov x29, sp\n"; // 设置 FP + + if (alignedSize > 0) { + os << " sub sp, sp, #" << alignedSize << "\n"; // 分配局部变量空间 + } + + // 输出每个基本块 + const auto& blocks = function.GetBasicBlocks(); + bool firstBlock = true; + + for (const auto& bb : blocks) { + // 输出基本块标签(非第一个基本块) + if (!firstBlock) { + os << bb->GetName() << ":\n"; + } + firstBlock = false; + + // 输出基本块中的指令 + for (const auto& inst : bb->GetInstructions()) { + PrintInstruction(os, inst, function); } } + + os << ".size " << function.GetName() << ", .-" << function.GetName() << "\n"; +} + +} // namespace - os << ".size " << function.GetName() << ", .-" << function.GetName() - << "\n"; +// 打印模块(模块版本) +void PrintAsm(const MachineModule& module, std::ostream& os) { + // 输出文件头 + os << ".arch armv8-a\n"; + os << ".text\n"; + + // 遍历所有函数,输出汇编 + for (const auto& func : module.GetFunctions()) { + PrintAsm(*func, os); + os << "\n"; + } } -} // namespace mir +} // namespace mir \ No newline at end of file diff --git a/src/mir/FrameLowering.cpp b/src/mir/FrameLowering.cpp index 679ab68..af3a863 100644 --- a/src/mir/FrameLowering.cpp +++ b/src/mir/FrameLowering.cpp @@ -14,7 +14,112 @@ int AlignTo(int value, int align) { } // namespace +// 计算栈帧中所有栈槽的总大小 +static int CalculateStackFrameSize(MachineFunction& function) { + int totalSize = 0; + + // 计算所有栈槽的总大小 + for (auto& slot : function.GetFrameSlots()) { + // 栈槽偏移从 -4, -8, -12 开始(负偏移) + int offset = -(totalSize + slot.size); + slot.offset = offset; + totalSize += slot.size; + } + + // 返回局部变量总大小(不需要额外加 16,因为 sp 已经减了 16) + return totalSize; +} + +// 单函数版本的栈帧布局(原有逻辑扩展) void RunFrameLowering(MachineFunction& function) { + // 计算栈帧大小 + int frameSize = CalculateStackFrameSize(function); + function.SetFrameSize(frameSize); + + // 获取入口基本块 + if (function.GetBasicBlocks().empty()) { + throw std::runtime_error(FormatError("framelowering", "函数没有基本块")); + } + + MachineBasicBlock& entry = function.GetEntry(); + + // 获取指令列表 + auto& instrs = entry.GetInstructions(); + + // 创建新的指令列表,先放序言,再放原有指令 + std::vector newInstrs; + + // ========== 函数序言 ========== + // 1. stp x29, x30, [sp, #-16]! (保存 FP 和 LR,同时 sp -= 16) + /* newInstrs.emplace_back(Opcode::StoreStackPair, + std::vector{Operand::Reg(PhysReg::X29), + Operand::Reg(PhysReg::X30), + Operand::Imm(-16)}); + + // 2. mov x29, sp (设置 FP) + newInstrs.emplace_back(Opcode::MovReg, + std::vector{Operand::Reg(PhysReg::X29), + Operand::Reg(PhysReg::SP)}); + + // 3. sub sp, sp, #frameSize (分配局部变量空间) + if (frameSize > 0) { + int alignedSize = (frameSize + 15) & ~15; // 16 字节对齐 + newInstrs.emplace_back(Opcode::SubRI, + std::vector{Operand::Reg(PhysReg::SP), + Operand::Reg(PhysReg::SP), + Operand::Imm(alignedSize)}); + } + + // 复制原有指令 + for (auto& instr : instrs) { + newInstrs.push_back(std::move(instr)); + } + + // 替换指令列表 + instrs = std::move(newInstrs); */ + + // ========== 处理尾声 ========== + /* for (auto& bb : function.GetBasicBlocks()) { + auto& instructions = bb->GetInstructions(); + + // 查找 Ret 指令 + for (auto it = instructions.begin(); it != instructions.end(); ++it) { + if (it->GetOpcode() == Opcode::Ret) { + // 创建尾声指令 + std::vector epilogue; + + // 1. add sp, sp, #frameSize (释放局部变量空间) + if (frameSize > 0) { + int alignedSize = (frameSize + 15) & ~15; + epilogue.emplace_back(Opcode::AddRI, + std::vector{Operand::Reg(PhysReg::SP), + Operand::Reg(PhysReg::SP), + Operand::Imm(alignedSize)}); + } + + // 2. ldp x29, x30, [sp], #16 (恢复 FP 和 LR,同时 sp += 16) + epilogue.emplace_back(Opcode::LoadStackPair, + std::vector{Operand::Reg(PhysReg::X29), + Operand::Reg(PhysReg::X30), + Operand::Imm(16)}); + + // 在 Ret 指令前插入尾声 + instructions.insert(it, epilogue.begin(), epilogue.end()); + break; // 每个函数只处理第一个 Ret(实际应该处理所有) + } + } + } */ +} + +// 模块版本的栈帧布局 +void RunFrameLowering(MachineModule& module) { + // 对模块中的每个函数执行栈帧布局 + for (auto& func : module.GetFunctions()) { + RunFrameLowering(*func); + } +} + +/* void RunFrameLowering(MachineFunction& function) { int cursor = 0; for (const auto& slot : function.GetFrameSlots()) { cursor += slot.size; @@ -40,6 +145,6 @@ void RunFrameLowering(MachineFunction& function) { lowered.push_back(inst); } insts = std::move(lowered); -} +} */ } // namespace mir diff --git a/src/mir/Lowering.cpp b/src/mir/Lowering.cpp index 5adca7f..7098107 100644 --- a/src/mir/Lowering.cpp +++ b/src/mir/Lowering.cpp @@ -12,13 +12,113 @@ namespace { using ValueSlotMap = std::unordered_map; +// 获取类型大小(字节) +int GetTypeSize(const ir::Type* type) { + if (!type) return 4; + size_t size = type->Size(); + return size > 0 ? static_cast(size) : 4; +} + +// 将 IR 整数比较谓词转换为 ARMv8 条件码 +CondCode IcmpToCondCode(ir::IcmpInst::Predicate pred) { + switch (pred) { + case ir::IcmpInst::Predicate::EQ: return CondCode::EQ; + case ir::IcmpInst::Predicate::NE: return CondCode::NE; + case ir::IcmpInst::Predicate::LT: return CondCode::LT; + case ir::IcmpInst::Predicate::GT: return CondCode::GT; + case ir::IcmpInst::Predicate::LE: return CondCode::LE; + case ir::IcmpInst::Predicate::GE: return CondCode::GE; + default: return CondCode::AL; + } +} + +// 将 IR 浮点比较谓词转换为 ARMv8 条件码 +CondCode FcmpToCondCode(ir::FcmpInst::Predicate pred, bool& isOrdered) { + isOrdered = true; + switch (pred) { + case ir::FcmpInst::Predicate::OEQ: return CondCode::EQ; + case ir::FcmpInst::Predicate::ONE: return CondCode::NE; + case ir::FcmpInst::Predicate::OLT: return CondCode::LT; + case ir::FcmpInst::Predicate::OGT: return CondCode::GT; + case ir::FcmpInst::Predicate::OLE: return CondCode::LE; + case ir::FcmpInst::Predicate::OGE: return CondCode::GE; + case ir::FcmpInst::Predicate::UEQ: isOrdered = false; return CondCode::EQ; + case ir::FcmpInst::Predicate::UNE: isOrdered = false; return CondCode::NE; + case ir::FcmpInst::Predicate::ULT: isOrdered = false; return CondCode::LT; + case ir::FcmpInst::Predicate::UGT: isOrdered = false; return CondCode::GT; + case ir::FcmpInst::Predicate::ULE: isOrdered = false; return CondCode::LE; + case ir::FcmpInst::Predicate::UGE: isOrdered = false; return CondCode::GE; + default: return CondCode::AL; + } +} + +// 获取基本块的标签名(用于汇编输出) +std::string GetBlockLabel(const ir::BasicBlock* bb) { + if (!bb || !bb->GetParent()) { + return ".Lunknown"; + } + // 格式:.L函数名_基本块名 + std::string funcName = bb->GetParent()->GetName(); + std::string blockName = bb->GetName(); + + // 如果基本块没有名字,使用地址作为标识 + if (blockName.empty()) { + blockName = std::to_string(reinterpret_cast(bb)); + } + + return ".L" + funcName + "_" + blockName; +} + +// 获取数组类型的维度信息 +static const ir::ArrayType* GetArrayType(const ir::Type* type) { + if (type->IsArray()) { + return static_cast(type); + } + return nullptr; +} + +static std::vector GetArrayStrides(const ir::ArrayType* arrayType) { + std::vector strides; + const std::vector& dims = arrayType->GetDimensions(); + int stride = 4; // 元素大小(int/float 是 4 字节) + + // 从最后一维向前计算步长 + for (int i = dims.size() - 1; i >= 0; --i) { + strides.insert(strides.begin(), stride); + stride *= dims[i]; + } + return strides; +} + void EmitValueToReg(const ir::Value* value, PhysReg target, - const ValueSlotMap& slots, MachineBasicBlock& block) { + const ValueSlotMap& slots, MachineBasicBlock& block, + MachineFunction& function) { + // 处理整数常量 if (auto* constant = dynamic_cast(value)) { block.Append(Opcode::MovImm, {Operand::Reg(target), Operand::Imm(constant->GetValue())}); return; } + // 处理浮点常量 + if (auto* fconstant = dynamic_cast(value)) { + // 浮点常量需要先存储到栈槽,再加载到寄存器 + // 因为 ARMv8 没有直接加载浮点立即数的指令 + int slot = -1; + // 注意:这里需要找到或创建该浮点常量的栈槽 + // 简单起见,可以每次都分配新栈槽 + // 更好的做法是:在 Module 级别缓存浮点常量 + throw std::runtime_error( + FormatError("mir", "浮点常量暂未实现")); + return; + } + // 处理零常量 + if (dynamic_cast(value) || + dynamic_cast(value)) { + // 零常量:直接加载 0 + block.Append(Opcode::MovImm, + {Operand::Reg(target), Operand::Imm(0)}); + return; + } auto it = slots.find(value); if (it == slots.end()) { @@ -31,22 +131,34 @@ void EmitValueToReg(const ir::Value* value, PhysReg target, } void LowerInstruction(const ir::Instruction& inst, MachineFunction& function, - ValueSlotMap& slots) { - auto& block = function.GetEntry(); + ValueSlotMap& slots, MachineBasicBlock& block, + std::unordered_map& blockMap) { + //auto& block = function.GetEntry(); switch (inst.GetOpcode()) { case ir::Opcode::Alloca: { - slots.emplace(&inst, function.CreateFrameIndex()); + slots.emplace(&inst, function.CreateFrameIndex(GetTypeSize(inst.GetType().get()))); return; } case ir::Opcode::Store: { auto& store = static_cast(inst); auto dst = slots.find(store.GetPtr()); if (dst == slots.end()) { - throw std::runtime_error( - FormatError("mir", "暂不支持对非栈变量地址进行写入")); + //throw std::runtime_error( + // FormatError("mir", "暂不支持对非栈变量地址进行写入")); + // 对于非栈变量地址(如 GEP 结果),地址本身在栈槽中 + // 需要先加载地址,然后存储值到该地址 + // 先加载地址到 x8 + EmitValueToReg(store.GetPtr(), PhysReg::X8, slots, block, function); + // 加载值到 w9 + EmitValueToReg(store.GetValue(), PhysReg::W9, slots, block, function); + // 存储值到地址 + block.Append(Opcode::StoreStack, + {Operand::Reg(PhysReg::W9), Operand::Reg(PhysReg::X8)}); + return; } - EmitValueToReg(store.GetValue(), PhysReg::W8, slots, block); + EmitValueToReg(store.GetValue(), PhysReg::W8, slots, block, function); block.Append(Opcode::StoreStack, {Operand::Reg(PhysReg::W8), Operand::FrameIndex(dst->second)}); return; @@ -55,10 +167,23 @@ void LowerInstruction(const ir::Instruction& inst, MachineFunction& function, auto& load = static_cast(inst); auto src = slots.find(load.GetPtr()); if (src == slots.end()) { - throw std::runtime_error( - FormatError("mir", "暂不支持对非栈变量地址进行读取")); + //throw std::runtime_error( + // FormatError("mir", "暂不支持对非栈变量地址进行读取")); + // 对于非栈变量地址(如 GEP 结果),地址本身在栈槽中 + // 需要先加载地址,然后从该地址加载值 + int dst_slot = function.CreateFrameIndex(GetTypeSize(inst.GetType().get())); + // 加载地址到 x8 + EmitValueToReg(load.GetPtr(), PhysReg::X8, slots, block, function); + // 从地址加载值到 w9 + block.Append(Opcode::LoadStack, + {Operand::Reg(PhysReg::W9), Operand::Reg(PhysReg::X8)}); + // 存储值到结果栈槽 + block.Append(Opcode::StoreStack, + {Operand::Reg(PhysReg::W9), Operand::FrameIndex(dst_slot)}); + slots.emplace(&inst, dst_slot); + return; } - int dst_slot = function.CreateFrameIndex(); + int dst_slot = function.CreateFrameIndex(GetTypeSize(inst.GetType().get())); // 分配结果槽 block.Append(Opcode::LoadStack, {Operand::Reg(PhysReg::W8), Operand::FrameIndex(src->second)}); block.Append(Opcode::StoreStack, @@ -68,9 +193,9 @@ void LowerInstruction(const ir::Instruction& inst, MachineFunction& function, } case ir::Opcode::Add: { auto& bin = static_cast(inst); - int dst_slot = function.CreateFrameIndex(); - EmitValueToReg(bin.GetLhs(), PhysReg::W8, slots, block); - EmitValueToReg(bin.GetRhs(), PhysReg::W9, slots, block); + int dst_slot = function.CreateFrameIndex(GetTypeSize(inst.GetType().get())); + EmitValueToReg(bin.GetLhs(), PhysReg::W8, slots, block, function); + EmitValueToReg(bin.GetRhs(), PhysReg::W9, slots, block, function); block.Append(Opcode::AddRR, {Operand::Reg(PhysReg::W8), Operand::Reg(PhysReg::W8), Operand::Reg(PhysReg::W9)}); @@ -79,46 +204,523 @@ void LowerInstruction(const ir::Instruction& inst, MachineFunction& function, slots.emplace(&inst, dst_slot); return; } + case ir::Opcode::Sub: { + auto& bin = static_cast(inst); + int dst_slot = function.CreateFrameIndex(GetTypeSize(inst.GetType().get())); // 分配结果栈槽 + EmitValueToReg(bin.GetLhs(), PhysReg::W8, slots, block, function); + EmitValueToReg(bin.GetRhs(), PhysReg::W9, slots, block, function); + block.Append(Opcode::SubRR, {Operand::Reg(PhysReg::W8), + Operand::Reg(PhysReg::W8), + Operand::Reg(PhysReg::W9)}); + block.Append(Opcode::StoreStack, + {Operand::Reg(PhysReg::W8), Operand::FrameIndex(dst_slot)}); + slots.emplace(&inst, dst_slot); + return; + } + case ir::Opcode::Mul: { + auto& bin = static_cast(inst); + int dst_slot = function.CreateFrameIndex(GetTypeSize(inst.GetType().get())); // 分配结果栈槽 + EmitValueToReg(bin.GetLhs(), PhysReg::W8, slots, block, function); + EmitValueToReg(bin.GetRhs(), PhysReg::W9, slots, block, function); + block.Append(Opcode::MulRR, {Operand::Reg(PhysReg::W8), + Operand::Reg(PhysReg::W8), + Operand::Reg(PhysReg::W9)}); + block.Append(Opcode::StoreStack, + {Operand::Reg(PhysReg::W8), Operand::FrameIndex(dst_slot)}); + slots.emplace(&inst, dst_slot); + return; + } + case ir::Opcode::Div: { + auto& bin = static_cast(inst); + int dst_slot = function.CreateFrameIndex(GetTypeSize(inst.GetType().get())); // 分配结果栈槽 + EmitValueToReg(bin.GetLhs(), PhysReg::W8, slots, block, function); + EmitValueToReg(bin.GetRhs(), PhysReg::W9, slots, block, function); + block.Append(Opcode::SDivRR, {Operand::Reg(PhysReg::W8), + Operand::Reg(PhysReg::W8), + Operand::Reg(PhysReg::W9)}); + block.Append(Opcode::StoreStack, + {Operand::Reg(PhysReg::W8), Operand::FrameIndex(dst_slot)}); + slots.emplace(&inst, dst_slot); + return; + } case ir::Opcode::Ret: { auto& ret = static_cast(inst); - EmitValueToReg(ret.GetValue(), PhysReg::W0, slots, block); + EmitValueToReg(ret.GetValue(), PhysReg::W0, slots, block, function); block.Append(Opcode::Ret); return; } - case ir::Opcode::Sub: - case ir::Opcode::Mul: - throw std::runtime_error(FormatError("mir", "暂不支持该二元运算")); + case ir::Opcode::FAdd: { + auto& bin = static_cast(inst); + int dst_slot = function.CreateFrameIndex(GetTypeSize(inst.GetType().get())); // 分配结果栈槽 + // 浮点值加载到 S0, S1(使用浮点寄存器) + EmitValueToReg(bin.GetLhs(), PhysReg::S0, slots, block, function); + EmitValueToReg(bin.GetRhs(), PhysReg::S1, slots, block, function); + block.Append(Opcode::FAddRR, {Operand::Reg(PhysReg::S0), + Operand::Reg(PhysReg::S0), + Operand::Reg(PhysReg::S1)}); + block.Append(Opcode::StoreStack, + {Operand::Reg(PhysReg::S0), Operand::FrameIndex(dst_slot)}); + slots.emplace(&inst, dst_slot); + return; + } + case ir::Opcode::FSub: { + auto& bin = static_cast(inst); + int dst_slot = function.CreateFrameIndex(GetTypeSize(inst.GetType().get())); // 分配结果栈槽 + // 浮点值加载到 S0, S1(使用浮点寄存器) + EmitValueToReg(bin.GetLhs(), PhysReg::S0, slots, block, function); + EmitValueToReg(bin.GetRhs(), PhysReg::S1, slots, block, function); + block.Append(Opcode::FSubRR, {Operand::Reg(PhysReg::S0), + Operand::Reg(PhysReg::S0), + Operand::Reg(PhysReg::S1)}); + block.Append(Opcode::StoreStack, + {Operand::Reg(PhysReg::S0), Operand::FrameIndex(dst_slot)}); + slots.emplace(&inst, dst_slot); + return; + } + case ir::Opcode::FMul: { + auto& bin = static_cast(inst); + int dst_slot = function.CreateFrameIndex(GetTypeSize(inst.GetType().get())); // 分配结果栈槽 + // 浮点值加载到 S0, S1(使用浮点寄存器) + EmitValueToReg(bin.GetLhs(), PhysReg::S0, slots, block, function); + EmitValueToReg(bin.GetRhs(), PhysReg::S1, slots, block, function); + block.Append(Opcode::FMulRR, {Operand::Reg(PhysReg::S0), + Operand::Reg(PhysReg::S0), + Operand::Reg(PhysReg::S1)}); + block.Append(Opcode::StoreStack, + {Operand::Reg(PhysReg::S0), Operand::FrameIndex(dst_slot)}); + slots.emplace(&inst, dst_slot); + return; + } + case ir::Opcode::FDiv: { + auto& bin = static_cast(inst); + int dst_slot = function.CreateFrameIndex(GetTypeSize(inst.GetType().get())); // 分配结果栈槽 + // 浮点值加载到 S0, S1(使用浮点寄存器) + EmitValueToReg(bin.GetLhs(), PhysReg::S0, slots, block, function); + EmitValueToReg(bin.GetRhs(), PhysReg::S1, slots, block, function); + block.Append(Opcode::FDivRR, {Operand::Reg(PhysReg::S0), + Operand::Reg(PhysReg::S0), + Operand::Reg(PhysReg::S1)}); + block.Append(Opcode::StoreStack, + {Operand::Reg(PhysReg::S0), Operand::FrameIndex(dst_slot)}); + slots.emplace(&inst, dst_slot); + return; + } + // ========== 整数比较指令(修正版)========== + case ir::Opcode::Icmp: { + auto& icmp = static_cast(inst); + int dst_slot = function.CreateFrameIndex(GetTypeSize(inst.GetType().get())); + + // 加载左右操作数到 w8, w9 + EmitValueToReg(icmp.GetLhs(), PhysReg::W8, slots, block, function); + EmitValueToReg(icmp.GetRhs(), PhysReg::W9, slots, block, function); + + // 生成比较指令 + block.Append(Opcode::CmpRR, {Operand::Reg(PhysReg::W8), Operand::Reg(PhysReg::W9)}); + + // 使用条件设置指令: CSET W8, cc + // 如果条件成立,W8 = 1;否则 W8 = 0 + CondCode cc = IcmpToCondCode(icmp.GetPredicate()); + + // 使用 CSET 的替代实现:条件移动 + // MOV W8, #1 + // MOV W9, #0 + // CSEL W8, W8, W9, cc + block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::W8), Operand::Imm(1)}); + block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::W9), Operand::Imm(0)}); + + // TODO: 需要添加 CSEL 指令,暂时使用条件跳转 + // 创建临时标签 + std::string true_label = ".L_cset_true_" + std::to_string(reinterpret_cast(&icmp)); + std::string end_label = ".L_cset_end_" + std::to_string(reinterpret_cast(&icmp)); + + // 条件跳转到 true_label + block.Append(Opcode::BCond, {Operand::Cond(cc), Operand::Imm(0)}); + // 条件不成立:W8 = 0 + block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::W8), Operand::Imm(0)}); + block.Append(Opcode::B, {Operand::Imm(0)}); // 跳转到 end_label + // true_label: W8 = 1(已经在上面设置了) + // end_label: 继续 + + block.Append(Opcode::StoreStack, + {Operand::Reg(PhysReg::W8), Operand::FrameIndex(dst_slot)}); + slots.emplace(&inst, dst_slot); + return; + } + // ========== 浮点比较指令 ========== + case ir::Opcode::FCmp: { + auto& fcmp = static_cast(inst); + int dst_slot = function.CreateFrameIndex(GetTypeSize(inst.GetType().get())); + + // 加载浮点操作数到 s0, s1 + EmitValueToReg(fcmp.GetLhs(), PhysReg::S0, slots, block, function); + EmitValueToReg(fcmp.GetRhs(), PhysReg::S1, slots, block, function); + + // 生成浮点比较指令 + block.Append(Opcode::FCmpRR, {Operand::Reg(PhysReg::S0), Operand::Reg(PhysReg::S1)}); + + // 简化实现:存储 1 作为结果 + block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::W8), Operand::Imm(1)}); + block.Append(Opcode::StoreStack, + {Operand::Reg(PhysReg::W8), Operand::FrameIndex(dst_slot)}); + slots.emplace(&inst, dst_slot); + return; + } + // ========== 跳转指令(使用标签操作数)========== + case ir::Opcode::Br: { + auto& br = static_cast(inst); + + if (br.IsConditional()) { + // 条件跳转: br i1 %cond, label %then, label %else + // 加载条件值到 w8 + EmitValueToReg(br.GetCondition(), PhysReg::W8, slots, block, function); + + // 比较条件值是否为 0 + block.Append(Opcode::CmpRI, {Operand::Reg(PhysReg::W8), Operand::Imm(0)}); + + // 获取目标基本块的标签名 + const ir::BasicBlock* irTrueTarget = br.GetTrueTarget(); + const ir::BasicBlock* irFalseTarget = br.GetFalseTarget(); + + std::string trueLabel = GetBlockLabel(irTrueTarget); + std::string falseLabel = GetBlockLabel(irFalseTarget); + + // 生成 B.NE true_label + block.Append(Opcode::BCond, {Operand::Cond(CondCode::NE), Operand::Label(trueLabel)}); + // 生成 B false_label + block.Append(Opcode::B, {Operand::Label(falseLabel)}); + } else { + // 无条件跳转: br label %target + const ir::BasicBlock* irTarget = br.GetTarget(); + std::string targetLabel = GetBlockLabel(irTarget); + + // 生成 B target_label + block.Append(Opcode::B, {Operand::Label(targetLabel)}); + } + return; + } + // ========== 函数调用 ========== + case ir::Opcode::Call: { + auto& call = static_cast(inst); + const ir::Function* callee = call.GetCallee(); + const std::string& calleeName = callee->GetName(); + + // 分配结果栈槽(如果有返回值) + int dst_slot = -1; + if (!inst.GetType()->IsVoid()) { + dst_slot = function.CreateFrameIndex(GetTypeSize(inst.GetType().get())); + } + + // 按照 ARM64 调用约定传递参数 + const auto& args = call.GetArgs(); + size_t intArgCount = 0; + size_t fpArgCount = 0; + + for (size_t i = 0; i < args.size(); ++i) { + const auto* arg = args[i]; + const ir::Type* argType = arg->GetType().get(); + + if (argType->IsFloat()) { + // 浮点参数 + PhysReg reg = static_cast(static_cast(PhysReg::S0) + fpArgCount); + EmitValueToReg(arg, reg, slots, block, function); + fpArgCount++; + } else { + // 整数参数 + PhysReg reg = static_cast(static_cast(PhysReg::W0) + intArgCount); + EmitValueToReg(arg, reg, slots, block, function); + intArgCount++; + } + } + + // 生成调用指令 + block.Append(Opcode::Call, {Operand::Imm(0)}); // 实际需要传递函数名 + + // 保存返回值 + if (dst_slot != -1) { + if (inst.GetType()->IsFloat()) { + block.Append(Opcode::StoreStack, + {Operand::Reg(PhysReg::S0), Operand::FrameIndex(dst_slot)}); + } else { + block.Append(Opcode::StoreStack, + {Operand::Reg(PhysReg::W0), Operand::FrameIndex(dst_slot)}); + } + slots.emplace(&inst, dst_slot); + } + return; + } + // ========== 类型转换指令 ========== + case ir::Opcode::ZExt: { + auto& zext = static_cast(inst); + int dst_slot = function.CreateFrameIndex(GetTypeSize(inst.GetType().get())); + + // 加载源值到 w8 + EmitValueToReg(zext.GetValue(), PhysReg::W8, slots, block, function); + + // 零扩展:i1 -> i32,直接存储即可(因为 i1 已经是 0 或 1) + block.Append(Opcode::StoreStack, + {Operand::Reg(PhysReg::W8), Operand::FrameIndex(dst_slot)}); + slots.emplace(&inst, dst_slot); + return; + } + case ir::Opcode::SIToFP: { + auto& sitofp = static_cast(inst); + int dst_slot = function.CreateFrameIndex(GetTypeSize(inst.GetType().get())); + + // 加载整数到 w8 + EmitValueToReg(sitofp.GetValue(), PhysReg::W8, slots, block, function); + + // 整数转浮点:SCVTF s0, w8 + block.Append(Opcode::SIToFP, {Operand::Reg(PhysReg::S0), Operand::Reg(PhysReg::W8)}); + block.Append(Opcode::StoreStack, + {Operand::Reg(PhysReg::S0), Operand::FrameIndex(dst_slot)}); + slots.emplace(&inst, dst_slot); + return; + } + case ir::Opcode::FPToSI: { + auto& fptosi = static_cast(inst); + int dst_slot = function.CreateFrameIndex(GetTypeSize(inst.GetType().get())); + + // 加载浮点数到 s0 + EmitValueToReg(fptosi.GetValue(), PhysReg::S0, slots, block, function); + + // 浮点转整数:FCVTZS w8, s0 + block.Append(Opcode::FPToSI, {Operand::Reg(PhysReg::W8), Operand::Reg(PhysReg::S0)}); + block.Append(Opcode::StoreStack, + {Operand::Reg(PhysReg::W8), Operand::FrameIndex(dst_slot)}); + slots.emplace(&inst, dst_slot); + return; + } + // ========== GEP 指令(计算数组元素地址)========== + case ir::Opcode::GEP: { + auto& gep = static_cast(inst); + + // GEP 返回指针类型,在 ARM64 上指针是 8 字节 + int dst_slot = function.CreateFrameIndex(8); + + // 获取基地址(数组的起始地址) + ir::Value* base = gep.GetBase(); + const auto& indices = gep.GetIndices(); + + // 加载基地址到 x8(使用 64 位寄存器存储地址) + EmitValueToReg(base, PhysReg::X8, slots, block, function); + + if (indices.empty()) { + // 没有索引,直接返回基地址 + block.Append(Opcode::StoreStack, + {Operand::Reg(PhysReg::X8), Operand::FrameIndex(dst_slot)}); + slots.emplace(&inst, dst_slot); + return; + } + + // 获取数组类型信息,计算每个维度的步长 + const ir::Type* baseType = base->GetType().get(); + + // 如果基地址是指针类型,需要解引用获取元素类型 + if (baseType->IsPtrInt32() || baseType->IsPtrFloat() || baseType->IsPtrInt1()) { + // 对于指针类型,第一个索引是偏移量(以元素为单位) + // 例如:int* p; p[1] 的 GEP 中 indices[0] = 1 + if (indices.size() >= 1) { + // 加载索引到 x9 + EmitValueToReg(indices[0], PhysReg::X9, slots, block, function); + + // 乘以元素大小(int/float 是 4 字节) + block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::X10), Operand::Imm(4)}); + block.Append(Opcode::MulRR, {Operand::Reg(PhysReg::X9), + Operand::Reg(PhysReg::X9), + Operand::Reg(PhysReg::X10)}); + + // 地址 = base + index * 4 + block.Append(Opcode::AddRR, {Operand::Reg(PhysReg::X8), + Operand::Reg(PhysReg::X8), + Operand::Reg(PhysReg::X9)}); + } + + // 存储计算出的地址 + block.Append(Opcode::StoreStack, + {Operand::Reg(PhysReg::X8), Operand::FrameIndex(dst_slot)}); + slots.emplace(&inst, dst_slot); + return; + } + + // 如果基地址是数组类型,需要处理多维数组 + if (baseType->IsArray()) { + const ir::ArrayType* arrayType = static_cast(baseType); + const std::vector& dims = arrayType->GetDimensions(); + + // 计算每个维度的步长 + std::vector strides(dims.size()); + int stride = 4; // 元素大小(int/float 是 4 字节) + for (int i = dims.size() - 1; i >= 0; --i) { + strides[i] = stride; + stride *= dims[i]; + } + + // 计算总偏移量 + // 地址 = base + index0 * stride0 + index1 * stride1 + ... + size_t numIndices = indices.size(); + + // 限制索引数量(不能超过维度数) + if (numIndices > dims.size()) { + numIndices = dims.size(); + } + + // 加载当前地址到 x9 作为偏移量累加器 + block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::X9), Operand::Imm(0)}); + + for (size_t i = 0; i < numIndices; ++i) { + // 加载当前索引到 x10 + EmitValueToReg(indices[i], PhysReg::X10, slots, block, function); + + // 乘以步长 + block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::X11), Operand::Imm(strides[i])}); + block.Append(Opcode::MulRR, {Operand::Reg(PhysReg::X10), + Operand::Reg(PhysReg::X10), + Operand::Reg(PhysReg::X11)}); + + // 累加到偏移量 + block.Append(Opcode::AddRR, {Operand::Reg(PhysReg::X9), + Operand::Reg(PhysReg::X9), + Operand::Reg(PhysReg::X10)}); + } + + // 最终地址 = base + offset + block.Append(Opcode::AddRR, {Operand::Reg(PhysReg::X8), + Operand::Reg(PhysReg::X8), + Operand::Reg(PhysReg::X9)}); + + // 存储计算出的地址 + block.Append(Opcode::StoreStack, + {Operand::Reg(PhysReg::X8), Operand::FrameIndex(dst_slot)}); + slots.emplace(&inst, dst_slot); + return; + } + + // 其他情况:简单处理 + // 只处理第一个索引 + if (indices.size() >= 1) { + EmitValueToReg(indices[0], PhysReg::X9, slots, block, function); + + // 乘以元素大小(默认 4 字节) + block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::X10), Operand::Imm(4)}); + block.Append(Opcode::MulRR, {Operand::Reg(PhysReg::X9), + Operand::Reg(PhysReg::X9), + Operand::Reg(PhysReg::X10)}); + + block.Append(Opcode::AddRR, {Operand::Reg(PhysReg::X8), + Operand::Reg(PhysReg::X8), + Operand::Reg(PhysReg::X9)}); + } + + // 存储计算出的地址 + block.Append(Opcode::StoreStack, + {Operand::Reg(PhysReg::X8), Operand::FrameIndex(dst_slot)}); + slots.emplace(&inst, dst_slot); + return; + } + //throw std::runtime_error(FormatError("mir", "暂不支持该 IR 指令")); + throw std::runtime_error(FormatError("mir", "暂不支持该 IR 指令,opcode: " + + std::to_string(static_cast(inst.GetOpcode())))); } - - throw std::runtime_error(FormatError("mir", "暂不支持该 IR 指令")); } -} // namespace - -std::unique_ptr LowerToMIR(const ir::Module& module) { - DefaultContext(); - - if (module.GetFunctions().size() != 1) { - throw std::runtime_error(FormatError("mir", "暂不支持多个函数")); - } - - const auto& func = *module.GetFunctions().front(); - if (func.GetName() != "main") { - throw std::runtime_error(FormatError("mir", "暂不支持非 main 函数")); - } +} // namespace +// 辅助函数,将单个 IR 函数转换为 MachineFunction +std::unique_ptr LowerFunction(const ir::Function& func) { auto machine_func = std::make_unique(func.GetName()); ValueSlotMap slots; - const auto* entry = func.GetEntry(); - if (!entry) { - throw std::runtime_error(FormatError("mir", "IR 函数缺少入口基本块")); + + // 为函数参数分配栈槽 + for (const auto& arg : func.GetArguments()) { + // 为每个参数分配栈槽 + int slot = machine_func->CreateFrameIndex(GetTypeSize(arg->GetType().get())); + slots.emplace(arg.get(), slot); + + // 注意:参数的值需要从寄存器加载到栈槽 + // 在 ARM64 调用约定中,前 8 个整数参数在 w0-w7,前 8 个浮点参数在 s0-s7 + // 这里需要生成指令将参数从寄存器存储到栈槽 + // 但 MachineFunction 还没有基本块,所以需要延迟处理 } - - for (const auto& inst : entry->GetInstructions()) { - LowerInstruction(*inst, *machine_func, slots); + + // IR 基本块到 MIR 基本块的映射 + std::unordered_map blockMap; + + // 第一遍:为每个 IR 基本块创建 MIR 基本块 + for (const auto& bb : func.GetBlocks()) { + auto mirBB = std::make_unique(bb->GetName()); + blockMap[bb.get()] = mirBB.get(); + machine_func->AddBasicBlock(std::move(mirBB)); } - + + // 在入口基本块的开头添加参数加载指令 + if (!func.GetBlocks().empty()) { + MachineBasicBlock* entryBB = blockMap[func.GetEntry()]; + if (entryBB) { + // 为每个参数生成从寄存器到栈槽的存储指令 + size_t intArgIdx = 0; + size_t fpArgIdx = 0; + + for (const auto& arg : func.GetArguments()) { + int slot = slots[arg.get()]; + const ir::Type* argType = arg->GetType().get(); + + if (argType->IsFloat()) { + // 浮点参数从 s0, s1, ... 读取 + if (fpArgIdx < 8) { + PhysReg reg = static_cast(static_cast(PhysReg::S0) + fpArgIdx); + entryBB->Append(Opcode::StoreStack, + {Operand::Reg(reg), Operand::FrameIndex(slot)}); + } + fpArgIdx++; + } else { + // 整数参数从 w0, w1, ... 读取 + if (intArgIdx < 8) { + PhysReg reg = static_cast(static_cast(PhysReg::W0) + intArgIdx); + entryBB->Append(Opcode::StoreStack, + {Operand::Reg(reg), Operand::FrameIndex(slot)}); + } + intArgIdx++; + } + } + } + } + + // 第二遍:遍历每个基本块,转换指令 + for (const auto& bb : func.GetBlocks()) { + MachineBasicBlock* mirBB = blockMap[bb.get()]; + if (!mirBB) { + throw std::runtime_error(FormatError("mir", "找不到基本块对应的 MIR 基本块")); + } + + for (const auto& inst : bb->GetInstructions()) { + LowerInstruction(*inst, *machine_func, slots, *mirBB, blockMap); + } + } + return machine_func; } +std::unique_ptr LowerToMIR(const ir::Module& module) { + DefaultContext(); + + auto machine_module = std::make_unique(); + + // 遍历模块中的所有函数 + for (const auto& func : module.GetFunctions()) { + try { + auto machine_func = LowerFunction(*func); + machine_module->AddFunction(std::move(machine_func)); + } catch (const std::runtime_error& e) { + // 记录错误但继续处理其他函数 + throw std::runtime_error(FormatError("mir", "转换函数失败: " + func->GetName() + " - " + e.what())); + } + } + + if (machine_module->GetFunctions().empty()) { + throw std::runtime_error(FormatError("mir", "模块中没有成功转换的函数")); + } + + return machine_module; +} + } // namespace mir diff --git a/src/mir/MIRInstr.cpp b/src/mir/MIRInstr.cpp index 34da3d3..1959b5c 100644 --- a/src/mir/MIRInstr.cpp +++ b/src/mir/MIRInstr.cpp @@ -4,21 +4,25 @@ namespace mir { -Operand::Operand(Kind kind, PhysReg reg, int imm, CondCode cc) - : kind_(kind), reg_(reg), imm_(imm), cc_(cc) {} +Operand::Operand(Kind kind, PhysReg reg, int imm, CondCode cc, const std::string& label) + : kind_(kind), reg_(reg), imm_(imm), cc_(cc), label_(label) {} -Operand Operand::Reg(PhysReg reg) { return Operand(Kind::Reg, reg, 0, CondCode::EQ); } +Operand Operand::Reg(PhysReg reg) { return Operand(Kind::Reg, reg, 0, CondCode::EQ, ""); } Operand Operand::Imm(int value) { - return Operand(Kind::Imm, PhysReg::W0, value, CondCode::EQ); + return Operand(Kind::Imm, PhysReg::W0, value, CondCode::EQ, ""); } Operand Operand::FrameIndex(int index) { - return Operand(Kind::FrameIndex, PhysReg::W0, index, CondCode::EQ); + return Operand(Kind::FrameIndex, PhysReg::W0, index, CondCode::EQ, ""); } Operand Operand::Cond(CondCode cc) { - return Operand(Kind::Cond, PhysReg::W0, 0, cc); + return Operand(Kind::Cond, PhysReg::W0, 0, cc, ""); +} + +Operand Operand::Label(const std::string& label) { + return Operand(Kind::Label, PhysReg::W0, 0, CondCode::EQ, label); } MachineInstr::MachineInstr(Opcode opcode, std::vector operands) diff --git a/src/mir/RegAlloc.cpp b/src/mir/RegAlloc.cpp index 972eac5..19f6f51 100644 --- a/src/mir/RegAlloc.cpp +++ b/src/mir/RegAlloc.cpp @@ -22,15 +22,61 @@ bool IsAllowedReg(PhysReg reg) { } // namespace +//void RunRegAlloc(MachineFunction& function) { +// for (const auto& inst : function.GetEntry().GetInstructions()) { +// for (const auto& operand : inst.GetOperands()) { +// if (operand.GetKind() == Operand::Kind::Reg && +// !IsAllowedReg(operand.GetReg())) { +// throw std::runtime_error(FormatError("mir", "寄存器分配失败")); +// } +// } +// } +//} + +// 单函数版本的寄存器分配(原有逻辑) void RunRegAlloc(MachineFunction& function) { - for (const auto& inst : function.GetEntry().GetInstructions()) { - for (const auto& operand : inst.GetOperands()) { - if (operand.GetKind() == Operand::Kind::Reg && - !IsAllowedReg(operand.GetReg())) { - throw std::runtime_error(FormatError("mir", "寄存器分配失败")); + // 当前仅执行最小一致性检查,不实现真实寄存器分配 + // Lab3 阶段保持栈槽模型,不需要真实寄存器分配 + + // 检查每个基本块中的指令 + for (auto& bb : function.GetBasicBlocks()) { + for (auto& instr : bb->GetInstructions()) { + // 检查指令的操作数是否有效 + for (const auto& operand : instr.GetOperands()) { + switch (operand.GetKind()) { + case Operand::Kind::Reg: + // 寄存器操作数:检查是否在允许的范围内 + // 当前使用固定寄存器 w0, w8, w9, s0, s1 等 + break; + case Operand::Kind::FrameIndex: + // 栈槽索引:检查是否有效 + if (operand.GetFrameIndex() < 0 || + operand.GetFrameIndex() >= static_cast(function.GetFrameSlots().size())) { + throw std::runtime_error( + FormatError("regalloc", "无效的栈槽索引: " + + std::to_string(operand.GetFrameIndex()))); + } + break; + case Operand::Kind::Imm: + case Operand::Kind::Cond: + case Operand::Kind::Label: + // 立即数、条件码、标签不需要检查 + break; + } } } } + + // 注意:Lab3 阶段不实现真实寄存器分配 + // 所有值仍然使用栈槽模型,寄存器仅作为临时计算使用 +} + +// 模块版本的寄存器分配 +void RunRegAlloc(MachineModule& module) { + // 对模块中的每个函数执行寄存器分配 + for (auto& func : module.GetFunctions()) { + RunRegAlloc(*func); + } } } // namespace mir -- 2.34.1 From c24a078bf57f020168f01e663f1d876332037d89 Mon Sep 17 00:00:00 2001 From: ftt <> Date: Thu, 9 Apr 2026 13:49:56 +0800 Subject: [PATCH 05/30] =?UTF-8?q?=E8=A1=A5=E5=85=85=E5=AF=84=E5=AD=98?= =?UTF-8?q?=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/mir/Register.cpp | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/src/mir/Register.cpp b/src/mir/Register.cpp index 5bf605f..772322e 100644 --- a/src/mir/Register.cpp +++ b/src/mir/Register.cpp @@ -25,6 +25,19 @@ const char* PhysRegName(PhysReg reg) { case PhysReg::W13: return "w13"; case PhysReg::W14: return "w14"; case PhysReg::W15: return "w15"; + case PhysReg::W16: return "w16"; // 添加 + case PhysReg::W17: return "w17"; // 添加 + case PhysReg::W18: return "w18"; // 添加 + case PhysReg::W19: return "w19"; // 添加 + case PhysReg::W20: return "w20"; // 添加 + case PhysReg::W21: return "w21"; // 添加 + case PhysReg::W22: return "w22"; // 添加 + case PhysReg::W23: return "w23"; // 添加 + case PhysReg::W24: return "w24"; // 添加 + case PhysReg::W25: return "w25"; // 添加 + case PhysReg::W26: return "w26"; // 添加 + case PhysReg::W27: return "w27"; // 添加 + case PhysReg::W28: return "w28"; // 添加 case PhysReg::W29: return "w29"; case PhysReg::W30: return "w30"; @@ -39,6 +52,25 @@ const char* PhysRegName(PhysReg reg) { case PhysReg::X7: return "x7"; case PhysReg::X8: return "x8"; case PhysReg::X9: return "x9"; + case PhysReg::X10: return "x10"; // 添加 + case PhysReg::X11: return "x11"; // 添加 + case PhysReg::X12: return "x12"; // 添加 + case PhysReg::X13: return "x13"; // 添加 + case PhysReg::X14: return "x14"; // 添加 + case PhysReg::X15: return "x15"; // 添加 + case PhysReg::X16: return "x16"; // 添加 + case PhysReg::X17: return "x17"; // 添加 + case PhysReg::X18: return "x18"; // 添加 + case PhysReg::X19: return "x19"; // 添加 + case PhysReg::X20: return "x20"; // 添加 + case PhysReg::X21: return "x21"; // 添加 + case PhysReg::X22: return "x22"; // 添加 + case PhysReg::X23: return "x23"; // 添加 + case PhysReg::X24: return "x24"; // 添加 + case PhysReg::X25: return "x25"; // 添加 + case PhysReg::X26: return "x26"; // 添加 + case PhysReg::X27: return "x27"; // 添加 + case PhysReg::X28: return "x28"; // 添加 case PhysReg::X29: return "x29"; case PhysReg::X30: return "x30"; -- 2.34.1 From 34ec79c399aadca7f8235824390a3ee77d075a07 Mon Sep 17 00:00:00 2001 From: mxr <> Date: Thu, 9 Apr 2026 14:47:19 +0800 Subject: [PATCH 06/30] =?UTF-8?q?feat(mir)=E4=BF=AE=E5=A4=8D=E6=A0=88?= =?UTF-8?q?=E5=B8=A7=E6=8C=87=E4=BB=A4=E9=81=8D=E5=8E=86=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/mir/AsmPrinter.cpp | 55 +++++++------- src/mir/FrameLowering.cpp | 153 ++++++++++---------------------------- 2 files changed, 66 insertions(+), 142 deletions(-) diff --git a/src/mir/AsmPrinter.cpp b/src/mir/AsmPrinter.cpp index 0be85f8..350a3b4 100644 --- a/src/mir/AsmPrinter.cpp +++ b/src/mir/AsmPrinter.cpp @@ -5,6 +5,15 @@ #include "utils/Log.h" +#define DEBUG_Asm + +#ifdef DEBUG_Asm +#include +#define DEBUG_MSG(msg) std::cerr << "[Asm Debug] " << msg << std::endl +#else +#define DEBUG_MSG(msg) +#endif + namespace mir { namespace { @@ -55,12 +64,19 @@ void PrintInstruction(std::ostream& os, const MachineInstr& instr, const auto& ops = instr.GetOperands(); switch (instr.GetOpcode()) { - case Opcode::Prologue: - // Prologue 在 RunFrameLowering 中已经生成具体指令,这里不需要输出 - break; - case Opcode::Epilogue: - // Epilogue 在 RunFrameLowering 中已经生成具体指令,这里不需要输出 - break; + case Opcode::Prologue: + os << " stp x29, x30, [sp, #-16]!\n"; + os << " mov x29, sp\n"; + if (function.GetFrameSize() > 0) { + os << " sub sp, sp, #" << function.GetFrameSize() << "\n"; + } + break; + case Opcode::Epilogue: + if (function.GetFrameSize() > 0) { + os << " add sp, sp, #" << function.GetFrameSize() << "\n"; + } + os << " ldp x29, x30, [sp], #16\n"; + break; case Opcode::MovImm: os << " mov " << PhysRegName(ops.at(0).GetReg()) << ", #" << ops.at(1).GetImm() << "\n"; @@ -225,21 +241,9 @@ void PrintInstruction(std::ostream& os, const MachineInstr& instr, PrintOperand(os, ops.at(0)); os << "\n"; break; - //case Opcode::Ret: - // os << " ret\n"; - // break; - case Opcode::Ret: { - // 输出函数尾声 - int frameSize = function.GetFrameSize(); - int alignedSize = (frameSize + 15) & ~15; - - if (alignedSize > 0) { - os << " add sp, sp, #" << alignedSize << "\n"; - } - os << " ldp x29, x30, [sp], #16\n"; + case Opcode::Ret: os << " ret\n"; break; - } case Opcode::Nop: os << " nop\n"; break; @@ -259,21 +263,13 @@ void PrintAsm(const MachineFunction& function, std::ostream& os) { // 计算栈帧大小 int frameSize = function.GetFrameSize(); - int alignedSize = (frameSize + 15) & ~15; // 16 字节对齐 - - // ========== 函数序言 ========== - os << " stp x29, x30, [sp, #-16]!\n"; // 保存 FP/LR,sp -= 16 - os << " mov x29, sp\n"; // 设置 FP - - if (alignedSize > 0) { - os << " sub sp, sp, #" << alignedSize << "\n"; // 分配局部变量空间 - } // 输出每个基本块 const auto& blocks = function.GetBasicBlocks(); bool firstBlock = true; for (const auto& bb : blocks) { + DEBUG_MSG("block"); // 输出基本块标签(非第一个基本块) if (!firstBlock) { os << bb->GetName() << ":\n"; @@ -282,6 +278,7 @@ void PrintAsm(const MachineFunction& function, std::ostream& os) { // 输出基本块中的指令 for (const auto& inst : bb->GetInstructions()) { + DEBUG_MSG("inst"); PrintInstruction(os, inst, function); } } @@ -297,8 +294,10 @@ void PrintAsm(const MachineModule& module, std::ostream& os) { os << ".arch armv8-a\n"; os << ".text\n"; + DEBUG_MSG("module"); // 遍历所有函数,输出汇编 for (const auto& func : module.GetFunctions()) { + DEBUG_MSG("func"); PrintAsm(*func, os); os << "\n"; } diff --git a/src/mir/FrameLowering.cpp b/src/mir/FrameLowering.cpp index af3a863..62d7ccb 100644 --- a/src/mir/FrameLowering.cpp +++ b/src/mir/FrameLowering.cpp @@ -5,6 +5,15 @@ #include "utils/Log.h" +#define DEBUG_Frame + +#ifdef DEBUG_Frame +#include +#define DEBUG_MSG(msg) std::cerr << "[Frame Debug] " << msg << std::endl +#else +#define DEBUG_MSG(msg) +#endif + namespace mir { namespace { @@ -14,112 +23,8 @@ int AlignTo(int value, int align) { } // namespace -// 计算栈帧中所有栈槽的总大小 -static int CalculateStackFrameSize(MachineFunction& function) { - int totalSize = 0; - - // 计算所有栈槽的总大小 - for (auto& slot : function.GetFrameSlots()) { - // 栈槽偏移从 -4, -8, -12 开始(负偏移) - int offset = -(totalSize + slot.size); - slot.offset = offset; - totalSize += slot.size; - } - - // 返回局部变量总大小(不需要额外加 16,因为 sp 已经减了 16) - return totalSize; -} - -// 单函数版本的栈帧布局(原有逻辑扩展) void RunFrameLowering(MachineFunction& function) { - // 计算栈帧大小 - int frameSize = CalculateStackFrameSize(function); - function.SetFrameSize(frameSize); - - // 获取入口基本块 - if (function.GetBasicBlocks().empty()) { - throw std::runtime_error(FormatError("framelowering", "函数没有基本块")); - } - - MachineBasicBlock& entry = function.GetEntry(); - - // 获取指令列表 - auto& instrs = entry.GetInstructions(); - - // 创建新的指令列表,先放序言,再放原有指令 - std::vector newInstrs; - - // ========== 函数序言 ========== - // 1. stp x29, x30, [sp, #-16]! (保存 FP 和 LR,同时 sp -= 16) - /* newInstrs.emplace_back(Opcode::StoreStackPair, - std::vector{Operand::Reg(PhysReg::X29), - Operand::Reg(PhysReg::X30), - Operand::Imm(-16)}); - - // 2. mov x29, sp (设置 FP) - newInstrs.emplace_back(Opcode::MovReg, - std::vector{Operand::Reg(PhysReg::X29), - Operand::Reg(PhysReg::SP)}); - - // 3. sub sp, sp, #frameSize (分配局部变量空间) - if (frameSize > 0) { - int alignedSize = (frameSize + 15) & ~15; // 16 字节对齐 - newInstrs.emplace_back(Opcode::SubRI, - std::vector{Operand::Reg(PhysReg::SP), - Operand::Reg(PhysReg::SP), - Operand::Imm(alignedSize)}); - } - - // 复制原有指令 - for (auto& instr : instrs) { - newInstrs.push_back(std::move(instr)); - } - - // 替换指令列表 - instrs = std::move(newInstrs); */ - - // ========== 处理尾声 ========== - /* for (auto& bb : function.GetBasicBlocks()) { - auto& instructions = bb->GetInstructions(); - - // 查找 Ret 指令 - for (auto it = instructions.begin(); it != instructions.end(); ++it) { - if (it->GetOpcode() == Opcode::Ret) { - // 创建尾声指令 - std::vector epilogue; - - // 1. add sp, sp, #frameSize (释放局部变量空间) - if (frameSize > 0) { - int alignedSize = (frameSize + 15) & ~15; - epilogue.emplace_back(Opcode::AddRI, - std::vector{Operand::Reg(PhysReg::SP), - Operand::Reg(PhysReg::SP), - Operand::Imm(alignedSize)}); - } - - // 2. ldp x29, x30, [sp], #16 (恢复 FP 和 LR,同时 sp += 16) - epilogue.emplace_back(Opcode::LoadStackPair, - std::vector{Operand::Reg(PhysReg::X29), - Operand::Reg(PhysReg::X30), - Operand::Imm(16)}); - - // 在 Ret 指令前插入尾声 - instructions.insert(it, epilogue.begin(), epilogue.end()); - break; // 每个函数只处理第一个 Ret(实际应该处理所有) - } - } - } */ -} - -// 模块版本的栈帧布局 -void RunFrameLowering(MachineModule& module) { - // 对模块中的每个函数执行栈帧布局 - for (auto& func : module.GetFunctions()) { - RunFrameLowering(*func); - } -} - -/* void RunFrameLowering(MachineFunction& function) { + DEBUG_MSG("function RunFrameLowering"); int cursor = 0; for (const auto& slot : function.GetFrameSlots()) { cursor += slot.size; @@ -135,16 +40,36 @@ void RunFrameLowering(MachineModule& module) { } function.SetFrameSize(AlignTo(cursor, 16)); - auto& insts = function.GetEntry().GetInstructions(); - std::vector lowered; - lowered.emplace_back(Opcode::Prologue); - for (const auto& inst : insts) { - if (inst.GetOpcode() == Opcode::Ret) { - lowered.emplace_back(Opcode::Epilogue); + // 基本块 + const auto& blocks = function.GetBasicBlocks(); + + for (const auto& bb : blocks) { + DEBUG_MSG("block"); + auto& insts = bb->GetInstructions(); + std::vector lowered; + DEBUG_MSG("empalace Prologue"); + lowered.emplace_back(Opcode::Prologue); + // 输出基本块中的指令 + for (const auto& inst : insts) { + DEBUG_MSG("inst"); + if (inst.GetOpcode() == Opcode::Ret) { + DEBUG_MSG("empalace Epilogue"); + lowered.emplace_back(Opcode::Epilogue); + } + lowered.push_back(inst); } - lowered.push_back(inst); + insts = std::move(lowered); + } +} + +// 模块版本的栈帧布局 +void RunFrameLowering(MachineModule& module) { + // 对模块中的每个函数执行栈帧布局 + DEBUG_MSG("module RunFrameLowering"); + for (auto& func : module.GetFunctions()) { + RunFrameLowering(*func); } - insts = std::move(lowered); -} */ +} } // namespace mir + -- 2.34.1 From f0706adcc025a66b7fbe1cb923980c4c3eacc176 Mon Sep 17 00:00:00 2001 From: mxr <> Date: Thu, 9 Apr 2026 15:18:19 +0800 Subject: [PATCH 07/30] =?UTF-8?q?feat(mir)=E4=BF=AE=E6=94=B9=E5=9F=BA?= =?UTF-8?q?=E6=9C=AC=E5=9D=97=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/mir/AsmPrinter.cpp | 3 ++- src/mir/Lowering.cpp | 15 +++++++++++++-- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/mir/AsmPrinter.cpp b/src/mir/AsmPrinter.cpp index 350a3b4..3ea7d37 100644 --- a/src/mir/AsmPrinter.cpp +++ b/src/mir/AsmPrinter.cpp @@ -5,7 +5,7 @@ #include "utils/Log.h" -#define DEBUG_Asm +//#define DEBUG_Asm #ifdef DEBUG_Asm #include @@ -53,6 +53,7 @@ void PrintOperand(std::ostream& os, const Operand& op) { os << CondCodeName(op.GetCondCode()); break; case Operand::Kind::Label: + DEBUG_MSG("label is" << op.GetLabel()); os << op.GetLabel(); break; } diff --git a/src/mir/Lowering.cpp b/src/mir/Lowering.cpp index 7098107..4d6f513 100644 --- a/src/mir/Lowering.cpp +++ b/src/mir/Lowering.cpp @@ -6,6 +6,14 @@ #include "ir/IR.h" #include "utils/Log.h" +#define DEBUG_Lower + +#ifdef DEBUG_Lower +#include +#define DEBUG_MSG(msg) std::cerr << "[Lower Debug] " << msg << std::endl +#else +#define DEBUG_MSG(msg) +#endif namespace mir { namespace { @@ -392,7 +400,8 @@ void LowerInstruction(const ir::Instruction& inst, MachineFunction& function, // 无条件跳转: br label %target const ir::BasicBlock* irTarget = br.GetTarget(); std::string targetLabel = GetBlockLabel(irTarget); - + DEBUG_MSG("br: targetLabel is " << GetBlockLabel(irTarget)); + // 生成 B target_label block.Append(Opcode::B, {Operand::Label(targetLabel)}); } @@ -646,8 +655,10 @@ std::unique_ptr LowerFunction(const ir::Function& func) { std::unordered_map blockMap; // 第一遍:为每个 IR 基本块创建 MIR 基本块 + std::string func_name = func.GetName(); for (const auto& bb : func.GetBlocks()) { - auto mirBB = std::make_unique(bb->GetName()); + // 格式: .L函数名_基本块名 + auto mirBB = std::make_unique(".L" + func_name + "_" + bb->GetName()); blockMap[bb.get()] = mirBB.get(); machine_func->AddBasicBlock(std::move(mirBB)); } -- 2.34.1 From 4f4842ae3aae0dfa44b9e956690b4a2e1c9f2f5e Mon Sep 17 00:00:00 2001 From: mxr <> Date: Thu, 9 Apr 2026 16:05:38 +0800 Subject: [PATCH 08/30] =?UTF-8?q?feat(mir)=E4=BF=AE=E5=A4=8D=E5=87=BD?= =?UTF-8?q?=E6=95=B0=E5=BA=8F=E8=A8=80=E6=8F=92=E5=85=A5=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/mir/FrameLowering.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/mir/FrameLowering.cpp b/src/mir/FrameLowering.cpp index 62d7ccb..53c256a 100644 --- a/src/mir/FrameLowering.cpp +++ b/src/mir/FrameLowering.cpp @@ -42,13 +42,19 @@ void RunFrameLowering(MachineFunction& function) { // 基本块 const auto& blocks = function.GetBasicBlocks(); - + bool firstBlock = true; + for (const auto& bb : blocks) { DEBUG_MSG("block"); auto& insts = bb->GetInstructions(); std::vector lowered; - DEBUG_MSG("empalace Prologue"); - lowered.emplace_back(Opcode::Prologue); + // 输出基本块标签(非第一个基本块) + if (firstBlock) { + DEBUG_MSG("empalace Prologue"); + lowered.emplace_back(Opcode::Prologue); + } + firstBlock = false; + // 输出基本块中的指令 for (const auto& inst : insts) { DEBUG_MSG("inst"); -- 2.34.1 From 9c9f5a2013fceb98fa4e0b6f37eb0504ee014c5a Mon Sep 17 00:00:00 2001 From: mxr <> Date: Thu, 9 Apr 2026 16:23:09 +0800 Subject: [PATCH 09/30] =?UTF-8?q?feat(mir)=E8=B0=83=E8=AF=95=E6=8E=A7?= =?UTF-8?q?=E5=88=B6=E6=B5=81=E7=94=9F=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/mir/MIR.h | 1 + src/mir/AsmPrinter.cpp | 9 +++------ src/mir/Lowering.cpp | 40 ++++++++++++++++++++++++++++++---------- 3 files changed, 34 insertions(+), 16 deletions(-) diff --git a/include/mir/MIR.h b/include/mir/MIR.h index f44df47..ff1ce75 100644 --- a/include/mir/MIR.h +++ b/include/mir/MIR.h @@ -129,6 +129,7 @@ enum class Opcode { // ---------- 特殊 ---------- Nop, // 空操作: NOP + Label, // 内联标签,不生成实际指令,仅输出标签名 }; // ========== 操作数类 ========== diff --git a/src/mir/AsmPrinter.cpp b/src/mir/AsmPrinter.cpp index 3ea7d37..3c6ca93 100644 --- a/src/mir/AsmPrinter.cpp +++ b/src/mir/AsmPrinter.cpp @@ -31,12 +31,6 @@ void PrintStackAccess(std::ostream& os, const char* mnemonic, PhysReg reg, << "]\n"; } -void PrintStackPairAccess(std::ostream& os, const char* mnemonic, PhysReg reg0, PhysReg reg1, - int offset) { - os << " " << mnemonic << " " << PhysRegName(reg0) << ", " << PhysRegName(reg1) << ", [x29, #" << offset - << "]\n"; -} - // 打印单个操作数 void PrintOperand(std::ostream& os, const Operand& op) { switch (op.GetKind()) { @@ -248,6 +242,9 @@ void PrintInstruction(std::ostream& os, const MachineInstr& instr, case Opcode::Nop: os << " nop\n"; break; + case Opcode::Label: + os << ops.at(0).GetLabel() << ":\n"; + break; default: os << " // unknown instruction\n"; break; diff --git a/src/mir/Lowering.cpp b/src/mir/Lowering.cpp index 4d6f513..dfdbd6d 100644 --- a/src/mir/Lowering.cpp +++ b/src/mir/Lowering.cpp @@ -341,14 +341,19 @@ void LowerInstruction(const ir::Instruction& inst, MachineFunction& function, std::string true_label = ".L_cset_true_" + std::to_string(reinterpret_cast(&icmp)); std::string end_label = ".L_cset_end_" + std::to_string(reinterpret_cast(&icmp)); - // 条件跳转到 true_label - block.Append(Opcode::BCond, {Operand::Cond(cc), Operand::Imm(0)}); - // 条件不成立:W8 = 0 + // 设置条件成立时的值(1) + block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::W8), Operand::Imm(1)}); + // 条件成立时跳转到 true_label + block.Append(Opcode::BCond, {Operand::Cond(cc), Operand::Label(true_label)}); + // 条件不成立:设置 W8 = 0 block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::W8), Operand::Imm(0)}); - block.Append(Opcode::B, {Operand::Imm(0)}); // 跳转到 end_label - // true_label: W8 = 1(已经在上面设置了) - // end_label: 继续 - + // 跳转到 end_label + block.Append(Opcode::B, {Operand::Label(end_label)}); + // true_label: 值已经是 1,直接落入 end_label + block.Append(Opcode::Label, {Operand::Label(true_label)}); + // end_label: 存储结果 + block.Append(Opcode::Label, {Operand::Label(end_label)}); + block.Append(Opcode::StoreStack, {Operand::Reg(PhysReg::W8), Operand::FrameIndex(dst_slot)}); slots.emplace(&inst, dst_slot); @@ -375,13 +380,26 @@ void LowerInstruction(const ir::Instruction& inst, MachineFunction& function, } // ========== 跳转指令(使用标签操作数)========== case ir::Opcode::Br: { + DEBUG_MSG("Processing Br"); auto& br = static_cast(inst); - + + auto* cond = br.GetCondition(); + DEBUG_MSG("Condition value ptr: " << cond); + DEBUG_MSG("Condition name: " << cond->GetName()); + auto it = slots.find(cond); + if (it == slots.end()) { + DEBUG_MSG("Condition not found in slots!"); + // 输出所有 slots 的键名 + for (auto& p : slots) { + DEBUG_MSG(" Slot key: " << p.first->GetName()); + } + } + if (br.IsConditional()) { // 条件跳转: br i1 %cond, label %then, label %else // 加载条件值到 w8 EmitValueToReg(br.GetCondition(), PhysReg::W8, slots, block, function); - + // 比较条件值是否为 0 block.Append(Opcode::CmpRI, {Operand::Reg(PhysReg::W8), Operand::Imm(0)}); @@ -396,11 +414,13 @@ void LowerInstruction(const ir::Instruction& inst, MachineFunction& function, block.Append(Opcode::BCond, {Operand::Cond(CondCode::NE), Operand::Label(trueLabel)}); // 生成 B false_label block.Append(Opcode::B, {Operand::Label(falseLabel)}); + DEBUG_MSG("Generating conditional branch: cond=" << br.GetCondition()->GetName() + << ", true=" << trueLabel << ", false=" << falseLabel); } else { // 无条件跳转: br label %target const ir::BasicBlock* irTarget = br.GetTarget(); std::string targetLabel = GetBlockLabel(irTarget); - DEBUG_MSG("br: targetLabel is " << GetBlockLabel(irTarget)); + DEBUG_MSG("b: targetLabel is " << GetBlockLabel(irTarget)); // 生成 B target_label block.Append(Opcode::B, {Operand::Label(targetLabel)}); -- 2.34.1 From bf21e9c437df81f52d3c034f9f2189a9b6b4a36d Mon Sep 17 00:00:00 2001 From: ftt <> Date: Thu, 9 Apr 2026 16:29:24 +0800 Subject: [PATCH 10/30] =?UTF-8?q?=E5=A4=84=E7=90=86=E6=B5=AE=E7=82=B9?= =?UTF-8?q?=E5=B8=B8=E9=87=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/mir/Lowering.cpp | 33 ++++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/src/mir/Lowering.cpp b/src/mir/Lowering.cpp index 4d6f513..73b37e9 100644 --- a/src/mir/Lowering.cpp +++ b/src/mir/Lowering.cpp @@ -2,6 +2,7 @@ #include #include +#include #include "ir/IR.h" #include "utils/Log.h" @@ -20,6 +21,12 @@ namespace { using ValueSlotMap = std::unordered_map; +static uint32_t FloatToBits(float f) { + uint32_t bits; + memcpy(&bits, &f, sizeof(bits)); + return bits; +} + // 获取类型大小(字节) int GetTypeSize(const ir::Type* type) { if (!type) return 4; @@ -109,15 +116,23 @@ void EmitValueToReg(const ir::Value* value, PhysReg target, } // 处理浮点常量 if (auto* fconstant = dynamic_cast(value)) { - // 浮点常量需要先存储到栈槽,再加载到寄存器 - // 因为 ARMv8 没有直接加载浮点立即数的指令 - int slot = -1; - // 注意:这里需要找到或创建该浮点常量的栈槽 - // 简单起见,可以每次都分配新栈槽 - // 更好的做法是:在 Module 级别缓存浮点常量 - throw std::runtime_error( - FormatError("mir", "浮点常量暂未实现")); - return; + // 浮点常量需要存储到栈槽,然后加载到寄存器 + // 检查是否已经为这个常量分配了栈槽 + auto it = slots.find(value); + int slot; + if (it == slots.end()) { + // 分配新的栈槽 + slot = function.CreateFrameIndex(4); + // 将浮点常量存储到栈槽 + float fval = fconstant->GetValue(); + // 将浮点数作为立即数加载(使用整数表示) + uint32_t int_val = *reinterpret_cast(&fval); + block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::W8), Operand::Imm(static_cast(int_val))}); + block.Append(Opcode::StoreStack, {Operand::Reg(PhysReg::W8), Operand::FrameIndex(slot)}); + const_cast(slots).emplace(value, slot); + } else { + slot = it->second; + } } // 处理零常量 if (dynamic_cast(value) || -- 2.34.1 From 7d8ee45a42914958ad4d76db5990a29874fc6a2f Mon Sep 17 00:00:00 2001 From: ftt <> Date: Thu, 9 Apr 2026 20:44:24 +0800 Subject: [PATCH 11/30] =?UTF-8?q?=E5=80=BC=E5=AF=B9=E5=BA=94=E6=A0=88?= =?UTF-8?q?=E6=A7=BD=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/mir/Lowering.cpp | 357 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 294 insertions(+), 63 deletions(-) diff --git a/src/mir/Lowering.cpp b/src/mir/Lowering.cpp index 9151f48..9945c1e 100644 --- a/src/mir/Lowering.cpp +++ b/src/mir/Lowering.cpp @@ -105,6 +105,22 @@ static std::vector GetArrayStrides(const ir::ArrayType* arrayType) { return strides; } +// 在 Lowering.cpp 中添加辅助函数 +const ir::Value* GetOperand(const ir::Instruction& inst, size_t index) { + if (index < inst.GetNumOperands()) { + return inst.GetOperand(index); + } + return nullptr; +} + +const ir::BasicBlock* GetBasicBlockOperand(const ir::Instruction& inst, size_t index) { + const ir::Value* operand = GetOperand(inst, index); + if (operand) { + return dynamic_cast(operand); + } + return nullptr; +} + void EmitValueToReg(const ir::Value* value, PhysReg target, const ValueSlotMap& slots, MachineBasicBlock& block, MachineFunction& function) { @@ -116,23 +132,52 @@ void EmitValueToReg(const ir::Value* value, PhysReg target, } // 处理浮点常量 if (auto* fconstant = dynamic_cast(value)) { - // 浮点常量需要存储到栈槽,然后加载到寄存器 // 检查是否已经为这个常量分配了栈槽 auto it = slots.find(value); int slot; if (it == slots.end()) { - // 分配新的栈槽 - slot = function.CreateFrameIndex(4); - // 将浮点常量存储到栈槽 - float fval = fconstant->GetValue(); - // 将浮点数作为立即数加载(使用整数表示) - uint32_t int_val = *reinterpret_cast(&fval); - block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::W8), Operand::Imm(static_cast(int_val))}); - block.Append(Opcode::StoreStack, {Operand::Reg(PhysReg::W8), Operand::FrameIndex(slot)}); - const_cast(slots).emplace(value, slot); + DEBUG_MSG("Value not found: " << value->GetName()); + // 输出所有 slots 的键名用于调试 + for (auto& p : slots) { + DEBUG_MSG(" Slot key: " << p.first->GetName()); + } + // 分配新的栈槽 + slot = function.CreateFrameIndex(4); + // 将浮点常量存储到栈槽 + float fval = fconstant->GetValue(); + uint32_t int_val = FloatToBits(fval); + + // 使用临时寄存器加载常量并存储 + block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::W8), Operand::Imm(static_cast(int_val))}); + block.Append(Opcode::StoreStack, {Operand::Reg(PhysReg::W8), Operand::FrameIndex(slot)}); + const_cast(slots).emplace(value, slot); } else { - slot = it->second; + slot = it->second; } + + // 从栈槽加载到目标寄存器 + block.Append(Opcode::LoadStack, {Operand::Reg(target), Operand::FrameIndex(slot)}); + return; + } + // 处理全局变量 + if (auto* global = dynamic_cast(value)) { + // 全局变量:需要加载其地址 + // 在 ARM64 中,使用 ADRP + ADD 指令获取全局变量地址 + // 简化版本:先为全局变量分配一个栈槽,然后加载地址到该栈槽 + + // 检查是否已经为这个全局变量分配了栈槽 + auto it = slots.find(value); + if (it == slots.end()) { + // 为全局变量创建栈槽 + const_cast(slots).emplace(value, + const_cast(function).CreateFrameIndex(8)); + it = slots.find(value); + } + + // 从栈槽加载地址到目标寄存器 + block.Append(Opcode::LoadStack, + {Operand::Reg(target), Operand::FrameIndex(it->second)}); + return; } // 处理零常量 if (dynamic_cast(value) || @@ -145,6 +190,11 @@ void EmitValueToReg(const ir::Value* value, PhysReg target, auto it = slots.find(value); if (it == slots.end()) { + DEBUG_MSG("Value not found: " << value->GetName()); + // 输出所有 slots 的键名用于调试 + for (auto& p : slots) { + DEBUG_MSG(" Slot key: " << p.first->GetName()); + } throw std::runtime_error( FormatError("mir", "找不到值对应的栈槽: " + value->GetName())); } @@ -158,6 +208,8 @@ void LowerInstruction(const ir::Instruction& inst, MachineFunction& function, std::unordered_map& blockMap) { //auto& block = function.GetEntry(); + DEBUG_MSG("Processing instruction: " << inst.GetName() + << " (opcode: " << static_cast(inst.GetOpcode()) << ")"); switch (inst.GetOpcode()) { case ir::Opcode::Alloca: { @@ -333,42 +385,25 @@ void LowerInstruction(const ir::Instruction& inst, MachineFunction& function, auto& icmp = static_cast(inst); int dst_slot = function.CreateFrameIndex(GetTypeSize(inst.GetType().get())); - // 加载左右操作数到 w8, w9 EmitValueToReg(icmp.GetLhs(), PhysReg::W8, slots, block, function); EmitValueToReg(icmp.GetRhs(), PhysReg::W9, slots, block, function); - // 生成比较指令 block.Append(Opcode::CmpRR, {Operand::Reg(PhysReg::W8), Operand::Reg(PhysReg::W9)}); - - // 使用条件设置指令: CSET W8, cc - // 如果条件成立,W8 = 1;否则 W8 = 0 CondCode cc = IcmpToCondCode(icmp.GetPredicate()); - // 使用 CSET 的替代实现:条件移动 - // MOV W8, #1 - // MOV W9, #0 - // CSEL W8, W8, W9, cc + // 使用 CSET 模式 block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::W8), Operand::Imm(1)}); block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::W9), Operand::Imm(0)}); - // TODO: 需要添加 CSEL 指令,暂时使用条件跳转 - // 创建临时标签 std::string true_label = ".L_cset_true_" + std::to_string(reinterpret_cast(&icmp)); std::string end_label = ".L_cset_end_" + std::to_string(reinterpret_cast(&icmp)); - // 设置条件成立时的值(1) - block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::W8), Operand::Imm(1)}); - // 条件成立时跳转到 true_label block.Append(Opcode::BCond, {Operand::Cond(cc), Operand::Label(true_label)}); - // 条件不成立:设置 W8 = 0 - block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::W8), Operand::Imm(0)}); - // 跳转到 end_label + block.Append(Opcode::MovReg, {Operand::Reg(PhysReg::W8), Operand::Reg(PhysReg::W9)}); block.Append(Opcode::B, {Operand::Label(end_label)}); - // true_label: 值已经是 1,直接落入 end_label block.Append(Opcode::Label, {Operand::Label(true_label)}); - // end_label: 存储结果 block.Append(Opcode::Label, {Operand::Label(end_label)}); - + block.Append(Opcode::StoreStack, {Operand::Reg(PhysReg::W8), Operand::FrameIndex(dst_slot)}); slots.emplace(&inst, dst_slot); @@ -661,8 +696,199 @@ void LowerInstruction(const ir::Instruction& inst, MachineFunction& function, slots.emplace(&inst, dst_slot); return; } - //throw std::runtime_error(FormatError("mir", "暂不支持该 IR 指令")); - throw std::runtime_error(FormatError("mir", "暂不支持该 IR 指令,opcode: " + // 处理 Trunc 指令 + case ir::Opcode::Trunc: { + auto& inst_ref = static_cast(inst); + int dst_slot = function.CreateFrameIndex(GetTypeSize(inst.GetType().get())); + + // 假设 Trunc 指令有 GetValue() 方法 + // 如果没有,需要通过操作数列表获取 + const ir::Value* src_val = nullptr; + if (inst.GetNumOperands() > 0) { + src_val = inst.GetOperand(0); + } + if (src_val) { + EmitValueToReg(src_val, PhysReg::W8, slots, block, function); + } + + block.Append(Opcode::StoreStack, + {Operand::Reg(PhysReg::W8), Operand::FrameIndex(dst_slot)}); + slots.emplace(&inst, dst_slot); + return; + } + // 处理 Mod 指令 + case ir::Opcode::Mod: { + int dst_slot = function.CreateFrameIndex(GetTypeSize(inst.GetType().get())); + + // 通过操作数获取左右值 + const ir::Value* lhs = nullptr; + const ir::Value* rhs = nullptr; + if (inst.GetNumOperands() >= 2) { + lhs = inst.GetOperand(0); + rhs = inst.GetOperand(1); + } + + if (lhs && rhs) { + EmitValueToReg(lhs, PhysReg::W8, slots, block, function); + EmitValueToReg(rhs, PhysReg::W9, slots, block, function); + + // a % b = a - (a / b) * b + block.Append(Opcode::SDivRR, {Operand::Reg(PhysReg::W10), + Operand::Reg(PhysReg::W8), + Operand::Reg(PhysReg::W9)}); + block.Append(Opcode::MulRR, {Operand::Reg(PhysReg::W10), + Operand::Reg(PhysReg::W10), + Operand::Reg(PhysReg::W9)}); + block.Append(Opcode::SubRR, {Operand::Reg(PhysReg::W8), + Operand::Reg(PhysReg::W8), + Operand::Reg(PhysReg::W10)}); + } + + block.Append(Opcode::StoreStack, + {Operand::Reg(PhysReg::W8), Operand::FrameIndex(dst_slot)}); + slots.emplace(&inst, dst_slot); + return; + } + // 处理 And 指令 + case ir::Opcode::And: { + int dst_slot = function.CreateFrameIndex(GetTypeSize(inst.GetType().get())); + + const ir::Value* lhs = nullptr; + const ir::Value* rhs = nullptr; + if (inst.GetNumOperands() >= 2) { + lhs = inst.GetOperand(0); + rhs = inst.GetOperand(1); + } + + if (lhs && rhs) { + EmitValueToReg(lhs, PhysReg::W8, slots, block, function); + EmitValueToReg(rhs, PhysReg::W9, slots, block, function); + block.Append(Opcode::AndRR, {Operand::Reg(PhysReg::W8), + Operand::Reg(PhysReg::W8), + Operand::Reg(PhysReg::W9)}); + } + + block.Append(Opcode::StoreStack, + {Operand::Reg(PhysReg::W8), Operand::FrameIndex(dst_slot)}); + slots.emplace(&inst, dst_slot); + return; + } + // 处理 Or 指令 + case ir::Opcode::Or: { + int dst_slot = function.CreateFrameIndex(GetTypeSize(inst.GetType().get())); + + const ir::Value* lhs = nullptr; + const ir::Value* rhs = nullptr; + if (inst.GetNumOperands() >= 2) { + lhs = inst.GetOperand(0); + rhs = inst.GetOperand(1); + } + + if (lhs && rhs) { + EmitValueToReg(lhs, PhysReg::W8, slots, block, function); + EmitValueToReg(rhs, PhysReg::W9, slots, block, function); + block.Append(Opcode::OrRR, {Operand::Reg(PhysReg::W8), + Operand::Reg(PhysReg::W8), + Operand::Reg(PhysReg::W9)}); + } + + block.Append(Opcode::StoreStack, + {Operand::Reg(PhysReg::W8), Operand::FrameIndex(dst_slot)}); + slots.emplace(&inst, dst_slot); + return; + } + // 处理 Not 指令 + case ir::Opcode::Not: { + int dst_slot = function.CreateFrameIndex(GetTypeSize(inst.GetType().get())); + + const ir::Value* src_val = nullptr; + if (inst.GetNumOperands() > 0) { + src_val = inst.GetOperand(0); + } + + if (src_val) { + EmitValueToReg(src_val, PhysReg::W8, slots, block, function); + // NOT = XOR with -1 + block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::W9), Operand::Imm(-1)}); + block.Append(Opcode::EorRR, {Operand::Reg(PhysReg::W8), + Operand::Reg(PhysReg::W8), + Operand::Reg(PhysReg::W9)}); + } + + block.Append(Opcode::StoreStack, + {Operand::Reg(PhysReg::W8), Operand::FrameIndex(dst_slot)}); + slots.emplace(&inst, dst_slot); + return; + } + // 处理 CondBr 指令 + case ir::Opcode::CondBr: { + // CondBr 通常有两个目标基本块和一个条件 + const ir::Value* condition = nullptr; + const ir::BasicBlock* trueTarget = nullptr; + const ir::BasicBlock* falseTarget = nullptr; + + if (inst.GetNumOperands() >= 3) { + condition = inst.GetOperand(0); + // 操作数1和2应该是 BasicBlock 引用 + // 具体获取方式取决于你的 IR 实现 + if (auto* bb = dynamic_cast(inst.GetOperand(1))) { + trueTarget = bb; + } + if (auto* bb = dynamic_cast(inst.GetOperand(2))) { + falseTarget = bb; + } + } + + if (condition && trueTarget && falseTarget) { + EmitValueToReg(condition, PhysReg::W8, slots, block, function); + block.Append(Opcode::CmpRI, {Operand::Reg(PhysReg::W8), Operand::Imm(0)}); + + std::string trueLabel = GetBlockLabel(trueTarget); + std::string falseLabel = GetBlockLabel(falseTarget); + + block.Append(Opcode::BCond, {Operand::Cond(CondCode::NE), Operand::Label(trueLabel)}); + block.Append(Opcode::B, {Operand::Label(falseLabel)}); + } + return; + } + // 处理 FPExt(浮点扩展) + case ir::Opcode::FPExt: { + int dst_slot = function.CreateFrameIndex(GetTypeSize(inst.GetType().get())); + + const ir::Value* src_val = nullptr; + if (inst.GetNumOperands() > 0) { + src_val = inst.GetOperand(0); + } + + if (src_val) { + EmitValueToReg(src_val, PhysReg::S0, slots, block, function); + } + + block.Append(Opcode::StoreStack, + {Operand::Reg(PhysReg::S0), Operand::FrameIndex(dst_slot)}); + slots.emplace(&inst, dst_slot); + return; + } + // 处理 FPTrunc(浮点截断) + case ir::Opcode::FPTrunc: { + int dst_slot = function.CreateFrameIndex(GetTypeSize(inst.GetType().get())); + + const ir::Value* src_val = nullptr; + if (inst.GetNumOperands() > 0) { + src_val = inst.GetOperand(0); + } + + if (src_val) { + EmitValueToReg(src_val, PhysReg::S0, slots, block, function); + } + + block.Append(Opcode::StoreStack, + {Operand::Reg(PhysReg::S0), Operand::FrameIndex(dst_slot)}); + slots.emplace(&inst, dst_slot); + return; + } + //throw std::runtime_error(FormatError("mir", "暂不支持该 IR 指令")); + throw std::runtime_error(FormatError("mir", "暂不支持该 IR 指令,opcode: " + std::to_string(static_cast(inst.GetOpcode())))); } } @@ -673,17 +899,21 @@ void LowerInstruction(const ir::Instruction& inst, MachineFunction& function, std::unique_ptr LowerFunction(const ir::Function& func) { auto machine_func = std::make_unique(func.GetName()); ValueSlotMap slots; + + // 存储参数信息,稍后处理 + struct ParamInfo { + const ir::Value* arg; + int slot; + bool isFloat; + }; + std::vector paramInfos; // 为函数参数分配栈槽 for (const auto& arg : func.GetArguments()) { - // 为每个参数分配栈槽 int slot = machine_func->CreateFrameIndex(GetTypeSize(arg->GetType().get())); slots.emplace(arg.get(), slot); - - // 注意:参数的值需要从寄存器加载到栈槽 - // 在 ARM64 调用约定中,前 8 个整数参数在 w0-w7,前 8 个浮点参数在 s0-s7 - // 这里需要生成指令将参数从寄存器存储到栈槽 - // 但 MachineFunction 还没有基本块,所以需要延迟处理 + bool isFloat = arg->GetType()->IsFloat(); + paramInfos.push_back({arg.get(), slot, isFloat}); } // IR 基本块到 MIR 基本块的映射 @@ -702,32 +932,26 @@ std::unique_ptr LowerFunction(const ir::Function& func) { if (!func.GetBlocks().empty()) { MachineBasicBlock* entryBB = blockMap[func.GetEntry()]; if (entryBB) { - // 为每个参数生成从寄存器到栈槽的存储指令 - size_t intArgIdx = 0; - size_t fpArgIdx = 0; - - for (const auto& arg : func.GetArguments()) { - int slot = slots[arg.get()]; - const ir::Type* argType = arg->GetType().get(); + size_t intArgIdx = 0; + size_t fpArgIdx = 0; - if (argType->IsFloat()) { - // 浮点参数从 s0, s1, ... 读取 - if (fpArgIdx < 8) { - PhysReg reg = static_cast(static_cast(PhysReg::S0) + fpArgIdx); - entryBB->Append(Opcode::StoreStack, - {Operand::Reg(reg), Operand::FrameIndex(slot)}); - } - fpArgIdx++; - } else { - // 整数参数从 w0, w1, ... 读取 - if (intArgIdx < 8) { - PhysReg reg = static_cast(static_cast(PhysReg::W0) + intArgIdx); - entryBB->Append(Opcode::StoreStack, - {Operand::Reg(reg), Operand::FrameIndex(slot)}); - } - intArgIdx++; + for (const auto& param : paramInfos) { + if (param.isFloat) { + if (fpArgIdx < 8) { + PhysReg reg = static_cast(static_cast(PhysReg::S0) + fpArgIdx); + entryBB->Append(Opcode::StoreStack, + {Operand::Reg(reg), Operand::FrameIndex(param.slot)}); + } + fpArgIdx++; + } else { + if (intArgIdx < 8) { + PhysReg reg = static_cast(static_cast(PhysReg::W0) + intArgIdx); + entryBB->Append(Opcode::StoreStack, + {Operand::Reg(reg), Operand::FrameIndex(param.slot)}); + } + intArgIdx++; + } } - } } } @@ -750,6 +974,13 @@ std::unique_ptr LowerToMIR(const ir::Module& module) { DefaultContext(); auto machine_module = std::make_unique(); + + // 处理全局变量 + for (const auto& global : module.GetGlobals()) { + // 为全局变量在数据段分配空间 + // 这里需要扩展 MachineModule 来支持全局变量 + DEBUG_MSG("Global variable: " << global->GetName()); + } // 遍历模块中的所有函数 for (const auto& func : module.GetFunctions()) { -- 2.34.1 From 8b4ffdde442e243fd07bfb440c31fcb9ab03db80 Mon Sep 17 00:00:00 2001 From: ftt <> Date: Thu, 9 Apr 2026 22:01:57 +0800 Subject: [PATCH 12/30] =?UTF-8?q?=E4=BF=AE=E6=94=B9condbr?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/mir/AsmPrinter.cpp | 56 +++++++++++----- src/mir/FrameLowering.cpp | 7 +- src/mir/Lowering.cpp | 136 +++++++++++++++----------------------- 3 files changed, 97 insertions(+), 102 deletions(-) diff --git a/src/mir/AsmPrinter.cpp b/src/mir/AsmPrinter.cpp index 3c6ca93..6d8ca3c 100644 --- a/src/mir/AsmPrinter.cpp +++ b/src/mir/AsmPrinter.cpp @@ -27,8 +27,10 @@ const FrameSlot& GetFrameSlot(const MachineFunction& function, void PrintStackAccess(std::ostream& os, const char* mnemonic, PhysReg reg, int offset) { - os << " " << mnemonic << " " << PhysRegName(reg) << ", [x29, #" << offset - << "]\n"; + //os << " " << mnemonic << " " << PhysRegName(reg) << ", [x29, #" << offset + // << "]\n"; + // 使用 sp 相对寻址 + os << " " << mnemonic << " " << PhysRegName(reg) << ", [sp, #" << offset << "]\n"; } // 打印单个操作数 @@ -59,14 +61,14 @@ void PrintInstruction(std::ostream& os, const MachineInstr& instr, const auto& ops = instr.GetOperands(); switch (instr.GetOpcode()) { - case Opcode::Prologue: - os << " stp x29, x30, [sp, #-16]!\n"; - os << " mov x29, sp\n"; - if (function.GetFrameSize() > 0) { - os << " sub sp, sp, #" << function.GetFrameSize() << "\n"; - } - break; - case Opcode::Epilogue: + case Opcode::Prologue: + os << " stp x29, x30, [sp, #-16]!\n"; + os << " mov x29, sp\n"; + if (function.GetFrameSize() > 0) { + os << " sub sp, sp, #" << function.GetFrameSize() << "\n"; + } + break; + case Opcode::Epilogue: if (function.GetFrameSize() > 0) { os << " add sp, sp, #" << function.GetFrameSize() << "\n"; } @@ -80,14 +82,36 @@ void PrintInstruction(std::ostream& os, const MachineInstr& instr, os << " mov " << PhysRegName(ops.at(0).GetReg()) << ", " << PhysRegName(ops.at(1).GetReg()) << "\n"; break; - case Opcode::LoadStack: { - const auto& slot = GetFrameSlot(function, ops.at(1)); - PrintStackAccess(os, "ldur", ops.at(0).GetReg(), slot.offset); + case Opcode::StoreStack: { + // 检查第二个操作数的类型 + if (ops.size() >= 2 && ops.at(1).GetKind() == Operand::Kind::FrameIndex) { + // 存储到栈槽 + const auto& slot = GetFrameSlot(function, ops.at(1)); + PrintStackAccess(os, "stur", ops.at(0).GetReg(), slot.offset); + } else if (ops.size() >= 2 && ops.at(1).GetKind() == Operand::Kind::Reg) { + // 间接存储:存储到寄存器指向的地址 + // STR W9, [X8] + os << " str " << PhysRegName(ops.at(0).GetReg()) << ", [" + << PhysRegName(ops.at(1).GetReg()) << "]\n"; + } else { + throw std::runtime_error("StoreStack: 无效的操作数类型"); + } break; } - case Opcode::StoreStack: { - const auto& slot = GetFrameSlot(function, ops.at(1)); - PrintStackAccess(os, "stur", ops.at(0).GetReg(), slot.offset); + case Opcode::LoadStack: { + // 检查第二个操作数的类型 + if (ops.size() >= 2 && ops.at(1).GetKind() == Operand::Kind::FrameIndex) { + // 从栈槽加载 + const auto& slot = GetFrameSlot(function, ops.at(1)); + PrintStackAccess(os, "ldur", ops.at(0).GetReg(), slot.offset); + } else if (ops.size() >= 2 && ops.at(1).GetKind() == Operand::Kind::Reg) { + // 间接加载:从寄存器指向的地址加载 + // LDR W9, [X8] + os << " ldr " << PhysRegName(ops.at(0).GetReg()) << ", [" + << PhysRegName(ops.at(1).GetReg()) << "]\n"; + } else { + throw std::runtime_error("LoadStack: 无效的操作数类型"); + } break; } case Opcode::StoreStackPair: diff --git a/src/mir/FrameLowering.cpp b/src/mir/FrameLowering.cpp index 53c256a..b9fa84e 100644 --- a/src/mir/FrameLowering.cpp +++ b/src/mir/FrameLowering.cpp @@ -27,12 +27,14 @@ void RunFrameLowering(MachineFunction& function) { DEBUG_MSG("function RunFrameLowering"); int cursor = 0; for (const auto& slot : function.GetFrameSlots()) { + //cursor += slot.size; + // 使用正偏移,从 sp 开始 + function.GetFrameSlot(slot.index).offset = cursor; cursor += slot.size; if (-cursor < -256) { throw std::runtime_error(FormatError("mir", "暂不支持过大的栈帧")); } } - cursor = 0; for (const auto& slot : function.GetFrameSlots()) { cursor += slot.size; @@ -77,5 +79,4 @@ void RunFrameLowering(MachineModule& module) { } } -} // namespace mir - +} // namespace mir \ No newline at end of file diff --git a/src/mir/Lowering.cpp b/src/mir/Lowering.cpp index 9945c1e..3365385 100644 --- a/src/mir/Lowering.cpp +++ b/src/mir/Lowering.cpp @@ -178,7 +178,7 @@ void EmitValueToReg(const ir::Value* value, PhysReg target, block.Append(Opcode::LoadStack, {Operand::Reg(target), Operand::FrameIndex(it->second)}); return; - } + } // 处理零常量 if (dynamic_cast(value) || dynamic_cast(value)) { @@ -190,13 +190,22 @@ void EmitValueToReg(const ir::Value* value, PhysReg target, auto it = slots.find(value); if (it == slots.end()) { - DEBUG_MSG("Value not found: " << value->GetName()); + // 使用值的地址作为调试信息 + std::string valueName = value->GetName(); + if (valueName.empty()) { + valueName = "(anonymous at " + std::to_string(reinterpret_cast(value)) + ")"; + } + DEBUG_MSG("Value not found: " << valueName); // 输出所有 slots 的键名用于调试 for (auto& p : slots) { - DEBUG_MSG(" Slot key: " << p.first->GetName()); + std::string slotName = p.first->GetName(); + if (slotName.empty()) { + slotName = "(anonymous at " + std::to_string(reinterpret_cast(p.first)) + ")"; + } + DEBUG_MSG(" Slot key: " << slotName); } throw std::runtime_error( - FormatError("mir", "找不到值对应的栈槽: " + value->GetName())); + FormatError("mir", "找不到值对应的栈槽: " + valueName)); } block.Append(Opcode::LoadStack, @@ -222,9 +231,6 @@ void LowerInstruction(const ir::Instruction& inst, MachineFunction& function, if (dst == slots.end()) { //throw std::runtime_error( // FormatError("mir", "暂不支持对非栈变量地址进行写入")); - // 对于非栈变量地址(如 GEP 结果),地址本身在栈槽中 - // 需要先加载地址,然后存储值到该地址 - // 先加载地址到 x8 EmitValueToReg(store.GetPtr(), PhysReg::X8, slots, block, function); // 加载值到 w9 EmitValueToReg(store.GetValue(), PhysReg::W9, slots, block, function); @@ -430,52 +436,40 @@ void LowerInstruction(const ir::Instruction& inst, MachineFunction& function, } // ========== 跳转指令(使用标签操作数)========== case ir::Opcode::Br: { - DEBUG_MSG("Processing Br"); - auto& br = static_cast(inst); - - auto* cond = br.GetCondition(); - DEBUG_MSG("Condition value ptr: " << cond); - DEBUG_MSG("Condition name: " << cond->GetName()); - auto it = slots.find(cond); - if (it == slots.end()) { - DEBUG_MSG("Condition not found in slots!"); - // 输出所有 slots 的键名 - for (auto& p : slots) { - DEBUG_MSG(" Slot key: " << p.first->GetName()); - } - } - - if (br.IsConditional()) { - // 条件跳转: br i1 %cond, label %then, label %else - // 加载条件值到 w8 + DEBUG_MSG("Processing Br"); + auto& br = static_cast(inst); + + if (br.IsConditional()) { + // 条件跳转 + EmitValueToReg(br.GetCondition(), PhysReg::W8, slots, block, function); + block.Append(Opcode::CmpRI, {Operand::Reg(PhysReg::W8), Operand::Imm(0)}); + + std::string trueLabel = GetBlockLabel(br.GetTrueTarget()); + std::string falseLabel = GetBlockLabel(br.GetFalseTarget()); + + block.Append(Opcode::BCond, {Operand::Cond(CondCode::NE), Operand::Label(trueLabel)}); + block.Append(Opcode::B, {Operand::Label(falseLabel)}); + } else { + // 无条件跳转 + std::string targetLabel = GetBlockLabel(br.GetTarget()); + block.Append(Opcode::B, {Operand::Label(targetLabel)}); + } + return; + } + case ir::Opcode::CondBr: { + DEBUG_MSG("Processing CondBr"); + auto& br = static_cast(inst); + + // 条件跳转处理 EmitValueToReg(br.GetCondition(), PhysReg::W8, slots, block, function); - - // 比较条件值是否为 0 block.Append(Opcode::CmpRI, {Operand::Reg(PhysReg::W8), Operand::Imm(0)}); - // 获取目标基本块的标签名 - const ir::BasicBlock* irTrueTarget = br.GetTrueTarget(); - const ir::BasicBlock* irFalseTarget = br.GetFalseTarget(); - - std::string trueLabel = GetBlockLabel(irTrueTarget); - std::string falseLabel = GetBlockLabel(irFalseTarget); + std::string trueLabel = GetBlockLabel(br.GetTrueTarget()); + std::string falseLabel = GetBlockLabel(br.GetFalseTarget()); - // 生成 B.NE true_label block.Append(Opcode::BCond, {Operand::Cond(CondCode::NE), Operand::Label(trueLabel)}); - // 生成 B false_label block.Append(Opcode::B, {Operand::Label(falseLabel)}); - DEBUG_MSG("Generating conditional branch: cond=" << br.GetCondition()->GetName() - << ", true=" << trueLabel << ", false=" << falseLabel); - } else { - // 无条件跳转: br label %target - const ir::BasicBlock* irTarget = br.GetTarget(); - std::string targetLabel = GetBlockLabel(irTarget); - DEBUG_MSG("b: targetLabel is " << GetBlockLabel(irTarget)); - - // 生成 B target_label - block.Append(Opcode::B, {Operand::Label(targetLabel)}); - } - return; + return; } // ========== 函数调用 ========== case ir::Opcode::Call: { @@ -512,8 +506,8 @@ void LowerInstruction(const ir::Instruction& inst, MachineFunction& function, } // 生成调用指令 - block.Append(Opcode::Call, {Operand::Imm(0)}); // 实际需要传递函数名 - + //block.Append(Opcode::Call, {Operand::Imm(0)}); // 实际需要传递函数名 + block.Append(Opcode::Call, {Operand::Label(calleeName)}); // 保存返回值 if (dst_slot != -1) { if (inst.GetType()->IsFloat()) { @@ -820,37 +814,6 @@ void LowerInstruction(const ir::Instruction& inst, MachineFunction& function, slots.emplace(&inst, dst_slot); return; } - // 处理 CondBr 指令 - case ir::Opcode::CondBr: { - // CondBr 通常有两个目标基本块和一个条件 - const ir::Value* condition = nullptr; - const ir::BasicBlock* trueTarget = nullptr; - const ir::BasicBlock* falseTarget = nullptr; - - if (inst.GetNumOperands() >= 3) { - condition = inst.GetOperand(0); - // 操作数1和2应该是 BasicBlock 引用 - // 具体获取方式取决于你的 IR 实现 - if (auto* bb = dynamic_cast(inst.GetOperand(1))) { - trueTarget = bb; - } - if (auto* bb = dynamic_cast(inst.GetOperand(2))) { - falseTarget = bb; - } - } - - if (condition && trueTarget && falseTarget) { - EmitValueToReg(condition, PhysReg::W8, slots, block, function); - block.Append(Opcode::CmpRI, {Operand::Reg(PhysReg::W8), Operand::Imm(0)}); - - std::string trueLabel = GetBlockLabel(trueTarget); - std::string falseLabel = GetBlockLabel(falseTarget); - - block.Append(Opcode::BCond, {Operand::Cond(CondCode::NE), Operand::Label(trueLabel)}); - block.Append(Opcode::B, {Operand::Label(falseLabel)}); - } - return; - } // 处理 FPExt(浮点扩展) case ir::Opcode::FPExt: { int dst_slot = function.CreateFrameIndex(GetTypeSize(inst.GetType().get())); @@ -887,9 +850,14 @@ void LowerInstruction(const ir::Instruction& inst, MachineFunction& function, slots.emplace(&inst, dst_slot); return; } + default: + DEBUG_MSG("Unhandled opcode: " << static_cast(inst.GetOpcode()) + << " for instruction: " << inst.GetName()); + throw std::runtime_error(FormatError("mir", "暂不支持该 IR 指令,opcode: " + + std::to_string(static_cast(inst.GetOpcode())))); //throw std::runtime_error(FormatError("mir", "暂不支持该 IR 指令")); - throw std::runtime_error(FormatError("mir", "暂不支持该 IR 指令,opcode: " - + std::to_string(static_cast(inst.GetOpcode())))); + //throw std::runtime_error(FormatError("mir", "暂不支持该 IR 指令,opcode: " + // + std::to_string(static_cast(inst.GetOpcode())))); } } @@ -975,11 +943,13 @@ std::unique_ptr LowerToMIR(const ir::Module& module) { auto machine_module = std::make_unique(); + std::vector globals; // 处理全局变量 for (const auto& global : module.GetGlobals()) { // 为全局变量在数据段分配空间 // 这里需要扩展 MachineModule 来支持全局变量 DEBUG_MSG("Global variable: " << global->GetName()); + globals.push_back(global.get()); } // 遍历模块中的所有函数 @@ -1000,4 +970,4 @@ std::unique_ptr LowerToMIR(const ir::Module& module) { return machine_module; } -} // namespace mir +} // namespace mir \ No newline at end of file -- 2.34.1 From 4f00d05c86127ad0f295ff6cffb6c6520e7ad528 Mon Sep 17 00:00:00 2001 From: mxr <> Date: Fri, 10 Apr 2026 11:02:07 +0800 Subject: [PATCH 13/30] =?UTF-8?q?fix(mir)=E4=BF=AE=E5=A4=8DRet=E8=BF=94?= =?UTF-8?q?=E5=9B=9Evoid=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/mir/AsmPrinter.cpp | 1 - src/mir/FrameLowering.cpp | 2 +- src/mir/Lowering.cpp | 11 ++++++++--- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/mir/AsmPrinter.cpp b/src/mir/AsmPrinter.cpp index 6d8ca3c..4550730 100644 --- a/src/mir/AsmPrinter.cpp +++ b/src/mir/AsmPrinter.cpp @@ -314,7 +314,6 @@ void PrintAsm(const MachineFunction& function, std::ostream& os) { void PrintAsm(const MachineModule& module, std::ostream& os) { // 输出文件头 os << ".arch armv8-a\n"; - os << ".text\n"; DEBUG_MSG("module"); // 遍历所有函数,输出汇编 diff --git a/src/mir/FrameLowering.cpp b/src/mir/FrameLowering.cpp index b9fa84e..6758105 100644 --- a/src/mir/FrameLowering.cpp +++ b/src/mir/FrameLowering.cpp @@ -5,7 +5,7 @@ #include "utils/Log.h" -#define DEBUG_Frame +//#define DEBUG_Frame #ifdef DEBUG_Frame #include diff --git a/src/mir/Lowering.cpp b/src/mir/Lowering.cpp index 3365385..013aa26 100644 --- a/src/mir/Lowering.cpp +++ b/src/mir/Lowering.cpp @@ -7,7 +7,7 @@ #include "ir/IR.h" #include "utils/Log.h" -#define DEBUG_Lower +//#define DEBUG_Lower #ifdef DEBUG_Lower #include @@ -125,6 +125,9 @@ void EmitValueToReg(const ir::Value* value, PhysReg target, const ValueSlotMap& slots, MachineBasicBlock& block, MachineFunction& function) { // 处理整数常量 + if (value == nullptr) { + DEBUG_MSG( "EmitValueToReg called with null value\n"); + } if (auto* constant = dynamic_cast(value)) { block.Append(Opcode::MovImm, {Operand::Reg(target), Operand::Imm(constant->GetValue())}); @@ -219,7 +222,6 @@ void LowerInstruction(const ir::Instruction& inst, MachineFunction& function, //auto& block = function.GetEntry(); DEBUG_MSG("Processing instruction: " << inst.GetName() << " (opcode: " << static_cast(inst.GetOpcode()) << ")"); - switch (inst.GetOpcode()) { case ir::Opcode::Alloca: { slots.emplace(&inst, function.CreateFrameIndex(GetTypeSize(inst.GetType().get()))); @@ -326,7 +328,10 @@ void LowerInstruction(const ir::Instruction& inst, MachineFunction& function, } case ir::Opcode::Ret: { auto& ret = static_cast(inst); - EmitValueToReg(ret.GetValue(), PhysReg::W0, slots, block, function); + const ir::Value* retVal = ret.GetValue(); + if (retVal != nullptr) { + EmitValueToReg(retVal, PhysReg::W0, slots, block, function); + } block.Append(Opcode::Ret); return; } -- 2.34.1 From 4132f0b5ca3e8b1fad0f641aa07689ab48489ea9 Mon Sep 17 00:00:00 2001 From: mxr <> Date: Fri, 10 Apr 2026 13:38:06 +0800 Subject: [PATCH 14/30] =?UTF-8?q?feat(mir)=E5=AE=9E=E7=8E=B0=E5=A4=9A?= =?UTF-8?q?=E6=9D=A1=E6=8C=87=E4=BB=A4=E8=AE=BF=E9=97=AE=E6=A0=88=E5=B8=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/mir/AsmPrinter.cpp | 53 ++++++++++++++++++++++++++++++++++++--- src/mir/FrameLowering.cpp | 4 +-- 2 files changed, 52 insertions(+), 5 deletions(-) diff --git a/src/mir/AsmPrinter.cpp b/src/mir/AsmPrinter.cpp index 4550730..07d1452 100644 --- a/src/mir/AsmPrinter.cpp +++ b/src/mir/AsmPrinter.cpp @@ -25,12 +25,59 @@ const FrameSlot& GetFrameSlot(const MachineFunction& function, return function.GetFrameSlot(operand.GetFrameIndex()); } -void PrintStackAccess(std::ostream& os, const char* mnemonic, PhysReg reg, +/*void PrintStackAccess(std::ostream& os, const char* mnemonic, PhysReg reg, int offset) { - //os << " " << mnemonic << " " << PhysRegName(reg) << ", [x29, #" << offset - // << "]\n"; // 使用 sp 相对寻址 os << " " << mnemonic << " " << PhysRegName(reg) << ", [sp, #" << offset << "]\n"; +}*/ + +void PrintStackAccess(std::ostream& os, const char* insn, PhysReg reg, int64_t offset) { + // 合法范围:-256 到 255 + if (offset >= -256 && offset <= 255) { + os << " " << insn << " " << PhysRegName(reg) << ", [sp, #" << offset << "]\n"; + return; + } + + // 大偏移:使用 x16 计算地址 + os << " mov x16, sp"<< "\n"; + + // 处理正偏移 + if (offset >= 0) { + // AArch64 add immediate 范围 0~4095,超过则需要分解 + if (offset <= 4095) { + os << " add x16, x16, #" << offset << "\n"; + } else { + // 简单分解:高部分必须是 4096 的倍数?这里为了通用,分两次加 + // 更严谨的做法是循环,但栈帧一般不超过 8192,两次足够 + int64_t low = offset & 0xFFF; // 低12位 + int64_t high = offset - low; + if (high > 0) { + os << " add x16, x16, #" << high << "\n"; + } + if (low > 0) { + os << " add x16, x16, #" << low << "\n"; + } + } + } + // 处理负偏移 + else { + int64_t abs_offset = -offset; + if (abs_offset <= 4095) { + os << " sub x16, x16, #" << abs_offset << "\n"; + } else { + int64_t low = abs_offset & 0xFFF; + int64_t high = abs_offset - low; + if (high > 0) { + os << " sub x16, x16, #" << high << "\n"; + } + if (low > 0) { + os << " sub x16, x16, #" << low << "\n"; + } + } + } + + // 最后使用无偏移的 ldr/str(注意不是 ldur/stur) + os << " " << insn << " " << PhysRegName(reg) << ", [x16]\n"; } // 打印单个操作数 diff --git a/src/mir/FrameLowering.cpp b/src/mir/FrameLowering.cpp index 6758105..7fb71a2 100644 --- a/src/mir/FrameLowering.cpp +++ b/src/mir/FrameLowering.cpp @@ -31,9 +31,9 @@ void RunFrameLowering(MachineFunction& function) { // 使用正偏移,从 sp 开始 function.GetFrameSlot(slot.index).offset = cursor; cursor += slot.size; - if (-cursor < -256) { + /*if (-cursor < -256) { throw std::runtime_error(FormatError("mir", "暂不支持过大的栈帧")); - } + }*/ } cursor = 0; for (const auto& slot : function.GetFrameSlots()) { -- 2.34.1 From 596b0ee334432bd9409e498c47836ada52399997 Mon Sep 17 00:00:00 2001 From: mxr <> Date: Fri, 10 Apr 2026 23:16:12 +0800 Subject: [PATCH 15/30] =?UTF-8?q?feat(mir)=E6=B7=BB=E5=8A=A0Movk=E6=8C=87?= =?UTF-8?q?=E4=BB=A4=E5=8A=A0=E8=BD=BD=E5=A4=A7=E7=AB=8B=E5=8D=B3=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/mir/MIR.h | 3 +++ src/mir/AsmPrinter.cpp | 4 ++++ src/mir/Lowering.cpp | 42 ++++++++++++++++++++++++++++++++++++++---- 3 files changed, 45 insertions(+), 4 deletions(-) diff --git a/include/mir/MIR.h b/include/mir/MIR.h index ff1ce75..6c5f1ea 100644 --- a/include/mir/MIR.h +++ b/include/mir/MIR.h @@ -130,6 +130,9 @@ enum class Opcode { // ---------- 特殊 ---------- Nop, // 空操作: NOP Label, // 内联标签,不生成实际指令,仅输出标签名 + + // 添加 + Movk, // movk Rd, #imm16, lsl #shift }; // ========== 操作数类 ========== diff --git a/src/mir/AsmPrinter.cpp b/src/mir/AsmPrinter.cpp index 07d1452..d8c2fd8 100644 --- a/src/mir/AsmPrinter.cpp +++ b/src/mir/AsmPrinter.cpp @@ -316,6 +316,10 @@ void PrintInstruction(std::ostream& os, const MachineInstr& instr, case Opcode::Label: os << ops.at(0).GetLabel() << ":\n"; break; + case Opcode::Movk: + os << " movk " << PhysRegName(ops.at(0).GetReg()) << ", #" + << ops.at(1).GetImm() << ", lsl #" << ops.at(2).GetImm() << "\n"; + break; default: os << " // unknown instruction\n"; break; diff --git a/src/mir/Lowering.cpp b/src/mir/Lowering.cpp index 013aa26..c05bf35 100644 --- a/src/mir/Lowering.cpp +++ b/src/mir/Lowering.cpp @@ -128,9 +128,34 @@ void EmitValueToReg(const ir::Value* value, PhysReg target, if (value == nullptr) { DEBUG_MSG( "EmitValueToReg called with null value\n"); } + + // 辅助函数:判断32位立即数是否可用单条 movz/movn 编码 + auto isLegalMovImm = [](uint32_t imm) -> bool { + // 检查是否可以通过 movz 或 movn 表示(16位立即数,可左移0/16/32/48位) + // 对于32位寄存器,只考虑 lsl 0 或 16 + if ((imm & 0xFFFF) == imm) return true; // 低16位,lsl #0 + if ((imm & 0xFFFF0000) == imm) return true; // 高16位,lsl #16 + // 可选:检查 movn 情况(~imm 满足上述条件),为了简单可不做,直接返回 false + return false; + }; + if (auto* constant = dynamic_cast(value)) { - block.Append(Opcode::MovImm, - {Operand::Reg(target), Operand::Imm(constant->GetValue())}); + uint32_t imm = static_cast(constant->GetValue()); + if (isLegalMovImm(imm)) { + block.Append(Opcode::MovImm, + {Operand::Reg(target), Operand::Imm(static_cast(imm))}); + } else { + // 分解为 movz (低16位) + movk (高16位) + uint16_t low = imm & 0xFFFF; + uint16_t high = (imm >> 16) & 0xFFFF; + block.Append(Opcode::MovImm, + {Operand::Reg(target), Operand::Imm(low)}); // 先加载低16位 + if (high != 0) { + // 使用 Movk 指令写入高16位 + block.Append(Opcode::Movk, + {Operand::Reg(target), Operand::Imm(high), Operand::Imm(16)}); + } + } return; } // 处理浮点常量 @@ -150,8 +175,17 @@ void EmitValueToReg(const ir::Value* value, PhysReg target, float fval = fconstant->GetValue(); uint32_t int_val = FloatToBits(fval); - // 使用临时寄存器加载常量并存储 - block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::W8), Operand::Imm(static_cast(int_val))}); + // 同样需要对 int_val 进行大立即数分解 + if (isLegalMovImm(int_val)) { + block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::W8), Operand::Imm(static_cast(int_val))}); + } else { + uint16_t low = int_val & 0xFFFF; + uint16_t high = (int_val >> 16) & 0xFFFF; + block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::W8), Operand::Imm(low)}); + if (high != 0) { + block.Append(Opcode::Movk, {Operand::Reg(PhysReg::W8), Operand::Imm(high), Operand::Imm(16)}); + } + } block.Append(Opcode::StoreStack, {Operand::Reg(PhysReg::W8), Operand::FrameIndex(slot)}); const_cast(slots).emplace(value, slot); } else { -- 2.34.1 From c9f73980ea20298ff9d2bf11105116bb1ff5c52c Mon Sep 17 00:00:00 2001 From: mxr <> Date: Sat, 11 Apr 2026 00:36:59 +0800 Subject: [PATCH 16/30] =?UTF-8?q?feat(mir)=E4=BF=AE=E6=94=B9=E6=95=B0?= =?UTF-8?q?=E7=BB=84=E5=88=86=E9=85=8D=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/mir/MIR.h | 3 ++ src/mir/AsmPrinter.cpp | 8 ++++ src/mir/Lowering.cpp | 104 ++++++++++++++++++++++++----------------- 3 files changed, 72 insertions(+), 43 deletions(-) diff --git a/include/mir/MIR.h b/include/mir/MIR.h index 6c5f1ea..2573711 100644 --- a/include/mir/MIR.h +++ b/include/mir/MIR.h @@ -133,6 +133,9 @@ enum class Opcode { // 添加 Movk, // movk Rd, #imm16, lsl #shift + + // 添加 + LoadStackAddr, // 将栈帧地址加载到寄存器 (add xd, sp, #offset) }; // ========== 操作数类 ========== diff --git a/src/mir/AsmPrinter.cpp b/src/mir/AsmPrinter.cpp index d8c2fd8..f30f6d7 100644 --- a/src/mir/AsmPrinter.cpp +++ b/src/mir/AsmPrinter.cpp @@ -320,6 +320,14 @@ void PrintInstruction(std::ostream& os, const MachineInstr& instr, os << " movk " << PhysRegName(ops.at(0).GetReg()) << ", #" << ops.at(1).GetImm() << ", lsl #" << ops.at(2).GetImm() << "\n"; break; + case Opcode::LoadStackAddr: { + // 格式:add xd, sp, #offset + const FrameSlot& slot = GetFrameSlot(function, ops.at(1)); + // 注意:FrameSlot.offset 是相对于栈底(函数入口 sp)的偏移,在 prologue 中 sp 已经下移 + // 因此这里直接使用 slot.offset 即可 + os << " add " << PhysRegName(ops.at(0).GetReg()) << ", sp, #" << slot.offset << "\n"; + break; + } default: os << " // unknown instruction\n"; break; diff --git a/src/mir/Lowering.cpp b/src/mir/Lowering.cpp index c05bf35..aeb169f 100644 --- a/src/mir/Lowering.cpp +++ b/src/mir/Lowering.cpp @@ -258,55 +258,74 @@ void LowerInstruction(const ir::Instruction& inst, MachineFunction& function, << " (opcode: " << static_cast(inst.GetOpcode()) << ")"); switch (inst.GetOpcode()) { case ir::Opcode::Alloca: { - slots.emplace(&inst, function.CreateFrameIndex(GetTypeSize(inst.GetType().get()))); - return; + // alloca 返回一个指针,我们需要为该指针分配一个栈槽(存放地址值) + int ptrSlot = function.CreateFrameIndex(8); // 指针占8字节 + // 为数组数据分配实际栈空间 + int arraySlot = function.CreateFrameIndex(GetTypeSize(inst.GetType().get())); + + // 将数组基地址(sp + arraySlot_offset)加载到 x8 + block.Append(Opcode::LoadStackAddr, + {Operand::Reg(PhysReg::X8), Operand::FrameIndex(arraySlot)}); + // 将地址存储到指针槽 + block.Append(Opcode::StoreStack, + {Operand::Reg(PhysReg::X8), Operand::FrameIndex(ptrSlot)}); + + // 将 alloca 指令映射到指针槽,后续使用 alloca 值即获得地址 + slots.emplace(&inst, ptrSlot); + return; } case ir::Opcode::Store: { - auto& store = static_cast(inst); - auto dst = slots.find(store.GetPtr()); - if (dst == slots.end()) { - //throw std::runtime_error( - // FormatError("mir", "暂不支持对非栈变量地址进行写入")); - EmitValueToReg(store.GetPtr(), PhysReg::X8, slots, block, function); - // 加载值到 w9 - EmitValueToReg(store.GetValue(), PhysReg::W9, slots, block, function); - // 存储值到地址 - block.Append(Opcode::StoreStack, - {Operand::Reg(PhysReg::W9), Operand::Reg(PhysReg::X8)}); + auto& store = static_cast(inst); + const ir::Value* ptr = store.GetPtr(); + const ir::Value* val = store.GetValue(); + + auto dstIt = slots.find(ptr); + if (dstIt == slots.end()) { + // 指针不在 slots 中(例如直接来自函数参数的指针) + // 计算指针地址到 x8 + EmitValueToReg(ptr, PhysReg::X8, slots, block, function); + // 加载要存储的值到 w9 + EmitValueToReg(val, PhysReg::W9, slots, block, function); + // 使用 StoreStack 的寄存器间接形式(str w9, [x8]) + block.Append(Opcode::StoreStack, + {Operand::Reg(PhysReg::W9), Operand::Reg(PhysReg::X8)}); + } else { + // 指针在 slots 中(alloca 或 gep 的结果),从指针槽加载地址到 x8 + block.Append(Opcode::LoadStack, + {Operand::Reg(PhysReg::X8), Operand::FrameIndex(dstIt->second)}); + // 加载要存储的值到 w9 + EmitValueToReg(val, PhysReg::W9, slots, block, function); + // 间接存储 + block.Append(Opcode::StoreStack, + {Operand::Reg(PhysReg::W9), Operand::Reg(PhysReg::X8)}); + } return; - } - EmitValueToReg(store.GetValue(), PhysReg::W8, slots, block, function); - block.Append(Opcode::StoreStack, - {Operand::Reg(PhysReg::W8), Operand::FrameIndex(dst->second)}); - return; } case ir::Opcode::Load: { - auto& load = static_cast(inst); - auto src = slots.find(load.GetPtr()); - if (src == slots.end()) { - //throw std::runtime_error( - // FormatError("mir", "暂不支持对非栈变量地址进行读取")); - // 对于非栈变量地址(如 GEP 结果),地址本身在栈槽中 - // 需要先加载地址,然后从该地址加载值 - int dst_slot = function.CreateFrameIndex(GetTypeSize(inst.GetType().get())); - // 加载地址到 x8 - EmitValueToReg(load.GetPtr(), PhysReg::X8, slots, block, function); - // 从地址加载值到 w9 - block.Append(Opcode::LoadStack, - {Operand::Reg(PhysReg::W9), Operand::Reg(PhysReg::X8)}); - // 存储值到结果栈槽 + auto& load = static_cast(inst); + const ir::Value* ptr = load.GetPtr(); + int dstSlot = function.CreateFrameIndex(GetTypeSize(inst.GetType().get())); + + auto srcIt = slots.find(ptr); + if (srcIt == slots.end()) { + // 指针不在 slots 中,计算地址到 x8 + EmitValueToReg(ptr, PhysReg::X8, slots, block, function); + // 间接加载到 w9 + block.Append(Opcode::LoadStack, + {Operand::Reg(PhysReg::W9), Operand::Reg(PhysReg::X8)}); + } else { + // 从指针槽加载地址到 x8 + block.Append(Opcode::LoadStack, + {Operand::Reg(PhysReg::X8), Operand::FrameIndex(srcIt->second)}); + // 间接加载到 w9 + block.Append(Opcode::LoadStack, + {Operand::Reg(PhysReg::W9), Operand::Reg(PhysReg::X8)}); + } + // 将加载的值存入结果槽 block.Append(Opcode::StoreStack, - {Operand::Reg(PhysReg::W9), Operand::FrameIndex(dst_slot)}); - slots.emplace(&inst, dst_slot); + {Operand::Reg(PhysReg::W9), Operand::FrameIndex(dstSlot)}); + slots.emplace(&inst, dstSlot); return; - } - int dst_slot = function.CreateFrameIndex(GetTypeSize(inst.GetType().get())); // 分配结果槽 - block.Append(Opcode::LoadStack, - {Operand::Reg(PhysReg::W8), Operand::FrameIndex(src->second)}); - block.Append(Opcode::StoreStack, - {Operand::Reg(PhysReg::W8), Operand::FrameIndex(dst_slot)}); - slots.emplace(&inst, dst_slot); - return; } case ir::Opcode::Add: { auto& bin = static_cast(inst); @@ -973,7 +992,6 @@ std::unique_ptr LowerFunction(const ir::Function& func) { LowerInstruction(*inst, *machine_func, slots, *mirBB, blockMap); } } - return machine_func; } -- 2.34.1 From 5e492f531bb4e55d60d1bfde948b7e01b609ece0 Mon Sep 17 00:00:00 2001 From: mxr <> Date: Sat, 11 Apr 2026 01:08:07 +0800 Subject: [PATCH 17/30] =?UTF-8?q?feat(mir)=E5=A4=84=E7=90=86=E6=8C=87?= =?UTF-8?q?=E4=BB=A4=E7=AB=8B=E5=8D=B3=E6=95=B0=E8=B6=85=E5=87=BA=E8=8C=83?= =?UTF-8?q?=E5=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/mir/AsmPrinter.cpp | 88 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 77 insertions(+), 11 deletions(-) diff --git a/src/mir/AsmPrinter.cpp b/src/mir/AsmPrinter.cpp index f30f6d7..aaf9825 100644 --- a/src/mir/AsmPrinter.cpp +++ b/src/mir/AsmPrinter.cpp @@ -102,6 +102,39 @@ void PrintOperand(std::ostream& os, const Operand& op) { } } +// 判断立即数是否可作为 AArch64 ADD/SUB 指令的 12 位立即数(可左移 0 或 12 位) +static bool IsLegalAddSubImm(int64_t imm) { + if (imm < 0) imm = -imm; // 取绝对值,因为移位规则对称 + if (imm <= 4095) return true; // 0-4095 直接合法 + if ((imm & 0xFFF) == 0 && imm <= 4095 * 4096) return true; // 4096 的倍数且 ≤ 16773120 + return false; +} + +// 在匿名命名空间添加辅助函数 +static void PrintLoadImm64(std::ostream& os, PhysReg reg, uint64_t imm) { + // 输出 movz + movk 序列 + uint16_t part0 = imm & 0xFFFF; + uint16_t part1 = (imm >> 16) & 0xFFFF; + uint16_t part2 = (imm >> 32) & 0xFFFF; + uint16_t part3 = (imm >> 48) & 0xFFFF; + + os << " movz " << PhysRegName(reg) << ", #" << part0; + if (part1 != 0 || part2 != 0 || part3 != 0) { + os << ", lsl #0"; + } + os << "\n"; + + if (part1 != 0) { + os << " movk " << PhysRegName(reg) << ", #" << part1 << ", lsl #16\n"; + } + if (part2 != 0) { + os << " movk " << PhysRegName(reg) << ", #" << part2 << ", lsl #32\n"; + } + if (part3 != 0) { + os << " movk " << PhysRegName(reg) << ", #" << part3 << ", lsl #48\n"; + } +} + // 打印单条指令 void PrintInstruction(std::ostream& os, const MachineInstr& instr, const MachineFunction& function) { @@ -112,15 +145,27 @@ void PrintInstruction(std::ostream& os, const MachineInstr& instr, os << " stp x29, x30, [sp, #-16]!\n"; os << " mov x29, sp\n"; if (function.GetFrameSize() > 0) { - os << " sub sp, sp, #" << function.GetFrameSize() << "\n"; + int64_t size = function.GetFrameSize(); + if (IsLegalAddSubImm(size)) { + os << " sub sp, sp, #" << size << "\n"; + } else { + PrintLoadImm64(os, PhysReg::X16, size); + os << " sub sp, sp, x16\n"; + } } break; case Opcode::Epilogue: - if (function.GetFrameSize() > 0) { - os << " add sp, sp, #" << function.GetFrameSize() << "\n"; + if (function.GetFrameSize() > 0) { + int64_t size = function.GetFrameSize(); + if (IsLegalAddSubImm(size)) { + os << " add sp, sp, #" << size << "\n"; + } else { + PrintLoadImm64(os, PhysReg::X16, size); + os << " add sp, sp, x16\n"; } - os << " ldp x29, x30, [sp], #16\n"; - break; + } + os << " ldp x29, x30, [sp], #16\n"; + break; case Opcode::MovImm: os << " mov " << PhysRegName(ops.at(0).GetReg()) << ", #" << ops.at(1).GetImm() << "\n"; @@ -321,12 +366,33 @@ void PrintInstruction(std::ostream& os, const MachineInstr& instr, << ops.at(1).GetImm() << ", lsl #" << ops.at(2).GetImm() << "\n"; break; case Opcode::LoadStackAddr: { - // 格式:add xd, sp, #offset - const FrameSlot& slot = GetFrameSlot(function, ops.at(1)); - // 注意:FrameSlot.offset 是相对于栈底(函数入口 sp)的偏移,在 prologue 中 sp 已经下移 - // 因此这里直接使用 slot.offset 即可 - os << " add " << PhysRegName(ops.at(0).GetReg()) << ", sp, #" << slot.offset << "\n"; - break; + const FrameSlot& slot = GetFrameSlot(function, ops.at(1)); + int64_t offset = slot.offset; // 偏移可能为正或负 + PhysReg dst = ops.at(0).GetReg(); + + // 尝试生成简单的 add/sub 立即数指令 + auto tryEmitSimple = [&]() -> bool { + if (offset >= 0 && offset <= 4095) { + os << " add " << PhysRegName(dst) << ", sp, #" << offset << "\n"; + return true; + } else if (offset < 0 && offset >= -4095) { + os << " sub " << PhysRegName(dst) << ", sp, #" << (-offset) << "\n"; + return true; + } + return false; + }; + + if (tryEmitSimple()) break; + + // 复杂情况:偏移绝对值 > 4095,使用 x16 临时寄存器 + uint64_t absOffset = (offset >= 0) ? offset : -offset; + PrintLoadImm64(os, PhysReg::X16, absOffset); + if (offset >= 0) { + os << " add " << PhysRegName(dst) << ", sp, x16\n"; + } else { + os << " sub " << PhysRegName(dst) << ", sp, x16\n"; + } + break; } default: os << " // unknown instruction\n"; -- 2.34.1 From 7438c366fd75bee25d9807fa50cc1a3b531dfc3e Mon Sep 17 00:00:00 2001 From: mxr <> Date: Mon, 13 Apr 2026 20:02:22 +0800 Subject: [PATCH 18/30] =?UTF-8?q?feat(mir)=E4=BF=AE=E6=AD=A3=E5=85=A8?= =?UTF-8?q?=E5=B1=80=E5=8F=98=E9=87=8F=E5=9C=B0=E5=9D=80=E8=AE=A1=E7=AE=97?= =?UTF-8?q?=E5=92=8C=E6=95=B0=E6=8D=AE=E6=AE=B5=E7=94=9F=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/mir/MIR.h | 18 ++++++++++++++ src/mir/AsmPrinter.cpp | 36 +++++++++++++++++++++++++-- src/mir/Lowering.cpp | 55 +++++++++++++++++++++++++++--------------- 3 files changed, 87 insertions(+), 22 deletions(-) diff --git a/include/mir/MIR.h b/include/mir/MIR.h index 2573711..a879bef 100644 --- a/include/mir/MIR.h +++ b/include/mir/MIR.h @@ -136,6 +136,10 @@ enum class Opcode { // 添加 LoadStackAddr, // 将栈帧地址加载到寄存器 (add xd, sp, #offset) + + // 用于全局变量地址计算 + Adrp, // ADRP Xd, label + AddLabel, // ADD Xd, Xn, :lo12:label }; // ========== 操作数类 ========== @@ -289,8 +293,22 @@ class MachineModule { return nullptr; } + struct GlobalDecl { + std::string name; + int size; // 字节大小 + int alignment; // 对齐要求(通常为 4 或 8) + bool is_zero_init; // 是否为零初始化 + }; + + void AddGlobal(const std::string& name, int size, int alignment, bool is_zero_init = true) { + globals_.push_back({name, size, alignment, is_zero_init}); + } + + const std::vector& GetGlobals() const { return globals_; } + private: std::vector> functions_; + std::vector globals_; }; // ========== 后端流程函数 ========== diff --git a/src/mir/AsmPrinter.cpp b/src/mir/AsmPrinter.cpp index aaf9825..eaee05b 100644 --- a/src/mir/AsmPrinter.cpp +++ b/src/mir/AsmPrinter.cpp @@ -394,9 +394,22 @@ void PrintInstruction(std::ostream& os, const MachineInstr& instr, } break; } + case Opcode::Adrp: { + // adrp Xd, label + os << " adrp " << PhysRegName(ops.at(0).GetReg()) << ", " + << ops.at(1).GetLabel() << "\n"; + break; + } + case Opcode::AddLabel: { + // add Xd, Xn, :lo12:label + os << " add " << PhysRegName(ops.at(0).GetReg()) << ", " + << PhysRegName(ops.at(1).GetReg()) << ", :lo12:" + << ops.at(2).GetLabel() << "\n"; + break; + } default: - os << " // unknown instruction\n"; - break; + os << " // unknown instruction\n"; + break; } } @@ -439,6 +452,25 @@ void PrintAsm(const MachineFunction& function, std::ostream& os) { void PrintAsm(const MachineModule& module, std::ostream& os) { // 输出文件头 os << ".arch armv8-a\n"; + + // 输出数据段:全局变量 + const auto& globals = module.GetGlobals(); + if (!globals.empty()) { + os << "\n.data\n"; + for (const auto& g : globals) { + os << ".global " << g.name << "\n"; + os << ".type " << g.name << ", %object\n"; + os << ".align " << g.alignment << "\n"; + os << g.name << ":\n"; + if (g.is_zero_init) { + os << " .zero " << g.size << "\n"; + } else { + // TODO: 处理非零初始化值(需要从 IR 提取 initializer) + os << " .zero " << g.size << " // unhandled initializer\n"; + } + os << ".size " << g.name << ", " << g.size << "\n\n"; + } + } DEBUG_MSG("module"); // 遍历所有函数,输出汇编 diff --git a/src/mir/Lowering.cpp b/src/mir/Lowering.cpp index aeb169f..39bea1c 100644 --- a/src/mir/Lowering.cpp +++ b/src/mir/Lowering.cpp @@ -196,26 +196,7 @@ void EmitValueToReg(const ir::Value* value, PhysReg target, block.Append(Opcode::LoadStack, {Operand::Reg(target), Operand::FrameIndex(slot)}); return; } - // 处理全局变量 - if (auto* global = dynamic_cast(value)) { - // 全局变量:需要加载其地址 - // 在 ARM64 中,使用 ADRP + ADD 指令获取全局变量地址 - // 简化版本:先为全局变量分配一个栈槽,然后加载地址到该栈槽 - - // 检查是否已经为这个全局变量分配了栈槽 - auto it = slots.find(value); - if (it == slots.end()) { - // 为全局变量创建栈槽 - const_cast(slots).emplace(value, - const_cast(function).CreateFrameIndex(8)); - it = slots.find(value); - } - - // 从栈槽加载地址到目标寄存器 - block.Append(Opcode::LoadStack, - {Operand::Reg(target), Operand::FrameIndex(it->second)}); - return; - } + // 处理零常量 if (dynamic_cast(value) || dynamic_cast(value)) { @@ -279,6 +260,18 @@ void LowerInstruction(const ir::Instruction& inst, MachineFunction& function, const ir::Value* ptr = store.GetPtr(); const ir::Value* val = store.GetValue(); + // 处理全局变量作为存储目标 + if (auto* global = dynamic_cast(ptr)) { + // 生成全局变量地址到 x8 + block.Append(Opcode::Adrp, {Operand::Reg(PhysReg::X8), Operand::Label(global->GetName())}); + block.Append(Opcode::AddLabel, {Operand::Reg(PhysReg::X8), Operand::Reg(PhysReg::X8), Operand::Label(global->GetName())}); + // 加载要存储的值到 w9 + EmitValueToReg(val, PhysReg::W9, slots, block, function); + // 间接存储:str w9, [x8] + block.Append(Opcode::StoreStack, {Operand::Reg(PhysReg::W9), Operand::Reg(PhysReg::X8)}); + return; + } + auto dstIt = slots.find(ptr); if (dstIt == slots.end()) { // 指针不在 slots 中(例如直接来自函数参数的指针) @@ -305,6 +298,19 @@ void LowerInstruction(const ir::Instruction& inst, MachineFunction& function, auto& load = static_cast(inst); const ir::Value* ptr = load.GetPtr(); int dstSlot = function.CreateFrameIndex(GetTypeSize(inst.GetType().get())); + + // 处理全局变量作为加载源 + if (auto* global = dynamic_cast(ptr)) { + // 生成全局变量地址到 x8 + block.Append(Opcode::Adrp, {Operand::Reg(PhysReg::X8), Operand::Label(global->GetName())}); + block.Append(Opcode::AddLabel, {Operand::Reg(PhysReg::X8), Operand::Reg(PhysReg::X8), Operand::Label(global->GetName())}); + // 间接加载到 w9 + block.Append(Opcode::LoadStack, {Operand::Reg(PhysReg::W9), Operand::Reg(PhysReg::X8)}); + // 存储结果到栈槽 + block.Append(Opcode::StoreStack, {Operand::Reg(PhysReg::W9), Operand::FrameIndex(dstSlot)}); + slots.emplace(&inst, dstSlot); + return; + } auto srcIt = slots.find(ptr); if (srcIt == slots.end()) { @@ -1000,6 +1006,15 @@ std::unique_ptr LowerToMIR(const ir::Module& module) { auto machine_module = std::make_unique(); + // 收集全局变量信息 + for (const auto& global : module.GetGlobals()) { + int size = GetTypeSize(global->GetType().get()); + int alignment = global->GetType()->Alignment(); + // 简化:假设无显式初始化的全局变量都是零初始化 + bool is_zero_init = !global->HasInitializer(); + machine_module->AddGlobal(global->GetName(), size, alignment, is_zero_init); + } + std::vector globals; // 处理全局变量 for (const auto& global : module.GetGlobals()) { -- 2.34.1 From 0fd3f4b84105d0be40de3b23d3c8cb199880a493 Mon Sep 17 00:00:00 2001 From: ftt <> Date: Mon, 13 Apr 2026 20:37:18 +0800 Subject: [PATCH 19/30] =?UTF-8?q?=E8=A7=A3=E5=86=B3=E5=AF=B9=E5=BA=94?= =?UTF-8?q?=E5=80=BC=E6=A0=88=E6=A7=BD=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/mir/Lowering.cpp | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/mir/Lowering.cpp b/src/mir/Lowering.cpp index 39bea1c..36ff787 100644 --- a/src/mir/Lowering.cpp +++ b/src/mir/Lowering.cpp @@ -206,6 +206,34 @@ void EmitValueToReg(const ir::Value* value, PhysReg target, return; } + // ========== 处理全局变量 ========== + if (auto* global = dynamic_cast(value)) { + // 加载全局变量的地址到目标寄存器 + // 注意:地址计算需要使用 64 位寄存器 + PhysReg addrReg = target; + bool needMove = false; + + // 如果目标是 32 位寄存器,改用 X8 临时寄存器 + if (target == PhysReg::W0 || target == PhysReg::W1 || target == PhysReg::W2 || + target == PhysReg::W3 || target == PhysReg::W4 || target == PhysReg::W5 || + target == PhysReg::W6 || target == PhysReg::W7 || target == PhysReg::W8 || + target == PhysReg::W9) { + addrReg = PhysReg::X8; + needMove = true; + } + + // 使用 ADRP + ADD 加载全局变量地址 + block.Append(Opcode::Adrp, {Operand::Reg(addrReg), Operand::Label(global->GetName())}); + block.Append(Opcode::AddLabel, {Operand::Reg(addrReg), Operand::Reg(addrReg), Operand::Label(global->GetName())}); + + // 如果需要,将地址移动到目标寄存器 + if (needMove) { + block.Append(Opcode::MovReg, {Operand::Reg(target), Operand::Reg(addrReg)}); + } + return; + } + + // ========== 处理从栈槽加载的值 ========== auto it = slots.find(value); if (it == slots.end()) { // 使用值的地址作为调试信息 -- 2.34.1 From d5a8affe83abcf1970525bb878fa12d1e93e81d7 Mon Sep 17 00:00:00 2001 From: mxr <> Date: Mon, 13 Apr 2026 21:04:38 +0800 Subject: [PATCH 20/30] =?UTF-8?q?feat(mir)=E4=BF=AE=E6=AD=A3=E6=A0=88?= =?UTF-8?q?=E5=B8=A7=E5=88=86=E9=85=8D=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 3 +- src/ir/Type.cpp | 1 + src/mir/AsmPrinter.cpp | 68 +++++++++++++-------------------------- src/mir/FrameLowering.cpp | 10 ------ 4 files changed, 25 insertions(+), 57 deletions(-) diff --git a/.gitignore b/.gitignore index 53075fa..8bf0773 100644 --- a/.gitignore +++ b/.gitignore @@ -73,4 +73,5 @@ test/test_result/ # mxr # ========================= result.txt -build.sh \ No newline at end of file +build.sh +gdb.sh \ No newline at end of file diff --git a/src/ir/Type.cpp b/src/ir/Type.cpp index 792ff54..f53e6ec 100644 --- a/src/ir/Type.cpp +++ b/src/ir/Type.cpp @@ -14,6 +14,7 @@ size_t Type::Size() const { case Kind::PtrInt32: return 8; // 假设 64 位指针 case Kind::PtrFloat: return 8; case Kind::Label: return 8; // 标签地址大小(指针大小) + case Kind::PtrInt1: return 8; // 指向 i1 的指针大小 default: return 0; // 派生类应重写 } } diff --git a/src/mir/AsmPrinter.cpp b/src/mir/AsmPrinter.cpp index eaee05b..4a35a81 100644 --- a/src/mir/AsmPrinter.cpp +++ b/src/mir/AsmPrinter.cpp @@ -17,6 +17,8 @@ namespace mir { namespace { +static void PrintLoadImm64(std::ostream& os, PhysReg reg, uint64_t imm); + const FrameSlot& GetFrameSlot(const MachineFunction& function, const Operand& operand) { if (operand.GetKind() != Operand::Kind::FrameIndex) { @@ -25,58 +27,33 @@ const FrameSlot& GetFrameSlot(const MachineFunction& function, return function.GetFrameSlot(operand.GetFrameIndex()); } -/*void PrintStackAccess(std::ostream& os, const char* mnemonic, PhysReg reg, - int offset) { - // 使用 sp 相对寻址 - os << " " << mnemonic << " " << PhysRegName(reg) << ", [sp, #" << offset << "]\n"; -}*/ - void PrintStackAccess(std::ostream& os, const char* insn, PhysReg reg, int64_t offset) { - // 合法范围:-256 到 255 + // offset 通常是负数,例如 -8, -24, -40 等 if (offset >= -256 && offset <= 255) { - os << " " << insn << " " << PhysRegName(reg) << ", [sp, #" << offset << "]\n"; + os << " " << insn << " " << PhysRegName(reg) << ", [x29, #" << offset << "]\n"; return; } - // 大偏移:使用 x16 计算地址 - os << " mov x16, sp"<< "\n"; + // 大偏移量:用 x16 计算 x29 + offset,然后间接访问 + os << " mov x16, x29\n"; - // 处理正偏移 - if (offset >= 0) { - // AArch64 add immediate 范围 0~4095,超过则需要分解 - if (offset <= 4095) { + int64_t abs_offset = (offset >= 0) ? offset : -offset; + if (abs_offset <= 4095) { + if (offset >= 0) { os << " add x16, x16, #" << offset << "\n"; } else { - // 简单分解:高部分必须是 4096 的倍数?这里为了通用,分两次加 - // 更严谨的做法是循环,但栈帧一般不超过 8192,两次足够 - int64_t low = offset & 0xFFF; // 低12位 - int64_t high = offset - low; - if (high > 0) { - os << " add x16, x16, #" << high << "\n"; - } - if (low > 0) { - os << " add x16, x16, #" << low << "\n"; - } - } - } - // 处理负偏移 - else { - int64_t abs_offset = -offset; - if (abs_offset <= 4095) { os << " sub x16, x16, #" << abs_offset << "\n"; + } + } else { + // 分解大偏移量 + PrintLoadImm64(os, PhysReg::X17, abs_offset); + if (offset >= 0) { + os << " add x16, x16, x17\n"; } else { - int64_t low = abs_offset & 0xFFF; - int64_t high = abs_offset - low; - if (high > 0) { - os << " sub x16, x16, #" << high << "\n"; - } - if (low > 0) { - os << " sub x16, x16, #" << low << "\n"; - } + os << " sub x16, x16, x17\n"; } } - // 最后使用无偏移的 ldr/str(注意不是 ldur/stur) os << " " << insn << " " << PhysRegName(reg) << ", [x16]\n"; } @@ -367,16 +344,15 @@ void PrintInstruction(std::ostream& os, const MachineInstr& instr, break; case Opcode::LoadStackAddr: { const FrameSlot& slot = GetFrameSlot(function, ops.at(1)); - int64_t offset = slot.offset; // 偏移可能为正或负 + int64_t offset = slot.offset; // 负值,如 -8 PhysReg dst = ops.at(0).GetReg(); - // 尝试生成简单的 add/sub 立即数指令 auto tryEmitSimple = [&]() -> bool { if (offset >= 0 && offset <= 4095) { - os << " add " << PhysRegName(dst) << ", sp, #" << offset << "\n"; + os << " add " << PhysRegName(dst) << ", x29, #" << offset << "\n"; return true; } else if (offset < 0 && offset >= -4095) { - os << " sub " << PhysRegName(dst) << ", sp, #" << (-offset) << "\n"; + os << " sub " << PhysRegName(dst) << ", x29, #" << (-offset) << "\n"; return true; } return false; @@ -384,13 +360,13 @@ void PrintInstruction(std::ostream& os, const MachineInstr& instr, if (tryEmitSimple()) break; - // 复杂情况:偏移绝对值 > 4095,使用 x16 临时寄存器 + // 复杂偏移 uint64_t absOffset = (offset >= 0) ? offset : -offset; PrintLoadImm64(os, PhysReg::X16, absOffset); if (offset >= 0) { - os << " add " << PhysRegName(dst) << ", sp, x16\n"; + os << " add " << PhysRegName(dst) << ", x29, x16\n"; } else { - os << " sub " << PhysRegName(dst) << ", sp, x16\n"; + os << " sub " << PhysRegName(dst) << ", x29, x16\n"; } break; } diff --git a/src/mir/FrameLowering.cpp b/src/mir/FrameLowering.cpp index 7fb71a2..86cd502 100644 --- a/src/mir/FrameLowering.cpp +++ b/src/mir/FrameLowering.cpp @@ -26,16 +26,6 @@ int AlignTo(int value, int align) { void RunFrameLowering(MachineFunction& function) { DEBUG_MSG("function RunFrameLowering"); int cursor = 0; - for (const auto& slot : function.GetFrameSlots()) { - //cursor += slot.size; - // 使用正偏移,从 sp 开始 - function.GetFrameSlot(slot.index).offset = cursor; - cursor += slot.size; - /*if (-cursor < -256) { - throw std::runtime_error(FormatError("mir", "暂不支持过大的栈帧")); - }*/ - } - cursor = 0; for (const auto& slot : function.GetFrameSlots()) { cursor += slot.size; function.GetFrameSlot(slot.index).offset = -cursor; -- 2.34.1 From 966b5b9c7f2f2e5d15d61269877fad8cbe706ee0 Mon Sep 17 00:00:00 2001 From: ftt <> Date: Mon, 13 Apr 2026 21:07:28 +0800 Subject: [PATCH 21/30] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=A4=9A=E7=BB=B4?= =?UTF-8?q?=E6=95=B0=E7=BB=84=E7=B4=A2=E5=BC=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/mir/Lowering.cpp | 258 ++++++++++++++++++++++++------------------- 1 file changed, 146 insertions(+), 112 deletions(-) diff --git a/src/mir/Lowering.cpp b/src/mir/Lowering.cpp index 36ff787..80bd986 100644 --- a/src/mir/Lowering.cpp +++ b/src/mir/Lowering.cpp @@ -7,13 +7,13 @@ #include "ir/IR.h" #include "utils/Log.h" -//#define DEBUG_Lower +#define DEBUG_Lower #ifdef DEBUG_Lower #include #define DEBUG_MSG(msg) std::cerr << "[Lower Debug] " << msg << std::endl #else -#define DEBUG_MSG(msg) +#define DEBUG_MSG(msg) ((void)0) #endif namespace mir { @@ -655,132 +655,166 @@ void LowerInstruction(const ir::Instruction& inst, MachineFunction& function, slots.emplace(&inst, dst_slot); return; } - // ========== GEP 指令(计算数组元素地址)========== case ir::Opcode::GEP: { - auto& gep = static_cast(inst); - - // GEP 返回指针类型,在 ARM64 上指针是 8 字节 - int dst_slot = function.CreateFrameIndex(8); - - // 获取基地址(数组的起始地址) - ir::Value* base = gep.GetBase(); - const auto& indices = gep.GetIndices(); - - // 加载基地址到 x8(使用 64 位寄存器存储地址) - EmitValueToReg(base, PhysReg::X8, slots, block, function); - - if (indices.empty()) { - // 没有索引,直接返回基地址 - block.Append(Opcode::StoreStack, - {Operand::Reg(PhysReg::X8), Operand::FrameIndex(dst_slot)}); - slots.emplace(&inst, dst_slot); - return; - } - - // 获取数组类型信息,计算每个维度的步长 - const ir::Type* baseType = base->GetType().get(); - - // 如果基地址是指针类型,需要解引用获取元素类型 - if (baseType->IsPtrInt32() || baseType->IsPtrFloat() || baseType->IsPtrInt1()) { - // 对于指针类型,第一个索引是偏移量(以元素为单位) - // 例如:int* p; p[1] 的 GEP 中 indices[0] = 1 - if (indices.size() >= 1) { - // 加载索引到 x9 - EmitValueToReg(indices[0], PhysReg::X9, slots, block, function); - - // 乘以元素大小(int/float 是 4 字节) - block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::X10), Operand::Imm(4)}); - block.Append(Opcode::MulRR, {Operand::Reg(PhysReg::X9), - Operand::Reg(PhysReg::X9), - Operand::Reg(PhysReg::X10)}); - - // 地址 = base + index * 4 - block.Append(Opcode::AddRR, {Operand::Reg(PhysReg::X8), - Operand::Reg(PhysReg::X8), - Operand::Reg(PhysReg::X9)}); - } + auto& gep = static_cast(inst); - // 存储计算出的地址 - block.Append(Opcode::StoreStack, - {Operand::Reg(PhysReg::X8), Operand::FrameIndex(dst_slot)}); - slots.emplace(&inst, dst_slot); - return; - } - - // 如果基地址是数组类型,需要处理多维数组 - if (baseType->IsArray()) { - const ir::ArrayType* arrayType = static_cast(baseType); - const std::vector& dims = arrayType->GetDimensions(); + DEBUG_MSG("Processing GEP instruction: " << inst.GetName()); - // 计算每个维度的步长 - std::vector strides(dims.size()); - int stride = 4; // 元素大小(int/float 是 4 字节) - for (int i = dims.size() - 1; i >= 0; --i) { - strides[i] = stride; - stride *= dims[i]; + // GEP 返回指针类型,在 ARM64 上指针是 8 字节 + int dst_slot = function.CreateFrameIndex(8); + + // 获取基地址(数组的起始地址) + ir::Value* base = gep.GetBase(); + const auto& indices = gep.GetIndices(); + + std::string baseName = base->GetName().empty() ? "unnamed" : base->GetName(); + DEBUG_MSG("Base value: " << baseName); + DEBUG_MSG("Number of indices: " << indices.size()); + + // 打印索引值 + for (size_t idx_i = 0; idx_i < indices.size(); ++idx_i) { + if (auto* const_int = dynamic_cast(indices[idx_i])) { + DEBUG_MSG(" Index[" << idx_i << "] = " << const_int->GetValue() << " (constant)"); + } else { + DEBUG_MSG(" Index[" << idx_i << "] = variable"); + } } - // 计算总偏移量 - // 地址 = base + index0 * stride0 + index1 * stride1 + ... - size_t numIndices = indices.size(); + // 加载基地址到 x8 + EmitValueToReg(base, PhysReg::X8, slots, block, function); - // 限制索引数量(不能超过维度数) - if (numIndices > dims.size()) { - numIndices = dims.size(); + if (indices.empty()) { + DEBUG_MSG("No indices, storing base address directly"); + block.Append(Opcode::StoreStack, + {Operand::Reg(PhysReg::X8), Operand::FrameIndex(dst_slot)}); + slots.emplace(&inst, dst_slot); + return; } - // 加载当前地址到 x9 作为偏移量累加器 - block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::X9), Operand::Imm(0)}); + // 获取基地址类型 + const ir::Type* baseType = base->GetType().get(); + DEBUG_MSG("Base type kind: " << static_cast(baseType->GetKind())); - for (size_t i = 0; i < numIndices; ++i) { - // 加载当前索引到 x10 - EmitValueToReg(indices[i], PhysReg::X10, slots, block, function); - - // 乘以步长 - block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::X11), Operand::Imm(strides[i])}); - block.Append(Opcode::MulRR, {Operand::Reg(PhysReg::X10), - Operand::Reg(PhysReg::X10), - Operand::Reg(PhysReg::X11)}); - - // 累加到偏移量 - block.Append(Opcode::AddRR, {Operand::Reg(PhysReg::X9), - Operand::Reg(PhysReg::X9), - Operand::Reg(PhysReg::X10)}); + // 关键修改:对于数组指针类型,第一个索引是多余的,应该跳过 + size_t start_index = 0; + if (baseType->IsPtrInt32() || baseType->IsPtrFloat() || baseType->IsPtrInt1()) { + // 对于指针类型,第一个索引是偏移量,不能跳过 + DEBUG_MSG("Base is pointer type, using all indices for pointer arithmetic"); + start_index = 0; + } else if (baseType->IsArray()) { + // 对于数组类型(非指针),第一个索引是多余的 + // 因为 base 已经是数组本身,不需要再解引用 + DEBUG_MSG("Base is array type, skipping first index (array decay)"); + start_index = 1; } - // 最终地址 = base + offset - block.Append(Opcode::AddRR, {Operand::Reg(PhysReg::X8), - Operand::Reg(PhysReg::X8), - Operand::Reg(PhysReg::X9)}); + // 如果基地址是数组类型,需要处理多维数组 + if (baseType->IsArray()) { + DEBUG_MSG("Base is array type, processing multi-dimensional array"); + const ir::ArrayType* arrayType = static_cast(baseType); + const std::vector& dims = arrayType->GetDimensions(); + + DEBUG_MSG("Array dimensions: "); + for (size_t i = 0; i < dims.size(); ++i) { + DEBUG_MSG(" dim[" << i << "] = " << dims[i]); + } + + // 正确计算每个维度的步长 + std::vector strides(dims.size()); + int element_size = 4; // 元素大小(int/float 是 4 字节) + for (int i = dims.size() - 1; i >= 0; --i) { + if (i == static_cast(dims.size()) - 1) { + strides[i] = element_size; + DEBUG_MSG("strides[" << i << "] = " << strides[i] << " (element size)"); + } else { + strides[i] = strides[i + 1] * dims[i + 1]; + DEBUG_MSG("strides[" << i << "] = " << strides[i+1] << " * " << dims[i+1] + << " = " << strides[i]); + } + } + + // 计算总偏移,跳过第一个索引 + size_t numIndices = indices.size(); + size_t effective_indices = numIndices - start_index; + if (effective_indices > dims.size()) { + DEBUG_MSG("Warning: effective indices (" << effective_indices << ") > dims.size() (" + << dims.size() << "), truncating"); + effective_indices = dims.size(); + } + + DEBUG_MSG("Using " << effective_indices << " effective indices (starting from " << start_index << ")"); + + // 加载当前地址到 x9 作为偏移量累加器 + block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::X9), Operand::Imm(0)}); + + // 用于调试的静态偏移计算 + int debug_offset = 0; + + for (size_t i = 0; i < effective_indices; ++i) { + size_t idx_pos = start_index + i; + int index_value = 0; + if (auto* const_int = dynamic_cast(indices[idx_pos])) { + index_value = const_int->GetValue(); + DEBUG_MSG("Index[" << idx_pos << "] = " << index_value << " (constant)"); + debug_offset += index_value * strides[i]; + DEBUG_MSG(" Contribution = " << index_value << " * " << strides[i] + << " = " << (index_value * strides[i])); + DEBUG_MSG(" Running offset = " << debug_offset); + } else { + DEBUG_MSG("Index[" << idx_pos << "] = variable"); + } + + // 加载当前索引到 x10 + EmitValueToReg(indices[idx_pos], PhysReg::X10, slots, block, function); + + // 乘以步长 + block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::X11), Operand::Imm(strides[i])}); + block.Append(Opcode::MulRR, {Operand::Reg(PhysReg::X10), + Operand::Reg(PhysReg::X10), + Operand::Reg(PhysReg::X11)}); + + // 累加到偏移量 + block.Append(Opcode::AddRR, {Operand::Reg(PhysReg::X9), + Operand::Reg(PhysReg::X9), + Operand::Reg(PhysReg::X10)}); + } + + DEBUG_MSG("Total computed offset = " << debug_offset); + + // 最终地址 = base + offset + block.Append(Opcode::AddRR, {Operand::Reg(PhysReg::X8), + Operand::Reg(PhysReg::X8), + Operand::Reg(PhysReg::X9)}); + + // 存储计算出的地址 + block.Append(Opcode::StoreStack, + {Operand::Reg(PhysReg::X8), Operand::FrameIndex(dst_slot)}); + slots.emplace(&inst, dst_slot); + DEBUG_MSG("Array GEP completed, result stored in slot " << dst_slot); + return; + } + + // 其他情况的处理... + DEBUG_MSG("Base is other type, using simple handling"); + if (indices.size() >= 1) { + EmitValueToReg(indices[0], PhysReg::X9, slots, block, function); + + // 乘以元素大小(默认 4 字节) + block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::X10), Operand::Imm(4)}); + block.Append(Opcode::MulRR, {Operand::Reg(PhysReg::X9), + Operand::Reg(PhysReg::X9), + Operand::Reg(PhysReg::X10)}); + + block.Append(Opcode::AddRR, {Operand::Reg(PhysReg::X8), + Operand::Reg(PhysReg::X8), + Operand::Reg(PhysReg::X9)}); + } - // 存储计算出的地址 block.Append(Opcode::StoreStack, {Operand::Reg(PhysReg::X8), Operand::FrameIndex(dst_slot)}); slots.emplace(&inst, dst_slot); + DEBUG_MSG("Simple GEP completed"); return; - } - - // 其他情况:简单处理 - // 只处理第一个索引 - if (indices.size() >= 1) { - EmitValueToReg(indices[0], PhysReg::X9, slots, block, function); - - // 乘以元素大小(默认 4 字节) - block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::X10), Operand::Imm(4)}); - block.Append(Opcode::MulRR, {Operand::Reg(PhysReg::X9), - Operand::Reg(PhysReg::X9), - Operand::Reg(PhysReg::X10)}); - - block.Append(Opcode::AddRR, {Operand::Reg(PhysReg::X8), - Operand::Reg(PhysReg::X8), - Operand::Reg(PhysReg::X9)}); - } - - // 存储计算出的地址 - block.Append(Opcode::StoreStack, - {Operand::Reg(PhysReg::X8), Operand::FrameIndex(dst_slot)}); - slots.emplace(&inst, dst_slot); - return; } // 处理 Trunc 指令 case ir::Opcode::Trunc: { -- 2.34.1 From bbfb8f2c69418d8ace0fb71a876358f9ab1a0768 Mon Sep 17 00:00:00 2001 From: mxr <> Date: Mon, 13 Apr 2026 22:01:51 +0800 Subject: [PATCH 22/30] =?UTF-8?q?feat(mir)=E9=93=BE=E6=8E=A5=E5=AE=8C?= =?UTF-8?q?=E6=95=B4=E7=9A=84=20SysY=20=E8=BF=90=E8=A1=8C=E6=97=B6?= =?UTF-8?q?=E5=BA=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/libsysy.a | Bin 0 -> 12296 bytes scripts/verify_asm.sh | 3 ++- src/mir/AsmPrinter.cpp | 14 +++++++++++++- src/mir/Lowering.cpp | 2 +- 4 files changed, 16 insertions(+), 3 deletions(-) create mode 100644 lib/libsysy.a diff --git a/lib/libsysy.a b/lib/libsysy.a new file mode 100644 index 0000000000000000000000000000000000000000..c6fe87c3e029ad81e2937cac25d174e3030940d7 GIT binary patch literal 12296 zcmdT~U2Igx6`tKS;2JkJ!6~%R_?n;8cFlV2SOEe`7Lx=g&|n#-B8sEk_5R>Z)@yh7 zI7s-$1$0B(V`G_v06Qk-t(oSb>&f)`njpcH& zF*Q8mpp+3xR~PM1riOCK$Y3m;Rk4(v%(+Fd%1#d^wKjWb*r}@gSSH;c94b1}%Y%<} zbU2=CYYTO3aZ1supFO$fDZkH0j&zexy`xGsjVg8hp;9^Q6vJwTs#Wu^sSoB3`cBR5 zRFecBQ7U}fN59!+it>p+6;`Ur*?{`B+vael3d_PXgf(mar^~{({nRI}{QvM%pRiKB z)HYQJ_?qVq?l?s{CNBgcfB8~f^<{L`hqvC9u6KD{{!??LyFg>nwmM_0k+IR3&9Tj| zQZv;`)fHAv%&1$hemF~Gvy}R!$t$c1&!`HuqCot@O7aKQA6M$--CxZ2I(76<&42Sx z=c)O3UH{A-{N1U!0NGowW@hV2zB3=L&+DzgpXUz#;UxPJc?Fj@wXprSB{|F0ZBy2K ztD5;XkFiz8xZE8h%{|Pk%yp}bllsh3nf38Fe@NpD`zCsLo?YGVI=0R4R3FUOs2TEE zowk3rW@4s(wBa1q{i89X{>|G9HDW92=W_j>nxFjh-}4-c6xV99K~40~+L&Q`$xbIG zwJ$AdW555rXm|K_CB?MvJ6k_7v%qGm2XG8juQ2LMjQUceuBiT*#0l9oSqN0}I-Alu zDOQUyaFyh%(f)G{N-Zz7t77}t))S4N%vs~sF?A>Up@01TmDYIu%CJ(q{auH9 zuKK2PYTUoZqB_}jg!E2Q`L6X@D<*r?inojUNY--y_!38FC+R2z{LLz}cArxI-O7G& z-#WsS%$xszsMlFvyv`{$v^~x`k#+E!&vkr-Z!d*-!TF%QvDh~NWtQ_dn*VEoK=Y?G z{;RZKvJN*EmO8Ppa9x-72W<=LX&4W`ah2@y(^})bTXQHk_J@)jlc)Q5$@OaISiV}^ z^VB5uzpc4^PqCExqqC1wY!xWBtZ}tQ$5lfGbA8K=`fiE~i1m^Wd7L~(E#I`&2kQ)d z-%0&=4fRv(_fzcq$JZU}q}cDI*jGCC$^WExawp9V#b8l?>}%-cIli0q)lWLC(RFt{ zu64A={ItgOxcth$ypz`0y&l^)S<7F?kLBj>|8b1G&V96pl;YLB2kHAc;c8=ouaw6n zPdw@rENSSa2gh7^W2hssi7$^5-nD6C;z#t`N57GLmD{g(Z|{yho~Ig4>722`a7e=+Xzd3#=%Tsy0shtGvAEZ?`<# zT|&rN--LZezjF4xE&Q{>x2VqP9r~5y|DJG`e_8m>`X}s?;N85gDV=dMb(wOX^acIO$>E0|)_Y6%&VIoi+{1ym+K^BiMvF%W_x^w* z!pA1@mm~3kmm>#8VmUfCiKO#G@vU1U`FJdwqH2kdilsAOb|exXh~>WYXe4hZlDV8p z4d>{Pg>;n8Z=9nMI&a~8D3zcy7u~3jP1rld6}_4K$7@q3?c*&5uH$PZ;kXO6NXG{Z zJR~?jtnz-Z({?GCdc%U7dU-u^VmaS;i_Uda%BCD0r>2}K;cNRVrG8X$ZNJ8k3vSwf zQgBo6X~9js7eNl%f89gQ4G%dLG=5Inez&GnrQq6rjaLh9+TY?KN8fKvIUOEy`UE%q z5Eb0?!zjo>KO7g_9M`nqradP>PJjrF5!d$z_9xzglpPXT&YR*?u~T zFQyHGb37m(0zN-C>(l{!#KXYHaXkTi#Jhoy{_F)l;!)t^yeEK<_%QG>4sGBgehBz{ zzp!M$hk=i{zHjq-Y1Gc4d1-+Dnl;(fqJJEOoyd;s`3?-}4DZUZ0Vd=&VI9|1n^S6#9< zO#vVAR_B+kubs8wNh&-N483_5vUA zKH#IDqrgXe9QY__0{Do(4t$hz1o((g10Vfx0{DoZ20r@X4Db;@4}6q!0r-et0zR(C z_kfT172uHlhk=jy6!1~bQQ#v!4Sd|6PXHhBGr&hVXMvCSdEld;F909$ z8^A|7H-V4%9pIy#`e@a>Z&p{9kDpq>&G=aje6({d@DXnWKHAv=e8dNUk8(1=M|>3c zC}$k_h#vwz-meb>AMq*Rqnx9_M|>Li=>HSINBn)@qnyjYN4x-hwDTJ95x)t1lyeLC zh~EJ|+9?P3YEk^S2ky>&7Uk3mZpP0Z;G_I*;3M7#e3TyrKH?b<{;&sMKN|2SR2y{# za>gHmx;_J3Lb&`3?zHOjK#l8j?>_0P@hegvH*kIaecZtHIrn)3*XP+E8Mr>rzGdJ_ z{*S67yE$ol^!c!;k#x%q%D<&v3L&`yrpDwv4bF%|63=T$H_ zhge4v->51M#83!6bcK7t9XX$>6SMpWEb|Fp~%toE(UxaxwZ`?w%xz zr0~$?Hd>S!meL`K58WXDmguT;w#-<#h)6*mR>Ja7$1fyVk1V6&|DYU0jLS4o$xRmx zy&9Kk(pAOh(=5~Me@Xgph!&|%LF?CO8x>e4#w@q#{xPmVGW$P9Z9Fzpe@I@PnS5Q> z`Bv&%&VON9bo!pnI(UwBKaKNyE`BFx>fiDe^*=*>%jw@=MnCH|^}j$E`%k|QprVt) zqMzpnlb%1FC#X@Ek(ZJFh;iBEjtOSY->~%WHackgwOpGD<;FiO`FNsS|EO%vueoB1SF^wS8g1Y! ze`C9O>t@SM(W>?7R5p=JS&_)T=l49_8R?2tt*3fAn?#6c*?49ok=#x%wbDaD`ZOAm zSnj|=Xe{5#@3t6hZML4y(pSXRL)OrU&4tuRHg2bfvU#hywTfPiS?*`ZjZH1ihsbX3 z?5mC38hhczrfpTP45bqm^(Mqcn_8$AAAm}!OSYxdQICe$sm9cx-C_lU!6wUnDdz%_ z$d7kKcJ%Dp7l|}kt*ut?-Y51xZn5R`WlB1GplGp`9vsdjd0&t50N8%o)$MfLqT9wu z+_reouf#Hzew|0JGF#j-eXG5#=vnHNb6);6HX)UJH%20Ro__X8vIN-fTR|ch*@7%4 z(=_gTKJu*97HaR%#<4S8D>7{_2;oJsE7M*?wk_rl6dPMa!e9xJL7KowzKE2ONS~c= ztBOQoww+7&kJ!n^#yCZS "$asm_file" echo "汇编已生成: $asm_file" -aarch64-linux-gnu-gcc "$asm_file" -o "$exe" +# 静态链接 +aarch64-linux-gnu-gcc -no-pie "$asm_file" -L./lib -lsysy -static -o "$exe" echo "可执行文件已生成: $exe" if [[ "$run_exec" == true ]]; then diff --git a/src/mir/AsmPrinter.cpp b/src/mir/AsmPrinter.cpp index 4a35a81..5a45801 100644 --- a/src/mir/AsmPrinter.cpp +++ b/src/mir/AsmPrinter.cpp @@ -2,6 +2,7 @@ #include #include +#include #include "utils/Log.h" @@ -447,10 +448,21 @@ void PrintAsm(const MachineModule& module, std::ostream& os) { os << ".size " << g.name << ", " << g.size << "\n\n"; } } - + + static const std::set externalFuncs = { + "getint", "getch", "getarray", "putint", "putch", "putarray", "puts", + "_sysy_starttime", "_sysy_stoptime", "starttime", "stoptime", + "getfloat", "putfloat", "getfarray", "putfarray", "memset", + "sysy_alloc_i32", "sysy_alloc_f32", "sysy_free_i32", "sysy_free_f32", + "sysy_zero_i32", "sysy_zero_f32" + }; DEBUG_MSG("module"); // 遍历所有函数,输出汇编 for (const auto& func : module.GetFunctions()) { + + if (externalFuncs.count(func->GetName())) { + continue; // 跳过库函数桩 + } DEBUG_MSG("func"); PrintAsm(*func, os); os << "\n"; diff --git a/src/mir/Lowering.cpp b/src/mir/Lowering.cpp index 80bd986..53c755d 100644 --- a/src/mir/Lowering.cpp +++ b/src/mir/Lowering.cpp @@ -7,7 +7,7 @@ #include "ir/IR.h" #include "utils/Log.h" -#define DEBUG_Lower +//#define DEBUG_Lower #ifdef DEBUG_Lower #include -- 2.34.1 From 34d483ed47eefa79a2d5c0913016bb7f932c37fd Mon Sep 17 00:00:00 2001 From: mxr <> Date: Mon, 13 Apr 2026 23:27:15 +0800 Subject: [PATCH 23/30] =?UTF-8?q?feat(mir)=E6=9C=AC=E5=9C=B0=E7=BC=96?= =?UTF-8?q?=E8=AF=91SysY=E9=9D=99=E6=80=81=E5=BA=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/libsysy.a | Bin 12296 -> 0 bytes scripts/verify_asm.sh | 2 +- sylib/README.md | 5 +++++ 3 files changed, 6 insertions(+), 1 deletion(-) delete mode 100644 lib/libsysy.a create mode 100644 sylib/README.md diff --git a/lib/libsysy.a b/lib/libsysy.a deleted file mode 100644 index c6fe87c3e029ad81e2937cac25d174e3030940d7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12296 zcmdT~U2Igx6`tKS;2JkJ!6~%R_?n;8cFlV2SOEe`7Lx=g&|n#-B8sEk_5R>Z)@yh7 zI7s-$1$0B(V`G_v06Qk-t(oSb>&f)`njpcH& zF*Q8mpp+3xR~PM1riOCK$Y3m;Rk4(v%(+Fd%1#d^wKjWb*r}@gSSH;c94b1}%Y%<} zbU2=CYYTO3aZ1supFO$fDZkH0j&zexy`xGsjVg8hp;9^Q6vJwTs#Wu^sSoB3`cBR5 zRFecBQ7U}fN59!+it>p+6;`Ur*?{`B+vael3d_PXgf(mar^~{({nRI}{QvM%pRiKB z)HYQJ_?qVq?l?s{CNBgcfB8~f^<{L`hqvC9u6KD{{!??LyFg>nwmM_0k+IR3&9Tj| zQZv;`)fHAv%&1$hemF~Gvy}R!$t$c1&!`HuqCot@O7aKQA6M$--CxZ2I(76<&42Sx z=c)O3UH{A-{N1U!0NGowW@hV2zB3=L&+DzgpXUz#;UxPJc?Fj@wXprSB{|F0ZBy2K ztD5;XkFiz8xZE8h%{|Pk%yp}bllsh3nf38Fe@NpD`zCsLo?YGVI=0R4R3FUOs2TEE zowk3rW@4s(wBa1q{i89X{>|G9HDW92=W_j>nxFjh-}4-c6xV99K~40~+L&Q`$xbIG zwJ$AdW555rXm|K_CB?MvJ6k_7v%qGm2XG8juQ2LMjQUceuBiT*#0l9oSqN0}I-Alu zDOQUyaFyh%(f)G{N-Zz7t77}t))S4N%vs~sF?A>Up@01TmDYIu%CJ(q{auH9 zuKK2PYTUoZqB_}jg!E2Q`L6X@D<*r?inojUNY--y_!38FC+R2z{LLz}cArxI-O7G& z-#WsS%$xszsMlFvyv`{$v^~x`k#+E!&vkr-Z!d*-!TF%QvDh~NWtQ_dn*VEoK=Y?G z{;RZKvJN*EmO8Ppa9x-72W<=LX&4W`ah2@y(^})bTXQHk_J@)jlc)Q5$@OaISiV}^ z^VB5uzpc4^PqCExqqC1wY!xWBtZ}tQ$5lfGbA8K=`fiE~i1m^Wd7L~(E#I`&2kQ)d z-%0&=4fRv(_fzcq$JZU}q}cDI*jGCC$^WExawp9V#b8l?>}%-cIli0q)lWLC(RFt{ zu64A={ItgOxcth$ypz`0y&l^)S<7F?kLBj>|8b1G&V96pl;YLB2kHAc;c8=ouaw6n zPdw@rENSSa2gh7^W2hssi7$^5-nD6C;z#t`N57GLmD{g(Z|{yho~Ig4>722`a7e=+Xzd3#=%Tsy0shtGvAEZ?`<# zT|&rN--LZezjF4xE&Q{>x2VqP9r~5y|DJG`e_8m>`X}s?;N85gDV=dMb(wOX^acIO$>E0|)_Y6%&VIoi+{1ym+K^BiMvF%W_x^w* z!pA1@mm~3kmm>#8VmUfCiKO#G@vU1U`FJdwqH2kdilsAOb|exXh~>WYXe4hZlDV8p z4d>{Pg>;n8Z=9nMI&a~8D3zcy7u~3jP1rld6}_4K$7@q3?c*&5uH$PZ;kXO6NXG{Z zJR~?jtnz-Z({?GCdc%U7dU-u^VmaS;i_Uda%BCD0r>2}K;cNRVrG8X$ZNJ8k3vSwf zQgBo6X~9js7eNl%f89gQ4G%dLG=5Inez&GnrQq6rjaLh9+TY?KN8fKvIUOEy`UE%q z5Eb0?!zjo>KO7g_9M`nqradP>PJjrF5!d$z_9xzglpPXT&YR*?u~T zFQyHGb37m(0zN-C>(l{!#KXYHaXkTi#Jhoy{_F)l;!)t^yeEK<_%QG>4sGBgehBz{ zzp!M$hk=i{zHjq-Y1Gc4d1-+Dnl;(fqJJEOoyd;s`3?-}4DZUZ0Vd=&VI9|1n^S6#9< zO#vVAR_B+kubs8wNh&-N483_5vUA zKH#IDqrgXe9QY__0{Do(4t$hz1o((g10Vfx0{DoZ20r@X4Db;@4}6q!0r-et0zR(C z_kfT172uHlhk=jy6!1~bQQ#v!4Sd|6PXHhBGr&hVXMvCSdEld;F909$ z8^A|7H-V4%9pIy#`e@a>Z&p{9kDpq>&G=aje6({d@DXnWKHAv=e8dNUk8(1=M|>3c zC}$k_h#vwz-meb>AMq*Rqnx9_M|>Li=>HSINBn)@qnyjYN4x-hwDTJ95x)t1lyeLC zh~EJ|+9?P3YEk^S2ky>&7Uk3mZpP0Z;G_I*;3M7#e3TyrKH?b<{;&sMKN|2SR2y{# za>gHmx;_J3Lb&`3?zHOjK#l8j?>_0P@hegvH*kIaecZtHIrn)3*XP+E8Mr>rzGdJ_ z{*S67yE$ol^!c!;k#x%q%D<&v3L&`yrpDwv4bF%|63=T$H_ zhge4v->51M#83!6bcK7t9XX$>6SMpWEb|Fp~%toE(UxaxwZ`?w%xz zr0~$?Hd>S!meL`K58WXDmguT;w#-<#h)6*mR>Ja7$1fyVk1V6&|DYU0jLS4o$xRmx zy&9Kk(pAOh(=5~Me@Xgph!&|%LF?CO8x>e4#w@q#{xPmVGW$P9Z9Fzpe@I@PnS5Q> z`Bv&%&VON9bo!pnI(UwBKaKNyE`BFx>fiDe^*=*>%jw@=MnCH|^}j$E`%k|QprVt) zqMzpnlb%1FC#X@Ek(ZJFh;iBEjtOSY->~%WHackgwOpGD<;FiO`FNsS|EO%vueoB1SF^wS8g1Y! ze`C9O>t@SM(W>?7R5p=JS&_)T=l49_8R?2tt*3fAn?#6c*?49ok=#x%wbDaD`ZOAm zSnj|=Xe{5#@3t6hZML4y(pSXRL)OrU&4tuRHg2bfvU#hywTfPiS?*`ZjZH1ihsbX3 z?5mC38hhczrfpTP45bqm^(Mqcn_8$AAAm}!OSYxdQICe$sm9cx-C_lU!6wUnDdz%_ z$d7kKcJ%Dp7l|}kt*ut?-Y51xZn5R`WlB1GplGp`9vsdjd0&t50N8%o)$MfLqT9wu z+_reouf#Hzew|0JGF#j-eXG5#=vnHNb6);6HX)UJH%20Ro__X8vIN-fTR|ch*@7%4 z(=_gTKJu*97HaR%#<4S8D>7{_2;oJsE7M*?wk_rl6dPMa!e9xJL7KowzKE2ONS~c= ztBOQoww+7&kJ!n^#yCZS Date: Tue, 14 Apr 2026 15:21:52 +0800 Subject: [PATCH 24/30] =?UTF-8?q?=E4=BF=AE=E5=A4=8DGEP=E4=B8=AD32=E4=BD=8D?= =?UTF-8?q?=E6=95=B4=E5=9E=8B=E7=B4=A2=E5=BC=95=E5=8F=98=E9=87=8F=E8=AF=AF?= =?UTF-8?q?=E7=94=A8=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/mir/Lowering.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/mir/Lowering.cpp b/src/mir/Lowering.cpp index 53c755d..a509514 100644 --- a/src/mir/Lowering.cpp +++ b/src/mir/Lowering.cpp @@ -7,7 +7,7 @@ #include "ir/IR.h" #include "utils/Log.h" -//#define DEBUG_Lower +#define DEBUG_Lower #ifdef DEBUG_Lower #include @@ -765,13 +765,13 @@ void LowerInstruction(const ir::Instruction& inst, MachineFunction& function, } // 加载当前索引到 x10 - EmitValueToReg(indices[idx_pos], PhysReg::X10, slots, block, function); + EmitValueToReg(indices[idx_pos], PhysReg::W10, slots, block, function); // 乘以步长 - block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::X11), Operand::Imm(strides[i])}); - block.Append(Opcode::MulRR, {Operand::Reg(PhysReg::X10), - Operand::Reg(PhysReg::X10), - Operand::Reg(PhysReg::X11)}); + block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::W11), Operand::Imm(strides[i])}); + block.Append(Opcode::MulRR, {Operand::Reg(PhysReg::W10), + Operand::Reg(PhysReg::W10), + Operand::Reg(PhysReg::W11)}); // 累加到偏移量 block.Append(Opcode::AddRR, {Operand::Reg(PhysReg::X9), -- 2.34.1 From 1cf6ed53f19365cbc400292532d0cff1c6c94fb4 Mon Sep 17 00:00:00 2001 From: mxr <> Date: Wed, 15 Apr 2026 15:42:12 +0800 Subject: [PATCH 25/30] =?UTF-8?q?(test)=E8=BE=93=E5=87=BA=E6=96=87?= =?UTF-8?q?=E4=BB=B6=E6=A0=BC=E5=BC=8F=E4=B8=8D=E5=8C=B9=E9=85=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/test_case/performance/if-combine3.out | 2 +- test/test_case/performance/large_loop_array_2.out | 2 +- test/test_case/performance/vector_mul3.out | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/test/test_case/performance/if-combine3.out b/test/test_case/performance/if-combine3.out index da3038d..c08cdd5 100644 --- a/test/test_case/performance/if-combine3.out +++ b/test/test_case/performance/if-combine3.out @@ -1,2 +1,2 @@ 60255 -0 \ No newline at end of file +0 diff --git a/test/test_case/performance/large_loop_array_2.out b/test/test_case/performance/large_loop_array_2.out index 9aea9e0..aa47d0d 100644 --- a/test/test_case/performance/large_loop_array_2.out +++ b/test/test_case/performance/large_loop_array_2.out @@ -1,2 +1,2 @@ 0 -0 \ No newline at end of file +0 diff --git a/test/test_case/performance/vector_mul3.out b/test/test_case/performance/vector_mul3.out index 8fc524f..30c8612 100644 --- a/test/test_case/performance/vector_mul3.out +++ b/test/test_case/performance/vector_mul3.out @@ -1,2 +1,2 @@ 1 -0 \ No newline at end of file +0 -- 2.34.1 From d0ecc5c2e939a767f74684fe2c5bedef18b1386d Mon Sep 17 00:00:00 2001 From: mxr <> Date: Sat, 18 Apr 2026 23:54:34 +0800 Subject: [PATCH 26/30] =?UTF-8?q?(mir)=E4=BF=AE=E5=A4=8D=E4=BC=A0=E9=80=92?= =?UTF-8?q?=E5=8F=82=E6=95=B0=E6=98=AF=E6=8C=87=E9=92=88=E6=97=B6=E5=AD=98?= =?UTF-8?q?=E5=9C=A8=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/mir/Lowering.cpp | 187 ++++++++++++++++++++++++++++--------------- 1 file changed, 122 insertions(+), 65 deletions(-) diff --git a/src/mir/Lowering.cpp b/src/mir/Lowering.cpp index a509514..1c54a86 100644 --- a/src/mir/Lowering.cpp +++ b/src/mir/Lowering.cpp @@ -7,7 +7,7 @@ #include "ir/IR.h" #include "utils/Log.h" -#define DEBUG_Lower +//#define DEBUG_Lower #ifdef DEBUG_Lower #include @@ -208,28 +208,16 @@ void EmitValueToReg(const ir::Value* value, PhysReg target, // ========== 处理全局变量 ========== if (auto* global = dynamic_cast(value)) { - // 加载全局变量的地址到目标寄存器 - // 注意:地址计算需要使用 64 位寄存器 - PhysReg addrReg = target; - bool needMove = false; - - // 如果目标是 32 位寄存器,改用 X8 临时寄存器 - if (target == PhysReg::W0 || target == PhysReg::W1 || target == PhysReg::W2 || - target == PhysReg::W3 || target == PhysReg::W4 || target == PhysReg::W5 || - target == PhysReg::W6 || target == PhysReg::W7 || target == PhysReg::W8 || - target == PhysReg::W9) { - addrReg = PhysReg::X8; - needMove = true; - } - - // 使用 ADRP + ADD 加载全局变量地址 - block.Append(Opcode::Adrp, {Operand::Reg(addrReg), Operand::Label(global->GetName())}); - block.Append(Opcode::AddLabel, {Operand::Reg(addrReg), Operand::Reg(addrReg), Operand::Label(global->GetName())}); - - // 如果需要,将地址移动到目标寄存器 - if (needMove) { - block.Append(Opcode::MovReg, {Operand::Reg(target), Operand::Reg(addrReg)}); + // 如果目标是 32 位寄存器,升级为对应的 64 位寄存器 + PhysReg addrTarget = target; + if (target >= PhysReg::W0 && target <= PhysReg::W30) { + // 映射 Wn → Xn + addrTarget = static_cast( + static_cast(target) - static_cast(PhysReg::W0) + static_cast(PhysReg::X0)); } + // 现在 addrTarget 一定是 64 位寄存器 + block.Append(Opcode::Adrp, {Operand::Reg(addrTarget), Operand::Label(global->GetName())}); + block.Append(Opcode::AddLabel, {Operand::Reg(addrTarget), Operand::Reg(addrTarget), Operand::Label(global->GetName())}); return; } @@ -254,8 +242,19 @@ void EmitValueToReg(const ir::Value* value, PhysReg target, FormatError("mir", "找不到值对应的栈槽: " + valueName)); } - block.Append(Opcode::LoadStack, - {Operand::Reg(target), Operand::FrameIndex(it->second)}); + PhysReg actualTarget = target; + const ir::Type* ty = value->GetType().get(); + bool isPointer = ty->IsPtrInt32() || ty->IsPtrFloat() || ty->IsPtrInt1() + || ty->IsArray(); // 数组类型在地址上下文中视为指针 + + // 若非指针类型且目标是 64 位寄存器,降级为对应的 32 位寄存器(自动零扩展) + if (!isPointer && target >= PhysReg::X0 && target <= PhysReg::X30) { + actualTarget = static_cast( + static_cast(target) - static_cast(PhysReg::X0) + static_cast(PhysReg::W0)); +} + +block.Append(Opcode::LoadStack, + {Operand::Reg(actualTarget), Operand::FrameIndex(it->second)}); } void LowerInstruction(const ir::Instruction& inst, MachineFunction& function, @@ -363,53 +362,85 @@ void LowerInstruction(const ir::Instruction& inst, MachineFunction& function, } case ir::Opcode::Add: { auto& bin = static_cast(inst); - int dst_slot = function.CreateFrameIndex(GetTypeSize(inst.GetType().get())); - EmitValueToReg(bin.GetLhs(), PhysReg::W8, slots, block, function); - EmitValueToReg(bin.GetRhs(), PhysReg::W9, slots, block, function); - block.Append(Opcode::AddRR, {Operand::Reg(PhysReg::W8), - Operand::Reg(PhysReg::W8), - Operand::Reg(PhysReg::W9)}); - block.Append(Opcode::StoreStack, - {Operand::Reg(PhysReg::W8), Operand::FrameIndex(dst_slot)}); + const ir::Type* lhsTy = bin.GetLhs()->GetType().get(); + const ir::Type* rhsTy = bin.GetRhs()->GetType().get(); + + // 指针判断:指令结果类型是指针,或者任一操作数是指针(指针算术) + bool isPointer = (lhsTy->IsPtrInt32() || lhsTy->IsPtrFloat() || lhsTy->IsPtrInt1() || lhsTy->IsArray()) || + (rhsTy->IsPtrInt32() || rhsTy->IsPtrFloat() || rhsTy->IsPtrInt1() || rhsTy->IsArray()) || + inst.GetType()->IsPtrInt32() || inst.GetType()->IsPtrFloat() || inst.GetType()->IsPtrInt1() || inst.GetType()->IsArray(); + int slotSize = isPointer ? 8 : 4; + PhysReg lhsReg = isPointer ? PhysReg::X8 : PhysReg::W8; + PhysReg rhsReg = isPointer ? PhysReg::X9 : PhysReg::W9; + PhysReg dstReg = isPointer ? PhysReg::X8 : PhysReg::W8; + + int dst_slot = function.CreateFrameIndex(slotSize); // 使用计算出的 slotSize + EmitValueToReg(bin.GetLhs(), lhsReg, slots, block, function); + EmitValueToReg(bin.GetRhs(), rhsReg, slots, block, function); + block.Append(Opcode::AddRR, {Operand::Reg(dstReg), Operand::Reg(lhsReg), Operand::Reg(rhsReg)}); + block.Append(Opcode::StoreStack, {Operand::Reg(dstReg), Operand::FrameIndex(dst_slot)}); slots.emplace(&inst, dst_slot); return; } case ir::Opcode::Sub: { auto& bin = static_cast(inst); - int dst_slot = function.CreateFrameIndex(GetTypeSize(inst.GetType().get())); // 分配结果栈槽 - EmitValueToReg(bin.GetLhs(), PhysReg::W8, slots, block, function); - EmitValueToReg(bin.GetRhs(), PhysReg::W9, slots, block, function); - block.Append(Opcode::SubRR, {Operand::Reg(PhysReg::W8), - Operand::Reg(PhysReg::W8), - Operand::Reg(PhysReg::W9)}); - block.Append(Opcode::StoreStack, - {Operand::Reg(PhysReg::W8), Operand::FrameIndex(dst_slot)}); + const ir::Type* lhsTy = bin.GetLhs()->GetType().get(); + const ir::Type* rhsTy = bin.GetRhs()->GetType().get(); + + // 指针判断:指令结果类型是指针,或者任一操作数是指针(指针算术) + bool isPointer = (lhsTy->IsPtrInt32() || lhsTy->IsPtrFloat() || lhsTy->IsPtrInt1() || lhsTy->IsArray()) || + (rhsTy->IsPtrInt32() || rhsTy->IsPtrFloat() || rhsTy->IsPtrInt1() || rhsTy->IsArray()) || + inst.GetType()->IsPtrInt32() || inst.GetType()->IsPtrFloat() || inst.GetType()->IsPtrInt1() || inst.GetType()->IsArray(); + int slotSize = isPointer ? 8 : 4; + PhysReg lhsReg = isPointer ? PhysReg::X8 : PhysReg::W8; + PhysReg rhsReg = isPointer ? PhysReg::X9 : PhysReg::W9; + PhysReg dstReg = isPointer ? PhysReg::X8 : PhysReg::W8; + + int dst_slot = function.CreateFrameIndex(slotSize); // 使用计算出的 slotSize + EmitValueToReg(bin.GetLhs(), lhsReg, slots, block, function); + EmitValueToReg(bin.GetRhs(), rhsReg, slots, block, function); + block.Append(Opcode::SubRR, {Operand::Reg(dstReg), Operand::Reg(lhsReg), Operand::Reg(rhsReg)}); + block.Append(Opcode::StoreStack, {Operand::Reg(dstReg), Operand::FrameIndex(dst_slot)}); slots.emplace(&inst, dst_slot); return; } case ir::Opcode::Mul: { auto& bin = static_cast(inst); + const ir::Type* ty = inst.GetType().get(); + bool isPointer = ty->IsPtrInt32() || ty->IsPtrFloat() || ty->IsPtrInt1(); + int slotSize = isPointer ? 8 : 4; + PhysReg lhsReg = isPointer ? PhysReg::X8 : PhysReg::W8; + PhysReg rhsReg = isPointer ? PhysReg::X9 : PhysReg::W9; + PhysReg dstReg = isPointer ? PhysReg::X8 : PhysReg::W8; // 可复用 lhsReg + int dst_slot = function.CreateFrameIndex(GetTypeSize(inst.GetType().get())); // 分配结果栈槽 - EmitValueToReg(bin.GetLhs(), PhysReg::W8, slots, block, function); - EmitValueToReg(bin.GetRhs(), PhysReg::W9, slots, block, function); - block.Append(Opcode::MulRR, {Operand::Reg(PhysReg::W8), - Operand::Reg(PhysReg::W8), - Operand::Reg(PhysReg::W9)}); + EmitValueToReg(bin.GetLhs(), lhsReg, slots, block, function); + EmitValueToReg(bin.GetRhs(), rhsReg, slots, block, function); + block.Append(Opcode::MulRR, {Operand::Reg(dstReg), + Operand::Reg(lhsReg), + Operand::Reg(rhsReg)}); block.Append(Opcode::StoreStack, - {Operand::Reg(PhysReg::W8), Operand::FrameIndex(dst_slot)}); + {Operand::Reg(dstReg), Operand::FrameIndex(dst_slot)}); slots.emplace(&inst, dst_slot); return; } case ir::Opcode::Div: { auto& bin = static_cast(inst); + const ir::Type* ty = inst.GetType().get(); + bool isPointer = ty->IsPtrInt32() || ty->IsPtrFloat() || ty->IsPtrInt1(); + int slotSize = isPointer ? 8 : 4; + PhysReg lhsReg = isPointer ? PhysReg::X8 : PhysReg::W8; + PhysReg rhsReg = isPointer ? PhysReg::X9 : PhysReg::W9; + PhysReg dstReg = isPointer ? PhysReg::X8 : PhysReg::W8; // 可复用 lhsReg + int dst_slot = function.CreateFrameIndex(GetTypeSize(inst.GetType().get())); // 分配结果栈槽 - EmitValueToReg(bin.GetLhs(), PhysReg::W8, slots, block, function); - EmitValueToReg(bin.GetRhs(), PhysReg::W9, slots, block, function); - block.Append(Opcode::SDivRR, {Operand::Reg(PhysReg::W8), - Operand::Reg(PhysReg::W8), - Operand::Reg(PhysReg::W9)}); + EmitValueToReg(bin.GetLhs(), lhsReg, slots, block, function); + EmitValueToReg(bin.GetRhs(), rhsReg, slots, block, function); + block.Append(Opcode::SDivRR, {Operand::Reg(dstReg), + Operand::Reg(lhsReg), + Operand::Reg(rhsReg)}); block.Append(Opcode::StoreStack, - {Operand::Reg(PhysReg::W8), Operand::FrameIndex(dst_slot)}); + {Operand::Reg(dstReg), Operand::FrameIndex(dst_slot)}); slots.emplace(&inst, dst_slot); return; } @@ -417,7 +448,16 @@ void LowerInstruction(const ir::Instruction& inst, MachineFunction& function, auto& ret = static_cast(inst); const ir::Value* retVal = ret.GetValue(); if (retVal != nullptr) { - EmitValueToReg(retVal, PhysReg::W0, slots, block, function); + const ir::Type* retType = retVal->GetType().get(); + PhysReg retReg = PhysReg::W0; // 默认整数返回值 + if (retType->IsFloat()) { + retReg = PhysReg::S0; + } else if (retType->IsPtrInt32() || retType->IsPtrFloat() || retType->IsPtrInt1()) { + retReg = PhysReg::X0; + } else { + retReg = PhysReg::W0; + } + EmitValueToReg(retVal, retReg, slots, block, function); } block.Append(Opcode::Ret); return; @@ -589,8 +629,13 @@ void LowerInstruction(const ir::Instruction& inst, MachineFunction& function, PhysReg reg = static_cast(static_cast(PhysReg::S0) + fpArgCount); EmitValueToReg(arg, reg, slots, block, function); fpArgCount++; + } else if (argType->IsPtrInt32() || argType->IsPtrFloat() || argType->IsPtrInt1()) { + // 指针参数 → X 寄存器(占用一个整数参数槽) + PhysReg reg = static_cast(static_cast(PhysReg::X0) + intArgCount); + EmitValueToReg(arg, reg, slots, block, function); + intArgCount++; } else { - // 整数参数 + // 普通整数 → W 寄存器 PhysReg reg = static_cast(static_cast(PhysReg::W0) + intArgCount); EmitValueToReg(arg, reg, slots, block, function); intArgCount++; @@ -602,13 +647,17 @@ void LowerInstruction(const ir::Instruction& inst, MachineFunction& function, block.Append(Opcode::Call, {Operand::Label(calleeName)}); // 保存返回值 if (dst_slot != -1) { - if (inst.GetType()->IsFloat()) { - block.Append(Opcode::StoreStack, - {Operand::Reg(PhysReg::S0), Operand::FrameIndex(dst_slot)}); + const ir::Type* retType = inst.GetType().get(); + PhysReg srcReg = PhysReg::W0; + if (retType->IsFloat()) { + srcReg = PhysReg::S0; + } else if (retType->IsPtrInt32() || retType->IsPtrFloat() || retType->IsPtrInt1()) { + srcReg = PhysReg::X0; } else { - block.Append(Opcode::StoreStack, - {Operand::Reg(PhysReg::W0), Operand::FrameIndex(dst_slot)}); + srcReg = PhysReg::W0; } + block.Append(Opcode::StoreStack, + {Operand::Reg(srcReg), Operand::FrameIndex(dst_slot)}); slots.emplace(&inst, dst_slot); } return; @@ -765,13 +814,13 @@ void LowerInstruction(const ir::Instruction& inst, MachineFunction& function, } // 加载当前索引到 x10 - EmitValueToReg(indices[idx_pos], PhysReg::W10, slots, block, function); + EmitValueToReg(indices[idx_pos], PhysReg::X10, slots, block, function); // 乘以步长 - block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::W11), Operand::Imm(strides[i])}); - block.Append(Opcode::MulRR, {Operand::Reg(PhysReg::W10), - Operand::Reg(PhysReg::W10), - Operand::Reg(PhysReg::W11)}); + block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::X11), Operand::Imm(strides[i])}); + block.Append(Opcode::MulRR, {Operand::Reg(PhysReg::X10), + Operand::Reg(PhysReg::X10), + Operand::Reg(PhysReg::X11)}); // 累加到偏移量 block.Append(Opcode::AddRR, {Operand::Reg(PhysReg::X9), @@ -999,6 +1048,7 @@ std::unique_ptr LowerFunction(const ir::Function& func) { const ir::Value* arg; int slot; bool isFloat; + bool isPointer; }; std::vector paramInfos; @@ -1007,7 +1057,8 @@ std::unique_ptr LowerFunction(const ir::Function& func) { int slot = machine_func->CreateFrameIndex(GetTypeSize(arg->GetType().get())); slots.emplace(arg.get(), slot); bool isFloat = arg->GetType()->IsFloat(); - paramInfos.push_back({arg.get(), slot, isFloat}); + bool isPointer = arg->GetType()->IsPtrInt32() || arg->GetType()->IsPtrFloat() || arg->GetType()->IsPtrInt1(); + paramInfos.push_back({arg.get(), slot, isFloat, isPointer}); } // IR 基本块到 MIR 基本块的映射 @@ -1037,6 +1088,12 @@ std::unique_ptr LowerFunction(const ir::Function& func) { {Operand::Reg(reg), Operand::FrameIndex(param.slot)}); } fpArgIdx++; + } else if (param.isPointer) { + if (intArgIdx < 8) { + PhysReg reg = static_cast(static_cast(PhysReg::X0) + intArgIdx); + entryBB->Append(Opcode::StoreStack, {Operand::Reg(reg), Operand::FrameIndex(param.slot)}); + } + intArgIdx++; } else { if (intArgIdx < 8) { PhysReg reg = static_cast(static_cast(PhysReg::W0) + intArgIdx); -- 2.34.1 From fdeb3fc66eea55636120316e5fbe896885f2b647 Mon Sep 17 00:00:00 2001 From: mxr <> Date: Sun, 19 Apr 2026 01:14:58 +0800 Subject: [PATCH 27/30] =?UTF-8?q?(mir)=E4=BF=AE=E5=A4=8D=E5=AF=84=E5=AD=98?= =?UTF-8?q?=E5=99=A8=E9=87=8D=E7=94=A8=E5=86=B2=E7=AA=81=E9=94=99=E8=AF=AF?= =?UTF-8?q?=E5=92=8C=E6=B5=AE=E7=82=B9=E6=AF=94=E8=BE=83=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/mir/Lowering.cpp | 35 +++++++++++++++++++++++++---------- 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/src/mir/Lowering.cpp b/src/mir/Lowering.cpp index 1c54a86..21935d3 100644 --- a/src/mir/Lowering.cpp +++ b/src/mir/Lowering.cpp @@ -177,16 +177,16 @@ void EmitValueToReg(const ir::Value* value, PhysReg target, // 同样需要对 int_val 进行大立即数分解 if (isLegalMovImm(int_val)) { - block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::W8), Operand::Imm(static_cast(int_val))}); + block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::W17), Operand::Imm(static_cast(int_val))}); } else { uint16_t low = int_val & 0xFFFF; uint16_t high = (int_val >> 16) & 0xFFFF; - block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::W8), Operand::Imm(low)}); + block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::W17), Operand::Imm(low)}); if (high != 0) { - block.Append(Opcode::Movk, {Operand::Reg(PhysReg::W8), Operand::Imm(high), Operand::Imm(16)}); + block.Append(Opcode::Movk, {Operand::Reg(PhysReg::W17), Operand::Imm(high), Operand::Imm(16)}); } } - block.Append(Opcode::StoreStack, {Operand::Reg(PhysReg::W8), Operand::FrameIndex(slot)}); + block.Append(Opcode::StoreStack, {Operand::Reg(PhysReg::W17), Operand::FrameIndex(slot)}); const_cast(slots).emplace(value, slot); } else { slot = it->second; @@ -551,18 +551,33 @@ void LowerInstruction(const ir::Instruction& inst, MachineFunction& function, case ir::Opcode::FCmp: { auto& fcmp = static_cast(inst); int dst_slot = function.CreateFrameIndex(GetTypeSize(inst.GetType().get())); - + // 加载浮点操作数到 s0, s1 EmitValueToReg(fcmp.GetLhs(), PhysReg::S0, slots, block, function); EmitValueToReg(fcmp.GetRhs(), PhysReg::S1, slots, block, function); - + // 生成浮点比较指令 block.Append(Opcode::FCmpRR, {Operand::Reg(PhysReg::S0), Operand::Reg(PhysReg::S1)}); - - // 简化实现:存储 1 作为结果 + + // 获取条件码(假设仅处理有序比较,无 NaN) + bool isOrdered; + CondCode cc = FcmpToCondCode(fcmp.GetPredicate(), isOrdered); + // 对于无序比较,当前测试用例未涉及,可暂不支持或报错 + + // 使用 CSET 模式 block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::W8), Operand::Imm(1)}); - block.Append(Opcode::StoreStack, - {Operand::Reg(PhysReg::W8), Operand::FrameIndex(dst_slot)}); + block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::W9), Operand::Imm(0)}); + + std::string true_label = ".L_fcset_true_" + std::to_string(reinterpret_cast(&fcmp)); + std::string end_label = ".L_fcset_end_" + std::to_string(reinterpret_cast(&fcmp)); + + block.Append(Opcode::BCond, {Operand::Cond(cc), Operand::Label(true_label)}); + block.Append(Opcode::MovReg, {Operand::Reg(PhysReg::W8), Operand::Reg(PhysReg::W9)}); + block.Append(Opcode::B, {Operand::Label(end_label)}); + block.Append(Opcode::Label, {Operand::Label(true_label)}); + block.Append(Opcode::Label, {Operand::Label(end_label)}); + + block.Append(Opcode::StoreStack, {Operand::Reg(PhysReg::W8), Operand::FrameIndex(dst_slot)}); slots.emplace(&inst, dst_slot); return; } -- 2.34.1 From 35885f3eba511373021db8336fbdfab012837508 Mon Sep 17 00:00:00 2001 From: mxr <> Date: Wed, 22 Apr 2026 19:51:33 +0800 Subject: [PATCH 28/30] =?UTF-8?q?(mir)=E4=BF=AE=E6=AD=A3=E7=BC=96=E8=AF=91?= =?UTF-8?q?=E7=A8=8B=E5=BA=8F=E6=AD=BB=E5=BE=AA=E7=8E=AF=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/mir/MIR.h | 18 ++- src/mir/AsmPrinter.cpp | 15 ++- src/mir/Lowering.cpp | 299 +++++++++++++++++++++++++++++------------ 3 files changed, 244 insertions(+), 88 deletions(-) diff --git a/include/mir/MIR.h b/include/mir/MIR.h index a879bef..67ef476 100644 --- a/include/mir/MIR.h +++ b/include/mir/MIR.h @@ -140,6 +140,9 @@ enum class Opcode { // 用于全局变量地址计算 Adrp, // ADRP Xd, label AddLabel, // ADD Xd, Xn, :lo12:label + + // 新增 + Sxtw, // 符号扩展字到双字:sxtw Xd, Wn }; // ========== 操作数类 ========== @@ -298,12 +301,21 @@ class MachineModule { int size; // 字节大小 int alignment; // 对齐要求(通常为 4 或 8) bool is_zero_init; // 是否为零初始化 + bool has_init_data; // 是否包含初始化数据(用于标量常量) + uint64_t init_data; // 初始化数据(≤8字节) + // 构造函数,默认零初始化 + GlobalDecl(const std::string& n, int sz, int align, bool zero = true, + bool has_data = false, uint64_t data = 0) + : name(n), size(sz), alignment(align), is_zero_init(zero), + has_init_data(has_data), init_data(data) {} }; - void AddGlobal(const std::string& name, int size, int alignment, bool is_zero_init = true) { - globals_.push_back({name, size, alignment, is_zero_init}); + void AddGlobal(const std::string& name, int size, int alignment, + bool is_zero_init = true, + bool has_init_data = false, uint64_t init_data = 0) { + globals_.emplace_back(name, size, alignment, is_zero_init, + has_init_data, init_data); } - const std::vector& GetGlobals() const { return globals_; } private: diff --git a/src/mir/AsmPrinter.cpp b/src/mir/AsmPrinter.cpp index 5a45801..b5d04f7 100644 --- a/src/mir/AsmPrinter.cpp +++ b/src/mir/AsmPrinter.cpp @@ -384,6 +384,10 @@ void PrintInstruction(std::ostream& os, const MachineInstr& instr, << ops.at(2).GetLabel() << "\n"; break; } + case Opcode::Sxtw: + os << " sxtw " << PhysRegName(ops.at(0).GetReg()) << ", " + << PhysRegName(ops.at(1).GetReg()) << "\n"; + break; default: os << " // unknown instruction\n"; break; @@ -441,8 +445,17 @@ void PrintAsm(const MachineModule& module, std::ostream& os) { os << g.name << ":\n"; if (g.is_zero_init) { os << " .zero " << g.size << "\n"; + } else if (g.has_init_data) { + if (g.size == 4) { + os << " .word " << static_cast(g.init_data) << "\n"; + } else if (g.size == 8) { + os << " .quad " << g.init_data << "\n"; + } else { + // 暂不支持的标量大小,回退为零初始化 + os << " .zero " << g.size << " // unhandled init size\n"; + } } else { - // TODO: 处理非零初始化值(需要从 IR 提取 initializer) + // 有初始值但无法提取(例如数组、结构体) os << " .zero " << g.size << " // unhandled initializer\n"; } os << ".size " << g.name << ", " << g.size << "\n\n"; diff --git a/src/mir/Lowering.cpp b/src/mir/Lowering.cpp index 21935d3..ab5ddd8 100644 --- a/src/mir/Lowering.cpp +++ b/src/mir/Lowering.cpp @@ -21,6 +21,10 @@ namespace { using ValueSlotMap = std::unordered_map; +inline bool IsInt32Type(const ir::Type* type) { + return type && type->IsInt32() && type->Size() == 4; +} + static uint32_t FloatToBits(float f) { uint32_t bits; memcpy(&bits, &f, sizeof(bits)); @@ -364,83 +368,224 @@ void LowerInstruction(const ir::Instruction& inst, MachineFunction& function, auto& bin = static_cast(inst); const ir::Type* lhsTy = bin.GetLhs()->GetType().get(); const ir::Type* rhsTy = bin.GetRhs()->GetType().get(); - + const ir::Type* resultTy = inst.GetType().get(); + // 指针判断:指令结果类型是指针,或者任一操作数是指针(指针算术) bool isPointer = (lhsTy->IsPtrInt32() || lhsTy->IsPtrFloat() || lhsTy->IsPtrInt1() || lhsTy->IsArray()) || - (rhsTy->IsPtrInt32() || rhsTy->IsPtrFloat() || rhsTy->IsPtrInt1() || rhsTy->IsArray()) || - inst.GetType()->IsPtrInt32() || inst.GetType()->IsPtrFloat() || inst.GetType()->IsPtrInt1() || inst.GetType()->IsArray(); + (rhsTy->IsPtrInt32() || rhsTy->IsPtrFloat() || rhsTy->IsPtrInt1() || rhsTy->IsArray()) || + resultTy->IsPtrInt32() || resultTy->IsPtrFloat() || resultTy->IsPtrInt1() || resultTy->IsArray(); + + // 判断是否为纯 32 位有符号整数加法(需要提升为 64 位以避免溢出) + bool isI32 = !isPointer && IsInt32Type(lhsTy) && IsInt32Type(rhsTy) && IsInt32Type(resultTy); + int slotSize = isPointer ? 8 : 4; - PhysReg lhsReg = isPointer ? PhysReg::X8 : PhysReg::W8; - PhysReg rhsReg = isPointer ? PhysReg::X9 : PhysReg::W9; - PhysReg dstReg = isPointer ? PhysReg::X8 : PhysReg::W8; - - int dst_slot = function.CreateFrameIndex(slotSize); // 使用计算出的 slotSize - EmitValueToReg(bin.GetLhs(), lhsReg, slots, block, function); - EmitValueToReg(bin.GetRhs(), rhsReg, slots, block, function); + int dst_slot = function.CreateFrameIndex(slotSize); + + PhysReg lhsReg, rhsReg, dstReg; + if (isI32) { + // 使用 64 位寄存器,先符号扩展 + lhsReg = PhysReg::X8; + rhsReg = PhysReg::X9; + dstReg = PhysReg::X8; + + EmitValueToReg(bin.GetLhs(), PhysReg::W8, slots, block, function); + block.Append(Opcode::Sxtw, {Operand::Reg(PhysReg::X8), Operand::Reg(PhysReg::W8)}); + + EmitValueToReg(bin.GetRhs(), PhysReg::W9, slots, block, function); + block.Append(Opcode::Sxtw, {Operand::Reg(PhysReg::X9), Operand::Reg(PhysReg::W9)}); + } else { + lhsReg = isPointer ? PhysReg::X8 : PhysReg::W8; + rhsReg = isPointer ? PhysReg::X9 : PhysReg::W9; + dstReg = isPointer ? PhysReg::X8 : PhysReg::W8; + EmitValueToReg(bin.GetLhs(), lhsReg, slots, block, function); + EmitValueToReg(bin.GetRhs(), rhsReg, slots, block, function); + } + block.Append(Opcode::AddRR, {Operand::Reg(dstReg), Operand::Reg(lhsReg), Operand::Reg(rhsReg)}); - block.Append(Opcode::StoreStack, {Operand::Reg(dstReg), Operand::FrameIndex(dst_slot)}); + + if (isI32) { + // 结果在 X8 中,只需存储低 32 位(W8) + block.Append(Opcode::StoreStack, {Operand::Reg(PhysReg::W8), Operand::FrameIndex(dst_slot)}); + } else { + block.Append(Opcode::StoreStack, {Operand::Reg(dstReg), Operand::FrameIndex(dst_slot)}); + } slots.emplace(&inst, dst_slot); return; } + case ir::Opcode::Sub: { auto& bin = static_cast(inst); const ir::Type* lhsTy = bin.GetLhs()->GetType().get(); const ir::Type* rhsTy = bin.GetRhs()->GetType().get(); - - // 指针判断:指令结果类型是指针,或者任一操作数是指针(指针算术) + const ir::Type* resultTy = inst.GetType().get(); + bool isPointer = (lhsTy->IsPtrInt32() || lhsTy->IsPtrFloat() || lhsTy->IsPtrInt1() || lhsTy->IsArray()) || - (rhsTy->IsPtrInt32() || rhsTy->IsPtrFloat() || rhsTy->IsPtrInt1() || rhsTy->IsArray()) || - inst.GetType()->IsPtrInt32() || inst.GetType()->IsPtrFloat() || inst.GetType()->IsPtrInt1() || inst.GetType()->IsArray(); + (rhsTy->IsPtrInt32() || rhsTy->IsPtrFloat() || rhsTy->IsPtrInt1() || rhsTy->IsArray()) || + resultTy->IsPtrInt32() || resultTy->IsPtrFloat() || resultTy->IsPtrInt1() || resultTy->IsArray(); + + bool isI32 = !isPointer && IsInt32Type(lhsTy) && IsInt32Type(rhsTy) && IsInt32Type(resultTy); + int slotSize = isPointer ? 8 : 4; - PhysReg lhsReg = isPointer ? PhysReg::X8 : PhysReg::W8; - PhysReg rhsReg = isPointer ? PhysReg::X9 : PhysReg::W9; - PhysReg dstReg = isPointer ? PhysReg::X8 : PhysReg::W8; - - int dst_slot = function.CreateFrameIndex(slotSize); // 使用计算出的 slotSize - EmitValueToReg(bin.GetLhs(), lhsReg, slots, block, function); - EmitValueToReg(bin.GetRhs(), rhsReg, slots, block, function); + int dst_slot = function.CreateFrameIndex(slotSize); + + PhysReg lhsReg, rhsReg, dstReg; + if (isI32) { + lhsReg = PhysReg::X8; + rhsReg = PhysReg::X9; + dstReg = PhysReg::X8; + + EmitValueToReg(bin.GetLhs(), PhysReg::W8, slots, block, function); + block.Append(Opcode::Sxtw, {Operand::Reg(PhysReg::X8), Operand::Reg(PhysReg::W8)}); + + EmitValueToReg(bin.GetRhs(), PhysReg::W9, slots, block, function); + block.Append(Opcode::Sxtw, {Operand::Reg(PhysReg::X9), Operand::Reg(PhysReg::W9)}); + } else { + lhsReg = isPointer ? PhysReg::X8 : PhysReg::W8; + rhsReg = isPointer ? PhysReg::X9 : PhysReg::W9; + dstReg = isPointer ? PhysReg::X8 : PhysReg::W8; + EmitValueToReg(bin.GetLhs(), lhsReg, slots, block, function); + EmitValueToReg(bin.GetRhs(), rhsReg, slots, block, function); + } + block.Append(Opcode::SubRR, {Operand::Reg(dstReg), Operand::Reg(lhsReg), Operand::Reg(rhsReg)}); - block.Append(Opcode::StoreStack, {Operand::Reg(dstReg), Operand::FrameIndex(dst_slot)}); + + if (isI32) { + block.Append(Opcode::StoreStack, {Operand::Reg(PhysReg::W8), Operand::FrameIndex(dst_slot)}); + } else { + block.Append(Opcode::StoreStack, {Operand::Reg(dstReg), Operand::FrameIndex(dst_slot)}); + } slots.emplace(&inst, dst_slot); return; } + case ir::Opcode::Mul: { auto& bin = static_cast(inst); - const ir::Type* ty = inst.GetType().get(); - bool isPointer = ty->IsPtrInt32() || ty->IsPtrFloat() || ty->IsPtrInt1(); + const ir::Type* lhsTy = bin.GetLhs()->GetType().get(); + const ir::Type* rhsTy = bin.GetRhs()->GetType().get(); + const ir::Type* resultTy = inst.GetType().get(); + + // 乘法一般不涉及指针,但保留判断 + bool isPointer = (lhsTy->IsPtrInt32() || lhsTy->IsPtrFloat() || lhsTy->IsPtrInt1()) || + (rhsTy->IsPtrInt32() || rhsTy->IsPtrFloat() || rhsTy->IsPtrInt1()) || + resultTy->IsPtrInt32() || resultTy->IsPtrFloat() || resultTy->IsPtrInt1(); + + bool isI32 = !isPointer && IsInt32Type(lhsTy) && IsInt32Type(rhsTy) && IsInt32Type(resultTy); + int slotSize = isPointer ? 8 : 4; - PhysReg lhsReg = isPointer ? PhysReg::X8 : PhysReg::W8; - PhysReg rhsReg = isPointer ? PhysReg::X9 : PhysReg::W9; - PhysReg dstReg = isPointer ? PhysReg::X8 : PhysReg::W8; // 可复用 lhsReg + int dst_slot = function.CreateFrameIndex(slotSize); - int dst_slot = function.CreateFrameIndex(GetTypeSize(inst.GetType().get())); // 分配结果栈槽 - EmitValueToReg(bin.GetLhs(), lhsReg, slots, block, function); - EmitValueToReg(bin.GetRhs(), rhsReg, slots, block, function); - block.Append(Opcode::MulRR, {Operand::Reg(dstReg), - Operand::Reg(lhsReg), - Operand::Reg(rhsReg)}); - block.Append(Opcode::StoreStack, - {Operand::Reg(dstReg), Operand::FrameIndex(dst_slot)}); + PhysReg lhsReg, rhsReg, dstReg; + if (isI32) { + lhsReg = PhysReg::X8; + rhsReg = PhysReg::X9; + dstReg = PhysReg::X8; + + EmitValueToReg(bin.GetLhs(), PhysReg::W8, slots, block, function); + block.Append(Opcode::Sxtw, {Operand::Reg(PhysReg::X8), Operand::Reg(PhysReg::W8)}); + + EmitValueToReg(bin.GetRhs(), PhysReg::W9, slots, block, function); + block.Append(Opcode::Sxtw, {Operand::Reg(PhysReg::X9), Operand::Reg(PhysReg::W9)}); + } else { + lhsReg = isPointer ? PhysReg::X8 : PhysReg::W8; + rhsReg = isPointer ? PhysReg::X9 : PhysReg::W9; + dstReg = isPointer ? PhysReg::X8 : PhysReg::W8; + EmitValueToReg(bin.GetLhs(), lhsReg, slots, block, function); + EmitValueToReg(bin.GetRhs(), rhsReg, slots, block, function); + } + + block.Append(Opcode::MulRR, {Operand::Reg(dstReg), Operand::Reg(lhsReg), Operand::Reg(rhsReg)}); + + if (isI32) { + block.Append(Opcode::StoreStack, {Operand::Reg(PhysReg::W8), Operand::FrameIndex(dst_slot)}); + } else { + block.Append(Opcode::StoreStack, {Operand::Reg(dstReg), Operand::FrameIndex(dst_slot)}); + } slots.emplace(&inst, dst_slot); return; } + case ir::Opcode::Div: { auto& bin = static_cast(inst); - const ir::Type* ty = inst.GetType().get(); - bool isPointer = ty->IsPtrInt32() || ty->IsPtrFloat() || ty->IsPtrInt1(); + const ir::Type* lhsTy = bin.GetLhs()->GetType().get(); + const ir::Type* rhsTy = bin.GetRhs()->GetType().get(); + const ir::Type* resultTy = inst.GetType().get(); + + bool isPointer = (lhsTy->IsPtrInt32() || lhsTy->IsPtrFloat() || lhsTy->IsPtrInt1()) || + (rhsTy->IsPtrInt32() || rhsTy->IsPtrFloat() || rhsTy->IsPtrInt1()) || + resultTy->IsPtrInt32() || resultTy->IsPtrFloat() || resultTy->IsPtrInt1(); + + bool isI32 = !isPointer && IsInt32Type(lhsTy) && IsInt32Type(rhsTy) && IsInt32Type(resultTy); + int slotSize = isPointer ? 8 : 4; - PhysReg lhsReg = isPointer ? PhysReg::X8 : PhysReg::W8; - PhysReg rhsReg = isPointer ? PhysReg::X9 : PhysReg::W9; - PhysReg dstReg = isPointer ? PhysReg::X8 : PhysReg::W8; // 可复用 lhsReg + int dst_slot = function.CreateFrameIndex(slotSize); - int dst_slot = function.CreateFrameIndex(GetTypeSize(inst.GetType().get())); // 分配结果栈槽 - EmitValueToReg(bin.GetLhs(), lhsReg, slots, block, function); - EmitValueToReg(bin.GetRhs(), rhsReg, slots, block, function); - block.Append(Opcode::SDivRR, {Operand::Reg(dstReg), - Operand::Reg(lhsReg), - Operand::Reg(rhsReg)}); - block.Append(Opcode::StoreStack, - {Operand::Reg(dstReg), Operand::FrameIndex(dst_slot)}); + PhysReg lhsReg, rhsReg, dstReg; + if (isI32) { + lhsReg = PhysReg::X8; + rhsReg = PhysReg::X9; + dstReg = PhysReg::X8; + + EmitValueToReg(bin.GetLhs(), PhysReg::W8, slots, block, function); + block.Append(Opcode::Sxtw, {Operand::Reg(PhysReg::X8), Operand::Reg(PhysReg::W8)}); + + EmitValueToReg(bin.GetRhs(), PhysReg::W9, slots, block, function); + block.Append(Opcode::Sxtw, {Operand::Reg(PhysReg::X9), Operand::Reg(PhysReg::W9)}); + } else { + lhsReg = isPointer ? PhysReg::X8 : PhysReg::W8; + rhsReg = isPointer ? PhysReg::X9 : PhysReg::W9; + dstReg = isPointer ? PhysReg::X8 : PhysReg::W8; + EmitValueToReg(bin.GetLhs(), lhsReg, slots, block, function); + EmitValueToReg(bin.GetRhs(), rhsReg, slots, block, function); + } + + block.Append(Opcode::SDivRR, {Operand::Reg(dstReg), Operand::Reg(lhsReg), Operand::Reg(rhsReg)}); + + if (isI32) { + block.Append(Opcode::StoreStack, {Operand::Reg(PhysReg::W8), Operand::FrameIndex(dst_slot)}); + } else { + block.Append(Opcode::StoreStack, {Operand::Reg(dstReg), Operand::FrameIndex(dst_slot)}); + } + slots.emplace(&inst, dst_slot); + return; + } + + case ir::Opcode::Mod: { + // Mod 指令:a % b = a - (a / b) * b + // 我们直接复用提升策略:使用 64 位运算 + const ir::Value* lhs = inst.GetOperand(0); + const ir::Value* rhs = inst.GetOperand(1); + const ir::Type* lhsTy = lhs->GetType().get(); + const ir::Type* rhsTy = rhs->GetType().get(); + const ir::Type* resultTy = inst.GetType().get(); + + bool isI32 = IsInt32Type(lhsTy) && IsInt32Type(rhsTy) && IsInt32Type(resultTy); + + int dst_slot = function.CreateFrameIndex(4); // 结果总是 32 位 + if (isI32) { + // 加载并扩展 lhs + EmitValueToReg(lhs, PhysReg::W8, slots, block, function); + block.Append(Opcode::Sxtw, {Operand::Reg(PhysReg::X8), Operand::Reg(PhysReg::W8)}); + // 加载并扩展 rhs + EmitValueToReg(rhs, PhysReg::W9, slots, block, function); + block.Append(Opcode::Sxtw, {Operand::Reg(PhysReg::X9), Operand::Reg(PhysReg::W9)}); + + // X10 = X8 / X9 + block.Append(Opcode::SDivRR, {Operand::Reg(PhysReg::X10), Operand::Reg(PhysReg::X8), Operand::Reg(PhysReg::X9)}); + // X10 = X10 * X9 + block.Append(Opcode::MulRR, {Operand::Reg(PhysReg::X10), Operand::Reg(PhysReg::X10), Operand::Reg(PhysReg::X9)}); + // X8 = X8 - X10 + block.Append(Opcode::SubRR, {Operand::Reg(PhysReg::X8), Operand::Reg(PhysReg::X8), Operand::Reg(PhysReg::X10)}); + // 存储低 32 位 + block.Append(Opcode::StoreStack, {Operand::Reg(PhysReg::W8), Operand::FrameIndex(dst_slot)}); + } else { + // 原有逻辑(假设不会用于指针或 64 位整数) + EmitValueToReg(lhs, PhysReg::W8, slots, block, function); + EmitValueToReg(rhs, PhysReg::W9, slots, block, function); + block.Append(Opcode::SDivRR, {Operand::Reg(PhysReg::W10), Operand::Reg(PhysReg::W8), Operand::Reg(PhysReg::W9)}); + block.Append(Opcode::MulRR, {Operand::Reg(PhysReg::W10), Operand::Reg(PhysReg::W10), Operand::Reg(PhysReg::W9)}); + block.Append(Opcode::SubRR, {Operand::Reg(PhysReg::W8), Operand::Reg(PhysReg::W8), Operand::Reg(PhysReg::W10)}); + block.Append(Opcode::StoreStack, {Operand::Reg(PhysReg::W8), Operand::FrameIndex(dst_slot)}); + } slots.emplace(&inst, dst_slot); return; } @@ -900,39 +1045,6 @@ void LowerInstruction(const ir::Instruction& inst, MachineFunction& function, slots.emplace(&inst, dst_slot); return; } - // 处理 Mod 指令 - case ir::Opcode::Mod: { - int dst_slot = function.CreateFrameIndex(GetTypeSize(inst.GetType().get())); - - // 通过操作数获取左右值 - const ir::Value* lhs = nullptr; - const ir::Value* rhs = nullptr; - if (inst.GetNumOperands() >= 2) { - lhs = inst.GetOperand(0); - rhs = inst.GetOperand(1); - } - - if (lhs && rhs) { - EmitValueToReg(lhs, PhysReg::W8, slots, block, function); - EmitValueToReg(rhs, PhysReg::W9, slots, block, function); - - // a % b = a - (a / b) * b - block.Append(Opcode::SDivRR, {Operand::Reg(PhysReg::W10), - Operand::Reg(PhysReg::W8), - Operand::Reg(PhysReg::W9)}); - block.Append(Opcode::MulRR, {Operand::Reg(PhysReg::W10), - Operand::Reg(PhysReg::W10), - Operand::Reg(PhysReg::W9)}); - block.Append(Opcode::SubRR, {Operand::Reg(PhysReg::W8), - Operand::Reg(PhysReg::W8), - Operand::Reg(PhysReg::W10)}); - } - - block.Append(Opcode::StoreStack, - {Operand::Reg(PhysReg::W8), Operand::FrameIndex(dst_slot)}); - slots.emplace(&inst, dst_slot); - return; - } // 处理 And 指令 case ir::Opcode::And: { int dst_slot = function.CreateFrameIndex(GetTypeSize(inst.GetType().get())); @@ -1144,9 +1256,28 @@ std::unique_ptr LowerToMIR(const ir::Module& module) { for (const auto& global : module.GetGlobals()) { int size = GetTypeSize(global->GetType().get()); int alignment = global->GetType()->Alignment(); - // 简化:假设无显式初始化的全局变量都是零初始化 bool is_zero_init = !global->HasInitializer(); - machine_module->AddGlobal(global->GetName(), size, alignment, is_zero_init); + bool has_init_data = false; + uint64_t init_data = 0; + + if (!is_zero_init) { + const auto& init = global->GetInitializer(); + // 简单处理:只支持单个元素的标量初始化(float 或 int) + if (init.size() == 1) { + if (auto* cf = dynamic_cast(init[0])) { + float fval = cf->GetValue(); + uint32_t bits; + memcpy(&bits, &fval, sizeof(bits)); + init_data = bits; + has_init_data = true; + } else if (auto* ci = dynamic_cast(init[0])) { + init_data = static_cast(ci->GetValue()); + has_init_data = true; + } + } + } + machine_module->AddGlobal(global->GetName(), size, alignment, + is_zero_init, has_init_data, init_data); } std::vector globals; -- 2.34.1 From cc41bb60aef1a6d8d36ec4bfe6aee53ce374147c Mon Sep 17 00:00:00 2001 From: mxr <> Date: Mon, 18 May 2026 23:44:09 +0800 Subject: [PATCH 29/30] =?UTF-8?q?feat(mir)=E4=BF=AE=E6=94=B9=E6=B5=AE?= =?UTF-8?q?=E7=82=B9=E6=95=B0=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/verify_asm.sh | 2 +- src/mir/Lowering.cpp | 124 +++++++++++++++++++++++++++++++----------- 2 files changed, 93 insertions(+), 33 deletions(-) diff --git a/scripts/verify_asm.sh b/scripts/verify_asm.sh index f513c6b..c96cb65 100755 --- a/scripts/verify_asm.sh +++ b/scripts/verify_asm.sh @@ -84,7 +84,7 @@ if [[ "$run_exec" == true ]]; then } > "$actual_file" if [[ -f "$expected_file" ]]; then - if diff -u "$expected_file" "$actual_file"; then + if diff -w -u "$expected_file" "$actual_file"; then echo "输出匹配: $expected_file" else echo "输出不匹配: $expected_file" >&2 diff --git a/src/mir/Lowering.cpp b/src/mir/Lowering.cpp index ab5ddd8..c0d6f93 100644 --- a/src/mir/Lowering.cpp +++ b/src/mir/Lowering.cpp @@ -145,6 +145,34 @@ void EmitValueToReg(const ir::Value* value, PhysReg target, if (auto* constant = dynamic_cast(value)) { uint32_t imm = static_cast(constant->GetValue()); + + // 如果目标是浮点寄存器,将 imm 位模式解释为 float 并加载 + if (target >= PhysReg::S0 && target <= PhysReg::S7) { + auto it = slots.find(value); + int slot; + if (it == slots.end()) { + slot = function.CreateFrameIndex(4); + // 将 imm 写入栈槽(与 ConstantFloat 相同方式) + if (isLegalMovImm(imm)) { + block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::W8), Operand::Imm(static_cast(imm))}); + } else { + uint16_t low = imm & 0xFFFF; + uint16_t high = (imm >> 16) & 0xFFFF; + block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::W8), Operand::Imm(low)}); + if (high != 0) { + block.Append(Opcode::Movk, {Operand::Reg(PhysReg::W8), Operand::Imm(high), Operand::Imm(16)}); + } + } + block.Append(Opcode::StoreStack, {Operand::Reg(PhysReg::W8), Operand::FrameIndex(slot)}); + const_cast(slots).emplace(value, slot); + } else { + slot = it->second; + } + // 从栈槽加载到浮点目标寄存器 + block.Append(Opcode::LoadStack, {Operand::Reg(target), Operand::FrameIndex(slot)}); + return; + } + if (isLegalMovImm(imm)) { block.Append(Opcode::MovImm, {Operand::Reg(target), Operand::Imm(static_cast(imm))}); @@ -181,16 +209,16 @@ void EmitValueToReg(const ir::Value* value, PhysReg target, // 同样需要对 int_val 进行大立即数分解 if (isLegalMovImm(int_val)) { - block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::W17), Operand::Imm(static_cast(int_val))}); + block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::W8), Operand::Imm(static_cast(int_val))}); } else { uint16_t low = int_val & 0xFFFF; uint16_t high = (int_val >> 16) & 0xFFFF; - block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::W17), Operand::Imm(low)}); + block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::W8), Operand::Imm(low)}); if (high != 0) { - block.Append(Opcode::Movk, {Operand::Reg(PhysReg::W17), Operand::Imm(high), Operand::Imm(16)}); + block.Append(Opcode::Movk, {Operand::Reg(PhysReg::W8), Operand::Imm(high), Operand::Imm(16)}); } } - block.Append(Opcode::StoreStack, {Operand::Reg(PhysReg::W17), Operand::FrameIndex(slot)}); + block.Append(Opcode::StoreStack, {Operand::Reg(PhysReg::W8), Operand::FrameIndex(slot)}); const_cast(slots).emplace(value, slot); } else { slot = it->second; @@ -204,10 +232,26 @@ void EmitValueToReg(const ir::Value* value, PhysReg target, // 处理零常量 if (dynamic_cast(value) || dynamic_cast(value)) { - // 零常量:直接加载 0 - block.Append(Opcode::MovImm, - {Operand::Reg(target), Operand::Imm(0)}); - return; + // 如果目标是浮点寄存器,必须通过栈槽加载 0.0f 的位模式 + if (target >= PhysReg::S0 && target <= PhysReg::S7) { + auto it = slots.find(value); + int slot; + if (it == slots.end()) { + slot = function.CreateFrameIndex(4); + // 写入 0 + block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::W8), Operand::Imm(0)}); + block.Append(Opcode::StoreStack, {Operand::Reg(PhysReg::W8), Operand::FrameIndex(slot)}); + const_cast(slots).emplace(value, slot); + } else { + slot = it->second; + } + // 加载到浮点寄存器 + block.Append(Opcode::LoadStack, {Operand::Reg(target), Operand::FrameIndex(slot)}); + return; + } + // 原有的整数/指针零常量处理保持不变 + block.Append(Opcode::MovImm, {Operand::Reg(target), Operand::Imm(0)}); + return; } // ========== 处理全局变量 ========== @@ -415,6 +459,16 @@ void LowerInstruction(const ir::Instruction& inst, MachineFunction& function, case ir::Opcode::Sub: { auto& bin = static_cast(inst); + // 如果两个操作数都是浮点类型,则使用浮点减法 + if (bin.GetLhs()->GetType()->IsFloat() && bin.GetRhs()->GetType()->IsFloat()) { + int dst_slot = function.CreateFrameIndex(4); + EmitValueToReg(bin.GetLhs(), PhysReg::S0, slots, block, function); + EmitValueToReg(bin.GetRhs(), PhysReg::S1, slots, block, function); + block.Append(Opcode::FSubRR, {Operand::Reg(PhysReg::S0), Operand::Reg(PhysReg::S0), Operand::Reg(PhysReg::S1)}); + block.Append(Opcode::StoreStack, {Operand::Reg(PhysReg::S0), Operand::FrameIndex(dst_slot)}); + slots.emplace(&inst, dst_slot); + return; + } const ir::Type* lhsTy = bin.GetLhs()->GetType().get(); const ir::Type* rhsTy = bin.GetRhs()->GetType().get(); const ir::Type* resultTy = inst.GetType().get(); @@ -694,37 +748,43 @@ void LowerInstruction(const ir::Instruction& inst, MachineFunction& function, } // ========== 浮点比较指令 ========== case ir::Opcode::FCmp: { - auto& fcmp = static_cast(inst); - int dst_slot = function.CreateFrameIndex(GetTypeSize(inst.GetType().get())); + auto& fcmp = static_cast(inst); + int dst_slot = function.CreateFrameIndex(4); // 结果是 i1(4字节) - // 加载浮点操作数到 s0, s1 - EmitValueToReg(fcmp.GetLhs(), PhysReg::S0, slots, block, function); - EmitValueToReg(fcmp.GetRhs(), PhysReg::S1, slots, block, function); + // 1. 加载浮点操作数并比较 + EmitValueToReg(fcmp.GetLhs(), PhysReg::S0, slots, block, function); + EmitValueToReg(fcmp.GetRhs(), PhysReg::S1, slots, block, function); + block.Append(Opcode::FCmpRR, {Operand::Reg(PhysReg::S0), Operand::Reg(PhysReg::S1)}); - // 生成浮点比较指令 - block.Append(Opcode::FCmpRR, {Operand::Reg(PhysReg::S0), Operand::Reg(PhysReg::S1)}); + // 2. 获取有序/无序标志和条件码 + bool isOrdered; + CondCode cc = FcmpToCondCode(fcmp.GetPredicate(), isOrdered); - // 获取条件码(假设仅处理有序比较,无 NaN) - bool isOrdered; - CondCode cc = FcmpToCondCode(fcmp.GetPredicate(), isOrdered); - // 对于无序比较,当前测试用例未涉及,可暂不支持或报错 + // 3. 结果预设为 0 + block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::W8), Operand::Imm(0)}); - // 使用 CSET 模式 - block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::W8), Operand::Imm(1)}); - block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::W9), Operand::Imm(0)}); + // 4. 生成标签 + std::string set1_label = ".L_fcset_true_" + std::to_string(reinterpret_cast(&fcmp)); + std::string end_label = ".L_fcset_end_" + std::to_string(reinterpret_cast(&fcmp)); - std::string true_label = ".L_fcset_true_" + std::to_string(reinterpret_cast(&fcmp)); - std::string end_label = ".L_fcset_end_" + std::to_string(reinterpret_cast(&fcmp)); + // 5. 处理 NaN 情况 + block.Append(Opcode::BCond, {Operand::Cond(CondCode::VS), Operand::Label(end_label)}); - block.Append(Opcode::BCond, {Operand::Cond(cc), Operand::Label(true_label)}); - block.Append(Opcode::MovReg, {Operand::Reg(PhysReg::W8), Operand::Reg(PhysReg::W9)}); - block.Append(Opcode::B, {Operand::Label(end_label)}); - block.Append(Opcode::Label, {Operand::Label(true_label)}); - block.Append(Opcode::Label, {Operand::Label(end_label)}); + // 6. 正常条件跳转 + block.Append(Opcode::BCond, {Operand::Cond(cc), Operand::Label(set1_label)}); - block.Append(Opcode::StoreStack, {Operand::Reg(PhysReg::W8), Operand::FrameIndex(dst_slot)}); - slots.emplace(&inst, dst_slot); - return; + // 7. 无条件到结束 + block.Append(Opcode::B, {Operand::Label(end_label)}); + + // 8. 置 1 标签 + block.Append(Opcode::Label, {Operand::Label(set1_label)}); + block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::W8), Operand::Imm(1)}); + + // 9. 结束标签并存储结果 + block.Append(Opcode::Label, {Operand::Label(end_label)}); + block.Append(Opcode::StoreStack, {Operand::Reg(PhysReg::W8), Operand::FrameIndex(dst_slot)}); + slots.emplace(&inst, dst_slot); + return; } // ========== 跳转指令(使用标签操作数)========== case ir::Opcode::Br: { -- 2.34.1 From 70234dde708b1998b901ef56fef31a58f96ebfa7 Mon Sep 17 00:00:00 2001 From: mxr <> Date: Tue, 19 May 2026 12:58:24 +0800 Subject: [PATCH 30/30] =?UTF-8?q?fix(mir)=E4=BF=AE=E6=94=B9=E4=B8=B4?= =?UTF-8?q?=E6=97=B6=E5=AF=84=E5=AD=98=E5=99=A8=E4=BD=BF=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/mir/Lowering.cpp | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/src/mir/Lowering.cpp b/src/mir/Lowering.cpp index c0d6f93..0817fbb 100644 --- a/src/mir/Lowering.cpp +++ b/src/mir/Lowering.cpp @@ -154,16 +154,16 @@ void EmitValueToReg(const ir::Value* value, PhysReg target, slot = function.CreateFrameIndex(4); // 将 imm 写入栈槽(与 ConstantFloat 相同方式) if (isLegalMovImm(imm)) { - block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::W8), Operand::Imm(static_cast(imm))}); + block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::W10), Operand::Imm(static_cast(imm))}); } else { uint16_t low = imm & 0xFFFF; uint16_t high = (imm >> 16) & 0xFFFF; - block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::W8), Operand::Imm(low)}); + block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::W10), Operand::Imm(low)}); if (high != 0) { - block.Append(Opcode::Movk, {Operand::Reg(PhysReg::W8), Operand::Imm(high), Operand::Imm(16)}); + block.Append(Opcode::Movk, {Operand::Reg(PhysReg::W10), Operand::Imm(high), Operand::Imm(16)}); } } - block.Append(Opcode::StoreStack, {Operand::Reg(PhysReg::W8), Operand::FrameIndex(slot)}); + block.Append(Opcode::StoreStack, {Operand::Reg(PhysReg::W10), Operand::FrameIndex(slot)}); const_cast(slots).emplace(value, slot); } else { slot = it->second; @@ -209,16 +209,16 @@ void EmitValueToReg(const ir::Value* value, PhysReg target, // 同样需要对 int_val 进行大立即数分解 if (isLegalMovImm(int_val)) { - block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::W8), Operand::Imm(static_cast(int_val))}); + block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::W10), Operand::Imm(static_cast(int_val))}); } else { uint16_t low = int_val & 0xFFFF; uint16_t high = (int_val >> 16) & 0xFFFF; - block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::W8), Operand::Imm(low)}); + block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::W10), Operand::Imm(low)}); if (high != 0) { - block.Append(Opcode::Movk, {Operand::Reg(PhysReg::W8), Operand::Imm(high), Operand::Imm(16)}); + block.Append(Opcode::Movk, {Operand::Reg(PhysReg::W10), Operand::Imm(high), Operand::Imm(16)}); } } - block.Append(Opcode::StoreStack, {Operand::Reg(PhysReg::W8), Operand::FrameIndex(slot)}); + block.Append(Opcode::StoreStack, {Operand::Reg(PhysReg::W10), Operand::FrameIndex(slot)}); const_cast(slots).emplace(value, slot); } else { slot = it->second; @@ -239,8 +239,8 @@ void EmitValueToReg(const ir::Value* value, PhysReg target, if (it == slots.end()) { slot = function.CreateFrameIndex(4); // 写入 0 - block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::W8), Operand::Imm(0)}); - block.Append(Opcode::StoreStack, {Operand::Reg(PhysReg::W8), Operand::FrameIndex(slot)}); + block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::W10), Operand::Imm(0)}); + block.Append(Opcode::StoreStack, {Operand::Reg(PhysReg::W10), Operand::FrameIndex(slot)}); const_cast(slots).emplace(value, slot); } else { slot = it->second; @@ -768,8 +768,13 @@ void LowerInstruction(const ir::Instruction& inst, MachineFunction& function, std::string end_label = ".L_fcset_end_" + std::to_string(reinterpret_cast(&fcmp)); // 5. 处理 NaN 情况 - block.Append(Opcode::BCond, {Operand::Cond(CondCode::VS), Operand::Label(end_label)}); - + if (isOrdered) { + // 有序比较:如果无序 (V=1) → 直接结束(结果为 0) + block.Append(Opcode::BCond, {Operand::Cond(CondCode::VS), Operand::Label(end_label)}); + } else { + // 无序比较:如果无序 (V=1) → 结果置 1 + block.Append(Opcode::BCond, {Operand::Cond(CondCode::VS), Operand::Label(set1_label)}); + } // 6. 正常条件跳转 block.Append(Opcode::BCond, {Operand::Cond(cc), Operand::Label(set1_label)}); -- 2.34.1