#pragma once #include #include #include #include #include namespace ir { class Module; } namespace mir { class MIRContext { public: MIRContext() = default; }; MIRContext& DefaultContext(); enum class PhysReg { W0, W8, W9, X29, X30, SP }; const char* PhysRegName(PhysReg reg); enum class Opcode { Prologue, Epilogue, MovImm, LoadStack, StoreStack, AddRR, Ret, }; class Operand { public: enum class Kind { Reg, Imm, FrameIndex }; static Operand Reg(PhysReg reg); static Operand Imm(int value); static Operand FrameIndex(int index); Kind GetKind() const { return kind_; } PhysReg GetReg() const { return reg_; } int GetImm() const { return imm_; } int GetFrameIndex() const { return imm_; } private: Operand(Kind kind, PhysReg reg, int imm); Kind kind_; PhysReg reg_; int imm_; }; class MachineInstr { public: MachineInstr(Opcode opcode, std::vector operands = {}); Opcode GetOpcode() const { return opcode_; } const std::vector& GetOperands() const { return operands_; } private: Opcode opcode_; std::vector operands_; }; struct FrameSlot { int index = 0; int size = 4; int offset = 0; }; class MachineBasicBlock { public: explicit MachineBasicBlock(std::string name); const std::string& GetName() const { return name_; } std::vector& GetInstructions() { return instructions_; } const std::vector& GetInstructions() const { return instructions_; } MachineInstr& Append(Opcode opcode, std::initializer_list operands = {}); private: std::string name_; std::vector instructions_; }; class MachineFunction { public: explicit MachineFunction(std::string name); const std::string& GetName() const { return name_; } MachineBasicBlock& GetEntry() { return entry_; } const MachineBasicBlock& GetEntry() const { return entry_; } int CreateFrameIndex(int size = 4); FrameSlot& GetFrameSlot(int index); const FrameSlot& GetFrameSlot(int index) const; const std::vector& GetFrameSlots() const { return frame_slots_; } int GetFrameSize() const { return frame_size_; } void SetFrameSize(int size) { frame_size_ = size; } private: std::string name_; MachineBasicBlock entry_; std::vector frame_slots_; int frame_size_ = 0; }; std::unique_ptr LowerToMIR(const ir::Module& module); void RunRegAlloc(MachineFunction& function); void RunFrameLowering(MachineFunction& function); void PrintAsm(const MachineFunction& function, std::ostream& os); } // namespace mir