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 "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"
30 class SubtargetEmitter {
32 RecordKeeper &Records;
33 CodeGenSchedModels &SchedModels;
36 void Enumeration(raw_ostream &OS, const char *ClassName, bool isBits);
37 unsigned FeatureKeyValues(raw_ostream &OS);
38 unsigned CPUKeyValues(raw_ostream &OS);
39 void FormItineraryStageString(const std::string &Names,
40 Record *ItinData, std::string &ItinString,
42 void FormItineraryOperandCycleString(Record *ItinData, std::string &ItinString,
43 unsigned &NOperandCycles);
44 void FormItineraryBypassString(const std::string &Names,
46 std::string &ItinString, unsigned NOperandCycles);
47 void EmitStageAndOperandCycleData(raw_ostream &OS,
48 std::vector<std::vector<InstrItinerary> >
50 void EmitItineraries(raw_ostream &OS,
51 std::vector<std::vector<InstrItinerary> >
53 void EmitProcessorProp(raw_ostream &OS, const Record *R, const char *Name,
55 void EmitProcessorResources(const CodeGenProcModel &ProcModel,
57 void EmitProcessorModels(raw_ostream &OS);
58 void EmitProcessorLookup(raw_ostream &OS);
59 void EmitSchedModel(raw_ostream &OS);
60 void ParseFeaturesFunction(raw_ostream &OS, unsigned NumFeatures,
64 SubtargetEmitter(RecordKeeper &R, CodeGenTarget &TGT):
65 Records(R), SchedModels(TGT.getSchedModels()), Target(TGT.getName()) {}
67 void run(raw_ostream &o);
70 } // End anonymous namespace
73 // Enumeration - Emit the specified class as an enumeration.
75 void SubtargetEmitter::Enumeration(raw_ostream &OS,
76 const char *ClassName,
78 // Get all records of class and sort
79 std::vector<Record*> DefList = Records.getAllDerivedDefinitions(ClassName);
80 std::sort(DefList.begin(), DefList.end(), LessRecord());
82 unsigned N = DefList.size();
86 errs() << "Too many (> 64) subtarget features!\n";
90 OS << "namespace " << Target << " {\n";
92 // For bit flag enumerations with more than 32 items, emit constants.
93 // Emit an enum for everything else.
94 if (isBits && N > 32) {
96 for (unsigned i = 0; i < N; i++) {
98 Record *Def = DefList[i];
100 // Get and emit name and expression (1 << i)
101 OS << " const uint64_t " << Def->getName() << " = 1ULL << " << i << ";\n";
108 for (unsigned i = 0; i < N;) {
110 Record *Def = DefList[i];
113 OS << " " << Def->getName();
115 // If bit flags then emit expression (1 << i)
116 if (isBits) OS << " = " << " 1ULL << " << i;
118 // Depending on 'if more in the list' emit comma
119 if (++i < N) OS << ",";
132 // FeatureKeyValues - Emit data of all the subtarget features. Used by the
135 unsigned SubtargetEmitter::FeatureKeyValues(raw_ostream &OS) {
136 // Gather and sort all the features
137 std::vector<Record*> FeatureList =
138 Records.getAllDerivedDefinitions("SubtargetFeature");
140 if (FeatureList.empty())
143 std::sort(FeatureList.begin(), FeatureList.end(), LessRecordFieldName());
145 // Begin feature table
146 OS << "// Sorted (by key) array of values for CPU features.\n"
147 << "extern const llvm::SubtargetFeatureKV " << Target
148 << "FeatureKV[] = {\n";
151 unsigned NumFeatures = 0;
152 for (unsigned i = 0, N = FeatureList.size(); i < N; ++i) {
154 Record *Feature = FeatureList[i];
156 const std::string &Name = Feature->getName();
157 const std::string &CommandLineName = Feature->getValueAsString("Name");
158 const std::string &Desc = Feature->getValueAsString("Desc");
160 if (CommandLineName.empty()) continue;
162 // Emit as { "feature", "description", featureEnum, i1 | i2 | ... | in }
164 << "\"" << CommandLineName << "\", "
165 << "\"" << Desc << "\", "
166 << Target << "::" << Name << ", ";
168 const std::vector<Record*> &ImpliesList =
169 Feature->getValueAsListOfDefs("Implies");
171 if (ImpliesList.empty()) {
174 for (unsigned j = 0, M = ImpliesList.size(); j < M;) {
175 OS << Target << "::" << ImpliesList[j]->getName();
176 if (++j < M) OS << " | ";
183 // Depending on 'if more in the list' emit comma
184 if ((i + 1) < N) OS << ",";
196 // CPUKeyValues - Emit data of all the subtarget processors. Used by command
199 unsigned SubtargetEmitter::CPUKeyValues(raw_ostream &OS) {
200 // Gather and sort processor information
201 std::vector<Record*> ProcessorList =
202 Records.getAllDerivedDefinitions("Processor");
203 std::sort(ProcessorList.begin(), ProcessorList.end(), LessRecordFieldName());
205 // Begin processor table
206 OS << "// Sorted (by key) array of values for CPU subtype.\n"
207 << "extern const llvm::SubtargetFeatureKV " << Target
208 << "SubTypeKV[] = {\n";
210 // For each processor
211 for (unsigned i = 0, N = ProcessorList.size(); i < N;) {
213 Record *Processor = ProcessorList[i];
215 const std::string &Name = Processor->getValueAsString("Name");
216 const std::vector<Record*> &FeatureList =
217 Processor->getValueAsListOfDefs("Features");
219 // Emit as { "cpu", "description", f1 | f2 | ... fn },
221 << "\"" << Name << "\", "
222 << "\"Select the " << Name << " processor\", ";
224 if (FeatureList.empty()) {
227 for (unsigned j = 0, M = FeatureList.size(); j < M;) {
228 OS << Target << "::" << FeatureList[j]->getName();
229 if (++j < M) OS << " | ";
233 // The "0" is for the "implies" section of this data structure.
236 // Depending on 'if more in the list' emit comma
237 if (++i < N) OS << ",";
242 // End processor table
245 return ProcessorList.size();
249 // FormItineraryStageString - Compose a string containing the stage
250 // data initialization for the specified itinerary. N is the number
253 void SubtargetEmitter::FormItineraryStageString(const std::string &Name,
255 std::string &ItinString,
258 const std::vector<Record*> &StageList =
259 ItinData->getValueAsListOfDefs("Stages");
262 unsigned N = NStages = StageList.size();
263 for (unsigned i = 0; i < N;) {
265 const Record *Stage = StageList[i];
267 // Form string as ,{ cycles, u1 | u2 | ... | un, timeinc, kind }
268 int Cycles = Stage->getValueAsInt("Cycles");
269 ItinString += " { " + itostr(Cycles) + ", ";
272 const std::vector<Record*> &UnitList = Stage->getValueAsListOfDefs("Units");
275 for (unsigned j = 0, M = UnitList.size(); j < M;) {
276 // Add name and bitwise or
277 ItinString += Name + "FU::" + UnitList[j]->getName();
278 if (++j < M) ItinString += " | ";
281 int TimeInc = Stage->getValueAsInt("TimeInc");
282 ItinString += ", " + itostr(TimeInc);
284 int Kind = Stage->getValueAsInt("Kind");
285 ItinString += ", (llvm::InstrStage::ReservationKinds)" + itostr(Kind);
289 if (++i < N) ItinString += ", ";
294 // FormItineraryOperandCycleString - Compose a string containing the
295 // operand cycle initialization for the specified itinerary. N is the
296 // number of operands that has cycles specified.
298 void SubtargetEmitter::FormItineraryOperandCycleString(Record *ItinData,
299 std::string &ItinString, unsigned &NOperandCycles) {
300 // Get operand cycle list
301 const std::vector<int64_t> &OperandCycleList =
302 ItinData->getValueAsListOfInts("OperandCycles");
304 // For each operand cycle
305 unsigned N = NOperandCycles = OperandCycleList.size();
306 for (unsigned i = 0; i < N;) {
307 // Next operand cycle
308 const int OCycle = OperandCycleList[i];
310 ItinString += " " + itostr(OCycle);
311 if (++i < N) ItinString += ", ";
315 void SubtargetEmitter::FormItineraryBypassString(const std::string &Name,
317 std::string &ItinString,
318 unsigned NOperandCycles) {
319 const std::vector<Record*> &BypassList =
320 ItinData->getValueAsListOfDefs("Bypasses");
321 unsigned N = BypassList.size();
324 ItinString += Name + "Bypass::" + BypassList[i]->getName();
325 if (++i < NOperandCycles) ItinString += ", ";
327 for (; i < NOperandCycles;) {
329 if (++i < NOperandCycles) ItinString += ", ";
334 // EmitStageAndOperandCycleData - Generate unique itinerary stages and operand
335 // cycle tables. Create a list of InstrItinerary objects (ProcItinLists) indexed
336 // by CodeGenSchedClass::Index.
338 void SubtargetEmitter::
339 EmitStageAndOperandCycleData(raw_ostream &OS,
340 std::vector<std::vector<InstrItinerary> >
343 // Multiple processor models may share an itinerary record. Emit it once.
344 SmallPtrSet<Record*, 8> ItinsDefSet;
346 // Emit functional units for all the itineraries.
347 for (CodeGenSchedModels::ProcIter PI = SchedModels.procModelBegin(),
348 PE = SchedModels.procModelEnd(); PI != PE; ++PI) {
350 if (!ItinsDefSet.insert(PI->ItinsDef))
353 std::vector<Record*> FUs = PI->ItinsDef->getValueAsListOfDefs("FU");
357 const std::string &Name = PI->ItinsDef->getName();
358 OS << "\n// Functional units for \"" << Name << "\"\n"
359 << "namespace " << Name << "FU {\n";
361 for (unsigned j = 0, FUN = FUs.size(); j < FUN; ++j)
362 OS << " const unsigned " << FUs[j]->getName()
363 << " = 1 << " << j << ";\n";
367 std::vector<Record*> BPs = PI->ItinsDef->getValueAsListOfDefs("BP");
369 OS << "\n// Pipeline forwarding pathes for itineraries \"" << Name
370 << "\"\n" << "namespace " << Name << "Bypass {\n";
372 OS << " const unsigned NoBypass = 0;\n";
373 for (unsigned j = 0, BPN = BPs.size(); j < BPN; ++j)
374 OS << " const unsigned " << BPs[j]->getName()
375 << " = 1 << " << j << ";\n";
381 // Begin stages table
382 std::string StageTable = "\nextern const llvm::InstrStage " + Target +
384 StageTable += " { 0, 0, 0, llvm::InstrStage::Required }, // No itinerary\n";
386 // Begin operand cycle table
387 std::string OperandCycleTable = "extern const unsigned " + Target +
388 "OperandCycles[] = {\n";
389 OperandCycleTable += " 0, // No itinerary\n";
391 // Begin pipeline bypass table
392 std::string BypassTable = "extern const unsigned " + Target +
393 "ForwardingPaths[] = {\n";
394 BypassTable += " 0, // No itinerary\n";
396 // For each Itinerary across all processors, add a unique entry to the stages,
397 // operand cycles, and pipepine bypess tables. Then add the new Itinerary
398 // object with computed offsets to the ProcItinLists result.
399 unsigned StageCount = 1, OperandCycleCount = 1;
400 std::map<std::string, unsigned> ItinStageMap, ItinOperandMap;
401 for (CodeGenSchedModels::ProcIter PI = SchedModels.procModelBegin(),
402 PE = SchedModels.procModelEnd(); PI != PE; ++PI) {
403 const CodeGenProcModel &ProcModel = *PI;
405 // Add process itinerary to the list.
406 ProcItinLists.resize(ProcItinLists.size()+1);
408 // If this processor defines no itineraries, then leave the itinerary list
410 std::vector<InstrItinerary> &ItinList = ProcItinLists.back();
411 if (ProcModel.ItinDefList.empty())
414 // Reserve index==0 for NoItinerary.
415 ItinList.resize(SchedModels.numItineraryClasses()+1);
417 const std::string &Name = ProcModel.ItinsDef->getName();
419 // For each itinerary data
420 for (unsigned SchedClassIdx = 0,
421 SchedClassEnd = ProcModel.ItinDefList.size();
422 SchedClassIdx < SchedClassEnd; ++SchedClassIdx) {
424 // Next itinerary data
425 Record *ItinData = ProcModel.ItinDefList[SchedClassIdx];
427 // Get string and stage count
428 std::string ItinStageString;
429 unsigned NStages = 0;
431 FormItineraryStageString(Name, ItinData, ItinStageString, NStages);
433 // Get string and operand cycle count
434 std::string ItinOperandCycleString;
435 unsigned NOperandCycles = 0;
436 std::string ItinBypassString;
438 FormItineraryOperandCycleString(ItinData, ItinOperandCycleString,
441 FormItineraryBypassString(Name, ItinData, ItinBypassString,
445 // Check to see if stage already exists and create if it doesn't
446 unsigned FindStage = 0;
448 FindStage = ItinStageMap[ItinStageString];
449 if (FindStage == 0) {
450 // Emit as { cycles, u1 | u2 | ... | un, timeinc }, // indices
451 StageTable += ItinStageString + ", // " + itostr(StageCount);
453 StageTable += "-" + itostr(StageCount + NStages - 1);
455 // Record Itin class number.
456 ItinStageMap[ItinStageString] = FindStage = StageCount;
457 StageCount += NStages;
461 // Check to see if operand cycle already exists and create if it doesn't
462 unsigned FindOperandCycle = 0;
463 if (NOperandCycles > 0) {
464 std::string ItinOperandString = ItinOperandCycleString+ItinBypassString;
465 FindOperandCycle = ItinOperandMap[ItinOperandString];
466 if (FindOperandCycle == 0) {
467 // Emit as cycle, // index
468 OperandCycleTable += ItinOperandCycleString + ", // ";
469 std::string OperandIdxComment = itostr(OperandCycleCount);
470 if (NOperandCycles > 1)
471 OperandIdxComment += "-"
472 + itostr(OperandCycleCount + NOperandCycles - 1);
473 OperandCycleTable += OperandIdxComment + "\n";
474 // Record Itin class number.
475 ItinOperandMap[ItinOperandCycleString] =
476 FindOperandCycle = OperandCycleCount;
477 // Emit as bypass, // index
478 BypassTable += ItinBypassString + ", // " + OperandIdxComment + "\n";
479 OperandCycleCount += NOperandCycles;
483 // Set up itinerary as location and location + stage count
484 int NumUOps = ItinData ? ItinData->getValueAsInt("NumMicroOps") : 0;
485 InstrItinerary Intinerary = { NumUOps, FindStage, FindStage + NStages,
487 FindOperandCycle + NOperandCycles};
489 // Inject - empty slots will be 0, 0
490 ItinList[SchedClassIdx] = Intinerary;
495 StageTable += " { 0, 0, 0, llvm::InstrStage::Required } // End stages\n";
496 StageTable += "};\n";
498 // Closing operand cycles
499 OperandCycleTable += " 0 // End operand cycles\n";
500 OperandCycleTable += "};\n";
502 BypassTable += " 0 // End bypass tables\n";
503 BypassTable += "};\n";
507 OS << OperandCycleTable;
512 // EmitProcessorData - Generate data for processor itineraries that were
513 // computed during EmitStageAndOperandCycleData(). ProcItinLists lists all
514 // Itineraries for each processor. The Itinerary lists are indexed on
515 // CodeGenSchedClass::Index.
517 void SubtargetEmitter::
518 EmitItineraries(raw_ostream &OS,
519 std::vector<std::vector<InstrItinerary> > &ProcItinLists) {
521 // Multiple processor models may share an itinerary record. Emit it once.
522 SmallPtrSet<Record*, 8> ItinsDefSet;
524 // For each processor's machine model
525 std::vector<std::vector<InstrItinerary> >::iterator
526 ProcItinListsIter = ProcItinLists.begin();
527 for (CodeGenSchedModels::ProcIter PI = SchedModels.procModelBegin(),
528 PE = SchedModels.procModelEnd(); PI != PE; ++PI, ++ProcItinListsIter) {
530 Record *ItinsDef = PI->ItinsDef;
531 if (!ItinsDefSet.insert(ItinsDef))
534 // Get processor itinerary name
535 const std::string &Name = ItinsDef->getName();
537 // Get the itinerary list for the processor.
538 assert(ProcItinListsIter != ProcItinLists.end() && "bad iterator");
539 std::vector<InstrItinerary> &ItinList = *ProcItinListsIter;
542 OS << "static const llvm::InstrItinerary ";
543 if (ItinList.empty()) {
544 OS << '*' << Name << " = 0;\n";
548 // Begin processor itinerary table
549 OS << Name << "[] = {\n";
551 // For each itinerary class in CodeGenSchedClass::Index order.
552 for (unsigned j = 0, M = ItinList.size(); j < M; ++j) {
553 InstrItinerary &Intinerary = ItinList[j];
555 // Emit Itinerary in the form of
556 // { firstStage, lastStage, firstCycle, lastCycle } // index
558 Intinerary.NumMicroOps << ", " <<
559 Intinerary.FirstStage << ", " <<
560 Intinerary.LastStage << ", " <<
561 Intinerary.FirstOperandCycle << ", " <<
562 Intinerary.LastOperandCycle << " }" <<
563 ", // " << j << " " << SchedModels.getSchedClass(j).Name << "\n";
565 // End processor itinerary table
566 OS << " { 0, ~0U, ~0U, ~0U, ~0U } // end marker\n";
571 // Emit either the value defined in the TableGen Record, or the default
572 // value defined in the C++ header. The Record is null if the processor does not
574 void SubtargetEmitter::EmitProcessorProp(raw_ostream &OS, const Record *R,
575 const char *Name, char Separator) {
577 int V = R ? R->getValueAsInt(Name) : -1;
579 OS << V << Separator << " // " << Name;
581 OS << "MCSchedModel::Default" << Name << Separator;
585 void SubtargetEmitter::EmitProcessorResources(const CodeGenProcModel &ProcModel,
587 char Sep = ProcModel.ProcResourceDefs.empty() ? ' ' : ',';
589 OS << "\n// {Name, NumUnits, SuperIdx}\n";
590 OS << "static const llvm::MCProcResourceDesc "
591 << ProcModel.ModelName << "ProcResources" << "[] = {\n"
592 << " {DBGFIELD(\"InvalidUnit\") 0, 0}" << Sep << "\n";
594 for (unsigned i = 0, e = ProcModel.ProcResourceDefs.size(); i < e; ++i) {
595 Record *PRDef = ProcModel.ProcResourceDefs[i];
598 unsigned SuperIdx = 0;
599 Record *SuperDef = 0;
600 if (PRDef->getValueInit("Super")->isComplete()) {
602 SchedModels.findProcResUnits(PRDef->getValueAsDef("Super"), ProcModel);
603 SuperIdx = ProcModel.getProcResourceIdx(SuperDef);
605 // Emit the ProcResourceDesc
608 OS << " {DBGFIELD(\"" << PRDef->getName() << "\") ";
609 if (PRDef->getName().size() < 15)
610 OS.indent(15 - PRDef->getName().size());
611 OS << PRDef->getValueAsInt("NumUnits") << ", " << SuperIdx
612 << "}" << Sep << " // #" << i+1;
614 OS << ", Super=" << SuperDef->getName();
620 void SubtargetEmitter::EmitProcessorModels(raw_ostream &OS) {
621 // For each processor model.
622 for (CodeGenSchedModels::ProcIter PI = SchedModels.procModelBegin(),
623 PE = SchedModels.procModelEnd(); PI != PE; ++PI) {
624 // Emit processor resource table.
625 if (PI->hasInstrSchedModel())
626 EmitProcessorResources(*PI, OS);
627 else if(!PI->ProcResourceDefs.empty())
628 throw TGError(PI->ModelDef->getLoc(), "SchedMachineModel defines "
629 "ProcResources without defining either WriteResourcesList "
632 // Begin processor itinerary properties
634 OS << "static const llvm::MCSchedModel " << PI->ModelName << "(\n";
635 EmitProcessorProp(OS, PI->ModelDef, "IssueWidth", ',');
636 EmitProcessorProp(OS, PI->ModelDef, "MinLatency", ',');
637 EmitProcessorProp(OS, PI->ModelDef, "LoadLatency", ',');
638 EmitProcessorProp(OS, PI->ModelDef, "HighLatency", ',');
639 EmitProcessorProp(OS, PI->ModelDef, "MispredictPenalty", ',');
640 if (SchedModels.hasItineraryClasses())
641 OS << " " << PI->ItinsDef->getName() << ");\n";
643 OS << " 0); // No Itinerary\n";
648 // EmitProcessorLookup - generate cpu name to itinerary lookup table.
650 void SubtargetEmitter::EmitProcessorLookup(raw_ostream &OS) {
651 // Gather and sort processor information
652 std::vector<Record*> ProcessorList =
653 Records.getAllDerivedDefinitions("Processor");
654 std::sort(ProcessorList.begin(), ProcessorList.end(), LessRecordFieldName());
656 // Begin processor table
658 OS << "// Sorted (by key) array of itineraries for CPU subtype.\n"
659 << "extern const llvm::SubtargetInfoKV "
660 << Target << "ProcSchedKV[] = {\n";
662 // For each processor
663 for (unsigned i = 0, N = ProcessorList.size(); i < N;) {
665 Record *Processor = ProcessorList[i];
667 const std::string &Name = Processor->getValueAsString("Name");
668 const std::string &ProcModelName =
669 SchedModels.getModelForProc(Processor).ModelName;
671 // Emit as { "cpu", procinit },
672 OS << " { \"" << Name << "\", (const void *)&" << ProcModelName << " }";
674 // Depending on ''if more in the list'' emit comma
675 if (++i < N) OS << ",";
680 // End processor table
685 // EmitSchedModel - Emits all scheduling model tables, folding common patterns.
687 void SubtargetEmitter::EmitSchedModel(raw_ostream &OS) {
688 OS << "#ifdef DBGFIELD\n"
689 << "#error \"<target>GenSubtargetInfo.inc requires a DBGFIELD macro\"\n"
691 << "#ifndef NDEBUG\n"
692 << "#define DBGFIELD(x) x,\n"
694 << "#define DBGFIELD(x)\n"
697 if (SchedModels.hasItineraryClasses()) {
698 std::vector<std::vector<InstrItinerary> > ProcItinLists;
699 // Emit the stage data
700 EmitStageAndOperandCycleData(OS, ProcItinLists);
701 EmitItineraries(OS, ProcItinLists);
704 // Emit the processor machine model
705 EmitProcessorModels(OS);
706 // Emit the processor lookup data
707 EmitProcessorLookup(OS);
709 OS << "#undef DBGFIELD";
713 // ParseFeaturesFunction - Produces a subtarget specific function for parsing
714 // the subtarget features string.
716 void SubtargetEmitter::ParseFeaturesFunction(raw_ostream &OS,
717 unsigned NumFeatures,
719 std::vector<Record*> Features =
720 Records.getAllDerivedDefinitions("SubtargetFeature");
721 std::sort(Features.begin(), Features.end(), LessRecord());
723 OS << "// ParseSubtargetFeatures - Parses features string setting specified\n"
724 << "// subtarget options.\n"
727 OS << "Subtarget::ParseSubtargetFeatures(StringRef CPU, StringRef FS) {\n"
728 << " DEBUG(dbgs() << \"\\nFeatures:\" << FS);\n"
729 << " DEBUG(dbgs() << \"\\nCPU:\" << CPU << \"\\n\\n\");\n";
731 if (Features.empty()) {
736 OS << " uint64_t Bits = ReInitMCSubtargetInfo(CPU, FS);\n";
738 for (unsigned i = 0; i < Features.size(); i++) {
740 Record *R = Features[i];
741 const std::string &Instance = R->getName();
742 const std::string &Value = R->getValueAsString("Value");
743 const std::string &Attribute = R->getValueAsString("Attribute");
745 if (Value=="true" || Value=="false")
746 OS << " if ((Bits & " << Target << "::"
747 << Instance << ") != 0) "
748 << Attribute << " = " << Value << ";\n";
750 OS << " if ((Bits & " << Target << "::"
751 << Instance << ") != 0 && "
752 << Attribute << " < " << Value << ") "
753 << Attribute << " = " << Value << ";\n";
760 // SubtargetEmitter::run - Main subtarget enumeration emitter.
762 void SubtargetEmitter::run(raw_ostream &OS) {
763 emitSourceFileHeader("Subtarget Enumeration Source Fragment", OS);
765 OS << "\n#ifdef GET_SUBTARGETINFO_ENUM\n";
766 OS << "#undef GET_SUBTARGETINFO_ENUM\n";
768 OS << "namespace llvm {\n";
769 Enumeration(OS, "SubtargetFeature", true);
770 OS << "} // End llvm namespace \n";
771 OS << "#endif // GET_SUBTARGETINFO_ENUM\n\n";
773 OS << "\n#ifdef GET_SUBTARGETINFO_MC_DESC\n";
774 OS << "#undef GET_SUBTARGETINFO_MC_DESC\n";
776 OS << "namespace llvm {\n";
778 OS << "namespace {\n";
780 unsigned NumFeatures = FeatureKeyValues(OS);
782 unsigned NumProcs = CPUKeyValues(OS);
790 // MCInstrInfo initialization routine.
791 OS << "static inline void Init" << Target
792 << "MCSubtargetInfo(MCSubtargetInfo *II, "
793 << "StringRef TT, StringRef CPU, StringRef FS) {\n";
794 OS << " II->InitMCSubtargetInfo(TT, CPU, FS, ";
796 OS << Target << "FeatureKV, ";
800 OS << Target << "SubTypeKV, ";
803 if (SchedModels.hasItineraryClasses()) {
804 OS << Target << "ProcSchedKV, "
805 << Target << "Stages, "
806 << Target << "OperandCycles, "
807 << Target << "ForwardingPaths, ";
809 OS << "0, 0, 0, 0, ";
810 OS << NumFeatures << ", " << NumProcs << ");\n}\n\n";
812 OS << "} // End llvm namespace \n";
814 OS << "#endif // GET_SUBTARGETINFO_MC_DESC\n\n";
816 OS << "\n#ifdef GET_SUBTARGETINFO_TARGET_DESC\n";
817 OS << "#undef GET_SUBTARGETINFO_TARGET_DESC\n";
819 OS << "#include \"llvm/Support/Debug.h\"\n";
820 OS << "#include \"llvm/Support/raw_ostream.h\"\n";
821 ParseFeaturesFunction(OS, NumFeatures, NumProcs);
823 OS << "#endif // GET_SUBTARGETINFO_TARGET_DESC\n\n";
825 // Create a TargetSubtargetInfo subclass to hide the MC layer initialization.
826 OS << "\n#ifdef GET_SUBTARGETINFO_HEADER\n";
827 OS << "#undef GET_SUBTARGETINFO_HEADER\n";
829 std::string ClassName = Target + "GenSubtargetInfo";
830 OS << "namespace llvm {\n";
831 OS << "class DFAPacketizer;\n";
832 OS << "struct " << ClassName << " : public TargetSubtargetInfo {\n"
833 << " explicit " << ClassName << "(StringRef TT, StringRef CPU, "
834 << "StringRef FS);\n"
836 << " DFAPacketizer *createDFAPacketizer(const InstrItineraryData *IID)"
839 OS << "} // End llvm namespace \n";
841 OS << "#endif // GET_SUBTARGETINFO_HEADER\n\n";
843 OS << "\n#ifdef GET_SUBTARGETINFO_CTOR\n";
844 OS << "#undef GET_SUBTARGETINFO_CTOR\n";
846 OS << "namespace llvm {\n";
847 OS << "extern const llvm::SubtargetFeatureKV " << Target << "FeatureKV[];\n";
848 OS << "extern const llvm::SubtargetFeatureKV " << Target << "SubTypeKV[];\n";
849 if (SchedModels.hasItineraryClasses()) {
850 OS << "extern const llvm::SubtargetInfoKV " << Target << "ProcSchedKV[];\n";
851 OS << "extern const llvm::InstrStage " << Target << "Stages[];\n";
852 OS << "extern const unsigned " << Target << "OperandCycles[];\n";
853 OS << "extern const unsigned " << Target << "ForwardingPaths[];\n";
856 OS << ClassName << "::" << ClassName << "(StringRef TT, StringRef CPU, "
858 << " : TargetSubtargetInfo() {\n"
859 << " InitMCSubtargetInfo(TT, CPU, FS, ";
861 OS << Target << "FeatureKV, ";
865 OS << Target << "SubTypeKV, ";
868 if (SchedModels.hasItineraryClasses()) {
869 OS << Target << "ProcSchedKV, "
870 << Target << "Stages, "
871 << Target << "OperandCycles, "
872 << Target << "ForwardingPaths, ";
874 OS << "0, 0, 0, 0, ";
875 OS << NumFeatures << ", " << NumProcs << ");\n}\n\n";
876 OS << "} // End llvm namespace \n";
878 OS << "#endif // GET_SUBTARGETINFO_CTOR\n\n";
883 void EmitSubtarget(RecordKeeper &RK, raw_ostream &OS) {
884 CodeGenTarget CGTarget(RK);
885 SubtargetEmitter(RK, CGTarget).run(OS);
888 } // End llvm namespace