#include "mir/MIR.h" #include #include #include #include "utils/Log.h" namespace mir { namespace { int AlignTo(int value, int align) { return ((value + align - 1) / align) * align; } } // namespace void RunFrameLowering(MachineFunction& function) { auto& saved = const_cast&>(function.GetCalleeSavedRegs()); auto has_reg = [&](PhysReg r) { return std::find(saved.begin(), saved.end(), r) != saved.end(); }; if (!has_reg(PhysReg::RA)) saved.push_back(PhysReg::RA); if (!has_reg(PhysReg::S0)) saved.push_back(PhysReg::S0); int cursor = 0; std::vector newSlots; // 1. 为每个现有栈槽分配偏移(包括局部变量、溢出槽) for (const auto& slot : function.GetFrameSlots()) { int align = slot.size; cursor = AlignTo(cursor, align); FrameSlot newSlot = slot; newSlot.offset = cursor; newSlots.push_back(newSlot); cursor += slot.size; } // 2. 为 callee-saved 寄存器分配空间(先计算需要保存的寄存器) const auto& savedRegs = function.GetCalleeSavedRegs(); int savedSize = 0; for (PhysReg reg : savedRegs) { bool isFloat = (reg >= PhysReg::FT0 && reg <= PhysReg::FT11) || (reg >= PhysReg::FA0 && reg <= PhysReg::FA7) || (reg == PhysReg::FS0 || reg == PhysReg::FS1); savedSize += isFloat ? 4 : 8; } // 3. 总帧大小 = 局部变量区 + callee-saved 区 + 对齐 int calleeSavedArea = AlignTo(savedSize, 8); cursor = AlignTo(cursor, 16); // 局部变量区对齐 int localVarsSize = cursor; function.SetLocalVarsSize(localVarsSize); int totalFrame = localVarsSize + calleeSavedArea; function.SetFrameSize(totalFrame); // 4. 记录每个 callee-saved 寄存器的偏移(相对于 sp) int offset = localVarsSize; for (PhysReg reg : savedRegs) { bool isFloat = (reg >= PhysReg::FT0 && reg <= PhysReg::FT11) || (reg >= PhysReg::FA0 && reg <= PhysReg::FA7) || (reg == PhysReg::FS0 || reg == PhysReg::FS1); int size = isFloat ? 4 : 8; function.SetCalleeSavedOffset(reg, offset); offset += size; } const_cast&>(function.GetFrameSlots()).clear(); for (auto& slot : newSlots) { const_cast&>(function.GetFrameSlots()).push_back(slot); } } } // namespace mir