// SPDX-License-Identifier: GPL-3.0-or-later #include "TableGenBackends.h" #include #include #include #include #include #include #include #include namespace rcc::targetgen { namespace { void emitRegisterIDList(std::ostream &Output, const NormalizedTargetModel &Model, std::span IDs) { for (const std::uint32_t ID : IDs) Output << "PhysicalRegisterID::" << findRegister(Model, ID).Symbol << ", "; } } // namespace [[nodiscard]] std::string emitRegisterHeader(const NormalizedTargetModel &Model, std::string_view SourceName) { const std::string Guard = "RCC_TARGET_" + upperIdentifier(Model.Target.Namespace) + "_" + upperIdentifier(Model.Target.Name) + "REGISTERS_H"; std::ostringstream Output; Output << "// SPDX-License-Identifier: GPL-3.0-or-later\n\n"; Output << "// This file is generated by rcc-tblgen from "; appendQuoted(Output, SourceName); Output << ". Do not edit it manually.\n\n"; Output << "#ifndef " << Guard << "\n#define " << Guard << "\n\n"; Output << "#include \n#include \n\n"; Output << "namespace rcc::" << Model.Target.Namespace << " {\n\n"; Output << "inline constexpr std::string_view TargetName = "; appendQuoted(Output, Model.Target.Name); Output << ";\ninline constexpr std::string_view TargetTriple = "; appendQuoted(Output, Model.Target.Triple); Output << ";\ninline constexpr std::string_view TargetCPU = "; appendQuoted(Output, Model.Target.CPU); Output << ";\ninline constexpr std::string_view TargetABI = "; appendQuoted(Output, Model.Target.ABI); Output << ";\ninline constexpr std::string_view TargetDataLayout = "; appendQuoted(Output, Model.Target.DataLayout); Output << ";\n\ninline constexpr std::string_view TargetFeatures[] = {\n"; for (const std::string &Feature : Model.Target.Features) { Output << " "; appendQuoted(Output, Feature); Output << ",\n"; } Output << "};\n\n"; Output << "enum class PhysicalRegisterID : std::uint32_t {\n NoRegister = 0,\n"; for (const NormalizedRegister &Register : Model.Registers) Output << " " << Register.Symbol << " = " << Register.ID << ",\n"; Output << "};\n\n"; Output << "enum class RegisterUnit : std::uint32_t {\n"; for (const SourceRegisterUnit &Unit : Model.RegisterUnits) Output << " " << Unit.Symbol << " = " << Unit.ID << ",\n"; Output << "};\n\n"; Output << "enum class RegisterBank : std::uint32_t {\n"; for (const NormalizedRegisterBank &Bank : Model.RegisterBanks) Output << " " << Bank.Symbol << " = " << Bank.ID << ",\n"; Output << "};\n\n"; Output << "enum class RegisterClass : std::uint32_t {\n"; for (const NormalizedRegisterClass &Class : Model.RegisterClasses) Output << " " << Class.Symbol << " = " << Class.ID << ",\n"; Output << "};\n\n"; Output << "} // namespace rcc::" << Model.Target.Namespace << "\n\n"; Output << "#endif // " << Guard << "\n"; return Output.str(); } std::string emitRegisterInfo(const NormalizedTargetModel &Model, std::string_view SourceName) { std::ostringstream Output; Output << "// SPDX-License-Identifier: GPL-3.0-or-later\n\n"; Output << "// This file is generated by rcc-tblgen from "; appendQuoted(Output, SourceName); Output << ". Do not edit it manually.\n\n"; Output << "void appendGeneratedRegisterInfo(TargetRegisterInfoDesc &Description) {\n"; Output << " Description.RegisterUnits = {\n"; for (const SourceRegisterUnit &Unit : Model.RegisterUnits) { Output << " {RegisterUnitID::fromValue(" << Unit.ID << "), "; appendQuoted(Output, Unit.Name); Output << "},\n"; } Output << " };\n\n Description.PhysicalRegisters = {\n"; for (const NormalizedRegister &Register : Model.Registers) { Output << " {physical(PhysicalRegisterID::" << Register.Symbol << "), "; appendQuoted(Output, Register.Name); Output << ", " << Register.Encoding << ", {"; for (const NormalizedRegisterUnitLane &Unit : Register.Units) { Output << "unitLane(RegisterUnit::" << findRegisterUnit(Model, Unit.UnitID).Symbol << ", " << Unit.Lanes << "), "; } Output << "}, " << (Register.IsConstant ? "true" : "false") << ", " << (Register.IsArtificial ? "true" : "false") << ", " << (Register.IsReserved ? "true" : "false") << ", {"; for (const std::string &Alias : Register.AlternativeNames) { appendQuoted(Output, Alias); Output << ", "; } Output << "}},\n"; } Output << " };\n\n Description.RegisterBanks = {\n"; Output << emitRegisterBanks(Model); Output << " };\n\n Description.RegisterClasses = {\n"; for (const NormalizedRegisterClass &Class : Model.RegisterClasses) { Output << " registerClass(RegisterClass::" << Class.Symbol << ", "; appendQuoted(Output, Class.Name); Output << ", {"; emitRegisterIDList(Output, Model, Class.Registers); Output << "}, {"; emitRegisterIDList(Output, Model, Class.AllocationOrder); Output << "}, RegisterBank::" << findRegisterBank(Model, Class.BankID).Symbol << ", " << Class.SizeInBits << ", " << Class.SpillSizeInBits << ", " << Class.SpillAlignmentInBits << ", " << Class.Lanes << ", " << (Class.Allocatable ? "true" : "false") << ", " << Class.CopyCost << "),\n"; } Output << " };\n}\n\n"; Output << "void appendGeneratedMIRTextInfo(TargetMIRTextInfoDesc &Description) {\n"; Output << " Description.DirectOperandFlagMask = " << Model.MIROperandFlags.DirectMask << ";\n Description.DirectOperandFlags = {\n"; for (const SourceMIROperandFlag &Flag : Model.MIROperandFlags.Direct) { Output << " {"; appendQuoted(Output, Flag.Name); Output << ", " << Flag.Value << "},\n"; } Output << " };\n Description.BitmaskOperandFlags = {\n"; for (const SourceMIROperandFlag &Flag : Model.MIROperandFlags.Bitmask) { Output << " {"; appendQuoted(Output, Flag.Name); Output << ", " << Flag.Value << "},\n"; } Output << " };\n"; Output << " Description.RegisterMasks = {\n"; for (const NormalizedRegisterMask &Mask : Model.RegisterMasks) { Output << " {"; appendQuoted(Output, Mask.Name); Output << ", makePreservedMask({"; emitRegisterIDList(Output, Model, Mask.PreservedRegisters); Output << "})},\n"; } Output << " };\n Description.CFIRegisters = {\n"; std::unordered_set CanonicalDwarfRegisters; for (const NormalizedRegister &Register : Model.Registers) { const bool IsCanonical = CanonicalDwarfRegisters.insert(Register.DwarfRegister).second; Output << " {physical(PhysicalRegisterID::" << Register.Symbol << "), " << Register.DwarfRegister << ", " << (IsCanonical ? "true" : "false") << "},\n"; } Output << " };\n}\n\n"; return Output.str(); } } // namespace rcc::targetgen