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