|
| 1 | +#pragma once |
| 2 | +#include <cstdint> |
| 3 | +#include <vector> |
| 4 | + |
| 5 | +#include "cinder/alloc/arena_list.hpp" |
| 6 | + |
| 7 | +namespace cinder::lir::aarch64 { |
| 8 | + |
| 9 | +enum class Opcode : uint8_t { |
| 10 | + COPY, |
| 11 | + PHI, |
| 12 | + |
| 13 | + ADDXrr, |
| 14 | + ADDXri, |
| 15 | + |
| 16 | + SUBXrr, |
| 17 | + SUBXri, |
| 18 | + MSUBrrr, |
| 19 | + |
| 20 | + MULXrr, |
| 21 | + SDIVrr, |
| 22 | + |
| 23 | + ANDXrr, |
| 24 | + ORRXrr, |
| 25 | + EORXrr, |
| 26 | + |
| 27 | + LSLXri, |
| 28 | + LSRXri, |
| 29 | + ASRXri, |
| 30 | + |
| 31 | + MOVZ, |
| 32 | + MOVK, |
| 33 | + |
| 34 | + LDRXui, |
| 35 | + STRXui, |
| 36 | + |
| 37 | + CMPXrr, |
| 38 | + CMPXri, |
| 39 | + |
| 40 | + B, |
| 41 | + B_EQ, |
| 42 | + B_NE, |
| 43 | + B_LT, |
| 44 | + B_LE, |
| 45 | + B_GE, |
| 46 | + |
| 47 | + BL, |
| 48 | + RET, |
| 49 | +}; |
| 50 | +class Register final { |
| 51 | + public: |
| 52 | + enum class Kind : uint8_t { Virtual, Phyiscal }; |
| 53 | + enum class RegClass : uint8_t { |
| 54 | + GPR32, |
| 55 | + GPR64, |
| 56 | + FPR32, |
| 57 | + FPR64, |
| 58 | + |
| 59 | + VECTOR_128 |
| 60 | + }; |
| 61 | + |
| 62 | + explicit constexpr Register(Kind kind, uint32_t id, RegClass reg_class) |
| 63 | + : id_(id), kind_(kind), reg_class_(reg_class) {} |
| 64 | + |
| 65 | + static constexpr Register vreg(uint32_t id, RegClass reg_class) { |
| 66 | + return Register(Kind::Virtual, id, reg_class); |
| 67 | + } |
| 68 | + |
| 69 | + static constexpr Register preg(uint32_t id, RegClass reg_class) { |
| 70 | + return Register(Kind::Phyiscal, id, reg_class); |
| 71 | + } |
| 72 | + |
| 73 | + [[nodiscard]] uint32_t id() const { return id_; } |
| 74 | + [[nodiscard]] RegClass reg_class() const { return reg_class_; } |
| 75 | + [[nodiscard]] Kind kind() const { return kind_; } |
| 76 | + |
| 77 | + private: |
| 78 | + uint32_t id_; |
| 79 | + Kind kind_; |
| 80 | + RegClass reg_class_; |
| 81 | +}; |
| 82 | + |
| 83 | +class StackSlot final {}; |
| 84 | + |
| 85 | +class Operand { |
| 86 | + public: |
| 87 | + enum class Kind { Register, Immediate, StackSlot }; |
| 88 | + static constexpr Operand reg(Register r) { return Operand(r); } |
| 89 | + static constexpr Operand imm(std::uint64_t value) { return Operand(value); } |
| 90 | + static constexpr Operand slot(StackSlot s) { return Operand(s); } |
| 91 | + |
| 92 | + [[nodiscard]] Kind kind() const { return kind_; } |
| 93 | + |
| 94 | + [[nodiscard]] bool is_register() const { return kind_ == Kind::Register; } |
| 95 | + [[nodiscard]] bool is_immediate() const { return kind_ == Kind::Register; } |
| 96 | + [[nodiscard]] bool is_stack_slot() const { return kind_ == Kind::Register; } |
| 97 | + |
| 98 | + [[nodiscard]] Register reg() const { |
| 99 | + assert(kind_ == Kind::Register && "Called reg() on non register operand"); |
| 100 | + return reg_; |
| 101 | + } |
| 102 | + [[nodiscard]] uint64_t imm() const { |
| 103 | + assert(kind_ == Kind::Immediate && "Called imm() on non immediate operand"); |
| 104 | + return imm_; |
| 105 | + } |
| 106 | + [[nodiscard]] StackSlot stack_slot() const { |
| 107 | + assert(kind_ == Kind::StackSlot && "Called stack_slot() on non stack_slot operand"); |
| 108 | + return stack_slot_; |
| 109 | + } |
| 110 | + |
| 111 | + private: |
| 112 | + explicit constexpr Operand(Register reg) : kind_(Kind::Register), reg_(reg) {} |
| 113 | + explicit constexpr Operand(uint64_t imm) : kind_(Kind::Immediate), imm_(imm) {} |
| 114 | + explicit constexpr Operand(StackSlot slot) : kind_(Kind::StackSlot), stack_slot_(slot) {} |
| 115 | + |
| 116 | + Kind kind_; |
| 117 | + union { |
| 118 | + Register reg_; |
| 119 | + uint64_t imm_; |
| 120 | + StackSlot stack_slot_; |
| 121 | + }; |
| 122 | +}; |
| 123 | + |
| 124 | +class Instruction final : public arena::ListHook<Instruction> { |
| 125 | + public: |
| 126 | + explicit Instruction(Opcode opcode, std::vector<Operand> uses, std::vector<Register> defs, |
| 127 | + std::vector<Register> implicit_uses = {}, |
| 128 | + std::vector<Register> implicit_defs = {}) |
| 129 | + : opcode_(opcode), |
| 130 | + defs_(std::move(defs)), |
| 131 | + uses_(std::move(uses)), |
| 132 | + implicit_defs_(std::move(implicit_defs)), |
| 133 | + implicit_uses_(std::move(implicit_uses)) {} |
| 134 | + |
| 135 | + [[nodiscard]] Opcode opcode() const { return opcode_; } |
| 136 | + |
| 137 | + [[nodiscard]] const std::vector<Operand>& uses() const { return uses_; } |
| 138 | + [[nodiscard]] std::vector<Operand>& uses_mut() { return uses_; } |
| 139 | + |
| 140 | + [[nodiscard]] Operand operand(unsigned n) const { return uses_[n]; } |
| 141 | + |
| 142 | + [[nodiscard]] const std::vector<Register>& defs() const { return defs_; } |
| 143 | + [[nodiscard]] std::vector<Register>& defs_mut() { return defs_; } |
| 144 | + |
| 145 | + [[nodiscard]] const std::vector<Register>& implicit_uses() const { return implicit_uses_; } |
| 146 | + [[nodiscard]] const std::vector<Register>& implicit_defs() const { return implicit_defs_; } |
| 147 | + |
| 148 | + private: |
| 149 | + Opcode opcode_; |
| 150 | + std::vector<Register> defs_; |
| 151 | + std::vector<Operand> uses_; |
| 152 | + std::vector<Register> implicit_defs_; |
| 153 | + std::vector<Register> implicit_uses_; |
| 154 | +}; |
| 155 | + |
| 156 | +class BasicBlock final : public arena::ListHook<BasicBlock> { |
| 157 | + public: |
| 158 | + void add_instruction(Instruction* instruction) { instructions_.push_back(instruction); } |
| 159 | + |
| 160 | + arena::ArenaList<Instruction>& instructions_mut() { return instructions_; } |
| 161 | + const arena::ArenaList<Instruction>& instructions() const { return instructions_; } |
| 162 | + |
| 163 | + private: |
| 164 | + arena::ArenaList<Instruction> instructions_; |
| 165 | +}; |
| 166 | + |
| 167 | +class Function final : public arena::ListHook<Function> { |
| 168 | + public: |
| 169 | + private: |
| 170 | + arena::ArenaList<BasicBlock> blocks_; |
| 171 | +}; |
| 172 | + |
| 173 | +class Module final { |
| 174 | + public: |
| 175 | + private: |
| 176 | + arena::ArenaList<Function> functions_; |
| 177 | +}; |
| 178 | +} // namespace cinder::lir::aarch64 |
0 commit comments