aboutsummaryrefslogtreecommitdiff
path: root/backend/include/rcc
diff options
context:
space:
mode:
authorRichard-Qin-X <richard.qin.001@gmail.com>2026-08-01 16:07:24 +0800
committerRichard-Qin-X <richard.qin.001@gmail.com>2026-08-01 16:07:24 +0800
commit924dcd36ebed84f04729de05ec08b311a36a04c1 (patch)
tree300af742968d4d48915ef178855741f7087fc979 /backend/include/rcc
parentcfdbcc469f9691bd9dce3b0b86982a63d86ca6b7 (diff)
downloadrcc-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')
-rw-r--r--backend/include/rcc/CodeGen/MachineFunctionCloner.h6
-rw-r--r--backend/include/rcc/CodeGen/MachineIRBuilder.h12
-rw-r--r--backend/include/rcc/CodeGen/MachineIRTypes.h2
-rw-r--r--backend/include/rcc/CodeGen/MachineVerifier.h4
-rw-r--r--backend/include/rcc/CodeGen/TargetDescription.h98
-rw-r--r--backend/include/rcc/CodeGen/TargetRegisterInfo.h192
6 files changed, 303 insertions, 11 deletions
diff --git a/backend/include/rcc/CodeGen/MachineFunctionCloner.h b/backend/include/rcc/CodeGen/MachineFunctionCloner.h
index 658614f..09877d2 100644
--- a/backend/include/rcc/CodeGen/MachineFunctionCloner.h
+++ b/backend/include/rcc/CodeGen/MachineFunctionCloner.h
@@ -15,10 +15,10 @@
namespace rcc {
-class InstructionSet;
class MachineBasicBlock;
class MachineFunction;
class MachineInstr;
+class TargetDescription;
struct MachineFunctionCloneOptions final {
MachineFunctionStableID NewStableID;
@@ -81,12 +81,12 @@ private:
const std::unordered_map<const MachineInstr *, MachineInstr *> &Instructions;
friend Expected<MachineFunctionCloneResult>
- cloneMachineFunction(const MachineFunction &Source, const InstructionSet &Instructions,
+ cloneMachineFunction(const MachineFunction &Source, const TargetDescription &Target,
MachineFunctionCloneOptions Options);
};
[[nodiscard]] Expected<MachineFunctionCloneResult>
-cloneMachineFunction(const MachineFunction &Source, const InstructionSet &Instructions,
+cloneMachineFunction(const MachineFunction &Source, const TargetDescription &Target,
MachineFunctionCloneOptions Options);
} // namespace rcc
diff --git a/backend/include/rcc/CodeGen/MachineIRBuilder.h b/backend/include/rcc/CodeGen/MachineIRBuilder.h
index 47fd63c..08ec9ba 100644
--- a/backend/include/rcc/CodeGen/MachineIRBuilder.h
+++ b/backend/include/rcc/CodeGen/MachineIRBuilder.h
@@ -3,10 +3,10 @@
#ifndef RCC_CODEGEN_MACHINEIRBUILDER_H
#define RCC_CODEGEN_MACHINEIRBUILDER_H
-#include "rcc/CodeGen/InstructionDescriptor.h"
#include "rcc/CodeGen/MachineIRTypes.h"
#include "rcc/CodeGen/MachineOperand.h"
#include "rcc/CodeGen/Register.h"
+#include "rcc/CodeGen/TargetDescription.h"
#include "rcc/Support/Error.h"
#include <cstddef>
@@ -90,7 +90,7 @@ public:
[[nodiscard]] Expected<MachineInstr *> build();
private:
- MachineInstrBuilder(MachineFunction &Function, const InstructionSet &Instructions,
+ MachineInstrBuilder(MachineFunction &Function, const TargetDescription &Target,
const InstructionDescriptor &Descriptor, MachineBasicBlock &InsertBlock,
MachineInstr *InsertBefore) noexcept;
@@ -106,7 +106,7 @@ private:
bool IsImplicit);
MachineFunction *Function;
- const InstructionSet *Instructions;
+ const TargetDescription *Target;
const InstructionDescriptor *Descriptor;
MachineBasicBlock *InsertBlock;
MachineInstr *InsertBefore;
@@ -124,8 +124,8 @@ private:
class MachineIRBuilder final {
public:
- MachineIRBuilder(MachineFunction &Function, const InstructionSet &Instructions) noexcept
- : Function(&Function), Instructions(&Instructions) {}
+ MachineIRBuilder(MachineFunction &Function, const TargetDescription &Target) noexcept
+ : Function(&Function), Target(&Target) {}
MachineIRBuilder(const MachineIRBuilder &) = delete;
MachineIRBuilder &operator=(const MachineIRBuilder &) = delete;
MachineIRBuilder(MachineIRBuilder &&) = delete;
@@ -154,7 +154,7 @@ private:
[[nodiscard]] Expected<void> validateInstruction(const MachineInstr &Instruction) const;
MachineFunction *Function;
- const InstructionSet *Instructions;
+ const TargetDescription *Target;
MachineBasicBlock *InsertBlock = nullptr;
MachineInstr *InsertBefore = nullptr;
};
diff --git a/backend/include/rcc/CodeGen/MachineIRTypes.h b/backend/include/rcc/CodeGen/MachineIRTypes.h
index 058cacb..8906bbe 100644
--- a/backend/include/rcc/CodeGen/MachineIRTypes.h
+++ b/backend/include/rcc/CodeGen/MachineIRTypes.h
@@ -44,6 +44,7 @@ struct ConstantPoolIndexTag;
struct JumpTableIndexTag;
struct TargetIndexTag;
struct SubRegIndexTag;
+struct RegisterUnitIDTag;
struct RegisterBankIDTag;
struct RegisterClassIDTag;
struct SchedulingClassIDTag;
@@ -66,6 +67,7 @@ using ConstantPoolIndex = MachineIndex<detail::ConstantPoolIndexTag>;
using JumpTableIndex = MachineIndex<detail::JumpTableIndexTag>;
using TargetIndex = MachineIndex<detail::TargetIndexTag>;
using SubRegIndex = MachineIndex<detail::SubRegIndexTag>;
+using RegisterUnitID = MachineIndex<detail::RegisterUnitIDTag>;
using RegisterBankID = MachineIndex<detail::RegisterBankIDTag>;
using RegisterClassID = MachineIndex<detail::RegisterClassIDTag>;
using SchedulingClassID = MachineIndex<detail::SchedulingClassIDTag>;
diff --git a/backend/include/rcc/CodeGen/MachineVerifier.h b/backend/include/rcc/CodeGen/MachineVerifier.h
index b1035a2..efe430e 100644
--- a/backend/include/rcc/CodeGen/MachineVerifier.h
+++ b/backend/include/rcc/CodeGen/MachineVerifier.h
@@ -3,7 +3,7 @@
#ifndef RCC_CODEGEN_MACHINEVERIFIER_H
#define RCC_CODEGEN_MACHINEVERIFIER_H
-#include "rcc/CodeGen/InstructionDescriptor.h"
+#include "rcc/CodeGen/TargetDescription.h"
#include "rcc/Support/Error.h"
#include <cstdint>
@@ -27,7 +27,7 @@ struct MachineVerifierOptions final {
class MachineVerifier final {
public:
[[nodiscard]] static Expected<void> verify(const MachineFunction &Function,
- const InstructionSet &Instructions,
+ const TargetDescription &Target,
MachineVerifierOptions Options = {});
};
diff --git a/backend/include/rcc/CodeGen/TargetDescription.h b/backend/include/rcc/CodeGen/TargetDescription.h
new file mode 100644
index 0000000..51a820a
--- /dev/null
+++ b/backend/include/rcc/CodeGen/TargetDescription.h
@@ -0,0 +1,98 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#ifndef RCC_CODEGEN_TARGETDESCRIPTION_H
+#define RCC_CODEGEN_TARGETDESCRIPTION_H
+
+#include "rcc/CodeGen/InstructionDescriptor.h"
+#include "rcc/CodeGen/TargetRegisterInfo.h"
+#include "rcc/Support/Error.h"
+
+#include <optional>
+#include <span>
+#include <utility>
+#include <vector>
+
+namespace rcc {
+
+class MachineBasicBlock;
+class MachineInstr;
+class MachineMemOperand;
+class MachineRegisterInfo;
+struct VirtualRegisterInfo;
+
+class TargetDescription final {
+public:
+ TargetDescription(const TargetDescription &) = delete;
+ TargetDescription &operator=(const TargetDescription &) = delete;
+ TargetDescription(TargetDescription &&) noexcept = default;
+ TargetDescription &operator=(TargetDescription &&) noexcept = default;
+ ~TargetDescription() = default;
+
+ [[nodiscard]] static Expected<TargetDescription> create(InstructionSet Instructions,
+ TargetRegisterInfo Registers);
+
+ [[nodiscard]] const InstructionSet &instructions() const noexcept {
+ return Instructions;
+ }
+
+ [[nodiscard]] const TargetRegisterInfo &registers() const noexcept {
+ return Registers;
+ }
+
+ [[nodiscard]] const InstructionDescriptor *
+ instructionDescriptor(Opcode InstructionOpcode) const noexcept {
+ return Instructions.descriptor(InstructionOpcode);
+ }
+
+ [[nodiscard]] Expected<void> validateExplicitOperands(Opcode InstructionOpcode,
+ std::span<const MachineOperand> Operands,
+ const MachineRegisterInfo &RegInfo) const;
+ [[nodiscard]] Expected<void> validateOperandTies(Opcode InstructionOpcode,
+ std::span<const MachineOperand> ExplicitOperands,
+ std::span<const MachineOperandTie> Ties,
+ const MachineRegisterInfo &RegInfo) const;
+ [[nodiscard]] Expected<void>
+ validateImplicitOperands(Opcode InstructionOpcode,
+ std::span<const MachineOperand *const> ImplicitOperands,
+ const MachineRegisterInfo &RegInfo) const;
+ [[nodiscard]] Expected<void>
+ validateEarlyClobber(std::span<const MachineOperand> ExplicitOperands,
+ std::span<const MachineOperand *const> ImplicitOperands,
+ std::span<const MachineOperandTie> Ties) const;
+ [[nodiscard]] Expected<void>
+ validateMemOperands(Opcode InstructionOpcode,
+ std::span<const MachineMemOperand *const> MemOperands) const {
+ return Instructions.validateMemOperands(InstructionOpcode, MemOperands);
+ }
+ [[nodiscard]] Expected<void> validateInstruction(const MachineInstr &Instruction,
+ const MachineRegisterInfo &RegInfo) const;
+ [[nodiscard]] Expected<void> validateRegisterInfo(const MachineRegisterInfo &RegInfo) const;
+ [[nodiscard]] Expected<void> validateBlockLiveIns(const MachineBasicBlock &Block) const;
+
+ [[nodiscard]] Expected<std::vector<MachineOperand>>
+ createDefaultImplicitOperands(const InstructionDescriptor &Descriptor) const {
+ return Instructions.createDefaultImplicitOperands(Descriptor);
+ }
+
+private:
+ TargetDescription(InstructionSet Instructions, TargetRegisterInfo Registers)
+ : Instructions(std::move(Instructions)), Registers(std::move(Registers)) {}
+
+ [[nodiscard]] Expected<void> validateTargetOperand(const OperandDescriptor *Descriptor,
+ const MachineOperand &Operand,
+ const MachineRegisterInfo &RegInfo) const;
+ [[nodiscard]] Expected<void> validateVirtualRegister(Register Reg,
+ const VirtualRegisterInfo &Info) const;
+ [[nodiscard]] std::optional<RegisterClassID>
+ effectiveRegisterClass(const MachineOperand &Operand, const MachineRegisterInfo &RegInfo) const;
+ [[nodiscard]] Expected<void> validateTieCompatibility(const MachineOperand &Def,
+ const MachineOperand &Use,
+ const MachineRegisterInfo &RegInfo) const;
+
+ InstructionSet Instructions;
+ TargetRegisterInfo Registers;
+};
+
+} // namespace rcc
+
+#endif // RCC_CODEGEN_TARGETDESCRIPTION_H
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