blob: e0885d1f9bcf9a320e99366c7605174690bedf3d [file] [log] [blame]
Chris Lattner1d1adea2003-08-01 04:39:05 +00001//===- TableGen.cpp - Top-Level TableGen implementation -------------------===//
John Criswell01d45822003-10-20 20:20:30 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file was developed by the LLVM research group and is distributed under
6// the University of Illinois Open Source License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
Chris Lattner1d1adea2003-08-01 04:39:05 +00009//
10// TableGen is a tool which can be used to build up a description of something,
11// then invoke one or more "tablegen backends" to emit information about the
12// description in some predefined format. In practice, this is used by the LLVM
13// code generators to automate generation of a code generator through a
14// high-level description of the target.
15//
16//===----------------------------------------------------------------------===//
17
Chris Lattnere62c1182002-12-02 01:23:04 +000018#include "Record.h"
19#include "Support/CommandLine.h"
Chris Lattnerbed85ff2004-05-27 05:41:36 +000020#include "llvm/System/Signals.h"
Chris Lattnere79c72d2003-08-01 20:35:01 +000021#include "Support/FileUtilities.h"
Misha Brukmanf00ce8b2003-05-24 00:17:12 +000022#include "CodeEmitterGen.h"
Chris Lattner1d1adea2003-08-01 04:39:05 +000023#include "RegisterInfoEmitter.h"
Chris Lattner169e66b2003-08-03 17:24:20 +000024#include "InstrInfoEmitter.h"
Chris Lattner3f781342003-08-06 04:47:56 +000025#include "InstrSelectorEmitter.h"
Jakub Staszak01b6a6f2004-04-06 19:30:56 +000026#include "SimpleInstrSelEmitter.h"
Chris Lattnere62c1182002-12-02 01:23:04 +000027#include <algorithm>
Misha Brukmanc3fe45b2003-08-14 16:05:35 +000028#include <cstdio>
Chris Lattner9a886382003-06-03 05:04:42 +000029#include <fstream>
Chris Lattnere62c1182002-12-02 01:23:04 +000030
Brian Gaeked0fde302003-11-11 22:41:34 +000031namespace llvm {
32
Chris Lattnerbc520132003-06-03 04:56:29 +000033enum ActionType {
34 PrintRecords,
35 GenEmitter,
Chris Lattner54d156d2003-08-01 05:59:20 +000036 GenRegisterEnums, GenRegister, GenRegisterHeader,
Chris Lattner3f781342003-08-06 04:47:56 +000037 GenInstrEnums, GenInstrs, GenInstrSelector,
Chris Lattnerbc520132003-06-03 04:56:29 +000038 PrintEnums,
Jakub Staszak01b6a6f2004-04-06 19:30:56 +000039 Parse, GenSimpInstrSel,
Chris Lattnerbc520132003-06-03 04:56:29 +000040};
41
42namespace {
43 cl::opt<ActionType>
44 Action(cl::desc("Action to perform:"),
45 cl::values(clEnumValN(PrintRecords, "print-records",
Chris Lattner85df2252003-06-03 05:07:28 +000046 "Print all records to stdout (default)"),
Chris Lattnerbc520132003-06-03 04:56:29 +000047 clEnumValN(GenEmitter, "gen-emitter",
48 "Generate machine code emitter"),
Chris Lattner54d156d2003-08-01 05:59:20 +000049 clEnumValN(GenRegisterEnums, "gen-register-enums",
50 "Generate enum values for registers"),
Chris Lattner1d1adea2003-08-01 04:39:05 +000051 clEnumValN(GenRegister, "gen-register-desc",
52 "Generate a register info description"),
53 clEnumValN(GenRegisterHeader, "gen-register-desc-header",
54 "Generate a register info description header"),
Chris Lattner169e66b2003-08-03 17:24:20 +000055 clEnumValN(GenInstrEnums, "gen-instr-enums",
56 "Generate enum values for instructions"),
Chris Lattner15de32d2003-08-03 21:58:28 +000057 clEnumValN(GenInstrs, "gen-instr-desc",
58 "Generate instruction descriptions"),
Chris Lattner3f781342003-08-06 04:47:56 +000059 clEnumValN(GenInstrSelector, "gen-instr-selector",
60 "Generate an instruction selector"),
Jakub Staszak01b6a6f2004-04-06 19:30:56 +000061 clEnumValN(GenSimpInstrSel, "gen-simp-instr-sel",
62 "Generate a simple instruction selector"),
Chris Lattnerbc520132003-06-03 04:56:29 +000063 clEnumValN(PrintEnums, "print-enums",
64 "Print enum values for a class"),
65 clEnumValN(Parse, "parse",
66 "Interpret machine code (testing only)"),
Chris Lattnerbd935332004-07-16 00:02:21 +000067 clEnumValEnd));
Chris Lattnerbc520132003-06-03 04:56:29 +000068
69 cl::opt<std::string>
Chris Lattner85df2252003-06-03 05:07:28 +000070 Class("class", cl::desc("Print Enum list for this class"),
71 cl::value_desc("class name"));
Chris Lattner9a886382003-06-03 05:04:42 +000072
Chris Lattner90523902003-07-30 19:48:02 +000073 cl::opt<std::string>
74 OutputFilename("o", cl::desc("Output filename"), cl::value_desc("filename"),
75 cl::init("-"));
76
77 cl::opt<std::string>
78 InputFilename(cl::Positional, cl::desc("<input file>"), cl::init("-"));
John Criswell96b4bed2003-08-27 13:41:57 +000079
80 cl::opt<std::string>
81 IncludeDir("I", cl::desc("Directory of include files"),
82 cl::value_desc("directory"), cl::init(""));
Chris Lattnerbc520132003-06-03 04:56:29 +000083}
84
Chris Lattnere62c1182002-12-02 01:23:04 +000085
John Criswell96b4bed2003-08-27 13:41:57 +000086void ParseFile(const std::string &Filename, const std::string & IncludeDir);
Chris Lattnere62c1182002-12-02 01:23:04 +000087
88RecordKeeper Records;
89
90static Init *getBit(Record *R, unsigned BitNo) {
91 const std::vector<RecordVal> &V = R->getValues();
92 for (unsigned i = 0, e = V.size(); i != e; ++i)
93 if (V[i].getPrefix()) {
94 assert(dynamic_cast<BitsInit*>(V[i].getValue()) &&
95 "Can only handle fields of bits<> type!");
96 BitsInit *I = (BitsInit*)V[i].getValue();
97 if (BitNo < I->getNumBits())
98 return I->getBit(BitNo);
99 BitNo -= I->getNumBits();
100 }
101
102 std::cerr << "Cannot find requested bit!\n";
Chris Lattnerf5761a52004-02-13 16:37:43 +0000103 exit(1);
Chris Lattnere62c1182002-12-02 01:23:04 +0000104 return 0;
105}
106
107static unsigned getNumBits(Record *R) {
108 const std::vector<RecordVal> &V = R->getValues();
109 unsigned Num = 0;
110 for (unsigned i = 0, e = V.size(); i != e; ++i)
111 if (V[i].getPrefix()) {
112 assert(dynamic_cast<BitsInit*>(V[i].getValue()) &&
113 "Can only handle fields of bits<> type!");
114 Num += ((BitsInit*)V[i].getValue())->getNumBits();
115 }
116 return Num;
117}
118
119static bool BitsAreFixed(Record *I1, Record *I2, unsigned BitNo) {
120 return dynamic_cast<BitInit*>(getBit(I1, BitNo)) &&
121 dynamic_cast<BitInit*>(getBit(I2, BitNo));
122}
123
124static bool BitsAreEqual(Record *I1, Record *I2, unsigned BitNo) {
125 BitInit *Bit1 = dynamic_cast<BitInit*>(getBit(I1, BitNo));
126 BitInit *Bit2 = dynamic_cast<BitInit*>(getBit(I2, BitNo));
127
128 return Bit1 && Bit2 && Bit1->getValue() == Bit2->getValue();
129}
130
131static bool BitRangesEqual(Record *I1, Record *I2,
132 unsigned Start, unsigned End) {
133 for (unsigned i = Start; i != End; ++i)
134 if (!BitsAreEqual(I1, I2, i))
135 return false;
136 return true;
137}
138
139static unsigned getFirstFixedBit(Record *R, unsigned FirstFixedBit) {
140 // Look for the first bit of the pair that are required to be 0 or 1.
141 while (!dynamic_cast<BitInit*>(getBit(R, FirstFixedBit)))
142 ++FirstFixedBit;
143 return FirstFixedBit;
144}
145
146static void FindInstDifferences(Record *I1, Record *I2,
147 unsigned FirstFixedBit, unsigned MaxBits,
148 unsigned &FirstVaryingBitOverall,
149 unsigned &LastFixedBitOverall) {
150 // Compare the first instruction to the rest of the instructions, looking for
151 // fields that differ.
152 //
153 unsigned FirstVaryingBit = FirstFixedBit;
154 while (FirstVaryingBit < MaxBits && BitsAreEqual(I1, I2, FirstVaryingBit))
155 ++FirstVaryingBit;
156
157 unsigned LastFixedBit = FirstVaryingBit;
158 while (LastFixedBit < MaxBits && BitsAreFixed(I1, I2, LastFixedBit))
159 ++LastFixedBit;
160
161 if (FirstVaryingBit < FirstVaryingBitOverall)
162 FirstVaryingBitOverall = FirstVaryingBit;
163 if (LastFixedBit < LastFixedBitOverall)
164 LastFixedBitOverall = LastFixedBit;
165}
166
167static bool getBitValue(Record *R, unsigned BitNo) {
168 Init *I = getBit(R, BitNo);
169 assert(dynamic_cast<BitInit*>(I) && "Bit should be fixed!");
170 return ((BitInit*)I)->getValue();
171}
172
173struct BitComparator {
174 unsigned BitBegin, BitEnd;
175 BitComparator(unsigned B, unsigned E) : BitBegin(B), BitEnd(E) {}
176
177 bool operator()(Record *R1, Record *R2) { // Return true if R1 is less than R2
178 for (unsigned i = BitBegin; i != BitEnd; ++i) {
179 bool V1 = getBitValue(R1, i), V2 = getBitValue(R2, i);
180 if (V1 < V2)
181 return true;
182 else if (V2 < V1)
183 return false;
184 }
185 return false;
186 }
187};
188
189static void PrintRange(std::vector<Record*>::iterator I,
190 std::vector<Record*>::iterator E) {
191 while (I != E) std::cerr << **I++;
192}
193
194static bool getMemoryBit(unsigned char *M, unsigned i) {
195 return (M[i/8] & (1 << (i&7))) != 0;
196}
197
198static unsigned getFirstFixedBitInSequence(std::vector<Record*>::iterator IB,
199 std::vector<Record*>::iterator IE,
200 unsigned StartBit) {
201 unsigned FirstFixedBit = 0;
202 for (std::vector<Record*>::iterator I = IB; I != IE; ++I)
203 FirstFixedBit = std::max(FirstFixedBit, getFirstFixedBit(*I, StartBit));
204 return FirstFixedBit;
205}
206
207// ParseMachineCode - Try to split the vector of instructions (which is
Misha Brukman737af822003-09-07 20:12:52 +0000208// intentionally taken by-copy) in half, narrowing down the possible
209// instructions that we may have found. Eventually, this list will get pared
210// down to zero or one instruction, in which case we have a match or failure.
Chris Lattnere62c1182002-12-02 01:23:04 +0000211//
212static Record *ParseMachineCode(std::vector<Record*>::iterator InstsB,
213 std::vector<Record*>::iterator InstsE,
214 unsigned char *M) {
215 assert(InstsB != InstsE && "Empty range?");
216 if (InstsB+1 == InstsE) {
217 // Only a single instruction, see if we match it...
218 Record *Inst = *InstsB;
219 for (unsigned i = 0, e = getNumBits(Inst); i != e; ++i)
220 if (BitInit *BI = dynamic_cast<BitInit*>(getBit(Inst, i)))
221 if (getMemoryBit(M, i) != BI->getValue())
Chris Lattner1d1adea2003-08-01 04:39:05 +0000222 throw std::string("Parse failed!\n");
Chris Lattnere62c1182002-12-02 01:23:04 +0000223 return Inst;
224 }
225
226 unsigned MaxBits = ~0;
227 for (std::vector<Record*>::iterator I = InstsB; I != InstsE; ++I)
228 MaxBits = std::min(MaxBits, getNumBits(*I));
229
230 unsigned FirstFixedBit = getFirstFixedBitInSequence(InstsB, InstsE, 0);
231 unsigned FirstVaryingBit, LastFixedBit;
232 do {
233 FirstVaryingBit = ~0;
234 LastFixedBit = ~0;
235 for (std::vector<Record*>::iterator I = InstsB+1; I != InstsE; ++I)
236 FindInstDifferences(*InstsB, *I, FirstFixedBit, MaxBits,
237 FirstVaryingBit, LastFixedBit);
238 if (FirstVaryingBit == MaxBits) {
239 std::cerr << "ERROR: Could not find bit to distinguish between "
240 << "the following entries!\n";
241 PrintRange(InstsB, InstsE);
242 }
243
244#if 0
245 std::cerr << "FVB: " << FirstVaryingBit << " - " << LastFixedBit
246 << ": " << InstsE-InstsB << "\n";
247#endif
248
249 FirstFixedBit = getFirstFixedBitInSequence(InstsB, InstsE, FirstVaryingBit);
250 } while (FirstVaryingBit != FirstFixedBit);
251
252 //std::cerr << "\n\nXXXXXXXXXXXXXXXXX\n\n";
253 //PrintRange(InstsB, InstsE);
254
255 // Sort the Insts list so that the entries have all of the bits in the range
256 // [FirstVaryingBit,LastFixedBit) sorted. These bits are all guaranteed to be
257 // set to either 0 or 1 (BitInit values), which simplifies things.
258 //
259 std::sort(InstsB, InstsE, BitComparator(FirstVaryingBit, LastFixedBit));
260
261 // Once the list is sorted by these bits, split the bit list into smaller
262 // lists, and recurse on each one.
263 //
264 std::vector<Record*>::iterator RangeBegin = InstsB;
265 Record *Match = 0;
266 while (RangeBegin != InstsE) {
267 std::vector<Record*>::iterator RangeEnd = RangeBegin+1;
268 while (RangeEnd != InstsE &&
269 BitRangesEqual(*RangeBegin, *RangeEnd, FirstVaryingBit, LastFixedBit))
270 ++RangeEnd;
271
272 // We just identified a range of equal instructions. If this range is the
273 // input range, we were not able to distinguish between the instructions in
274 // the set. Print an error and exit!
275 //
276 if (RangeBegin == InstsB && RangeEnd == InstsE) {
277 std::cerr << "Error: Could not distinguish among the following insts!:\n";
278 PrintRange(InstsB, InstsE);
Chris Lattnerf5761a52004-02-13 16:37:43 +0000279 exit(1);
Chris Lattnere62c1182002-12-02 01:23:04 +0000280 }
281
Chris Lattner7b1d49b2002-12-03 20:01:04 +0000282#if 0
283 std::cerr << "FVB: " << FirstVaryingBit << " - " << LastFixedBit
284 << ": [" << RangeEnd-RangeBegin << "] - ";
285 for (int i = LastFixedBit-1; i >= (int)FirstVaryingBit; --i)
286 std::cerr << (int)((BitInit*)getBit(*RangeBegin, i))->getValue() << " ";
287 std::cerr << "\n";
288#endif
289
Chris Lattnere62c1182002-12-02 01:23:04 +0000290 if (Record *R = ParseMachineCode(RangeBegin, RangeEnd, M)) {
291 if (Match) {
292 std::cerr << "Error: Multiple matches found:\n";
293 PrintRange(InstsB, InstsE);
294 }
295
296 assert(Match == 0 && "Multiple matches??");
297 Match = R;
298 }
299 RangeBegin = RangeEnd;
300 }
301
302 return Match;
303}
304
305static void PrintValue(Record *I, unsigned char *Ptr, const RecordVal &Val) {
306 assert(dynamic_cast<BitsInit*>(Val.getValue()) &&
307 "Can only handle undefined bits<> types!");
308 BitsInit *BI = (BitsInit*)Val.getValue();
309 assert(BI->getNumBits() <= 32 && "Can only handle fields up to 32 bits!");
310
311 unsigned Value = 0;
312 const std::vector<RecordVal> &Vals = I->getValues();
313
314 // Start by filling in fixed values...
315 for (unsigned i = 0, e = BI->getNumBits(); i != e; ++i)
316 if (BitInit *B = dynamic_cast<BitInit*>(BI->getBit(i)))
317 Value |= B->getValue() << i;
318
319 // Loop over all of the fields in the instruction adding in any
320 // contributions to this value (due to bit references).
321 //
322 unsigned Offset = 0;
323 for (unsigned f = 0, e = Vals.size(); f != e; ++f)
324 if (Vals[f].getPrefix()) {
Chris Lattner98334932002-12-02 17:43:43 +0000325 BitsInit *FieldInitializer = (BitsInit*)Vals[f].getValue();
Chris Lattnere62c1182002-12-02 01:23:04 +0000326 if (&Vals[f] == &Val) {
327 // Read the bits directly now...
328 for (unsigned i = 0, e = BI->getNumBits(); i != e; ++i)
329 Value |= getMemoryBit(Ptr, Offset+i) << i;
330 break;
331 }
332
333 // Scan through the field looking for bit initializers of the current
334 // variable...
Chris Lattner98334932002-12-02 17:43:43 +0000335 for (unsigned i = 0, e = FieldInitializer->getNumBits(); i != e; ++i)
Chris Lattnere62c1182002-12-02 01:23:04 +0000336 if (VarBitInit *VBI =
Chris Lattner98334932002-12-02 17:43:43 +0000337 dynamic_cast<VarBitInit*>(FieldInitializer->getBit(i))) {
338 TypedInit *TI = VBI->getVariable();
339 if (VarInit *VI = dynamic_cast<VarInit*>(TI)) {
340 if (VI->getName() == Val.getName())
341 Value |= getMemoryBit(Ptr, Offset+i) << VBI->getBitNum();
342 } else if (FieldInit *FI = dynamic_cast<FieldInit*>(TI)) {
343 // FIXME: implement this!
344 std::cerr << "FIELD INIT not implemented yet!\n";
345 }
Chris Lattnere62c1182002-12-02 01:23:04 +0000346 }
Chris Lattner98334932002-12-02 17:43:43 +0000347 Offset += FieldInitializer->getNumBits();
Chris Lattnere62c1182002-12-02 01:23:04 +0000348 }
349
350 std::cout << "0x" << std::hex << Value << std::dec;
351}
352
353static void PrintInstruction(Record *I, unsigned char *Ptr) {
354 std::cout << "Inst " << getNumBits(I)/8 << " bytes: "
355 << "\t" << I->getName() << "\t" << *I->getValue("Name")->getValue()
356 << "\t";
357
358 const std::vector<RecordVal> &Vals = I->getValues();
359 for (unsigned i = 0, e = Vals.size(); i != e; ++i)
360 if (!Vals[i].getValue()->isComplete()) {
361 std::cout << Vals[i].getName() << "=";
362 PrintValue(I, Ptr, Vals[i]);
363 std::cout << "\t";
364 }
365
366 std::cout << "\n";// << *I;
367}
368
369static void ParseMachineCode() {
Misha Brukmanf00ce8b2003-05-24 00:17:12 +0000370 // X86 code
Chris Lattner7b1d49b2002-12-03 20:01:04 +0000371 unsigned char Buffer[] = {
372 0x55, // push EBP
Chris Lattnere62c1182002-12-02 01:23:04 +0000373 0x89, 0xE5, // mov EBP, ESP
374 //0x83, 0xEC, 0x08, // sub ESP, 0x8
375 0xE8, 1, 2, 3, 4, // call +0x04030201
376 0x89, 0xEC, // mov ESP, EBP
377 0x5D, // pop EBP
378 0xC3, // ret
379 0x90, // nop
380 0xC9, // leave
381 0x89, 0xF6, // mov ESI, ESI
Chris Lattnere62c1182002-12-02 01:23:04 +0000382 0x68, 1, 2, 3, 4, // push 0x04030201
383 0x5e, // pop ESI
384 0xFF, 0xD0, // call EAX
Chris Lattner7b1d49b2002-12-03 20:01:04 +0000385 0xB8, 1, 2, 3, 4, // mov EAX, 0x04030201
Chris Lattnere62c1182002-12-02 01:23:04 +0000386 0x85, 0xC0, // test EAX, EAX
387 0xF4, // hlt
388 };
Misha Brukmanf00ce8b2003-05-24 00:17:12 +0000389
390#if 0
391 // SparcV9 code
392 unsigned char Buffer[] = { 0xbf, 0xe0, 0x20, 0x1f, 0x1, 0x0, 0x0, 0x1,
393 0x0, 0x0, 0x0, 0x0, 0xc1, 0x0, 0x20, 0x1, 0x1,
394 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
395 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x0, 0x0, 0x0, 0x1,
396 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
397 0x0, 0x0, 0xaf, 0xe8, 0x20, 0x17
398 };
399#endif
400
Chris Lattner1d1adea2003-08-01 04:39:05 +0000401 std::vector<Record*> Insts = Records.getAllDerivedDefinitions("Instruction");
Chris Lattnere62c1182002-12-02 01:23:04 +0000402
403 unsigned char *BuffPtr = Buffer;
404 while (1) {
405 Record *R = ParseMachineCode(Insts.begin(), Insts.end(), BuffPtr);
Chris Lattnere62c1182002-12-02 01:23:04 +0000406 PrintInstruction(R, BuffPtr);
407
408 unsigned Bits = getNumBits(R);
409 assert((Bits & 7) == 0 && "Instruction is not an even number of bytes!");
410 BuffPtr += Bits/8;
411 }
412}
413
Brian Gaeked0fde302003-11-11 22:41:34 +0000414} // End llvm namespace
415
416using namespace llvm;
Chris Lattnere62c1182002-12-02 01:23:04 +0000417
418int main(int argc, char **argv) {
419 cl::ParseCommandLineOptions(argc, argv);
John Criswell96b4bed2003-08-27 13:41:57 +0000420 ParseFile(InputFilename, IncludeDir);
Chris Lattnere62c1182002-12-02 01:23:04 +0000421
Chris Lattner9a886382003-06-03 05:04:42 +0000422 std::ostream *Out = &std::cout;
423 if (OutputFilename != "-") {
Chris Lattner42df6d12004-07-13 06:11:46 +0000424 Out = new std::ofstream(OutputFilename.c_str());
Chris Lattner9a886382003-06-03 05:04:42 +0000425
426 if (!Out->good()) {
Chris Lattner42df6d12004-07-13 06:11:46 +0000427 std::cerr << argv[0] << ": error opening " << OutputFilename << "!\n";
Chris Lattner9a886382003-06-03 05:04:42 +0000428 return 1;
429 }
430
431 // Make sure the file gets removed if *gasp* tablegen crashes...
Chris Lattner42df6d12004-07-13 06:11:46 +0000432 RemoveFileOnSignal(OutputFilename);
Chris Lattner9a886382003-06-03 05:04:42 +0000433 }
434
Chris Lattner1d1adea2003-08-01 04:39:05 +0000435 try {
436 switch (Action) {
Chris Lattneraccd8ab2003-08-01 04:47:20 +0000437 case PrintRecords:
438 *Out << Records; // No argument, dump all contents
439 break;
Chris Lattner1d1adea2003-08-01 04:39:05 +0000440 case Parse:
441 ParseMachineCode();
442 break;
443 case GenEmitter:
444 CodeEmitterGen(Records).run(*Out);
445 break;
Chris Lattner169e66b2003-08-03 17:24:20 +0000446
Chris Lattner54d156d2003-08-01 05:59:20 +0000447 case GenRegisterEnums:
448 RegisterInfoEmitter(Records).runEnums(*Out);
449 break;
Chris Lattner1d1adea2003-08-01 04:39:05 +0000450 case GenRegister:
451 RegisterInfoEmitter(Records).run(*Out);
452 break;
453 case GenRegisterHeader:
454 RegisterInfoEmitter(Records).runHeader(*Out);
455 break;
Chris Lattner169e66b2003-08-03 17:24:20 +0000456
457 case GenInstrEnums:
458 InstrInfoEmitter(Records).runEnums(*Out);
459 break;
Chris Lattner15de32d2003-08-03 21:58:28 +0000460 case GenInstrs:
461 InstrInfoEmitter(Records).run(*Out);
462 break;
Chris Lattner3f781342003-08-06 04:47:56 +0000463 case GenInstrSelector:
464 InstrSelectorEmitter(Records).run(*Out);
465 break;
Chris Lattner1d1adea2003-08-01 04:39:05 +0000466 case PrintEnums:
Brian Gaeked0fde302003-11-11 22:41:34 +0000467 {
Chris Lattner1d1adea2003-08-01 04:39:05 +0000468 std::vector<Record*> Recs = Records.getAllDerivedDefinitions(Class);
Chris Lattner1d1adea2003-08-01 04:39:05 +0000469 for (unsigned i = 0, e = Recs.size(); i != e; ++i)
Chris Lattner7b9ee512004-02-06 03:19:17 +0000470 *Out << Recs[i]->getName() << ", ";
Chris Lattner1d1adea2003-08-01 04:39:05 +0000471 *Out << "\n";
472 break;
Chris Lattnere62c1182002-12-02 01:23:04 +0000473 }
Jakub Staszak01b6a6f2004-04-06 19:30:56 +0000474 case GenSimpInstrSel:
475 SimpleInstrSelEmitter(Records).run(*Out);
476 break;
Brian Gaeked0fde302003-11-11 22:41:34 +0000477 default:
478 assert(1 && "Invalid Action");
479 return 1;
480 }
Chris Lattner1d1adea2003-08-01 04:39:05 +0000481 } catch (const std::string &Error) {
482 std::cerr << Error << "\n";
Chris Lattnerf1e366a2003-08-01 19:21:43 +0000483 if (Out != &std::cout) {
484 delete Out; // Close the file
485 std::remove(OutputFilename.c_str()); // Remove the file, it's broken
486 }
Chris Lattner1d1adea2003-08-01 04:39:05 +0000487 return 1;
Chris Lattnere62c1182002-12-02 01:23:04 +0000488 }
Chris Lattner9a886382003-06-03 05:04:42 +0000489
Chris Lattnere79c72d2003-08-01 20:35:01 +0000490 if (Out != &std::cout) {
491 delete Out; // Close the file
Chris Lattnere79c72d2003-08-01 20:35:01 +0000492 }
Chris Lattner1d1adea2003-08-01 04:39:05 +0000493 return 0;
Chris Lattnere62c1182002-12-02 01:23:04 +0000494}