// SPDX-License-Identifier: GPL-3.0-or-later #include "rcc/Target/RISCV/RISCVTarget.h" #include "rcc/CodeGen/GenericOpcodes.h" #include "rcc/Target/RISCV/RISCVFunctionInfo.h" #include #include #include #include #include #include #include #include #include namespace rcc::riscv { namespace { [[nodiscard]] PhysicalRegister physical(PhysicalRegisterID ID) { const auto Register = physicalRegister(ID); assert(Register.has_value()); return *Register; } [[nodiscard]] RegisterUnitLane unitLane(RegisterUnit Unit, std::uint64_t Lanes) { return { .Unit = RegisterUnitID::fromValue(static_cast(Unit)), .Lanes = LaneMask::fromRaw(Lanes), }; } [[nodiscard]] std::vector physicalRegisters(std::initializer_list IDs) { std::vector Result; Result.reserve(IDs.size()); for (const PhysicalRegisterID ID : IDs) Result.push_back(physical(ID)); return Result; } [[nodiscard]] RegisterClassDesc registerClass( RegisterClass ID, const char *Name, std::initializer_list Registers, std::initializer_list AllocationOrder, RegisterBank Bank, std::uint32_t SizeInBits, std::uint32_t SpillSizeInBits, std::uint32_t SpillAlignmentInBits, std::uint64_t Lanes, bool Allocatable, std::uint32_t CopyCost) { return { .ID = RegisterClassID::fromValue(static_cast(ID)), .Name = Name, .Registers = physicalRegisters(Registers), .AllocationOrder = physicalRegisters(AllocationOrder), .SizeInBits = SizeInBits, .SpillSizeInBits = SpillSizeInBits, .SpillAlignmentInBits = SpillAlignmentInBits, .Lanes = LaneMask::fromRaw(Lanes), .SupportedSubRegs = {}, .SuperClasses = {}, .DefaultBank = RegisterBankID::fromValue(static_cast(Bank)), .Allocatable = Allocatable, .CopyCost = CopyCost, }; } [[nodiscard]] std::shared_ptr makePreservedMask(std::initializer_list Preserved) { std::vector Words; for (const PhysicalRegisterID ID : Preserved) { const std::uint32_t Number = static_cast(ID); const std::size_t Word = Number / 64U; if (Words.size() <= Word) Words.resize(Word + 1U); Words[Word] |= std::uint64_t{1} << (Number % 64U); } return std::make_shared(std::move(Words)); } #include "RISCVGenTargetDescription.inc" } // namespace Expected physicalRegister(PhysicalRegisterID ID) { return PhysicalRegister::create(static_cast(ID)); } Expected createRegisterInfo() { TargetRegisterInfoDesc Description; appendGeneratedRegisterInfo(Description); return TargetRegisterInfo::create(std::move(Description)); } Expected createMIRTextInfo() { auto Registers = createRegisterInfo(); if (!Registers) return std::unexpected(Registers.error()); TargetMIRTextInfoDesc Description; appendGeneratedMIRTextInfo(Description); configureFunctionInfoMIRSchema(Description); return TargetMIRTextInfo::create(std::move(Description), *Registers); } Expected createTargetDescription() { auto Registers = createRegisterInfo(); if (!Registers) return std::unexpected(Registers.error()); std::vector Descriptors; std::vector Predicates; appendGeneratedInstructionInfo(Descriptors, Predicates); auto GenericInfo = appendGenericInstructionInfo(Descriptors, Predicates); if (!GenericInfo) return std::unexpected(GenericInfo.error()); auto Instructions = InstructionSet::create(std::move(Descriptors), std::move(Predicates)); if (!Instructions) return std::unexpected(Instructions.error()); TargetMIRTextInfoDesc MIRText; appendGeneratedMIRTextInfo(MIRText); configureFunctionInfoMIRSchema(MIRText); return TargetDescription::create(std::move(*Instructions), std::move(*Registers), std::move(MIRText)); } std::shared_ptr createCallPreservedMask() { TargetMIRTextInfoDesc Description; appendGeneratedMIRTextInfo(Description); configureFunctionInfoMIRSchema(Description); assert(!Description.RegisterMasks.empty()); return Description.RegisterMasks.front().Mask; } std::span schedulingClasses() noexcept { return GeneratedSchedulingClasses; } std::span encodingCategories() noexcept { return GeneratedEncodingCategories; } std::span assemblyFormats() noexcept { return GeneratedAssemblyFormats; } std::span assemblyInstructions() noexcept { return GeneratedAssemblyInstructions; } const AssemblyInstructionInfo *assemblyInstruction(Opcode InstructionOpcode) noexcept { for (const AssemblyInstructionInfo &Info : GeneratedAssemblyInstructions) { if (Info.InstructionOpcode == InstructionOpcode) return &Info; } return nullptr; } std::span callingConventions() noexcept { return GeneratedCallingConventions; } const CallingConventionInfo *callingConvention(CallingConvention ID) noexcept { for (const CallingConventionInfo &Info : GeneratedCallingConventions) { if (Info.ID == ID) return &Info; } return nullptr; } } // namespace rcc::riscv