SubtargetEmitter.cpp revision 3f696e568bae8afa5986e7af48156c2bac041ba7
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    // Skip default
426    if (Name == "NoItineraries") continue;
427
428    // Create and expand processor itinerary to cover all itinerary classes
429    std::vector<InstrItinerary> ItinList;
430    ItinList.resize(NItinClasses);
431
432    // Get itinerary data list
433    std::vector<Record*> ItinDataList = Proc->getValueAsListOfDefs("IID");
434
435    // For each itinerary data
436    for (unsigned j = 0, M = ItinDataList.size(); j < M; j++) {
437      // Next itinerary data
438      Record *ItinData = ItinDataList[j];
439
440      // Get string and stage count
441      std::string ItinStageString;
442      unsigned NStages;
443      FormItineraryStageString(Name, ItinData, ItinStageString, NStages);
444
445      // Get string and operand cycle count
446      std::string ItinOperandCycleString;
447      unsigned NOperandCycles;
448      FormItineraryOperandCycleString(ItinData, ItinOperandCycleString,
449                                      NOperandCycles);
450
451      std::string ItinBypassString;
452      FormItineraryBypassString(Name, ItinData, ItinBypassString,
453                                NOperandCycles);
454
455      // Check to see if stage already exists and create if it doesn't
456      unsigned FindStage = 0;
457      if (NStages > 0) {
458        FindStage = ItinStageMap[ItinStageString];
459        if (FindStage == 0) {
460          // Emit as { cycles, u1 | u2 | ... | un, timeinc }, // indices
461          StageTable += ItinStageString + ", // " + itostr(StageCount);
462          if (NStages > 1)
463            StageTable += "-" + itostr(StageCount + NStages - 1);
464          StageTable += "\n";
465          // Record Itin class number.
466          ItinStageMap[ItinStageString] = FindStage = StageCount;
467          StageCount += NStages;
468        }
469      }
470
471      // Check to see if operand cycle already exists and create if it doesn't
472      unsigned FindOperandCycle = 0;
473      if (NOperandCycles > 0) {
474        std::string ItinOperandString = ItinOperandCycleString+ItinBypassString;
475        FindOperandCycle = ItinOperandMap[ItinOperandString];
476        if (FindOperandCycle == 0) {
477          // Emit as  cycle, // index
478          OperandCycleTable += ItinOperandCycleString + ", // ";
479          std::string OperandIdxComment = itostr(OperandCycleCount);
480          if (NOperandCycles > 1)
481            OperandIdxComment += "-"
482              + itostr(OperandCycleCount + NOperandCycles - 1);
483          OperandCycleTable += OperandIdxComment + "\n";
484          // Record Itin class number.
485          ItinOperandMap[ItinOperandCycleString] =
486            FindOperandCycle = OperandCycleCount;
487          // Emit as bypass, // index
488          BypassTable += ItinBypassString + ", // " + OperandIdxComment + "\n";
489          OperandCycleCount += NOperandCycles;
490        }
491      }
492
493      // Locate where to inject into processor itinerary table
494      const std::string &Name = ItinData->getValueAsDef("TheClass")->getName();
495      unsigned Find = ItinClassesMap[Name];
496
497      // Set up itinerary as location and location + stage count
498      unsigned NumUOps = ItinClassList[Find]->getValueAsInt("NumMicroOps");
499      InstrItinerary Intinerary = { NumUOps, FindStage, FindStage + NStages,
500                                    FindOperandCycle,
501                                    FindOperandCycle + NOperandCycles};
502
503      // Inject - empty slots will be 0, 0
504      ItinList[Find] = Intinerary;
505    }
506
507    // Add process itinerary to list
508    ProcList.push_back(ItinList);
509  }
510
511  // Closing stage
512  StageTable += "  { 0, 0, 0, llvm::InstrStage::Required } // End itinerary\n";
513  StageTable += "};\n";
514
515  // Closing operand cycles
516  OperandCycleTable += "  0 // End itinerary\n";
517  OperandCycleTable += "};\n";
518
519  BypassTable += "  0 // End itinerary\n";
520  BypassTable += "};\n";
521
522  // Emit tables.
523  OS << StageTable;
524  OS << OperandCycleTable;
525  OS << BypassTable;
526}
527
528void SubtargetEmitter::EmitItineraryProp(raw_ostream &OS, const Record *R,
529                                         const char *Name, char Separator) {
530  OS << "  ";
531  int V = R->getValueAsInt(Name);
532  if (V >= 0)
533    OS << V << Separator << " // " << Name;
534  else
535    OS << "InstrItineraryProps::Default" << Name << Separator;
536  OS << '\n';
537}
538
539//
540// EmitProcessorData - Generate data for processor itineraries.
541//
542void SubtargetEmitter::
543EmitProcessorData(raw_ostream &OS,
544                  std::vector<Record*> &ItinClassList,
545                  std::vector<std::vector<InstrItinerary> > &ProcList) {
546
547  // Get an iterator for processor itinerary stages
548  std::vector<std::vector<InstrItinerary> >::iterator
549      ProcListIter = ProcList.begin();
550
551  // For each processor itinerary
552  std::vector<Record*> Itins =
553                       Records.getAllDerivedDefinitions("ProcessorItineraries");
554  for (unsigned i = 0, N = Itins.size(); i < N; i++) {
555    // Next record
556    Record *Itin = Itins[i];
557
558    // Get processor itinerary name
559    const std::string &Name = Itin->getName();
560
561    // Skip default
562    if (Name == "NoItineraries") continue;
563
564    // Begin processor itinerary properties
565    OS << "\n";
566    OS << "static const llvm::InstrItineraryProps " << Name << "Props(\n";
567    EmitItineraryProp(OS, Itin, "IssueWidth", ',');
568    EmitItineraryProp(OS, Itin, "MinLatency", ',');
569    EmitItineraryProp(OS, Itin, "LoadLatency", ',');
570    EmitItineraryProp(OS, Itin, "HighLatency", ' ');
571    OS << ");\n";
572
573    // Begin processor itinerary table
574    OS << "\n";
575    OS << "static const llvm::InstrItinerary " << Name << "Entries"
576       << "[] = {\n";
577
578    // For each itinerary class
579    std::vector<InstrItinerary> &ItinList = *ProcListIter++;
580    assert(ItinList.size() == ItinClassList.size() && "bad itinerary");
581    for (unsigned j = 0, M = ItinList.size(); j < M; ++j) {
582      InstrItinerary &Intinerary = ItinList[j];
583
584      // Emit in the form of
585      // { firstStage, lastStage, firstCycle, lastCycle } // index
586      if (Intinerary.FirstStage == 0) {
587        OS << "  { 1, 0, 0, 0, 0 }";
588      } else {
589        OS << "  { " <<
590          Intinerary.NumMicroOps << ", " <<
591          Intinerary.FirstStage << ", " <<
592          Intinerary.LastStage << ", " <<
593          Intinerary.FirstOperandCycle << ", " <<
594          Intinerary.LastOperandCycle << " }";
595      }
596
597      OS << ", // " << j << " " << ItinClassList[j]->getName() << "\n";
598    }
599
600    // End processor itinerary table
601    OS << "  { 1, ~0U, ~0U, ~0U, ~0U } // end marker\n";
602    OS << "};\n";
603
604    OS << '\n';
605    OS << "static const llvm::InstrItinerarySubtargetValue "
606       << Name << " = {\n";
607    OS << "  &" << Name << "Props,\n";
608    OS << "  " << Name << "Entries\n";
609    OS << "};\n";
610  }
611}
612
613//
614// EmitProcessorLookup - generate cpu name to itinerary lookup table.
615//
616void SubtargetEmitter::EmitProcessorLookup(raw_ostream &OS) {
617  // Gather and sort processor information
618  std::vector<Record*> ProcessorList =
619                          Records.getAllDerivedDefinitions("Processor");
620  std::sort(ProcessorList.begin(), ProcessorList.end(), LessRecordFieldName());
621
622  // Begin processor table
623  OS << "\n";
624  OS << "// Sorted (by key) array of itineraries for CPU subtype.\n"
625     << "extern const llvm::SubtargetInfoKV "
626     << Target << "ProcItinKV[] = {\n";
627
628  // For each processor
629  for (unsigned i = 0, N = ProcessorList.size(); i < N;) {
630    // Next processor
631    Record *Processor = ProcessorList[i];
632
633    const std::string &Name = Processor->getValueAsString("Name");
634    const std::string &ProcItin =
635      Processor->getValueAsDef("ProcItin")->getName();
636
637    // Emit as { "cpu", procinit },
638    OS << "  { "
639       << "\"" << Name << "\", "
640       << "(void *)&" << ProcItin;
641
642    OS << " }";
643
644    // Depending on ''if more in the list'' emit comma
645    if (++i < N) OS << ",";
646
647    OS << "\n";
648  }
649
650  // End processor table
651  OS << "};\n";
652}
653
654//
655// EmitData - Emits all stages and itineries, folding common patterns.
656//
657void SubtargetEmitter::EmitData(raw_ostream &OS) {
658  std::map<std::string, unsigned> ItinClassesMap;
659  // Gather and sort all itinerary classes
660  std::vector<Record*> ItinClassList =
661    Records.getAllDerivedDefinitions("InstrItinClass");
662  std::sort(ItinClassList.begin(), ItinClassList.end(), LessRecord());
663
664  // Enumerate all the itinerary classes
665  unsigned NItinClasses = CollectAllItinClasses(OS, ItinClassesMap,
666                                                ItinClassList);
667  // Make sure the rest is worth the effort
668  HasItineraries = NItinClasses != 1;   // Ignore NoItinerary.
669
670  if (HasItineraries) {
671    std::vector<std::vector<InstrItinerary> > ProcList;
672    // Emit the stage data
673    EmitStageAndOperandCycleData(OS, NItinClasses, ItinClassesMap,
674                                 ItinClassList, ProcList);
675    // Emit the processor itinerary data
676    EmitProcessorData(OS, ItinClassList, ProcList);
677    // Emit the processor lookup data
678    EmitProcessorLookup(OS);
679  }
680}
681
682//
683// ParseFeaturesFunction - Produces a subtarget specific function for parsing
684// the subtarget features string.
685//
686void SubtargetEmitter::ParseFeaturesFunction(raw_ostream &OS,
687                                             unsigned NumFeatures,
688                                             unsigned NumProcs) {
689  std::vector<Record*> Features =
690                       Records.getAllDerivedDefinitions("SubtargetFeature");
691  std::sort(Features.begin(), Features.end(), LessRecord());
692
693  OS << "// ParseSubtargetFeatures - Parses features string setting specified\n"
694     << "// subtarget options.\n"
695     << "void llvm::";
696  OS << Target;
697  OS << "Subtarget::ParseSubtargetFeatures(StringRef CPU, StringRef FS) {\n"
698     << "  DEBUG(dbgs() << \"\\nFeatures:\" << FS);\n"
699     << "  DEBUG(dbgs() << \"\\nCPU:\" << CPU << \"\\n\\n\");\n";
700
701  if (Features.empty()) {
702    OS << "}\n";
703    return;
704  }
705
706  OS << "  uint64_t Bits = ReInitMCSubtargetInfo(CPU, FS);\n";
707
708  for (unsigned i = 0; i < Features.size(); i++) {
709    // Next record
710    Record *R = Features[i];
711    const std::string &Instance = R->getName();
712    const std::string &Value = R->getValueAsString("Value");
713    const std::string &Attribute = R->getValueAsString("Attribute");
714
715    if (Value=="true" || Value=="false")
716      OS << "  if ((Bits & " << Target << "::"
717         << Instance << ") != 0) "
718         << Attribute << " = " << Value << ";\n";
719    else
720      OS << "  if ((Bits & " << Target << "::"
721         << Instance << ") != 0 && "
722         << Attribute << " < " << Value << ") "
723         << Attribute << " = " << Value << ";\n";
724  }
725
726  OS << "}\n";
727}
728
729//
730// SubtargetEmitter::run - Main subtarget enumeration emitter.
731//
732void SubtargetEmitter::run(raw_ostream &OS) {
733  Target = CodeGenTarget(Records).getName();
734
735  emitSourceFileHeader("Subtarget Enumeration Source Fragment", OS);
736
737  OS << "\n#ifdef GET_SUBTARGETINFO_ENUM\n";
738  OS << "#undef GET_SUBTARGETINFO_ENUM\n";
739
740  OS << "namespace llvm {\n";
741  Enumeration(OS, "SubtargetFeature", true);
742  OS << "} // End llvm namespace \n";
743  OS << "#endif // GET_SUBTARGETINFO_ENUM\n\n";
744
745  OS << "\n#ifdef GET_SUBTARGETINFO_MC_DESC\n";
746  OS << "#undef GET_SUBTARGETINFO_MC_DESC\n";
747
748  OS << "namespace llvm {\n";
749#if 0
750  OS << "namespace {\n";
751#endif
752  unsigned NumFeatures = FeatureKeyValues(OS);
753  OS << "\n";
754  unsigned NumProcs = CPUKeyValues(OS);
755  OS << "\n";
756  EmitData(OS);
757  OS << "\n";
758#if 0
759  OS << "}\n";
760#endif
761
762  // MCInstrInfo initialization routine.
763  OS << "static inline void Init" << Target
764     << "MCSubtargetInfo(MCSubtargetInfo *II, "
765     << "StringRef TT, StringRef CPU, StringRef FS) {\n";
766  OS << "  II->InitMCSubtargetInfo(TT, CPU, FS, ";
767  if (NumFeatures)
768    OS << Target << "FeatureKV, ";
769  else
770    OS << "0, ";
771  if (NumProcs)
772    OS << Target << "SubTypeKV, ";
773  else
774    OS << "0, ";
775  if (HasItineraries) {
776    OS << Target << "ProcItinKV, "
777       << Target << "Stages, "
778       << Target << "OperandCycles, "
779       << Target << "ForwardingPathes, ";
780  } else
781    OS << "0, 0, 0, 0, ";
782  OS << NumFeatures << ", " << NumProcs << ");\n}\n\n";
783
784  OS << "} // End llvm namespace \n";
785
786  OS << "#endif // GET_SUBTARGETINFO_MC_DESC\n\n";
787
788  OS << "\n#ifdef GET_SUBTARGETINFO_TARGET_DESC\n";
789  OS << "#undef GET_SUBTARGETINFO_TARGET_DESC\n";
790
791  OS << "#include \"llvm/Support/Debug.h\"\n";
792  OS << "#include \"llvm/Support/raw_ostream.h\"\n";
793  ParseFeaturesFunction(OS, NumFeatures, NumProcs);
794
795  OS << "#endif // GET_SUBTARGETINFO_TARGET_DESC\n\n";
796
797  // Create a TargetSubtargetInfo subclass to hide the MC layer initialization.
798  OS << "\n#ifdef GET_SUBTARGETINFO_HEADER\n";
799  OS << "#undef GET_SUBTARGETINFO_HEADER\n";
800
801  std::string ClassName = Target + "GenSubtargetInfo";
802  OS << "namespace llvm {\n";
803  OS << "class DFAPacketizer;\n";
804  OS << "struct " << ClassName << " : public TargetSubtargetInfo {\n"
805     << "  explicit " << ClassName << "(StringRef TT, StringRef CPU, "
806     << "StringRef FS);\n"
807     << "public:\n"
808     << "  DFAPacketizer *createDFAPacketizer(const InstrItineraryData *IID)"
809     << " const;\n"
810     << "};\n";
811  OS << "} // End llvm namespace \n";
812
813  OS << "#endif // GET_SUBTARGETINFO_HEADER\n\n";
814
815  OS << "\n#ifdef GET_SUBTARGETINFO_CTOR\n";
816  OS << "#undef GET_SUBTARGETINFO_CTOR\n";
817
818  OS << "namespace llvm {\n";
819  OS << "extern const llvm::SubtargetFeatureKV " << Target << "FeatureKV[];\n";
820  OS << "extern const llvm::SubtargetFeatureKV " << Target << "SubTypeKV[];\n";
821  if (HasItineraries) {
822    OS << "extern const llvm::SubtargetInfoKV " << Target << "ProcItinKV[];\n";
823    OS << "extern const llvm::InstrStage " << Target << "Stages[];\n";
824    OS << "extern const unsigned " << Target << "OperandCycles[];\n";
825    OS << "extern const unsigned " << Target << "ForwardingPathes[];\n";
826  }
827
828  OS << ClassName << "::" << ClassName << "(StringRef TT, StringRef CPU, "
829     << "StringRef FS)\n"
830     << "  : TargetSubtargetInfo() {\n"
831     << "  InitMCSubtargetInfo(TT, CPU, FS, ";
832  if (NumFeatures)
833    OS << Target << "FeatureKV, ";
834  else
835    OS << "0, ";
836  if (NumProcs)
837    OS << Target << "SubTypeKV, ";
838  else
839    OS << "0, ";
840  if (HasItineraries) {
841    OS << Target << "ProcItinKV, "
842       << Target << "Stages, "
843       << Target << "OperandCycles, "
844       << Target << "ForwardingPathes, ";
845  } else
846    OS << "0, 0, 0, 0, ";
847  OS << NumFeatures << ", " << NumProcs << ");\n}\n\n";
848  OS << "} // End llvm namespace \n";
849
850  OS << "#endif // GET_SUBTARGETINFO_CTOR\n\n";
851}
852
853namespace llvm {
854
855void EmitSubtarget(RecordKeeper &RK, raw_ostream &OS) {
856  SubtargetEmitter(RK).run(OS);
857}
858
859} // End llvm namespace
860