#include "mir/MIR.h" #include #include #include "utils/Log.h" namespace mir { namespace { const FrameSlot& GetFrameSlot(const MachineFunction& function, const Operand& operand) { if (operand.GetKind() != Operand::Kind::FrameIndex) { throw std::runtime_error(FormatError("mir", "期望 FrameIndex 操作数")); } return function.GetFrameSlot(operand.GetFrameIndex()); } 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.GetName() << "\n"; os << ".type " << function.GetName() << ", %function\n"; os << function.GetName() << ":\n"; for (const auto& inst : function.GetEntry().GetInstructions()) { const auto& ops = inst.GetOperands(); switch (inst.GetOpcode()) { case Opcode::Prologue: os << " stp x29, x30, [sp, #-16]!\n"; os << " mov x29, sp\n"; if (function.GetFrameSize() > 0) { os << " sub sp, sp, #" << function.GetFrameSize() << "\n"; } break; case Opcode::Epilogue: if (function.GetFrameSize() > 0) { os << " add sp, sp, #" << function.GetFrameSize() << "\n"; } os << " ldp x29, x30, [sp], #16\n"; break; case Opcode::MovImm: os << " mov " << PhysRegName(ops.at(0).GetReg()) << ", #" << ops.at(1).GetImm() << "\n"; break; case Opcode::LoadStack: { const auto& slot = GetFrameSlot(function, ops.at(1)); PrintStackAccess(os, "ldur", ops.at(0).GetReg(), slot.offset); break; } case Opcode::StoreStack: { const auto& slot = GetFrameSlot(function, ops.at(1)); PrintStackAccess(os, "stur", ops.at(0).GetReg(), slot.offset); break; } case Opcode::AddRR: os << " add " << PhysRegName(ops.at(0).GetReg()) << ", " << PhysRegName(ops.at(1).GetReg()) << ", " << PhysRegName(ops.at(2).GetReg()) << "\n"; break; case Opcode::Ret: os << " ret\n"; break; } } os << ".size " << function.GetName() << ", .-" << function.GetName() << "\n"; } } // namespace mir