// SPDX-License-Identifier: GPL-3.0-or-later // The private header follows the source-tree ownership of LLVM TableGen Common. // NOLINTNEXTLINE(llvm-header-guard) #ifndef RCC_UTILS_TABLEGEN_COMMON_CODEGENTARGET_H #define RCC_UTILS_TABLEGEN_COMMON_CODEGENTARGET_H #include "rcc/TableGen/Record.h" #include #include #include #include #include #include namespace rcc::targetgen { struct NormalizedRegisterUnitLane final { std::uint32_t UnitID = 0; std::uint64_t Lanes = 0; }; struct NormalizedRegister final { std::uint32_t ID = 0; std::string Symbol; std::string Name; std::uint32_t Encoding = 0; std::uint32_t DwarfRegister = 0; std::vector Units; bool IsConstant = false; bool IsArtificial = false; bool IsReserved = false; std::vector AlternativeNames; }; struct NormalizedRegisterBank final { std::uint32_t ID = 0; std::string Symbol; std::string Name; std::uint32_t MaximumSizeInBits = 0; std::vector RegisterClasses; }; struct NormalizedRegisterClass final { std::uint32_t ID = 0; std::string Symbol; std::string Name; std::uint32_t BankID = 0; std::uint32_t SizeInBits = 0; std::uint32_t SpillSizeInBits = 0; std::uint32_t SpillAlignmentInBits = 0; std::uint64_t Lanes = 0; std::vector Registers; std::vector AllocationOrder; std::vector SuperClasses; bool Allocatable = true; std::uint32_t CopyCost = 1; }; struct NormalizedRegisterMask final { std::string Name; std::vector PreservedRegisters; }; struct NormalizedCallingConvention final { std::uint32_t ID = 0; std::string Symbol; std::string Name; std::uint32_t IntegerRegisterClass = 0; std::uint32_t FloatingRegisterClass = 0; std::vector IntegerArgumentRegisters; std::vector FloatingArgumentRegisters; std::vector IntegerReturnRegisters; std::vector FloatingReturnRegisters; std::string PreservedMaskName; std::uint32_t StackAlignmentBytes = 0; std::uint32_t StackArgumentAlignmentBytes = 0; std::uint32_t ShadowSpaceBytes = 0; bool SupportsVarArgs = false; bool SupportsTailCalls = false; }; struct NormalizedNamedOperand final { std::uint32_t ID = 0; std::string Symbol; std::string Name; }; struct NormalizedImmediatePredicate final { std::uint32_t ID = 0; std::string Symbol; std::string Name; bool IsSigned = false; std::uint32_t Bits = 0; std::uint64_t Alignment = 1; bool NonZero = false; std::vector AllowedValues; }; struct NormalizedSchedulingClass final { std::uint32_t ID = 0; std::string Symbol; std::string Name; std::uint32_t MicroOps = 0; std::uint32_t Latency = 0; }; struct NormalizedEncodingCategory final { std::uint32_t ID = 0; std::string Symbol; std::string Name; std::uint32_t SizeInBytes = 0; }; struct NormalizedAssemblyFormat final { std::uint32_t ID = 0; std::string Symbol; std::string Name; }; struct NormalizedOperand final { std::vector Kinds; std::string RegisterRole; std::optional RegisterClass; std::optional RegisterBank; std::optional ImmediatePredicate; std::string MemoryRole; std::optional DefaultTiedOperand; bool EarlyClobber = false; bool Optional = false; bool VariadicGroup = false; bool AllowSubReg = false; std::optional Name; std::optional TypeIndex; std::uint32_t AllowedTargetFlags = 0; }; struct NormalizedImplicitRegister final { std::uint32_t Register = 0; bool EarlyClobber = false; bool Renamable = false; }; struct NormalizedInstruction final { std::uint32_t ID = 0; std::string Symbol; std::string Name; std::string AssemblyMnemonic; std::uint32_t BinaryEncoding = 0; std::vector Operands; std::uint32_t NumExplicitDefs = 0; bool Variadic = false; std::vector ImplicitDefs; std::vector ImplicitUses; bool AllowExtraImplicitOperands = false; std::vector Flags; std::uint32_t SchedulingClass = 0; std::uint32_t EncodingCategory = 0; std::uint32_t SizeInBytes = 0; std::uint32_t AssemblyFormat = 0; bool RequiresMemoryOperands = false; std::string Owner; std::string Deadline; }; enum class NormalizedSelectionTypeKind : std::uint8_t { Any, Scalar, Pointer, }; struct NormalizedSelectionTypePredicate final { NormalizedSelectionTypeKind Kind = NormalizedSelectionTypeKind::Any; std::uint32_t Bits = 0; }; struct NormalizedSelectionOperandTypePredicate final { std::uint32_t OperandIndex = 0; NormalizedSelectionTypePredicate Type; }; struct NormalizedSelectionOperandBankPredicate final { std::uint32_t OperandIndex = 0; std::uint32_t Bank = 0; }; struct NormalizedSelectionOperandClassPredicate final { std::uint32_t OperandIndex = 0; std::uint32_t RegClass = 0; }; struct NormalizedSelectionIntegerPredicate final { std::uint32_t OperandIndex = 0; std::uint32_t Predicate = 0; }; struct NormalizedSelectionFloatingPredicate final { std::uint32_t OperandIndex = 0; std::uint32_t Predicate = 0; }; struct NormalizedSelectionConstantRange final { std::int64_t Minimum = 0; std::int64_t Maximum = 0; }; struct NormalizedSelectionOperandImmediatePredicate final { std::uint32_t OperandIndex = 0; std::vector Ranges; }; struct NormalizedSelectionOperandDefConstantPredicate final { std::uint32_t OperandIndex = 0; std::vector Ranges; }; struct NormalizedSelectionDefUseCapture final { std::uint32_t ID = 0; std::uint32_t OperandIndex = 0; }; struct NormalizedSelectionDefUsePredicate final { std::uint32_t RootOperandIndex = 0; std::uint32_t Opcode = 0; std::optional IntegerPredicate; std::vector Captures; std::vector OperandDefConstants; }; struct NormalizedSelectionTemporary final { std::uint32_t ID = 0; std::uint32_t TypeFromOperand = 0; }; enum class NormalizedSelectionImmediateTransform : std::uint8_t { Identity, Negate, PlusOne, }; struct NormalizedSelectionOperandRenderer final { enum class Kind : std::uint8_t { Operand, ComplexOperand, PhysicalRegister, Temporary, CapturedOperand, CapturedImmediate, Immediate, }; Kind SourceKind = Kind::Operand; std::uint32_t Value = 0; std::string ComplexRenderer; std::uint16_t Flags = 0; NormalizedSelectionImmediateTransform Transform = NormalizedSelectionImmediateTransform::Identity; std::int64_t Immediate = 0; }; struct NormalizedSelectionAction final { std::uint32_t ResultOpcode = 0; bool ReplacesRoot = false; std::vector OperandRenderers; }; struct NormalizedSelectionRule final { std::string Symbol; std::uint32_t Priority = 0; std::uint32_t Specificity = 0; std::uint32_t MatchOpcode = 0; std::optional ResultType; std::optional IntegerPredicate; std::optional FloatingPredicate; std::vector TargetPredicates; std::vector OperandTypes; std::vector OperandBanks; std::vector OperandClasses; std::vector OperandImmediates; std::vector OperandDefConstants; std::vector DefUsePredicates; std::vector Temporaries; std::vector Actions; std::vector EraseOperandDefinitions; }; struct NormalizedTargetModel final { SourceTarget Target; std::vector RegisterUnits; std::vector Registers; std::vector RegisterBanks; std::vector RegisterClasses; std::vector RegisterMasks; SourceMIROperandFlags MIROperandFlags; std::vector CallingConventions; std::vector NamedOperands; std::vector ImmediatePredicates; std::vector SchedulingClasses; std::vector EncodingCategories; std::vector AssemblyFormats; std::vector Instructions; std::vector SelectionRules; }; [[nodiscard]] std::optional operandKindEnumerator(std::string_view Value) noexcept; [[nodiscard]] std::optional registerRoleEnumerator(std::string_view Value) noexcept; [[nodiscard]] std::optional memoryRoleEnumerator(std::string_view Value) noexcept; [[nodiscard]] std::optional instructionFlagEnumerator(std::string_view Value) noexcept; [[nodiscard]] std::optional pseudoOwnerEnumerator(std::string_view Value) noexcept; [[nodiscard]] std::optional pipelineStageEnumerator(std::string_view Value) noexcept; [[nodiscard]] bool isPowerOfTwo(std::uint64_t Value) noexcept; class CodeGenTarget final { public: CodeGenTarget(const DescriptionAST &Input, std::string SourceName); [[nodiscard]] std::optional normalize(); [[nodiscard]] std::vector takeDiagnostics(); private: void fail(TextRange Range, std::string Message); [[nodiscard]] bool validateTarget(); [[nodiscard]] bool normalizeRegisterUnits(); [[nodiscard]] bool normalizeRegisters(NormalizedTargetModel &Result); [[nodiscard]] bool normalizeRegisterBanks(NormalizedTargetModel &Result); [[nodiscard]] bool normalizeRegisterClasses(NormalizedTargetModel &Result); [[nodiscard]] bool normalizeRegisterMasks(NormalizedTargetModel &Result); [[nodiscard]] bool normalizeMIROperandFlags(NormalizedTargetModel &Result); [[nodiscard]] bool normalizeCallingConventions(NormalizedTargetModel &Result); [[nodiscard]] bool normalizeNamedOperands(NormalizedTargetModel &Result); [[nodiscard]] bool normalizeImmediatePredicates(NormalizedTargetModel &Result); [[nodiscard]] bool normalizeSchedulingClasses(NormalizedTargetModel &Result); [[nodiscard]] bool normalizeEncodingCategories(NormalizedTargetModel &Result); [[nodiscard]] bool normalizeAssemblyFormats(NormalizedTargetModel &Result); [[nodiscard]] bool normalizeOperand(const SourceOperand &InputOperand, NormalizedOperand &Result); [[nodiscard]] bool normalizeImplicitRegisters(const std::vector &InputRegisters, bool IsDef, std::vector &Result); [[nodiscard]] bool normalizeInstructions(NormalizedTargetModel &Result); [[nodiscard]] bool normalizeSelectionRules(NormalizedTargetModel &Result); const DescriptionAST &Input; std::string SourceName; std::unordered_map UnitBySymbol; std::unordered_map RegisterBySymbol; std::unordered_map BankBySymbol; std::unordered_map ClassBySymbol; std::unordered_map NamedOperandBySymbol; std::unordered_map ImmediatePredicateBySymbol; std::unordered_map SchedulingClassBySymbol; std::unordered_map EncodingCategoryBySymbol; std::unordered_map AssemblyFormatBySymbol; std::unordered_map CallingConventionBySymbol; std::vector Diagnostics; }; [[nodiscard]] const NormalizedRegister &findRegister(const NormalizedTargetModel &Model, std::uint32_t ID); [[nodiscard]] const SourceRegisterUnit &findRegisterUnit(const NormalizedTargetModel &Model, std::uint32_t ID); [[nodiscard]] const NormalizedRegisterBank &findRegisterBank(const NormalizedTargetModel &Model, std::uint32_t ID); } // namespace rcc::targetgen #endif // RCC_UTILS_TABLEGEN_COMMON_CODEGENTARGET_H