blob: 10ae4ea77d03cee47b213a2a094367392ac057a9 [file] [log] [blame]
Jim Laskey4bb9cbb2005-10-21 19:00:04 +00001//===- 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"
Jeff Cohen9489c042005-10-28 01:43:09 +000019#include <algorithm>
Jim Laskey4bb9cbb2005-10-21 19:00:04 +000020using namespace llvm;
21
Jim Laskey7dc02042005-10-22 07:59:56 +000022//
23// Convenience types.
24//
Jim Laskey4bb9cbb2005-10-21 19:00:04 +000025typedef std::vector<Record*> RecordList;
Jim Laskey0d841e02005-10-27 19:47:21 +000026
27struct 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
40struct 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};
Jim Laskey4bb9cbb2005-10-21 19:00:04 +000060
Jim Laskey7dc02042005-10-22 07:59:56 +000061//
62// Record sort by name function.
63//
64struct LessRecord {
65 bool operator()(const Record *Rec1, const Record *Rec2) const {
66 return Rec1->getName() < Rec2->getName();
67 }
68};
Jim Laskey4bb9cbb2005-10-21 19:00:04 +000069
Jim Laskey7dc02042005-10-22 07:59:56 +000070//
71// Record sort by field "Name" function.
72//
73struct LessRecordFieldName {
74 bool operator()(const Record *Rec1, const Record *Rec2) const {
75 return Rec1->getValueAsString("Name") < Rec2->getValueAsString("Name");
76 }
77};
78
Jim Laskeyb3b1d5f2005-10-25 15:16:36 +000079//
Jim Laskey581a8f72005-10-26 17:30:34 +000080// Enumeration - Emit the specified class as an enumeration.
Jim Laskeyb3b1d5f2005-10-25 15:16:36 +000081//
Jim Laskey581a8f72005-10-26 17:30:34 +000082void 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());
Jim Laskeyb3b1d5f2005-10-25 15:16:36 +000087
88 int i = 0;
89
90 OS << "enum {\n";
91
Jim Laskey0d841e02005-10-27 19:47:21 +000092 RecordListIter DI(Defs);
93 while (Record *R = DI.next()) {
Jim Laskeyb3b1d5f2005-10-25 15:16:36 +000094 std::string Instance = R->getName();
95 OS << " "
Jim Laskey581a8f72005-10-26 17:30:34 +000096 << Instance;
97 if (isBits) {
98 OS << " = "
99 << " 1 << " << i++;
100 }
Jim Laskey0d841e02005-10-27 19:47:21 +0000101 OS << (DI.isMore() ? ",\n" : "\n");
Jim Laskeyb3b1d5f2005-10-25 15:16:36 +0000102 }
103
104 OS << "};\n";
105}
106
107//
108// FeatureKeyValues - Emit data of all the subtarget features. Used by command
109// line.
110//
111void SubtargetEmitter::FeatureKeyValues(std::ostream &OS) {
112 RecordList Features = Records.getAllDerivedDefinitions("SubtargetFeature");
113 sort(Features.begin(), Features.end(), LessRecord());
114
Jim Laskey581a8f72005-10-26 17:30:34 +0000115 OS << "// Sorted (by key) array of values for CPU features.\n"
Jim Laskeyb3b1d5f2005-10-25 15:16:36 +0000116 << "static llvm::SubtargetFeatureKV FeatureKV[] = {\n";
Jim Laskey0d841e02005-10-27 19:47:21 +0000117 RecordListIter FI(Features);
118 while (Record *R = FI.next()) {
Jim Laskeyb3b1d5f2005-10-25 15:16:36 +0000119 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
Jim Laskey0d841e02005-10-27 19:47:21 +0000126 << (FI.isMore() ? " },\n" : " }\n");
Jim Laskeyb3b1d5f2005-10-25 15:16:36 +0000127 }
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//
139void SubtargetEmitter::CPUKeyValues(std::ostream &OS) {
140 RecordList Processors = Records.getAllDerivedDefinitions("Processor");
141 sort(Processors.begin(), Processors.end(), LessRecordFieldName());
142
Jim Laskey581a8f72005-10-26 17:30:34 +0000143 OS << "// Sorted (by key) array of values for CPU subtype.\n"
Jim Laskeyb3b1d5f2005-10-25 15:16:36 +0000144 << "static const llvm::SubtargetFeatureKV SubTypeKV[] = {\n";
Jim Laskey0d841e02005-10-27 19:47:21 +0000145 RecordListIter PI(Processors);
146 while (Record *R = PI.next()) {
Jim Laskeyb3b1d5f2005-10-25 15:16:36 +0000147 std::string Name = R->getValueAsString("Name");
Jim Laskey0d841e02005-10-27 19:47:21 +0000148 DefListIter FI(R, "Features");
149
Jim Laskeyb3b1d5f2005-10-25 15:16:36 +0000150 OS << " { "
151 << "\"" << Name << "\", "
152 << "\"Select the " << Name << " processor\", ";
Jim Laskeyb3b1d5f2005-10-25 15:16:36 +0000153
Jim Laskey0d841e02005-10-27 19:47:21 +0000154 if (!FI.isMore()) {
Jim Laskeyb3b1d5f2005-10-25 15:16:36 +0000155 OS << "0";
156 } else {
Jim Laskey0d841e02005-10-27 19:47:21 +0000157 while (Record *Feature = FI.next()) {
158 std::string Name = Feature->getName();
159 OS << Name;
160 if (FI.isMore()) OS << " | ";
Jim Laskeyb3b1d5f2005-10-25 15:16:36 +0000161 }
162 }
163
Jim Laskey0d841e02005-10-27 19:47:21 +0000164 OS << (PI.isMore() ? " },\n" : " }\n");
Jim Laskeyb3b1d5f2005-10-25 15:16:36 +0000165 }
166 OS << "};\n";
167
168 OS<<"\nenum {\n";
169 OS<<" SubTypeKVSize = sizeof(SubTypeKV)/sizeof(llvm::SubtargetFeatureKV)\n";
170 OS<<"};\n";
171}
Jim Laskey7dc02042005-10-22 07:59:56 +0000172
Jim Laskey581a8f72005-10-26 17:30:34 +0000173//
Jim Laskey0d841e02005-10-27 19:47:21 +0000174// CollectAllItinClasses - Gathers and enumerates all the itinerary classes.
175//
176unsigned 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//
194void 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//
218void 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//
265void 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//
298void 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//
Jim Laskey581a8f72005-10-26 17:30:34 +0000308// ParseFeaturesFunction - Produces a subtarget specific function for parsing
309// the subtarget features string.
310//
311void 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
Jim Laskey0d841e02005-10-27 19:47:21 +0000326 RecordListIter FI(Features);
327 while (Record *R = FI.next()) {
Jim Laskey581a8f72005-10-26 17:30:34 +0000328 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
Jim Laskey7dc02042005-10-22 07:59:56 +0000338//
Jim Laskey4bb9cbb2005-10-21 19:00:04 +0000339// SubtargetEmitter::run - Main subtarget enumeration emitter.
340//
341void SubtargetEmitter::run(std::ostream &OS) {
Jim Laskey6c302fc2005-10-26 17:49:21 +0000342 Target = CodeGenTarget().getName();
Jim Laskey581a8f72005-10-26 17:30:34 +0000343
Jim Laskey4bb9cbb2005-10-21 19:00:04 +0000344 EmitSourceFileHeader("Subtarget Enumeration Source Fragment", OS);
Jim Laskey4bb9cbb2005-10-21 19:00:04 +0000345
Jim Laskey0d841e02005-10-27 19:47:21 +0000346 OS << "#include \"llvm/Target/SubtargetFeature.h\"\n";
347 OS << "#include \"llvm/Target/TargetInstrItineraries.h\"\n\n";
Jim Laskey4bb9cbb2005-10-21 19:00:04 +0000348
Jim Laskey581a8f72005-10-26 17:30:34 +0000349 Enumeration(OS, "FuncUnit", true);
350 OS<<"\n";
351 Enumeration(OS, "InstrItinClass", false);
352 OS<<"\n";
353 Enumeration(OS, "SubtargetFeature", true);
354 OS<<"\n";
Jim Laskeyb3b1d5f2005-10-25 15:16:36 +0000355 FeatureKeyValues(OS);
Jim Laskey581a8f72005-10-26 17:30:34 +0000356 OS<<"\n";
Jim Laskeyb3b1d5f2005-10-25 15:16:36 +0000357 CPUKeyValues(OS);
Jim Laskey581a8f72005-10-26 17:30:34 +0000358 OS<<"\n";
Jim Laskey0d841e02005-10-27 19:47:21 +0000359 EmitData(OS);
360 OS<<"\n";
Jim Laskey581a8f72005-10-26 17:30:34 +0000361 ParseFeaturesFunction(OS);
Jim Laskey4bb9cbb2005-10-21 19:00:04 +0000362}