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