SubtargetEmitter.cpp revision ee290ba35af88393ba18dd19e6e39d50c7872534
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 "CodeGenSchedule.h"
16#include "llvm/ADT/StringExtras.h"
17#include "llvm/ADT/STLExtras.h"
18#include "llvm/MC/MCInstrItineraries.h"
19#include "llvm/TableGen/Error.h"
20#include "llvm/TableGen/Record.h"
21#include "llvm/TableGen/TableGenBackend.h"
22#include "llvm/Support/Debug.h"
23#include "llvm/Support/Format.h"
24#include <algorithm>
25#include <map>
26#include <string>
27#include <vector>
28using namespace llvm;
29
30namespace {
31class SubtargetEmitter {
32  // Each processor has a SchedClassDesc table with an entry for each SchedClass.
33  // The SchedClassDesc table indexes into a global write resource table, write
34  // latency table, and read advance table.
35  struct SchedClassTables {
36    std::vector<std::vector<MCSchedClassDesc> > ProcSchedClasses;
37    std::vector<MCWriteProcResEntry> WriteProcResources;
38    std::vector<MCWriteLatencyEntry> WriteLatencies;
39    std::vector<MCReadAdvanceEntry> ReadAdvanceEntries;
40
41    // Reserve an invalid entry at index 0
42    SchedClassTables() {
43      ProcSchedClasses.resize(1);
44      WriteProcResources.resize(1);
45      WriteLatencies.resize(1);
46      ReadAdvanceEntries.resize(1);
47    }
48  };
49
50  struct LessWriteProcResources {
51    bool operator()(const MCWriteProcResEntry &LHS,
52                    const MCWriteProcResEntry &RHS) {
53      return LHS.ProcResourceIdx < RHS.ProcResourceIdx;
54    }
55  };
56
57  RecordKeeper &Records;
58  CodeGenSchedModels &SchedModels;
59  std::string Target;
60
61  void Enumeration(raw_ostream &OS, const char *ClassName, bool isBits);
62  unsigned FeatureKeyValues(raw_ostream &OS);
63  unsigned CPUKeyValues(raw_ostream &OS);
64  void FormItineraryStageString(const std::string &Names,
65                                Record *ItinData, std::string &ItinString,
66                                unsigned &NStages);
67  void FormItineraryOperandCycleString(Record *ItinData, std::string &ItinString,
68                                       unsigned &NOperandCycles);
69  void FormItineraryBypassString(const std::string &Names,
70                                 Record *ItinData,
71                                 std::string &ItinString, unsigned NOperandCycles);
72  void EmitStageAndOperandCycleData(raw_ostream &OS,
73                                    std::vector<std::vector<InstrItinerary> >
74                                      &ProcItinLists);
75  void EmitItineraries(raw_ostream &OS,
76                       std::vector<std::vector<InstrItinerary> >
77                         &ProcItinLists);
78  void EmitProcessorProp(raw_ostream &OS, const Record *R, const char *Name,
79                         char Separator);
80  void EmitProcessorResources(const CodeGenProcModel &ProcModel,
81                              raw_ostream &OS);
82  Record *FindWriteResources(Record *WriteDef,
83                             const CodeGenProcModel &ProcModel);
84  Record *FindReadAdvance(Record *ReadDef, const CodeGenProcModel &ProcModel);
85  void GenSchedClassTables(const CodeGenProcModel &ProcModel,
86                           SchedClassTables &SchedTables);
87  void EmitSchedClassTables(SchedClassTables &SchedTables, raw_ostream &OS);
88  void EmitProcessorModels(raw_ostream &OS);
89  void EmitProcessorLookup(raw_ostream &OS);
90  void EmitSchedModel(raw_ostream &OS);
91  void ParseFeaturesFunction(raw_ostream &OS, unsigned NumFeatures,
92                             unsigned NumProcs);
93
94public:
95  SubtargetEmitter(RecordKeeper &R, CodeGenTarget &TGT):
96    Records(R), SchedModels(TGT.getSchedModels()), Target(TGT.getName()) {}
97
98  void run(raw_ostream &o);
99
100};
101} // End anonymous namespace
102
103//
104// Enumeration - Emit the specified class as an enumeration.
105//
106void SubtargetEmitter::Enumeration(raw_ostream &OS,
107                                   const char *ClassName,
108                                   bool isBits) {
109  // Get all records of class and sort
110  std::vector<Record*> DefList = Records.getAllDerivedDefinitions(ClassName);
111  std::sort(DefList.begin(), DefList.end(), LessRecord());
112
113  unsigned N = DefList.size();
114  if (N == 0)
115    return;
116  if (N > 64) {
117    errs() << "Too many (> 64) subtarget features!\n";
118    exit(1);
119  }
120
121  OS << "namespace " << Target << " {\n";
122
123  // For bit flag enumerations with more than 32 items, emit constants.
124  // Emit an enum for everything else.
125  if (isBits && N > 32) {
126    // For each record
127    for (unsigned i = 0; i < N; i++) {
128      // Next record
129      Record *Def = DefList[i];
130
131      // Get and emit name and expression (1 << i)
132      OS << "  const uint64_t " << Def->getName() << " = 1ULL << " << i << ";\n";
133    }
134  } else {
135    // Open enumeration
136    OS << "enum {\n";
137
138    // For each record
139    for (unsigned i = 0; i < N;) {
140      // Next record
141      Record *Def = DefList[i];
142
143      // Get and emit name
144      OS << "  " << Def->getName();
145
146      // If bit flags then emit expression (1 << i)
147      if (isBits)  OS << " = " << " 1ULL << " << i;
148
149      // Depending on 'if more in the list' emit comma
150      if (++i < N) OS << ",";
151
152      OS << "\n";
153    }
154
155    // Close enumeration
156    OS << "};\n";
157  }
158
159  OS << "}\n";
160}
161
162//
163// FeatureKeyValues - Emit data of all the subtarget features.  Used by the
164// command line.
165//
166unsigned SubtargetEmitter::FeatureKeyValues(raw_ostream &OS) {
167  // Gather and sort all the features
168  std::vector<Record*> FeatureList =
169                           Records.getAllDerivedDefinitions("SubtargetFeature");
170
171  if (FeatureList.empty())
172    return 0;
173
174  std::sort(FeatureList.begin(), FeatureList.end(), LessRecordFieldName());
175
176  // Begin feature table
177  OS << "// Sorted (by key) array of values for CPU features.\n"
178     << "extern const llvm::SubtargetFeatureKV " << Target
179     << "FeatureKV[] = {\n";
180
181  // For each feature
182  unsigned NumFeatures = 0;
183  for (unsigned i = 0, N = FeatureList.size(); i < N; ++i) {
184    // Next feature
185    Record *Feature = FeatureList[i];
186
187    const std::string &Name = Feature->getName();
188    const std::string &CommandLineName = Feature->getValueAsString("Name");
189    const std::string &Desc = Feature->getValueAsString("Desc");
190
191    if (CommandLineName.empty()) continue;
192
193    // Emit as { "feature", "description", featureEnum, i1 | i2 | ... | in }
194    OS << "  { "
195       << "\"" << CommandLineName << "\", "
196       << "\"" << Desc << "\", "
197       << Target << "::" << Name << ", ";
198
199    const std::vector<Record*> &ImpliesList =
200      Feature->getValueAsListOfDefs("Implies");
201
202    if (ImpliesList.empty()) {
203      OS << "0ULL";
204    } else {
205      for (unsigned j = 0, M = ImpliesList.size(); j < M;) {
206        OS << Target << "::" << ImpliesList[j]->getName();
207        if (++j < M) OS << " | ";
208      }
209    }
210
211    OS << " }";
212    ++NumFeatures;
213
214    // Depending on 'if more in the list' emit comma
215    if ((i + 1) < N) OS << ",";
216
217    OS << "\n";
218  }
219
220  // End feature table
221  OS << "};\n";
222
223  return NumFeatures;
224}
225
226//
227// CPUKeyValues - Emit data of all the subtarget processors.  Used by command
228// line.
229//
230unsigned SubtargetEmitter::CPUKeyValues(raw_ostream &OS) {
231  // Gather and sort processor information
232  std::vector<Record*> ProcessorList =
233                          Records.getAllDerivedDefinitions("Processor");
234  std::sort(ProcessorList.begin(), ProcessorList.end(), LessRecordFieldName());
235
236  // Begin processor table
237  OS << "// Sorted (by key) array of values for CPU subtype.\n"
238     << "extern const llvm::SubtargetFeatureKV " << Target
239     << "SubTypeKV[] = {\n";
240
241  // For each processor
242  for (unsigned i = 0, N = ProcessorList.size(); i < N;) {
243    // Next processor
244    Record *Processor = ProcessorList[i];
245
246    const std::string &Name = Processor->getValueAsString("Name");
247    const std::vector<Record*> &FeatureList =
248      Processor->getValueAsListOfDefs("Features");
249
250    // Emit as { "cpu", "description", f1 | f2 | ... fn },
251    OS << "  { "
252       << "\"" << Name << "\", "
253       << "\"Select the " << Name << " processor\", ";
254
255    if (FeatureList.empty()) {
256      OS << "0ULL";
257    } else {
258      for (unsigned j = 0, M = FeatureList.size(); j < M;) {
259        OS << Target << "::" << FeatureList[j]->getName();
260        if (++j < M) OS << " | ";
261      }
262    }
263
264    // The "0" is for the "implies" section of this data structure.
265    OS << ", 0ULL }";
266
267    // Depending on 'if more in the list' emit comma
268    if (++i < N) OS << ",";
269
270    OS << "\n";
271  }
272
273  // End processor table
274  OS << "};\n";
275
276  return ProcessorList.size();
277}
278
279//
280// FormItineraryStageString - Compose a string containing the stage
281// data initialization for the specified itinerary.  N is the number
282// of stages.
283//
284void SubtargetEmitter::FormItineraryStageString(const std::string &Name,
285                                                Record *ItinData,
286                                                std::string &ItinString,
287                                                unsigned &NStages) {
288  // Get states list
289  const std::vector<Record*> &StageList =
290    ItinData->getValueAsListOfDefs("Stages");
291
292  // For each stage
293  unsigned N = NStages = StageList.size();
294  for (unsigned i = 0; i < N;) {
295    // Next stage
296    const Record *Stage = StageList[i];
297
298    // Form string as ,{ cycles, u1 | u2 | ... | un, timeinc, kind }
299    int Cycles = Stage->getValueAsInt("Cycles");
300    ItinString += "  { " + itostr(Cycles) + ", ";
301
302    // Get unit list
303    const std::vector<Record*> &UnitList = Stage->getValueAsListOfDefs("Units");
304
305    // For each unit
306    for (unsigned j = 0, M = UnitList.size(); j < M;) {
307      // Add name and bitwise or
308      ItinString += Name + "FU::" + UnitList[j]->getName();
309      if (++j < M) ItinString += " | ";
310    }
311
312    int TimeInc = Stage->getValueAsInt("TimeInc");
313    ItinString += ", " + itostr(TimeInc);
314
315    int Kind = Stage->getValueAsInt("Kind");
316    ItinString += ", (llvm::InstrStage::ReservationKinds)" + itostr(Kind);
317
318    // Close off stage
319    ItinString += " }";
320    if (++i < N) ItinString += ", ";
321  }
322}
323
324//
325// FormItineraryOperandCycleString - Compose a string containing the
326// operand cycle initialization for the specified itinerary.  N is the
327// number of operands that has cycles specified.
328//
329void SubtargetEmitter::FormItineraryOperandCycleString(Record *ItinData,
330                         std::string &ItinString, unsigned &NOperandCycles) {
331  // Get operand cycle list
332  const std::vector<int64_t> &OperandCycleList =
333    ItinData->getValueAsListOfInts("OperandCycles");
334
335  // For each operand cycle
336  unsigned N = NOperandCycles = OperandCycleList.size();
337  for (unsigned i = 0; i < N;) {
338    // Next operand cycle
339    const int OCycle = OperandCycleList[i];
340
341    ItinString += "  " + itostr(OCycle);
342    if (++i < N) ItinString += ", ";
343  }
344}
345
346void SubtargetEmitter::FormItineraryBypassString(const std::string &Name,
347                                                 Record *ItinData,
348                                                 std::string &ItinString,
349                                                 unsigned NOperandCycles) {
350  const std::vector<Record*> &BypassList =
351    ItinData->getValueAsListOfDefs("Bypasses");
352  unsigned N = BypassList.size();
353  unsigned i = 0;
354  for (; i < N;) {
355    ItinString += Name + "Bypass::" + BypassList[i]->getName();
356    if (++i < NOperandCycles) ItinString += ", ";
357  }
358  for (; i < NOperandCycles;) {
359    ItinString += " 0";
360    if (++i < NOperandCycles) ItinString += ", ";
361  }
362}
363
364//
365// EmitStageAndOperandCycleData - Generate unique itinerary stages and operand
366// cycle tables. Create a list of InstrItinerary objects (ProcItinLists) indexed
367// by CodeGenSchedClass::Index.
368//
369void SubtargetEmitter::
370EmitStageAndOperandCycleData(raw_ostream &OS,
371                             std::vector<std::vector<InstrItinerary> >
372                               &ProcItinLists) {
373
374  // Multiple processor models may share an itinerary record. Emit it once.
375  SmallPtrSet<Record*, 8> ItinsDefSet;
376
377  // Emit functional units for all the itineraries.
378  for (CodeGenSchedModels::ProcIter PI = SchedModels.procModelBegin(),
379         PE = SchedModels.procModelEnd(); PI != PE; ++PI) {
380
381    if (!ItinsDefSet.insert(PI->ItinsDef))
382      continue;
383
384    std::vector<Record*> FUs = PI->ItinsDef->getValueAsListOfDefs("FU");
385    if (FUs.empty())
386      continue;
387
388    const std::string &Name = PI->ItinsDef->getName();
389    OS << "\n// Functional units for \"" << Name << "\"\n"
390       << "namespace " << Name << "FU {\n";
391
392    for (unsigned j = 0, FUN = FUs.size(); j < FUN; ++j)
393      OS << "  const unsigned " << FUs[j]->getName()
394         << " = 1 << " << j << ";\n";
395
396    OS << "}\n";
397
398    std::vector<Record*> BPs = PI->ItinsDef->getValueAsListOfDefs("BP");
399    if (BPs.size()) {
400      OS << "\n// Pipeline forwarding pathes for itineraries \"" << Name
401         << "\"\n" << "namespace " << Name << "Bypass {\n";
402
403      OS << "  const unsigned NoBypass = 0;\n";
404      for (unsigned j = 0, BPN = BPs.size(); j < BPN; ++j)
405        OS << "  const unsigned " << BPs[j]->getName()
406           << " = 1 << " << j << ";\n";
407
408      OS << "}\n";
409    }
410  }
411
412  // Begin stages table
413  std::string StageTable = "\nextern const llvm::InstrStage " + Target +
414                           "Stages[] = {\n";
415  StageTable += "  { 0, 0, 0, llvm::InstrStage::Required }, // No itinerary\n";
416
417  // Begin operand cycle table
418  std::string OperandCycleTable = "extern const unsigned " + Target +
419    "OperandCycles[] = {\n";
420  OperandCycleTable += "  0, // No itinerary\n";
421
422  // Begin pipeline bypass table
423  std::string BypassTable = "extern const unsigned " + Target +
424    "ForwardingPaths[] = {\n";
425  BypassTable += " 0, // No itinerary\n";
426
427  // For each Itinerary across all processors, add a unique entry to the stages,
428  // operand cycles, and pipepine bypess tables. Then add the new Itinerary
429  // object with computed offsets to the ProcItinLists result.
430  unsigned StageCount = 1, OperandCycleCount = 1;
431  std::map<std::string, unsigned> ItinStageMap, ItinOperandMap;
432  for (CodeGenSchedModels::ProcIter PI = SchedModels.procModelBegin(),
433         PE = SchedModels.procModelEnd(); PI != PE; ++PI) {
434    const CodeGenProcModel &ProcModel = *PI;
435
436    // Add process itinerary to the list.
437    ProcItinLists.resize(ProcItinLists.size()+1);
438
439    // If this processor defines no itineraries, then leave the itinerary list
440    // empty.
441    std::vector<InstrItinerary> &ItinList = ProcItinLists.back();
442    if (ProcModel.ItinDefList.empty())
443      continue;
444
445    // Reserve index==0 for NoItinerary.
446    ItinList.resize(SchedModels.numItineraryClasses()+1);
447
448    const std::string &Name = ProcModel.ItinsDef->getName();
449
450    // For each itinerary data
451    for (unsigned SchedClassIdx = 0,
452           SchedClassEnd = ProcModel.ItinDefList.size();
453         SchedClassIdx < SchedClassEnd; ++SchedClassIdx) {
454
455      // Next itinerary data
456      Record *ItinData = ProcModel.ItinDefList[SchedClassIdx];
457
458      // Get string and stage count
459      std::string ItinStageString;
460      unsigned NStages = 0;
461      if (ItinData)
462        FormItineraryStageString(Name, ItinData, ItinStageString, NStages);
463
464      // Get string and operand cycle count
465      std::string ItinOperandCycleString;
466      unsigned NOperandCycles = 0;
467      std::string ItinBypassString;
468      if (ItinData) {
469        FormItineraryOperandCycleString(ItinData, ItinOperandCycleString,
470                                        NOperandCycles);
471
472        FormItineraryBypassString(Name, ItinData, ItinBypassString,
473                                  NOperandCycles);
474      }
475
476      // Check to see if stage already exists and create if it doesn't
477      unsigned FindStage = 0;
478      if (NStages > 0) {
479        FindStage = ItinStageMap[ItinStageString];
480        if (FindStage == 0) {
481          // Emit as { cycles, u1 | u2 | ... | un, timeinc }, // indices
482          StageTable += ItinStageString + ", // " + itostr(StageCount);
483          if (NStages > 1)
484            StageTable += "-" + itostr(StageCount + NStages - 1);
485          StageTable += "\n";
486          // Record Itin class number.
487          ItinStageMap[ItinStageString] = FindStage = StageCount;
488          StageCount += NStages;
489        }
490      }
491
492      // Check to see if operand cycle already exists and create if it doesn't
493      unsigned FindOperandCycle = 0;
494      if (NOperandCycles > 0) {
495        std::string ItinOperandString = ItinOperandCycleString+ItinBypassString;
496        FindOperandCycle = ItinOperandMap[ItinOperandString];
497        if (FindOperandCycle == 0) {
498          // Emit as  cycle, // index
499          OperandCycleTable += ItinOperandCycleString + ", // ";
500          std::string OperandIdxComment = itostr(OperandCycleCount);
501          if (NOperandCycles > 1)
502            OperandIdxComment += "-"
503              + itostr(OperandCycleCount + NOperandCycles - 1);
504          OperandCycleTable += OperandIdxComment + "\n";
505          // Record Itin class number.
506          ItinOperandMap[ItinOperandCycleString] =
507            FindOperandCycle = OperandCycleCount;
508          // Emit as bypass, // index
509          BypassTable += ItinBypassString + ", // " + OperandIdxComment + "\n";
510          OperandCycleCount += NOperandCycles;
511        }
512      }
513
514      // Set up itinerary as location and location + stage count
515      int NumUOps = ItinData ? ItinData->getValueAsInt("NumMicroOps") : 0;
516      InstrItinerary Intinerary = { NumUOps, FindStage, FindStage + NStages,
517                                    FindOperandCycle,
518                                    FindOperandCycle + NOperandCycles};
519
520      // Inject - empty slots will be 0, 0
521      ItinList[SchedClassIdx] = Intinerary;
522    }
523  }
524
525  // Closing stage
526  StageTable += "  { 0, 0, 0, llvm::InstrStage::Required } // End stages\n";
527  StageTable += "};\n";
528
529  // Closing operand cycles
530  OperandCycleTable += "  0 // End operand cycles\n";
531  OperandCycleTable += "};\n";
532
533  BypassTable += " 0 // End bypass tables\n";
534  BypassTable += "};\n";
535
536  // Emit tables.
537  OS << StageTable;
538  OS << OperandCycleTable;
539  OS << BypassTable;
540}
541
542//
543// EmitProcessorData - Generate data for processor itineraries that were
544// computed during EmitStageAndOperandCycleData(). ProcItinLists lists all
545// Itineraries for each processor. The Itinerary lists are indexed on
546// CodeGenSchedClass::Index.
547//
548void SubtargetEmitter::
549EmitItineraries(raw_ostream &OS,
550                std::vector<std::vector<InstrItinerary> > &ProcItinLists) {
551
552  // Multiple processor models may share an itinerary record. Emit it once.
553  SmallPtrSet<Record*, 8> ItinsDefSet;
554
555  // For each processor's machine model
556  std::vector<std::vector<InstrItinerary> >::iterator
557      ProcItinListsIter = ProcItinLists.begin();
558  for (CodeGenSchedModels::ProcIter PI = SchedModels.procModelBegin(),
559         PE = SchedModels.procModelEnd(); PI != PE; ++PI, ++ProcItinListsIter) {
560
561    Record *ItinsDef = PI->ItinsDef;
562    if (!ItinsDefSet.insert(ItinsDef))
563      continue;
564
565    // Get processor itinerary name
566    const std::string &Name = ItinsDef->getName();
567
568    // Get the itinerary list for the processor.
569    assert(ProcItinListsIter != ProcItinLists.end() && "bad iterator");
570    std::vector<InstrItinerary> &ItinList = *ProcItinListsIter;
571
572    OS << "\n";
573    OS << "static const llvm::InstrItinerary ";
574    if (ItinList.empty()) {
575      OS << '*' << Name << " = 0;\n";
576      continue;
577    }
578
579    // Begin processor itinerary table
580    OS << Name << "[] = {\n";
581
582    // For each itinerary class in CodeGenSchedClass::Index order.
583    for (unsigned j = 0, M = ItinList.size(); j < M; ++j) {
584      InstrItinerary &Intinerary = ItinList[j];
585
586      // Emit Itinerary in the form of
587      // { firstStage, lastStage, firstCycle, lastCycle } // index
588      OS << "  { " <<
589        Intinerary.NumMicroOps << ", " <<
590        Intinerary.FirstStage << ", " <<
591        Intinerary.LastStage << ", " <<
592        Intinerary.FirstOperandCycle << ", " <<
593        Intinerary.LastOperandCycle << " }" <<
594        ", // " << j << " " << SchedModels.getSchedClass(j).Name << "\n";
595    }
596    // End processor itinerary table
597    OS << "  { 0, ~0U, ~0U, ~0U, ~0U } // end marker\n";
598    OS << "};\n";
599  }
600}
601
602// Emit either the value defined in the TableGen Record, or the default
603// value defined in the C++ header. The Record is null if the processor does not
604// define a model.
605void SubtargetEmitter::EmitProcessorProp(raw_ostream &OS, const Record *R,
606                                         const char *Name, char Separator) {
607  OS << "  ";
608  int V = R ? R->getValueAsInt(Name) : -1;
609  if (V >= 0)
610    OS << V << Separator << " // " << Name;
611  else
612    OS << "MCSchedModel::Default" << Name << Separator;
613  OS << '\n';
614}
615
616void SubtargetEmitter::EmitProcessorResources(const CodeGenProcModel &ProcModel,
617                                              raw_ostream &OS) {
618  char Sep = ProcModel.ProcResourceDefs.empty() ? ' ' : ',';
619
620  OS << "\n// {Name, NumUnits, SuperIdx}\n";
621  OS << "static const llvm::MCProcResourceDesc "
622     << ProcModel.ModelName << "ProcResources" << "[] = {\n"
623     << "  {DBGFIELD(\"InvalidUnit\")     0, 0}" << Sep << "\n";
624
625  for (unsigned i = 0, e = ProcModel.ProcResourceDefs.size(); i < e; ++i) {
626    Record *PRDef = ProcModel.ProcResourceDefs[i];
627
628    // Find the SuperIdx
629    unsigned SuperIdx = 0;
630    Record *SuperDef = 0;
631    if (PRDef->getValueInit("Super")->isComplete()) {
632      SuperDef =
633        SchedModels.findProcResUnits(PRDef->getValueAsDef("Super"), ProcModel);
634      SuperIdx = ProcModel.getProcResourceIdx(SuperDef);
635    }
636    // Emit the ProcResourceDesc
637    if (i+1 == e)
638      Sep = ' ';
639    OS << "  {DBGFIELD(\"" << PRDef->getName() << "\") ";
640    if (PRDef->getName().size() < 15)
641      OS.indent(15 - PRDef->getName().size());
642    OS << PRDef->getValueAsInt("NumUnits") << ", " << SuperIdx
643       << "}" << Sep << " // #" << i+1;
644    if (SuperDef)
645      OS << ", Super=" << SuperDef->getName();
646    OS << "\n";
647  }
648  OS << "};\n";
649}
650
651// Find the WriteRes Record that defines processor resources for this
652// SchedWrite.
653Record *SubtargetEmitter::FindWriteResources(
654  Record *WriteDef, const CodeGenProcModel &ProcModel) {
655
656  // Check if the SchedWrite is already subtarget-specific and directly
657  // specifies a set of processor resources.
658  if (WriteDef->isSubClassOf("SchedWriteRes"))
659    return WriteDef;
660
661  // Check this processor's list of write resources.
662  for (RecIter WRI = ProcModel.WriteResDefs.begin(),
663         WRE = ProcModel.WriteResDefs.end(); WRI != WRE; ++WRI) {
664    if (!(*WRI)->isSubClassOf("WriteRes"))
665      continue;
666    if (WriteDef == (*WRI)->getValueAsDef("WriteType"))
667      return *WRI;
668  }
669  throw TGError(ProcModel.ModelDef->getLoc(),
670                std::string("Processor does not define resources for ")
671                + WriteDef->getName());
672}
673
674/// Find the ReadAdvance record for the given SchedRead on this processor or
675/// return NULL.
676Record *SubtargetEmitter::FindReadAdvance(Record *ReadDef,
677                                          const CodeGenProcModel &ProcModel) {
678  // Check for SchedReads that directly specify a ReadAdvance.
679  if (ReadDef->isSubClassOf("SchedReadAdvance"))
680    return ReadDef;
681
682  // Check this processor's ReadAdvanceList.
683  for (RecIter RAI = ProcModel.ReadAdvanceDefs.begin(),
684         RAE = ProcModel.ReadAdvanceDefs.end(); RAI != RAE; ++RAI) {
685    if (!(*RAI)->isSubClassOf("ReadAdvance"))
686      continue;
687    if (ReadDef == (*RAI)->getValueAsDef("ReadType"))
688      return *RAI;
689  }
690  if (ReadDef->getName() != "ReadDefault") {
691    throw TGError(ProcModel.ModelDef->getLoc(),
692                  std::string("Processor does not define resources for ")
693                  + ReadDef->getName());
694  }
695  return NULL;
696}
697
698// Generate the SchedClass table for this processor and update global
699// tables. Must be called for each processor in order.
700void SubtargetEmitter::GenSchedClassTables(const CodeGenProcModel &ProcModel,
701                                           SchedClassTables &SchedTables) {
702  SchedTables.ProcSchedClasses.resize(SchedTables.ProcSchedClasses.size() + 1);
703  if (!ProcModel.hasInstrSchedModel())
704    return;
705
706  std::vector<MCSchedClassDesc> &SCTab = SchedTables.ProcSchedClasses.back();
707  for (CodeGenSchedModels::SchedClassIter SCI = SchedModels.schedClassBegin(),
708         SCE = SchedModels.schedClassEnd(); SCI != SCE; ++SCI) {
709    SCTab.resize(SCTab.size() + 1);
710    MCSchedClassDesc &SCDesc = SCTab.back();
711    // SCDesc.Name is guarded by NDEBUG
712    SCDesc.NumMicroOps = 0;
713    SCDesc.BeginGroup = false;
714    SCDesc.EndGroup = false;
715    SCDesc.WriteProcResIdx = 0;
716    SCDesc.WriteLatencyIdx = 0;
717    SCDesc.ReadAdvanceIdx = 0;
718
719    // A Variant SchedClass has no resources of its own.
720    if (!SCI->Transitions.empty()) {
721      SCDesc.NumMicroOps = MCSchedClassDesc::VariantNumMicroOps;
722      continue;
723    }
724
725    // Determine if the SchedClass is actually reachable on this processor. If
726    // not don't try to locate the processor resources, it will fail.
727    // If ProcIndices contains 0, this class applies to all processors.
728    assert(!SCI->ProcIndices.empty() && "expect at least one procidx");
729    if (SCI->ProcIndices[0] != 0) {
730      IdxIter PIPos = std::find(SCI->ProcIndices.begin(),
731                                SCI->ProcIndices.end(), ProcModel.Index);
732      if (PIPos == SCI->ProcIndices.end())
733        continue;
734    }
735    IdxVec Writes = SCI->Writes;
736    IdxVec Reads = SCI->Reads;
737    if (SCI->ItinClassDef) {
738      assert(SCI->InstRWs.empty() && "ItinClass should not have InstRWs");
739      // Check this processor's itinerary class resources.
740      for (RecIter II = ProcModel.ItinRWDefs.begin(),
741             IE = ProcModel.ItinRWDefs.end(); II != IE; ++II) {
742        RecVec Matched = (*II)->getValueAsListOfDefs("MatchedItinClasses");
743        if (std::find(Matched.begin(), Matched.end(), SCI->ItinClassDef)
744            != Matched.end()) {
745          SchedModels.findRWs((*II)->getValueAsListOfDefs("OperandReadWrites"),
746                              Writes, Reads);
747          break;
748        }
749      }
750      if (Writes.empty()) {
751        DEBUG(dbgs() << ProcModel.ItinsDef->getName()
752              << " does not have resources for itinerary class "
753              << SCI->ItinClassDef->getName() << '\n');
754      }
755    }
756    else if (!SCI->InstRWs.empty()) {
757      assert(SCI->Writes.empty() && SCI->Reads.empty() &&
758             "InstRW class should not have its own ReadWrites");
759      Record *RWDef = 0;
760      for (RecIter RWI = SCI->InstRWs.begin(), RWE = SCI->InstRWs.end();
761           RWI != RWE; ++RWI) {
762        Record *RWModelDef = (*RWI)->getValueAsDef("SchedModel");
763        if (&ProcModel == &SchedModels.getProcModel(RWModelDef)) {
764          RWDef = *RWI;
765          break;
766        }
767      }
768      if (RWDef) {
769        SchedModels.findRWs(RWDef->getValueAsListOfDefs("OperandReadWrites"),
770                            Writes, Reads);
771      }
772    }
773    // Sum resources across all operand writes.
774    std::vector<MCWriteProcResEntry> WriteProcResources;
775    std::vector<MCWriteLatencyEntry> WriteLatencies;
776    std::vector<MCReadAdvanceEntry> ReadAdvanceEntries;
777    for (IdxIter WI = Writes.begin(), WE = Writes.end(); WI != WE; ++WI) {
778      IdxVec WriteSeq;
779      SchedModels.expandRWSequence(*WI, WriteSeq, /*IsRead=*/false);
780
781      // For each operand, create a latency entry.
782      MCWriteLatencyEntry WLEntry;
783      WLEntry.Cycles = 0;
784      WLEntry.WriteResourceID = WriteSeq.back();
785
786      for (IdxIter WSI = WriteSeq.begin(), WSE = WriteSeq.end();
787           WSI != WSE; ++WSI) {
788
789        Record *WriteDef = SchedModels.getSchedWrite(*WSI).TheDef;
790        Record *WriteRes = FindWriteResources(WriteDef, ProcModel);
791
792        // Mark the parent class as invalid for unsupported write types.
793        if (WriteRes->getValueAsBit("Unsupported")) {
794          SCDesc.NumMicroOps = MCSchedClassDesc::InvalidNumMicroOps;
795          break;
796        }
797        WLEntry.Cycles += WriteRes->getValueAsInt("Latency");
798        SCDesc.NumMicroOps += WriteRes->getValueAsInt("NumMicroOps");
799        SCDesc.BeginGroup |= WriteRes->getValueAsBit("BeginGroup");
800        SCDesc.EndGroup |= WriteRes->getValueAsBit("EndGroup");
801
802        // Create an entry for each ProcResource listed in WriteRes.
803        RecVec PRVec = WriteRes->getValueAsListOfDefs("ProcResources");
804        std::vector<int64_t> Cycles =
805          WriteRes->getValueAsListOfInts("ResourceCycles");
806        for (unsigned PRIdx = 0, PREnd = PRVec.size();
807             PRIdx != PREnd; ++PRIdx) {
808          MCWriteProcResEntry WPREntry;
809          WPREntry.ProcResourceIdx = ProcModel.getProcResourceIdx(PRVec[PRIdx]);
810          assert(WPREntry.ProcResourceIdx && "Bad ProcResourceIdx");
811          if (Cycles.size() > PRIdx)
812            WPREntry.Cycles = Cycles[PRIdx];
813          else
814            WPREntry.Cycles = 1;
815          WriteProcResources.push_back(WPREntry);
816        }
817      }
818      WriteLatencies.push_back(WLEntry);
819    }
820    // Create an entry for each operand Read in this SchedClass.
821    // Entries must be sorted first by UseIdx then by WriteResourceID.
822    for (unsigned UseIdx = 0, EndIdx = Reads.size();
823         UseIdx != EndIdx; ++UseIdx) {
824      Record *ReadDef = SchedModels.getSchedRead(Reads[UseIdx]).TheDef;
825      Record *ReadAdvance = FindReadAdvance(ReadDef, ProcModel);
826      if (!ReadAdvance)
827        continue;
828
829      // Mark the parent class as invalid for unsupported write types.
830      if (ReadAdvance->getValueAsBit("Unsupported")) {
831        SCDesc.NumMicroOps = MCSchedClassDesc::InvalidNumMicroOps;
832        break;
833      }
834      RecVec ValidWrites = ReadAdvance->getValueAsListOfDefs("ValidWrites");
835      IdxVec WriteIDs;
836      if (ValidWrites.empty())
837        WriteIDs.push_back(0);
838      else {
839        for (RecIter VWI = ValidWrites.begin(), VWE = ValidWrites.end();
840             VWI != VWE; ++VWI) {
841          WriteIDs.push_back(SchedModels.getSchedRWIdx(*VWI, /*IsRead=*/false));
842        }
843      }
844      std::sort(WriteIDs.begin(), WriteIDs.end());
845      for(IdxIter WI = WriteIDs.begin(), WE = WriteIDs.end(); WI != WE; ++WI) {
846        MCReadAdvanceEntry RAEntry;
847        RAEntry.UseIdx = UseIdx;
848        RAEntry.WriteResourceID = *WI;
849        RAEntry.Cycles = ReadAdvance->getValueAsInt("Cycles");
850        ReadAdvanceEntries.push_back(RAEntry);
851      }
852    }
853    if (SCDesc.NumMicroOps == MCSchedClassDesc::InvalidNumMicroOps) {
854      WriteProcResources.clear();
855      WriteLatencies.clear();
856      ReadAdvanceEntries.clear();
857    }
858    // Add the information for this SchedClass to the global tables using basic
859    // compression.
860    //
861    // WritePrecRes entries are sorted by ProcResIdx.
862    std::sort(WriteProcResources.begin(), WriteProcResources.end(),
863              LessWriteProcResources());
864
865    SCDesc.NumWriteProcResEntries = WriteProcResources.size();
866    std::vector<MCWriteProcResEntry>::iterator WPRPos =
867      std::search(SchedTables.WriteProcResources.begin(),
868                  SchedTables.WriteProcResources.end(),
869                  WriteProcResources.begin(), WriteProcResources.end());
870    if (WPRPos != SchedTables.WriteProcResources.end())
871      SCDesc.WriteProcResIdx = WPRPos - SchedTables.WriteProcResources.begin();
872    else {
873      SCDesc.WriteProcResIdx = SchedTables.WriteProcResources.size();
874      SchedTables.WriteProcResources.insert(WPRPos, WriteProcResources.begin(),
875                                            WriteProcResources.end());
876    }
877    // Latency entries must remain in operand order.
878    SCDesc.NumWriteLatencyEntries = WriteLatencies.size();
879    std::vector<MCWriteLatencyEntry>::iterator WLPos =
880      std::search(SchedTables.WriteLatencies.begin(),
881                  SchedTables.WriteLatencies.end(),
882                  WriteLatencies.begin(), WriteLatencies.end());
883    if (WLPos != SchedTables.WriteLatencies.end())
884      SCDesc.WriteLatencyIdx = WLPos - SchedTables.WriteLatencies.begin();
885    else {
886      SCDesc.WriteLatencyIdx = SchedTables.WriteLatencies.size();
887      SchedTables.WriteLatencies.insert(WLPos, WriteLatencies.begin(),
888                                     WriteLatencies.end());
889    }
890    // ReadAdvanceEntries must remain in operand order.
891    SCDesc.NumReadAdvanceEntries = ReadAdvanceEntries.size();
892    std::vector<MCReadAdvanceEntry>::iterator RAPos =
893      std::search(SchedTables.ReadAdvanceEntries.begin(),
894                  SchedTables.ReadAdvanceEntries.end(),
895                  ReadAdvanceEntries.begin(), ReadAdvanceEntries.end());
896    if (RAPos != SchedTables.ReadAdvanceEntries.end())
897      SCDesc.ReadAdvanceIdx = RAPos - SchedTables.ReadAdvanceEntries.begin();
898    else {
899      SCDesc.ReadAdvanceIdx = SchedTables.ReadAdvanceEntries.size();
900      SchedTables.ReadAdvanceEntries.insert(RAPos, ReadAdvanceEntries.begin(),
901                                            ReadAdvanceEntries.end());
902    }
903  }
904}
905
906// Emit SchedClass tables for all processors and associated global tables.
907void SubtargetEmitter::EmitSchedClassTables(SchedClassTables &SchedTables,
908                                            raw_ostream &OS) {
909  // Emit global WriteProcResTable.
910  OS << "\n// {ProcResourceIdx, Cycles}\n"
911     << "extern const llvm::MCWriteProcResEntry "
912     << Target << "WriteProcResTable[] = {\n"
913     << "  { 0,  0}, // Invalid\n";
914  for (unsigned WPRIdx = 1, WPREnd = SchedTables.WriteProcResources.size();
915       WPRIdx != WPREnd; ++WPRIdx) {
916    MCWriteProcResEntry &WPREntry = SchedTables.WriteProcResources[WPRIdx];
917    OS << "  {" << format("%2d", WPREntry.ProcResourceIdx) << ", "
918       << format("%2d", WPREntry.Cycles) << "}";
919    if (WPRIdx + 1 < WPREnd)
920      OS << ',';
921    OS << " // #" << WPRIdx << '\n';
922  }
923  OS << "}; // " << Target << "WriteProcResTable\n";
924
925  // Emit global WriteLatencyTable.
926  OS << "\n// {Cycles, WriteResourceID}\n"
927     << "extern const llvm::MCWriteLatencyEntry "
928     << Target << "WriteLatencyTable[] = {\n"
929     << "  { 0,  0}, // Invalid\n";
930  for (unsigned WLIdx = 1, WLEnd = SchedTables.WriteLatencies.size();
931       WLIdx != WLEnd; ++WLIdx) {
932    MCWriteLatencyEntry &WLEntry = SchedTables.WriteLatencies[WLIdx];
933    OS << "  {" << format("%2d", WLEntry.Cycles) << ", "
934       << format("%2d", WLEntry.WriteResourceID) << "}";
935    if (WLIdx + 1 < WLEnd)
936      OS << ',';
937    OS << " // #" << WLIdx << " "
938       << SchedModels.getSchedWrite(WLEntry.WriteResourceID).Name << '\n';
939  }
940  OS << "}; // " << Target << "WriteLatencyTable\n";
941
942  // Emit global ReadAdvanceTable.
943  OS << "\n// {UseIdx, WriteResourceID, Cycles}\n"
944     << "extern const llvm::MCReadAdvanceEntry "
945     << Target << "ReadAdvanceTable[] = {\n"
946     << "  {0,  0,  0}, // Invalid\n";
947  for (unsigned RAIdx = 1, RAEnd = SchedTables.ReadAdvanceEntries.size();
948       RAIdx != RAEnd; ++RAIdx) {
949    MCReadAdvanceEntry &RAEntry = SchedTables.ReadAdvanceEntries[RAIdx];
950    OS << "  {" << RAEntry.UseIdx << ", "
951       << format("%2d", RAEntry.WriteResourceID) << ", "
952       << format("%2d", RAEntry.Cycles) << "}";
953    if (RAIdx + 1 < RAEnd)
954      OS << ',';
955    OS << " // #" << RAIdx << '\n';
956  }
957  OS << "}; // " << Target << "ReadAdvanceTable\n";
958
959  // Emit a SchedClass table for each processor.
960  for (CodeGenSchedModels::ProcIter PI = SchedModels.procModelBegin(),
961         PE = SchedModels.procModelEnd(); PI != PE; ++PI) {
962    if (!PI->hasInstrSchedModel())
963      continue;
964
965    std::vector<MCSchedClassDesc> &SCTab =
966      SchedTables.ProcSchedClasses[1 + PI - SchedModels.procModelBegin()];
967
968    OS << "\n// {Name, NumMicroOps, BeginGroup, EndGroup,"
969       << " WriteProcResIdx,#, WriteLatencyIdx,#, ReadAdvanceIdx,#}\n";
970    OS << "static const llvm::MCSchedClassDesc "
971       << PI->ModelName << "SchedClasses[] = {\n";
972
973    // The first class is always invalid. We no way to distinguish it except by
974    // name and position.
975    assert(SchedModels.getSchedClass(0).Name == "NoItinerary"
976           && "invalid class not first");
977    OS << "  {DBGFIELD(\"InvalidSchedClass\")  "
978       << MCSchedClassDesc::InvalidNumMicroOps
979       << ", 0, 0,  0, 0,  0, 0,  0, 0},\n";
980
981    for (unsigned SCIdx = 1, SCEnd = SCTab.size(); SCIdx != SCEnd; ++SCIdx) {
982      MCSchedClassDesc &MCDesc = SCTab[SCIdx];
983      const CodeGenSchedClass &SchedClass = SchedModels.getSchedClass(SCIdx);
984      OS << "  {DBGFIELD(\"" << SchedClass.Name << "\") ";
985      if (SchedClass.Name.size() < 18)
986        OS.indent(18 - SchedClass.Name.size());
987      OS << MCDesc.NumMicroOps
988         << ", " << MCDesc.BeginGroup << ", " << MCDesc.EndGroup
989         << ", " << format("%2d", MCDesc.WriteProcResIdx)
990         << ", " << MCDesc.NumWriteProcResEntries
991         << ", " << format("%2d", MCDesc.WriteLatencyIdx)
992         << ", " << MCDesc.NumWriteLatencyEntries
993         << ", " << format("%2d", MCDesc.ReadAdvanceIdx)
994         << ", " << MCDesc.NumReadAdvanceEntries << "}";
995      if (SCIdx + 1 < SCEnd)
996        OS << ',';
997      OS << " // #" << SCIdx << '\n';
998    }
999    OS << "}; // " << PI->ModelName << "SchedClasses\n";
1000  }
1001}
1002
1003void SubtargetEmitter::EmitProcessorModels(raw_ostream &OS) {
1004  // For each processor model.
1005  for (CodeGenSchedModels::ProcIter PI = SchedModels.procModelBegin(),
1006         PE = SchedModels.procModelEnd(); PI != PE; ++PI) {
1007    // Emit processor resource table.
1008    if (PI->hasInstrSchedModel())
1009      EmitProcessorResources(*PI, OS);
1010    else if(!PI->ProcResourceDefs.empty())
1011      throw TGError(PI->ModelDef->getLoc(), "SchedMachineModel defines "
1012                    "ProcResources without defining WriteRes SchedWriteRes");
1013
1014    // Begin processor itinerary properties
1015    OS << "\n";
1016    OS << "static const llvm::MCSchedModel " << PI->ModelName << "(\n";
1017    EmitProcessorProp(OS, PI->ModelDef, "IssueWidth", ',');
1018    EmitProcessorProp(OS, PI->ModelDef, "MinLatency", ',');
1019    EmitProcessorProp(OS, PI->ModelDef, "LoadLatency", ',');
1020    EmitProcessorProp(OS, PI->ModelDef, "HighLatency", ',');
1021    EmitProcessorProp(OS, PI->ModelDef, "MispredictPenalty", ',');
1022    OS << "  " << PI->Index << ", // Processor ID\n";
1023    if (PI->hasInstrSchedModel())
1024      OS << "  " << PI->ModelName << "ProcResources" << ",\n"
1025         << "  " << PI->ModelName << "SchedClasses" << ",\n"
1026         << "  " << PI->ProcResourceDefs.size()+1 << ",\n"
1027         << "  " << (SchedModels.schedClassEnd()
1028                     - SchedModels.schedClassBegin()) << ",\n";
1029    else
1030      OS << "  0, 0, 0, 0, // No instruction-level machine model.\n";
1031    if (SchedModels.hasItineraryClasses())
1032      OS << "  " << PI->ItinsDef->getName() << ");\n";
1033    else
1034      OS << "  0); // No Itinerary\n";
1035  }
1036}
1037
1038//
1039// EmitProcessorLookup - generate cpu name to itinerary lookup table.
1040//
1041void SubtargetEmitter::EmitProcessorLookup(raw_ostream &OS) {
1042  // Gather and sort processor information
1043  std::vector<Record*> ProcessorList =
1044                          Records.getAllDerivedDefinitions("Processor");
1045  std::sort(ProcessorList.begin(), ProcessorList.end(), LessRecordFieldName());
1046
1047  // Begin processor table
1048  OS << "\n";
1049  OS << "// Sorted (by key) array of itineraries for CPU subtype.\n"
1050     << "extern const llvm::SubtargetInfoKV "
1051     << Target << "ProcSchedKV[] = {\n";
1052
1053  // For each processor
1054  for (unsigned i = 0, N = ProcessorList.size(); i < N;) {
1055    // Next processor
1056    Record *Processor = ProcessorList[i];
1057
1058    const std::string &Name = Processor->getValueAsString("Name");
1059    const std::string &ProcModelName =
1060      SchedModels.getModelForProc(Processor).ModelName;
1061
1062    // Emit as { "cpu", procinit },
1063    OS << "  { \"" << Name << "\", (const void *)&" << ProcModelName << " }";
1064
1065    // Depending on ''if more in the list'' emit comma
1066    if (++i < N) OS << ",";
1067
1068    OS << "\n";
1069  }
1070
1071  // End processor table
1072  OS << "};\n";
1073}
1074
1075//
1076// EmitSchedModel - Emits all scheduling model tables, folding common patterns.
1077//
1078void SubtargetEmitter::EmitSchedModel(raw_ostream &OS) {
1079  OS << "#ifdef DBGFIELD\n"
1080     << "#error \"<target>GenSubtargetInfo.inc requires a DBGFIELD macro\"\n"
1081     << "#endif\n"
1082     << "#ifndef NDEBUG\n"
1083     << "#define DBGFIELD(x) x,\n"
1084     << "#else\n"
1085     << "#define DBGFIELD(x)\n"
1086     << "#endif\n";
1087
1088  if (SchedModels.hasItineraryClasses()) {
1089    std::vector<std::vector<InstrItinerary> > ProcItinLists;
1090    // Emit the stage data
1091    EmitStageAndOperandCycleData(OS, ProcItinLists);
1092    EmitItineraries(OS, ProcItinLists);
1093  }
1094  OS << "\n// ===============================================================\n"
1095     << "// Data tables for the new per-operand machine model.\n";
1096
1097  SchedClassTables SchedTables;
1098  for (CodeGenSchedModels::ProcIter PI = SchedModels.procModelBegin(),
1099         PE = SchedModels.procModelEnd(); PI != PE; ++PI) {
1100    GenSchedClassTables(*PI, SchedTables);
1101  }
1102  EmitSchedClassTables(SchedTables, OS);
1103
1104  // Emit the processor machine model
1105  EmitProcessorModels(OS);
1106  // Emit the processor lookup data
1107  EmitProcessorLookup(OS);
1108
1109  OS << "#undef DBGFIELD";
1110}
1111
1112//
1113// ParseFeaturesFunction - Produces a subtarget specific function for parsing
1114// the subtarget features string.
1115//
1116void SubtargetEmitter::ParseFeaturesFunction(raw_ostream &OS,
1117                                             unsigned NumFeatures,
1118                                             unsigned NumProcs) {
1119  std::vector<Record*> Features =
1120                       Records.getAllDerivedDefinitions("SubtargetFeature");
1121  std::sort(Features.begin(), Features.end(), LessRecord());
1122
1123  OS << "// ParseSubtargetFeatures - Parses features string setting specified\n"
1124     << "// subtarget options.\n"
1125     << "void llvm::";
1126  OS << Target;
1127  OS << "Subtarget::ParseSubtargetFeatures(StringRef CPU, StringRef FS) {\n"
1128     << "  DEBUG(dbgs() << \"\\nFeatures:\" << FS);\n"
1129     << "  DEBUG(dbgs() << \"\\nCPU:\" << CPU << \"\\n\\n\");\n";
1130
1131  if (Features.empty()) {
1132    OS << "}\n";
1133    return;
1134  }
1135
1136  OS << "  uint64_t Bits = ReInitMCSubtargetInfo(CPU, FS);\n";
1137
1138  for (unsigned i = 0; i < Features.size(); i++) {
1139    // Next record
1140    Record *R = Features[i];
1141    const std::string &Instance = R->getName();
1142    const std::string &Value = R->getValueAsString("Value");
1143    const std::string &Attribute = R->getValueAsString("Attribute");
1144
1145    if (Value=="true" || Value=="false")
1146      OS << "  if ((Bits & " << Target << "::"
1147         << Instance << ") != 0) "
1148         << Attribute << " = " << Value << ";\n";
1149    else
1150      OS << "  if ((Bits & " << Target << "::"
1151         << Instance << ") != 0 && "
1152         << Attribute << " < " << Value << ") "
1153         << Attribute << " = " << Value << ";\n";
1154  }
1155
1156  OS << "}\n";
1157}
1158
1159//
1160// SubtargetEmitter::run - Main subtarget enumeration emitter.
1161//
1162void SubtargetEmitter::run(raw_ostream &OS) {
1163  emitSourceFileHeader("Subtarget Enumeration Source Fragment", OS);
1164
1165  OS << "\n#ifdef GET_SUBTARGETINFO_ENUM\n";
1166  OS << "#undef GET_SUBTARGETINFO_ENUM\n";
1167
1168  OS << "namespace llvm {\n";
1169  Enumeration(OS, "SubtargetFeature", true);
1170  OS << "} // End llvm namespace \n";
1171  OS << "#endif // GET_SUBTARGETINFO_ENUM\n\n";
1172
1173  OS << "\n#ifdef GET_SUBTARGETINFO_MC_DESC\n";
1174  OS << "#undef GET_SUBTARGETINFO_MC_DESC\n";
1175
1176  OS << "namespace llvm {\n";
1177#if 0
1178  OS << "namespace {\n";
1179#endif
1180  unsigned NumFeatures = FeatureKeyValues(OS);
1181  OS << "\n";
1182  unsigned NumProcs = CPUKeyValues(OS);
1183  OS << "\n";
1184  EmitSchedModel(OS);
1185  OS << "\n";
1186#if 0
1187  OS << "}\n";
1188#endif
1189
1190  // MCInstrInfo initialization routine.
1191  OS << "static inline void Init" << Target
1192     << "MCSubtargetInfo(MCSubtargetInfo *II, "
1193     << "StringRef TT, StringRef CPU, StringRef FS) {\n";
1194  OS << "  II->InitMCSubtargetInfo(TT, CPU, FS, ";
1195  if (NumFeatures)
1196    OS << Target << "FeatureKV, ";
1197  else
1198    OS << "0, ";
1199  if (NumProcs)
1200    OS << Target << "SubTypeKV, ";
1201  else
1202    OS << "0, ";
1203  OS << '\n'; OS.indent(22);
1204  OS << Target << "ProcSchedKV, "
1205     << Target << "WriteProcResTable, "
1206     << Target << "WriteLatencyTable, "
1207     << Target << "ReadAdvanceTable, ";
1208  if (SchedModels.hasItineraryClasses()) {
1209    OS << '\n'; OS.indent(22);
1210    OS << Target << "Stages, "
1211       << Target << "OperandCycles, "
1212       << Target << "ForwardingPaths, ";
1213  } else
1214    OS << "0, 0, 0, ";
1215  OS << NumFeatures << ", " << NumProcs << ");\n}\n\n";
1216
1217  OS << "} // End llvm namespace \n";
1218
1219  OS << "#endif // GET_SUBTARGETINFO_MC_DESC\n\n";
1220
1221  OS << "\n#ifdef GET_SUBTARGETINFO_TARGET_DESC\n";
1222  OS << "#undef GET_SUBTARGETINFO_TARGET_DESC\n";
1223
1224  OS << "#include \"llvm/Support/Debug.h\"\n";
1225  OS << "#include \"llvm/Support/raw_ostream.h\"\n";
1226  ParseFeaturesFunction(OS, NumFeatures, NumProcs);
1227
1228  OS << "#endif // GET_SUBTARGETINFO_TARGET_DESC\n\n";
1229
1230  // Create a TargetSubtargetInfo subclass to hide the MC layer initialization.
1231  OS << "\n#ifdef GET_SUBTARGETINFO_HEADER\n";
1232  OS << "#undef GET_SUBTARGETINFO_HEADER\n";
1233
1234  std::string ClassName = Target + "GenSubtargetInfo";
1235  OS << "namespace llvm {\n";
1236  OS << "class DFAPacketizer;\n";
1237  OS << "struct " << ClassName << " : public TargetSubtargetInfo {\n"
1238     << "  explicit " << ClassName << "(StringRef TT, StringRef CPU, "
1239     << "StringRef FS);\n"
1240     << "public:\n"
1241     << "  DFAPacketizer *createDFAPacketizer(const InstrItineraryData *IID)"
1242     << " const;\n"
1243     << "};\n";
1244  OS << "} // End llvm namespace \n";
1245
1246  OS << "#endif // GET_SUBTARGETINFO_HEADER\n\n";
1247
1248  OS << "\n#ifdef GET_SUBTARGETINFO_CTOR\n";
1249  OS << "#undef GET_SUBTARGETINFO_CTOR\n";
1250
1251  OS << "#include \"llvm/CodeGen/TargetSchedule.h\"\n";
1252  OS << "namespace llvm {\n";
1253  OS << "extern const llvm::SubtargetFeatureKV " << Target << "FeatureKV[];\n";
1254  OS << "extern const llvm::SubtargetFeatureKV " << Target << "SubTypeKV[];\n";
1255  OS << "extern const llvm::SubtargetInfoKV " << Target << "ProcSchedKV[];\n";
1256  OS << "extern const llvm::MCWriteProcResEntry "
1257     << Target << "WriteProcResTable[];\n";
1258  OS << "extern const llvm::MCWriteLatencyEntry "
1259     << Target << "WriteLatencyTable[];\n";
1260  OS << "extern const llvm::MCReadAdvanceEntry "
1261     << Target << "ReadAdvanceTable[];\n";
1262
1263  if (SchedModels.hasItineraryClasses()) {
1264    OS << "extern const llvm::InstrStage " << Target << "Stages[];\n";
1265    OS << "extern const unsigned " << Target << "OperandCycles[];\n";
1266    OS << "extern const unsigned " << Target << "ForwardingPaths[];\n";
1267  }
1268
1269  OS << ClassName << "::" << ClassName << "(StringRef TT, StringRef CPU, "
1270     << "StringRef FS)\n"
1271     << "  : TargetSubtargetInfo() {\n"
1272     << "  InitMCSubtargetInfo(TT, CPU, FS, ";
1273  if (NumFeatures)
1274    OS << Target << "FeatureKV, ";
1275  else
1276    OS << "0, ";
1277  if (NumProcs)
1278    OS << Target << "SubTypeKV, ";
1279  else
1280    OS << "0, ";
1281  OS << '\n'; OS.indent(22);
1282  OS << Target << "ProcSchedKV, "
1283     << Target << "WriteProcResTable, "
1284     << Target << "WriteLatencyTable, "
1285     << Target << "ReadAdvanceTable, ";
1286  OS << '\n'; OS.indent(22);
1287  if (SchedModels.hasItineraryClasses()) {
1288    OS << Target << "Stages, "
1289       << Target << "OperandCycles, "
1290       << Target << "ForwardingPaths, ";
1291  } else
1292    OS << "0, 0, 0, ";
1293  OS << NumFeatures << ", " << NumProcs << ");\n}\n\n";
1294
1295  OS << "} // End llvm namespace \n";
1296
1297  OS << "#endif // GET_SUBTARGETINFO_CTOR\n\n";
1298}
1299
1300namespace llvm {
1301
1302void EmitSubtarget(RecordKeeper &RK, raw_ostream &OS) {
1303  CodeGenTarget CGTarget(RK);
1304  SubtargetEmitter(RK, CGTarget).run(OS);
1305}
1306
1307} // End llvm namespace
1308