You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

72 lines
2.4 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#include "mir/MIR.h"
#include <algorithm>
#include <stdexcept>
#include <vector>
#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<std::vector<PhysReg>&>(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<FrameSlot> 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<std::vector<FrameSlot>&>(function.GetFrameSlots()).clear();
for (auto& slot : newSlots) {
const_cast<std::vector<FrameSlot>&>(function.GetFrameSlots()).push_back(slot);
}
}
} // namespace mir