#pragma once #include #include #include #include #include namespace ir { class Module; } namespace mir { class MIRContext { public: MIRContext() = default; }; MIRContext& DefaultContext(); enum class PhysReg { W0, W1, W2, W3, W4, W5, W6, W7, W8, W9, W10, W11, W12, W13, W14, W15, W16, W17, W18, W19, W20, W21, W22, W23, W24, W25, W26, W27, W28, W29, W30, X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, XZR, SP, WZR }; const char* PhysRegName(PhysReg reg); enum class Opcode { Prologue, Epilogue, MovImm, LoadStack, StoreStack, AddRR, SubRR, MulRR, DivRR, ModRR, AndRR, OrRR, XorRR, ShlRR, ShrRR, CmpRR, CSet, Br, CondBr, Call, Ret, LoadAddr, MovReg, }; enum class CondCode { EQ, NE, LT, LE, GT, GE }; class Operand { public: enum class Kind { Reg, Imm, FrameIndex, Label }; static Operand Reg(PhysReg reg); static Operand Imm(int value); static Operand FrameIndex(int index); static Operand Label(int label_id); Kind GetKind() const { return kind_; } PhysReg GetReg() const { return reg_; } int GetImm() const { return imm_; } int GetFrameIndex() const { return imm_; } int GetLabel() 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