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"
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());
36 for (unsigned i
= 0, N
= DefList
.size(); i
< N
;) {
38 Record
*Def
= DefList
[i
];
41 OS
<< " " << Def
->getName();
43 // If bit flags then emit expression (1 << i)
44 if (isBits
) OS
<< " = " << " 1 << " << i
;
46 // Depending on 'if more in the list' emit comma
47 if (++i
< N
) OS
<< ",";
57 // FeatureKeyValues - Emit data of all the subtarget features. Used by the
60 void SubtargetEmitter::FeatureKeyValues(raw_ostream
&OS
) {
61 // Gather and sort all the features
62 std::vector
<Record
*> FeatureList
=
63 Records
.getAllDerivedDefinitions("SubtargetFeature");
64 std::sort(FeatureList
.begin(), FeatureList
.end(), LessRecordFieldName());
66 // Begin feature table
67 OS
<< "// Sorted (by key) array of values for CPU features.\n"
68 << "static const llvm::SubtargetFeatureKV FeatureKV[] = {\n";
71 for (unsigned i
= 0, N
= FeatureList
.size(); i
< N
; ++i
) {
73 Record
*Feature
= FeatureList
[i
];
75 const std::string
&Name
= Feature
->getName();
76 const std::string
&CommandLineName
= Feature
->getValueAsString("Name");
77 const std::string
&Desc
= Feature
->getValueAsString("Desc");
79 if (CommandLineName
.empty()) continue;
81 // Emit as { "feature", "description", featureEnum, i1 | i2 | ... | in }
83 << "\"" << CommandLineName
<< "\", "
84 << "\"" << Desc
<< "\", "
87 const std::vector
<Record
*> &ImpliesList
=
88 Feature
->getValueAsListOfDefs("Implies");
90 if (ImpliesList
.empty()) {
93 for (unsigned j
= 0, M
= ImpliesList
.size(); j
< M
;) {
94 OS
<< ImpliesList
[j
]->getName();
95 if (++j
< M
) OS
<< " | ";
101 // Depending on 'if more in the list' emit comma
102 if ((i
+ 1) < N
) OS
<< ",";
110 // Emit size of table
112 OS
<<" FeatureKVSize = sizeof(FeatureKV)/sizeof(llvm::SubtargetFeatureKV)\n";
117 // CPUKeyValues - Emit data of all the subtarget processors. Used by command
120 void SubtargetEmitter::CPUKeyValues(raw_ostream
&OS
) {
121 // Gather and sort processor information
122 std::vector
<Record
*> ProcessorList
=
123 Records
.getAllDerivedDefinitions("Processor");
124 std::sort(ProcessorList
.begin(), ProcessorList
.end(), LessRecordFieldName());
126 // Begin processor table
127 OS
<< "// Sorted (by key) array of values for CPU subtype.\n"
128 << "static const llvm::SubtargetFeatureKV SubTypeKV[] = {\n";
130 // For each processor
131 for (unsigned i
= 0, N
= ProcessorList
.size(); i
< N
;) {
133 Record
*Processor
= ProcessorList
[i
];
135 const std::string
&Name
= Processor
->getValueAsString("Name");
136 const std::vector
<Record
*> &FeatureList
=
137 Processor
->getValueAsListOfDefs("Features");
139 // Emit as { "cpu", "description", f1 | f2 | ... fn },
141 << "\"" << Name
<< "\", "
142 << "\"Select the " << Name
<< " processor\", ";
144 if (FeatureList
.empty()) {
147 for (unsigned j
= 0, M
= FeatureList
.size(); j
< M
;) {
148 OS
<< FeatureList
[j
]->getName();
149 if (++j
< M
) OS
<< " | ";
153 // The "0" is for the "implies" section of this data structure.
156 // Depending on 'if more in the list' emit comma
157 if (++i
< N
) OS
<< ",";
162 // End processor table
165 // Emit size of table
167 OS
<<" SubTypeKVSize = sizeof(SubTypeKV)/sizeof(llvm::SubtargetFeatureKV)\n";
172 // CollectAllItinClasses - Gathers and enumerates all the itinerary classes.
173 // Returns itinerary class count.
175 unsigned SubtargetEmitter::CollectAllItinClasses(raw_ostream
&OS
,
176 std::map
<std::string
, unsigned> &ItinClassesMap
) {
177 // Gather and sort all itinerary classes
178 std::vector
<Record
*> ItinClassList
=
179 Records
.getAllDerivedDefinitions("InstrItinClass");
180 std::sort(ItinClassList
.begin(), ItinClassList
.end(), LessRecord());
182 // For each itinerary class
183 unsigned N
= ItinClassList
.size();
184 for (unsigned i
= 0; i
< N
; i
++) {
185 // Next itinerary class
186 const Record
*ItinClass
= ItinClassList
[i
];
187 // Get name of itinerary class
188 // Assign itinerary class a unique number
189 ItinClassesMap
[ItinClass
->getName()] = i
;
192 // Emit size of table
194 OS
<<" ItinClassesSize = " << N
<< "\n";
197 // Return itinerary class count
202 // FormItineraryStageString - Compose a string containing the stage
203 // data initialization for the specified itinerary. N is the number
206 void SubtargetEmitter::FormItineraryStageString(Record
*ItinData
,
207 std::string
&ItinString
,
210 const std::vector
<Record
*> &StageList
=
211 ItinData
->getValueAsListOfDefs("Stages");
214 unsigned N
= NStages
= StageList
.size();
215 for (unsigned i
= 0; i
< N
;) {
217 const Record
*Stage
= StageList
[i
];
219 // Form string as ,{ cycles, u1 | u2 | ... | un, timeinc }
220 int Cycles
= Stage
->getValueAsInt("Cycles");
221 ItinString
+= " { " + itostr(Cycles
) + ", ";
224 const std::vector
<Record
*> &UnitList
= Stage
->getValueAsListOfDefs("Units");
227 for (unsigned j
= 0, M
= UnitList
.size(); j
< M
;) {
228 // Add name and bitwise or
229 ItinString
+= UnitList
[j
]->getName();
230 if (++j
< M
) ItinString
+= " | ";
233 int TimeInc
= Stage
->getValueAsInt("TimeInc");
234 ItinString
+= ", " + itostr(TimeInc
);
238 if (++i
< N
) ItinString
+= ", ";
243 // FormItineraryOperandCycleString - Compose a string containing the
244 // operand cycle initialization for the specified itinerary. N is the
245 // number of operands that has cycles specified.
247 void SubtargetEmitter::FormItineraryOperandCycleString(Record
*ItinData
,
248 std::string
&ItinString
, unsigned &NOperandCycles
) {
249 // Get operand cycle list
250 const std::vector
<int64_t> &OperandCycleList
=
251 ItinData
->getValueAsListOfInts("OperandCycles");
253 // For each operand cycle
254 unsigned N
= NOperandCycles
= OperandCycleList
.size();
255 for (unsigned i
= 0; i
< N
;) {
256 // Next operand cycle
257 const int OCycle
= OperandCycleList
[i
];
259 ItinString
+= " " + itostr(OCycle
);
260 if (++i
< N
) ItinString
+= ", ";
265 // EmitStageAndOperandCycleData - Generate unique itinerary stages and
266 // operand cycle tables. Record itineraries for processors.
268 void SubtargetEmitter::EmitStageAndOperandCycleData(raw_ostream
&OS
,
269 unsigned NItinClasses
,
270 std::map
<std::string
, unsigned> &ItinClassesMap
,
271 std::vector
<std::vector
<InstrItinerary
> > &ProcList
) {
272 // Gather processor iteraries
273 std::vector
<Record
*> ProcItinList
=
274 Records
.getAllDerivedDefinitions("ProcessorItineraries");
276 // If just no itinerary then don't bother
277 if (ProcItinList
.size() < 2) return;
279 // Begin stages table
280 std::string StageTable
= "static const llvm::InstrStage Stages[] = {\n";
281 StageTable
+= " { 0, 0, 0 }, // No itinerary\n";
283 // Begin operand cycle table
284 std::string OperandCycleTable
= "static const unsigned OperandCycles[] = {\n";
285 OperandCycleTable
+= " 0, // No itinerary\n";
287 unsigned StageCount
= 1, OperandCycleCount
= 1;
288 unsigned ItinStageEnum
= 1, ItinOperandCycleEnum
= 1;
289 std::map
<std::string
, unsigned> ItinStageMap
, ItinOperandCycleMap
;
290 for (unsigned i
= 0, N
= ProcItinList
.size(); i
< N
; i
++) {
292 Record
*Proc
= ProcItinList
[i
];
294 // Get processor itinerary name
295 const std::string
&Name
= Proc
->getName();
298 if (Name
== "NoItineraries") continue;
300 // Create and expand processor itinerary to cover all itinerary classes
301 std::vector
<InstrItinerary
> ItinList
;
302 ItinList
.resize(NItinClasses
);
304 // Get itinerary data list
305 std::vector
<Record
*> ItinDataList
= Proc
->getValueAsListOfDefs("IID");
307 // For each itinerary data
308 for (unsigned j
= 0, M
= ItinDataList
.size(); j
< M
; j
++) {
309 // Next itinerary data
310 Record
*ItinData
= ItinDataList
[j
];
312 // Get string and stage count
313 std::string ItinStageString
;
315 FormItineraryStageString(ItinData
, ItinStageString
, NStages
);
317 // Get string and operand cycle count
318 std::string ItinOperandCycleString
;
319 unsigned NOperandCycles
;
320 FormItineraryOperandCycleString(ItinData
, ItinOperandCycleString
,
323 // Check to see if stage already exists and create if it doesn't
324 unsigned FindStage
= 0;
326 FindStage
= ItinStageMap
[ItinStageString
];
327 if (FindStage
== 0) {
328 // Emit as { cycles, u1 | u2 | ... | un, timeinc }, // index
329 StageTable
+= ItinStageString
+ ", // " + itostr(ItinStageEnum
) + "\n";
330 // Record Itin class number.
331 ItinStageMap
[ItinStageString
] = FindStage
= StageCount
;
332 StageCount
+= NStages
;
337 // Check to see if operand cycle already exists and create if it doesn't
338 unsigned FindOperandCycle
= 0;
339 if (NOperandCycles
> 0) {
340 FindOperandCycle
= ItinOperandCycleMap
[ItinOperandCycleString
];
341 if (FindOperandCycle
== 0) {
342 // Emit as cycle, // index
343 OperandCycleTable
+= ItinOperandCycleString
+ ", // " +
344 itostr(ItinOperandCycleEnum
) + "\n";
345 // Record Itin class number.
346 ItinOperandCycleMap
[ItinOperandCycleString
] =
347 FindOperandCycle
= OperandCycleCount
;
348 OperandCycleCount
+= NOperandCycles
;
349 ItinOperandCycleEnum
++;
353 // Set up itinerary as location and location + stage count
354 InstrItinerary Intinerary
= { FindStage
, FindStage
+ NStages
,
355 FindOperandCycle
, FindOperandCycle
+ NOperandCycles
};
357 // Locate where to inject into processor itinerary table
358 const std::string
&Name
= ItinData
->getValueAsDef("TheClass")->getName();
359 unsigned Find
= ItinClassesMap
[Name
];
361 // Inject - empty slots will be 0, 0
362 ItinList
[Find
] = Intinerary
;
365 // Add process itinerary to list
366 ProcList
.push_back(ItinList
);
370 StageTable
+= " { 0, 0, 0 } // End itinerary\n";
371 StageTable
+= "};\n";
373 // Closing operand cycles
374 OperandCycleTable
+= " 0 // End itinerary\n";
375 OperandCycleTable
+= "};\n";
379 OS
<< OperandCycleTable
;
381 // Emit size of tables
383 OS
<<" StagesSize = sizeof(Stages)/sizeof(llvm::InstrStage),\n";
384 OS
<<" OperandCyclesSize = sizeof(OperandCycles)/sizeof(unsigned)\n";
389 // EmitProcessorData - Generate data for processor itineraries.
391 void SubtargetEmitter::EmitProcessorData(raw_ostream
&OS
,
392 std::vector
<std::vector
<InstrItinerary
> > &ProcList
) {
393 // Get an iterator for processor itinerary stages
394 std::vector
<std::vector
<InstrItinerary
> >::iterator
395 ProcListIter
= ProcList
.begin();
397 // For each processor itinerary
398 std::vector
<Record
*> Itins
=
399 Records
.getAllDerivedDefinitions("ProcessorItineraries");
400 for (unsigned i
= 0, N
= Itins
.size(); i
< N
; i
++) {
402 Record
*Itin
= Itins
[i
];
404 // Get processor itinerary name
405 const std::string
&Name
= Itin
->getName();
408 if (Name
== "NoItineraries") continue;
410 // Begin processor itinerary table
412 OS
<< "static const llvm::InstrItinerary " << Name
<< "[] = {\n";
414 // For each itinerary class
415 std::vector
<InstrItinerary
> &ItinList
= *ProcListIter
++;
416 for (unsigned j
= 0, M
= ItinList
.size(); j
< M
;) {
417 InstrItinerary
&Intinerary
= ItinList
[j
];
419 // Emit in the form of
420 // { firstStage, lastStage, firstCycle, lastCycle } // index
421 if (Intinerary
.FirstStage
== 0) {
422 OS
<< " { 0, 0, 0, 0 }";
424 OS
<< " { " << Intinerary
.FirstStage
<< ", " <<
425 Intinerary
.LastStage
<< ", " <<
426 Intinerary
.FirstOperandCycle
<< ", " <<
427 Intinerary
.LastOperandCycle
<< " }";
430 // If more in list add comma
431 if (++j
< M
) OS
<< ",";
433 OS
<< " // " << (j
- 1) << "\n";
436 // End processor itinerary table
442 // EmitProcessorLookup - generate cpu name to itinerary lookup table.
444 void SubtargetEmitter::EmitProcessorLookup(raw_ostream
&OS
) {
445 // Gather and sort processor information
446 std::vector
<Record
*> ProcessorList
=
447 Records
.getAllDerivedDefinitions("Processor");
448 std::sort(ProcessorList
.begin(), ProcessorList
.end(), LessRecordFieldName());
450 // Begin processor table
452 OS
<< "// Sorted (by key) array of itineraries for CPU subtype.\n"
453 << "static const llvm::SubtargetInfoKV ProcItinKV[] = {\n";
455 // For each processor
456 for (unsigned i
= 0, N
= ProcessorList
.size(); i
< N
;) {
458 Record
*Processor
= ProcessorList
[i
];
460 const std::string
&Name
= Processor
->getValueAsString("Name");
461 const std::string
&ProcItin
=
462 Processor
->getValueAsDef("ProcItin")->getName();
464 // Emit as { "cpu", procinit },
466 << "\"" << Name
<< "\", "
467 << "(void *)&" << ProcItin
;
471 // Depending on ''if more in the list'' emit comma
472 if (++i
< N
) OS
<< ",";
477 // End processor table
480 // Emit size of table
482 OS
<<" ProcItinKVSize = sizeof(ProcItinKV)/"
483 "sizeof(llvm::SubtargetInfoKV)\n";
488 // EmitData - Emits all stages and itineries, folding common patterns.
490 void SubtargetEmitter::EmitData(raw_ostream
&OS
) {
491 std::map
<std::string
, unsigned> ItinClassesMap
;
492 std::vector
<std::vector
<InstrItinerary
> > ProcList
;
494 // Enumerate all the itinerary classes
495 unsigned NItinClasses
= CollectAllItinClasses(OS
, ItinClassesMap
);
496 // Make sure the rest is worth the effort
497 HasItineraries
= NItinClasses
!= 1; // Ignore NoItinerary.
499 if (HasItineraries
) {
500 // Emit the stage data
501 EmitStageAndOperandCycleData(OS
, NItinClasses
, ItinClassesMap
, ProcList
);
502 // Emit the processor itinerary data
503 EmitProcessorData(OS
, ProcList
);
504 // Emit the processor lookup data
505 EmitProcessorLookup(OS
);
510 // ParseFeaturesFunction - Produces a subtarget specific function for parsing
511 // the subtarget features string.
513 void SubtargetEmitter::ParseFeaturesFunction(raw_ostream
&OS
) {
514 std::vector
<Record
*> Features
=
515 Records
.getAllDerivedDefinitions("SubtargetFeature");
516 std::sort(Features
.begin(), Features
.end(), LessRecord());
518 OS
<< "// ParseSubtargetFeatures - Parses features string setting specified\n"
519 << "// subtarget options.\n"
520 << "std::string llvm::";
522 OS
<< "Subtarget::ParseSubtargetFeatures(const std::string &FS,\n"
523 << " const std::string &CPU) {\n"
524 << " SubtargetFeatures Features(FS);\n"
525 << " Features.setCPUIfNone(CPU);\n"
526 << " uint32_t Bits = Features.getBits(SubTypeKV, SubTypeKVSize,\n"
527 << " FeatureKV, FeatureKVSize);\n";
529 for (unsigned i
= 0; i
< Features
.size(); i
++) {
531 Record
*R
= Features
[i
];
532 const std::string
&Instance
= R
->getName();
533 const std::string
&Value
= R
->getValueAsString("Value");
534 const std::string
&Attribute
= R
->getValueAsString("Attribute");
536 if (Value
=="true" || Value
=="false")
537 OS
<< " if ((Bits & " << Instance
<< ") != 0) "
538 << Attribute
<< " = " << Value
<< ";\n";
540 OS
<< " if ((Bits & " << Instance
<< ") != 0 && " << Attribute
<<
541 " < " << Value
<< ") " << Attribute
<< " = " << Value
<< ";\n";
544 if (HasItineraries
) {
546 << " InstrItinerary *Itinerary = (InstrItinerary *)"
547 << "Features.getInfo(ProcItinKV, ProcItinKVSize);\n"
548 << " InstrItins = InstrItineraryData(Stages, OperandCycles, Itinerary);\n";
551 OS
<< " return Features.getCPU();\n"
556 // SubtargetEmitter::run - Main subtarget enumeration emitter.
558 void SubtargetEmitter::run(raw_ostream
&OS
) {
559 Target
= CodeGenTarget().getName();
561 EmitSourceFileHeader("Subtarget Enumeration Source Fragment", OS
);
563 OS
<< "#include \"llvm/Target/SubtargetFeature.h\"\n";
564 OS
<< "#include \"llvm/Target/TargetInstrItineraries.h\"\n\n";
566 Enumeration(OS
, "FuncUnit", true);
568 // Enumeration(OS, "InstrItinClass", false);
570 Enumeration(OS
, "SubtargetFeature", true);
572 FeatureKeyValues(OS
);
578 ParseFeaturesFunction(OS
);