#include "mir/MIR.h" #include #include namespace mir { namespace { const FrameSlot& GetFrameSlot(const MachineFunction& function, const Operand& operand) { if (operand.kind() != Operand::Kind::FrameIndex) { throw std::runtime_error("期望 FrameIndex 操作数"); } return function.frame_slot(operand.frame_index()); } void PrintStackAccess(std::ostream& os, const char* mnemonic, PhysReg reg, int offset) { os << " " << mnemonic << " " << PhysRegName(reg) << ", [x29, #" << offset << "]\n"; } } // namespace void PrintAsm(const MachineFunction& function, std::ostream& os) { os << ".text\n"; os << ".global " << function.name() << "\n"; os << ".type " << function.name() << ", %function\n"; os << function.name() << ":\n"; for (const auto& inst : function.entry().instructions()) { const auto& ops = inst.operands(); switch (inst.opcode()) { case Opcode::Prologue: os << " stp x29, x30, [sp, #-16]!\n"; os << " mov x29, sp\n"; if (function.frame_size() > 0) { os << " sub sp, sp, #" << function.frame_size() << "\n"; } break; case Opcode::Epilogue: if (function.frame_size() > 0) { os << " add sp, sp, #" << function.frame_size() << "\n"; } os << " ldp x29, x30, [sp], #16\n"; break; case Opcode::MovImm: os << " mov " << PhysRegName(ops.at(0).reg()) << ", #" << ops.at(1).imm() << "\n"; break; case Opcode::LoadStack: { const auto& slot = GetFrameSlot(function, ops.at(1)); PrintStackAccess(os, "ldur", ops.at(0).reg(), slot.offset); break; } case Opcode::StoreStack: { const auto& slot = GetFrameSlot(function, ops.at(1)); PrintStackAccess(os, "stur", ops.at(0).reg(), slot.offset); break; } case Opcode::AddRR: os << " add " << PhysRegName(ops.at(0).reg()) << ", " << PhysRegName(ops.at(1).reg()) << ", " << PhysRegName(ops.at(2).reg()) << "\n"; break; case Opcode::Ret: os << " ret\n"; break; } } os << ".size " << function.name() << ", .-" << function.name() << "\n"; } } // namespace mir