diff options
| author | Richard-Qin-X <richard.qin.001@gmail.com> | 2026-08-01 16:07:24 +0800 |
|---|---|---|
| committer | Richard-Qin-X <richard.qin.001@gmail.com> | 2026-08-01 16:07:24 +0800 |
| commit | 924dcd36ebed84f04729de05ec08b311a36a04c1 (patch) | |
| tree | 300af742968d4d48915ef178855741f7087fc979 /backend/include/rcc/CodeGen/TargetRegisterInfo.h | |
| parent | cfdbcc469f9691bd9dce3b0b86982a63d86ca6b7 (diff) | |
| download | rcc-project-924dcd36ebed84f04729de05ec08b311a36a04c1.tar.gz rcc-project-924dcd36ebed84f04729de05ec08b311a36a04c1.tar.xz | |
[CodeGen] Add target register descriptions
Introduce an immutable register topology for units, subregisters, classes, banks, and preserved masks. Bind instruction descriptors to this topology through TargetDescription so builders, cloning, and verification share one target-aware contract. Add the test-only TestTarget model and positive and negative target fact coverage.
Diffstat (limited to 'backend/include/rcc/CodeGen/TargetRegisterInfo.h')
| -rw-r--r-- | backend/include/rcc/CodeGen/TargetRegisterInfo.h | 192 |
1 files changed, 192 insertions, 0 deletions
diff --git a/backend/include/rcc/CodeGen/TargetRegisterInfo.h b/backend/include/rcc/CodeGen/TargetRegisterInfo.h new file mode 100644 index 0000000..5d7de2c --- /dev/null +++ b/backend/include/rcc/CodeGen/TargetRegisterInfo.h @@ -0,0 +1,192 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef RCC_CODEGEN_TARGETREGISTERINFO_H +#define RCC_CODEGEN_TARGETREGISTERINFO_H + +#include "rcc/CodeGen/MachineIRTypes.h" +#include "rcc/CodeGen/Register.h" +#include "rcc/CodeGen/RegisterMask.h" +#include "rcc/Support/Error.h" + +#include <cstddef> +#include <cstdint> +#include <optional> +#include <span> +#include <string> +#include <string_view> +#include <unordered_map> +#include <unordered_set> +#include <utility> +#include <vector> + +namespace rcc { + +struct RegisterUnitDesc final { + RegisterUnitID ID; + std::string Name; +}; + +struct RegisterUnitLane final { + RegisterUnitID Unit; + LaneMask Lanes; +}; + +struct PhysicalRegisterDesc final { + PhysicalRegister Reg; + std::string Name; + std::uint32_t Encoding = 0; + std::vector<RegisterUnitLane> Units; + bool IsConstant = false; + bool IsArtificial = false; +}; + +struct SubRegIndexDesc final { + SubRegIndex ID; + std::string Name; + LaneMask Lanes; + std::uint32_t SizeInBits = 0; + std::uint32_t OffsetInBits = 0; +}; + +struct PhysicalSubRegisterDesc final { + PhysicalRegister SuperReg; + SubRegIndex Index; + PhysicalRegister SubReg; +}; + +struct SubRegIndexComposition final { + SubRegIndex First; + SubRegIndex Second; + SubRegIndex Result; +}; + +struct RegisterClassDesc final { + RegisterClassID ID; + std::string Name; + std::vector<PhysicalRegister> Registers; + std::vector<PhysicalRegister> AllocationOrder; + std::uint32_t SizeInBits = 0; + std::uint32_t SpillSizeInBits = 0; + std::uint32_t SpillAlignmentInBits = 0; + LaneMask Lanes; + std::vector<SubRegIndex> SupportedSubRegs; + std::vector<RegisterClassID> SuperClasses; + RegisterBankID DefaultBank; + bool Allocatable = true; + std::uint32_t CopyCost = 1; + bool CoveredBySubRegs = false; +}; + +struct SubRegClassMapping final { + RegisterClassID SourceClass; + SubRegIndex Index; + RegisterClassID ResultClass; +}; + +struct RegisterBankDesc final { + RegisterBankID ID; + std::string Name; + std::uint32_t MaximumSizeInBits = 0; + std::vector<RegisterClassID> RegisterClasses; +}; + +struct TargetRegisterInfoDesc final { + std::vector<RegisterUnitDesc> RegisterUnits; + std::vector<PhysicalRegisterDesc> PhysicalRegisters; + std::vector<SubRegIndexDesc> SubRegIndices; + std::vector<PhysicalSubRegisterDesc> PhysicalSubRegisters; + std::vector<SubRegIndexComposition> SubRegCompositions; + std::vector<RegisterClassDesc> RegisterClasses; + std::vector<SubRegClassMapping> SubRegClassMappings; + std::vector<RegisterBankDesc> RegisterBanks; +}; + +class TargetRegisterInfo final { +public: + [[nodiscard]] static Expected<TargetRegisterInfo> create(TargetRegisterInfoDesc Description); + + [[nodiscard]] std::span<const RegisterUnitDesc> registerUnits() const noexcept { + return Description.RegisterUnits; + } + + [[nodiscard]] std::span<const PhysicalRegisterDesc> physicalRegisters() const noexcept { + return Description.PhysicalRegisters; + } + + [[nodiscard]] std::span<const SubRegIndexDesc> subRegIndices() const noexcept { + return Description.SubRegIndices; + } + + [[nodiscard]] std::span<const RegisterClassDesc> registerClasses() const noexcept { + return Description.RegisterClasses; + } + + [[nodiscard]] std::span<const RegisterBankDesc> registerBanks() const noexcept { + return Description.RegisterBanks; + } + + [[nodiscard]] const RegisterUnitDesc *registerUnit(RegisterUnitID ID) const noexcept; + [[nodiscard]] const PhysicalRegisterDesc *physicalRegister(PhysicalRegister Reg) const noexcept; + [[nodiscard]] const PhysicalRegisterDesc *physicalRegister(std::string_view Name) const noexcept; + [[nodiscard]] const SubRegIndexDesc *subRegIndex(SubRegIndex Index) const noexcept; + [[nodiscard]] const RegisterClassDesc *registerClass(RegisterClassID ID) const noexcept; + [[nodiscard]] const RegisterBankDesc *registerBank(RegisterBankID ID) const noexcept; + + [[nodiscard]] bool isKnownPhysicalRegister(PhysicalRegister Reg) const noexcept { + return physicalRegister(Reg) != nullptr; + } + + [[nodiscard]] LaneMask registerLaneMask(PhysicalRegister Reg) const noexcept; + [[nodiscard]] bool isValidLaneMask(PhysicalRegister Reg, LaneMask Lanes) const noexcept; + [[nodiscard]] bool regsOverlap(PhysicalRegister Left, PhysicalRegister Right) const noexcept; + [[nodiscard]] std::span<const PhysicalRegister> aliases(PhysicalRegister Reg) const noexcept; + + [[nodiscard]] std::optional<PhysicalRegister> subRegister(PhysicalRegister SuperReg, + SubRegIndex Index) const noexcept; + [[nodiscard]] bool isSubRegister(PhysicalRegister SuperReg, + PhysicalRegister SubReg) const noexcept; + [[nodiscard]] std::span<const PhysicalRegister> + superRegisters(PhysicalRegister Reg) const noexcept; + [[nodiscard]] std::optional<SubRegIndex> composeSubRegIndices(SubRegIndex First, + SubRegIndex Second) const noexcept; + + [[nodiscard]] bool registerClassContains(RegisterClassID Class, + PhysicalRegister Reg) const noexcept; + [[nodiscard]] bool isSubclass(RegisterClassID Candidate, RegisterClassID Required) const noexcept; + [[nodiscard]] bool registerClassesOverlap(RegisterClassID Left, + RegisterClassID Right) const noexcept; + [[nodiscard]] std::optional<RegisterClassID> subRegClass(RegisterClassID Source, + SubRegIndex Index) const noexcept; + + [[nodiscard]] bool bankCoversClass(RegisterBankID Bank, RegisterClassID Class) const noexcept; + [[nodiscard]] bool bankContainsRegister(RegisterBankID Bank, PhysicalRegister Reg) const noexcept; + [[nodiscard]] bool registerBanksOverlap(RegisterBankID Left, RegisterBankID Right) const noexcept; + + [[nodiscard]] Expected<void> validateRegisterMask(const RegisterMask &Mask) const; + +private: + explicit TargetRegisterInfo(TargetRegisterInfoDesc Description) + : Description(std::move(Description)) {} + + [[nodiscard]] static std::uint64_t pairKey(std::uint32_t First, std::uint32_t Second) noexcept { + return (static_cast<std::uint64_t>(First) << 32U) | Second; + } + + TargetRegisterInfoDesc Description; + std::unordered_map<RegisterUnitID, std::size_t> UnitToIndex; + std::unordered_map<PhysicalRegister, std::size_t> RegisterToIndex; + std::unordered_map<std::string, std::size_t> RegisterNameToIndex; + std::unordered_map<SubRegIndex, std::size_t> SubRegIndexToIndex; + std::unordered_map<RegisterClassID, std::size_t> ClassToIndex; + std::unordered_map<RegisterBankID, std::size_t> BankToIndex; + std::unordered_map<std::uint64_t, PhysicalRegister> SubRegisterMap; + std::unordered_map<std::uint64_t, SubRegIndex> CompositionMap; + std::unordered_map<std::uint64_t, RegisterClassID> SubRegClassMap; + std::unordered_set<std::uint64_t> SubclassRelations; + std::vector<std::vector<PhysicalRegister>> Aliases; + std::vector<std::vector<PhysicalRegister>> SuperRegisters; +}; + +} // namespace rcc + +#endif // RCC_CODEGEN_TARGETREGISTERINFO_H |
