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