1 //===- SubtargetEmitter.cpp - Generate subtarget enumerations -------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This tablegen backend emits subtarget enumerations.
12 //===----------------------------------------------------------------------===//
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"
23 // Enumeration - Emit the specified class as an enumeration.
25 void SubtargetEmitter::Enumeration(raw_ostream &OS,
26 const char *ClassName,
28 // Get all records of class and sort
29 std::vector<Record*> DefList = Records.getAllDerivedDefinitions(ClassName);
30 std::sort(DefList.begin(), DefList.end(), LessRecord());
32 unsigned N = DefList.size();
36 errs() << "Too many (> 64) subtarget features!\n";
40 OS << "namespace " << Target << " {\n";
42 // For bit flag enumerations with more than 32 items, emit constants.
43 // Emit an enum for everything else.
44 if (isBits && N > 32) {
46 for (unsigned i = 0; i < N; i++) {
48 Record *Def = DefList[i];
50 // Get and emit name and expression (1 << i)
51 OS << " const uint64_t " << Def->getName() << " = 1ULL << " << i << ";\n";
58 for (unsigned i = 0; i < N;) {
60 Record *Def = DefList[i];
63 OS << " " << Def->getName();
65 // If bit flags then emit expression (1 << i)
66 if (isBits) OS << " = " << " 1ULL << " << i;
68 // Depending on 'if more in the list' emit comma
69 if (++i < N) OS << ",";
82 // FeatureKeyValues - Emit data of all the subtarget features. Used by the
85 unsigned SubtargetEmitter::FeatureKeyValues(raw_ostream &OS) {
86 // Gather and sort all the features
87 std::vector<Record*> FeatureList =
88 Records.getAllDerivedDefinitions("SubtargetFeature");
90 if (FeatureList.empty())
93 std::sort(FeatureList.begin(), FeatureList.end(), LessRecordFieldName());
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";
101 unsigned NumFeatures = 0;
102 for (unsigned i = 0, N = FeatureList.size(); i < N; ++i) {
104 Record *Feature = FeatureList[i];
106 const std::string &Name = Feature->getName();
107 const std::string &CommandLineName = Feature->getValueAsString("Name");
108 const std::string &Desc = Feature->getValueAsString("Desc");
110 if (CommandLineName.empty()) continue;
112 // Emit as { "feature", "description", featureEnum, i1 | i2 | ... | in }
114 << "\"" << CommandLineName << "\", "
115 << "\"" << Desc << "\", "
116 << Target << "::" << Name << ", ";
118 const std::vector<Record*> &ImpliesList =
119 Feature->getValueAsListOfDefs("Implies");
121 if (ImpliesList.empty()) {
124 for (unsigned j = 0, M = ImpliesList.size(); j < M;) {
125 OS << Target << "::" << ImpliesList[j]->getName();
126 if (++j < M) OS << " | ";
133 // Depending on 'if more in the list' emit comma
134 if ((i + 1) < N) OS << ",";
146 // CPUKeyValues - Emit data of all the subtarget processors. Used by command
149 unsigned 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());
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";
160 // For each processor
161 for (unsigned i = 0, N = ProcessorList.size(); i < N;) {
163 Record *Processor = ProcessorList[i];
165 const std::string &Name = Processor->getValueAsString("Name");
166 const std::vector<Record*> &FeatureList =
167 Processor->getValueAsListOfDefs("Features");
169 // Emit as { "cpu", "description", f1 | f2 | ... fn },
171 << "\"" << Name << "\", "
172 << "\"Select the " << Name << " processor\", ";
174 if (FeatureList.empty()) {
177 for (unsigned j = 0, M = FeatureList.size(); j < M;) {
178 OS << Target << "::" << FeatureList[j]->getName();
179 if (++j < M) OS << " | ";
183 // The "0" is for the "implies" section of this data structure.
186 // Depending on 'if more in the list' emit comma
187 if (++i < N) OS << ",";
192 // End processor table
195 return ProcessorList.size();
199 // CollectAllItinClasses - Gathers and enumerates all the itinerary classes.
200 // Returns itinerary class count.
202 unsigned SubtargetEmitter::
203 CollectAllItinClasses(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;
216 // Return itinerary class count
221 // FormItineraryStageString - Compose a string containing the stage
222 // data initialization for the specified itinerary. N is the number
225 void SubtargetEmitter::FormItineraryStageString(const std::string &Name,
227 std::string &ItinString,
230 const std::vector<Record*> &StageList =
231 ItinData->getValueAsListOfDefs("Stages");
234 unsigned N = NStages = StageList.size();
235 for (unsigned i = 0; i < N;) {
237 const Record *Stage = StageList[i];
239 // Form string as ,{ cycles, u1 | u2 | ... | un, timeinc, kind }
240 int Cycles = Stage->getValueAsInt("Cycles");
241 ItinString += " { " + itostr(Cycles) + ", ";
244 const std::vector<Record*> &UnitList = Stage->getValueAsListOfDefs("Units");
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 += " | ";
253 int TimeInc = Stage->getValueAsInt("TimeInc");
254 ItinString += ", " + itostr(TimeInc);
256 int Kind = Stage->getValueAsInt("Kind");
257 ItinString += ", (llvm::InstrStage::ReservationKinds)" + itostr(Kind);
261 if (++i < N) ItinString += ", ";
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.
270 void 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");
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];
282 ItinString += " " + itostr(OCycle);
283 if (++i < N) ItinString += ", ";
287 void SubtargetEmitter::FormItineraryBypassString(const std::string &Name,
289 std::string &ItinString,
290 unsigned NOperandCycles) {
291 const std::vector<Record*> &BypassList =
292 ItinData->getValueAsListOfDefs("Bypasses");
293 unsigned N = BypassList.size();
296 ItinString += Name + "Bypass::" + BypassList[i]->getName();
297 if (++i < NOperandCycles) ItinString += ", ";
299 for (; i < NOperandCycles;) {
301 if (++i < NOperandCycles) ItinString += ", ";
306 // EmitStageAndOperandCycleData - Generate unique itinerary stages and
307 // operand cycle tables. Record itineraries for processors.
309 void 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");
318 // If just no itinerary then don't bother
319 if (ProcItinList.size() < 2) return;
321 // Emit functional units for all the itineraries.
322 for (unsigned i = 0, N = ProcItinList.size(); i < N; ++i) {
324 Record *Proc = ProcItinList[i];
326 std::vector<Record*> FUs = Proc->getValueAsListOfDefs("FU");
330 const std::string &Name = Proc->getName();
331 OS << "\n// Functional units for itineraries \"" << Name << "\"\n"
332 << "namespace " << Name << "FU {\n";
334 for (unsigned j = 0, FUN = FUs.size(); j < FUN; ++j)
335 OS << " const unsigned " << FUs[j]->getName()
336 << " = 1 << " << j << ";\n";
340 std::vector<Record*> BPs = Proc->getValueAsListOfDefs("BP");
342 OS << "\n// Pipeline forwarding pathes for itineraries \"" << Name
343 << "\"\n" << "namespace " << Name << "Bypass {\n";
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";
354 // Begin stages table
355 std::string StageTable = "\nextern const llvm::InstrStage " + Target +
357 StageTable += " { 0, 0, 0, llvm::InstrStage::Required }, // No itinerary\n";
359 // Begin operand cycle table
360 std::string OperandCycleTable = "extern const unsigned " + Target +
361 "OperandCycles[] = {\n";
362 OperandCycleTable += " 0, // No itinerary\n";
364 // Begin pipeline bypass table
365 std::string BypassTable = "extern const unsigned " + Target +
366 "ForwardingPathes[] = {\n";
367 BypassTable += " 0, // No itinerary\n";
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++) {
373 Record *Proc = ProcItinList[i];
375 // Get processor itinerary name
376 const std::string &Name = Proc->getName();
379 if (Name == "NoItineraries") continue;
381 // Create and expand processor itinerary to cover all itinerary classes
382 std::vector<InstrItinerary> ItinList;
383 ItinList.resize(NItinClasses);
385 // Get itinerary data list
386 std::vector<Record*> ItinDataList = Proc->getValueAsListOfDefs("IID");
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];
393 // Get string and stage count
394 std::string ItinStageString;
396 FormItineraryStageString(Name, ItinData, ItinStageString, NStages);
398 // Get string and operand cycle count
399 std::string ItinOperandCycleString;
400 unsigned NOperandCycles;
401 FormItineraryOperandCycleString(ItinData, ItinOperandCycleString,
404 std::string ItinBypassString;
405 FormItineraryBypassString(Name, ItinData, ItinBypassString,
408 // Check to see if stage already exists and create if it doesn't
409 unsigned FindStage = 0;
411 FindStage = ItinStageMap[ItinStageString];
412 if (FindStage == 0) {
413 // Emit as { cycles, u1 | u2 | ... | un, timeinc }, // indices
414 StageTable += ItinStageString + ", // " + itostr(StageCount);
416 StageTable += "-" + itostr(StageCount + NStages - 1);
418 // Record Itin class number.
419 ItinStageMap[ItinStageString] = FindStage = StageCount;
420 StageCount += NStages;
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;
446 // Locate where to inject into processor itinerary table
447 const std::string &Name = ItinData->getValueAsDef("TheClass")->getName();
448 unsigned Find = ItinClassesMap[Name];
450 // Set up itinerary as location and location + stage count
451 unsigned NumUOps = ItinClassList[Find]->getValueAsInt("NumMicroOps");
452 InstrItinerary Intinerary = { NumUOps, FindStage, FindStage + NStages,
454 FindOperandCycle + NOperandCycles};
456 // Inject - empty slots will be 0, 0
457 ItinList[Find] = Intinerary;
460 // Add process itinerary to list
461 ProcList.push_back(ItinList);
465 StageTable += " { 0, 0, 0, llvm::InstrStage::Required } // End itinerary\n";
466 StageTable += "};\n";
468 // Closing operand cycles
469 OperandCycleTable += " 0 // End itinerary\n";
470 OperandCycleTable += "};\n";
472 BypassTable += " 0 // End itinerary\n";
473 BypassTable += "};\n";
477 OS << OperandCycleTable;
481 void SubtargetEmitter::EmitItineraryProp(raw_ostream &OS, const Record *R,
482 const char *Name, char Separator) {
484 int V = R->getValueAsInt(Name);
486 OS << V << Separator << " // " << Name;
488 OS << "DefaultItineraryProps." << Name << Separator;
493 // EmitProcessorData - Generate data for processor itineraries.
495 void SubtargetEmitter::
496 EmitProcessorData(raw_ostream &OS,
497 std::vector<Record*> &ItinClassList,
498 std::vector<std::vector<InstrItinerary> > &ProcList) {
499 OS << "static const llvm::InstrItineraryProps " << "DefaultItineraryProps;";
501 // Get an iterator for processor itinerary stages
502 std::vector<std::vector<InstrItinerary> >::iterator
503 ProcListIter = ProcList.begin();
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++) {
510 Record *Itin = Itins[i];
512 // Get processor itinerary name
513 const std::string &Name = Itin->getName();
516 if (Name == "NoItineraries") continue;
518 // Begin processor itinerary properties
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", ' ');
527 // Begin processor itinerary table
529 OS << "static const llvm::InstrItinerary " << Name << "Entries"
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];
538 // Emit in the form of
539 // { firstStage, lastStage, firstCycle, lastCycle } // index
540 if (Intinerary.FirstStage == 0) {
541 OS << " { 1, 0, 0, 0, 0 }";
544 Intinerary.NumMicroOps << ", " <<
545 Intinerary.FirstStage << ", " <<
546 Intinerary.LastStage << ", " <<
547 Intinerary.FirstOperandCycle << ", " <<
548 Intinerary.LastOperandCycle << " }";
551 OS << ", // " << j << " " << ItinClassList[j]->getName() << "\n";
554 // End processor itinerary table
555 OS << " { 1, ~0U, ~0U, ~0U, ~0U } // end marker\n";
559 OS << "static const llvm::InstrItinerarySubtargetValue "
561 OS << " &" << Name << "Props,\n";
562 OS << " " << Name << "Entries\n";
568 // EmitProcessorLookup - generate cpu name to itinerary lookup table.
570 void 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());
576 // Begin processor table
578 OS << "// Sorted (by key) array of itineraries for CPU subtype.\n"
579 << "extern const llvm::SubtargetInfoKV "
580 << Target << "ProcItinKV[] = {\n";
582 // For each processor
583 for (unsigned i = 0, N = ProcessorList.size(); i < N;) {
585 Record *Processor = ProcessorList[i];
587 const std::string &Name = Processor->getValueAsString("Name");
588 const std::string &ProcItin =
589 Processor->getValueAsDef("ProcItin")->getName();
591 // Emit as { "cpu", procinit },
593 << "\"" << Name << "\", "
594 << "(void *)&" << ProcItin;
598 // Depending on ''if more in the list'' emit comma
599 if (++i < N) OS << ",";
604 // End processor table
609 // EmitData - Emits all stages and itineries, folding common patterns.
611 void 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());
618 // Enumerate all the itinerary classes
619 unsigned NItinClasses = CollectAllItinClasses(OS, ItinClassesMap,
621 // Make sure the rest is worth the effort
622 HasItineraries = NItinClasses != 1; // Ignore NoItinerary.
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);
637 // ParseFeaturesFunction - Produces a subtarget specific function for parsing
638 // the subtarget features string.
640 void SubtargetEmitter::ParseFeaturesFunction(raw_ostream &OS,
641 unsigned NumFeatures,
643 std::vector<Record*> Features =
644 Records.getAllDerivedDefinitions("SubtargetFeature");
645 std::sort(Features.begin(), Features.end(), LessRecord());
647 OS << "// ParseSubtargetFeatures - Parses features string setting specified\n"
648 << "// subtarget options.\n"
651 OS << "Subtarget::ParseSubtargetFeatures(StringRef CPU, StringRef FS) {\n"
652 << " DEBUG(dbgs() << \"\\nFeatures:\" << FS);\n"
653 << " DEBUG(dbgs() << \"\\nCPU:\" << CPU);\n";
655 if (Features.empty()) {
660 OS << " uint64_t Bits = ReInitMCSubtargetInfo(CPU, FS);\n";
662 for (unsigned i = 0; i < Features.size(); i++) {
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");
669 if (Value=="true" || Value=="false")
670 OS << " if ((Bits & " << Target << "::"
671 << Instance << ") != 0) "
672 << Attribute << " = " << Value << ";\n";
674 OS << " if ((Bits & " << Target << "::"
675 << Instance << ") != 0 && "
676 << Attribute << " < " << Value << ") "
677 << Attribute << " = " << Value << ";\n";
684 // SubtargetEmitter::run - Main subtarget enumeration emitter.
686 void SubtargetEmitter::run(raw_ostream &OS) {
687 Target = CodeGenTarget(Records).getName();
689 EmitSourceFileHeader("Subtarget Enumeration Source Fragment", OS);
691 OS << "\n#ifdef GET_SUBTARGETINFO_ENUM\n";
692 OS << "#undef GET_SUBTARGETINFO_ENUM\n";
694 OS << "namespace llvm {\n";
695 Enumeration(OS, "SubtargetFeature", true);
696 OS << "} // End llvm namespace \n";
697 OS << "#endif // GET_SUBTARGETINFO_ENUM\n\n";
699 OS << "\n#ifdef GET_SUBTARGETINFO_MC_DESC\n";
700 OS << "#undef GET_SUBTARGETINFO_MC_DESC\n";
702 OS << "namespace llvm {\n";
704 OS << "namespace {\n";
706 unsigned NumFeatures = FeatureKeyValues(OS);
708 unsigned NumProcs = CPUKeyValues(OS);
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, ";
722 OS << Target << "FeatureKV, ";
726 OS << Target << "SubTypeKV, ";
729 if (HasItineraries) {
730 OS << Target << "ProcItinKV, "
731 << Target << "Stages, "
732 << Target << "OperandCycles, "
733 << Target << "ForwardingPathes, ";
735 OS << "0, 0, 0, 0, ";
736 OS << NumFeatures << ", " << NumProcs << ");\n}\n\n";
738 OS << "} // End llvm namespace \n";
740 OS << "#endif // GET_SUBTARGETINFO_MC_DESC\n\n";
742 OS << "\n#ifdef GET_SUBTARGETINFO_TARGET_DESC\n";
743 OS << "#undef GET_SUBTARGETINFO_TARGET_DESC\n";
745 OS << "#include \"llvm/Support/Debug.h\"\n";
746 OS << "#include \"llvm/Support/raw_ostream.h\"\n";
747 ParseFeaturesFunction(OS, NumFeatures, NumProcs);
749 OS << "#endif // GET_SUBTARGETINFO_TARGET_DESC\n\n";
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";
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"
762 << " DFAPacketizer *createDFAPacketizer(const InstrItineraryData *IID)"
765 OS << "} // End llvm namespace \n";
767 OS << "#endif // GET_SUBTARGETINFO_HEADER\n\n";
769 OS << "\n#ifdef GET_SUBTARGETINFO_CTOR\n";
770 OS << "#undef GET_SUBTARGETINFO_CTOR\n";
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";
782 OS << ClassName << "::" << ClassName << "(StringRef TT, StringRef CPU, "
784 << " : TargetSubtargetInfo() {\n"
785 << " InitMCSubtargetInfo(TT, CPU, FS, ";
787 OS << Target << "FeatureKV, ";
791 OS << Target << "SubTypeKV, ";
794 if (HasItineraries) {
795 OS << Target << "ProcItinKV, "
796 << Target << "Stages, "
797 << Target << "OperandCycles, "
798 << Target << "ForwardingPathes, ";
800 OS << "0, 0, 0, 0, ";
801 OS << NumFeatures << ", " << NumProcs << ");\n}\n\n";
802 OS << "} // End llvm namespace \n";
804 OS << "#endif // GET_SUBTARGETINFO_CTOR\n\n";