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