// 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/TargetMIRTextInfo.h" #include "rcc/CodeGen/TargetRegisterInfo.h" #include "rcc/Support/Error.h" #include #include #include #include #include namespace rcc { class MachineBasicBlock; class MachineCFIInfo; class MachineFrameInfo; class MachineInstr; class MachineMemOperand; class MachineRegisterInfo; struct VirtualRegisterInfo; enum class BooleanContent : std::uint8_t { Undefined, ZeroOrOne, ZeroOrNegativeOne, }; struct TargetBooleanContentInfo final { BooleanContent ScalarInteger = BooleanContent::Undefined; BooleanContent ScalarFloatingPoint = BooleanContent::Undefined; BooleanContent Vector = BooleanContent::Undefined; }; enum class StackGrowthDirection : std::uint8_t { Down, Up, }; struct TargetStackInfo final { PhysicalRegister StackPointerRegisterToSaveRestore; StackGrowthDirection GrowthDirection = StackGrowthDirection::Down; }; 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 create(InstructionSet Instructions, TargetRegisterInfo Registers, TargetMIRTextInfoDesc MIRText = {}, TargetBooleanContentInfo BooleanInfo = {}, TargetStackInfo StackInfo = {}); [[nodiscard]] const InstructionSet &instructions() const noexcept { return Instructions; } [[nodiscard]] const TargetRegisterInfo ®isters() const noexcept { return Registers; } [[nodiscard]] const TargetMIRTextInfo &mirText() const noexcept { return MIRText; } [[nodiscard]] BooleanContent getBooleanContents(bool IsVector, bool IsFloatingPoint) const noexcept { if (IsVector) return BooleanInfo.Vector; return IsFloatingPoint ? BooleanInfo.ScalarFloatingPoint : BooleanInfo.ScalarInteger; } [[nodiscard]] PhysicalRegister stackPointerRegisterToSaveRestore() const noexcept { return StackInfo.StackPointerRegisterToSaveRestore; } [[nodiscard]] StackGrowthDirection stackGrowthDirection() const noexcept { return StackInfo.GrowthDirection; } [[nodiscard]] const InstructionDescriptor * instructionDescriptor(Opcode InstructionOpcode) const noexcept { return Instructions.descriptor(InstructionOpcode); } [[nodiscard]] Expected validateExplicitOperands(Opcode InstructionOpcode, std::span Operands, const MachineRegisterInfo &RegInfo) const; [[nodiscard]] Expected validateOperandTies(Opcode InstructionOpcode, std::span ExplicitOperands, std::span Ties, const MachineRegisterInfo &RegInfo) const; [[nodiscard]] Expected validateImplicitOperands(Opcode InstructionOpcode, std::span ImplicitOperands, const MachineRegisterInfo &RegInfo) const; [[nodiscard]] Expected validateEarlyClobber(std::span ExplicitOperands, std::span ImplicitOperands, std::span Ties) const; [[nodiscard]] Expected validateMemOperands(Opcode InstructionOpcode, std::span MemOperands) const; [[nodiscard]] Expected validateInstruction(const MachineInstr &Instruction, const MachineRegisterInfo &RegInfo) const; [[nodiscard]] Expected validateTieCompatibility(const MachineOperand &Def, const MachineOperand &Use, const MachineRegisterInfo &RegInfo) const; [[nodiscard]] Expected validateCFIInfo(const MachineCFIInfo &Info) const; [[nodiscard]] Expected validateFrameInfo(const MachineFrameInfo &Info) const; [[nodiscard]] Expected validateRegisterInfo(const MachineRegisterInfo &RegInfo) const; [[nodiscard]] Expected validateBlockLiveIns(const MachineBasicBlock &Block) const; [[nodiscard]] Expected> createDefaultImplicitOperands(const InstructionDescriptor &Descriptor) const { return Instructions.createDefaultImplicitOperands(Descriptor); } private: TargetDescription(InstructionSet Instructions, TargetRegisterInfo Registers, TargetMIRTextInfo MIRText, TargetBooleanContentInfo BooleanInfo, TargetStackInfo StackInfo) : Instructions(std::move(Instructions)), Registers(std::move(Registers)), MIRText(std::move(MIRText)), BooleanInfo(BooleanInfo), StackInfo(StackInfo) {} [[nodiscard]] Expected validateTargetOperand(const OperandDescriptor *Descriptor, const MachineOperand &Operand, const MachineRegisterInfo &RegInfo) const; [[nodiscard]] Expected validateVirtualRegister(Register Reg, const VirtualRegisterInfo &Info) const; [[nodiscard]] std::optional effectiveRegisterClass(const MachineOperand &Operand, const MachineRegisterInfo &RegInfo) const; InstructionSet Instructions; TargetRegisterInfo Registers; TargetMIRTextInfo MIRText; TargetBooleanContentInfo BooleanInfo; TargetStackInfo StackInfo; }; } // namespace rcc #endif // RCC_CODEGEN_TARGETDESCRIPTION_H