Give full control of subtarget features over to table generated code.
[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 #include <set>
21 using namespace llvm;
22
23 //
24 // Convenience types.
25 //
26 typedef std::vector<Record*> RecordList;
27 typedef std::vector<Record*>::iterator RecordListIter;
28
29 //
30 // Record sort by name function.
31 //
32 struct LessRecord {
33   bool operator()(const Record *Rec1, const Record *Rec2) const {
34     return Rec1->getName() < Rec2->getName();
35   }
36 };
37
38 //
39 // Record sort by field "Name" function.
40 //
41 struct LessRecordFieldName {
42   bool operator()(const Record *Rec1, const Record *Rec2) const {
43     return Rec1->getValueAsString("Name") < Rec2->getValueAsString("Name");
44   }
45 };
46
47 //
48 // Enumeration - Emit the specified class as an enumeration.
49 //
50 void SubtargetEmitter::Enumeration(std::ostream &OS,
51                                    const char *ClassName,
52                                    bool isBits) {
53   RecordList Defs = Records.getAllDerivedDefinitions(ClassName);
54   sort(Defs.begin(), Defs.end(), LessRecord());
55
56   int i = 0;
57   
58   OS << "enum {\n";
59   
60   for (RecordListIter RI = Defs.begin(), E = Defs.end(); RI != E;) {
61     Record *R = *RI++;
62     std::string Instance = R->getName();
63     OS << "  "
64        << Instance;
65     if (isBits) {
66       OS << " = "
67          << " 1 << " << i++;
68     }
69     OS << ((RI != E) ? ",\n" : "\n");
70   }
71   
72   OS << "};\n";
73 }
74
75 //
76 // FeatureKeyValues - Emit data of all the subtarget features.  Used by command
77 // line.
78 //
79 void SubtargetEmitter::FeatureKeyValues(std::ostream &OS) {
80   RecordList Features = Records.getAllDerivedDefinitions("SubtargetFeature");
81   sort(Features.begin(), Features.end(), LessRecord());
82
83   OS << "// Sorted (by key) array of values for CPU features.\n"
84      << "static llvm::SubtargetFeatureKV FeatureKV[] = {\n";
85   for (RecordListIter RI = Features.begin(), E = Features.end(); RI != E;) {
86     Record *R = *RI++;
87     std::string Instance = R->getName();
88     std::string Name = R->getValueAsString("Name");
89     std::string Desc = R->getValueAsString("Desc");
90     OS << "  { "
91        << "\"" << Name << "\", "
92        << "\"" << Desc << "\", "
93        << Instance
94        << ((RI != E) ? " },\n" : " }\n");
95   }
96   OS << "};\n";
97
98   OS<<"\nenum {\n";
99   OS<<"  FeatureKVSize = sizeof(FeatureKV)/sizeof(llvm::SubtargetFeatureKV)\n";
100   OS<<"};\n";
101 }
102
103 //
104 // CPUKeyValues - Emit data of all the subtarget processors.  Used by command
105 // line.
106 //
107 void SubtargetEmitter::CPUKeyValues(std::ostream &OS) {
108   RecordList Processors = Records.getAllDerivedDefinitions("Processor");
109   sort(Processors.begin(), Processors.end(), LessRecordFieldName());
110
111   OS << "// Sorted (by key) array of values for CPU subtype.\n"
112      << "static const llvm::SubtargetFeatureKV SubTypeKV[] = {\n";
113   for (RecordListIter RI = Processors.begin(), E = Processors.end();
114        RI != E;) {
115     Record *R = *RI++;
116     std::string Name = R->getValueAsString("Name");
117     Record *ProcItin = R->getValueAsDef("ProcItin");
118     ListInit *Features = R->getValueAsListInit("Features");
119     unsigned N = Features->getSize();
120     OS << "  { "
121        << "\"" << Name << "\", "
122        << "\"Select the " << Name << " processor\", ";
123        
124     
125     if (N == 0) {
126       OS << "0";
127     } else {
128       for (unsigned i = 0; i < N; ) {
129         if (DefInit *DI = dynamic_cast<DefInit*>(Features->getElement(i++))) {
130           Record *Feature = DI->getDef();
131           std::string Name = Feature->getName();
132           OS << Name;
133           if (i != N) OS << " | ";
134         } else {
135           throw "Feature: " + Name +
136                 " expected feature in processor feature list!";
137         }
138       }
139     }
140     
141     OS << ((RI != E) ? " },\n" : " }\n");
142   }
143   OS << "};\n";
144
145   OS<<"\nenum {\n";
146   OS<<"  SubTypeKVSize = sizeof(SubTypeKV)/sizeof(llvm::SubtargetFeatureKV)\n";
147   OS<<"};\n";
148 }
149
150 //
151 // ParseFeaturesFunction - Produces a subtarget specific function for parsing
152 // the subtarget features string.
153 //
154 void SubtargetEmitter::ParseFeaturesFunction(std::ostream &OS) {
155   RecordList Features = Records.getAllDerivedDefinitions("SubtargetFeature");
156   sort(Features.begin(), Features.end(), LessRecord());
157
158   OS << "// ParseSubtargetFeatures - Parses features string setting specified\n" 
159         "// subtarget options.\n" 
160         "void llvm::";
161   OS << Target;
162   OS << "Subtarget::ParseSubtargetFeatures(const std::string &FS,\n"
163         "                                  const std::string &CPU) {\n"
164         "  SubtargetFeatures Features(FS);\n"
165         "  Features.setCPUIfNone(CPU);\n"
166         "  uint32_t Bits =  Features.getBits(SubTypeKV, SubTypeKVSize,\n"
167         "                                    FeatureKV, FeatureKVSize);\n";
168         
169   for (RecordListIter RI = Features.begin(), E = Features.end(); RI != E;) {
170     Record *R = *RI++;
171     std::string Instance = R->getName();
172     std::string Name = R->getValueAsString("Name");
173     std::string Type = R->getValueAsString("Type");
174     std::string Attribute = R->getValueAsString("Attribute");
175     
176     OS << "  " << Attribute << " = (Bits & " << Instance << ") != 0;\n";
177   }
178   OS << "}\n";
179 }
180
181 // 
182 // SubtargetEmitter::run - Main subtarget enumeration emitter.
183 //
184 void SubtargetEmitter::run(std::ostream &OS) {
185   std::vector<Record*> Targets = Records.getAllDerivedDefinitions("Target");
186   if (Targets.size() == 0)
187     throw std::string("ERROR: No 'Target' subclasses defined!");
188   if (Targets.size() != 1)
189     throw std::string("ERROR: Multiple subclasses of Target defined!");
190   Target = Targets[0]->getName();
191
192   EmitSourceFileHeader("Subtarget Enumeration Source Fragment", OS);
193
194   OS << "#include \"llvm/Target/SubtargetFeature.h\"\n\n";
195   
196   Enumeration(OS, "FuncUnit", true);
197   OS<<"\n";
198   Enumeration(OS, "InstrItinClass", false);
199   OS<<"\n";
200   Enumeration(OS, "SubtargetFeature", true);
201   OS<<"\n";
202   FeatureKeyValues(OS);
203   OS<<"\n";
204   CPUKeyValues(OS);
205   OS<<"\n";
206   ParseFeaturesFunction(OS);
207 }