1*0b57cec5SDimitry Andric //===- RegisterBankEmitter.cpp - Generate a Register Bank Desc. -*- C++ -*-===// 2*0b57cec5SDimitry Andric // 3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric // 7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8*0b57cec5SDimitry Andric // 9*0b57cec5SDimitry Andric // This tablegen backend is responsible for emitting a description of a target 10*0b57cec5SDimitry Andric // register bank for a code generator. 11*0b57cec5SDimitry Andric // 12*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 13*0b57cec5SDimitry Andric 14*0b57cec5SDimitry Andric #include "llvm/ADT/BitVector.h" 15*0b57cec5SDimitry Andric #include "llvm/Support/Debug.h" 16*0b57cec5SDimitry Andric #include "llvm/TableGen/Error.h" 17*0b57cec5SDimitry Andric #include "llvm/TableGen/Record.h" 18*0b57cec5SDimitry Andric #include "llvm/TableGen/TableGenBackend.h" 19*0b57cec5SDimitry Andric 20*0b57cec5SDimitry Andric #include "CodeGenHwModes.h" 21*0b57cec5SDimitry Andric #include "CodeGenRegisters.h" 22*0b57cec5SDimitry Andric 23*0b57cec5SDimitry Andric #define DEBUG_TYPE "register-bank-emitter" 24*0b57cec5SDimitry Andric 25*0b57cec5SDimitry Andric using namespace llvm; 26*0b57cec5SDimitry Andric 27*0b57cec5SDimitry Andric namespace { 28*0b57cec5SDimitry Andric class RegisterBank { 29*0b57cec5SDimitry Andric 30*0b57cec5SDimitry Andric /// A vector of register classes that are included in the register bank. 31*0b57cec5SDimitry Andric typedef std::vector<const CodeGenRegisterClass *> RegisterClassesTy; 32*0b57cec5SDimitry Andric 33*0b57cec5SDimitry Andric private: 34*0b57cec5SDimitry Andric const Record &TheDef; 35*0b57cec5SDimitry Andric 36*0b57cec5SDimitry Andric /// The register classes that are covered by the register bank. 37*0b57cec5SDimitry Andric RegisterClassesTy RCs; 38*0b57cec5SDimitry Andric 39*0b57cec5SDimitry Andric /// The register class with the largest register size. 40*0b57cec5SDimitry Andric const CodeGenRegisterClass *RCWithLargestRegsSize; 41*0b57cec5SDimitry Andric 42*0b57cec5SDimitry Andric public: 43*0b57cec5SDimitry Andric RegisterBank(const Record &TheDef) 44*0b57cec5SDimitry Andric : TheDef(TheDef), RCs(), RCWithLargestRegsSize(nullptr) {} 45*0b57cec5SDimitry Andric 46*0b57cec5SDimitry Andric /// Get the human-readable name for the bank. 47*0b57cec5SDimitry Andric StringRef getName() const { return TheDef.getValueAsString("Name"); } 48*0b57cec5SDimitry Andric /// Get the name of the enumerator in the ID enumeration. 49*0b57cec5SDimitry Andric std::string getEnumeratorName() const { return (TheDef.getName() + "ID").str(); } 50*0b57cec5SDimitry Andric 51*0b57cec5SDimitry Andric /// Get the name of the array holding the register class coverage data; 52*0b57cec5SDimitry Andric std::string getCoverageArrayName() const { 53*0b57cec5SDimitry Andric return (TheDef.getName() + "CoverageData").str(); 54*0b57cec5SDimitry Andric } 55*0b57cec5SDimitry Andric 56*0b57cec5SDimitry Andric /// Get the name of the global instance variable. 57*0b57cec5SDimitry Andric StringRef getInstanceVarName() const { return TheDef.getName(); } 58*0b57cec5SDimitry Andric 59*0b57cec5SDimitry Andric const Record &getDef() const { return TheDef; } 60*0b57cec5SDimitry Andric 61*0b57cec5SDimitry Andric /// Get the register classes listed in the RegisterBank.RegisterClasses field. 62*0b57cec5SDimitry Andric std::vector<const CodeGenRegisterClass *> 63*0b57cec5SDimitry Andric getExplictlySpecifiedRegisterClasses( 64*0b57cec5SDimitry Andric CodeGenRegBank &RegisterClassHierarchy) const { 65*0b57cec5SDimitry Andric std::vector<const CodeGenRegisterClass *> RCs; 66*0b57cec5SDimitry Andric for (const auto &RCDef : getDef().getValueAsListOfDefs("RegisterClasses")) 67*0b57cec5SDimitry Andric RCs.push_back(RegisterClassHierarchy.getRegClass(RCDef)); 68*0b57cec5SDimitry Andric return RCs; 69*0b57cec5SDimitry Andric } 70*0b57cec5SDimitry Andric 71*0b57cec5SDimitry Andric /// Add a register class to the bank without duplicates. 72*0b57cec5SDimitry Andric void addRegisterClass(const CodeGenRegisterClass *RC) { 73*0b57cec5SDimitry Andric if (std::find_if(RCs.begin(), RCs.end(), 74*0b57cec5SDimitry Andric [&RC](const CodeGenRegisterClass *X) { 75*0b57cec5SDimitry Andric return X == RC; 76*0b57cec5SDimitry Andric }) != RCs.end()) 77*0b57cec5SDimitry Andric return; 78*0b57cec5SDimitry Andric 79*0b57cec5SDimitry Andric // FIXME? We really want the register size rather than the spill size 80*0b57cec5SDimitry Andric // since the spill size may be bigger on some targets with 81*0b57cec5SDimitry Andric // limited load/store instructions. However, we don't store the 82*0b57cec5SDimitry Andric // register size anywhere (we could sum the sizes of the subregisters 83*0b57cec5SDimitry Andric // but there may be additional bits too) and we can't derive it from 84*0b57cec5SDimitry Andric // the VT's reliably due to Untyped. 85*0b57cec5SDimitry Andric if (RCWithLargestRegsSize == nullptr) 86*0b57cec5SDimitry Andric RCWithLargestRegsSize = RC; 87*0b57cec5SDimitry Andric else if (RCWithLargestRegsSize->RSI.get(DefaultMode).SpillSize < 88*0b57cec5SDimitry Andric RC->RSI.get(DefaultMode).SpillSize) 89*0b57cec5SDimitry Andric RCWithLargestRegsSize = RC; 90*0b57cec5SDimitry Andric assert(RCWithLargestRegsSize && "RC was nullptr?"); 91*0b57cec5SDimitry Andric 92*0b57cec5SDimitry Andric RCs.emplace_back(RC); 93*0b57cec5SDimitry Andric } 94*0b57cec5SDimitry Andric 95*0b57cec5SDimitry Andric const CodeGenRegisterClass *getRCWithLargestRegsSize() const { 96*0b57cec5SDimitry Andric return RCWithLargestRegsSize; 97*0b57cec5SDimitry Andric } 98*0b57cec5SDimitry Andric 99*0b57cec5SDimitry Andric iterator_range<typename RegisterClassesTy::const_iterator> 100*0b57cec5SDimitry Andric register_classes() const { 101*0b57cec5SDimitry Andric return llvm::make_range(RCs.begin(), RCs.end()); 102*0b57cec5SDimitry Andric } 103*0b57cec5SDimitry Andric }; 104*0b57cec5SDimitry Andric 105*0b57cec5SDimitry Andric class RegisterBankEmitter { 106*0b57cec5SDimitry Andric private: 107*0b57cec5SDimitry Andric RecordKeeper &Records; 108*0b57cec5SDimitry Andric CodeGenRegBank RegisterClassHierarchy; 109*0b57cec5SDimitry Andric 110*0b57cec5SDimitry Andric void emitHeader(raw_ostream &OS, const StringRef TargetName, 111*0b57cec5SDimitry Andric const std::vector<RegisterBank> &Banks); 112*0b57cec5SDimitry Andric void emitBaseClassDefinition(raw_ostream &OS, const StringRef TargetName, 113*0b57cec5SDimitry Andric const std::vector<RegisterBank> &Banks); 114*0b57cec5SDimitry Andric void emitBaseClassImplementation(raw_ostream &OS, const StringRef TargetName, 115*0b57cec5SDimitry Andric std::vector<RegisterBank> &Banks); 116*0b57cec5SDimitry Andric 117*0b57cec5SDimitry Andric public: 118*0b57cec5SDimitry Andric RegisterBankEmitter(RecordKeeper &R) 119*0b57cec5SDimitry Andric : Records(R), RegisterClassHierarchy(Records, CodeGenHwModes(R)) {} 120*0b57cec5SDimitry Andric 121*0b57cec5SDimitry Andric void run(raw_ostream &OS); 122*0b57cec5SDimitry Andric }; 123*0b57cec5SDimitry Andric 124*0b57cec5SDimitry Andric } // end anonymous namespace 125*0b57cec5SDimitry Andric 126*0b57cec5SDimitry Andric /// Emit code to declare the ID enumeration and external global instance 127*0b57cec5SDimitry Andric /// variables. 128*0b57cec5SDimitry Andric void RegisterBankEmitter::emitHeader(raw_ostream &OS, 129*0b57cec5SDimitry Andric const StringRef TargetName, 130*0b57cec5SDimitry Andric const std::vector<RegisterBank> &Banks) { 131*0b57cec5SDimitry Andric // <Target>RegisterBankInfo.h 132*0b57cec5SDimitry Andric OS << "namespace llvm {\n" 133*0b57cec5SDimitry Andric << "namespace " << TargetName << " {\n" 134*0b57cec5SDimitry Andric << "enum {\n"; 135*0b57cec5SDimitry Andric for (const auto &Bank : Banks) 136*0b57cec5SDimitry Andric OS << " " << Bank.getEnumeratorName() << ",\n"; 137*0b57cec5SDimitry Andric OS << " NumRegisterBanks,\n" 138*0b57cec5SDimitry Andric << "};\n" 139*0b57cec5SDimitry Andric << "} // end namespace " << TargetName << "\n" 140*0b57cec5SDimitry Andric << "} // end namespace llvm\n"; 141*0b57cec5SDimitry Andric } 142*0b57cec5SDimitry Andric 143*0b57cec5SDimitry Andric /// Emit declarations of the <Target>GenRegisterBankInfo class. 144*0b57cec5SDimitry Andric void RegisterBankEmitter::emitBaseClassDefinition( 145*0b57cec5SDimitry Andric raw_ostream &OS, const StringRef TargetName, 146*0b57cec5SDimitry Andric const std::vector<RegisterBank> &Banks) { 147*0b57cec5SDimitry Andric OS << "private:\n" 148*0b57cec5SDimitry Andric << " static RegisterBank *RegBanks[];\n\n" 149*0b57cec5SDimitry Andric << "protected:\n" 150*0b57cec5SDimitry Andric << " " << TargetName << "GenRegisterBankInfo();\n" 151*0b57cec5SDimitry Andric << "\n"; 152*0b57cec5SDimitry Andric } 153*0b57cec5SDimitry Andric 154*0b57cec5SDimitry Andric /// Visit each register class belonging to the given register bank. 155*0b57cec5SDimitry Andric /// 156*0b57cec5SDimitry Andric /// A class belongs to the bank iff any of these apply: 157*0b57cec5SDimitry Andric /// * It is explicitly specified 158*0b57cec5SDimitry Andric /// * It is a subclass of a class that is a member. 159*0b57cec5SDimitry Andric /// * It is a class containing subregisters of the registers of a class that 160*0b57cec5SDimitry Andric /// is a member. This is known as a subreg-class. 161*0b57cec5SDimitry Andric /// 162*0b57cec5SDimitry Andric /// This function must be called for each explicitly specified register class. 163*0b57cec5SDimitry Andric /// 164*0b57cec5SDimitry Andric /// \param RC The register class to search. 165*0b57cec5SDimitry Andric /// \param Kind A debug string containing the path the visitor took to reach RC. 166*0b57cec5SDimitry Andric /// \param VisitFn The action to take for each class visited. It may be called 167*0b57cec5SDimitry Andric /// multiple times for a given class if there are multiple paths 168*0b57cec5SDimitry Andric /// to the class. 169*0b57cec5SDimitry Andric static void visitRegisterBankClasses( 170*0b57cec5SDimitry Andric CodeGenRegBank &RegisterClassHierarchy, const CodeGenRegisterClass *RC, 171*0b57cec5SDimitry Andric const Twine Kind, 172*0b57cec5SDimitry Andric std::function<void(const CodeGenRegisterClass *, StringRef)> VisitFn, 173*0b57cec5SDimitry Andric SmallPtrSetImpl<const CodeGenRegisterClass *> &VisitedRCs) { 174*0b57cec5SDimitry Andric 175*0b57cec5SDimitry Andric // Make sure we only visit each class once to avoid infinite loops. 176*0b57cec5SDimitry Andric if (VisitedRCs.count(RC)) 177*0b57cec5SDimitry Andric return; 178*0b57cec5SDimitry Andric VisitedRCs.insert(RC); 179*0b57cec5SDimitry Andric 180*0b57cec5SDimitry Andric // Visit each explicitly named class. 181*0b57cec5SDimitry Andric VisitFn(RC, Kind.str()); 182*0b57cec5SDimitry Andric 183*0b57cec5SDimitry Andric for (const auto &PossibleSubclass : RegisterClassHierarchy.getRegClasses()) { 184*0b57cec5SDimitry Andric std::string TmpKind = 185*0b57cec5SDimitry Andric (Twine(Kind) + " (" + PossibleSubclass.getName() + ")").str(); 186*0b57cec5SDimitry Andric 187*0b57cec5SDimitry Andric // Visit each subclass of an explicitly named class. 188*0b57cec5SDimitry Andric if (RC != &PossibleSubclass && RC->hasSubClass(&PossibleSubclass)) 189*0b57cec5SDimitry Andric visitRegisterBankClasses(RegisterClassHierarchy, &PossibleSubclass, 190*0b57cec5SDimitry Andric TmpKind + " " + RC->getName() + " subclass", 191*0b57cec5SDimitry Andric VisitFn, VisitedRCs); 192*0b57cec5SDimitry Andric 193*0b57cec5SDimitry Andric // Visit each class that contains only subregisters of RC with a common 194*0b57cec5SDimitry Andric // subregister-index. 195*0b57cec5SDimitry Andric // 196*0b57cec5SDimitry Andric // More precisely, PossibleSubclass is a subreg-class iff Reg:SubIdx is in 197*0b57cec5SDimitry Andric // PossibleSubclass for all registers Reg from RC using any 198*0b57cec5SDimitry Andric // subregister-index SubReg 199*0b57cec5SDimitry Andric for (const auto &SubIdx : RegisterClassHierarchy.getSubRegIndices()) { 200*0b57cec5SDimitry Andric BitVector BV(RegisterClassHierarchy.getRegClasses().size()); 201*0b57cec5SDimitry Andric PossibleSubclass.getSuperRegClasses(&SubIdx, BV); 202*0b57cec5SDimitry Andric if (BV.test(RC->EnumValue)) { 203*0b57cec5SDimitry Andric std::string TmpKind2 = (Twine(TmpKind) + " " + RC->getName() + 204*0b57cec5SDimitry Andric " class-with-subregs: " + RC->getName()) 205*0b57cec5SDimitry Andric .str(); 206*0b57cec5SDimitry Andric VisitFn(&PossibleSubclass, TmpKind2); 207*0b57cec5SDimitry Andric } 208*0b57cec5SDimitry Andric } 209*0b57cec5SDimitry Andric } 210*0b57cec5SDimitry Andric } 211*0b57cec5SDimitry Andric 212*0b57cec5SDimitry Andric void RegisterBankEmitter::emitBaseClassImplementation( 213*0b57cec5SDimitry Andric raw_ostream &OS, StringRef TargetName, 214*0b57cec5SDimitry Andric std::vector<RegisterBank> &Banks) { 215*0b57cec5SDimitry Andric 216*0b57cec5SDimitry Andric OS << "namespace llvm {\n" 217*0b57cec5SDimitry Andric << "namespace " << TargetName << " {\n"; 218*0b57cec5SDimitry Andric for (const auto &Bank : Banks) { 219*0b57cec5SDimitry Andric std::vector<std::vector<const CodeGenRegisterClass *>> RCsGroupedByWord( 220*0b57cec5SDimitry Andric (RegisterClassHierarchy.getRegClasses().size() + 31) / 32); 221*0b57cec5SDimitry Andric 222*0b57cec5SDimitry Andric for (const auto &RC : Bank.register_classes()) 223*0b57cec5SDimitry Andric RCsGroupedByWord[RC->EnumValue / 32].push_back(RC); 224*0b57cec5SDimitry Andric 225*0b57cec5SDimitry Andric OS << "const uint32_t " << Bank.getCoverageArrayName() << "[] = {\n"; 226*0b57cec5SDimitry Andric unsigned LowestIdxInWord = 0; 227*0b57cec5SDimitry Andric for (const auto &RCs : RCsGroupedByWord) { 228*0b57cec5SDimitry Andric OS << " // " << LowestIdxInWord << "-" << (LowestIdxInWord + 31) << "\n"; 229*0b57cec5SDimitry Andric for (const auto &RC : RCs) { 230*0b57cec5SDimitry Andric std::string QualifiedRegClassID = 231*0b57cec5SDimitry Andric (Twine(RC->Namespace) + "::" + RC->getName() + "RegClassID").str(); 232*0b57cec5SDimitry Andric OS << " (1u << (" << QualifiedRegClassID << " - " 233*0b57cec5SDimitry Andric << LowestIdxInWord << ")) |\n"; 234*0b57cec5SDimitry Andric } 235*0b57cec5SDimitry Andric OS << " 0,\n"; 236*0b57cec5SDimitry Andric LowestIdxInWord += 32; 237*0b57cec5SDimitry Andric } 238*0b57cec5SDimitry Andric OS << "};\n"; 239*0b57cec5SDimitry Andric } 240*0b57cec5SDimitry Andric OS << "\n"; 241*0b57cec5SDimitry Andric 242*0b57cec5SDimitry Andric for (const auto &Bank : Banks) { 243*0b57cec5SDimitry Andric std::string QualifiedBankID = 244*0b57cec5SDimitry Andric (TargetName + "::" + Bank.getEnumeratorName()).str(); 245*0b57cec5SDimitry Andric const CodeGenRegisterClass &RC = *Bank.getRCWithLargestRegsSize(); 246*0b57cec5SDimitry Andric unsigned Size = RC.RSI.get(DefaultMode).SpillSize; 247*0b57cec5SDimitry Andric OS << "RegisterBank " << Bank.getInstanceVarName() << "(/* ID */ " 248*0b57cec5SDimitry Andric << QualifiedBankID << ", /* Name */ \"" << Bank.getName() 249*0b57cec5SDimitry Andric << "\", /* Size */ " << Size << ", " 250*0b57cec5SDimitry Andric << "/* CoveredRegClasses */ " << Bank.getCoverageArrayName() 251*0b57cec5SDimitry Andric << ", /* NumRegClasses */ " 252*0b57cec5SDimitry Andric << RegisterClassHierarchy.getRegClasses().size() << ");\n"; 253*0b57cec5SDimitry Andric } 254*0b57cec5SDimitry Andric OS << "} // end namespace " << TargetName << "\n" 255*0b57cec5SDimitry Andric << "\n"; 256*0b57cec5SDimitry Andric 257*0b57cec5SDimitry Andric OS << "RegisterBank *" << TargetName 258*0b57cec5SDimitry Andric << "GenRegisterBankInfo::RegBanks[] = {\n"; 259*0b57cec5SDimitry Andric for (const auto &Bank : Banks) 260*0b57cec5SDimitry Andric OS << " &" << TargetName << "::" << Bank.getInstanceVarName() << ",\n"; 261*0b57cec5SDimitry Andric OS << "};\n\n"; 262*0b57cec5SDimitry Andric 263*0b57cec5SDimitry Andric OS << TargetName << "GenRegisterBankInfo::" << TargetName 264*0b57cec5SDimitry Andric << "GenRegisterBankInfo()\n" 265*0b57cec5SDimitry Andric << " : RegisterBankInfo(RegBanks, " << TargetName 266*0b57cec5SDimitry Andric << "::NumRegisterBanks) {\n" 267*0b57cec5SDimitry Andric << " // Assert that RegBank indices match their ID's\n" 268*0b57cec5SDimitry Andric << "#ifndef NDEBUG\n" 269*0b57cec5SDimitry Andric << " unsigned Index = 0;\n" 270*0b57cec5SDimitry Andric << " for (const auto &RB : RegBanks)\n" 271*0b57cec5SDimitry Andric << " assert(Index++ == RB->getID() && \"Index != ID\");\n" 272*0b57cec5SDimitry Andric << "#endif // NDEBUG\n" 273*0b57cec5SDimitry Andric << "}\n" 274*0b57cec5SDimitry Andric << "} // end namespace llvm\n"; 275*0b57cec5SDimitry Andric } 276*0b57cec5SDimitry Andric 277*0b57cec5SDimitry Andric void RegisterBankEmitter::run(raw_ostream &OS) { 278*0b57cec5SDimitry Andric std::vector<Record*> Targets = Records.getAllDerivedDefinitions("Target"); 279*0b57cec5SDimitry Andric if (Targets.size() != 1) 280*0b57cec5SDimitry Andric PrintFatalError("ERROR: Too many or too few subclasses of Target defined!"); 281*0b57cec5SDimitry Andric StringRef TargetName = Targets[0]->getName(); 282*0b57cec5SDimitry Andric 283*0b57cec5SDimitry Andric std::vector<RegisterBank> Banks; 284*0b57cec5SDimitry Andric for (const auto &V : Records.getAllDerivedDefinitions("RegisterBank")) { 285*0b57cec5SDimitry Andric SmallPtrSet<const CodeGenRegisterClass *, 8> VisitedRCs; 286*0b57cec5SDimitry Andric RegisterBank Bank(*V); 287*0b57cec5SDimitry Andric 288*0b57cec5SDimitry Andric for (const CodeGenRegisterClass *RC : 289*0b57cec5SDimitry Andric Bank.getExplictlySpecifiedRegisterClasses(RegisterClassHierarchy)) { 290*0b57cec5SDimitry Andric visitRegisterBankClasses( 291*0b57cec5SDimitry Andric RegisterClassHierarchy, RC, "explicit", 292*0b57cec5SDimitry Andric [&Bank](const CodeGenRegisterClass *RC, StringRef Kind) { 293*0b57cec5SDimitry Andric LLVM_DEBUG(dbgs() 294*0b57cec5SDimitry Andric << "Added " << RC->getName() << "(" << Kind << ")\n"); 295*0b57cec5SDimitry Andric Bank.addRegisterClass(RC); 296*0b57cec5SDimitry Andric }, 297*0b57cec5SDimitry Andric VisitedRCs); 298*0b57cec5SDimitry Andric } 299*0b57cec5SDimitry Andric 300*0b57cec5SDimitry Andric Banks.push_back(Bank); 301*0b57cec5SDimitry Andric } 302*0b57cec5SDimitry Andric 303*0b57cec5SDimitry Andric // Warn about ambiguous MIR caused by register bank/class name clashes. 304*0b57cec5SDimitry Andric for (const auto &Class : Records.getAllDerivedDefinitions("RegisterClass")) { 305*0b57cec5SDimitry Andric for (const auto &Bank : Banks) { 306*0b57cec5SDimitry Andric if (Bank.getName().lower() == Class->getName().lower()) { 307*0b57cec5SDimitry Andric PrintWarning(Bank.getDef().getLoc(), "Register bank names should be " 308*0b57cec5SDimitry Andric "distinct from register classes " 309*0b57cec5SDimitry Andric "to avoid ambiguous MIR"); 310*0b57cec5SDimitry Andric PrintNote(Bank.getDef().getLoc(), "RegisterBank was declared here"); 311*0b57cec5SDimitry Andric PrintNote(Class->getLoc(), "RegisterClass was declared here"); 312*0b57cec5SDimitry Andric } 313*0b57cec5SDimitry Andric } 314*0b57cec5SDimitry Andric } 315*0b57cec5SDimitry Andric 316*0b57cec5SDimitry Andric emitSourceFileHeader("Register Bank Source Fragments", OS); 317*0b57cec5SDimitry Andric OS << "#ifdef GET_REGBANK_DECLARATIONS\n" 318*0b57cec5SDimitry Andric << "#undef GET_REGBANK_DECLARATIONS\n"; 319*0b57cec5SDimitry Andric emitHeader(OS, TargetName, Banks); 320*0b57cec5SDimitry Andric OS << "#endif // GET_REGBANK_DECLARATIONS\n\n" 321*0b57cec5SDimitry Andric << "#ifdef GET_TARGET_REGBANK_CLASS\n" 322*0b57cec5SDimitry Andric << "#undef GET_TARGET_REGBANK_CLASS\n"; 323*0b57cec5SDimitry Andric emitBaseClassDefinition(OS, TargetName, Banks); 324*0b57cec5SDimitry Andric OS << "#endif // GET_TARGET_REGBANK_CLASS\n\n" 325*0b57cec5SDimitry Andric << "#ifdef GET_TARGET_REGBANK_IMPL\n" 326*0b57cec5SDimitry Andric << "#undef GET_TARGET_REGBANK_IMPL\n"; 327*0b57cec5SDimitry Andric emitBaseClassImplementation(OS, TargetName, Banks); 328*0b57cec5SDimitry Andric OS << "#endif // GET_TARGET_REGBANK_IMPL\n"; 329*0b57cec5SDimitry Andric } 330*0b57cec5SDimitry Andric 331*0b57cec5SDimitry Andric namespace llvm { 332*0b57cec5SDimitry Andric 333*0b57cec5SDimitry Andric void EmitRegisterBank(RecordKeeper &RK, raw_ostream &OS) { 334*0b57cec5SDimitry Andric RegisterBankEmitter(RK).run(OS); 335*0b57cec5SDimitry Andric } 336*0b57cec5SDimitry Andric 337*0b57cec5SDimitry Andric } // end namespace llvm 338