From 4132f0b5ca3e8b1fad0f641aa07689ab48489ea9 Mon Sep 17 00:00:00 2001 From: mxr <> Date: Fri, 10 Apr 2026 13:38:06 +0800 Subject: [PATCH] =?UTF-8?q?feat(mir)=E5=AE=9E=E7=8E=B0=E5=A4=9A=E6=9D=A1?= =?UTF-8?q?=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()) {