From c759cebef15bdac2ef160065efd116fe6ed540a7 Mon Sep 17 00:00:00 2001 From: Richard-Qin-X Date: Sat, 1 Aug 2026 05:27:13 +0800 Subject: [CodeGen] Build the core MachineIR object model Add arena-owned, address-stable MachineFunction, MachineBasicBlock, and MachineInstr nodes with intrusive layout and instruction lists. Model every required MachineOperand category, reciprocal ties, source state, and immutable per-instruction memory references. Implement physical and virtual register def-use chains whose back-links survive operand vector moves, plus vreg properties, tombstones, live-ins, reserved registers, and atomic CFG updates. Exercise ownership, reallocation, unlink/relink, cross-function rejection, and sanitizer paths. --- backend/include/rcc/CodeGen/MachineRegisterInfo.h | 168 ++++++++++++++++++++++ 1 file changed, 168 insertions(+) create mode 100644 backend/include/rcc/CodeGen/MachineRegisterInfo.h (limited to 'backend/include/rcc/CodeGen/MachineRegisterInfo.h') diff --git a/backend/include/rcc/CodeGen/MachineRegisterInfo.h b/backend/include/rcc/CodeGen/MachineRegisterInfo.h new file mode 100644 index 0000000..495853a --- /dev/null +++ b/backend/include/rcc/CodeGen/MachineRegisterInfo.h @@ -0,0 +1,168 @@ +// 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]] 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; + +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 -- cgit v1.2.3