remove dead stuff
[oota-llvm.git] / utils / TableGen / SubtargetEmitter.cpp
1 //===- SubtargetEmitter.cpp - Generate subtarget enumerations -------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
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.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This tablegen backend emits subtarget enumerations.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "SubtargetEmitter.h"
15 #include "CodeGenTarget.h"
16 #include "Record.h"
17 #include "llvm/ADT/StringExtras.h"
18 #include "llvm/Support/Debug.h"
19 #include <algorithm>
20 using namespace llvm;
21
22 //
23 // Convenience types.
24 //
25 typedef std::vector<Record*> RecordList;
26
27 struct RecordListIter {
28   std::vector<Record*>::iterator RI;
29   std::vector<Record*>::iterator E;
30   
31   RecordListIter(RecordList &RL)
32       : RI(RL.begin()), E(RL.end())
33   {}
34   
35   bool isMore() const { return RI != E; }
36   
37   Record *next() { return isMore() ? *RI++ : NULL; }
38 };
39
40 struct DefListIter {
41   ListInit *List;
42   unsigned N;
43   unsigned i;
44
45   DefListIter(Record *R, const std::string &Name)
46       : List(R->getValueAsListInit(Name)), N(List->getSize()), i(0)
47   {}
48   
49   bool isMore() const { return i < N; }
50   
51   Record *next() {
52     if (isMore()) {
53       if (DefInit *DI = dynamic_cast<DefInit*>(List->getElement(i++))) {
54         return DI->getDef();
55       }
56     }
57     return NULL;
58   }
59 };
60
61 //
62 // Record sort by name function.
63 //
64 struct LessRecord {
65   bool operator()(const Record *Rec1, const Record *Rec2) const {
66     return Rec1->getName() < Rec2->getName();
67   }
68 };
69
70 //
71 // Record sort by field "Name" function.
72 //
73 struct LessRecordFieldName {
74   bool operator()(const Record *Rec1, const Record *Rec2) const {
75     return Rec1->getValueAsString("Name") < Rec2->getValueAsString("Name");
76   }
77 };
78
79 //
80 // Enumeration - Emit the specified class as an enumeration.
81 //
82 void SubtargetEmitter::Enumeration(std::ostream &OS,
83                                    const char *ClassName,
84                                    bool isBits) {
85   RecordList Defs = Records.getAllDerivedDefinitions(ClassName);
86   sort(Defs.begin(), Defs.end(), LessRecord());
87
88   int i = 0;
89   
90   OS << "enum {\n";
91   
92   RecordListIter DI(Defs);
93   while (Record *R = DI.next()) {
94     std::string Instance = R->getName();
95     OS << "  "
96        << Instance;
97     if (isBits) {
98       OS << " = "
99          << " 1 << " << i++;
100     }
101     OS << (DI.isMore() ? ",\n" : "\n");
102   }
103   
104   OS << "};\n";
105 }
106
107 //
108 // FeatureKeyValues - Emit data of all the subtarget features.  Used by command
109 // line.
110 //
111 void SubtargetEmitter::FeatureKeyValues(std::ostream &OS) {
112   RecordList Features = Records.getAllDerivedDefinitions("SubtargetFeature");
113   sort(Features.begin(), Features.end(), LessRecord());
114
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");
122     OS << "  { "
123        << "\"" << Name << "\", "
124        << "\"" << Desc << "\", "
125        << Instance
126        << (FI.isMore() ? " },\n" : " }\n");
127   }
128   OS << "};\n";
129
130   OS<<"\nenum {\n";
131   OS<<"  FeatureKVSize = sizeof(FeatureKV)/sizeof(llvm::SubtargetFeatureKV)\n";
132   OS<<"};\n";
133 }
134
135 //
136 // CPUKeyValues - Emit data of all the subtarget processors.  Used by command
137 // line.
138 //
139 void SubtargetEmitter::CPUKeyValues(std::ostream &OS) {
140   RecordList Processors = Records.getAllDerivedDefinitions("Processor");
141   sort(Processors.begin(), Processors.end(), LessRecordFieldName());
142
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");
149     
150     OS << "  { "
151        << "\"" << Name << "\", "
152        << "\"Select the " << Name << " processor\", ";
153     
154     if (!FI.isMore()) {
155       OS << "0";
156     } else {
157       while (Record *Feature = FI.next()) {
158         std::string Name = Feature->getName();
159         OS << Name;
160         if (FI.isMore()) OS << " | ";
161       }
162     }
163     
164     OS << (PI.isMore() ? " },\n" : " }\n");
165   }
166   OS << "};\n";
167
168   OS<<"\nenum {\n";
169   OS<<"  SubTypeKVSize = sizeof(SubTypeKV)/sizeof(llvm::SubtargetFeatureKV)\n";
170   OS<<"};\n";
171 }
172
173 //
174 // CollectAllItinClasses - Gathers and enumerates all the itinerary classes.
175 //
176 unsigned SubtargetEmitter::CollectAllItinClasses(IntMap &ItinClassesMap) {
177   RecordList ICL = Records.getAllDerivedDefinitions("InstrItinClass");
178   sort(ICL.begin(), ICL.end(), LessRecord());
179   
180   RecordListIter ICI(ICL);
181   unsigned Index = 0;
182   while (Record *ItinClass = ICI.next()) {
183     std::string Name = ItinClass->getName();
184     ItinClassesMap[Name] = Index++;
185   }
186   
187   return Index;
188 }
189
190 //
191 // FormItineraryString - Compose a string containing the data initialization
192 // for the specified itinerary.  N is the number of stages.
193 //
194 void SubtargetEmitter::FormItineraryString(Record *ItinData,
195                                            std::string &ItinString,
196                                            unsigned &N) {
197   DefListIter SLI(ItinData, "Stages");
198   N = SLI.N;
199   while (Record *Stage = SLI.next()) {
200     int Cycles = Stage->getValueAsInt("Cycles");
201     ItinString += "  ,{ " + itostr(Cycles) + ", ";
202     
203     DefListIter ULI(Stage, "Units");
204     while (Record *Unit = ULI.next()) {
205       std::string Name = Unit->getName();
206       ItinString += Name;
207       if (ULI.isMore())ItinString += " | ";
208     }
209   }
210   
211   ItinString += " }";
212 }
213
214 //
215 // EmitStageData - Generate unique itinerary stages.  Record itineraries for 
216 // processors.
217 //
218 void SubtargetEmitter::EmitStageData(std::ostream &OS,
219                                      unsigned N,
220                                      IntMap &ItinClassesMap, 
221                                      ProcessorList &ProcList) {
222   OS << "static llvm::InstrStage Stages[] = {\n"
223         "  { 0, 0 } // No itinerary\n";
224         
225   IntMap ItinMap;
226   unsigned Index  = 1;
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;
232     
233     IntineraryList IL;
234     IL.resize(N);
235     
236     DefListIter IDLI(Itin, "IID");
237     while (Record *ItinData = IDLI.next()) {
238       std::string ItinString;
239       unsigned M;
240       FormItineraryString(ItinData, ItinString, M);
241
242       unsigned Find = ItinMap[ItinString];
243       
244       if (Find == 0) {
245         OS << ItinString << " // " << Index << "\n";
246         ItinMap[ItinString] = Find = Index++;
247       }
248       
249       InstrItinerary Intinerary = { Find, Find + M };
250
251       std::string Name = ItinData->getValueAsDef("TheClass")->getName();
252       Find = ItinClassesMap[Name];
253       IL[Find] = Intinerary;
254     }
255     
256     ProcList.push_back(IL);
257   }
258   
259   OS << "};\n";
260 }
261
262 //
263 // EmitProcessData - Generate data for processor itineraries.
264 //
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;
273
274     OS << "\n";
275     OS << "static llvm::InstrItinerary " << Name << "[] = {\n";
276     
277     IntineraryList &IL = *PLI++;
278     unsigned Index = 0;
279     for (IntineraryList::iterator ILI = IL.begin(), E = IL.end(); ILI != E;) {
280       InstrItinerary &Intinerary = *ILI++;
281       
282       if (Intinerary.First == 0) {
283         OS << "  { 0, 0 }";
284       } else {
285         OS << "  { " << Intinerary.First << ", " << Intinerary.Last << " }";
286       }
287       
288       if (ILI != E) OS << ",";
289       OS << " // " << Index++ << "\n";
290     }
291     OS << "};\n";
292   }
293 }
294
295 //
296 // EmitData - Emits all stages and itineries, folding common patterns.
297 //
298 void SubtargetEmitter::EmitData(std::ostream &OS) {
299   IntMap ItinClassesMap;
300   ProcessorList ProcList;
301   
302   unsigned N = CollectAllItinClasses(ItinClassesMap);
303   EmitStageData(OS, N, ItinClassesMap, ProcList);
304   EmitProcessData(OS, ProcList);
305 }
306
307 //
308 // ParseFeaturesFunction - Produces a subtarget specific function for parsing
309 // the subtarget features string.
310 //
311 void SubtargetEmitter::ParseFeaturesFunction(std::ostream &OS) {
312   RecordList Features = Records.getAllDerivedDefinitions("SubtargetFeature");
313   sort(Features.begin(), Features.end(), LessRecord());
314
315   OS << "// ParseSubtargetFeatures - Parses features string setting specified\n" 
316         "// subtarget options.\n" 
317         "void llvm::";
318   OS << Target;
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";
325         
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");
332     
333     OS << "  " << Attribute << " = (Bits & " << Instance << ") != 0;\n";
334   }
335   OS << "}\n";
336 }
337
338 // 
339 // SubtargetEmitter::run - Main subtarget enumeration emitter.
340 //
341 void SubtargetEmitter::run(std::ostream &OS) {
342   Target = CodeGenTarget().getName();
343
344   EmitSourceFileHeader("Subtarget Enumeration Source Fragment", OS);
345
346   OS << "#include \"llvm/Target/SubtargetFeature.h\"\n";
347   OS << "#include \"llvm/Target/TargetInstrItineraries.h\"\n\n";
348   
349   Enumeration(OS, "FuncUnit", true);
350   OS<<"\n";
351   Enumeration(OS, "InstrItinClass", false);
352   OS<<"\n";
353   Enumeration(OS, "SubtargetFeature", true);
354   OS<<"\n";
355   FeatureKeyValues(OS);
356   OS<<"\n";
357   CPUKeyValues(OS);
358   OS<<"\n";
359   EmitData(OS);
360   OS<<"\n";
361   ParseFeaturesFunction(OS);
362 }