blob: 7c06cf5148b14f893c58ec14d886e59240289d33 [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"
Jim Laskey4bb9cbb2005-10-21 19:00:04 +000019using namespace llvm;
20
Jim Laskey7dc02042005-10-22 07:59:56 +000021//
22// Convenience types.
23//
Jim Laskey4bb9cbb2005-10-21 19:00:04 +000024typedef std::vector<Record*> RecordList;
Jim Laskey0d841e02005-10-27 19:47:21 +000025
26struct RecordListIter {
27 std::vector<Record*>::iterator RI;
28 std::vector<Record*>::iterator E;
29
30 RecordListIter(RecordList &RL)
31 : RI(RL.begin()), E(RL.end())
32 {}
33
34 bool isMore() const { return RI != E; }
35
36 Record *next() { return isMore() ? *RI++ : NULL; }
37};
38
39struct DefListIter {
40 ListInit *List;
41 unsigned N;
42 unsigned i;
43
44 DefListIter(Record *R, const std::string &Name)
45 : List(R->getValueAsListInit(Name)), N(List->getSize()), i(0)
46 {}
47
48 bool isMore() const { return i < N; }
49
50 Record *next() {
51 if (isMore()) {
52 if (DefInit *DI = dynamic_cast<DefInit*>(List->getElement(i++))) {
53 return DI->getDef();
54 }
55 }
56 return NULL;
57 }
58};
Jim Laskey4bb9cbb2005-10-21 19:00:04 +000059
Jim Laskey7dc02042005-10-22 07:59:56 +000060//
61// Record sort by name function.
62//
63struct LessRecord {
64 bool operator()(const Record *Rec1, const Record *Rec2) const {
65 return Rec1->getName() < Rec2->getName();
66 }
67};
Jim Laskey4bb9cbb2005-10-21 19:00:04 +000068
Jim Laskey7dc02042005-10-22 07:59:56 +000069//
70// Record sort by field "Name" function.
71//
72struct LessRecordFieldName {
73 bool operator()(const Record *Rec1, const Record *Rec2) const {
74 return Rec1->getValueAsString("Name") < Rec2->getValueAsString("Name");
75 }
76};
77
Jim Laskeyb3b1d5f2005-10-25 15:16:36 +000078//
Jim Laskey581a8f72005-10-26 17:30:34 +000079// Enumeration - Emit the specified class as an enumeration.
Jim Laskeyb3b1d5f2005-10-25 15:16:36 +000080//
Jim Laskey581a8f72005-10-26 17:30:34 +000081void SubtargetEmitter::Enumeration(std::ostream &OS,
82 const char *ClassName,
83 bool isBits) {
84 RecordList Defs = Records.getAllDerivedDefinitions(ClassName);
85 sort(Defs.begin(), Defs.end(), LessRecord());
Jim Laskeyb3b1d5f2005-10-25 15:16:36 +000086
87 int i = 0;
88
89 OS << "enum {\n";
90
Jim Laskey0d841e02005-10-27 19:47:21 +000091 RecordListIter DI(Defs);
92 while (Record *R = DI.next()) {
Jim Laskeyb3b1d5f2005-10-25 15:16:36 +000093 std::string Instance = R->getName();
94 OS << " "
Jim Laskey581a8f72005-10-26 17:30:34 +000095 << Instance;
96 if (isBits) {
97 OS << " = "
98 << " 1 << " << i++;
99 }
Jim Laskey0d841e02005-10-27 19:47:21 +0000100 OS << (DI.isMore() ? ",\n" : "\n");
Jim Laskeyb3b1d5f2005-10-25 15:16:36 +0000101 }
102
103 OS << "};\n";
104}
105
106//
107// FeatureKeyValues - Emit data of all the subtarget features. Used by command
108// line.
109//
110void SubtargetEmitter::FeatureKeyValues(std::ostream &OS) {
111 RecordList Features = Records.getAllDerivedDefinitions("SubtargetFeature");
112 sort(Features.begin(), Features.end(), LessRecord());
113
Jim Laskey581a8f72005-10-26 17:30:34 +0000114 OS << "// Sorted (by key) array of values for CPU features.\n"
Jim Laskeyb3b1d5f2005-10-25 15:16:36 +0000115 << "static llvm::SubtargetFeatureKV FeatureKV[] = {\n";
Jim Laskey0d841e02005-10-27 19:47:21 +0000116 RecordListIter FI(Features);
117 while (Record *R = FI.next()) {
Jim Laskeyb3b1d5f2005-10-25 15:16:36 +0000118 std::string Instance = R->getName();
119 std::string Name = R->getValueAsString("Name");
120 std::string Desc = R->getValueAsString("Desc");
121 OS << " { "
122 << "\"" << Name << "\", "
123 << "\"" << Desc << "\", "
124 << Instance
Jim Laskey0d841e02005-10-27 19:47:21 +0000125 << (FI.isMore() ? " },\n" : " }\n");
Jim Laskeyb3b1d5f2005-10-25 15:16:36 +0000126 }
127 OS << "};\n";
128
129 OS<<"\nenum {\n";
130 OS<<" FeatureKVSize = sizeof(FeatureKV)/sizeof(llvm::SubtargetFeatureKV)\n";
131 OS<<"};\n";
132}
133
134//
135// CPUKeyValues - Emit data of all the subtarget processors. Used by command
136// line.
137//
138void SubtargetEmitter::CPUKeyValues(std::ostream &OS) {
139 RecordList Processors = Records.getAllDerivedDefinitions("Processor");
140 sort(Processors.begin(), Processors.end(), LessRecordFieldName());
141
Jim Laskey581a8f72005-10-26 17:30:34 +0000142 OS << "// Sorted (by key) array of values for CPU subtype.\n"
Jim Laskeyb3b1d5f2005-10-25 15:16:36 +0000143 << "static const llvm::SubtargetFeatureKV SubTypeKV[] = {\n";
Jim Laskey0d841e02005-10-27 19:47:21 +0000144 RecordListIter PI(Processors);
145 while (Record *R = PI.next()) {
Jim Laskeyb3b1d5f2005-10-25 15:16:36 +0000146 std::string Name = R->getValueAsString("Name");
Jim Laskey0d841e02005-10-27 19:47:21 +0000147 DefListIter FI(R, "Features");
148
Jim Laskeyb3b1d5f2005-10-25 15:16:36 +0000149 OS << " { "
150 << "\"" << Name << "\", "
151 << "\"Select the " << Name << " processor\", ";
Jim Laskeyb3b1d5f2005-10-25 15:16:36 +0000152
Jim Laskey0d841e02005-10-27 19:47:21 +0000153 if (!FI.isMore()) {
Jim Laskeyb3b1d5f2005-10-25 15:16:36 +0000154 OS << "0";
155 } else {
Jim Laskey0d841e02005-10-27 19:47:21 +0000156 while (Record *Feature = FI.next()) {
157 std::string Name = Feature->getName();
158 OS << Name;
159 if (FI.isMore()) OS << " | ";
Jim Laskeyb3b1d5f2005-10-25 15:16:36 +0000160 }
161 }
162
Jim Laskey0d841e02005-10-27 19:47:21 +0000163 OS << (PI.isMore() ? " },\n" : " }\n");
Jim Laskeyb3b1d5f2005-10-25 15:16:36 +0000164 }
165 OS << "};\n";
166
167 OS<<"\nenum {\n";
168 OS<<" SubTypeKVSize = sizeof(SubTypeKV)/sizeof(llvm::SubtargetFeatureKV)\n";
169 OS<<"};\n";
170}
Jim Laskey7dc02042005-10-22 07:59:56 +0000171
Jim Laskey581a8f72005-10-26 17:30:34 +0000172//
Jim Laskey0d841e02005-10-27 19:47:21 +0000173// CollectAllItinClasses - Gathers and enumerates all the itinerary classes.
174//
175unsigned SubtargetEmitter::CollectAllItinClasses(IntMap &ItinClassesMap) {
176 RecordList ICL = Records.getAllDerivedDefinitions("InstrItinClass");
177 sort(ICL.begin(), ICL.end(), LessRecord());
178
179 RecordListIter ICI(ICL);
180 unsigned Index = 0;
181 while (Record *ItinClass = ICI.next()) {
182 std::string Name = ItinClass->getName();
183 ItinClassesMap[Name] = Index++;
184 }
185
186 return Index;
187}
188
189//
190// FormItineraryString - Compose a string containing the data initialization
191// for the specified itinerary. N is the number of stages.
192//
193void SubtargetEmitter::FormItineraryString(Record *ItinData,
194 std::string &ItinString,
195 unsigned &N) {
196 DefListIter SLI(ItinData, "Stages");
197 N = SLI.N;
198 while (Record *Stage = SLI.next()) {
199 int Cycles = Stage->getValueAsInt("Cycles");
200 ItinString += " ,{ " + itostr(Cycles) + ", ";
201
202 DefListIter ULI(Stage, "Units");
203 while (Record *Unit = ULI.next()) {
204 std::string Name = Unit->getName();
205 ItinString += Name;
206 if (ULI.isMore())ItinString += " | ";
207 }
208 }
209
210 ItinString += " }";
211}
212
213//
214// EmitStageData - Generate unique itinerary stages. Record itineraries for
215// processors.
216//
217void SubtargetEmitter::EmitStageData(std::ostream &OS,
218 unsigned N,
219 IntMap &ItinClassesMap,
220 ProcessorList &ProcList) {
221 OS << "static llvm::InstrStage Stages[] = {\n"
222 " { 0, 0 } // No itinerary\n";
223
224 IntMap ItinMap;
225 unsigned Index = 1;
226 RecordList Itins = Records.getAllDerivedDefinitions("ProcessorItineraries");
227 RecordListIter II(Itins);
228 while (Record *Itin = II.next()) {
229 std::string Name = Itin->getName();
230 if (Name == "NoItineraries") continue;
231
232 IntineraryList IL;
233 IL.resize(N);
234
235 DefListIter IDLI(Itin, "IID");
236 while (Record *ItinData = IDLI.next()) {
237 std::string ItinString;
238 unsigned M;
239 FormItineraryString(ItinData, ItinString, M);
240
241 unsigned Find = ItinMap[ItinString];
242
243 if (Find == 0) {
244 OS << ItinString << " // " << Index << "\n";
245 ItinMap[ItinString] = Find = Index++;
246 }
247
248 InstrItinerary Intinerary = { Find, Find + M };
249
250 std::string Name = ItinData->getValueAsDef("TheClass")->getName();
251 Find = ItinClassesMap[Name];
252 IL[Find] = Intinerary;
253 }
254
255 ProcList.push_back(IL);
256 }
257
258 OS << "};\n";
259}
260
261//
262// EmitProcessData - Generate data for processor itineraries.
263//
264void SubtargetEmitter::EmitProcessData(std::ostream &OS,
265 ProcessorList &ProcList) {
266 ProcessorList::iterator PLI = ProcList.begin();
267 RecordList Itins = Records.getAllDerivedDefinitions("ProcessorItineraries");
268 RecordListIter II(Itins);
269 while (Record *Itin = II.next()) {
270 std::string Name = Itin->getName();
271 if (Name == "NoItineraries") continue;
272
273 OS << "\n";
274 OS << "static llvm::InstrItinerary " << Name << "[] = {\n";
275
276 IntineraryList &IL = *PLI++;
277 unsigned Index = 0;
278 for (IntineraryList::iterator ILI = IL.begin(), E = IL.end(); ILI != E;) {
279 InstrItinerary &Intinerary = *ILI++;
280
281 if (Intinerary.First == 0) {
282 OS << " { 0, 0 }";
283 } else {
284 OS << " { " << Intinerary.First << ", " << Intinerary.Last << " }";
285 }
286
287 if (ILI != E) OS << ",";
288 OS << " // " << Index++ << "\n";
289 }
290 OS << "};\n";
291 }
292}
293
294//
295// EmitData - Emits all stages and itineries, folding common patterns.
296//
297void SubtargetEmitter::EmitData(std::ostream &OS) {
298 IntMap ItinClassesMap;
299 ProcessorList ProcList;
300
301 unsigned N = CollectAllItinClasses(ItinClassesMap);
302 EmitStageData(OS, N, ItinClassesMap, ProcList);
303 EmitProcessData(OS, ProcList);
304}
305
306//
Jim Laskey581a8f72005-10-26 17:30:34 +0000307// ParseFeaturesFunction - Produces a subtarget specific function for parsing
308// the subtarget features string.
309//
310void SubtargetEmitter::ParseFeaturesFunction(std::ostream &OS) {
311 RecordList Features = Records.getAllDerivedDefinitions("SubtargetFeature");
312 sort(Features.begin(), Features.end(), LessRecord());
313
314 OS << "// ParseSubtargetFeatures - Parses features string setting specified\n"
315 "// subtarget options.\n"
316 "void llvm::";
317 OS << Target;
318 OS << "Subtarget::ParseSubtargetFeatures(const std::string &FS,\n"
319 " const std::string &CPU) {\n"
320 " SubtargetFeatures Features(FS);\n"
321 " Features.setCPUIfNone(CPU);\n"
322 " uint32_t Bits = Features.getBits(SubTypeKV, SubTypeKVSize,\n"
323 " FeatureKV, FeatureKVSize);\n";
324
Jim Laskey0d841e02005-10-27 19:47:21 +0000325 RecordListIter FI(Features);
326 while (Record *R = FI.next()) {
Jim Laskey581a8f72005-10-26 17:30:34 +0000327 std::string Instance = R->getName();
328 std::string Name = R->getValueAsString("Name");
329 std::string Type = R->getValueAsString("Type");
330 std::string Attribute = R->getValueAsString("Attribute");
331
332 OS << " " << Attribute << " = (Bits & " << Instance << ") != 0;\n";
333 }
334 OS << "}\n";
335}
336
Jim Laskey7dc02042005-10-22 07:59:56 +0000337//
Jim Laskey4bb9cbb2005-10-21 19:00:04 +0000338// SubtargetEmitter::run - Main subtarget enumeration emitter.
339//
340void SubtargetEmitter::run(std::ostream &OS) {
Jim Laskey6c302fc2005-10-26 17:49:21 +0000341 Target = CodeGenTarget().getName();
Jim Laskey581a8f72005-10-26 17:30:34 +0000342
Jim Laskey4bb9cbb2005-10-21 19:00:04 +0000343 EmitSourceFileHeader("Subtarget Enumeration Source Fragment", OS);
Jim Laskey4bb9cbb2005-10-21 19:00:04 +0000344
Jim Laskey0d841e02005-10-27 19:47:21 +0000345 OS << "#include \"llvm/Target/SubtargetFeature.h\"\n";
346 OS << "#include \"llvm/Target/TargetInstrItineraries.h\"\n\n";
Jim Laskey4bb9cbb2005-10-21 19:00:04 +0000347
Jim Laskey581a8f72005-10-26 17:30:34 +0000348 Enumeration(OS, "FuncUnit", true);
349 OS<<"\n";
350 Enumeration(OS, "InstrItinClass", false);
351 OS<<"\n";
352 Enumeration(OS, "SubtargetFeature", true);
353 OS<<"\n";
Jim Laskeyb3b1d5f2005-10-25 15:16:36 +0000354 FeatureKeyValues(OS);
Jim Laskey581a8f72005-10-26 17:30:34 +0000355 OS<<"\n";
Jim Laskeyb3b1d5f2005-10-25 15:16:36 +0000356 CPUKeyValues(OS);
Jim Laskey581a8f72005-10-26 17:30:34 +0000357 OS<<"\n";
Jim Laskey0d841e02005-10-27 19:47:21 +0000358 EmitData(OS);
359 OS<<"\n";
Jim Laskey581a8f72005-10-26 17:30:34 +0000360 ParseFeaturesFunction(OS);
Jim Laskey4bb9cbb2005-10-21 19:00:04 +0000361}