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 140b57cec5SDimitry Andric #include "llvm/ADT/BitVector.h" 150b57cec5SDimitry Andric #include "llvm/Support/Debug.h" 160b57cec5SDimitry Andric #include "llvm/TableGen/Error.h" 170b57cec5SDimitry Andric #include "llvm/TableGen/Record.h" 180b57cec5SDimitry Andric #include "llvm/TableGen/TableGenBackend.h" 190b57cec5SDimitry Andric 200b57cec5SDimitry Andric #include "CodeGenHwModes.h" 210b57cec5SDimitry Andric #include "CodeGenRegisters.h" 225ffd83dbSDimitry Andric #include "CodeGenTarget.h" 230b57cec5SDimitry Andric 240b57cec5SDimitry Andric #define DEBUG_TYPE "register-bank-emitter" 250b57cec5SDimitry Andric 260b57cec5SDimitry Andric using namespace llvm; 270b57cec5SDimitry Andric 280b57cec5SDimitry Andric namespace { 290b57cec5SDimitry Andric class RegisterBank { 300b57cec5SDimitry Andric 310b57cec5SDimitry Andric /// A vector of register classes that are included in the register bank. 320b57cec5SDimitry Andric typedef std::vector<const CodeGenRegisterClass *> RegisterClassesTy; 330b57cec5SDimitry Andric 340b57cec5SDimitry Andric private: 350b57cec5SDimitry Andric const Record &TheDef; 360b57cec5SDimitry Andric 370b57cec5SDimitry Andric /// The register classes that are covered by the register bank. 380b57cec5SDimitry Andric RegisterClassesTy RCs; 390b57cec5SDimitry Andric 400b57cec5SDimitry Andric /// The register class with the largest register size. 410b57cec5SDimitry Andric const CodeGenRegisterClass *RCWithLargestRegsSize; 420b57cec5SDimitry Andric 430b57cec5SDimitry Andric public: 440b57cec5SDimitry Andric RegisterBank(const Record &TheDef) 450b57cec5SDimitry Andric : TheDef(TheDef), RCs(), RCWithLargestRegsSize(nullptr) {} 460b57cec5SDimitry Andric 470b57cec5SDimitry Andric /// Get the human-readable name for the bank. 480b57cec5SDimitry Andric StringRef getName() const { return TheDef.getValueAsString("Name"); } 490b57cec5SDimitry Andric /// Get the name of the enumerator in the ID enumeration. 500b57cec5SDimitry Andric std::string getEnumeratorName() const { return (TheDef.getName() + "ID").str(); } 510b57cec5SDimitry Andric 520b57cec5SDimitry Andric /// Get the name of the array holding the register class coverage data; 530b57cec5SDimitry Andric std::string getCoverageArrayName() const { 540b57cec5SDimitry Andric return (TheDef.getName() + "CoverageData").str(); 550b57cec5SDimitry Andric } 560b57cec5SDimitry Andric 570b57cec5SDimitry Andric /// Get the name of the global instance variable. 580b57cec5SDimitry Andric StringRef getInstanceVarName() const { return TheDef.getName(); } 590b57cec5SDimitry Andric 600b57cec5SDimitry Andric const Record &getDef() const { return TheDef; } 610b57cec5SDimitry Andric 620b57cec5SDimitry Andric /// Get the register classes listed in the RegisterBank.RegisterClasses field. 630b57cec5SDimitry Andric std::vector<const CodeGenRegisterClass *> 645ffd83dbSDimitry Andric getExplicitlySpecifiedRegisterClasses( 655ffd83dbSDimitry Andric const CodeGenRegBank &RegisterClassHierarchy) const { 660b57cec5SDimitry Andric std::vector<const CodeGenRegisterClass *> RCs; 675ffd83dbSDimitry Andric for (const auto *RCDef : getDef().getValueAsListOfDefs("RegisterClasses")) 680b57cec5SDimitry Andric RCs.push_back(RegisterClassHierarchy.getRegClass(RCDef)); 690b57cec5SDimitry Andric return RCs; 700b57cec5SDimitry Andric } 710b57cec5SDimitry Andric 720b57cec5SDimitry Andric /// Add a register class to the bank without duplicates. 730b57cec5SDimitry Andric void addRegisterClass(const CodeGenRegisterClass *RC) { 74*e8d8bef9SDimitry Andric if (llvm::is_contained(RCs, RC)) 750b57cec5SDimitry Andric return; 760b57cec5SDimitry Andric 770b57cec5SDimitry Andric // FIXME? We really want the register size rather than the spill size 780b57cec5SDimitry Andric // since the spill size may be bigger on some targets with 790b57cec5SDimitry Andric // limited load/store instructions. However, we don't store the 800b57cec5SDimitry Andric // register size anywhere (we could sum the sizes of the subregisters 810b57cec5SDimitry Andric // but there may be additional bits too) and we can't derive it from 820b57cec5SDimitry Andric // the VT's reliably due to Untyped. 830b57cec5SDimitry Andric if (RCWithLargestRegsSize == nullptr) 840b57cec5SDimitry Andric RCWithLargestRegsSize = RC; 850b57cec5SDimitry Andric else if (RCWithLargestRegsSize->RSI.get(DefaultMode).SpillSize < 860b57cec5SDimitry Andric RC->RSI.get(DefaultMode).SpillSize) 870b57cec5SDimitry Andric RCWithLargestRegsSize = RC; 880b57cec5SDimitry Andric assert(RCWithLargestRegsSize && "RC was nullptr?"); 890b57cec5SDimitry Andric 900b57cec5SDimitry Andric RCs.emplace_back(RC); 910b57cec5SDimitry Andric } 920b57cec5SDimitry Andric 930b57cec5SDimitry Andric const CodeGenRegisterClass *getRCWithLargestRegsSize() const { 940b57cec5SDimitry Andric return RCWithLargestRegsSize; 950b57cec5SDimitry Andric } 960b57cec5SDimitry Andric 970b57cec5SDimitry Andric iterator_range<typename RegisterClassesTy::const_iterator> 980b57cec5SDimitry Andric register_classes() const { 990b57cec5SDimitry Andric return llvm::make_range(RCs.begin(), RCs.end()); 1000b57cec5SDimitry Andric } 1010b57cec5SDimitry Andric }; 1020b57cec5SDimitry Andric 1030b57cec5SDimitry Andric class RegisterBankEmitter { 1040b57cec5SDimitry Andric private: 1055ffd83dbSDimitry Andric CodeGenTarget Target; 1060b57cec5SDimitry Andric RecordKeeper &Records; 1070b57cec5SDimitry Andric 1080b57cec5SDimitry Andric void emitHeader(raw_ostream &OS, const StringRef TargetName, 1090b57cec5SDimitry Andric const std::vector<RegisterBank> &Banks); 1100b57cec5SDimitry Andric void emitBaseClassDefinition(raw_ostream &OS, const StringRef TargetName, 1110b57cec5SDimitry Andric const std::vector<RegisterBank> &Banks); 1120b57cec5SDimitry Andric void emitBaseClassImplementation(raw_ostream &OS, const StringRef TargetName, 1130b57cec5SDimitry Andric std::vector<RegisterBank> &Banks); 1140b57cec5SDimitry Andric 1150b57cec5SDimitry Andric public: 1165ffd83dbSDimitry Andric RegisterBankEmitter(RecordKeeper &R) : Target(R), Records(R) {} 1170b57cec5SDimitry Andric 1180b57cec5SDimitry Andric void run(raw_ostream &OS); 1190b57cec5SDimitry Andric }; 1200b57cec5SDimitry Andric 1210b57cec5SDimitry Andric } // end anonymous namespace 1220b57cec5SDimitry Andric 1230b57cec5SDimitry Andric /// Emit code to declare the ID enumeration and external global instance 1240b57cec5SDimitry Andric /// variables. 1250b57cec5SDimitry Andric void RegisterBankEmitter::emitHeader(raw_ostream &OS, 1260b57cec5SDimitry Andric const StringRef TargetName, 1270b57cec5SDimitry Andric const std::vector<RegisterBank> &Banks) { 1280b57cec5SDimitry Andric // <Target>RegisterBankInfo.h 1290b57cec5SDimitry Andric OS << "namespace llvm {\n" 1300b57cec5SDimitry Andric << "namespace " << TargetName << " {\n" 131*e8d8bef9SDimitry Andric << "enum : unsigned {\n"; 132*e8d8bef9SDimitry Andric 133*e8d8bef9SDimitry Andric OS << " InvalidRegBankID = ~0u,\n"; 134*e8d8bef9SDimitry Andric unsigned ID = 0; 1350b57cec5SDimitry Andric for (const auto &Bank : Banks) 136*e8d8bef9SDimitry Andric OS << " " << Bank.getEnumeratorName() << " = " << ID++ << ",\n"; 1370b57cec5SDimitry Andric OS << " NumRegisterBanks,\n" 1380b57cec5SDimitry Andric << "};\n" 1390b57cec5SDimitry Andric << "} // end namespace " << TargetName << "\n" 1400b57cec5SDimitry Andric << "} // end namespace llvm\n"; 1410b57cec5SDimitry Andric } 1420b57cec5SDimitry Andric 1430b57cec5SDimitry Andric /// Emit declarations of the <Target>GenRegisterBankInfo class. 1440b57cec5SDimitry Andric void RegisterBankEmitter::emitBaseClassDefinition( 1450b57cec5SDimitry Andric raw_ostream &OS, const StringRef TargetName, 1460b57cec5SDimitry Andric const std::vector<RegisterBank> &Banks) { 1470b57cec5SDimitry Andric OS << "private:\n" 1480b57cec5SDimitry Andric << " static RegisterBank *RegBanks[];\n\n" 1490b57cec5SDimitry Andric << "protected:\n" 1500b57cec5SDimitry Andric << " " << TargetName << "GenRegisterBankInfo();\n" 1510b57cec5SDimitry Andric << "\n"; 1520b57cec5SDimitry Andric } 1530b57cec5SDimitry Andric 1540b57cec5SDimitry Andric /// Visit each register class belonging to the given register bank. 1550b57cec5SDimitry Andric /// 1560b57cec5SDimitry Andric /// A class belongs to the bank iff any of these apply: 1570b57cec5SDimitry Andric /// * It is explicitly specified 1580b57cec5SDimitry Andric /// * It is a subclass of a class that is a member. 1590b57cec5SDimitry Andric /// * It is a class containing subregisters of the registers of a class that 1600b57cec5SDimitry Andric /// is a member. This is known as a subreg-class. 1610b57cec5SDimitry Andric /// 1620b57cec5SDimitry Andric /// This function must be called for each explicitly specified register class. 1630b57cec5SDimitry Andric /// 1640b57cec5SDimitry Andric /// \param RC The register class to search. 1650b57cec5SDimitry Andric /// \param Kind A debug string containing the path the visitor took to reach RC. 1660b57cec5SDimitry Andric /// \param VisitFn The action to take for each class visited. It may be called 1670b57cec5SDimitry Andric /// multiple times for a given class if there are multiple paths 1680b57cec5SDimitry Andric /// to the class. 1690b57cec5SDimitry Andric static void visitRegisterBankClasses( 1705ffd83dbSDimitry Andric const CodeGenRegBank &RegisterClassHierarchy, 171*e8d8bef9SDimitry Andric const CodeGenRegisterClass *RC, const Twine &Kind, 1720b57cec5SDimitry Andric std::function<void(const CodeGenRegisterClass *, StringRef)> VisitFn, 1730b57cec5SDimitry Andric SmallPtrSetImpl<const CodeGenRegisterClass *> &VisitedRCs) { 1740b57cec5SDimitry Andric 1750b57cec5SDimitry Andric // Make sure we only visit each class once to avoid infinite loops. 1760b57cec5SDimitry Andric if (VisitedRCs.count(RC)) 1770b57cec5SDimitry Andric return; 1780b57cec5SDimitry Andric VisitedRCs.insert(RC); 1790b57cec5SDimitry Andric 1800b57cec5SDimitry Andric // Visit each explicitly named class. 1810b57cec5SDimitry Andric VisitFn(RC, Kind.str()); 1820b57cec5SDimitry Andric 1830b57cec5SDimitry Andric for (const auto &PossibleSubclass : RegisterClassHierarchy.getRegClasses()) { 1840b57cec5SDimitry Andric std::string TmpKind = 185*e8d8bef9SDimitry Andric (Kind + " (" + PossibleSubclass.getName() + ")").str(); 1860b57cec5SDimitry Andric 1870b57cec5SDimitry Andric // Visit each subclass of an explicitly named class. 1880b57cec5SDimitry Andric if (RC != &PossibleSubclass && RC->hasSubClass(&PossibleSubclass)) 1890b57cec5SDimitry Andric visitRegisterBankClasses(RegisterClassHierarchy, &PossibleSubclass, 1900b57cec5SDimitry Andric TmpKind + " " + RC->getName() + " subclass", 1910b57cec5SDimitry Andric VisitFn, VisitedRCs); 1920b57cec5SDimitry Andric 1930b57cec5SDimitry Andric // Visit each class that contains only subregisters of RC with a common 1940b57cec5SDimitry Andric // subregister-index. 1950b57cec5SDimitry Andric // 1960b57cec5SDimitry Andric // More precisely, PossibleSubclass is a subreg-class iff Reg:SubIdx is in 1970b57cec5SDimitry Andric // PossibleSubclass for all registers Reg from RC using any 1980b57cec5SDimitry Andric // subregister-index SubReg 1990b57cec5SDimitry Andric for (const auto &SubIdx : RegisterClassHierarchy.getSubRegIndices()) { 2000b57cec5SDimitry Andric BitVector BV(RegisterClassHierarchy.getRegClasses().size()); 2010b57cec5SDimitry Andric PossibleSubclass.getSuperRegClasses(&SubIdx, BV); 2020b57cec5SDimitry Andric if (BV.test(RC->EnumValue)) { 2030b57cec5SDimitry Andric std::string TmpKind2 = (Twine(TmpKind) + " " + RC->getName() + 2040b57cec5SDimitry Andric " class-with-subregs: " + RC->getName()) 2050b57cec5SDimitry Andric .str(); 2060b57cec5SDimitry Andric VisitFn(&PossibleSubclass, TmpKind2); 2070b57cec5SDimitry Andric } 2080b57cec5SDimitry Andric } 2090b57cec5SDimitry Andric } 2100b57cec5SDimitry Andric } 2110b57cec5SDimitry Andric 2120b57cec5SDimitry Andric void RegisterBankEmitter::emitBaseClassImplementation( 2130b57cec5SDimitry Andric raw_ostream &OS, StringRef TargetName, 2140b57cec5SDimitry Andric std::vector<RegisterBank> &Banks) { 2155ffd83dbSDimitry Andric const CodeGenRegBank &RegisterClassHierarchy = Target.getRegBank(); 2160b57cec5SDimitry Andric 2170b57cec5SDimitry Andric OS << "namespace llvm {\n" 2180b57cec5SDimitry Andric << "namespace " << TargetName << " {\n"; 2190b57cec5SDimitry Andric for (const auto &Bank : Banks) { 2200b57cec5SDimitry Andric std::vector<std::vector<const CodeGenRegisterClass *>> RCsGroupedByWord( 2210b57cec5SDimitry Andric (RegisterClassHierarchy.getRegClasses().size() + 31) / 32); 2220b57cec5SDimitry Andric 2230b57cec5SDimitry Andric for (const auto &RC : Bank.register_classes()) 2240b57cec5SDimitry Andric RCsGroupedByWord[RC->EnumValue / 32].push_back(RC); 2250b57cec5SDimitry Andric 2260b57cec5SDimitry Andric OS << "const uint32_t " << Bank.getCoverageArrayName() << "[] = {\n"; 2270b57cec5SDimitry Andric unsigned LowestIdxInWord = 0; 2280b57cec5SDimitry Andric for (const auto &RCs : RCsGroupedByWord) { 2290b57cec5SDimitry Andric OS << " // " << LowestIdxInWord << "-" << (LowestIdxInWord + 31) << "\n"; 2300b57cec5SDimitry Andric for (const auto &RC : RCs) { 2310b57cec5SDimitry Andric std::string QualifiedRegClassID = 2320b57cec5SDimitry Andric (Twine(RC->Namespace) + "::" + RC->getName() + "RegClassID").str(); 2330b57cec5SDimitry Andric OS << " (1u << (" << QualifiedRegClassID << " - " 2340b57cec5SDimitry Andric << LowestIdxInWord << ")) |\n"; 2350b57cec5SDimitry Andric } 2360b57cec5SDimitry Andric OS << " 0,\n"; 2370b57cec5SDimitry Andric LowestIdxInWord += 32; 2380b57cec5SDimitry Andric } 2390b57cec5SDimitry Andric OS << "};\n"; 2400b57cec5SDimitry Andric } 2410b57cec5SDimitry Andric OS << "\n"; 2420b57cec5SDimitry Andric 2430b57cec5SDimitry Andric for (const auto &Bank : Banks) { 2440b57cec5SDimitry Andric std::string QualifiedBankID = 2450b57cec5SDimitry Andric (TargetName + "::" + Bank.getEnumeratorName()).str(); 2460b57cec5SDimitry Andric const CodeGenRegisterClass &RC = *Bank.getRCWithLargestRegsSize(); 2470b57cec5SDimitry Andric unsigned Size = RC.RSI.get(DefaultMode).SpillSize; 2480b57cec5SDimitry Andric OS << "RegisterBank " << Bank.getInstanceVarName() << "(/* ID */ " 2490b57cec5SDimitry Andric << QualifiedBankID << ", /* Name */ \"" << Bank.getName() 2500b57cec5SDimitry Andric << "\", /* Size */ " << Size << ", " 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 2580b57cec5SDimitry Andric OS << "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 2640b57cec5SDimitry Andric OS << TargetName << "GenRegisterBankInfo::" << TargetName 2650b57cec5SDimitry Andric << "GenRegisterBankInfo()\n" 2660b57cec5SDimitry Andric << " : RegisterBankInfo(RegBanks, " << TargetName 2670b57cec5SDimitry Andric << "::NumRegisterBanks) {\n" 2680b57cec5SDimitry Andric << " // Assert that RegBank indices match their ID's\n" 2690b57cec5SDimitry Andric << "#ifndef NDEBUG\n" 2700b57cec5SDimitry Andric << " unsigned Index = 0;\n" 2710b57cec5SDimitry Andric << " for (const auto &RB : RegBanks)\n" 2720b57cec5SDimitry Andric << " assert(Index++ == RB->getID() && \"Index != ID\");\n" 2730b57cec5SDimitry Andric << "#endif // NDEBUG\n" 2740b57cec5SDimitry Andric << "}\n" 2750b57cec5SDimitry Andric << "} // end namespace llvm\n"; 2760b57cec5SDimitry Andric } 2770b57cec5SDimitry Andric 2780b57cec5SDimitry Andric void RegisterBankEmitter::run(raw_ostream &OS) { 2795ffd83dbSDimitry Andric StringRef TargetName = Target.getName(); 2805ffd83dbSDimitry Andric const CodeGenRegBank &RegisterClassHierarchy = Target.getRegBank(); 2810b57cec5SDimitry Andric 282*e8d8bef9SDimitry Andric Records.startTimer("Analyze records"); 2830b57cec5SDimitry Andric std::vector<RegisterBank> Banks; 2840b57cec5SDimitry Andric for (const auto &V : Records.getAllDerivedDefinitions("RegisterBank")) { 2850b57cec5SDimitry Andric SmallPtrSet<const CodeGenRegisterClass *, 8> VisitedRCs; 2860b57cec5SDimitry Andric RegisterBank Bank(*V); 2870b57cec5SDimitry Andric 2880b57cec5SDimitry Andric for (const CodeGenRegisterClass *RC : 2895ffd83dbSDimitry Andric Bank.getExplicitlySpecifiedRegisterClasses(RegisterClassHierarchy)) { 2900b57cec5SDimitry Andric visitRegisterBankClasses( 2910b57cec5SDimitry Andric RegisterClassHierarchy, RC, "explicit", 2920b57cec5SDimitry Andric [&Bank](const CodeGenRegisterClass *RC, StringRef Kind) { 2930b57cec5SDimitry Andric LLVM_DEBUG(dbgs() 2940b57cec5SDimitry Andric << "Added " << RC->getName() << "(" << Kind << ")\n"); 2950b57cec5SDimitry Andric Bank.addRegisterClass(RC); 2960b57cec5SDimitry Andric }, 2970b57cec5SDimitry Andric VisitedRCs); 2980b57cec5SDimitry Andric } 2990b57cec5SDimitry Andric 3000b57cec5SDimitry Andric Banks.push_back(Bank); 3010b57cec5SDimitry Andric } 3020b57cec5SDimitry Andric 3030b57cec5SDimitry Andric // Warn about ambiguous MIR caused by register bank/class name clashes. 304*e8d8bef9SDimitry Andric Records.startTimer("Warn ambiguous"); 3055ffd83dbSDimitry Andric for (const auto &Class : RegisterClassHierarchy.getRegClasses()) { 3060b57cec5SDimitry Andric for (const auto &Bank : Banks) { 3075ffd83dbSDimitry Andric if (Bank.getName().lower() == StringRef(Class.getName()).lower()) { 3080b57cec5SDimitry Andric PrintWarning(Bank.getDef().getLoc(), "Register bank names should be " 3090b57cec5SDimitry Andric "distinct from register classes " 3100b57cec5SDimitry Andric "to avoid ambiguous MIR"); 3110b57cec5SDimitry Andric PrintNote(Bank.getDef().getLoc(), "RegisterBank was declared here"); 3125ffd83dbSDimitry Andric PrintNote(Class.getDef()->getLoc(), "RegisterClass was declared here"); 3130b57cec5SDimitry Andric } 3140b57cec5SDimitry Andric } 3150b57cec5SDimitry Andric } 3160b57cec5SDimitry Andric 317*e8d8bef9SDimitry Andric Records.startTimer("Emit output"); 3180b57cec5SDimitry Andric emitSourceFileHeader("Register Bank Source Fragments", OS); 3190b57cec5SDimitry Andric OS << "#ifdef GET_REGBANK_DECLARATIONS\n" 3200b57cec5SDimitry Andric << "#undef GET_REGBANK_DECLARATIONS\n"; 3210b57cec5SDimitry Andric emitHeader(OS, TargetName, Banks); 3220b57cec5SDimitry Andric OS << "#endif // GET_REGBANK_DECLARATIONS\n\n" 3230b57cec5SDimitry Andric << "#ifdef GET_TARGET_REGBANK_CLASS\n" 3240b57cec5SDimitry Andric << "#undef GET_TARGET_REGBANK_CLASS\n"; 3250b57cec5SDimitry Andric emitBaseClassDefinition(OS, TargetName, Banks); 3260b57cec5SDimitry Andric OS << "#endif // GET_TARGET_REGBANK_CLASS\n\n" 3270b57cec5SDimitry Andric << "#ifdef GET_TARGET_REGBANK_IMPL\n" 3280b57cec5SDimitry Andric << "#undef GET_TARGET_REGBANK_IMPL\n"; 3290b57cec5SDimitry Andric emitBaseClassImplementation(OS, TargetName, Banks); 3300b57cec5SDimitry Andric OS << "#endif // GET_TARGET_REGBANK_IMPL\n"; 3310b57cec5SDimitry Andric } 3320b57cec5SDimitry Andric 3330b57cec5SDimitry Andric namespace llvm { 3340b57cec5SDimitry Andric 3350b57cec5SDimitry Andric void EmitRegisterBank(RecordKeeper &RK, raw_ostream &OS) { 3360b57cec5SDimitry Andric RegisterBankEmitter(RK).run(OS); 3370b57cec5SDimitry Andric } 3380b57cec5SDimitry Andric 3390b57cec5SDimitry Andric } // end namespace llvm 340