1 //===- SubtargetEmitter.cpp - Generate subtarget enumerations -------------===//
3 // The LLVM Compiler Infrastructure
5 // This file was developed by James M. Laskey and is distributed under
6 // the University of Illinois Open Source 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"
25 typedef std::vector<Record*> RecordList;
27 struct RecordListIter {
28 std::vector<Record*>::iterator RI;
29 std::vector<Record*>::iterator E;
31 RecordListIter(RecordList &RL)
32 : RI(RL.begin()), E(RL.end())
35 bool isMore() const { return RI != E; }
37 Record *next() { return isMore() ? *RI++ : NULL; }
45 DefListIter(Record *R, const std::string &Name)
46 : List(R->getValueAsListInit(Name)), N(List->getSize()), i(0)
49 bool isMore() const { return i < N; }
53 if (DefInit *DI = dynamic_cast<DefInit*>(List->getElement(i++))) {
62 // Record sort by name function.
65 bool operator()(const Record *Rec1, const Record *Rec2) const {
66 return Rec1->getName() < Rec2->getName();
71 // Record sort by field "Name" function.
73 struct LessRecordFieldName {
74 bool operator()(const Record *Rec1, const Record *Rec2) const {
75 return Rec1->getValueAsString("Name") < Rec2->getValueAsString("Name");
80 // Enumeration - Emit the specified class as an enumeration.
82 void SubtargetEmitter::Enumeration(std::ostream &OS,
83 const char *ClassName,
85 RecordList Defs = Records.getAllDerivedDefinitions(ClassName);
86 sort(Defs.begin(), Defs.end(), LessRecord());
92 RecordListIter DI(Defs);
93 while (Record *R = DI.next()) {
94 std::string Instance = R->getName();
101 OS << (DI.isMore() ? ",\n" : "\n");
108 // FeatureKeyValues - Emit data of all the subtarget features. Used by command
111 void SubtargetEmitter::FeatureKeyValues(std::ostream &OS) {
112 RecordList Features = Records.getAllDerivedDefinitions("SubtargetFeature");
113 sort(Features.begin(), Features.end(), LessRecord());
115 OS << "// Sorted (by key) array of values for CPU features.\n"
116 << "static llvm::SubtargetFeatureKV FeatureKV[] = {\n";
117 RecordListIter FI(Features);
118 while (Record *R = FI.next()) {
119 std::string Instance = R->getName();
120 std::string Name = R->getValueAsString("Name");
121 std::string Desc = R->getValueAsString("Desc");
123 << "\"" << Name << "\", "
124 << "\"" << Desc << "\", "
126 << (FI.isMore() ? " },\n" : " }\n");
131 OS<<" FeatureKVSize = sizeof(FeatureKV)/sizeof(llvm::SubtargetFeatureKV)\n";
136 // CPUKeyValues - Emit data of all the subtarget processors. Used by command
139 void SubtargetEmitter::CPUKeyValues(std::ostream &OS) {
140 RecordList Processors = Records.getAllDerivedDefinitions("Processor");
141 sort(Processors.begin(), Processors.end(), LessRecordFieldName());
143 OS << "// Sorted (by key) array of values for CPU subtype.\n"
144 << "static const llvm::SubtargetFeatureKV SubTypeKV[] = {\n";
145 RecordListIter PI(Processors);
146 while (Record *R = PI.next()) {
147 std::string Name = R->getValueAsString("Name");
148 DefListIter FI(R, "Features");
151 << "\"" << Name << "\", "
152 << "\"Select the " << Name << " processor\", ";
157 while (Record *Feature = FI.next()) {
158 std::string Name = Feature->getName();
160 if (FI.isMore()) OS << " | ";
164 OS << (PI.isMore() ? " },\n" : " }\n");
169 OS<<" SubTypeKVSize = sizeof(SubTypeKV)/sizeof(llvm::SubtargetFeatureKV)\n";
174 // CollectAllItinClasses - Gathers and enumerates all the itinerary classes.
176 unsigned SubtargetEmitter::CollectAllItinClasses(IntMap &ItinClassesMap) {
177 RecordList ICL = Records.getAllDerivedDefinitions("InstrItinClass");
178 sort(ICL.begin(), ICL.end(), LessRecord());
180 RecordListIter ICI(ICL);
182 while (Record *ItinClass = ICI.next()) {
183 std::string Name = ItinClass->getName();
184 ItinClassesMap[Name] = Index++;
191 // FormItineraryString - Compose a string containing the data initialization
192 // for the specified itinerary. N is the number of stages.
194 void SubtargetEmitter::FormItineraryString(Record *ItinData,
195 std::string &ItinString,
197 DefListIter SLI(ItinData, "Stages");
199 while (Record *Stage = SLI.next()) {
200 int Cycles = Stage->getValueAsInt("Cycles");
201 ItinString += " ,{ " + itostr(Cycles) + ", ";
203 DefListIter ULI(Stage, "Units");
204 while (Record *Unit = ULI.next()) {
205 std::string Name = Unit->getName();
207 if (ULI.isMore())ItinString += " | ";
215 // EmitStageData - Generate unique itinerary stages. Record itineraries for
218 void SubtargetEmitter::EmitStageData(std::ostream &OS,
220 IntMap &ItinClassesMap,
221 ProcessorList &ProcList) {
222 OS << "static llvm::InstrStage Stages[] = {\n"
223 " { 0, 0 } // No itinerary\n";
227 RecordList Itins = Records.getAllDerivedDefinitions("ProcessorItineraries");
228 RecordListIter II(Itins);
229 while (Record *Itin = II.next()) {
230 std::string Name = Itin->getName();
231 if (Name == "NoItineraries") continue;
236 DefListIter IDLI(Itin, "IID");
237 while (Record *ItinData = IDLI.next()) {
238 std::string ItinString;
240 FormItineraryString(ItinData, ItinString, M);
242 unsigned Find = ItinMap[ItinString];
245 OS << ItinString << " // " << Index << "\n";
246 ItinMap[ItinString] = Find = Index++;
249 InstrItinerary Intinerary = { Find, Find + M };
251 std::string Name = ItinData->getValueAsDef("TheClass")->getName();
252 Find = ItinClassesMap[Name];
253 IL[Find] = Intinerary;
256 ProcList.push_back(IL);
263 // EmitProcessData - Generate data for processor itineraries.
265 void SubtargetEmitter::EmitProcessData(std::ostream &OS,
266 ProcessorList &ProcList) {
267 ProcessorList::iterator PLI = ProcList.begin();
268 RecordList Itins = Records.getAllDerivedDefinitions("ProcessorItineraries");
269 RecordListIter II(Itins);
270 while (Record *Itin = II.next()) {
271 std::string Name = Itin->getName();
272 if (Name == "NoItineraries") continue;
275 OS << "static llvm::InstrItinerary " << Name << "[] = {\n";
277 IntineraryList &IL = *PLI++;
279 for (IntineraryList::iterator ILI = IL.begin(), E = IL.end(); ILI != E;) {
280 InstrItinerary &Intinerary = *ILI++;
282 if (Intinerary.First == 0) {
285 OS << " { " << Intinerary.First << ", " << Intinerary.Last << " }";
288 if (ILI != E) OS << ",";
289 OS << " // " << Index++ << "\n";
296 // EmitData - Emits all stages and itineries, folding common patterns.
298 void SubtargetEmitter::EmitData(std::ostream &OS) {
299 IntMap ItinClassesMap;
300 ProcessorList ProcList;
302 unsigned N = CollectAllItinClasses(ItinClassesMap);
303 EmitStageData(OS, N, ItinClassesMap, ProcList);
304 EmitProcessData(OS, ProcList);
308 // ParseFeaturesFunction - Produces a subtarget specific function for parsing
309 // the subtarget features string.
311 void SubtargetEmitter::ParseFeaturesFunction(std::ostream &OS) {
312 RecordList Features = Records.getAllDerivedDefinitions("SubtargetFeature");
313 sort(Features.begin(), Features.end(), LessRecord());
315 OS << "// ParseSubtargetFeatures - Parses features string setting specified\n"
316 "// subtarget options.\n"
319 OS << "Subtarget::ParseSubtargetFeatures(const std::string &FS,\n"
320 " const std::string &CPU) {\n"
321 " SubtargetFeatures Features(FS);\n"
322 " Features.setCPUIfNone(CPU);\n"
323 " uint32_t Bits = Features.getBits(SubTypeKV, SubTypeKVSize,\n"
324 " FeatureKV, FeatureKVSize);\n";
326 RecordListIter FI(Features);
327 while (Record *R = FI.next()) {
328 std::string Instance = R->getName();
329 std::string Name = R->getValueAsString("Name");
330 std::string Type = R->getValueAsString("Type");
331 std::string Attribute = R->getValueAsString("Attribute");
333 OS << " " << Attribute << " = (Bits & " << Instance << ") != 0;\n";
339 // SubtargetEmitter::run - Main subtarget enumeration emitter.
341 void SubtargetEmitter::run(std::ostream &OS) {
342 Target = CodeGenTarget().getName();
344 EmitSourceFileHeader("Subtarget Enumeration Source Fragment", OS);
346 OS << "#include \"llvm/Target/SubtargetFeature.h\"\n";
347 OS << "#include \"llvm/Target/TargetInstrItineraries.h\"\n\n";
349 Enumeration(OS, "FuncUnit", true);
351 Enumeration(OS, "InstrItinClass", false);
353 Enumeration(OS, "SubtargetFeature", true);
355 FeatureKeyValues(OS);
361 ParseFeaturesFunction(OS);