feat(mir)修正栈帧分配错误

mxr 4 weeks ago
parent 0fd3f4b841
commit d5a8affe83

3
.gitignore vendored

@ -73,4 +73,5 @@ test/test_result/
# mxr
# =========================
result.txt
build.sh
build.sh
gdb.sh

@ -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; // 派生类应重写
}
}

@ -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;
}

@ -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;

Loading…
Cancel
Save