#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, W19, W20, W21, W22, W23, W24, W25, W26, W27, W28, X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, S0, S1, S2, S3, S4, S5, S6, S7, S8, S9, S10, S11, S12, S13, S14, S15, X29, X30, SP }; const char* PhysRegName(PhysReg reg); enum class Opcode { Prologue, Epilogue, MovImm, LoadStack, StoreStack, AddRR, SubRR, MulRR, SDivRR, MSubRRRR, FAddRRR, FSubRRR, FMulRRR, FDivRRR, CmpRR, FCmpRR, Cset, B, BCond, Call, Ret, MovReg, Adrp, AddRegImm, LdrRegReg, StrRegReg, SIToFP, FPToSI, ZExt }; class Operand { public: enum class Kind { Reg, Imm, FrameIndex, Global, Label, Cond }; static Operand Reg(PhysReg reg); static Operand Imm(int value); static Operand FrameIndex(int index); static Operand Global(std::string name); static Operand Label(std::string name); static Operand Cond(std::string cond); Kind GetKind() const { return kind_; } PhysReg GetReg() const { return reg_; } int GetImm() const { return imm_; } int GetFrameIndex() const { return imm_; } const std::string& GetGlobalName() const { return str_; } const std::string& GetLabelName() const { return str_; } const std::string& GetCondCode() const { return str_; } private: Operand(Kind kind, PhysReg reg, int imm, std::string str = ""); Kind kind_; PhysReg reg_; int imm_; std::string str_; }; 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& CreateBlock(std::string name); std::vector& GetBlocks() { return blocks_; } const std::vector& GetBlocks() const { return blocks_; } // Stack/Frame management 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_; std::vector blocks_; std::vector frame_slots_; int frame_size_ = 0; }; std::vector> LowerToMIR(const ir::Module& module); void RunRegAlloc(MachineFunction& function); void RunFrameLowering(MachineFunction& function); void RunPeephole(MachineFunction& function); void PrintAsm(const MachineFunction& function, std::ostream& os); void PrintGlobals(const ir::Module& module, std::ostream& os); } // namespace mir