Index: llvm/utils/TableGen/CMakeLists.txt =================================================================== --- llvm/utils/TableGen/CMakeLists.txt +++ llvm/utils/TableGen/CMakeLists.txt @@ -41,6 +41,7 @@ OptParserEmitter.cpp OptRSTEmitter.cpp PredicateExpander.cpp + PrinterLLVM.cpp PseudoLoweringEmitter.cpp CompressInstEmitter.cpp RegisterBankEmitter.cpp Index: llvm/utils/TableGen/Printer.h =================================================================== --- /dev/null +++ llvm/utils/TableGen/Printer.h @@ -0,0 +1,273 @@ +//===--------------- Printer.h - Printer Interface --------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_UTILS_TABLEGEN_PRINTER_H +#define LLVM_UTILS_TABLEGEN_PRINTER_H + +#include "CodeGenRegisters.h" +#include "CodeGenTarget.h" +#include "PrinterTypes.h" +#include "RegisterInfoEmitterTypes.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/FormattedStream.h" +#include "llvm/Support/raw_ostream.h" + +namespace llvm { + +class PrinterBitVectorEmitter { + BitVector Values; + +public: + virtual void add(unsigned V); + virtual void print(raw_ostream &OS); +}; + +void printBitVectorAsHex(raw_ostream &OS, const BitVector &Bits, + unsigned Width); + +//============================== +// +// Implementation: LLVM +// +//============================== + +/// Interface for printing the generated code. +/// Every string which will be in the generated code of a backend originates +/// from here. +/// +/// It also is the only class which writes directly into the output stream for +/// the backend. +/// +/// This class has methods for all classes of backends which emit generated +/// code. If a backend currently does not emit the code in a language you need +/// you simply inherit this class and implement the relevant methods. +/// +/// Printer implementation of LLVM. +/// This is the default printer for all backends. +/// +/// Output language: C++ +class PrinterLLVM { + +private: + formatted_raw_ostream &OS; + +public: + PrinterLLVM(formatted_raw_ostream &OS); + + virtual ~PrinterLLVM(); + + static PrinterLanguage getLanguage(); + + virtual void flushOS() const { OS.flush(); } + + //-------------------------- + // General printing methods + //-------------------------- + + virtual void emitNewline(unsigned Count) const { + for (unsigned I = Count; I > 0; --I) + OS << "\n"; + } + virtual void emitString(std::string const &Str) const { OS << Str; } + + //-------------------------- + // General printing methods + //-------------------------- + + virtual void emitNamespace(std::string const &Name, bool Begin, + std::string const &Comment = "") const; + virtual void emitIncludeToggle(std::string const &Name, bool Begin) const; + + //------------------------ + // Backend: RegisterInfo + //------------------------ + + virtual void regInfoEmitSourceFileHeader(std::string const &Desc) const; + virtual void regInfoEmitEnums(CodeGenTarget const &Target, + CodeGenRegBank const &Bank) const; + virtual void + regInfoEmitRegDiffLists(std::string const TargetName, + SequenceToOffsetTable const &DiffSeqs) const; + virtual void regInfoEmitLaneMaskLists( + std::string const TargetName, + SequenceToOffsetTable const &DiffSeqs) const; + virtual void regInfoEmitSubRegIdxLists( + std::string const TargetName, + SequenceToOffsetTable>> const + &SubRegIdxSeqs) const; + virtual void regInfoEmitSubRegIdxSizes( + std::string const TargetName, + std::deque const &SubRegIndices) const; + virtual void regInfoEmitSubRegStrTable( + std::string const TargetName, + SequenceToOffsetTable const &RegStrings) const; + virtual void regInfoEmitRegDesc( + SequenceToOffsetTable const &LaneMaskSeqs, + std::deque const &Regs, + SequenceToOffsetTable>> const + &SubRegIdxSeqs, + SequenceToOffsetTable const &DiffSeqs, + SmallVector const &SubRegIdxLists, + SmallVector const &SubRegLists, + SmallVector const &SuperRegLists, + SmallVector const &RegUnitLists, + SmallVector const &RegUnitInitScale, + SmallVector const &RegUnitLaneMasks, + SequenceToOffsetTable const &RegStrings) const; + virtual void regInfoEmitRegUnitRoots(std::string const TargetName, + CodeGenRegBank const &RegBank) const; + virtual void + regInfoEmitRegClasses(std::list const &RegClasses, + SequenceToOffsetTable &RegClassStrings, + CodeGenTarget const &Target) const; + virtual void regInfoEmitStrLiteralRegClasses( + std::string const TargetName, + SequenceToOffsetTable const &RegClassStrings) const; + virtual void regInfoEmitMCRegClassesTable( + std::string const TargetName, + std::list const &RegClasses, + SequenceToOffsetTable &RegClassStrings) const; + virtual void + regInfoEmitRegEncodingTable(std::string const TargetName, + std::deque const &Regs) const; + virtual void regInfoEmitMCRegInfoInit( + std::string const TargetName, CodeGenRegBank const &RegBank, + std::deque const &Regs, + std::list const &RegClasses, + std::deque const &SubRegIndices) const; + virtual void regInfoEmitInfoDwarfRegs(StringRef const &Namespace, + DwarfRegNumsVecTy &DwarfRegNums, + unsigned MaxLength, bool IsCtor) const; + virtual void regInfoEmitInfoDwarfRegsRev(StringRef const &Namespace, + DwarfRegNumsVecTy &DwarfRegNums, + unsigned MaxLength, + bool IsCtor) const; + virtual void regInfoEmitInfoRegMapping(StringRef const &Namespace, + unsigned MaxLength, bool IsCtor) const; + virtual void regInfoEmitHeaderIncludes() const; + virtual void regInfoEmitHeaderExternRegClasses( + std::list const &RegClasses) const; + virtual void regInfoEmitHeaderDecl(std::string const &TargetName, + std::string const &ClassName, + bool SubRegsPresent, + bool DeclareGetPhysRegBaseClass) const; + virtual void + regInfoEmitExternRegClassesArr(std::string const &TargetName) const; + virtual void regInfoEmitVTSeqs( + SequenceToOffsetTable> const &VTSeqs) + const; + virtual void regInfoEmitSubRegIdxTable( + std::deque const &SubRegIndices) const; + virtual void regInfoEmitRegClassInfoTable( + std::list const &RegClasses, + SequenceToOffsetTable> const &VTSeqs, + CodeGenHwModes const &CGH, unsigned NumModes) const; + virtual void regInfoEmitSubClassMaskTable( + std::list const &RegClasses, + SmallVector &SuperRegIdxLists, + SequenceToOffsetTable>> &SuperRegIdxSeqs, + std::deque const &SubRegIndices, + BitVector &MaskBV) const; + virtual void regInfoEmitSuperRegIdxSeqsTable( + SequenceToOffsetTable>> const &SuperRegIdxSeqs) + const; + virtual void regInfoEmitSuperClassesTable( + std::list const &RegClasses) const; + virtual void + regInfoEmitRegClassMethods(std::list const &RegClasses, + std::string const &TargetName) const; + virtual void regInfomitRegClassInstances( + std::list const &RegClasses, + SequenceToOffsetTable>> const &SuperRegIdxSeqs, + SmallVector const &SuperRegIdxLists, + std::string const &TargetName) const; + virtual void regInfoEmitRegClassTable( + std::list const &RegClasses) const; + virtual void + regInfoEmitCostPerUseTable(std::vector const &AllRegCostPerUse, + unsigned NumRegCosts) const; + virtual void + regInfoEmitInAllocatableClassTable(llvm::BitVector const &InAllocClass) const; + virtual void regInfoEmitRegExtraDesc(std::string const &TargetName, + unsigned NumRegCosts) const; + virtual void regInfoEmitSubClassSubRegGetter( + std::string const &ClassName, unsigned SubRegIndicesSize, + std::deque const &SubRegIndices, + std::list const &RegClasses, + CodeGenRegBank &RegBank) const; + virtual void regInfoEmitRegClassWeight(CodeGenRegBank const &RegBank, + std::string const &ClassName) const; + virtual void regInfoEmitRegUnitWeight(CodeGenRegBank const &RegBank, + std::string const &ClassName, + bool RegUnitsHaveUnitWeight) const; + virtual void regInfoEmitGetNumRegPressureSets(std::string const &ClassName, + unsigned NumSets) const; + virtual void regInfoEmitGetRegPressureTables(CodeGenRegBank const &RegBank, + std::string const &ClassName, + unsigned NumSets) const; + virtual void regInfoEmitRCSetsTable( + std::string const &ClassName, unsigned NumRCs, + SequenceToOffsetTable> const &PSetsSeqs, + std::vector> const &PSets) const; + virtual void regInfoEmitGetRegUnitPressureSets( + SequenceToOffsetTable> const &PSetsSeqs, + CodeGenRegBank const &RegBank, std::string const &ClassName, + std::vector> const &PSets) const; + virtual void regInfoEmitExternTableDecl(std::string const &TargetName) const; + virtual void + regInfoEmitRegClassInit(std::string const &TargetName, + std::string const &ClassName, + CodeGenRegBank const &RegBank, + std::list const &RegClasses, + std::deque const &Regs, + unsigned SubRegIndicesSize) const; + virtual void regInfoEmitSaveListTable(Record const *CSRSet, + SetTheory::RecVec const *Regs) const; + virtual void regInfoEmitRegMaskTable(std::string const &CSRSetName, + BitVector &Covered) const; + virtual void + regInfoEmitIsConstantPhysReg(std::deque const &Regs, + std::string const &ClassName) const; + virtual void regInfoEmitGetRegMasks(std::vector const &CSRSets, + std::string const &ClassName) const; + virtual void regInfoEmitGPRCheck( + std::string const &ClassName, + std::list const &RegCategories) const; + virtual void regInfoEmitFixedRegCheck( + std::string const &ClassName, + std::list const &RegCategories) const; + virtual void regInfoEmitArgRegCheck( + std::string const &ClassName, + std::list const &RegCategories) const; + virtual void regInfoEmitGetRegMaskNames(std::vector const &CSRSets, + std::string const &ClassName) const; + virtual void regInfoEmitGetFrameLowering(std::string const &TargetName) const; + virtual void + regInfoEmitComposeSubRegIndicesImplHead(std::string const &ClName) const; + virtual void regInfoEmitComposeSubRegIndicesImplBody( + SmallVector, 4> const &Rows, + unsigned SubRegIndicesSize, SmallVector const &RowMap) const; + virtual void regInfoEmitLaneMaskComposeSeq( + SmallVector, 4> const &Sequences, + SmallVector const &SubReg2SequenceIndexMap, + std::deque const &SubRegIndices) const; + virtual void regInfoEmitComposeSubRegIdxLaneMask( + std::string const &ClName, + std::deque const &SubRegIndices) const; + virtual void regInfoEmitComposeSubRegIdxLaneMaskRev( + std::string const &ClName, + std::deque const &SubRegIndices) const; + virtual void regInfoEmitRegBaseClassMapping( + std::string const &ClassName, + SmallVector const BaseClasses, + std::vector const Mapping) const; +}; + +#endif // LLVM_UTILS_TABLEGEN_PRINTER_H + +} // end namespace llvm Index: llvm/utils/TableGen/PrinterLLVM.cpp =================================================================== --- /dev/null +++ llvm/utils/TableGen/PrinterLLVM.cpp @@ -0,0 +1,1422 @@ +//===------------ PrinterLLVM.cpp - LLVM C++ code printer -----------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Implementation of the LLVM C++ printer. +// +//===----------------------------------------------------------------------===// + +#include "Printer.h" +#include "llvm/TableGen/TableGenBackend.h" + +namespace llvm { + +cl::OptionCategory PrinterLang("Select output language of backends"); + +static cl::opt + PrinterLangOpt("printerLang", cl::init("C++"), + cl::desc("Output language options: \"C++\" (default), " + "\"CCS\" (C Capstone style)"), + cl::cat(PrinterLang)); + +// Print a BitVector as a sequence of hex numbers using a little-endian mapping. +// Width is the number of bits per hex number. +void printBitVectorAsHex(raw_ostream &OS, const BitVector &Bits, + unsigned Width) { + assert(Width <= 32 && "Width too large"); + unsigned const Digits = (Width + 3) / 4; + for (unsigned I = 0, E = Bits.size(); I < E; I += Width) { + unsigned Value = 0; + for (unsigned J = 0; J != Width && I + J != E; ++J) + Value |= Bits.test(I + J) << J; + OS << format("0x%0*x, ", Digits, Value); + } +} + +void PrinterBitVectorEmitter::add(unsigned V) { + if (V >= Values.size()) + Values.resize(((V / 8) + 1) * 8); // Round up to the next byte. + Values[V] = true; +} + +void PrinterBitVectorEmitter::print(raw_ostream &OS) { + printBitVectorAsHex(OS, Values, 8); +} + +// +// General PrinterLLVM methods +// + +PrinterLLVM::PrinterLLVM(formatted_raw_ostream &OS) : OS(OS) {} +PrinterLLVM::~PrinterLLVM() {} + +PrinterLanguage PrinterLLVM::getLanguage() { + if (PrinterLangOpt == "C++") + return PRINTER_LANG_CPP; + if (PrinterLangOpt == "CCS") + return PRINTER_LANG_CAPSTONE_C; + + PrintFatalNote("Unkown output language for printer selected."); +} + +/// Prints `namespace {` and `} // end namespace ` to the output +/// stream. If Name == "" it emits an anonymous namespace. +void PrinterLLVM::emitNamespace(std::string const &Name, bool Begin, + std::string const &Comment) const { + if (Begin) { + OS << "namespace " << Name; + std::string const Bracket = (Name == "" ? "{" : " {"); + if (Comment != "") + OS << Bracket << " // " << Comment << "\n"; + else + OS << Bracket << "\n\n"; + return; + } + + if (Name == "") { + OS << "} // end anonymous namespace\n\n"; + } else { + OS << "} // end namespace " << Name << "\n\n"; + } +} + +/// Prints +/// ``` +/// #ifdef +/// #undef +/// ``` +/// and +/// `#endif // ` +/// Used to control inclusion of a code block via a macro definition. +void PrinterLLVM::emitIncludeToggle(std::string const &Name, bool Begin) const { + if (Begin) { + OS << "\n#ifdef " << Name << "\n"; + OS << "#undef " << Name << "\n\n"; + } else { + OS << "#endif // " << Name << "\n\n"; + } +} + +void PrinterLLVM::regInfoEmitSourceFileHeader(std::string const &Desc) const { + emitSourceFileHeader(Desc, OS); +} + +// runEnums - Print out enum values for all of the registers. +void PrinterLLVM::regInfoEmitEnums(CodeGenTarget const &Target, + CodeGenRegBank const &Bank) const { + const auto &Registers = Bank.getRegisters(); + + // Register enums are stored as uint16_t in the tables. Make sure we'll fit. + assert(Registers.size() <= 0xffff && "Too many regs to fit in tables"); + + StringRef const Namespace = + Registers.front().TheDef->getValueAsString("Namespace"); + + OS << "\n#ifdef GET_REGINFO_ENUM\n"; + OS << "#undef GET_REGINFO_ENUM\n\n"; + + OS << "namespace llvm {\n\n"; + + OS << "class MCRegisterClass;\n" + << "extern const MCRegisterClass " << Target.getName() + << "MCRegisterClasses[];\n\n"; + + if (!Namespace.empty()) + OS << "namespace " << Namespace << " {\n"; + OS << "enum {\n NoRegister,\n"; + + for (const auto &Reg : Registers) + OS << " " << Reg.getName() << " = " << Reg.EnumValue << ",\n"; + assert(Registers.size() == Registers.back().EnumValue && + "Register enum value mismatch!"); + OS << " NUM_TARGET_REGS // " << Registers.size() + 1 << "\n"; + OS << "};\n"; + if (!Namespace.empty()) + OS << "} // end namespace " << Namespace << "\n"; + + const auto &RegisterClasses = Bank.getRegClasses(); + if (!RegisterClasses.empty()) { + + // RegisterClass enums are stored as uint16_t in the tables. + assert(RegisterClasses.size() <= 0xffff && + "Too many register classes to fit in tables"); + + OS << "\n// Register classes\n\n"; + if (!Namespace.empty()) + OS << "namespace " << Namespace << " {\n"; + OS << "enum {\n"; + for (const auto &RC : RegisterClasses) + OS << " " << RC.getName() << "RegClassID" + << " = " << RC.EnumValue << ",\n"; + OS << "\n};\n"; + if (!Namespace.empty()) + OS << "} // end namespace " << Namespace << "\n\n"; + } + + const std::vector &RegAltNameIndices = + Target.getRegAltNameIndices(); + // If the only definition is the default NoRegAltName, we don't need to + // emit anything. + if (RegAltNameIndices.size() > 1) { + OS << "\n// Register alternate name indices\n\n"; + if (!Namespace.empty()) + OS << "namespace " << Namespace << " {\n"; + OS << "enum {\n"; + for (unsigned I = 0, E = RegAltNameIndices.size(); I != E; ++I) + OS << " " << RegAltNameIndices[I]->getName() << ",\t// " << I << "\n"; + OS << " NUM_TARGET_REG_ALT_NAMES = " << RegAltNameIndices.size() << "\n"; + OS << "};\n"; + if (!Namespace.empty()) + OS << "} // end namespace " << Namespace << "\n\n"; + } + + auto &SubRegIndices = Bank.getSubRegIndices(); + if (!SubRegIndices.empty()) { + OS << "\n// Subregister indices\n\n"; + std::string const Namespace = SubRegIndices.front().getNamespace(); + if (!Namespace.empty()) + OS << "namespace " << Namespace << " {\n"; + OS << "enum : uint16_t {\n NoSubRegister,\n"; + unsigned I = 0; + for (const auto &Idx : SubRegIndices) + OS << " " << Idx.getName() << ",\t// " << ++I << "\n"; + OS << " NUM_TARGET_SUBREGS\n};\n"; + if (!Namespace.empty()) + OS << "} // end namespace " << Namespace << "\n\n"; + } + + OS << "// Register pressure sets enum.\n"; + if (!Namespace.empty()) + OS << "namespace " << Namespace << " {\n"; + OS << "enum RegisterPressureSets {\n"; + unsigned const NumSets = Bank.getNumRegPressureSets(); + for (unsigned I = 0; I < NumSets; ++I) { + const RegUnitSet &RegUnits = Bank.getRegSetAt(I); + OS << " " << RegUnits.Name << " = " << I << ",\n"; + } + OS << "};\n"; + if (!Namespace.empty()) + OS << "} // end namespace " << Namespace << '\n'; + OS << '\n'; + + OS << "} // end namespace llvm\n\n"; + OS << "#endif // GET_REGINFO_ENUM\n\n"; +} + +void PrinterLLVM::regInfoEmitRegDiffLists( + std::string const TargetName, + SequenceToOffsetTable const &DiffSeqs) const { + OS << "extern const MCPhysReg " << TargetName << "RegDiffLists[] = {\n"; + DiffSeqs.emit(OS, [](raw_ostream &OS, uint16_t Val) { OS << Val; }); + OS << "};\n\n"; +} + +static void regInfoPrintMask(raw_ostream &OS, LaneBitmask Val) { + OS << "LaneBitmask(0x" << PrintLaneMask(Val) << ')'; +} + +void PrinterLLVM::regInfoEmitLaneMaskLists( + std::string const TargetName, + SequenceToOffsetTable const &LaneMaskSeqs) const { + OS << "extern const LaneBitmask " << TargetName << "LaneMaskLists[] = {\n"; + LaneMaskSeqs.emit(OS, regInfoPrintMask, "LaneBitmask::getAll()"); + OS << "};\n\n"; +} + +void PrinterLLVM::regInfoEmitSubRegIdxLists( + std::string const TargetName, + SequenceToOffsetTable>> const + &SubRegIdxSeqs) const { + OS << "extern const uint16_t " << TargetName << "SubRegIdxLists[] = {\n"; + SubRegIdxSeqs.emit(OS, [](raw_ostream &OS, const CodeGenSubRegIndex *Idx) { + OS << Idx->EnumValue; + }); + OS << "};\n\n"; +} + +void PrinterLLVM::regInfoEmitSubRegIdxSizes( + std::string const TargetName, + std::deque const &SubRegIndices) const { + OS << "extern const MCRegisterInfo::SubRegCoveredBits " << TargetName + << "SubRegIdxRanges[] = {\n"; + OS << " { " << (uint16_t)-1 << ", " << (uint16_t)-1 << " },\n"; + for (const auto &Idx : SubRegIndices) { + OS << " { " << Idx.Offset << ", " << Idx.Size << " },\t// " + << Idx.getName() << "\n"; + } + OS << "};\n\n"; +} + +void PrinterLLVM::regInfoEmitSubRegStrTable( + std::string const TargetName, + SequenceToOffsetTable const &RegStrings) const { + RegStrings.emitStringLiteralDef(OS, Twine("extern const char ") + TargetName + + "RegStrings[]"); + + OS << "extern const MCRegisterDesc " << TargetName + << "RegDesc[] = { // Descriptors\n"; + OS << " { " << RegStrings.get("") << ", 0, 0, 0, 0, 0 },\n"; +} + +void PrinterLLVM::regInfoEmitRegDesc( + SequenceToOffsetTable const &LaneMaskSeqs, + std::deque const &Regs, + SequenceToOffsetTable>> const + &SubRegIdxSeqs, + SequenceToOffsetTable const &DiffSeqs, + SmallVector const &SubRegIdxLists, + SmallVector const &SubRegLists, + SmallVector const &SuperRegLists, + SmallVector const &RegUnitLists, + SmallVector const &RegUnitInitScale, + SmallVector const &RegUnitLaneMasks, + SequenceToOffsetTable const &RegStrings) const { + unsigned I = 0; + for (const auto &Reg : Regs) { + OS << " { " << RegStrings.get(std::string(Reg.getName())) << ", " + << DiffSeqs.get(SubRegLists[I]) << ", " << DiffSeqs.get(SuperRegLists[I]) + << ", " << SubRegIdxSeqs.get(SubRegIdxLists[I]) << ", " + << (DiffSeqs.get(RegUnitLists[I]) * 16 + RegUnitInitScale[I]) << ", " + << LaneMaskSeqs.get(RegUnitLaneMasks[I]) << " },\n"; + ++I; + } + OS << "};\n\n"; // End of register descriptors... +} + +void PrinterLLVM::regInfoEmitRegUnitRoots(std::string const TargetName, + CodeGenRegBank const &RegBank) const { + OS << "extern const MCPhysReg " << TargetName << "RegUnitRoots[][2] = {\n"; + for (unsigned I = 0, E = RegBank.getNumNativeRegUnits(); I != E; ++I) { + ArrayRef const Roots = + RegBank.getRegUnit(I).getRoots(); + assert(!Roots.empty() && "All regunits must have a root register."); + assert(Roots.size() <= 2 && "More than two roots not supported yet."); + OS << " { "; + ListSeparator LS; + for (const CodeGenRegister *R : Roots) + OS << LS << getQualifiedName(R->TheDef); + OS << " },\n"; + } + OS << "};\n\n"; +} + +void PrinterLLVM::regInfoEmitRegClasses( + std::list const &RegClasses, + SequenceToOffsetTable &RegClassStrings, + CodeGenTarget const &Target) const { + for (const auto &RC : RegClasses) { + ArrayRef const Order = RC.getOrder(); + + // Give the register class a legal C name if it's anonymous. + const std::string &Name = RC.getName(); + + RegClassStrings.add(Name); + + // Emit the register list now (unless it would be a zero-length array). + if (!Order.empty()) { + OS << " // " << Name << " Register Class...\n" + << " const MCPhysReg " << Name << "[] = {\n "; + for (Record *Reg : Order) { + OS << getQualifiedName(Reg) << ", "; + } + OS << "\n };\n\n"; + + OS << " // " << Name << " Bit set.\n" + << " const uint8_t " << Name << "Bits[] = {\n "; + PrinterBitVectorEmitter BVE; + for (Record *Reg : Order) { + BVE.add(Target.getRegBank().getReg(Reg)->EnumValue); + } + BVE.print(OS); + OS << "\n };\n\n"; + } + } +} + +void PrinterLLVM::regInfoEmitStrLiteralRegClasses( + std::string const TargetName, + SequenceToOffsetTable const &RegClassStrings) const { + RegClassStrings.emitStringLiteralDef( + OS, Twine("extern const char ") + TargetName + "RegClassStrings[]"); +} + +void PrinterLLVM::regInfoEmitMCRegClassesTable( + std::string const TargetName, + std::list const &RegClasses, + SequenceToOffsetTable &RegClassStrings) const { + OS << "extern const MCRegisterClass " << TargetName + << "MCRegisterClasses[] = {\n"; + + for (const auto &RC : RegClasses) { + ArrayRef const Order = RC.getOrder(); + std::string const RCName = Order.empty() ? "nullptr" : RC.getName(); + std::string const RCBitsName = + Order.empty() ? "nullptr" : RC.getName() + "Bits"; + std::string const RCBitsSize = + Order.empty() ? "0" : "sizeof(" + RCBitsName + ")"; + assert(isInt<8>(RC.CopyCost) && "Copy cost too large."); + uint32_t RegSize = 0; + if (RC.RSI.isSimple()) + RegSize = RC.RSI.getSimple().RegSize; + OS << " { " << RCName << ", " << RCBitsName << ", " + << RegClassStrings.get(RC.getName()) << ", " << RC.getOrder().size() + << ", " << RCBitsSize << ", " << RC.getQualifiedName() + "RegClassID" + << ", " << RegSize << ", " << RC.CopyCost << ", " + << (RC.Allocatable ? "true" : "false") << " },\n"; + } + + OS << "};\n\n"; +} + +void PrinterLLVM::regInfoEmitRegEncodingTable( + std::string const TargetName, + std::deque const &Regs) const { + OS << "extern const uint16_t " << TargetName; + OS << "RegEncodingTable[] = {\n"; + // Add entry for NoRegister + OS << " 0,\n"; + for (const auto &RE : Regs) { + Record *Reg = RE.TheDef; + BitsInit *BI = Reg->getValueAsBitsInit("HWEncoding"); + uint64_t Value = 0; + for (unsigned I = 0, Ie = BI->getNumBits(); I != Ie; ++I) { + if (BitInit *B = dyn_cast(BI->getBit(I))) + Value |= (uint64_t)B->getValue() << I; + } + OS << " " << Value << ",\n"; + } + OS << "};\n"; // End of HW encoding table +} + +void PrinterLLVM::regInfoEmitMCRegInfoInit( + std::string const TargetName, CodeGenRegBank const &RegBank, + std::deque const &Regs, + std::list const &RegClasses, + std::deque const &SubRegIndices) const { + OS << "static inline void Init" << TargetName + << "MCRegisterInfo(MCRegisterInfo *RI, unsigned RA, " + << "unsigned DwarfFlavour = 0, unsigned EHFlavour = 0, unsigned PC = 0) " + "{\n" + << " RI->InitMCRegisterInfo(" << TargetName << "RegDesc, " + << Regs.size() + 1 << ", RA, PC, " << TargetName << "MCRegisterClasses, " + << RegClasses.size() << ", " << TargetName << "RegUnitRoots, " + << RegBank.getNumNativeRegUnits() << ", " << TargetName << "RegDiffLists, " + << TargetName << "LaneMaskLists, " << TargetName << "RegStrings, " + << TargetName << "RegClassStrings, " << TargetName << "SubRegIdxLists, " + << (std::distance(SubRegIndices.begin(), SubRegIndices.end()) + 1) << ",\n" + << TargetName << "SubRegIdxRanges, " << TargetName + << "RegEncodingTable);\n\n"; +} + +void PrinterLLVM::regInfoEmitInfoDwarfRegsRev(StringRef const &Namespace, + DwarfRegNumsVecTy &DwarfRegNums, + unsigned MaxLength, + bool IsCtor) const { + OS << "// " << Namespace << " Dwarf<->LLVM register mappings.\n"; + + // Emit reverse information about the dwarf register numbers. + for (unsigned j = 0; j < 2; ++j) { + for (unsigned I = 0, E = MaxLength; I != E; ++I) { + OS << "extern const MCRegisterInfo::DwarfLLVMRegPair " << Namespace; + OS << (j == 0 ? "DwarfFlavour" : "EHFlavour"); + OS << I << "Dwarf2L[]"; + + if (!IsCtor) { + OS << " = {\n"; + + // Store the mapping sorted by the LLVM reg num so lookup can be done + // with a binary search. + std::map Dwarf2LMap; + for (auto &DwarfRegNum : DwarfRegNums) { + int DwarfRegNo = DwarfRegNum.second[I]; + if (DwarfRegNo < 0) + continue; + Dwarf2LMap[DwarfRegNo] = DwarfRegNum.first; + } + + for (auto &I : Dwarf2LMap) + OS << " { " << I.first << "U, " << getQualifiedName(I.second) + << " },\n"; + + OS << "};\n"; + } else { + OS << ";\n"; + } + + // We have to store the size in a const global, it's used in multiple + // places. + OS << "extern const unsigned " << Namespace + << (j == 0 ? "DwarfFlavour" : "EHFlavour") << I << "Dwarf2LSize"; + if (!IsCtor) + OS << " = std::size(" << Namespace + << (j == 0 ? "DwarfFlavour" : "EHFlavour") << I << "Dwarf2L);\n\n"; + else + OS << ";\n\n"; + } + } +} + +void PrinterLLVM::regInfoEmitInfoDwarfRegs(StringRef const &Namespace, + DwarfRegNumsVecTy &DwarfRegNums, + unsigned MaxLength, + bool IsCtor) const { + for (unsigned J = 0; J < 2; ++J) { + for (unsigned I = 0, E = MaxLength; I != E; ++I) { + OS << "extern const MCRegisterInfo::DwarfLLVMRegPair " << Namespace; + OS << (J == 0 ? "DwarfFlavour" : "EHFlavour"); + OS << I << "L2Dwarf[]"; + if (!IsCtor) { + OS << " = {\n"; + // Store the mapping sorted by the Dwarf reg num so lookup can be done + // with a binary search. + for (auto &DwarfRegNum : DwarfRegNums) { + int RegNo = DwarfRegNum.second[I]; + if (RegNo == -1) // -1 is the default value, don't emit a mapping. + continue; + + OS << " { " << getQualifiedName(DwarfRegNum.first) << ", " << RegNo + << "U },\n"; + } + OS << "};\n"; + } else { + OS << ";\n"; + } + + // We have to store the size in a const global, it's used in multiple + // places. + OS << "extern const unsigned " << Namespace + << (J == 0 ? "DwarfFlavour" : "EHFlavour") << I << "L2DwarfSize"; + if (!IsCtor) + OS << " = std::size(" << Namespace + << (J == 0 ? "DwarfFlavour" : "EHFlavour") << I << "L2Dwarf);\n\n"; + else + OS << ";\n\n"; + } + } +} + +void PrinterLLVM::regInfoEmitInfoRegMapping(StringRef const &Namespace, + unsigned MaxLength, + bool IsCtor) const { + if (MaxLength == 0) { + OS << "}\n\n"; + return; + } + + // Emit reverse information about the dwarf register numbers. + for (unsigned J = 0; J < 2; ++J) { + OS << " switch ("; + if (J == 0) + OS << "DwarfFlavour"; + else + OS << "EHFlavour"; + OS << ") {\n" + << " default:\n" + << " llvm_unreachable(\"Unknown DWARF flavour\");\n"; + + for (unsigned I = 0, E = MaxLength; I != E; ++I) { + OS << " case " << I << ":\n"; + OS << " "; + if (!IsCtor) + OS << "RI->"; + std::string Tmp; + raw_string_ostream(Tmp) + << Namespace << (J == 0 ? "DwarfFlavour" : "EHFlavour") << I + << "Dwarf2L"; + OS << "mapDwarfRegsToLLVMRegs(" << Tmp << ", " << Tmp << "Size, "; + if (J == 0) + OS << "false"; + else + OS << "true"; + OS << ");\n"; + OS << " break;\n"; + } + OS << " }\n"; + } + + // Emit information about the dwarf register numbers. + for (unsigned J = 0; J < 2; ++J) { + OS << " switch ("; + if (J == 0) + OS << "DwarfFlavour"; + else + OS << "EHFlavour"; + OS << ") {\n" + << " default:\n" + << " llvm_unreachable(\"Unknown DWARF flavour\");\n"; + + for (unsigned I = 0, E = MaxLength; I != E; ++I) { + OS << " case " << I << ":\n"; + OS << " "; + if (!IsCtor) + OS << "RI->"; + std::string Tmp; + raw_string_ostream(Tmp) + << Namespace << (J == 0 ? "DwarfFlavour" : "EHFlavour") << I + << "L2Dwarf"; + OS << "mapLLVMRegsToDwarfRegs(" << Tmp << ", " << Tmp << "Size, "; + if (J == 0) + OS << "false"; + else + OS << "true"; + OS << ");\n"; + OS << " break;\n"; + } + OS << " }\n"; + } + + OS << "}\n\n"; +} + +void PrinterLLVM::regInfoEmitHeaderIncludes() const { + OS << "#include \"llvm/CodeGen/TargetRegisterInfo.h\"\n\n"; +} + +void PrinterLLVM::regInfoEmitHeaderExternRegClasses( + std::list const &RegClasses) const { + for (const auto &RC : RegClasses) { + const std::string &Name = RC.getName(); + + // Output the extern for the instance. + OS << " extern const TargetRegisterClass " << Name << "RegClass;\n"; + } +} + +void PrinterLLVM::regInfoEmitHeaderDecl(std::string const &TargetName, + std::string const &ClassName, + bool SubRegsPresent, + bool DeclareGetPhysRegBaseClass) const { + OS << "class " << TargetName << "FrameLowering;\n\n"; + + OS << "struct " << ClassName << " : public TargetRegisterInfo {\n" + << " explicit " << ClassName + << "(unsigned RA, unsigned D = 0, unsigned E = 0,\n" + << " unsigned PC = 0, unsigned HwMode = 0);\n"; + if (SubRegsPresent) { + OS << " unsigned composeSubRegIndicesImpl" + << "(unsigned, unsigned) const override;\n" + << " LaneBitmask composeSubRegIndexLaneMaskImpl" + << "(unsigned, LaneBitmask) const override;\n" + << " LaneBitmask reverseComposeSubRegIndexLaneMaskImpl" + << "(unsigned, LaneBitmask) const override;\n" + << " const TargetRegisterClass *getSubClassWithSubReg" + << "(const TargetRegisterClass *, unsigned) const override;\n" + << " const TargetRegisterClass *getSubRegisterClass" + << "(const TargetRegisterClass *, unsigned) const override;\n"; + } + OS << " const RegClassWeight &getRegClassWeight(" + << "const TargetRegisterClass *RC) const override;\n" + << " unsigned getRegUnitWeight(unsigned RegUnit) const override;\n" + << " unsigned getNumRegPressureSets() const override;\n" + << " const char *getRegPressureSetName(unsigned Idx) const override;\n" + << " unsigned getRegPressureSetLimit(const MachineFunction &MF, unsigned " + "Idx) const override;\n" + << " const int *getRegClassPressureSets(" + << "const TargetRegisterClass *RC) const override;\n" + << " const int *getRegUnitPressureSets(" + << "unsigned RegUnit) const override;\n" + << " ArrayRef getRegMaskNames() const override;\n" + << " ArrayRef getRegMasks() const override;\n" + << " bool isGeneralPurposeRegister(const MachineFunction &, " + << "MCRegister) const override;\n" + << " bool isFixedRegister(const MachineFunction &, " + << "MCRegister) const override;\n" + << " bool isArgumentRegister(const MachineFunction &, " + << "MCRegister) const override;\n" + << " bool isConstantPhysReg(MCRegister PhysReg) const override final;\n" + << " /// Devirtualized TargetFrameLowering.\n" + << " static const " << TargetName << "FrameLowering *getFrameLowering(\n" + << " const MachineFunction &MF);\n"; + if (DeclareGetPhysRegBaseClass) { + OS << " const TargetRegisterClass *getPhysRegBaseClass(MCRegister Reg) " + "const override;\n"; + } + OS << "};\n\n"; +} + +void PrinterLLVM::regInfoEmitExternRegClassesArr( + std::string const &TargetName) const { + OS << "extern const MCRegisterClass " << TargetName + << "MCRegisterClasses[];\n"; +} + +static void printSimpleValueType(raw_ostream &OS, MVT::SimpleValueType VT) { + OS << getEnumName(VT); +} + +void PrinterLLVM::regInfoEmitVTSeqs( + SequenceToOffsetTable> const &VTSeqs) + const { + OS << "\nstatic const MVT::SimpleValueType VTLists[] = {\n"; + VTSeqs.emit(OS, printSimpleValueType, "MVT::Other"); + OS << "};\n"; +} + +static void printMask(raw_ostream &OS, LaneBitmask Val) { + OS << "LaneBitmask(0x" << PrintLaneMask(Val) << ')'; +} + +void PrinterLLVM::regInfoEmitSubRegIdxTable( + std::deque const &SubRegIndices) const { + OS << "\nstatic const char *SubRegIndexNameTable[] = { \""; + + for (const auto &Idx : SubRegIndices) { + OS << Idx.getName(); + OS << "\", \""; + } + OS << "\" };\n\n"; + + // Emit SubRegIndex lane masks, including 0. + OS << "\nstatic const LaneBitmask SubRegIndexLaneMaskTable[] = {\n " + "LaneBitmask::getAll(),\n"; + for (const auto &Idx : SubRegIndices) { + printMask(OS << " ", Idx.LaneMask); + OS << ", // " << Idx.getName() << '\n'; + } + OS << " };\n\n"; + + OS << "\n"; +} + +void PrinterLLVM::regInfoEmitRegClassInfoTable( + std::list const &RegClasses, + SequenceToOffsetTable> const &VTSeqs, + CodeGenHwModes const &CGH, unsigned NumModes) const { + OS << "\nstatic const TargetRegisterInfo::RegClassInfo RegClassInfos[]" + << " = {\n"; + for (unsigned M = 0; M < NumModes; ++M) { + unsigned EV = 0; + OS << " // Mode = " << M << " ("; + if (M == 0) + OS << "Default"; + else + OS << CGH.getMode(M).Name; + OS << ")\n"; + for (const auto &RC : RegClasses) { + assert(RC.EnumValue == EV && "Unexpected order of register classes"); + ++EV; + (void)EV; + const RegSizeInfo &RI = RC.RSI.get(M); + OS << " { " << RI.RegSize << ", " << RI.SpillSize << ", " + << RI.SpillAlignment; + std::vector VTs; + for (const ValueTypeByHwMode &VVT : RC.VTs) + VTs.push_back(VVT.get(M).SimpleTy); + OS << ", VTLists+" << VTSeqs.get(VTs) << " }, // " << RC.getName() + << '\n'; + } + } + OS << "};\n"; + + OS << "\nstatic const TargetRegisterClass *const " + << "NullRegClasses[] = { nullptr };\n\n"; +} + +void PrinterLLVM::regInfoEmitSubClassMaskTable( + std::list const &RegClasses, + SmallVector &SuperRegIdxLists, + SequenceToOffsetTable>> &SuperRegIdxSeqs, + std::deque const &SubRegIndices, + BitVector &MaskBV) const { + for (const auto &RC : RegClasses) { + OS << "static const uint32_t " << RC.getName() << "SubClassMask[] = {\n "; + printBitVectorAsHex(OS, RC.getSubClasses(), 32); + + // Emit super-reg class masks for any relevant SubRegIndices that can + // project into RC. + IdxList &SRIList = SuperRegIdxLists[RC.EnumValue]; + for (auto &Idx : SubRegIndices) { + MaskBV.reset(); + RC.getSuperRegClasses(&Idx, MaskBV); + if (MaskBV.none()) + continue; + SRIList.push_back(&Idx); + OS << "\n "; + printBitVectorAsHex(OS, MaskBV, 32); + OS << "// " << Idx.getName(); + } + SuperRegIdxSeqs.add(SRIList); + OS << "\n};\n\n"; + } +} + +static void printSubRegIndex(raw_ostream &OS, const CodeGenSubRegIndex *Idx) { + OS << Idx->EnumValue; +} + +void PrinterLLVM::regInfoEmitSuperRegIdxSeqsTable( + SequenceToOffsetTable>> const &SuperRegIdxSeqs) + const { + OS << "static const uint16_t SuperRegIdxSeqs[] = {\n"; + SuperRegIdxSeqs.emit(OS, printSubRegIndex); + OS << "};\n\n"; +} + +void PrinterLLVM::regInfoEmitSuperClassesTable( + std::list const &RegClasses) const { + for (const auto &RC : RegClasses) { + ArrayRef const Supers = RC.getSuperClasses(); + + // Skip classes without supers. We can reuse NullRegClasses. + if (Supers.empty()) + continue; + + OS << "static const TargetRegisterClass *const " << RC.getName() + << "Superclasses[] = {\n"; + for (const auto *Super : Supers) + OS << " &" << Super->getQualifiedName() << "RegClass,\n"; + OS << " nullptr\n};\n\n"; + } +} + +void PrinterLLVM::regInfoEmitRegClassMethods( + std::list const &RegClasses, + std::string const &TargetName) const { + for (const auto &RC : RegClasses) { + if (!RC.AltOrderSelect.empty()) { + OS << "\nstatic inline unsigned " << RC.getName() + << "AltOrderSelect(const MachineFunction &MF) {" << RC.AltOrderSelect + << "}\n\n" + << "static ArrayRef " << RC.getName() + << "GetRawAllocationOrder(const MachineFunction &MF) {\n"; + for (unsigned Oi = 1, Oe = RC.getNumOrders(); Oi != Oe; ++Oi) { + ArrayRef const Elems = RC.getOrder(Oi); + if (!Elems.empty()) { + OS << " static const MCPhysReg AltOrder" << Oi << "[] = {"; + for (unsigned Elem = 0; Elem != Elems.size(); ++Elem) + OS << (Elem ? ", " : " ") << getQualifiedName(Elems[Elem]); + OS << " };\n"; + } + } + OS << " const MCRegisterClass &MCR = " << TargetName + << "MCRegisterClasses[" << RC.getQualifiedName() + "RegClassID];\n" + << " const ArrayRef Order[] = {\n" + << " makeArrayRef(MCR.begin(), MCR.getNumRegs()"; + for (unsigned Oi = 1, Oe = RC.getNumOrders(); Oi != Oe; ++Oi) + if (RC.getOrder(Oi).empty()) + OS << "),\n ArrayRef("; + else + OS << "),\n makeArrayRef(AltOrder" << Oi; + OS << ")\n };\n const unsigned Select = " << RC.getName() + << "AltOrderSelect(MF);\n assert(Select < " << RC.getNumOrders() + << ");\n return Order[Select];\n}\n"; + } + } +} + +void PrinterLLVM::regInfomitRegClassInstances( + std::list const &RegClasses, + SequenceToOffsetTable>> const &SuperRegIdxSeqs, + SmallVector const &SuperRegIdxLists, + std::string const &TargetName) const { + for (const auto &RC : RegClasses) { + OS << " extern const TargetRegisterClass " << RC.getName() + << "RegClass = {\n " << '&' << TargetName << "MCRegisterClasses[" + << RC.getName() << "RegClassID],\n " << RC.getName() + << "SubClassMask,\n SuperRegIdxSeqs + " + << SuperRegIdxSeqs.get(SuperRegIdxLists[RC.EnumValue]) << ",\n "; + printMask(OS, RC.LaneMask); + OS << ",\n " << (unsigned)RC.AllocationPriority << ",\n " + << (RC.GlobalPriority ? "true" : "false") << ",\n " + << format("0x%02x", RC.TSFlags) << ", /* TSFlags */\n " + << (RC.HasDisjunctSubRegs ? "true" : "false") + << ", /* HasDisjunctSubRegs */\n " + << (RC.CoveredBySubRegs ? "true" : "false") + << ", /* CoveredBySubRegs */\n "; + if (RC.getSuperClasses().empty()) + OS << "NullRegClasses,\n "; + else + OS << RC.getName() << "Superclasses,\n "; + if (RC.AltOrderSelect.empty()) + OS << "nullptr\n"; + else + OS << RC.getName() << "GetRawAllocationOrder\n"; + OS << " };\n\n"; + } +} + +void PrinterLLVM::regInfoEmitRegClassTable( + std::list const &RegClasses) const { + OS << " const TargetRegisterClass *const RegisterClasses[] = {\n"; + for (const auto &RC : RegClasses) + OS << " &" << RC.getQualifiedName() << "RegClass,\n"; + OS << " };\n"; +} + +void PrinterLLVM::regInfoEmitCostPerUseTable( + std::vector const &AllRegCostPerUse, unsigned NumRegCosts) const { + OS << "\nstatic const uint8_t " + << "CostPerUseTable[] = { \n"; + for (unsigned int I = 0; I < NumRegCosts; ++I) { + for (unsigned J = I, E = AllRegCostPerUse.size(); J < E; J += NumRegCosts) + OS << AllRegCostPerUse[J] << ", "; + } + OS << "};\n\n"; +} + +void PrinterLLVM::regInfoEmitInAllocatableClassTable( + llvm::BitVector const &InAllocClass) const { + OS << "\nstatic const bool " + << "InAllocatableClassTable[] = { \n"; + for (unsigned I = 0, E = InAllocClass.size(); I < E; ++I) { + OS << (InAllocClass[I] ? "true" : "false") << ", "; + } + OS << "};\n\n"; +} + +void PrinterLLVM::regInfoEmitRegExtraDesc(std::string const &TargetName, + unsigned NumRegCosts) const { + OS << "\nstatic const TargetRegisterInfoDesc " << TargetName + << "RegInfoDesc = { // Extra Descriptors\n"; + OS << "CostPerUseTable, " << NumRegCosts << ", " + << "InAllocatableClassTable"; + OS << "};\n\n"; +} + +void PrinterLLVM::regInfoEmitSubClassSubRegGetter( + std::string const &ClassName, unsigned SubRegIndicesSize, + std::deque const &SubRegIndices, + std::list const &RegClasses, + CodeGenRegBank &RegBank) const { + // Emit getSubClassWithSubReg. + OS << "const TargetRegisterClass *" << ClassName + << "::getSubClassWithSubReg(const TargetRegisterClass *RC, unsigned Idx)" + << " const {\n"; + // Use the smallest type that can hold a regclass ID with room for a + // sentinel. + if (RegClasses.size() <= UINT8_MAX) + OS << " static const uint8_t Table["; + else if (RegClasses.size() <= UINT16_MAX) + OS << " static const uint16_t Table["; + else + PrintFatalError("Too many register classes."); + OS << RegClasses.size() << "][" << SubRegIndicesSize << "] = {\n"; + for (const auto &RC : RegClasses) { + OS << " {\t// " << RC.getName() << "\n"; + for (auto &Idx : SubRegIndices) { + if (CodeGenRegisterClass *SRC = RC.getSubClassWithSubReg(&Idx)) + OS << " " << SRC->EnumValue + 1 << ",\t// " << Idx.getName() + << " -> " << SRC->getName() << "\n"; + else + OS << " 0,\t// " << Idx.getName() << "\n"; + } + OS << " },\n"; + } + OS << " };\n assert(RC && \"Missing regclass\");\n" + << " if (!Idx) return RC;\n --Idx;\n" + << " assert(Idx < " << SubRegIndicesSize << " && \"Bad subreg\");\n" + << " unsigned TV = Table[RC->getID()][Idx];\n" + << " return TV ? getRegClass(TV - 1) : nullptr;\n}\n\n"; + + // Emit getSubRegisterClass + OS << "const TargetRegisterClass *" << ClassName + << "::getSubRegisterClass(const TargetRegisterClass *RC, unsigned Idx)" + << " const {\n"; + + // Use the smallest type that can hold a regclass ID with room for a + // sentinel. + if (RegClasses.size() <= UINT8_MAX) + OS << " static const uint8_t Table["; + else if (RegClasses.size() <= UINT16_MAX) + OS << " static const uint16_t Table["; + else + PrintFatalError("Too many register classes."); + + OS << RegClasses.size() << "][" << SubRegIndicesSize << "] = {\n"; + + for (const auto &RC : RegClasses) { + OS << " {\t// " << RC.getName() << '\n'; + for (auto &Idx : SubRegIndices) { + std::optional> + MatchingSubClass = RC.getMatchingSubClassWithSubRegs(RegBank, &Idx); + + unsigned EnumValue = 0; + if (MatchingSubClass) { + CodeGenRegisterClass *SubRegClass = MatchingSubClass->second; + EnumValue = SubRegClass->EnumValue + 1; + } + + OS << " " << EnumValue << ",\t// " << RC.getName() << ':' + << Idx.getName(); + + if (MatchingSubClass) { + CodeGenRegisterClass *SubRegClass = MatchingSubClass->second; + OS << " -> " << SubRegClass->getName(); + } + + OS << '\n'; + } + + OS << " },\n"; + } + OS << " };\n assert(RC && \"Missing regclass\");\n" + << " if (!Idx) return RC;\n --Idx;\n" + << " assert(Idx < " << SubRegIndicesSize << " && \"Bad subreg\");\n" + << " unsigned TV = Table[RC->getID()][Idx];\n" + << " return TV ? getRegClass(TV - 1) : nullptr;\n}\n\n"; +} + +void PrinterLLVM::regInfoEmitRegClassWeight( + CodeGenRegBank const &RegBank, std::string const &ClassName) const { + OS << "/// Get the weight in units of pressure for this register class.\n" + << "const RegClassWeight &" << ClassName << "::\n" + << "getRegClassWeight(const TargetRegisterClass *RC) const {\n" + << " static const RegClassWeight RCWeightTable[] = {\n"; + for (const auto &RC : RegBank.getRegClasses()) { + const CodeGenRegister::Vec &Regs = RC.getMembers(); + OS << " {" << RC.getWeight(RegBank) << ", "; + if (Regs.empty() || RC.Artificial) + OS << '0'; + else { + std::vector RegUnits; + RC.buildRegUnitSet(RegBank, RegUnits); + OS << RegBank.getRegUnitSetWeight(RegUnits); + } + OS << "}, \t// " << RC.getName() << "\n"; + } + OS << " };\n" + << " return RCWeightTable[RC->getID()];\n" + << "}\n\n"; +} + +void PrinterLLVM::regInfoEmitRegUnitWeight(CodeGenRegBank const &RegBank, + std::string const &ClassName, + bool RegUnitsHaveUnitWeight) const { + OS << "/// Get the weight in units of pressure for this register unit.\n" + << "unsigned " << ClassName << "::\n" + << "getRegUnitWeight(unsigned RegUnit) const {\n" + << " assert(RegUnit < " << RegBank.getNumNativeRegUnits() + << " && \"invalid register unit\");\n"; + if (!RegUnitsHaveUnitWeight) { + OS << " static const uint8_t RUWeightTable[] = {\n "; + for (unsigned UnitIdx = 0, UnitEnd = RegBank.getNumNativeRegUnits(); + UnitIdx < UnitEnd; ++UnitIdx) { + const RegUnit &RU = RegBank.getRegUnit(UnitIdx); + assert(RU.Weight < 256 && "RegUnit too heavy"); + OS << RU.Weight << ", "; + } + OS << "};\n" + << " return RUWeightTable[RegUnit];\n"; + } else { + OS << " // All register units have unit weight.\n" + << " return 1;\n"; + } + OS << "}\n\n"; +} + +void PrinterLLVM::regInfoEmitGetNumRegPressureSets(std::string const &ClassName, + unsigned NumSets) const { + OS << "\n" + << "// Get the number of dimensions of register pressure.\n" + << "unsigned " << ClassName << "::getNumRegPressureSets() const {\n" + << " return " << NumSets << ";\n}\n\n"; +} + +void PrinterLLVM::regInfoEmitGetRegPressureTables(CodeGenRegBank const &RegBank, + std::string const &ClassName, + unsigned NumSets) const { + OS << "// Get the name of this register unit pressure set.\n" + << "const char *" << ClassName << "::\n" + << "getRegPressureSetName(unsigned Idx) const {\n" + << " static const char *PressureNameTable[] = {\n"; + unsigned MaxRegUnitWeight = 0; + for (unsigned I = 0; I < NumSets; ++I) { + const RegUnitSet &RegUnits = RegBank.getRegSetAt(I); + MaxRegUnitWeight = std::max(MaxRegUnitWeight, RegUnits.Weight); + OS << " \"" << RegUnits.Name << "\",\n"; + } + OS << " };\n" + << " return PressureNameTable[Idx];\n" + << "}\n\n"; + + OS << "// Get the register unit pressure limit for this dimension.\n" + << "// This limit must be adjusted dynamically for reserved registers.\n" + << "unsigned " << ClassName << "::\n" + << "getRegPressureSetLimit(const MachineFunction &MF, unsigned Idx) const " + "{\n" + << " static const " << getMinimalTypeForRange(MaxRegUnitWeight, 32) + << " PressureLimitTable[] = {\n"; + for (unsigned I = 0; I < NumSets; ++I) { + const RegUnitSet &RegUnits = RegBank.getRegSetAt(I); + OS << " " << RegUnits.Weight << ", \t// " << I << ": " << RegUnits.Name + << "\n"; + } + OS << " };\n" + << " return PressureLimitTable[Idx];\n" + << "}\n\n"; +} + +static void printInt(raw_ostream &OS, int Val) { OS << Val; } + +void PrinterLLVM::regInfoEmitRCSetsTable( + std::string const &ClassName, unsigned NumRCs, + SequenceToOffsetTable> const &PSetsSeqs, + std::vector> const &PSets) const { + OS << "/// Table of pressure sets per register class or unit.\n" + << "static const int RCSetsTable[] = {\n"; + PSetsSeqs.emit(OS, printInt, "-1"); + OS << "};\n\n"; + + OS << "/// Get the dimensions of register pressure impacted by this " + << "register class.\n" + << "/// Returns a -1 terminated array of pressure set IDs\n" + << "const int *" << ClassName << "::\n" + << "getRegClassPressureSets(const TargetRegisterClass *RC) const {\n"; + OS << " static const " << getMinimalTypeForRange(PSetsSeqs.size() - 1, 32) + << " RCSetStartTable[] = {\n "; + for (unsigned I = 0, E = NumRCs; I != E; ++I) { + OS << PSetsSeqs.get(PSets[I]) << ","; + } + OS << "};\n" + << " return &RCSetsTable[RCSetStartTable[RC->getID()]];\n" + << "}\n\n"; +} + +void PrinterLLVM::regInfoEmitGetRegUnitPressureSets( + SequenceToOffsetTable> const &PSetsSeqs, + CodeGenRegBank const &RegBank, std::string const &ClassName, + std::vector> const &PSets) const { + OS << "/// Get the dimensions of register pressure impacted by this " + << "register unit.\n" + << "/// Returns a -1 terminated array of pressure set IDs\n" + << "const int *" << ClassName << "::\n" + << "getRegUnitPressureSets(unsigned RegUnit) const {\n" + << " assert(RegUnit < " << RegBank.getNumNativeRegUnits() + << " && \"invalid register unit\");\n"; + OS << " static const " << getMinimalTypeForRange(PSetsSeqs.size() - 1, 32) + << " RUSetStartTable[] = {\n "; + for (unsigned UnitIdx = 0, UnitEnd = RegBank.getNumNativeRegUnits(); + UnitIdx < UnitEnd; ++UnitIdx) { + OS << PSetsSeqs.get(PSets[RegBank.getRegUnit(UnitIdx).RegClassUnitSetsIdx]) + << ","; + } + OS << "};\n" + << " return &RCSetsTable[RUSetStartTable[RegUnit]];\n" + << "}\n\n"; +} + +void PrinterLLVM::regInfoEmitExternTableDecl( + std::string const &TargetName) const { + OS << "extern const MCRegisterDesc " << TargetName << "RegDesc[];\n"; + OS << "extern const MCPhysReg " << TargetName << "RegDiffLists[];\n"; + OS << "extern const LaneBitmask " << TargetName << "LaneMaskLists[];\n"; + OS << "extern const char " << TargetName << "RegStrings[];\n"; + OS << "extern const char " << TargetName << "RegClassStrings[];\n"; + OS << "extern const MCPhysReg " << TargetName << "RegUnitRoots[][2];\n"; + OS << "extern const uint16_t " << TargetName << "SubRegIdxLists[];\n"; + OS << "extern const MCRegisterInfo::SubRegCoveredBits " << TargetName + << "SubRegIdxRanges[];\n"; + OS << "extern const uint16_t " << TargetName << "RegEncodingTable[];\n"; +} + +void PrinterLLVM::regInfoEmitRegClassInit( + std::string const &TargetName, std::string const &ClassName, + CodeGenRegBank const &RegBank, + std::list const &RegClasses, + std::deque const &Regs, unsigned SubRegIndicesSize) const { + OS << ClassName << "::\n" + << ClassName + << "(unsigned RA, unsigned DwarfFlavour, unsigned EHFlavour,\n" + " unsigned PC, unsigned HwMode)\n" + << " : TargetRegisterInfo(&" << TargetName << "RegInfoDesc" + << ", RegisterClasses, RegisterClasses+" << RegClasses.size() << ",\n" + << " SubRegIndexNameTable, SubRegIndexLaneMaskTable,\n" + << " "; + printMask(OS, RegBank.CoveringLanes); + OS << ", RegClassInfos, HwMode) {\n" + << " InitMCRegisterInfo(" << TargetName << "RegDesc, " << Regs.size() + 1 + << ", RA, PC,\n " << TargetName + << "MCRegisterClasses, " << RegClasses.size() << ",\n" + << " " << TargetName << "RegUnitRoots,\n" + << " " << RegBank.getNumNativeRegUnits() << ",\n" + << " " << TargetName << "RegDiffLists,\n" + << " " << TargetName << "LaneMaskLists,\n" + << " " << TargetName << "RegStrings,\n" + << " " << TargetName << "RegClassStrings,\n" + << " " << TargetName << "SubRegIdxLists,\n" + << " " << SubRegIndicesSize + 1 << ",\n" + << " " << TargetName << "SubRegIdxRanges,\n" + << " " << TargetName << "RegEncodingTable);\n\n"; +} + +void PrinterLLVM::regInfoEmitSaveListTable( + Record const *CSRSet, SetTheory::RecVec const *Regs) const { + OS << "static const MCPhysReg " << CSRSet->getName() << "_SaveList[] = { "; + for (unsigned R = 0, Re = Regs->size(); R != Re; ++R) + OS << getQualifiedName((*Regs)[R]) << ", "; + OS << "0 };\n"; +} + +void PrinterLLVM::regInfoEmitRegMaskTable(std::string const &CSRSetName, + BitVector &Covered) const { + OS << "static const uint32_t " << CSRSetName << "_RegMask[] = { "; + printBitVectorAsHex(OS, Covered, 32); + OS << "};\n"; +} + +void PrinterLLVM::regInfoEmitGetRegMasks(std::vector const &CSRSets, + std::string const &ClassName) const { + OS << "ArrayRef " << ClassName + << "::getRegMasks() const {\n"; + if (!CSRSets.empty()) { + OS << " static const uint32_t *const Masks[] = {\n"; + for (Record *CSRSet : CSRSets) + OS << " " << CSRSet->getName() << "_RegMask,\n"; + OS << " };\n"; + OS << " return makeArrayRef(Masks);\n"; + } else { + OS << " return std::nullopt;\n"; + } + OS << "}\n\n"; +} + +void PrinterLLVM::regInfoEmitGPRCheck( + std::string const &ClassName, + std::list const &RegCategories) const { + OS << "bool " << ClassName << "::\n" + << "isGeneralPurposeRegister(const MachineFunction &MF, " + << "MCRegister PhysReg) const {\n" + << " return\n"; + for (const CodeGenRegisterCategory &Category : RegCategories) + if (Category.getName() == "GeneralPurposeRegisters") { + for (const CodeGenRegisterClass *RC : Category.getClasses()) + OS << " " << RC->getQualifiedName() + << "RegClass.contains(PhysReg) ||\n"; + break; + } + OS << " false;\n"; + OS << "}\n\n"; +} +void PrinterLLVM::regInfoEmitFixedRegCheck( + std::string const &ClassName, + std::list const &RegCategories) const { + OS << "bool " << ClassName << "::\n" + << "isFixedRegister(const MachineFunction &MF, " + << "MCRegister PhysReg) const {\n" + << " return\n"; + for (const CodeGenRegisterCategory &Category : RegCategories) + if (Category.getName() == "FixedRegisters") { + for (const CodeGenRegisterClass *RC : Category.getClasses()) + OS << " " << RC->getQualifiedName() + << "RegClass.contains(PhysReg) ||\n"; + break; + } + OS << " false;\n"; + OS << "}\n\n"; +} + +void PrinterLLVM::regInfoEmitArgRegCheck( + std::string const &ClassName, + std::list const &RegCategories) const { + OS << "bool " << ClassName << "::\n" + << "isArgumentRegister(const MachineFunction &MF, " + << "MCRegister PhysReg) const {\n" + << " return\n"; + for (const CodeGenRegisterCategory &Category : RegCategories) + if (Category.getName() == "ArgumentRegisters") { + for (const CodeGenRegisterClass *RC : Category.getClasses()) + OS << " " << RC->getQualifiedName() + << "RegClass.contains(PhysReg) ||\n"; + break; + } + OS << " false;\n"; + OS << "}\n\n"; +} + +void PrinterLLVM::regInfoEmitIsConstantPhysReg( + std::deque const &Regs, + std::string const &ClassName) const { + OS << "bool " << ClassName << "::\n" + << "isConstantPhysReg(MCRegister PhysReg) const {\n" + << " return\n"; + for (const auto &Reg : Regs) + if (Reg.Constant) + OS << " PhysReg == " << getQualifiedName(Reg.TheDef) << " ||\n"; + OS << " false;\n"; + OS << "}\n\n"; +} + +void PrinterLLVM::regInfoEmitGetRegMaskNames( + std::vector const &CSRSets, std::string const &ClassName) const { + OS << "ArrayRef " << ClassName + << "::getRegMaskNames() const {\n"; + if (!CSRSets.empty()) { + OS << " static const char *Names[] = {\n"; + for (Record *CSRSet : CSRSets) + OS << " " << '"' << CSRSet->getName() << '"' << ",\n"; + OS << " };\n"; + OS << " return makeArrayRef(Names);\n"; + } else { + OS << " return std::nullopt;\n"; + } + OS << "}\n\n"; +} + +void PrinterLLVM::regInfoEmitGetFrameLowering( + std::string const &TargetName) const { + OS << "const " << TargetName << "FrameLowering *\n" + << TargetName + << "GenRegisterInfo::getFrameLowering(const MachineFunction &MF) {\n" + << " return static_cast(\n" + << " MF.getSubtarget().getFrameLowering());\n" + << "}\n\n"; +} + +void PrinterLLVM::regInfoEmitComposeSubRegIndicesImplHead( + std::string const &ClName) const { + OS << "unsigned " << ClName + << "::composeSubRegIndicesImpl(unsigned IdxA, unsigned IdxB) const {\n"; +} + +void PrinterLLVM::regInfoEmitComposeSubRegIndicesImplBody( + SmallVector, 4> const &Rows, + unsigned SubRegIndicesSize, SmallVector const &RowMap) const { + if (Rows.size() > 1) { + OS << " static const " << getMinimalTypeForRange(Rows.size(), 32) + << " RowMap[" << SubRegIndicesSize << "] = {\n "; + for (unsigned I = 0, E = SubRegIndicesSize; I != E; ++I) + OS << RowMap[I] << ", "; + OS << "\n };\n"; + } + + // Output the rows. + OS << " static const " << getMinimalTypeForRange(SubRegIndicesSize + 1, 32) + << " Rows[" << Rows.size() << "][" << SubRegIndicesSize << "] = {\n"; + for (unsigned R = 0, Re = Rows.size(); R != Re; ++R) { + OS << " { "; + for (unsigned I = 0, E = SubRegIndicesSize; I != E; ++I) + if (Rows[R][I]) + OS << Rows[R][I]->getQualifiedName() << ", "; + else + OS << "0, "; + OS << "},\n"; + } + OS << " };\n\n"; + + OS << " --IdxA; assert(IdxA < " << SubRegIndicesSize << "); (void) IdxA;\n" + << " --IdxB; assert(IdxB < " << SubRegIndicesSize << ");\n"; + if (Rows.size() > 1) + OS << " return Rows[RowMap[IdxA]][IdxB];\n"; + else + OS << " return Rows[0][IdxB];\n"; + OS << "}\n\n"; +} + +void PrinterLLVM::regInfoEmitLaneMaskComposeSeq( + SmallVector, 4> const &Sequences, + SmallVector const &SubReg2SequenceIndexMap, + std::deque const &SubRegIndices) const { + OS << " struct MaskRolOp {\n" + " LaneBitmask Mask;\n" + " uint8_t RotateLeft;\n" + " };\n" + " static const MaskRolOp LaneMaskComposeSequences[] = {\n"; + unsigned Idx = 0; + for (size_t S = 0, Se = Sequences.size(); S != Se; ++S) { + OS << " "; + const SmallVectorImpl &Sequence = Sequences[S]; + for (size_t P = 0, Pe = Sequence.size(); P != Pe; ++P) { + const MaskRolPair &MRP = Sequence[P]; + printMask(OS << "{ ", MRP.Mask); + OS << format(", %2u }, ", MRP.RotateLeft); + } + OS << "{ LaneBitmask::getNone(), 0 }"; + if (S + 1 != Se) + OS << ", "; + OS << " // Sequence " << Idx << "\n"; + Idx += Sequence.size() + 1; + } + auto *IntType = getMinimalTypeForRange(*std::max_element( + SubReg2SequenceIndexMap.begin(), SubReg2SequenceIndexMap.end())); + OS << " };\n" + " static const " + << IntType << " CompositeSequences[] = {\n"; + for (size_t I = 0, E = SubRegIndices.size(); I != E; ++I) { + OS << " "; + OS << SubReg2SequenceIndexMap[I]; + if (I + 1 != E) + OS << ","; + OS << " // to " << SubRegIndices[I].getName() << "\n"; + } + OS << " };\n\n"; +} + +void PrinterLLVM::regInfoEmitComposeSubRegIdxLaneMask( + std::string const &ClName, + std::deque const &SubRegIndices) const { + OS << "LaneBitmask " << ClName + << "::composeSubRegIndexLaneMaskImpl(unsigned IdxA, " + "LaneBitmask LaneMask) const {\n" + " --IdxA; assert(IdxA < " + << SubRegIndices.size() + << " && \"Subregister index out of bounds\");\n" + " LaneBitmask Result;\n" + " for (const MaskRolOp *Ops =\n" + " &LaneMaskComposeSequences[CompositeSequences[IdxA]];\n" + " Ops->Mask.any(); ++Ops) {\n" + " LaneBitmask::Type M = LaneMask.getAsInteger() & " + "Ops->Mask.getAsInteger();\n" + " if (unsigned S = Ops->RotateLeft)\n" + " Result |= LaneBitmask((M << S) | (M >> (LaneBitmask::BitWidth - " + "S)));\n" + " else\n" + " Result |= LaneBitmask(M);\n" + " }\n" + " return Result;\n" + "}\n\n"; +} + +void PrinterLLVM::regInfoEmitComposeSubRegIdxLaneMaskRev( + std::string const &ClName, + std::deque const &SubRegIndices) const { + OS << "LaneBitmask " << ClName + << "::reverseComposeSubRegIndexLaneMaskImpl(unsigned IdxA, " + " LaneBitmask LaneMask) const {\n" + " LaneMask &= getSubRegIndexLaneMask(IdxA);\n" + " --IdxA; assert(IdxA < " + << SubRegIndices.size() + << " && \"Subregister index out of bounds\");\n" + " LaneBitmask Result;\n" + " for (const MaskRolOp *Ops =\n" + " &LaneMaskComposeSequences[CompositeSequences[IdxA]];\n" + " Ops->Mask.any(); ++Ops) {\n" + " LaneBitmask::Type M = LaneMask.getAsInteger();\n" + " if (unsigned S = Ops->RotateLeft)\n" + " Result |= LaneBitmask((M >> S) | (M << (LaneBitmask::BitWidth - " + "S)));\n" + " else\n" + " Result |= LaneBitmask(M);\n" + " }\n" + " return Result;\n" + "}\n\n"; +} + +void PrinterLLVM::regInfoEmitRegBaseClassMapping( + std::string const &ClassName, + SmallVector const BaseClasses, + std::vector const Mapping) const { + OS << "\n// Register to base register class mapping\n\n"; + OS << "\n"; + OS << "const TargetRegisterClass *" << ClassName + << "::getPhysRegBaseClass(MCRegister Reg)" + << " const {\n"; + OS << " static const TargetRegisterClass *BaseClasses[" + << (BaseClasses.size() + 1) << "] = {\n"; + OS << " nullptr,\n"; + for (const auto *const RC : BaseClasses) + OS << " &" << RC->getQualifiedName() << "RegClass,\n"; + OS << " };\n"; + OS << " static const uint8_t Mapping[" << Mapping.size() << "] = {\n "; + for (const uint8_t Value : Mapping) + OS << (unsigned)Value << ","; + OS << " };\n\n"; + OS << " assert(Reg < sizeof(Mapping));\n"; + OS << " return BaseClasses[Mapping[Reg]];\n"; + OS << "}\n"; +} + +} // end namespace llvm Index: llvm/utils/TableGen/PrinterTypes.h =================================================================== --- /dev/null +++ llvm/utils/TableGen/PrinterTypes.h @@ -0,0 +1,22 @@ +//===------------- PrinterTypes.h - Printer Interface -----------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_UTILS_TABLEGEN_PRINTERTYPES_H +#define LLVM_UTILS_TABLEGEN_PRINTERTYPES_H + +#include "llvm/ADT/BitVector.h" +namespace llvm { + +enum PrinterLanguage { + PRINTER_LANG_CPP, + PRINTER_LANG_CAPSTONE_C, +}; + +} // end namespace llvm + +#endif // LLVM_UTILS_TABLEGEN_PRINTERTYPES_H Index: llvm/utils/TableGen/RegisterInfoEmitter.cpp =================================================================== --- llvm/utils/TableGen/RegisterInfoEmitter.cpp +++ llvm/utils/TableGen/RegisterInfoEmitter.cpp @@ -12,35 +12,8 @@ // //===----------------------------------------------------------------------===// -#include "CodeGenRegisters.h" -#include "CodeGenTarget.h" -#include "SequenceToOffsetTable.h" -#include "Types.h" -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/BitVector.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/SetVector.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/SparseBitVector.h" -#include "llvm/ADT/Twine.h" -#include "llvm/Support/Casting.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/Format.h" -#include "llvm/Support/MachineValueType.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/TableGen/Error.h" -#include "llvm/TableGen/Record.h" -#include "llvm/TableGen/SetTheory.h" -#include "llvm/TableGen/TableGenBackend.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include "Printer.h" +#include "RegisterInfoEmitterTypes.h" using namespace llvm; @@ -56,180 +29,53 @@ class RegisterInfoEmitter { CodeGenTarget Target; RecordKeeper &Records; + PrinterLLVM &PI; public: - RegisterInfoEmitter(RecordKeeper &R) : Target(R), Records(R) { + RegisterInfoEmitter(RecordKeeper &R, PrinterLLVM &PI) + : Target(R), Records(R), PI(PI) { CodeGenRegBank &RegBank = Target.getRegBank(); RegBank.computeDerivedInfo(); } - // runEnums - Print out enum values for all of the registers. - void runEnums(raw_ostream &o, CodeGenTarget &Target, CodeGenRegBank &Bank); - // runMCDesc - Print out MC register descriptions. - void runMCDesc(raw_ostream &o, CodeGenTarget &Target, CodeGenRegBank &Bank); + void runMCDesc(CodeGenTarget &Target, CodeGenRegBank &Bank); // runTargetHeader - Emit a header fragment for the register info emitter. - void runTargetHeader(raw_ostream &o, CodeGenTarget &Target, + void runTargetHeader(CodeGenTarget &Target, CodeGenRegBank &Bank); // runTargetDesc - Output the target register and register file descriptions. - void runTargetDesc(raw_ostream &o, CodeGenTarget &Target, + void runTargetDesc(CodeGenTarget &Target, CodeGenRegBank &Bank); // run - Output the register file description. - void run(raw_ostream &o); + void run(); void debugDump(raw_ostream &OS); private: - void EmitRegMapping(raw_ostream &o, const std::deque &Regs, + void EmitRegMapping(const std::deque &Regs, bool isCtor); - void EmitRegMappingTables(raw_ostream &o, - const std::deque &Regs, + void EmitRegMappingTables(const std::deque &Regs, bool isCtor); - void EmitRegUnitPressure(raw_ostream &OS, const CodeGenRegBank &RegBank, + void EmitRegUnitPressure(const CodeGenRegBank &RegBank, const std::string &ClassName); - void emitComposeSubRegIndices(raw_ostream &OS, CodeGenRegBank &RegBank, + void emitComposeSubRegIndices(CodeGenRegBank &RegBank, const std::string &ClassName); - void emitComposeSubRegIndexLaneMask(raw_ostream &OS, CodeGenRegBank &RegBank, + void emitComposeSubRegIndexLaneMask(CodeGenRegBank &RegBank, const std::string &ClassName); }; } // end anonymous namespace -// runEnums - Print out enum values for all of the registers. -void RegisterInfoEmitter::runEnums(raw_ostream &OS, - CodeGenTarget &Target, CodeGenRegBank &Bank) { - const auto &Registers = Bank.getRegisters(); - - // Register enums are stored as uint16_t in the tables. Make sure we'll fit. - assert(Registers.size() <= 0xffff && "Too many regs to fit in tables"); - - StringRef Namespace = Registers.front().TheDef->getValueAsString("Namespace"); - - emitSourceFileHeader("Target Register Enum Values", OS); - - OS << "\n#ifdef GET_REGINFO_ENUM\n"; - OS << "#undef GET_REGINFO_ENUM\n\n"; - - OS << "namespace llvm {\n\n"; - - OS << "class MCRegisterClass;\n" - << "extern const MCRegisterClass " << Target.getName() - << "MCRegisterClasses[];\n\n"; - - if (!Namespace.empty()) - OS << "namespace " << Namespace << " {\n"; - OS << "enum {\n NoRegister,\n"; - - for (const auto &Reg : Registers) - OS << " " << Reg.getName() << " = " << Reg.EnumValue << ",\n"; - assert(Registers.size() == Registers.back().EnumValue && - "Register enum value mismatch!"); - OS << " NUM_TARGET_REGS // " << Registers.size()+1 << "\n"; - OS << "};\n"; - if (!Namespace.empty()) - OS << "} // end namespace " << Namespace << "\n"; - - const auto &RegisterClasses = Bank.getRegClasses(); - if (!RegisterClasses.empty()) { - - // RegisterClass enums are stored as uint16_t in the tables. - assert(RegisterClasses.size() <= 0xffff && - "Too many register classes to fit in tables"); - - OS << "\n// Register classes\n\n"; - if (!Namespace.empty()) - OS << "namespace " << Namespace << " {\n"; - OS << "enum {\n"; - for (const auto &RC : RegisterClasses) - OS << " " << RC.getName() << "RegClassID" - << " = " << RC.EnumValue << ",\n"; - OS << "\n};\n"; - if (!Namespace.empty()) - OS << "} // end namespace " << Namespace << "\n\n"; - } - - const std::vector &RegAltNameIndices = Target.getRegAltNameIndices(); - // If the only definition is the default NoRegAltName, we don't need to - // emit anything. - if (RegAltNameIndices.size() > 1) { - OS << "\n// Register alternate name indices\n\n"; - if (!Namespace.empty()) - OS << "namespace " << Namespace << " {\n"; - OS << "enum {\n"; - for (unsigned i = 0, e = RegAltNameIndices.size(); i != e; ++i) - OS << " " << RegAltNameIndices[i]->getName() << ",\t// " << i << "\n"; - OS << " NUM_TARGET_REG_ALT_NAMES = " << RegAltNameIndices.size() << "\n"; - OS << "};\n"; - if (!Namespace.empty()) - OS << "} // end namespace " << Namespace << "\n\n"; - } - - auto &SubRegIndices = Bank.getSubRegIndices(); - if (!SubRegIndices.empty()) { - OS << "\n// Subregister indices\n\n"; - std::string Namespace = SubRegIndices.front().getNamespace(); - if (!Namespace.empty()) - OS << "namespace " << Namespace << " {\n"; - OS << "enum : uint16_t {\n NoSubRegister,\n"; - unsigned i = 0; - for (const auto &Idx : SubRegIndices) - OS << " " << Idx.getName() << ",\t// " << ++i << "\n"; - OS << " NUM_TARGET_SUBREGS\n};\n"; - if (!Namespace.empty()) - OS << "} // end namespace " << Namespace << "\n\n"; - } - - OS << "// Register pressure sets enum.\n"; - if (!Namespace.empty()) - OS << "namespace " << Namespace << " {\n"; - OS << "enum RegisterPressureSets {\n"; - unsigned NumSets = Bank.getNumRegPressureSets(); - for (unsigned i = 0; i < NumSets; ++i ) { - const RegUnitSet &RegUnits = Bank.getRegSetAt(i); - OS << " " << RegUnits.Name << " = " << i << ",\n"; - } - OS << "};\n"; - if (!Namespace.empty()) - OS << "} // end namespace " << Namespace << '\n'; - OS << '\n'; - - OS << "} // end namespace llvm\n\n"; - OS << "#endif // GET_REGINFO_ENUM\n\n"; -} - -static void printInt(raw_ostream &OS, int Val) { - OS << Val; -} - void RegisterInfoEmitter:: -EmitRegUnitPressure(raw_ostream &OS, const CodeGenRegBank &RegBank, +EmitRegUnitPressure(const CodeGenRegBank &RegBank, const std::string &ClassName) { unsigned NumRCs = RegBank.getRegClasses().size(); unsigned NumSets = RegBank.getNumRegPressureSets(); - OS << "/// Get the weight in units of pressure for this register class.\n" - << "const RegClassWeight &" << ClassName << "::\n" - << "getRegClassWeight(const TargetRegisterClass *RC) const {\n" - << " static const RegClassWeight RCWeightTable[] = {\n"; - for (const auto &RC : RegBank.getRegClasses()) { - const CodeGenRegister::Vec &Regs = RC.getMembers(); - OS << " {" << RC.getWeight(RegBank) << ", "; - if (Regs.empty() || RC.Artificial) - OS << '0'; - else { - std::vector RegUnits; - RC.buildRegUnitSet(RegBank, RegUnits); - OS << RegBank.getRegUnitSetWeight(RegUnits); - } - OS << "}, \t// " << RC.getName() << "\n"; - } - OS << " };\n" - << " return RCWeightTable[RC->getID()];\n" - << "}\n\n"; - + PI.regInfoEmitRegClassWeight(RegBank, ClassName); // Reasonable targets (not ARMv7) have unit weight for all units, so don't // bother generating a table. bool RegUnitsHaveUnitWeight = true; @@ -238,64 +84,11 @@ if (RegBank.getRegUnit(UnitIdx).Weight > 1) RegUnitsHaveUnitWeight = false; } - OS << "/// Get the weight in units of pressure for this register unit.\n" - << "unsigned " << ClassName << "::\n" - << "getRegUnitWeight(unsigned RegUnit) const {\n" - << " assert(RegUnit < " << RegBank.getNumNativeRegUnits() - << " && \"invalid register unit\");\n"; - if (!RegUnitsHaveUnitWeight) { - OS << " static const uint8_t RUWeightTable[] = {\n "; - for (unsigned UnitIdx = 0, UnitEnd = RegBank.getNumNativeRegUnits(); - UnitIdx < UnitEnd; ++UnitIdx) { - const RegUnit &RU = RegBank.getRegUnit(UnitIdx); - assert(RU.Weight < 256 && "RegUnit too heavy"); - OS << RU.Weight << ", "; - } - OS << "};\n" - << " return RUWeightTable[RegUnit];\n"; - } - else { - OS << " // All register units have unit weight.\n" - << " return 1;\n"; - } - OS << "}\n\n"; - - OS << "\n" - << "// Get the number of dimensions of register pressure.\n" - << "unsigned " << ClassName << "::getNumRegPressureSets() const {\n" - << " return " << NumSets << ";\n}\n\n"; - - OS << "// Get the name of this register unit pressure set.\n" - << "const char *" << ClassName << "::\n" - << "getRegPressureSetName(unsigned Idx) const {\n" - << " static const char *PressureNameTable[] = {\n"; - unsigned MaxRegUnitWeight = 0; - for (unsigned i = 0; i < NumSets; ++i ) { - const RegUnitSet &RegUnits = RegBank.getRegSetAt(i); - MaxRegUnitWeight = std::max(MaxRegUnitWeight, RegUnits.Weight); - OS << " \"" << RegUnits.Name << "\",\n"; - } - OS << " };\n" - << " return PressureNameTable[Idx];\n" - << "}\n\n"; - - OS << "// Get the register unit pressure limit for this dimension.\n" - << "// This limit must be adjusted dynamically for reserved registers.\n" - << "unsigned " << ClassName << "::\n" - << "getRegPressureSetLimit(const MachineFunction &MF, unsigned Idx) const " - "{\n" - << " static const " << getMinimalTypeForRange(MaxRegUnitWeight, 32) - << " PressureLimitTable[] = {\n"; - for (unsigned i = 0; i < NumSets; ++i ) { - const RegUnitSet &RegUnits = RegBank.getRegSetAt(i); - OS << " " << RegUnits.Weight << ", \t// " << i << ": " - << RegUnits.Name << "\n"; - } - OS << " };\n" - << " return PressureLimitTable[Idx];\n" - << "}\n\n"; + PI.regInfoEmitRegUnitWeight(RegBank, ClassName, RegUnitsHaveUnitWeight); + PI.regInfoEmitGetNumRegPressureSets(ClassName, NumSets); + PI.regInfoEmitGetRegPressureTables(RegBank, ClassName, NumSets); - SequenceToOffsetTable> PSetsSeqs; + SequenceToOffsetTable> PSetsSeqs(PI.getLanguage()); // This table may be larger than NumRCs if some register units needed a list // of unit sets that did not correspond to a register class. @@ -313,48 +106,11 @@ } PSetsSeqs.layout(); - - OS << "/// Table of pressure sets per register class or unit.\n" - << "static const int RCSetsTable[] = {\n"; - PSetsSeqs.emit(OS, printInt, "-1"); - OS << "};\n\n"; - - OS << "/// Get the dimensions of register pressure impacted by this " - << "register class.\n" - << "/// Returns a -1 terminated array of pressure set IDs\n" - << "const int *" << ClassName << "::\n" - << "getRegClassPressureSets(const TargetRegisterClass *RC) const {\n"; - OS << " static const " << getMinimalTypeForRange(PSetsSeqs.size() - 1, 32) - << " RCSetStartTable[] = {\n "; - for (unsigned i = 0, e = NumRCs; i != e; ++i) { - OS << PSetsSeqs.get(PSets[i]) << ","; - } - OS << "};\n" - << " return &RCSetsTable[RCSetStartTable[RC->getID()]];\n" - << "}\n\n"; - - OS << "/// Get the dimensions of register pressure impacted by this " - << "register unit.\n" - << "/// Returns a -1 terminated array of pressure set IDs\n" - << "const int *" << ClassName << "::\n" - << "getRegUnitPressureSets(unsigned RegUnit) const {\n" - << " assert(RegUnit < " << RegBank.getNumNativeRegUnits() - << " && \"invalid register unit\");\n"; - OS << " static const " << getMinimalTypeForRange(PSetsSeqs.size() - 1, 32) - << " RUSetStartTable[] = {\n "; - for (unsigned UnitIdx = 0, UnitEnd = RegBank.getNumNativeRegUnits(); - UnitIdx < UnitEnd; ++UnitIdx) { - OS << PSetsSeqs.get(PSets[RegBank.getRegUnit(UnitIdx).RegClassUnitSetsIdx]) - << ","; - } - OS << "};\n" - << " return &RCSetsTable[RUSetStartTable[RegUnit]];\n" - << "}\n\n"; + PI.regInfoEmitRCSetsTable(ClassName, NumRCs, PSetsSeqs, PSets); + PI.regInfoEmitGetRegUnitPressureSets(PSetsSeqs, RegBank, + ClassName, PSets); } -using DwarfRegNumsMapPair = std::pair>; -using DwarfRegNumsVecTy = std::vector; - static void finalizeDwarfRegNumsKeys(DwarfRegNumsVecTy &DwarfRegNums) { // Sort and unique to get a map-like vector. We want the last assignment to // match previous behaviour. @@ -380,7 +136,7 @@ } void RegisterInfoEmitter::EmitRegMappingTables( - raw_ostream &OS, const std::deque &Regs, bool isCtor) { + const std::deque &Regs, bool isCtor) { // Collect all information about dwarf register numbers DwarfRegNumsVecTy DwarfRegNums; @@ -403,49 +159,7 @@ DwarfRegNum.second.push_back(-1); StringRef Namespace = Regs.front().TheDef->getValueAsString("Namespace"); - - OS << "// " << Namespace << " Dwarf<->LLVM register mappings.\n"; - - // Emit reverse information about the dwarf register numbers. - for (unsigned j = 0; j < 2; ++j) { - for (unsigned I = 0, E = maxLength; I != E; ++I) { - OS << "extern const MCRegisterInfo::DwarfLLVMRegPair " << Namespace; - OS << (j == 0 ? "DwarfFlavour" : "EHFlavour"); - OS << I << "Dwarf2L[]"; - - if (!isCtor) { - OS << " = {\n"; - - // Store the mapping sorted by the LLVM reg num so lookup can be done - // with a binary search. - std::map Dwarf2LMap; - for (auto &DwarfRegNum : DwarfRegNums) { - int DwarfRegNo = DwarfRegNum.second[I]; - if (DwarfRegNo < 0) - continue; - Dwarf2LMap[DwarfRegNo] = DwarfRegNum.first; - } - - for (auto &I : Dwarf2LMap) - OS << " { " << I.first << "U, " << getQualifiedName(I.second) - << " },\n"; - - OS << "};\n"; - } else { - OS << ";\n"; - } - - // We have to store the size in a const global, it's used in multiple - // places. - OS << "extern const unsigned " << Namespace - << (j == 0 ? "DwarfFlavour" : "EHFlavour") << I << "Dwarf2LSize"; - if (!isCtor) - OS << " = std::size(" << Namespace - << (j == 0 ? "DwarfFlavour" : "EHFlavour") << I << "Dwarf2L);\n\n"; - else - OS << ";\n\n"; - } - } + PI.regInfoEmitInfoDwarfRegsRev(Namespace, DwarfRegNums, maxLength, isCtor); for (auto &RE : Regs) { Record *Reg = RE.TheDef; @@ -471,43 +185,11 @@ } // Emit information about the dwarf register numbers. - for (unsigned j = 0; j < 2; ++j) { - for (unsigned i = 0, e = maxLength; i != e; ++i) { - OS << "extern const MCRegisterInfo::DwarfLLVMRegPair " << Namespace; - OS << (j == 0 ? "DwarfFlavour" : "EHFlavour"); - OS << i << "L2Dwarf[]"; - if (!isCtor) { - OS << " = {\n"; - // Store the mapping sorted by the Dwarf reg num so lookup can be done - // with a binary search. - for (auto &DwarfRegNum : DwarfRegNums) { - int RegNo = DwarfRegNum.second[i]; - if (RegNo == -1) // -1 is the default value, don't emit a mapping. - continue; - - OS << " { " << getQualifiedName(DwarfRegNum.first) << ", " << RegNo - << "U },\n"; - } - OS << "};\n"; - } else { - OS << ";\n"; - } - - // We have to store the size in a const global, it's used in multiple - // places. - OS << "extern const unsigned " << Namespace - << (j == 0 ? "DwarfFlavour" : "EHFlavour") << i << "L2DwarfSize"; - if (!isCtor) - OS << " = std::size(" << Namespace - << (j == 0 ? "DwarfFlavour" : "EHFlavour") << i << "L2Dwarf);\n\n"; - else - OS << ";\n\n"; - } - } + PI.regInfoEmitInfoDwarfRegs(Namespace, DwarfRegNums, maxLength, isCtor); } void RegisterInfoEmitter::EmitRegMapping( - raw_ostream &OS, const std::deque &Regs, bool isCtor) { + const std::deque &Regs, bool isCtor) { // Emit the initializer so the tables from EmitRegMappingTables get wired up // to the MCRegisterInfo object. unsigned maxLength = 0; @@ -517,125 +199,10 @@ Reg->getValueAsListOfInts("DwarfNumbers").size()); } - if (!maxLength) - return; - StringRef Namespace = Regs.front().TheDef->getValueAsString("Namespace"); - - // Emit reverse information about the dwarf register numbers. - for (unsigned j = 0; j < 2; ++j) { - OS << " switch ("; - if (j == 0) - OS << "DwarfFlavour"; - else - OS << "EHFlavour"; - OS << ") {\n" - << " default:\n" - << " llvm_unreachable(\"Unknown DWARF flavour\");\n"; - - for (unsigned i = 0, e = maxLength; i != e; ++i) { - OS << " case " << i << ":\n"; - OS << " "; - if (!isCtor) - OS << "RI->"; - std::string Tmp; - raw_string_ostream(Tmp) << Namespace - << (j == 0 ? "DwarfFlavour" : "EHFlavour") << i - << "Dwarf2L"; - OS << "mapDwarfRegsToLLVMRegs(" << Tmp << ", " << Tmp << "Size, "; - if (j == 0) - OS << "false"; - else - OS << "true"; - OS << ");\n"; - OS << " break;\n"; - } - OS << " }\n"; - } - - // Emit information about the dwarf register numbers. - for (unsigned j = 0; j < 2; ++j) { - OS << " switch ("; - if (j == 0) - OS << "DwarfFlavour"; - else - OS << "EHFlavour"; - OS << ") {\n" - << " default:\n" - << " llvm_unreachable(\"Unknown DWARF flavour\");\n"; - - for (unsigned i = 0, e = maxLength; i != e; ++i) { - OS << " case " << i << ":\n"; - OS << " "; - if (!isCtor) - OS << "RI->"; - std::string Tmp; - raw_string_ostream(Tmp) << Namespace - << (j == 0 ? "DwarfFlavour" : "EHFlavour") << i - << "L2Dwarf"; - OS << "mapLLVMRegsToDwarfRegs(" << Tmp << ", " << Tmp << "Size, "; - if (j == 0) - OS << "false"; - else - OS << "true"; - OS << ");\n"; - OS << " break;\n"; - } - OS << " }\n"; - } -} - -// Print a BitVector as a sequence of hex numbers using a little-endian mapping. -// Width is the number of bits per hex number. -static void printBitVectorAsHex(raw_ostream &OS, - const BitVector &Bits, - unsigned Width) { - assert(Width <= 32 && "Width too large"); - unsigned Digits = (Width + 3) / 4; - for (unsigned i = 0, e = Bits.size(); i < e; i += Width) { - unsigned Value = 0; - for (unsigned j = 0; j != Width && i + j != e; ++j) - Value |= Bits.test(i + j) << j; - OS << format("0x%0*x, ", Digits, Value); - } -} - -// Helper to emit a set of bits into a constant byte array. -class BitVectorEmitter { - BitVector Values; -public: - void add(unsigned v) { - if (v >= Values.size()) - Values.resize(((v/8)+1)*8); // Round up to the next byte. - Values[v] = true; - } - - void print(raw_ostream &OS) { - printBitVectorAsHex(OS, Values, 8); - } -}; - -static void printSimpleValueType(raw_ostream &OS, MVT::SimpleValueType VT) { - OS << getEnumName(VT); -} - -static void printSubRegIndex(raw_ostream &OS, const CodeGenSubRegIndex *Idx) { - OS << Idx->EnumValue; + PI.regInfoEmitInfoRegMapping(Namespace, maxLength, isCtor); } -// Differentially encoded register and regunit lists allow for better -// compression on regular register banks. The sequence is computed from the -// differential list as: -// -// out[0] = InitVal; -// out[n+1] = out[n] + diff[n]; // n = 0, 1, ... -// -// The initial value depends on the specific list. The list is terminated by a -// 0 differential which means we can't encode repeated elements. - -typedef SmallVector DiffVec; -typedef SmallVector MaskVec; - // Differentially encode a sequence of numbers into V. The starting value and // terminating 0 are not added to V, so it will have the same size as List. static @@ -663,14 +230,6 @@ return V; } -static void printDiff16(raw_ostream &OS, uint16_t Val) { - OS << Val; -} - -static void printMask(raw_ostream &OS, LaneBitmask Val) { - OS << "LaneBitmask(0x" << PrintLaneMask(Val) << ')'; -} - // Try to combine Idx's compose map into Vec if it is compatible. // Return false if it's not possible. static bool combine(const CodeGenSubRegIndex *Idx, @@ -693,13 +252,10 @@ } void -RegisterInfoEmitter::emitComposeSubRegIndices(raw_ostream &OS, - CodeGenRegBank &RegBank, +RegisterInfoEmitter::emitComposeSubRegIndices(CodeGenRegBank &RegBank, const std::string &ClName) { const auto &SubRegIndices = RegBank.getSubRegIndices(); - OS << "unsigned " << ClName - << "::composeSubRegIndicesImpl(unsigned IdxA, unsigned IdxB) const {\n"; - + PI.regInfoEmitComposeSubRegIndicesImplHead(ClName); // Many sub-register indexes are composition-compatible, meaning that // // compose(IdxA, IdxB) == compose(IdxA', IdxB) @@ -731,40 +287,11 @@ } // Output the row map if there is multiple rows. - if (Rows.size() > 1) { - OS << " static const " << getMinimalTypeForRange(Rows.size(), 32) - << " RowMap[" << SubRegIndicesSize << "] = {\n "; - for (unsigned i = 0, e = SubRegIndicesSize; i != e; ++i) - OS << RowMap[i] << ", "; - OS << "\n };\n"; - } - - // Output the rows. - OS << " static const " << getMinimalTypeForRange(SubRegIndicesSize + 1, 32) - << " Rows[" << Rows.size() << "][" << SubRegIndicesSize << "] = {\n"; - for (unsigned r = 0, re = Rows.size(); r != re; ++r) { - OS << " { "; - for (unsigned i = 0, e = SubRegIndicesSize; i != e; ++i) - if (Rows[r][i]) - OS << Rows[r][i]->getQualifiedName() << ", "; - else - OS << "0, "; - OS << "},\n"; - } - OS << " };\n\n"; - - OS << " --IdxA; assert(IdxA < " << SubRegIndicesSize << "); (void) IdxA;\n" - << " --IdxB; assert(IdxB < " << SubRegIndicesSize << ");\n"; - if (Rows.size() > 1) - OS << " return Rows[RowMap[IdxA]][IdxB];\n"; - else - OS << " return Rows[0][IdxB];\n"; - OS << "}\n\n"; + PI.regInfoEmitComposeSubRegIndicesImplBody(Rows, SubRegIndicesSize, RowMap); } void -RegisterInfoEmitter::emitComposeSubRegIndexLaneMask(raw_ostream &OS, - CodeGenRegBank &RegBank, +RegisterInfoEmitter::emitComposeSubRegIndexLaneMask(CodeGenRegBank &RegBank, const std::string &ClName) { // See the comments in computeSubRegLaneMasks() for our goal here. const auto &SubRegIndices = RegBank.getSubRegIndices(); @@ -794,114 +321,39 @@ SubReg2SequenceIndexMap.push_back(Found); } - OS << " struct MaskRolOp {\n" - " LaneBitmask Mask;\n" - " uint8_t RotateLeft;\n" - " };\n" - " static const MaskRolOp LaneMaskComposeSequences[] = {\n"; - unsigned Idx = 0; - for (size_t s = 0, se = Sequences.size(); s != se; ++s) { - OS << " "; - const SmallVectorImpl &Sequence = Sequences[s]; - for (size_t p = 0, pe = Sequence.size(); p != pe; ++p) { - const MaskRolPair &P = Sequence[p]; - printMask(OS << "{ ", P.Mask); - OS << format(", %2u }, ", P.RotateLeft); - } - OS << "{ LaneBitmask::getNone(), 0 }"; - if (s+1 != se) - OS << ", "; - OS << " // Sequence " << Idx << "\n"; - Idx += Sequence.size() + 1; - } - auto *IntType = getMinimalTypeForRange(*std::max_element( - SubReg2SequenceIndexMap.begin(), SubReg2SequenceIndexMap.end())); - OS << " };\n" - " static const " - << IntType << " CompositeSequences[] = {\n"; - for (size_t i = 0, e = SubRegIndices.size(); i != e; ++i) { - OS << " "; - OS << SubReg2SequenceIndexMap[i]; - if (i+1 != e) - OS << ","; - OS << " // to " << SubRegIndices[i].getName() << "\n"; - } - OS << " };\n\n"; - - OS << "LaneBitmask " << ClName - << "::composeSubRegIndexLaneMaskImpl(unsigned IdxA, LaneBitmask LaneMask)" - " const {\n" - " --IdxA; assert(IdxA < " << SubRegIndices.size() - << " && \"Subregister index out of bounds\");\n" - " LaneBitmask Result;\n" - " for (const MaskRolOp *Ops =\n" - " &LaneMaskComposeSequences[CompositeSequences[IdxA]];\n" - " Ops->Mask.any(); ++Ops) {\n" - " LaneBitmask::Type M = LaneMask.getAsInteger() & Ops->Mask.getAsInteger();\n" - " if (unsigned S = Ops->RotateLeft)\n" - " Result |= LaneBitmask((M << S) | (M >> (LaneBitmask::BitWidth - S)));\n" - " else\n" - " Result |= LaneBitmask(M);\n" - " }\n" - " return Result;\n" - "}\n\n"; - - OS << "LaneBitmask " << ClName - << "::reverseComposeSubRegIndexLaneMaskImpl(unsigned IdxA, " - " LaneBitmask LaneMask) const {\n" - " LaneMask &= getSubRegIndexLaneMask(IdxA);\n" - " --IdxA; assert(IdxA < " << SubRegIndices.size() - << " && \"Subregister index out of bounds\");\n" - " LaneBitmask Result;\n" - " for (const MaskRolOp *Ops =\n" - " &LaneMaskComposeSequences[CompositeSequences[IdxA]];\n" - " Ops->Mask.any(); ++Ops) {\n" - " LaneBitmask::Type M = LaneMask.getAsInteger();\n" - " if (unsigned S = Ops->RotateLeft)\n" - " Result |= LaneBitmask((M >> S) | (M << (LaneBitmask::BitWidth - S)));\n" - " else\n" - " Result |= LaneBitmask(M);\n" - " }\n" - " return Result;\n" - "}\n\n"; + PI.regInfoEmitLaneMaskComposeSeq(Sequences, SubReg2SequenceIndexMap, SubRegIndices); + PI.regInfoEmitComposeSubRegIdxLaneMask(ClName, SubRegIndices); + PI.regInfoEmitComposeSubRegIdxLaneMaskRev(ClName, SubRegIndices); + } // // runMCDesc - Print out MC register descriptions. // void -RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target, +RegisterInfoEmitter::runMCDesc(CodeGenTarget &Target, CodeGenRegBank &RegBank) { - emitSourceFileHeader("MC Register Information", OS); - - OS << "\n#ifdef GET_REGINFO_MC_DESC\n"; - OS << "#undef GET_REGINFO_MC_DESC\n\n"; + PI.regInfoEmitSourceFileHeader("MC Register Information"); const auto &Regs = RegBank.getRegisters(); auto &SubRegIndices = RegBank.getSubRegIndices(); - // The lists of sub-registers and super-registers go in the same array. That - // allows us to share suffixes. - typedef std::vector RegVec; // Differentially encoded lists. - SequenceToOffsetTable DiffSeqs; + SequenceToOffsetTable DiffSeqs(PI.getLanguage()); SmallVector SubRegLists(Regs.size()); SmallVector SuperRegLists(Regs.size()); SmallVector RegUnitLists(Regs.size()); SmallVector RegUnitInitScale(Regs.size()); // List of lane masks accompanying register unit sequences. - SequenceToOffsetTable LaneMaskSeqs; + SequenceToOffsetTable LaneMaskSeqs(PI.getLanguage()); SmallVector RegUnitLaneMasks(Regs.size()); - // Keep track of sub-register names as well. These are not differentially - // encoded. - typedef SmallVector SubRegIdxVec; - SequenceToOffsetTable>> SubRegIdxSeqs; + SequenceToOffsetTable>> SubRegIdxSeqs(PI.getLanguage()); SmallVector SubRegIdxLists(Regs.size()); - SequenceToOffsetTable RegStrings; + SequenceToOffsetTable RegStrings(PI.getLanguage()); // Precompute register lists for the SequenceToOffsetTable. unsigned i = 0; @@ -971,271 +423,106 @@ LaneMaskSeqs.layout(); SubRegIdxSeqs.layout(); - OS << "namespace llvm {\n\n"; + PI.emitIncludeToggle("GET_REGINFO_MC_DESC", true); + PI.emitNamespace("llvm", true); const std::string &TargetName = std::string(Target.getName()); // Emit the shared table of differential lists. - OS << "extern const MCPhysReg " << TargetName << "RegDiffLists[] = {\n"; - DiffSeqs.emit(OS, printDiff16); - OS << "};\n\n"; + PI.regInfoEmitRegDiffLists(TargetName, DiffSeqs); // Emit the shared table of regunit lane mask sequences. - OS << "extern const LaneBitmask " << TargetName << "LaneMaskLists[] = {\n"; - LaneMaskSeqs.emit(OS, printMask, "LaneBitmask::getAll()"); - OS << "};\n\n"; + PI.regInfoEmitLaneMaskLists(TargetName, LaneMaskSeqs); // Emit the table of sub-register indexes. - OS << "extern const uint16_t " << TargetName << "SubRegIdxLists[] = {\n"; - SubRegIdxSeqs.emit(OS, printSubRegIndex); - OS << "};\n\n"; + PI.regInfoEmitSubRegIdxLists(TargetName, SubRegIdxSeqs); // Emit the table of sub-register index sizes. - OS << "extern const MCRegisterInfo::SubRegCoveredBits " - << TargetName << "SubRegIdxRanges[] = {\n"; - OS << " { " << (uint16_t)-1 << ", " << (uint16_t)-1 << " },\n"; - for (const auto &Idx : SubRegIndices) { - OS << " { " << Idx.Offset << ", " << Idx.Size << " },\t// " - << Idx.getName() << "\n"; - } - OS << "};\n\n"; + PI.regInfoEmitSubRegIdxSizes(TargetName, SubRegIndices); // Emit the string table. RegStrings.layout(); - RegStrings.emitStringLiteralDef(OS, Twine("extern const char ") + TargetName + - "RegStrings[]"); - - OS << "extern const MCRegisterDesc " << TargetName - << "RegDesc[] = { // Descriptors\n"; - OS << " { " << RegStrings.get("") << ", 0, 0, 0, 0, 0 },\n"; + PI.regInfoEmitSubRegStrTable(TargetName, RegStrings); // Emit the register descriptors now. - i = 0; - for (const auto &Reg : Regs) { - OS << " { " << RegStrings.get(std::string(Reg.getName())) << ", " - << DiffSeqs.get(SubRegLists[i]) << ", " << DiffSeqs.get(SuperRegLists[i]) - << ", " << SubRegIdxSeqs.get(SubRegIdxLists[i]) << ", " - << (DiffSeqs.get(RegUnitLists[i]) * 16 + RegUnitInitScale[i]) << ", " - << LaneMaskSeqs.get(RegUnitLaneMasks[i]) << " },\n"; - ++i; - } - OS << "};\n\n"; // End of register descriptors... + PI.regInfoEmitRegDesc(LaneMaskSeqs, + Regs, SubRegIdxSeqs, DiffSeqs, + SubRegIdxLists, SubRegLists, + SuperRegLists, RegUnitLists, + RegUnitInitScale, RegUnitLaneMasks, + RegStrings); // Emit the table of register unit roots. Each regunit has one or two root // registers. - OS << "extern const MCPhysReg " << TargetName << "RegUnitRoots[][2] = {\n"; - for (unsigned i = 0, e = RegBank.getNumNativeRegUnits(); i != e; ++i) { - ArrayRef Roots = RegBank.getRegUnit(i).getRoots(); - assert(!Roots.empty() && "All regunits must have a root register."); - assert(Roots.size() <= 2 && "More than two roots not supported yet."); - OS << " { "; - ListSeparator LS; - for (const CodeGenRegister *R : Roots) - OS << LS << getQualifiedName(R->TheDef); - OS << " },\n"; - } - OS << "};\n\n"; + PI.regInfoEmitRegUnitRoots(TargetName, RegBank); const auto &RegisterClasses = RegBank.getRegClasses(); // Loop over all of the register classes... emitting each one. - OS << "namespace { // Register classes...\n"; + PI.emitNamespace("", true, "Register classes..."); - SequenceToOffsetTable RegClassStrings; + SequenceToOffsetTable RegClassStrings(PI.getLanguage()); // Emit the register enum value arrays for each RegisterClass - for (const auto &RC : RegisterClasses) { - ArrayRef Order = RC.getOrder(); - - // Give the register class a legal C name if it's anonymous. - const std::string &Name = RC.getName(); - - RegClassStrings.add(Name); - - // Emit the register list now (unless it would be a zero-length array). - if (!Order.empty()) { - OS << " // " << Name << " Register Class...\n" - << " const MCPhysReg " << Name << "[] = {\n "; - for (Record *Reg : Order) { - OS << getQualifiedName(Reg) << ", "; - } - OS << "\n };\n\n"; - - OS << " // " << Name << " Bit set.\n" - << " const uint8_t " << Name << "Bits[] = {\n "; - BitVectorEmitter BVE; - for (Record *Reg : Order) { - BVE.add(Target.getRegBank().getReg(Reg)->EnumValue); - } - BVE.print(OS); - OS << "\n };\n\n"; - } - } - OS << "} // end anonymous namespace\n\n"; + PI.regInfoEmitRegClasses(RegisterClasses, RegClassStrings, Target); + PI.emitNamespace("", false); RegClassStrings.layout(); - RegClassStrings.emitStringLiteralDef( - OS, Twine("extern const char ") + TargetName + "RegClassStrings[]"); + PI.regInfoEmitStrLiteralRegClasses(TargetName, RegClassStrings); - OS << "extern const MCRegisterClass " << TargetName - << "MCRegisterClasses[] = {\n"; + PI.regInfoEmitMCRegClassesTable(TargetName, RegisterClasses, RegClassStrings); - for (const auto &RC : RegisterClasses) { - ArrayRef Order = RC.getOrder(); - std::string RCName = Order.empty() ? "nullptr" : RC.getName(); - std::string RCBitsName = Order.empty() ? "nullptr" : RC.getName() + "Bits"; - std::string RCBitsSize = Order.empty() ? "0" : "sizeof(" + RCBitsName + ")"; - assert(isInt<8>(RC.CopyCost) && "Copy cost too large."); - uint32_t RegSize = 0; - if (RC.RSI.isSimple()) - RegSize = RC.RSI.getSimple().RegSize; - OS << " { " << RCName << ", " << RCBitsName << ", " - << RegClassStrings.get(RC.getName()) << ", " << RC.getOrder().size() - << ", " << RCBitsSize << ", " << RC.getQualifiedName() + "RegClassID" - << ", " << RegSize << ", " << RC.CopyCost << ", " - << (RC.Allocatable ? "true" : "false") << " },\n"; - } - - OS << "};\n\n"; - - EmitRegMappingTables(OS, Regs, false); + EmitRegMappingTables(Regs, false); // Emit Reg encoding table - OS << "extern const uint16_t " << TargetName; - OS << "RegEncodingTable[] = {\n"; - // Add entry for NoRegister - OS << " 0,\n"; - for (const auto &RE : Regs) { - Record *Reg = RE.TheDef; - BitsInit *BI = Reg->getValueAsBitsInit("HWEncoding"); - uint64_t Value = 0; - for (unsigned b = 0, be = BI->getNumBits(); b != be; ++b) { - if (BitInit *B = dyn_cast(BI->getBit(b))) - Value |= (uint64_t)B->getValue() << b; - } - OS << " " << Value << ",\n"; - } - OS << "};\n"; // End of HW encoding table + PI.regInfoEmitRegEncodingTable(TargetName, Regs); // MCRegisterInfo initialization routine. - OS << "static inline void Init" << TargetName - << "MCRegisterInfo(MCRegisterInfo *RI, unsigned RA, " - << "unsigned DwarfFlavour = 0, unsigned EHFlavour = 0, unsigned PC = 0) " - "{\n" - << " RI->InitMCRegisterInfo(" << TargetName << "RegDesc, " - << Regs.size() + 1 << ", RA, PC, " << TargetName << "MCRegisterClasses, " - << RegisterClasses.size() << ", " << TargetName << "RegUnitRoots, " - << RegBank.getNumNativeRegUnits() << ", " << TargetName << "RegDiffLists, " - << TargetName << "LaneMaskLists, " << TargetName << "RegStrings, " - << TargetName << "RegClassStrings, " << TargetName << "SubRegIdxLists, " - << (std::distance(SubRegIndices.begin(), SubRegIndices.end()) + 1) << ",\n" - << TargetName << "SubRegIdxRanges, " << TargetName - << "RegEncodingTable);\n\n"; - - EmitRegMapping(OS, Regs, false); - - OS << "}\n\n"; - - OS << "} // end namespace llvm\n\n"; - OS << "#endif // GET_REGINFO_MC_DESC\n\n"; + PI.regInfoEmitMCRegInfoInit(TargetName, RegBank, Regs, RegisterClasses, SubRegIndices); + + EmitRegMapping(Regs, false); + + PI.emitNamespace("llvm", false); + PI.emitIncludeToggle("GET_REGINFO_MC_DESC", false); } void -RegisterInfoEmitter::runTargetHeader(raw_ostream &OS, CodeGenTarget &Target, +RegisterInfoEmitter::runTargetHeader(CodeGenTarget &Target, CodeGenRegBank &RegBank) { - emitSourceFileHeader("Register Information Header Fragment", OS); - - OS << "\n#ifdef GET_REGINFO_HEADER\n"; - OS << "#undef GET_REGINFO_HEADER\n\n"; + PI.regInfoEmitSourceFileHeader("Register Information Header Fragment"); + PI.emitIncludeToggle("GET_REGINFO_HEADER", true); const std::string &TargetName = std::string(Target.getName()); std::string ClassName = TargetName + "GenRegisterInfo"; + PI.regInfoEmitHeaderIncludes(); - OS << "#include \"llvm/CodeGen/TargetRegisterInfo.h\"\n\n"; - - OS << "namespace llvm {\n\n"; - - OS << "class " << TargetName << "FrameLowering;\n\n"; - - OS << "struct " << ClassName << " : public TargetRegisterInfo {\n" - << " explicit " << ClassName - << "(unsigned RA, unsigned D = 0, unsigned E = 0,\n" - << " unsigned PC = 0, unsigned HwMode = 0);\n"; - if (!RegBank.getSubRegIndices().empty()) { - OS << " unsigned composeSubRegIndicesImpl" - << "(unsigned, unsigned) const override;\n" - << " LaneBitmask composeSubRegIndexLaneMaskImpl" - << "(unsigned, LaneBitmask) const override;\n" - << " LaneBitmask reverseComposeSubRegIndexLaneMaskImpl" - << "(unsigned, LaneBitmask) const override;\n" - << " const TargetRegisterClass *getSubClassWithSubReg" - << "(const TargetRegisterClass *, unsigned) const override;\n" - << " const TargetRegisterClass *getSubRegisterClass" - << "(const TargetRegisterClass *, unsigned) const override;\n"; - } - OS << " const RegClassWeight &getRegClassWeight(" - << "const TargetRegisterClass *RC) const override;\n" - << " unsigned getRegUnitWeight(unsigned RegUnit) const override;\n" - << " unsigned getNumRegPressureSets() const override;\n" - << " const char *getRegPressureSetName(unsigned Idx) const override;\n" - << " unsigned getRegPressureSetLimit(const MachineFunction &MF, unsigned " - "Idx) const override;\n" - << " const int *getRegClassPressureSets(" - << "const TargetRegisterClass *RC) const override;\n" - << " const int *getRegUnitPressureSets(" - << "unsigned RegUnit) const override;\n" - << " ArrayRef getRegMaskNames() const override;\n" - << " ArrayRef getRegMasks() const override;\n" - << " bool isGeneralPurposeRegister(const MachineFunction &, " - << "MCRegister) const override;\n" - << " bool isFixedRegister(const MachineFunction &, " - << "MCRegister) const override;\n" - << " bool isArgumentRegister(const MachineFunction &, " - << "MCRegister) const override;\n" - << " bool isConstantPhysReg(MCRegister PhysReg) const override final;\n" - << " /// Devirtualized TargetFrameLowering.\n" - << " static const " << TargetName << "FrameLowering *getFrameLowering(\n" - << " const MachineFunction &MF);\n"; - + PI.emitNamespace("llvm", true); const auto &RegisterClasses = RegBank.getRegClasses(); - if (llvm::any_of(RegisterClasses, [](const auto &RC) { return RC.getBaseClassOrder(); })) { - OS << " const TargetRegisterClass *getPhysRegBaseClass(MCRegister Reg) const override;\n"; - } - - OS << "};\n\n"; + PI.regInfoEmitHeaderDecl(TargetName, ClassName, !RegBank.getSubRegIndices().empty(), + llvm::any_of(RegisterClasses, [](const auto &RC) { return RC.getBaseClassOrder(); })); if (!RegisterClasses.empty()) { - OS << "namespace " << RegisterClasses.front().Namespace - << " { // Register classes\n"; - - for (const auto &RC : RegisterClasses) { - const std::string &Name = RC.getName(); - - // Output the extern for the instance. - OS << " extern const TargetRegisterClass " << Name << "RegClass;\n"; - } - OS << "} // end namespace " << RegisterClasses.front().Namespace << "\n\n"; + PI.emitNamespace(RegisterClasses.front().Namespace.str(), true, "Register classes"); + PI.regInfoEmitHeaderExternRegClasses(RegisterClasses); + PI.emitNamespace(RegisterClasses.front().Namespace.str(), false); } - OS << "} // end namespace llvm\n\n"; - OS << "#endif // GET_REGINFO_HEADER\n\n"; + PI.emitNamespace("llvm", false); + PI.emitIncludeToggle("GET_REGINFO_HEADER", false); } // // runTargetDesc - Output the target register and register file descriptions. // void -RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, +RegisterInfoEmitter::runTargetDesc(CodeGenTarget &Target, CodeGenRegBank &RegBank){ - emitSourceFileHeader("Target Register and Register Classes Information", OS); - - OS << "\n#ifdef GET_REGINFO_TARGET_DESC\n"; - OS << "#undef GET_REGINFO_TARGET_DESC\n\n"; + PI.regInfoEmitSourceFileHeader("Target Register and Register Classes Information"); - OS << "namespace llvm {\n\n"; + PI.emitIncludeToggle("GET_REGINFO_TARGET_DESC", true); + PI.emitNamespace("llvm", true); // Get access to MCRegisterClass data. - OS << "extern const MCRegisterClass " << Target.getName() - << "MCRegisterClasses[];\n"; + PI.regInfoEmitExternRegClassesArr(Target.getName().str()); // Start out by emitting each of the register classes. const auto &RegisterClasses = RegBank.getRegClasses(); @@ -1256,7 +543,7 @@ unsigned NumModes = CGH.getNumModeIds(); // Build a shared array of value types. - SequenceToOffsetTable> VTSeqs; + SequenceToOffsetTable> VTSeqs(PI.getLanguage()); for (unsigned M = 0; M < NumModes; ++M) { for (const auto &RC : RegisterClasses) { std::vector S; @@ -1266,61 +553,14 @@ } } VTSeqs.layout(); - OS << "\nstatic const MVT::SimpleValueType VTLists[] = {\n"; - VTSeqs.emit(OS, printSimpleValueType, "MVT::Other"); - OS << "};\n"; + PI.regInfoEmitVTSeqs(VTSeqs); // Emit SubRegIndex names, skipping 0. - OS << "\nstatic const char *SubRegIndexNameTable[] = { \""; - - for (const auto &Idx : SubRegIndices) { - OS << Idx.getName(); - OS << "\", \""; - } - OS << "\" };\n\n"; - - // Emit SubRegIndex lane masks, including 0. - OS << "\nstatic const LaneBitmask SubRegIndexLaneMaskTable[] = {\n " - "LaneBitmask::getAll(),\n"; - for (const auto &Idx : SubRegIndices) { - printMask(OS << " ", Idx.LaneMask); - OS << ", // " << Idx.getName() << '\n'; - } - OS << " };\n\n"; - - OS << "\n"; + PI.regInfoEmitSubRegIdxTable(SubRegIndices); // Now that all of the structs have been emitted, emit the instances. if (!RegisterClasses.empty()) { - OS << "\nstatic const TargetRegisterInfo::RegClassInfo RegClassInfos[]" - << " = {\n"; - for (unsigned M = 0; M < NumModes; ++M) { - unsigned EV = 0; - OS << " // Mode = " << M << " ("; - if (M == 0) - OS << "Default"; - else - OS << CGH.getMode(M).Name; - OS << ")\n"; - for (const auto &RC : RegisterClasses) { - assert(RC.EnumValue == EV && "Unexpected order of register classes"); - ++EV; - (void)EV; - const RegSizeInfo &RI = RC.RSI.get(M); - OS << " { " << RI.RegSize << ", " << RI.SpillSize << ", " - << RI.SpillAlignment; - std::vector VTs; - for (const ValueTypeByHwMode &VVT : RC.VTs) - VTs.push_back(VVT.get(M).SimpleTy); - OS << ", VTLists+" << VTSeqs.get(VTs) << " }, // " - << RC.getName() << '\n'; - } - } - OS << "};\n"; - - - OS << "\nstatic const TargetRegisterClass *const " - << "NullRegClasses[] = { nullptr };\n\n"; + PI.regInfoEmitRegClassInfoTable(RegisterClasses, VTSeqs, CGH, NumModes); // Emit register class bit mask tables. The first bit mask emitted for a // register class, RC, is the set of sub-classes, including RC itself. @@ -1340,124 +580,37 @@ // // Every bit mask present in the list has at least one bit set. - // Compress the sub-reg index lists. - typedef std::vector IdxList; SmallVector SuperRegIdxLists(RegisterClasses.size()); - SequenceToOffsetTable>> SuperRegIdxSeqs; + SequenceToOffsetTable>> SuperRegIdxSeqs(PI.getLanguage()); BitVector MaskBV(RegisterClasses.size()); - for (const auto &RC : RegisterClasses) { - OS << "static const uint32_t " << RC.getName() - << "SubClassMask[] = {\n "; - printBitVectorAsHex(OS, RC.getSubClasses(), 32); - - // Emit super-reg class masks for any relevant SubRegIndices that can - // project into RC. - IdxList &SRIList = SuperRegIdxLists[RC.EnumValue]; - for (auto &Idx : SubRegIndices) { - MaskBV.reset(); - RC.getSuperRegClasses(&Idx, MaskBV); - if (MaskBV.none()) - continue; - SRIList.push_back(&Idx); - OS << "\n "; - printBitVectorAsHex(OS, MaskBV, 32); - OS << "// " << Idx.getName(); - } - SuperRegIdxSeqs.add(SRIList); - OS << "\n};\n\n"; - } + PI.regInfoEmitSubClassMaskTable(RegisterClasses, + SuperRegIdxLists, + SuperRegIdxSeqs, + SubRegIndices, + MaskBV); - OS << "static const uint16_t SuperRegIdxSeqs[] = {\n"; SuperRegIdxSeqs.layout(); - SuperRegIdxSeqs.emit(OS, printSubRegIndex); - OS << "};\n\n"; + PI.regInfoEmitSuperRegIdxSeqsTable(SuperRegIdxSeqs); // Emit NULL terminated super-class lists. - for (const auto &RC : RegisterClasses) { - ArrayRef Supers = RC.getSuperClasses(); - - // Skip classes without supers. We can reuse NullRegClasses. - if (Supers.empty()) - continue; - - OS << "static const TargetRegisterClass *const " - << RC.getName() << "Superclasses[] = {\n"; - for (const auto *Super : Supers) - OS << " &" << Super->getQualifiedName() << "RegClass,\n"; - OS << " nullptr\n};\n\n"; - } + PI.regInfoEmitSuperClassesTable(RegisterClasses); // Emit methods. - for (const auto &RC : RegisterClasses) { - if (!RC.AltOrderSelect.empty()) { - OS << "\nstatic inline unsigned " << RC.getName() - << "AltOrderSelect(const MachineFunction &MF) {" - << RC.AltOrderSelect << "}\n\n" - << "static ArrayRef " << RC.getName() - << "GetRawAllocationOrder(const MachineFunction &MF) {\n"; - for (unsigned oi = 1 , oe = RC.getNumOrders(); oi != oe; ++oi) { - ArrayRef Elems = RC.getOrder(oi); - if (!Elems.empty()) { - OS << " static const MCPhysReg AltOrder" << oi << "[] = {"; - for (unsigned elem = 0; elem != Elems.size(); ++elem) - OS << (elem ? ", " : " ") << getQualifiedName(Elems[elem]); - OS << " };\n"; - } - } - OS << " const MCRegisterClass &MCR = " << Target.getName() - << "MCRegisterClasses[" << RC.getQualifiedName() + "RegClassID];\n" - << " const ArrayRef Order[] = {\n" - << " makeArrayRef(MCR.begin(), MCR.getNumRegs()"; - for (unsigned oi = 1, oe = RC.getNumOrders(); oi != oe; ++oi) - if (RC.getOrder(oi).empty()) - OS << "),\n ArrayRef("; - else - OS << "),\n makeArrayRef(AltOrder" << oi; - OS << ")\n };\n const unsigned Select = " << RC.getName() - << "AltOrderSelect(MF);\n assert(Select < " << RC.getNumOrders() - << ");\n return Order[Select];\n}\n"; - } - } + PI.regInfoEmitRegClassMethods(RegisterClasses, Target.getName().str()); // Now emit the actual value-initialized register class instances. - OS << "\nnamespace " << RegisterClasses.front().Namespace - << " { // Register class instances\n"; - - for (const auto &RC : RegisterClasses) { - OS << " extern const TargetRegisterClass " << RC.getName() - << "RegClass = {\n " << '&' << Target.getName() - << "MCRegisterClasses[" << RC.getName() << "RegClassID],\n " - << RC.getName() << "SubClassMask,\n SuperRegIdxSeqs + " - << SuperRegIdxSeqs.get(SuperRegIdxLists[RC.EnumValue]) << ",\n "; - printMask(OS, RC.LaneMask); - OS << ",\n " << (unsigned)RC.AllocationPriority << ",\n " - << (RC.GlobalPriority ? "true" : "false") << ",\n " - << format("0x%02x", RC.TSFlags) << ", /* TSFlags */\n " - << (RC.HasDisjunctSubRegs ? "true" : "false") - << ", /* HasDisjunctSubRegs */\n " - << (RC.CoveredBySubRegs ? "true" : "false") - << ", /* CoveredBySubRegs */\n "; - if (RC.getSuperClasses().empty()) - OS << "NullRegClasses,\n "; - else - OS << RC.getName() << "Superclasses,\n "; - if (RC.AltOrderSelect.empty()) - OS << "nullptr\n"; - else - OS << RC.getName() << "GetRawAllocationOrder\n"; - OS << " };\n\n"; - } - - OS << "} // end namespace " << RegisterClasses.front().Namespace << "\n"; + PI.emitNamespace(RegisterClasses.front().Namespace.str(), true, "Register class instances"); + PI.regInfomitRegClassInstances(RegisterClasses, + SuperRegIdxSeqs, + SuperRegIdxLists, + Target.getName().str()); + PI.emitNamespace(RegisterClasses.front().Namespace.str(), false); } - OS << "\nnamespace {\n"; - OS << " const TargetRegisterClass *const RegisterClasses[] = {\n"; - for (const auto &RC : RegisterClasses) - OS << " &" << RC.getQualifiedName() << "RegClass,\n"; - OS << " };\n"; - OS << "} // end anonymous namespace\n"; + PI.emitNamespace("", true); + PI.regInfoEmitRegClassTable(RegisterClasses); + PI.emitNamespace("", false); // Emit extra information about registers. const std::string &TargetName = std::string(Target.getName()); @@ -1487,26 +640,10 @@ // Emit the cost values as a 1D-array after grouping them by their indices, // i.e. the costs for all registers corresponds to index 0, 1, 2, etc. // Size of the emitted array should be NumRegCosts * (Regs.size() + 1). - OS << "\nstatic const uint8_t " - << "CostPerUseTable[] = { \n"; - for (unsigned int I = 0; I < NumRegCosts; ++I) { - for (unsigned J = I, E = AllRegCostPerUse.size(); J < E; J += NumRegCosts) - OS << AllRegCostPerUse[J] << ", "; - } - OS << "};\n\n"; - - OS << "\nstatic const bool " - << "InAllocatableClassTable[] = { \n"; - for (unsigned I = 0, E = InAllocClass.size(); I < E; ++I) { - OS << (InAllocClass[I] ? "true" : "false") << ", "; - } - OS << "};\n\n"; - - OS << "\nstatic const TargetRegisterInfoDesc " << TargetName - << "RegInfoDesc = { // Extra Descriptors\n"; - OS << "CostPerUseTable, " << NumRegCosts << ", " - << "InAllocatableClassTable"; - OS << "};\n\n"; // End of register descriptors... + PI.regInfoEmitCostPerUseTable(AllRegCostPerUse, NumRegCosts); + PI.regInfoEmitInAllocatableClassTable(InAllocClass); + PI.regInfoEmitRegExtraDesc(TargetName, NumRegCosts); + // End of register descriptors... std::string ClassName = Target.getName().str() + "GenRegisterInfo"; @@ -1514,90 +651,19 @@ std::distance(SubRegIndices.begin(), SubRegIndices.end()); if (!SubRegIndices.empty()) { - emitComposeSubRegIndices(OS, RegBank, ClassName); - emitComposeSubRegIndexLaneMask(OS, RegBank, ClassName); + emitComposeSubRegIndices(RegBank, ClassName); + emitComposeSubRegIndexLaneMask(RegBank, ClassName); } if (!SubRegIndices.empty()) { - // Emit getSubClassWithSubReg. - OS << "const TargetRegisterClass *" << ClassName - << "::getSubClassWithSubReg(const TargetRegisterClass *RC, unsigned Idx)" - << " const {\n"; - // Use the smallest type that can hold a regclass ID with room for a - // sentinel. - if (RegisterClasses.size() <= UINT8_MAX) - OS << " static const uint8_t Table["; - else if (RegisterClasses.size() <= UINT16_MAX) - OS << " static const uint16_t Table["; - else - PrintFatalError("Too many register classes."); - OS << RegisterClasses.size() << "][" << SubRegIndicesSize << "] = {\n"; - for (const auto &RC : RegisterClasses) { - OS << " {\t// " << RC.getName() << "\n"; - for (auto &Idx : SubRegIndices) { - if (CodeGenRegisterClass *SRC = RC.getSubClassWithSubReg(&Idx)) - OS << " " << SRC->EnumValue + 1 << ",\t// " << Idx.getName() - << " -> " << SRC->getName() << "\n"; - else - OS << " 0,\t// " << Idx.getName() << "\n"; - } - OS << " },\n"; - } - OS << " };\n assert(RC && \"Missing regclass\");\n" - << " if (!Idx) return RC;\n --Idx;\n" - << " assert(Idx < " << SubRegIndicesSize << " && \"Bad subreg\");\n" - << " unsigned TV = Table[RC->getID()][Idx];\n" - << " return TV ? getRegClass(TV - 1) : nullptr;\n}\n\n"; - - // Emit getSubRegisterClass - OS << "const TargetRegisterClass *" << ClassName - << "::getSubRegisterClass(const TargetRegisterClass *RC, unsigned Idx)" - << " const {\n"; - - // Use the smallest type that can hold a regclass ID with room for a - // sentinel. - if (RegisterClasses.size() <= UINT8_MAX) - OS << " static const uint8_t Table["; - else if (RegisterClasses.size() <= UINT16_MAX) - OS << " static const uint16_t Table["; - else - PrintFatalError("Too many register classes."); - - OS << RegisterClasses.size() << "][" << SubRegIndicesSize << "] = {\n"; - - for (const auto &RC : RegisterClasses) { - OS << " {\t// " << RC.getName() << '\n'; - for (auto &Idx : SubRegIndices) { - std::optional> - MatchingSubClass = RC.getMatchingSubClassWithSubRegs(RegBank, &Idx); - - unsigned EnumValue = 0; - if (MatchingSubClass) { - CodeGenRegisterClass *SubRegClass = MatchingSubClass->second; - EnumValue = SubRegClass->EnumValue + 1; - } - - OS << " " << EnumValue << ",\t// " - << RC.getName() << ':' << Idx.getName(); - - if (MatchingSubClass) { - CodeGenRegisterClass *SubRegClass = MatchingSubClass->second; - OS << " -> " << SubRegClass->getName(); - } - - OS << '\n'; - } - - OS << " },\n"; - } - OS << " };\n assert(RC && \"Missing regclass\");\n" - << " if (!Idx) return RC;\n --Idx;\n" - << " assert(Idx < " << SubRegIndicesSize << " && \"Bad subreg\");\n" - << " unsigned TV = Table[RC->getID()][Idx];\n" - << " return TV ? getRegClass(TV - 1) : nullptr;\n}\n\n"; + PI.regInfoEmitSubClassSubRegGetter(ClassName, + SubRegIndicesSize, + SubRegIndices, + RegisterClasses, + RegBank); } - EmitRegUnitPressure(OS, RegBank, ClassName); + EmitRegUnitPressure(RegBank, ClassName); // Emit register base class mapper if (!RegisterClasses.empty()) { @@ -1627,67 +693,23 @@ Mapping[Reg->EnumValue] = RCIdx + 1; } - OS << "\n// Register to base register class mapping\n\n"; - OS << "\n"; - OS << "const TargetRegisterClass *" << ClassName - << "::getPhysRegBaseClass(MCRegister Reg)" - << " const {\n"; - OS << " static const TargetRegisterClass *BaseClasses[" << (BaseClasses.size() + 1) << "] = {\n"; - OS << " nullptr,\n"; - for (const auto RC : BaseClasses) - OS << " &" << RC->getQualifiedName() << "RegClass,\n"; - OS << " };\n"; - OS << " static const uint8_t Mapping[" << Mapping.size() << "] = {\n "; - for (const uint8_t Value : Mapping) - OS << (unsigned)Value << ","; - OS << " };\n\n"; - OS << " assert(Reg < sizeof(Mapping));\n"; - OS << " return BaseClasses[Mapping[Reg]];\n"; - OS << "}\n"; + PI.regInfoEmitRegBaseClassMapping(ClassName, BaseClasses, Mapping); } } // Emit the constructor of the class... - OS << "extern const MCRegisterDesc " << TargetName << "RegDesc[];\n"; - OS << "extern const MCPhysReg " << TargetName << "RegDiffLists[];\n"; - OS << "extern const LaneBitmask " << TargetName << "LaneMaskLists[];\n"; - OS << "extern const char " << TargetName << "RegStrings[];\n"; - OS << "extern const char " << TargetName << "RegClassStrings[];\n"; - OS << "extern const MCPhysReg " << TargetName << "RegUnitRoots[][2];\n"; - OS << "extern const uint16_t " << TargetName << "SubRegIdxLists[];\n"; - OS << "extern const MCRegisterInfo::SubRegCoveredBits " - << TargetName << "SubRegIdxRanges[];\n"; - OS << "extern const uint16_t " << TargetName << "RegEncodingTable[];\n"; - - EmitRegMappingTables(OS, Regs, true); - - OS << ClassName << "::\n" - << ClassName - << "(unsigned RA, unsigned DwarfFlavour, unsigned EHFlavour,\n" - " unsigned PC, unsigned HwMode)\n" - << " : TargetRegisterInfo(&" << TargetName << "RegInfoDesc" - << ", RegisterClasses, RegisterClasses+" << RegisterClasses.size() << ",\n" - << " SubRegIndexNameTable, SubRegIndexLaneMaskTable,\n" - << " "; - printMask(OS, RegBank.CoveringLanes); - OS << ", RegClassInfos, HwMode) {\n" - << " InitMCRegisterInfo(" << TargetName << "RegDesc, " << Regs.size() + 1 - << ", RA, PC,\n " << TargetName - << "MCRegisterClasses, " << RegisterClasses.size() << ",\n" - << " " << TargetName << "RegUnitRoots,\n" - << " " << RegBank.getNumNativeRegUnits() << ",\n" - << " " << TargetName << "RegDiffLists,\n" - << " " << TargetName << "LaneMaskLists,\n" - << " " << TargetName << "RegStrings,\n" - << " " << TargetName << "RegClassStrings,\n" - << " " << TargetName << "SubRegIdxLists,\n" - << " " << SubRegIndicesSize + 1 << ",\n" - << " " << TargetName << "SubRegIdxRanges,\n" - << " " << TargetName << "RegEncodingTable);\n\n"; - - EmitRegMapping(OS, Regs, true); - - OS << "}\n\n"; + PI.regInfoEmitExternTableDecl(TargetName); + + EmitRegMappingTables(Regs, true); + + PI.regInfoEmitRegClassInit(TargetName, + ClassName, + RegBank, + RegisterClasses, + Regs, + SubRegIndicesSize); + + EmitRegMapping(Regs, true); // Emit CalleeSavedRegs information. std::vector CSRSets = @@ -1698,11 +720,7 @@ assert(Regs && "Cannot expand CalleeSavedRegs instance"); // Emit the *_SaveList list of callee-saved registers. - OS << "static const MCPhysReg " << CSRSet->getName() - << "_SaveList[] = { "; - for (unsigned r = 0, re = Regs->size(); r != re; ++r) - OS << getQualifiedName((*Regs)[r]) << ", "; - OS << "0 };\n"; + PI.regInfoEmitSaveListTable(CSRSet, Regs); // Emit the *_RegMask bit mask of call-preserved registers. BitVector Covered = RegBank.computeCoveredRegisters(*Regs); @@ -1726,121 +744,47 @@ Covered |= RegBank.computeCoveredRegisters( ArrayRef(ConstantSet.begin(), ConstantSet.end())); - OS << "static const uint32_t " << CSRSet->getName() - << "_RegMask[] = { "; - printBitVectorAsHex(OS, Covered, 32); - OS << "};\n"; - } - OS << "\n\n"; - - OS << "ArrayRef " << ClassName - << "::getRegMasks() const {\n"; - if (!CSRSets.empty()) { - OS << " static const uint32_t *const Masks[] = {\n"; - for (Record *CSRSet : CSRSets) - OS << " " << CSRSet->getName() << "_RegMask,\n"; - OS << " };\n"; - OS << " return makeArrayRef(Masks);\n"; - } else { - OS << " return std::nullopt;\n"; + PI.regInfoEmitRegMaskTable(CSRSet->getName().str(), Covered); } - OS << "}\n\n"; + PI.emitNewline(2); + PI.regInfoEmitGetRegMasks(CSRSets, ClassName); const std::list &RegCategories = RegBank.getRegCategories(); - OS << "bool " << ClassName << "::\n" - << "isGeneralPurposeRegister(const MachineFunction &MF, " - << "MCRegister PhysReg) const {\n" - << " return\n"; - for (const CodeGenRegisterCategory &Category : RegCategories) - if (Category.getName() == "GeneralPurposeRegisters") { - for (const CodeGenRegisterClass *RC : Category.getClasses()) - OS << " " << RC->getQualifiedName() - << "RegClass.contains(PhysReg) ||\n"; - break; - } - OS << " false;\n"; - OS << "}\n\n"; - - OS << "bool " << ClassName << "::\n" - << "isFixedRegister(const MachineFunction &MF, " - << "MCRegister PhysReg) const {\n" - << " return\n"; - for (const CodeGenRegisterCategory &Category : RegCategories) - if (Category.getName() == "FixedRegisters") { - for (const CodeGenRegisterClass *RC : Category.getClasses()) - OS << " " << RC->getQualifiedName() - << "RegClass.contains(PhysReg) ||\n"; - break; - } - OS << " false;\n"; - OS << "}\n\n"; - - OS << "bool " << ClassName << "::\n" - << "isArgumentRegister(const MachineFunction &MF, " - << "MCRegister PhysReg) const {\n" - << " return\n"; - for (const CodeGenRegisterCategory &Category : RegCategories) - if (Category.getName() == "ArgumentRegisters") { - for (const CodeGenRegisterClass *RC : Category.getClasses()) - OS << " " << RC->getQualifiedName() - << "RegClass.contains(PhysReg) ||\n"; - break; - } - OS << " false;\n"; - OS << "}\n\n"; + PI.regInfoEmitGPRCheck(ClassName, RegCategories); + PI.regInfoEmitFixedRegCheck(ClassName, RegCategories); + PI.regInfoEmitArgRegCheck(ClassName, RegCategories); - OS << "bool " << ClassName << "::\n" - << "isConstantPhysReg(MCRegister PhysReg) const {\n" - << " return\n"; - for (const auto &Reg : Regs) - if (Reg.Constant) - OS << " PhysReg == " << getQualifiedName(Reg.TheDef) << " ||\n"; - OS << " false;\n"; - OS << "}\n\n"; - - OS << "ArrayRef " << ClassName - << "::getRegMaskNames() const {\n"; - if (!CSRSets.empty()) { - OS << " static const char *Names[] = {\n"; - for (Record *CSRSet : CSRSets) - OS << " " << '"' << CSRSet->getName() << '"' << ",\n"; - OS << " };\n"; - OS << " return makeArrayRef(Names);\n"; - } else { - OS << " return std::nullopt;\n"; - } - OS << "}\n\n"; + PI.regInfoEmitIsConstantPhysReg(Regs, ClassName); + PI.regInfoEmitGetRegMaskNames(CSRSets, ClassName); - OS << "const " << TargetName << "FrameLowering *\n" << TargetName - << "GenRegisterInfo::getFrameLowering(const MachineFunction &MF) {\n" - << " return static_cast(\n" - << " MF.getSubtarget().getFrameLowering());\n" - << "}\n\n"; + PI.regInfoEmitGetFrameLowering(TargetName); - OS << "} // end namespace llvm\n\n"; - OS << "#endif // GET_REGINFO_TARGET_DESC\n\n"; + PI.emitNamespace("llvm", false); + PI.emitIncludeToggle("GET_REGINFO_TARGET_DESC", false); } -void RegisterInfoEmitter::run(raw_ostream &OS) { +void RegisterInfoEmitter::run() { CodeGenRegBank &RegBank = Target.getRegBank(); Records.startTimer("Print enums"); - runEnums(OS, Target, RegBank); + + PI.regInfoEmitSourceFileHeader("Target Register Enum Values"); + PI.regInfoEmitEnums(Target, RegBank); Records.startTimer("Print MC registers"); - runMCDesc(OS, Target, RegBank); + runMCDesc(Target, RegBank); Records.startTimer("Print header fragment"); - runTargetHeader(OS, Target, RegBank); + runTargetHeader(Target, RegBank); Records.startTimer("Print target registers"); - runTargetDesc(OS, Target, RegBank); + runTargetDesc(Target, RegBank); if (RegisterInfoDebug) debugDump(errs()); } -void RegisterInfoEmitter::debugDump(raw_ostream &OS) { +void RegisterInfoEmitter::debugDump(raw_ostream &ErrOS) { CodeGenRegBank &RegBank = Target.getRegBank(); const CodeGenHwModes &CGH = Target.getHwModes(); unsigned NumModes = CGH.getNumModeIds(); @@ -1851,56 +795,56 @@ }; for (const CodeGenRegisterClass &RC : RegBank.getRegClasses()) { - OS << "RegisterClass " << RC.getName() << ":\n"; - OS << "\tSpillSize: {"; + ErrOS << "RegisterClass " << RC.getName() << ":\n"; + ErrOS << "\tSpillSize: {"; for (unsigned M = 0; M != NumModes; ++M) - OS << ' ' << getModeName(M) << ':' << RC.RSI.get(M).SpillSize; - OS << " }\n\tSpillAlignment: {"; + ErrOS << ' ' << getModeName(M) << ':' << RC.RSI.get(M).SpillSize; + ErrOS << " }\n\tSpillAlignment: {"; for (unsigned M = 0; M != NumModes; ++M) - OS << ' ' << getModeName(M) << ':' << RC.RSI.get(M).SpillAlignment; - OS << " }\n\tNumRegs: " << RC.getMembers().size() << '\n'; - OS << "\tLaneMask: " << PrintLaneMask(RC.LaneMask) << '\n'; - OS << "\tHasDisjunctSubRegs: " << RC.HasDisjunctSubRegs << '\n'; - OS << "\tCoveredBySubRegs: " << RC.CoveredBySubRegs << '\n'; - OS << "\tAllocatable: " << RC.Allocatable << '\n'; - OS << "\tAllocationPriority: " << unsigned(RC.AllocationPriority) << '\n'; - OS << "\tRegs:"; + ErrOS << ' ' << getModeName(M) << ':' << RC.RSI.get(M).SpillAlignment; + ErrOS << " }\n\tNumRegs: " << RC.getMembers().size() << '\n'; + ErrOS << "\tLaneMask: " << PrintLaneMask(RC.LaneMask) << '\n'; + ErrOS << "\tHasDisjunctSubRegs: " << RC.HasDisjunctSubRegs << '\n'; + ErrOS << "\tCoveredBySubRegs: " << RC.CoveredBySubRegs << '\n'; + ErrOS << "\tAllocatable: " << RC.Allocatable << '\n'; + ErrOS << "\tAllocationPriority: " << unsigned(RC.AllocationPriority) << '\n'; + ErrOS << "\tRegs:"; for (const CodeGenRegister *R : RC.getMembers()) { - OS << " " << R->getName(); + ErrOS << " " << R->getName(); } - OS << '\n'; - OS << "\tSubClasses:"; + ErrOS << '\n'; + ErrOS << "\tSubClasses:"; const BitVector &SubClasses = RC.getSubClasses(); for (const CodeGenRegisterClass &SRC : RegBank.getRegClasses()) { if (!SubClasses.test(SRC.EnumValue)) continue; - OS << " " << SRC.getName(); + ErrOS << " " << SRC.getName(); } - OS << '\n'; - OS << "\tSuperClasses:"; + ErrOS << '\n'; + ErrOS << "\tSuperClasses:"; for (const CodeGenRegisterClass *SRC : RC.getSuperClasses()) { - OS << " " << SRC->getName(); + ErrOS << " " << SRC->getName(); } - OS << '\n'; + ErrOS << '\n'; } for (const CodeGenSubRegIndex &SRI : RegBank.getSubRegIndices()) { - OS << "SubRegIndex " << SRI.getName() << ":\n"; - OS << "\tLaneMask: " << PrintLaneMask(SRI.LaneMask) << '\n'; - OS << "\tAllSuperRegsCovered: " << SRI.AllSuperRegsCovered << '\n'; - OS << "\tOffset, Size: " << SRI.Offset << ", " << SRI.Size << '\n'; + ErrOS << "SubRegIndex " << SRI.getName() << ":\n"; + ErrOS << "\tLaneMask: " << PrintLaneMask(SRI.LaneMask) << '\n'; + ErrOS << "\tAllSuperRegsCovered: " << SRI.AllSuperRegsCovered << '\n'; + ErrOS << "\tOffset, Size: " << SRI.Offset << ", " << SRI.Size << '\n'; } for (const CodeGenRegister &R : RegBank.getRegisters()) { - OS << "Register " << R.getName() << ":\n"; - OS << "\tCostPerUse: "; + ErrOS << "Register " << R.getName() << ":\n"; + ErrOS << "\tCostPerUse: "; for (const auto &Cost : R.CostPerUse) - OS << Cost << " "; - OS << '\n'; - OS << "\tCoveredBySubregs: " << R.CoveredBySubRegs << '\n'; - OS << "\tHasDisjunctSubRegs: " << R.HasDisjunctSubRegs << '\n'; + ErrOS << Cost << " "; + ErrOS << '\n'; + ErrOS << "\tCoveredBySubregs: " << R.CoveredBySubRegs << '\n'; + ErrOS << "\tHasDisjunctSubRegs: " << R.HasDisjunctSubRegs << '\n'; for (std::pair P : R.getSubRegs()) { - OS << "\tSubReg " << P.first->getName() + ErrOS << "\tSubReg " << P.first->getName() << " = " << P.second->getName() << '\n'; } } @@ -1909,7 +853,20 @@ namespace llvm { void EmitRegisterInfo(RecordKeeper &RK, raw_ostream &OS) { - RegisterInfoEmitter(RK).run(OS); + formatted_raw_ostream FOS(OS); + PrinterLanguage const PLang = PrinterLLVM::getLanguage(); + PrinterLLVM *PI = nullptr; + switch (PLang) { + default: + PrintFatalNote( + "RegisterInfo backend does not support the selected ouput language."); + return; + case PRINTER_LANG_CPP: + PI = new PrinterLLVM(FOS); + break; + } + RegisterInfoEmitter(RK, *PI).run(); + delete PI; } } // end namespace llvm Index: llvm/utils/TableGen/RegisterInfoEmitterTypes.h =================================================================== --- /dev/null +++ llvm/utils/TableGen/RegisterInfoEmitterTypes.h @@ -0,0 +1,70 @@ +//===- RegisterInfoEmitterTypes.h - Register Emitter Types -*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===-----------------------------------------------------------------===// + +#ifndef LLVM_UTILS_TABLEGEN_REGISTERINFOEMITTERTYPES_H +#define LLVM_UTILS_TABLEGEN_REGISTERINFOEMITTERTYPES_H + +#include "CodeGenRegisters.h" +#include "CodeGenTarget.h" +#include "SequenceToOffsetTable.h" +#include "Types.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/BitVector.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SetVector.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/SparseBitVector.h" +#include "llvm/ADT/Twine.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/MachineValueType.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/TableGen/Error.h" +#include "llvm/TableGen/Record.h" +#include "llvm/TableGen/SetTheory.h" +#include "llvm/TableGen/TableGenBackend.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace llvm; + +// Compress the sub-reg index lists. +typedef std::vector IdxList; + +// Keep track of sub-register names as well. These are not differentially +// encoded. +typedef SmallVector SubRegIdxVec; + +// Differentially encoded register and regunit lists allow for better +// compression on regular register banks. The sequence is computed from the +// differential list as: +// +// out[0] = InitVal; +// out[n+1] = out[n] + diff[n]; // n = 0, 1, ... +// +// The initial value depends on the specific list. The list is terminated by a +// 0 differential which means we can't encode repeated elements. +typedef SmallVector DiffVec; +typedef SmallVector MaskVec; + +// The lists of sub-registers and super-registers go in the same array. That +// allows us to share suffixes. +typedef std::vector RegVec; + +using DwarfRegNumsMapPair = std::pair>; +using DwarfRegNumsVecTy = std::vector; + +#endif // LLVM_UTILS_TABLEGEN_REGISTERINFOEMITTERTYPES_H Index: llvm/utils/TableGen/SequenceToOffsetTable.h =================================================================== --- llvm/utils/TableGen/SequenceToOffsetTable.h +++ llvm/utils/TableGen/SequenceToOffsetTable.h @@ -15,6 +15,7 @@ #ifndef LLVM_UTILS_TABLEGEN_SEQUENCETOOFFSETTABLE_H #define LLVM_UTILS_TABLEGEN_SEQUENCETOOFFSETTABLE_H +#include "PrinterTypes.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/raw_ostream.h" #include @@ -110,13 +111,17 @@ // Entries in the final table, or 0 before layout was called. unsigned Entries; + // The output language of the table. + PrinterLanguage PL; + // isSuffix - Returns true if A is a suffix of B. static bool isSuffix(const SeqT &A, const SeqT &B) { return A.size() <= B.size() && std::equal(A.rbegin(), A.rend(), B.rbegin()); } public: - SequenceToOffsetTable() : Entries(0) {} + SequenceToOffsetTable() : Entries(0), PL(PRINTER_LANG_CPP) {} + SequenceToOffsetTable(PrinterLanguage PL) : Entries(0), PL(PL) {} /// add - Add a sequence to the table. /// This must be called before layout(). @@ -164,11 +169,31 @@ return I->second + (I->first.size() - Seq.size()); } + void emitStringLiteralDef(raw_ostream &OS, const llvm::Twine &Decl) const { + switch (PL) { + default: + llvm_unreachable("Language not specified to print table in."); + case PRINTER_LANG_CPP: + emitStringLiteralDefCPP(OS, Decl); + } + } + + void emit(raw_ostream &OS, + void (*Print)(raw_ostream&, ElemT), + const char *Term = "0") const { + switch (PL) { + default: + llvm_unreachable("Language not specified to print table in."); + case PRINTER_LANG_CPP: + emitCPP(OS, Print, Term); + } + } + /// `emitStringLiteralDef` - Print out the table as the body of an array /// initializer, where each element is a C string literal terminated by /// `\0`. Falls back to emitting a comma-separated integer list if /// `EmitLongStrLiterals` is false - void emitStringLiteralDef(raw_ostream &OS, const llvm::Twine &Decl) const { + void emitStringLiteralDefCPP(raw_ostream &OS, const llvm::Twine &Decl) const { assert(Entries && "Call layout() before emitStringLiteralDef()"); if (!EmitLongStrLiterals) { OS << Decl << " = {\n"; @@ -197,9 +222,9 @@ /// emit - Print out the table as the body of an array initializer. /// Use the Print function to print elements. - void emit(raw_ostream &OS, + void emitCPP(raw_ostream &OS, void (*Print)(raw_ostream&, ElemT), - const char *Term = "0") const { + const char *Term) const { assert((empty() || Entries) && "Call layout() before emit()"); for (typename SeqMap::const_iterator I = Seqs.begin(), E = Seqs.end(); I != E; ++I) {