Home | History | Annotate | Download | only in TableGen
      1 //===- SubtargetEmitter.cpp - Generate subtarget enumerations -------------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 // This tablegen backend emits subtarget enumerations.
     11 //
     12 //===----------------------------------------------------------------------===//
     13 
     14 #include "SubtargetEmitter.h"
     15 #include "CodeGenTarget.h"
     16 #include "llvm/TableGen/Record.h"
     17 #include "llvm/ADT/StringExtras.h"
     18 #include "llvm/Support/Debug.h"
     19 #include <algorithm>
     20 using namespace llvm;
     21 
     22 //
     23 // Enumeration - Emit the specified class as an enumeration.
     24 //
     25 void SubtargetEmitter::Enumeration(raw_ostream &OS,
     26                                    const char *ClassName,
     27                                    bool isBits) {
     28   // Get all records of class and sort
     29   std::vector<Record*> DefList = Records.getAllDerivedDefinitions(ClassName);
     30   std::sort(DefList.begin(), DefList.end(), LessRecord());
     31 
     32   unsigned N = DefList.size();
     33   if (N == 0)
     34     return;
     35   if (N > 64) {
     36     errs() << "Too many (> 64) subtarget features!\n";
     37     exit(1);
     38   }
     39 
     40   OS << "namespace " << Target << " {\n";
     41 
     42   // Open enumeration
     43   OS << "enum {\n";
     44 
     45   // For each record
     46   for (unsigned i = 0; i < N;) {
     47     // Next record
     48     Record *Def = DefList[i];
     49 
     50     // Get and emit name
     51     OS << "  " << Def->getName();
     52 
     53     // If bit flags then emit expression (1 << i)
     54     if (isBits)  OS << " = " << " 1ULL << " << i;
     55 
     56     // Depending on 'if more in the list' emit comma
     57     if (++i < N) OS << ",";
     58 
     59     OS << "\n";
     60   }
     61 
     62   // Close enumeration
     63   OS << "};\n";
     64 
     65   OS << "}\n";
     66 }
     67 
     68 //
     69 // FeatureKeyValues - Emit data of all the subtarget features.  Used by the
     70 // command line.
     71 //
     72 unsigned SubtargetEmitter::FeatureKeyValues(raw_ostream &OS) {
     73   // Gather and sort all the features
     74   std::vector<Record*> FeatureList =
     75                            Records.getAllDerivedDefinitions("SubtargetFeature");
     76 
     77   if (FeatureList.empty())
     78     return 0;
     79 
     80   std::sort(FeatureList.begin(), FeatureList.end(), LessRecordFieldName());
     81 
     82   // Begin feature table
     83   OS << "// Sorted (by key) array of values for CPU features.\n"
     84      << "llvm::SubtargetFeatureKV " << Target << "FeatureKV[] = {\n";
     85 
     86   // For each feature
     87   unsigned NumFeatures = 0;
     88   for (unsigned i = 0, N = FeatureList.size(); i < N; ++i) {
     89     // Next feature
     90     Record *Feature = FeatureList[i];
     91 
     92     const std::string &Name = Feature->getName();
     93     const std::string &CommandLineName = Feature->getValueAsString("Name");
     94     const std::string &Desc = Feature->getValueAsString("Desc");
     95 
     96     if (CommandLineName.empty()) continue;
     97 
     98     // Emit as { "feature", "description", featureEnum, i1 | i2 | ... | in }
     99     OS << "  { "
    100        << "\"" << CommandLineName << "\", "
    101        << "\"" << Desc << "\", "
    102        << Target << "::" << Name << ", ";
    103 
    104     const std::vector<Record*> &ImpliesList =
    105       Feature->getValueAsListOfDefs("Implies");
    106 
    107     if (ImpliesList.empty()) {
    108       OS << "0ULL";
    109     } else {
    110       for (unsigned j = 0, M = ImpliesList.size(); j < M;) {
    111         OS << Target << "::" << ImpliesList[j]->getName();
    112         if (++j < M) OS << " | ";
    113       }
    114     }
    115 
    116     OS << " }";
    117     ++NumFeatures;
    118 
    119     // Depending on 'if more in the list' emit comma
    120     if ((i + 1) < N) OS << ",";
    121 
    122     OS << "\n";
    123   }
    124 
    125   // End feature table
    126   OS << "};\n";
    127 
    128   return NumFeatures;
    129 }
    130 
    131 //
    132 // CPUKeyValues - Emit data of all the subtarget processors.  Used by command
    133 // line.
    134 //
    135 unsigned SubtargetEmitter::CPUKeyValues(raw_ostream &OS) {
    136   // Gather and sort processor information
    137   std::vector<Record*> ProcessorList =
    138                           Records.getAllDerivedDefinitions("Processor");
    139   std::sort(ProcessorList.begin(), ProcessorList.end(), LessRecordFieldName());
    140 
    141   // Begin processor table
    142   OS << "// Sorted (by key) array of values for CPU subtype.\n"
    143      << "llvm::SubtargetFeatureKV " << Target << "SubTypeKV[] = {\n";
    144 
    145   // For each processor
    146   for (unsigned i = 0, N = ProcessorList.size(); i < N;) {
    147     // Next processor
    148     Record *Processor = ProcessorList[i];
    149 
    150     const std::string &Name = Processor->getValueAsString("Name");
    151     const std::vector<Record*> &FeatureList =
    152       Processor->getValueAsListOfDefs("Features");
    153 
    154     // Emit as { "cpu", "description", f1 | f2 | ... fn },
    155     OS << "  { "
    156        << "\"" << Name << "\", "
    157        << "\"Select the " << Name << " processor\", ";
    158 
    159     if (FeatureList.empty()) {
    160       OS << "0ULL";
    161     } else {
    162       for (unsigned j = 0, M = FeatureList.size(); j < M;) {
    163         OS << Target << "::" << FeatureList[j]->getName();
    164         if (++j < M) OS << " | ";
    165       }
    166     }
    167 
    168     // The "0" is for the "implies" section of this data structure.
    169     OS << ", 0ULL }";
    170 
    171     // Depending on 'if more in the list' emit comma
    172     if (++i < N) OS << ",";
    173 
    174     OS << "\n";
    175   }
    176 
    177   // End processor table
    178   OS << "};\n";
    179 
    180   return ProcessorList.size();
    181 }
    182 
    183 //
    184 // CollectAllItinClasses - Gathers and enumerates all the itinerary classes.
    185 // Returns itinerary class count.
    186 //
    187 unsigned SubtargetEmitter::
    188 CollectAllItinClasses(raw_ostream &OS,
    189                       std::map<std::string, unsigned> &ItinClassesMap,
    190                       std::vector<Record*> &ItinClassList) {
    191   // For each itinerary class
    192   unsigned N = ItinClassList.size();
    193   for (unsigned i = 0; i < N; i++) {
    194     // Next itinerary class
    195     const Record *ItinClass = ItinClassList[i];
    196     // Get name of itinerary class
    197     // Assign itinerary class a unique number
    198     ItinClassesMap[ItinClass->getName()] = i;
    199   }
    200 
    201   // Return itinerary class count
    202   return N;
    203 }
    204 
    205 //
    206 // FormItineraryStageString - Compose a string containing the stage
    207 // data initialization for the specified itinerary.  N is the number
    208 // of stages.
    209 //
    210 void SubtargetEmitter::FormItineraryStageString(const std::string &Name,
    211                                                 Record *ItinData,
    212                                                 std::string &ItinString,
    213                                                 unsigned &NStages) {
    214   // Get states list
    215   const std::vector<Record*> &StageList =
    216     ItinData->getValueAsListOfDefs("Stages");
    217 
    218   // For each stage
    219   unsigned N = NStages = StageList.size();
    220   for (unsigned i = 0; i < N;) {
    221     // Next stage
    222     const Record *Stage = StageList[i];
    223 
    224     // Form string as ,{ cycles, u1 | u2 | ... | un, timeinc, kind }
    225     int Cycles = Stage->getValueAsInt("Cycles");
    226     ItinString += "  { " + itostr(Cycles) + ", ";
    227 
    228     // Get unit list
    229     const std::vector<Record*> &UnitList = Stage->getValueAsListOfDefs("Units");
    230 
    231     // For each unit
    232     for (unsigned j = 0, M = UnitList.size(); j < M;) {
    233       // Add name and bitwise or
    234       ItinString += Name + "FU::" + UnitList[j]->getName();
    235       if (++j < M) ItinString += " | ";
    236     }
    237 
    238     int TimeInc = Stage->getValueAsInt("TimeInc");
    239     ItinString += ", " + itostr(TimeInc);
    240 
    241     int Kind = Stage->getValueAsInt("Kind");
    242     ItinString += ", (llvm::InstrStage::ReservationKinds)" + itostr(Kind);
    243 
    244     // Close off stage
    245     ItinString += " }";
    246     if (++i < N) ItinString += ", ";
    247   }
    248 }
    249 
    250 //
    251 // FormItineraryOperandCycleString - Compose a string containing the
    252 // operand cycle initialization for the specified itinerary.  N is the
    253 // number of operands that has cycles specified.
    254 //
    255 void SubtargetEmitter::FormItineraryOperandCycleString(Record *ItinData,
    256                          std::string &ItinString, unsigned &NOperandCycles) {
    257   // Get operand cycle list
    258   const std::vector<int64_t> &OperandCycleList =
    259     ItinData->getValueAsListOfInts("OperandCycles");
    260 
    261   // For each operand cycle
    262   unsigned N = NOperandCycles = OperandCycleList.size();
    263   for (unsigned i = 0; i < N;) {
    264     // Next operand cycle
    265     const int OCycle = OperandCycleList[i];
    266 
    267     ItinString += "  " + itostr(OCycle);
    268     if (++i < N) ItinString += ", ";
    269   }
    270 }
    271 
    272 void SubtargetEmitter::FormItineraryBypassString(const std::string &Name,
    273                                                  Record *ItinData,
    274                                                  std::string &ItinString,
    275                                                  unsigned NOperandCycles) {
    276   const std::vector<Record*> &BypassList =
    277     ItinData->getValueAsListOfDefs("Bypasses");
    278   unsigned N = BypassList.size();
    279   unsigned i = 0;
    280   for (; i < N;) {
    281     ItinString += Name + "Bypass::" + BypassList[i]->getName();
    282     if (++i < NOperandCycles) ItinString += ", ";
    283   }
    284   for (; i < NOperandCycles;) {
    285     ItinString += " 0";
    286     if (++i < NOperandCycles) ItinString += ", ";
    287   }
    288 }
    289 
    290 //
    291 // EmitStageAndOperandCycleData - Generate unique itinerary stages and
    292 // operand cycle tables.  Record itineraries for processors.
    293 //
    294 void SubtargetEmitter::EmitStageAndOperandCycleData(raw_ostream &OS,
    295        unsigned NItinClasses,
    296        std::map<std::string, unsigned> &ItinClassesMap,
    297        std::vector<Record*> &ItinClassList,
    298        std::vector<std::vector<InstrItinerary> > &ProcList) {
    299   // Gather processor iteraries
    300   std::vector<Record*> ProcItinList =
    301                        Records.getAllDerivedDefinitions("ProcessorItineraries");
    302 
    303   // If just no itinerary then don't bother
    304   if (ProcItinList.size() < 2) return;
    305 
    306   // Emit functional units for all the itineraries.
    307   for (unsigned i = 0, N = ProcItinList.size(); i < N; ++i) {
    308     // Next record
    309     Record *Proc = ProcItinList[i];
    310 
    311     std::vector<Record*> FUs = Proc->getValueAsListOfDefs("FU");
    312     if (FUs.empty())
    313       continue;
    314 
    315     const std::string &Name = Proc->getName();
    316     OS << "\n// Functional units for itineraries \"" << Name << "\"\n"
    317        << "namespace " << Name << "FU {\n";
    318 
    319     for (unsigned j = 0, FUN = FUs.size(); j < FUN; ++j)
    320       OS << "  const unsigned " << FUs[j]->getName()
    321          << " = 1 << " << j << ";\n";
    322 
    323     OS << "}\n";
    324 
    325     std::vector<Record*> BPs = Proc->getValueAsListOfDefs("BP");
    326     if (BPs.size()) {
    327       OS << "\n// Pipeline forwarding pathes for itineraries \"" << Name
    328          << "\"\n" << "namespace " << Name << "Bypass {\n";
    329 
    330       OS << "  unsigned NoBypass = 0;\n";
    331       for (unsigned j = 0, BPN = BPs.size(); j < BPN; ++j)
    332         OS << "  unsigned " << BPs[j]->getName()
    333            << " = 1 << " << j << ";\n";
    334 
    335       OS << "}\n";
    336     }
    337   }
    338 
    339   // Begin stages table
    340   std::string StageTable = "\nllvm::InstrStage " + Target + "Stages[] = {\n";
    341   StageTable += "  { 0, 0, 0, llvm::InstrStage::Required }, // No itinerary\n";
    342 
    343   // Begin operand cycle table
    344   std::string OperandCycleTable = "unsigned " + Target +
    345     "OperandCycles[] = {\n";
    346   OperandCycleTable += "  0, // No itinerary\n";
    347 
    348   // Begin pipeline bypass table
    349   std::string BypassTable = "unsigned " + Target +
    350     "ForwardingPathes[] = {\n";
    351   BypassTable += "  0, // No itinerary\n";
    352 
    353   unsigned StageCount = 1, OperandCycleCount = 1;
    354   std::map<std::string, unsigned> ItinStageMap, ItinOperandMap;
    355   for (unsigned i = 0, N = ProcItinList.size(); i < N; i++) {
    356     // Next record
    357     Record *Proc = ProcItinList[i];
    358 
    359     // Get processor itinerary name
    360     const std::string &Name = Proc->getName();
    361 
    362     // Skip default
    363     if (Name == "NoItineraries") continue;
    364 
    365     // Create and expand processor itinerary to cover all itinerary classes
    366     std::vector<InstrItinerary> ItinList;
    367     ItinList.resize(NItinClasses);
    368 
    369     // Get itinerary data list
    370     std::vector<Record*> ItinDataList = Proc->getValueAsListOfDefs("IID");
    371 
    372     // For each itinerary data
    373     for (unsigned j = 0, M = ItinDataList.size(); j < M; j++) {
    374       // Next itinerary data
    375       Record *ItinData = ItinDataList[j];
    376 
    377       // Get string and stage count
    378       std::string ItinStageString;
    379       unsigned NStages;
    380       FormItineraryStageString(Name, ItinData, ItinStageString, NStages);
    381 
    382       // Get string and operand cycle count
    383       std::string ItinOperandCycleString;
    384       unsigned NOperandCycles;
    385       FormItineraryOperandCycleString(ItinData, ItinOperandCycleString,
    386                                       NOperandCycles);
    387 
    388       std::string ItinBypassString;
    389       FormItineraryBypassString(Name, ItinData, ItinBypassString,
    390                                 NOperandCycles);
    391 
    392       // Check to see if stage already exists and create if it doesn't
    393       unsigned FindStage = 0;
    394       if (NStages > 0) {
    395         FindStage = ItinStageMap[ItinStageString];
    396         if (FindStage == 0) {
    397           // Emit as { cycles, u1 | u2 | ... | un, timeinc }, // indices
    398           StageTable += ItinStageString + ", // " + itostr(StageCount);
    399           if (NStages > 1)
    400             StageTable += "-" + itostr(StageCount + NStages - 1);
    401           StageTable += "\n";
    402           // Record Itin class number.
    403           ItinStageMap[ItinStageString] = FindStage = StageCount;
    404           StageCount += NStages;
    405         }
    406       }
    407 
    408       // Check to see if operand cycle already exists and create if it doesn't
    409       unsigned FindOperandCycle = 0;
    410       if (NOperandCycles > 0) {
    411         std::string ItinOperandString = ItinOperandCycleString+ItinBypassString;
    412         FindOperandCycle = ItinOperandMap[ItinOperandString];
    413         if (FindOperandCycle == 0) {
    414           // Emit as  cycle, // index
    415           OperandCycleTable += ItinOperandCycleString + ", // ";
    416           std::string OperandIdxComment = itostr(OperandCycleCount);
    417           if (NOperandCycles > 1)
    418             OperandIdxComment += "-"
    419               + itostr(OperandCycleCount + NOperandCycles - 1);
    420           OperandCycleTable += OperandIdxComment + "\n";
    421           // Record Itin class number.
    422           ItinOperandMap[ItinOperandCycleString] =
    423             FindOperandCycle = OperandCycleCount;
    424           // Emit as bypass, // index
    425           BypassTable += ItinBypassString + ", // " + OperandIdxComment + "\n";
    426           OperandCycleCount += NOperandCycles;
    427         }
    428       }
    429 
    430       // Locate where to inject into processor itinerary table
    431       const std::string &Name = ItinData->getValueAsDef("TheClass")->getName();
    432       unsigned Find = ItinClassesMap[Name];
    433 
    434       // Set up itinerary as location and location + stage count
    435       unsigned NumUOps = ItinClassList[Find]->getValueAsInt("NumMicroOps");
    436       InstrItinerary Intinerary = { NumUOps, FindStage, FindStage + NStages,
    437                                     FindOperandCycle,
    438                                     FindOperandCycle + NOperandCycles};
    439 
    440       // Inject - empty slots will be 0, 0
    441       ItinList[Find] = Intinerary;
    442     }
    443 
    444     // Add process itinerary to list
    445     ProcList.push_back(ItinList);
    446   }
    447 
    448   // Closing stage
    449   StageTable += "  { 0, 0, 0, llvm::InstrStage::Required } // End itinerary\n";
    450   StageTable += "};\n";
    451 
    452   // Closing operand cycles
    453   OperandCycleTable += "  0 // End itinerary\n";
    454   OperandCycleTable += "};\n";
    455 
    456   BypassTable += "  0 // End itinerary\n";
    457   BypassTable += "};\n";
    458 
    459   // Emit tables.
    460   OS << StageTable;
    461   OS << OperandCycleTable;
    462   OS << BypassTable;
    463 }
    464 
    465 //
    466 // EmitProcessorData - Generate data for processor itineraries.
    467 //
    468 void SubtargetEmitter::
    469 EmitProcessorData(raw_ostream &OS,
    470                   std::vector<Record*> &ItinClassList,
    471                   std::vector<std::vector<InstrItinerary> > &ProcList) {
    472   // Get an iterator for processor itinerary stages
    473   std::vector<std::vector<InstrItinerary> >::iterator
    474       ProcListIter = ProcList.begin();
    475 
    476   // For each processor itinerary
    477   std::vector<Record*> Itins =
    478                        Records.getAllDerivedDefinitions("ProcessorItineraries");
    479   for (unsigned i = 0, N = Itins.size(); i < N; i++) {
    480     // Next record
    481     Record *Itin = Itins[i];
    482 
    483     // Get processor itinerary name
    484     const std::string &Name = Itin->getName();
    485 
    486     // Skip default
    487     if (Name == "NoItineraries") continue;
    488 
    489     // Begin processor itinerary table
    490     OS << "\n";
    491     OS << "llvm::InstrItinerary " << Name << "[] = {\n";
    492 
    493     // For each itinerary class
    494     std::vector<InstrItinerary> &ItinList = *ProcListIter++;
    495     assert(ItinList.size() == ItinClassList.size() && "bad itinerary");
    496     for (unsigned j = 0, M = ItinList.size(); j < M; ++j) {
    497       InstrItinerary &Intinerary = ItinList[j];
    498 
    499       // Emit in the form of
    500       // { firstStage, lastStage, firstCycle, lastCycle } // index
    501       if (Intinerary.FirstStage == 0) {
    502         OS << "  { 1, 0, 0, 0, 0 }";
    503       } else {
    504         OS << "  { " <<
    505           Intinerary.NumMicroOps << ", " <<
    506           Intinerary.FirstStage << ", " <<
    507           Intinerary.LastStage << ", " <<
    508           Intinerary.FirstOperandCycle << ", " <<
    509           Intinerary.LastOperandCycle << " }";
    510       }
    511 
    512       OS << ", // " << j << " " << ItinClassList[j]->getName() << "\n";
    513     }
    514 
    515     // End processor itinerary table
    516     OS << "  { 1, ~0U, ~0U, ~0U, ~0U } // end marker\n";
    517     OS << "};\n";
    518   }
    519 }
    520 
    521 //
    522 // EmitProcessorLookup - generate cpu name to itinerary lookup table.
    523 //
    524 void SubtargetEmitter::EmitProcessorLookup(raw_ostream &OS) {
    525   // Gather and sort processor information
    526   std::vector<Record*> ProcessorList =
    527                           Records.getAllDerivedDefinitions("Processor");
    528   std::sort(ProcessorList.begin(), ProcessorList.end(), LessRecordFieldName());
    529 
    530   // Begin processor table
    531   OS << "\n";
    532   OS << "// Sorted (by key) array of itineraries for CPU subtype.\n"
    533      << "llvm::SubtargetInfoKV "
    534      << Target << "ProcItinKV[] = {\n";
    535 
    536   // For each processor
    537   for (unsigned i = 0, N = ProcessorList.size(); i < N;) {
    538     // Next processor
    539     Record *Processor = ProcessorList[i];
    540 
    541     const std::string &Name = Processor->getValueAsString("Name");
    542     const std::string &ProcItin =
    543       Processor->getValueAsDef("ProcItin")->getName();
    544 
    545     // Emit as { "cpu", procinit },
    546     OS << "  { "
    547        << "\"" << Name << "\", "
    548        << "(void *)&" << ProcItin;
    549 
    550     OS << " }";
    551 
    552     // Depending on ''if more in the list'' emit comma
    553     if (++i < N) OS << ",";
    554 
    555     OS << "\n";
    556   }
    557 
    558   // End processor table
    559   OS << "};\n";
    560 }
    561 
    562 //
    563 // EmitData - Emits all stages and itineries, folding common patterns.
    564 //
    565 void SubtargetEmitter::EmitData(raw_ostream &OS) {
    566   std::map<std::string, unsigned> ItinClassesMap;
    567   // Gather and sort all itinerary classes
    568   std::vector<Record*> ItinClassList =
    569     Records.getAllDerivedDefinitions("InstrItinClass");
    570   std::sort(ItinClassList.begin(), ItinClassList.end(), LessRecord());
    571 
    572   // Enumerate all the itinerary classes
    573   unsigned NItinClasses = CollectAllItinClasses(OS, ItinClassesMap,
    574                                                 ItinClassList);
    575   // Make sure the rest is worth the effort
    576   HasItineraries = NItinClasses != 1;   // Ignore NoItinerary.
    577 
    578   if (HasItineraries) {
    579     std::vector<std::vector<InstrItinerary> > ProcList;
    580     // Emit the stage data
    581     EmitStageAndOperandCycleData(OS, NItinClasses, ItinClassesMap,
    582                                  ItinClassList, ProcList);
    583     // Emit the processor itinerary data
    584     EmitProcessorData(OS, ItinClassList, ProcList);
    585     // Emit the processor lookup data
    586     EmitProcessorLookup(OS);
    587   }
    588 }
    589 
    590 //
    591 // ParseFeaturesFunction - Produces a subtarget specific function for parsing
    592 // the subtarget features string.
    593 //
    594 void SubtargetEmitter::ParseFeaturesFunction(raw_ostream &OS,
    595                                              unsigned NumFeatures,
    596                                              unsigned NumProcs) {
    597   std::vector<Record*> Features =
    598                        Records.getAllDerivedDefinitions("SubtargetFeature");
    599   std::sort(Features.begin(), Features.end(), LessRecord());
    600 
    601   OS << "// ParseSubtargetFeatures - Parses features string setting specified\n"
    602      << "// subtarget options.\n"
    603      << "void llvm::";
    604   OS << Target;
    605   OS << "Subtarget::ParseSubtargetFeatures(StringRef CPU, StringRef FS) {\n"
    606      << "  DEBUG(dbgs() << \"\\nFeatures:\" << FS);\n"
    607      << "  DEBUG(dbgs() << \"\\nCPU:\" << CPU);\n";
    608 
    609   if (Features.empty()) {
    610     OS << "}\n";
    611     return;
    612   }
    613 
    614   OS << "  uint64_t Bits = ReInitMCSubtargetInfo(CPU, FS);\n";
    615 
    616   for (unsigned i = 0; i < Features.size(); i++) {
    617     // Next record
    618     Record *R = Features[i];
    619     const std::string &Instance = R->getName();
    620     const std::string &Value = R->getValueAsString("Value");
    621     const std::string &Attribute = R->getValueAsString("Attribute");
    622 
    623     if (Value=="true" || Value=="false")
    624       OS << "  if ((Bits & " << Target << "::"
    625          << Instance << ") != 0) "
    626          << Attribute << " = " << Value << ";\n";
    627     else
    628       OS << "  if ((Bits & " << Target << "::"
    629          << Instance << ") != 0 && "
    630          << Attribute << " < " << Value << ") "
    631          << Attribute << " = " << Value << ";\n";
    632   }
    633 
    634   OS << "}\n";
    635 }
    636 
    637 //
    638 // SubtargetEmitter::run - Main subtarget enumeration emitter.
    639 //
    640 void SubtargetEmitter::run(raw_ostream &OS) {
    641   Target = CodeGenTarget(Records).getName();
    642 
    643   EmitSourceFileHeader("Subtarget Enumeration Source Fragment", OS);
    644 
    645   OS << "\n#ifdef GET_SUBTARGETINFO_ENUM\n";
    646   OS << "#undef GET_SUBTARGETINFO_ENUM\n";
    647 
    648   OS << "namespace llvm {\n";
    649   Enumeration(OS, "SubtargetFeature", true);
    650   OS << "} // End llvm namespace \n";
    651   OS << "#endif // GET_SUBTARGETINFO_ENUM\n\n";
    652 
    653   OS << "\n#ifdef GET_SUBTARGETINFO_MC_DESC\n";
    654   OS << "#undef GET_SUBTARGETINFO_MC_DESC\n";
    655 
    656   OS << "namespace llvm {\n";
    657 #if 0
    658   OS << "namespace {\n";
    659 #endif
    660   unsigned NumFeatures = FeatureKeyValues(OS);
    661   OS << "\n";
    662   unsigned NumProcs = CPUKeyValues(OS);
    663   OS << "\n";
    664   EmitData(OS);
    665   OS << "\n";
    666 #if 0
    667   OS << "}\n";
    668 #endif
    669 
    670   // MCInstrInfo initialization routine.
    671   OS << "static inline void Init" << Target
    672      << "MCSubtargetInfo(MCSubtargetInfo *II, "
    673      << "StringRef TT, StringRef CPU, StringRef FS) {\n";
    674   OS << "  II->InitMCSubtargetInfo(TT, CPU, FS, ";
    675   if (NumFeatures)
    676     OS << Target << "FeatureKV, ";
    677   else
    678     OS << "0, ";
    679   if (NumProcs)
    680     OS << Target << "SubTypeKV, ";
    681   else
    682     OS << "0, ";
    683   if (HasItineraries) {
    684     OS << Target << "ProcItinKV, "
    685        << Target << "Stages, "
    686        << Target << "OperandCycles, "
    687        << Target << "ForwardingPathes, ";
    688   } else
    689     OS << "0, 0, 0, 0, ";
    690   OS << NumFeatures << ", " << NumProcs << ");\n}\n\n";
    691 
    692   OS << "} // End llvm namespace \n";
    693 
    694   OS << "#endif // GET_SUBTARGETINFO_MC_DESC\n\n";
    695 
    696   OS << "\n#ifdef GET_SUBTARGETINFO_TARGET_DESC\n";
    697   OS << "#undef GET_SUBTARGETINFO_TARGET_DESC\n";
    698 
    699   OS << "#include \"llvm/Support/Debug.h\"\n";
    700   OS << "#include \"llvm/Support/raw_ostream.h\"\n";
    701   ParseFeaturesFunction(OS, NumFeatures, NumProcs);
    702 
    703   OS << "#endif // GET_SUBTARGETINFO_TARGET_DESC\n\n";
    704 
    705   // Create a TargetSubtargetInfo subclass to hide the MC layer initialization.
    706   OS << "\n#ifdef GET_SUBTARGETINFO_HEADER\n";
    707   OS << "#undef GET_SUBTARGETINFO_HEADER\n";
    708 
    709   std::string ClassName = Target + "GenSubtargetInfo";
    710   OS << "namespace llvm {\n";
    711   OS << "struct " << ClassName << " : public TargetSubtargetInfo {\n"
    712      << "  explicit " << ClassName << "(StringRef TT, StringRef CPU, "
    713      << "StringRef FS);\n"
    714      << "};\n";
    715   OS << "} // End llvm namespace \n";
    716 
    717   OS << "#endif // GET_SUBTARGETINFO_HEADER\n\n";
    718 
    719   OS << "\n#ifdef GET_SUBTARGETINFO_CTOR\n";
    720   OS << "#undef GET_SUBTARGETINFO_CTOR\n";
    721 
    722   OS << "namespace llvm {\n";
    723   OS << "extern llvm::SubtargetFeatureKV " << Target << "FeatureKV[];\n";
    724   OS << "extern llvm::SubtargetFeatureKV " << Target << "SubTypeKV[];\n";
    725   if (HasItineraries) {
    726     OS << "extern llvm::SubtargetInfoKV " << Target << "ProcItinKV[];\n";
    727     OS << "extern llvm::InstrStage " << Target << "Stages[];\n";
    728     OS << "extern unsigned " << Target << "OperandCycles[];\n";
    729     OS << "extern unsigned " << Target << "ForwardingPathes[];\n";
    730   }
    731 
    732   OS << ClassName << "::" << ClassName << "(StringRef TT, StringRef CPU, "
    733      << "StringRef FS)\n"
    734      << "  : TargetSubtargetInfo() {\n"
    735      << "  InitMCSubtargetInfo(TT, CPU, FS, ";
    736   if (NumFeatures)
    737     OS << Target << "FeatureKV, ";
    738   else
    739     OS << "0, ";
    740   if (NumProcs)
    741     OS << Target << "SubTypeKV, ";
    742   else
    743     OS << "0, ";
    744   if (HasItineraries) {
    745     OS << Target << "ProcItinKV, "
    746        << Target << "Stages, "
    747        << Target << "OperandCycles, "
    748        << Target << "ForwardingPathes, ";
    749   } else
    750     OS << "0, 0, 0, 0, ";
    751   OS << NumFeatures << ", " << NumProcs << ");\n}\n\n";
    752   OS << "} // End llvm namespace \n";
    753 
    754   OS << "#endif // GET_SUBTARGETINFO_CTOR\n\n";
    755 }
    756