// SPDX-License-Identifier: GPL-3.0-or-later #ifndef RCC_CODEGEN_MACHINEREGISTERINFO_H #define RCC_CODEGEN_MACHINEREGISTERINFO_H #include "rcc/CodeGen/LowLevelType.h" #include "rcc/CodeGen/MachineIRTypes.h" #include "rcc/CodeGen/Register.h" #include "rcc/Support/Error.h" #include #include #include #include #include #include #include #include namespace rcc { class MachineOperand; class RegOperandIterator final { public: using difference_type = std::ptrdiff_t; // NOLINT(readability-identifier-naming) using value_type = MachineOperand; // NOLINT(readability-identifier-naming) using pointer = MachineOperand *; // NOLINT(readability-identifier-naming) using reference = MachineOperand &; // NOLINT(readability-identifier-naming) using iterator_category = // NOLINT(readability-identifier-naming) std::forward_iterator_tag; RegOperandIterator() = default; [[nodiscard]] reference operator*() const noexcept; [[nodiscard]] pointer operator->() const noexcept; RegOperandIterator &operator++() noexcept; RegOperandIterator operator++(int) noexcept; friend bool operator==(const RegOperandIterator &Left, const RegOperandIterator &Right) noexcept { return Left.Current == Right.Current; } private: RegOperandIterator(MachineOperand *Current, bool RequireUse, bool RequireDef, bool SkipDebug) noexcept; void skipFiltered() noexcept; MachineOperand *Current = nullptr; bool RequireUse = false; bool RequireDef = false; bool SkipDebug = false; friend class RegOperandRange; friend class MachineRegisterInfo; }; class RegOperandRange final { public: [[nodiscard]] RegOperandIterator begin() const noexcept { return RegOperandIterator(Head, RequireUse, RequireDef, SkipDebug); } [[nodiscard]] RegOperandIterator end() const noexcept { return {}; } private: RegOperandRange(MachineOperand *Head, bool RequireUse, bool RequireDef, bool SkipDebug) noexcept : Head(Head), RequireUse(RequireUse), RequireDef(RequireDef), SkipDebug(SkipDebug) {} MachineOperand *Head = nullptr; bool RequireUse = false; bool RequireDef = false; bool SkipDebug = false; friend class MachineRegisterInfo; }; struct VirtualRegisterInfo final { std::optional Type; std::optional Bank; std::optional RegClass; std::vector AllocationHints; bool IsTombstone = false; }; struct PhysicalRegisterLiveIn final { PhysicalRegister PhysReg; std::optional InitialVirtualRegister; friend bool operator==(const PhysicalRegisterLiveIn &Left, const PhysicalRegisterLiveIn &Right) = default; }; class MachineRegisterInfo final { public: MachineRegisterInfo() = default; MachineRegisterInfo(const MachineRegisterInfo &) = delete; MachineRegisterInfo &operator=(const MachineRegisterInfo &) = delete; MachineRegisterInfo(MachineRegisterInfo &&) = delete; MachineRegisterInfo &operator=(MachineRegisterInfo &&) = delete; ~MachineRegisterInfo(); [[nodiscard]] Expected createVirtualRegister(); [[nodiscard]] Expected createVirtualRegister(LLT Type); [[nodiscard]] Expected eraseVirtualRegister(Register Reg); [[nodiscard]] bool isKnownVirtualRegister(Register Reg) const noexcept; [[nodiscard]] std::span virtualRegisters() const noexcept { return VirtualRegisters; } [[nodiscard]] Expected> virtualRegisterInfo(Register Reg); [[nodiscard]] Expected> virtualRegisterInfo(Register Reg) const; [[nodiscard]] Expected setType(Register Reg, LLT Type); [[nodiscard]] Expected clearType(Register Reg); [[nodiscard]] Expected setRegisterBank(Register Reg, RegisterBankID Bank); [[nodiscard]] Expected clearRegisterBank(Register Reg); [[nodiscard]] Expected setRegisterClass(Register Reg, RegisterClassID RegClass); [[nodiscard]] Expected clearRegisterClass(Register Reg); [[nodiscard]] Expected addAllocationHint(Register Reg, PhysicalRegister Hint); void clearAllVirtualRegisterTypes() noexcept; [[nodiscard]] Expected addLiveIn(PhysicalRegister PhysReg, std::optional InitialVirtualRegister = std::nullopt); [[nodiscard]] std::span liveIns() const noexcept { return LiveIns; } [[nodiscard]] Expected reservePhysicalRegister(PhysicalRegister PhysReg); [[nodiscard]] bool isReserved(PhysicalRegister PhysReg) const noexcept; [[nodiscard]] std::span reservedRegisters() const noexcept { return ReservedRegisters; } [[nodiscard]] RegOperandRange regOperands(Register Reg) noexcept; [[nodiscard]] RegOperandRange regNoDebugOperands(Register Reg) noexcept; [[nodiscard]] RegOperandRange useOperands(Register Reg, bool IncludeDebug = true) noexcept; [[nodiscard]] RegOperandRange defOperands(Register Reg) noexcept; [[nodiscard]] bool useEmpty(Register Reg, bool IncludeDebug = true) const noexcept; [[nodiscard]] bool hasOneUse(Register Reg, bool IncludeDebug = true) const noexcept; [[nodiscard]] const MachineOperand *getUniqueVRegDef(Register Reg) const noexcept; [[nodiscard]] Expected replaceRegWith(Register OldReg, Register NewReg); [[nodiscard]] Expected verifyDefUseChains() const; [[nodiscard]] bool isLinkedOperand(const MachineOperand &Operand) const noexcept; private: struct RegOperandListHead final { MachineOperand *Head = nullptr; }; [[nodiscard]] MachineOperand *headFor(Register Reg) const noexcept; void linkOperand(MachineOperand &Operand); std::vector VirtualRegisters; std::vector LiveIns; std::vector ReservedRegisters; std::unordered_map> DefUseHeads; friend class MachineOperand; }; } // namespace rcc #endif // RCC_CODEGEN_MACHINEREGISTERINFO_H