10b57cec5SDimitry Andric //===- RegisterBankEmitter.cpp - Generate a Register Bank Desc. -*- C++ -*-===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This tablegen backend is responsible for emitting a description of a target 100b57cec5SDimitry Andric // register bank for a code generator. 110b57cec5SDimitry Andric // 120b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 130b57cec5SDimitry Andric 14*0fca6ea1SDimitry Andric #include "Common/CodeGenRegisters.h" 15*0fca6ea1SDimitry Andric #include "Common/CodeGenTarget.h" 16*0fca6ea1SDimitry Andric #include "Common/InfoByHwMode.h" 170b57cec5SDimitry Andric #include "llvm/ADT/BitVector.h" 180b57cec5SDimitry Andric #include "llvm/Support/Debug.h" 190b57cec5SDimitry Andric #include "llvm/TableGen/Error.h" 200b57cec5SDimitry Andric #include "llvm/TableGen/Record.h" 210b57cec5SDimitry Andric #include "llvm/TableGen/TableGenBackend.h" 220b57cec5SDimitry Andric 230b57cec5SDimitry Andric #define DEBUG_TYPE "register-bank-emitter" 240b57cec5SDimitry Andric 250b57cec5SDimitry Andric using namespace llvm; 260b57cec5SDimitry Andric 270b57cec5SDimitry Andric namespace { 280b57cec5SDimitry Andric class RegisterBank { 290b57cec5SDimitry Andric 300b57cec5SDimitry Andric /// A vector of register classes that are included in the register bank. 310b57cec5SDimitry Andric typedef std::vector<const CodeGenRegisterClass *> RegisterClassesTy; 320b57cec5SDimitry Andric 330b57cec5SDimitry Andric private: 340b57cec5SDimitry Andric const Record &TheDef; 350b57cec5SDimitry Andric 360b57cec5SDimitry Andric /// The register classes that are covered by the register bank. 370b57cec5SDimitry Andric RegisterClassesTy RCs; 380b57cec5SDimitry Andric 390b57cec5SDimitry Andric /// The register class with the largest register size. 4006c3fb27SDimitry Andric std::vector<const CodeGenRegisterClass *> RCsWithLargestRegSize; 410b57cec5SDimitry Andric 420b57cec5SDimitry Andric public: 4306c3fb27SDimitry Andric RegisterBank(const Record &TheDef, unsigned NumModeIds) 4406c3fb27SDimitry Andric : TheDef(TheDef), RCsWithLargestRegSize(NumModeIds) {} 450b57cec5SDimitry Andric 460b57cec5SDimitry Andric /// Get the human-readable name for the bank. 470b57cec5SDimitry Andric StringRef getName() const { return TheDef.getValueAsString("Name"); } 480b57cec5SDimitry Andric /// Get the name of the enumerator in the ID enumeration. 49*0fca6ea1SDimitry Andric std::string getEnumeratorName() const { 50*0fca6ea1SDimitry Andric return (TheDef.getName() + "ID").str(); 51*0fca6ea1SDimitry Andric } 520b57cec5SDimitry Andric 530b57cec5SDimitry Andric /// Get the name of the array holding the register class coverage data; 540b57cec5SDimitry Andric std::string getCoverageArrayName() const { 550b57cec5SDimitry Andric return (TheDef.getName() + "CoverageData").str(); 560b57cec5SDimitry Andric } 570b57cec5SDimitry Andric 580b57cec5SDimitry Andric /// Get the name of the global instance variable. 590b57cec5SDimitry Andric StringRef getInstanceVarName() const { return TheDef.getName(); } 600b57cec5SDimitry Andric 610b57cec5SDimitry Andric const Record &getDef() const { return TheDef; } 620b57cec5SDimitry Andric 630b57cec5SDimitry Andric /// Get the register classes listed in the RegisterBank.RegisterClasses field. 640b57cec5SDimitry Andric std::vector<const CodeGenRegisterClass *> 655ffd83dbSDimitry Andric getExplicitlySpecifiedRegisterClasses( 665ffd83dbSDimitry Andric const CodeGenRegBank &RegisterClassHierarchy) const { 670b57cec5SDimitry Andric std::vector<const CodeGenRegisterClass *> RCs; 685ffd83dbSDimitry Andric for (const auto *RCDef : getDef().getValueAsListOfDefs("RegisterClasses")) 690b57cec5SDimitry Andric RCs.push_back(RegisterClassHierarchy.getRegClass(RCDef)); 700b57cec5SDimitry Andric return RCs; 710b57cec5SDimitry Andric } 720b57cec5SDimitry Andric 730b57cec5SDimitry Andric /// Add a register class to the bank without duplicates. 740b57cec5SDimitry Andric void addRegisterClass(const CodeGenRegisterClass *RC) { 75e8d8bef9SDimitry Andric if (llvm::is_contained(RCs, RC)) 760b57cec5SDimitry Andric return; 770b57cec5SDimitry Andric 780b57cec5SDimitry Andric // FIXME? We really want the register size rather than the spill size 790b57cec5SDimitry Andric // since the spill size may be bigger on some targets with 800b57cec5SDimitry Andric // limited load/store instructions. However, we don't store the 810b57cec5SDimitry Andric // register size anywhere (we could sum the sizes of the subregisters 820b57cec5SDimitry Andric // but there may be additional bits too) and we can't derive it from 830b57cec5SDimitry Andric // the VT's reliably due to Untyped. 8406c3fb27SDimitry Andric unsigned NumModeIds = RCsWithLargestRegSize.size(); 8506c3fb27SDimitry Andric for (unsigned M = 0; M < NumModeIds; ++M) { 8606c3fb27SDimitry Andric if (RCsWithLargestRegSize[M] == nullptr) 8706c3fb27SDimitry Andric RCsWithLargestRegSize[M] = RC; 8806c3fb27SDimitry Andric else if (RCsWithLargestRegSize[M]->RSI.get(M).SpillSize < 8906c3fb27SDimitry Andric RC->RSI.get(M).SpillSize) 9006c3fb27SDimitry Andric RCsWithLargestRegSize[M] = RC; 9106c3fb27SDimitry Andric assert(RCsWithLargestRegSize[M] && "RC was nullptr?"); 9206c3fb27SDimitry Andric } 930b57cec5SDimitry Andric 940b57cec5SDimitry Andric RCs.emplace_back(RC); 950b57cec5SDimitry Andric } 960b57cec5SDimitry Andric 9706c3fb27SDimitry Andric const CodeGenRegisterClass *getRCWithLargestRegSize(unsigned HwMode) const { 9806c3fb27SDimitry Andric return RCsWithLargestRegSize[HwMode]; 990b57cec5SDimitry Andric } 1000b57cec5SDimitry Andric 1010b57cec5SDimitry Andric iterator_range<typename RegisterClassesTy::const_iterator> 1020b57cec5SDimitry Andric register_classes() const { 1030b57cec5SDimitry Andric return llvm::make_range(RCs.begin(), RCs.end()); 1040b57cec5SDimitry Andric } 1050b57cec5SDimitry Andric }; 1060b57cec5SDimitry Andric 1070b57cec5SDimitry Andric class RegisterBankEmitter { 1080b57cec5SDimitry Andric private: 1095ffd83dbSDimitry Andric CodeGenTarget Target; 1100b57cec5SDimitry Andric RecordKeeper &Records; 1110b57cec5SDimitry Andric 1120b57cec5SDimitry Andric void emitHeader(raw_ostream &OS, const StringRef TargetName, 1130b57cec5SDimitry Andric const std::vector<RegisterBank> &Banks); 1140b57cec5SDimitry Andric void emitBaseClassDefinition(raw_ostream &OS, const StringRef TargetName, 1150b57cec5SDimitry Andric const std::vector<RegisterBank> &Banks); 1160b57cec5SDimitry Andric void emitBaseClassImplementation(raw_ostream &OS, const StringRef TargetName, 1170b57cec5SDimitry Andric std::vector<RegisterBank> &Banks); 1180b57cec5SDimitry Andric 1190b57cec5SDimitry Andric public: 1205ffd83dbSDimitry Andric RegisterBankEmitter(RecordKeeper &R) : Target(R), Records(R) {} 1210b57cec5SDimitry Andric 1220b57cec5SDimitry Andric void run(raw_ostream &OS); 1230b57cec5SDimitry Andric }; 1240b57cec5SDimitry Andric 1250b57cec5SDimitry Andric } // end anonymous namespace 1260b57cec5SDimitry Andric 1270b57cec5SDimitry Andric /// Emit code to declare the ID enumeration and external global instance 1280b57cec5SDimitry Andric /// variables. 1290b57cec5SDimitry Andric void RegisterBankEmitter::emitHeader(raw_ostream &OS, 1300b57cec5SDimitry Andric const StringRef TargetName, 1310b57cec5SDimitry Andric const std::vector<RegisterBank> &Banks) { 1320b57cec5SDimitry Andric // <Target>RegisterBankInfo.h 1330b57cec5SDimitry Andric OS << "namespace llvm {\n" 1340b57cec5SDimitry Andric << "namespace " << TargetName << " {\n" 135e8d8bef9SDimitry Andric << "enum : unsigned {\n"; 136e8d8bef9SDimitry Andric 137e8d8bef9SDimitry Andric OS << " InvalidRegBankID = ~0u,\n"; 138e8d8bef9SDimitry Andric unsigned ID = 0; 1390b57cec5SDimitry Andric for (const auto &Bank : Banks) 140e8d8bef9SDimitry Andric OS << " " << Bank.getEnumeratorName() << " = " << ID++ << ",\n"; 1410b57cec5SDimitry Andric OS << " NumRegisterBanks,\n" 1420b57cec5SDimitry Andric << "};\n" 1430b57cec5SDimitry Andric << "} // end namespace " << TargetName << "\n" 1440b57cec5SDimitry Andric << "} // end namespace llvm\n"; 1450b57cec5SDimitry Andric } 1460b57cec5SDimitry Andric 1470b57cec5SDimitry Andric /// Emit declarations of the <Target>GenRegisterBankInfo class. 1480b57cec5SDimitry Andric void RegisterBankEmitter::emitBaseClassDefinition( 1490b57cec5SDimitry Andric raw_ostream &OS, const StringRef TargetName, 1500b57cec5SDimitry Andric const std::vector<RegisterBank> &Banks) { 1510b57cec5SDimitry Andric OS << "private:\n" 15206c3fb27SDimitry Andric << " static const RegisterBank *RegBanks[];\n" 15306c3fb27SDimitry Andric << " static const unsigned Sizes[];\n\n" 1540b57cec5SDimitry Andric << "protected:\n" 15506c3fb27SDimitry Andric << " " << TargetName << "GenRegisterBankInfo(unsigned HwMode = 0);\n" 1560b57cec5SDimitry Andric << "\n"; 1570b57cec5SDimitry Andric } 1580b57cec5SDimitry Andric 1590b57cec5SDimitry Andric /// Visit each register class belonging to the given register bank. 1600b57cec5SDimitry Andric /// 1610b57cec5SDimitry Andric /// A class belongs to the bank iff any of these apply: 1620b57cec5SDimitry Andric /// * It is explicitly specified 1630b57cec5SDimitry Andric /// * It is a subclass of a class that is a member. 1640b57cec5SDimitry Andric /// * It is a class containing subregisters of the registers of a class that 1650b57cec5SDimitry Andric /// is a member. This is known as a subreg-class. 1660b57cec5SDimitry Andric /// 1670b57cec5SDimitry Andric /// This function must be called for each explicitly specified register class. 1680b57cec5SDimitry Andric /// 1690b57cec5SDimitry Andric /// \param RC The register class to search. 1700b57cec5SDimitry Andric /// \param Kind A debug string containing the path the visitor took to reach RC. 1710b57cec5SDimitry Andric /// \param VisitFn The action to take for each class visited. It may be called 1720b57cec5SDimitry Andric /// multiple times for a given class if there are multiple paths 1730b57cec5SDimitry Andric /// to the class. 1740b57cec5SDimitry Andric static void visitRegisterBankClasses( 1755ffd83dbSDimitry Andric const CodeGenRegBank &RegisterClassHierarchy, 176e8d8bef9SDimitry Andric const CodeGenRegisterClass *RC, const Twine &Kind, 1770b57cec5SDimitry Andric std::function<void(const CodeGenRegisterClass *, StringRef)> VisitFn, 1780b57cec5SDimitry Andric SmallPtrSetImpl<const CodeGenRegisterClass *> &VisitedRCs) { 1790b57cec5SDimitry Andric 1800b57cec5SDimitry Andric // Make sure we only visit each class once to avoid infinite loops. 18181ad6265SDimitry Andric if (!VisitedRCs.insert(RC).second) 1820b57cec5SDimitry Andric return; 1830b57cec5SDimitry Andric 1840b57cec5SDimitry Andric // Visit each explicitly named class. 1850b57cec5SDimitry Andric VisitFn(RC, Kind.str()); 1860b57cec5SDimitry Andric 1870b57cec5SDimitry Andric for (const auto &PossibleSubclass : RegisterClassHierarchy.getRegClasses()) { 1880b57cec5SDimitry Andric std::string TmpKind = 189e8d8bef9SDimitry Andric (Kind + " (" + PossibleSubclass.getName() + ")").str(); 1900b57cec5SDimitry Andric 1910b57cec5SDimitry Andric // Visit each subclass of an explicitly named class. 1920b57cec5SDimitry Andric if (RC != &PossibleSubclass && RC->hasSubClass(&PossibleSubclass)) 1930b57cec5SDimitry Andric visitRegisterBankClasses(RegisterClassHierarchy, &PossibleSubclass, 1940b57cec5SDimitry Andric TmpKind + " " + RC->getName() + " subclass", 1950b57cec5SDimitry Andric VisitFn, VisitedRCs); 1960b57cec5SDimitry Andric 1970b57cec5SDimitry Andric // Visit each class that contains only subregisters of RC with a common 1980b57cec5SDimitry Andric // subregister-index. 1990b57cec5SDimitry Andric // 2000b57cec5SDimitry Andric // More precisely, PossibleSubclass is a subreg-class iff Reg:SubIdx is in 2010b57cec5SDimitry Andric // PossibleSubclass for all registers Reg from RC using any 2020b57cec5SDimitry Andric // subregister-index SubReg 2030b57cec5SDimitry Andric for (const auto &SubIdx : RegisterClassHierarchy.getSubRegIndices()) { 2040b57cec5SDimitry Andric BitVector BV(RegisterClassHierarchy.getRegClasses().size()); 2050b57cec5SDimitry Andric PossibleSubclass.getSuperRegClasses(&SubIdx, BV); 2060b57cec5SDimitry Andric if (BV.test(RC->EnumValue)) { 2070b57cec5SDimitry Andric std::string TmpKind2 = (Twine(TmpKind) + " " + RC->getName() + 2080b57cec5SDimitry Andric " class-with-subregs: " + RC->getName()) 2090b57cec5SDimitry Andric .str(); 2100b57cec5SDimitry Andric VisitFn(&PossibleSubclass, TmpKind2); 2110b57cec5SDimitry Andric } 2120b57cec5SDimitry Andric } 2130b57cec5SDimitry Andric } 2140b57cec5SDimitry Andric } 2150b57cec5SDimitry Andric 2160b57cec5SDimitry Andric void RegisterBankEmitter::emitBaseClassImplementation( 217*0fca6ea1SDimitry Andric raw_ostream &OS, StringRef TargetName, std::vector<RegisterBank> &Banks) { 2185ffd83dbSDimitry Andric const CodeGenRegBank &RegisterClassHierarchy = Target.getRegBank(); 21906c3fb27SDimitry Andric const CodeGenHwModes &CGH = Target.getHwModes(); 2200b57cec5SDimitry Andric 2210b57cec5SDimitry Andric OS << "namespace llvm {\n" 2220b57cec5SDimitry Andric << "namespace " << TargetName << " {\n"; 2230b57cec5SDimitry Andric for (const auto &Bank : Banks) { 2240b57cec5SDimitry Andric std::vector<std::vector<const CodeGenRegisterClass *>> RCsGroupedByWord( 2250b57cec5SDimitry Andric (RegisterClassHierarchy.getRegClasses().size() + 31) / 32); 2260b57cec5SDimitry Andric 2270b57cec5SDimitry Andric for (const auto &RC : Bank.register_classes()) 2280b57cec5SDimitry Andric RCsGroupedByWord[RC->EnumValue / 32].push_back(RC); 2290b57cec5SDimitry Andric 2300b57cec5SDimitry Andric OS << "const uint32_t " << Bank.getCoverageArrayName() << "[] = {\n"; 2310b57cec5SDimitry Andric unsigned LowestIdxInWord = 0; 2320b57cec5SDimitry Andric for (const auto &RCs : RCsGroupedByWord) { 233*0fca6ea1SDimitry Andric OS << " // " << LowestIdxInWord << "-" << (LowestIdxInWord + 31) 234*0fca6ea1SDimitry Andric << "\n"; 2350b57cec5SDimitry Andric for (const auto &RC : RCs) { 2365f757f3fSDimitry Andric OS << " (1u << (" << RC->getQualifiedIdName() << " - " 2370b57cec5SDimitry Andric << LowestIdxInWord << ")) |\n"; 2380b57cec5SDimitry Andric } 2390b57cec5SDimitry Andric OS << " 0,\n"; 2400b57cec5SDimitry Andric LowestIdxInWord += 32; 2410b57cec5SDimitry Andric } 2420b57cec5SDimitry Andric OS << "};\n"; 2430b57cec5SDimitry Andric } 2440b57cec5SDimitry Andric OS << "\n"; 2450b57cec5SDimitry Andric 2460b57cec5SDimitry Andric for (const auto &Bank : Banks) { 2470b57cec5SDimitry Andric std::string QualifiedBankID = 2480b57cec5SDimitry Andric (TargetName + "::" + Bank.getEnumeratorName()).str(); 2495f757f3fSDimitry Andric OS << "constexpr RegisterBank " << Bank.getInstanceVarName() << "(/* ID */ " 25006c3fb27SDimitry Andric << QualifiedBankID << ", /* Name */ \"" << Bank.getName() << "\", " 2510b57cec5SDimitry Andric << "/* CoveredRegClasses */ " << Bank.getCoverageArrayName() 2520b57cec5SDimitry Andric << ", /* NumRegClasses */ " 2530b57cec5SDimitry Andric << RegisterClassHierarchy.getRegClasses().size() << ");\n"; 2540b57cec5SDimitry Andric } 2550b57cec5SDimitry Andric OS << "} // end namespace " << TargetName << "\n" 2560b57cec5SDimitry Andric << "\n"; 2570b57cec5SDimitry Andric 25806c3fb27SDimitry Andric OS << "const RegisterBank *" << TargetName 2590b57cec5SDimitry Andric << "GenRegisterBankInfo::RegBanks[] = {\n"; 2600b57cec5SDimitry Andric for (const auto &Bank : Banks) 2610b57cec5SDimitry Andric OS << " &" << TargetName << "::" << Bank.getInstanceVarName() << ",\n"; 2620b57cec5SDimitry Andric OS << "};\n\n"; 2630b57cec5SDimitry Andric 26406c3fb27SDimitry Andric unsigned NumModeIds = CGH.getNumModeIds(); 26506c3fb27SDimitry Andric OS << "const unsigned " << TargetName << "GenRegisterBankInfo::Sizes[] = {\n"; 26606c3fb27SDimitry Andric for (unsigned M = 0; M < NumModeIds; ++M) { 26706c3fb27SDimitry Andric OS << " // Mode = " << M << " ("; 26806c3fb27SDimitry Andric if (M == DefaultMode) 26906c3fb27SDimitry Andric OS << "Default"; 27006c3fb27SDimitry Andric else 27106c3fb27SDimitry Andric OS << CGH.getMode(M).Name; 27206c3fb27SDimitry Andric OS << ")\n"; 27306c3fb27SDimitry Andric for (const auto &Bank : Banks) { 27406c3fb27SDimitry Andric const CodeGenRegisterClass &RC = *Bank.getRCWithLargestRegSize(M); 27506c3fb27SDimitry Andric unsigned Size = RC.RSI.get(M).SpillSize; 27606c3fb27SDimitry Andric OS << " " << Size << ",\n"; 27706c3fb27SDimitry Andric } 27806c3fb27SDimitry Andric } 27906c3fb27SDimitry Andric OS << "};\n\n"; 28006c3fb27SDimitry Andric 2810b57cec5SDimitry Andric OS << TargetName << "GenRegisterBankInfo::" << TargetName 28206c3fb27SDimitry Andric << "GenRegisterBankInfo(unsigned HwMode)\n" 2830b57cec5SDimitry Andric << " : RegisterBankInfo(RegBanks, " << TargetName 28406c3fb27SDimitry Andric << "::NumRegisterBanks, Sizes, HwMode) {\n" 2850b57cec5SDimitry Andric << " // Assert that RegBank indices match their ID's\n" 2860b57cec5SDimitry Andric << "#ifndef NDEBUG\n" 28781ad6265SDimitry Andric << " for (auto RB : enumerate(RegBanks))\n" 28881ad6265SDimitry Andric << " assert(RB.index() == RB.value()->getID() && \"Index != ID\");\n" 2890b57cec5SDimitry Andric << "#endif // NDEBUG\n" 2900b57cec5SDimitry Andric << "}\n" 2910b57cec5SDimitry Andric << "} // end namespace llvm\n"; 2920b57cec5SDimitry Andric } 2930b57cec5SDimitry Andric 2940b57cec5SDimitry Andric void RegisterBankEmitter::run(raw_ostream &OS) { 2955ffd83dbSDimitry Andric StringRef TargetName = Target.getName(); 2965ffd83dbSDimitry Andric const CodeGenRegBank &RegisterClassHierarchy = Target.getRegBank(); 29706c3fb27SDimitry Andric const CodeGenHwModes &CGH = Target.getHwModes(); 2980b57cec5SDimitry Andric 299e8d8bef9SDimitry Andric Records.startTimer("Analyze records"); 3000b57cec5SDimitry Andric std::vector<RegisterBank> Banks; 3010b57cec5SDimitry Andric for (const auto &V : Records.getAllDerivedDefinitions("RegisterBank")) { 3020b57cec5SDimitry Andric SmallPtrSet<const CodeGenRegisterClass *, 8> VisitedRCs; 30306c3fb27SDimitry Andric RegisterBank Bank(*V, CGH.getNumModeIds()); 3040b57cec5SDimitry Andric 3050b57cec5SDimitry Andric for (const CodeGenRegisterClass *RC : 3065ffd83dbSDimitry Andric Bank.getExplicitlySpecifiedRegisterClasses(RegisterClassHierarchy)) { 3070b57cec5SDimitry Andric visitRegisterBankClasses( 3080b57cec5SDimitry Andric RegisterClassHierarchy, RC, "explicit", 3090b57cec5SDimitry Andric [&Bank](const CodeGenRegisterClass *RC, StringRef Kind) { 3100b57cec5SDimitry Andric LLVM_DEBUG(dbgs() 3110b57cec5SDimitry Andric << "Added " << RC->getName() << "(" << Kind << ")\n"); 3120b57cec5SDimitry Andric Bank.addRegisterClass(RC); 3130b57cec5SDimitry Andric }, 3140b57cec5SDimitry Andric VisitedRCs); 3150b57cec5SDimitry Andric } 3160b57cec5SDimitry Andric 3170b57cec5SDimitry Andric Banks.push_back(Bank); 3180b57cec5SDimitry Andric } 3190b57cec5SDimitry Andric 3200b57cec5SDimitry Andric // Warn about ambiguous MIR caused by register bank/class name clashes. 321e8d8bef9SDimitry Andric Records.startTimer("Warn ambiguous"); 3225ffd83dbSDimitry Andric for (const auto &Class : RegisterClassHierarchy.getRegClasses()) { 3230b57cec5SDimitry Andric for (const auto &Bank : Banks) { 3245ffd83dbSDimitry Andric if (Bank.getName().lower() == StringRef(Class.getName()).lower()) { 3250b57cec5SDimitry Andric PrintWarning(Bank.getDef().getLoc(), "Register bank names should be " 3260b57cec5SDimitry Andric "distinct from register classes " 3270b57cec5SDimitry Andric "to avoid ambiguous MIR"); 3280b57cec5SDimitry Andric PrintNote(Bank.getDef().getLoc(), "RegisterBank was declared here"); 3295ffd83dbSDimitry Andric PrintNote(Class.getDef()->getLoc(), "RegisterClass was declared here"); 3300b57cec5SDimitry Andric } 3310b57cec5SDimitry Andric } 3320b57cec5SDimitry Andric } 3330b57cec5SDimitry Andric 334e8d8bef9SDimitry Andric Records.startTimer("Emit output"); 3350b57cec5SDimitry Andric emitSourceFileHeader("Register Bank Source Fragments", OS); 3360b57cec5SDimitry Andric OS << "#ifdef GET_REGBANK_DECLARATIONS\n" 3370b57cec5SDimitry Andric << "#undef GET_REGBANK_DECLARATIONS\n"; 3380b57cec5SDimitry Andric emitHeader(OS, TargetName, Banks); 3390b57cec5SDimitry Andric OS << "#endif // GET_REGBANK_DECLARATIONS\n\n" 3400b57cec5SDimitry Andric << "#ifdef GET_TARGET_REGBANK_CLASS\n" 3410b57cec5SDimitry Andric << "#undef GET_TARGET_REGBANK_CLASS\n"; 3420b57cec5SDimitry Andric emitBaseClassDefinition(OS, TargetName, Banks); 3430b57cec5SDimitry Andric OS << "#endif // GET_TARGET_REGBANK_CLASS\n\n" 3440b57cec5SDimitry Andric << "#ifdef GET_TARGET_REGBANK_IMPL\n" 3450b57cec5SDimitry Andric << "#undef GET_TARGET_REGBANK_IMPL\n"; 3460b57cec5SDimitry Andric emitBaseClassImplementation(OS, TargetName, Banks); 3470b57cec5SDimitry Andric OS << "#endif // GET_TARGET_REGBANK_IMPL\n"; 3480b57cec5SDimitry Andric } 3490b57cec5SDimitry Andric 35006c3fb27SDimitry Andric static TableGen::Emitter::OptClass<RegisterBankEmitter> 35106c3fb27SDimitry Andric X("gen-register-bank", "Generate registers bank descriptions"); 352