blob: baa15eb6df459efaa7897750ba5573159e0ef329 [file] [log] [blame]
Chris Lattnerf5bd1b72003-10-05 19:27:59 +00001//===- TableGen.cpp - Top-Level TableGen implementation -------------------===//
Misha Brukman650ba8e2005-04-22 00:00:37 +00002//
John Criswelld3032032003-10-20 20:20:30 +00003// 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.
Misha Brukman650ba8e2005-04-22 00:00:37 +00007//
John Criswelld3032032003-10-20 20:20:30 +00008//===----------------------------------------------------------------------===//
Chris Lattnerf5bd1b72003-10-05 19:27:59 +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
18#include "Record.h"
Reid Spencer7c16caa2004-09-01 22:55:40 +000019#include "llvm/Support/CommandLine.h"
Chris Lattner278f5152004-05-27 05:41:36 +000020#include "llvm/System/Signals.h"
Reid Spencer7c16caa2004-09-01 22:55:40 +000021#include "llvm/Support/FileUtilities.h"
Chris Lattnerf5bd1b72003-10-05 19:27:59 +000022#include "CodeEmitterGen.h"
23#include "RegisterInfoEmitter.h"
24#include "InstrInfoEmitter.h"
Chris Lattner1c4ae852004-08-01 05:59:33 +000025#include "AsmWriterEmitter.h"
Chris Lattnerf5bd1b72003-10-05 19:27:59 +000026#include "InstrSelectorEmitter.h"
Chris Lattner90d00042005-09-03 01:14:03 +000027#include "DAGISelEmitter.h"
Chris Lattnerf5bd1b72003-10-05 19:27:59 +000028#include <algorithm>
29#include <cstdio>
30#include <fstream>
Chris Lattner68478662004-08-01 03:55:39 +000031using namespace llvm;
Brian Gaeke960707c2003-11-11 22:41:34 +000032
Chris Lattnerf5bd1b72003-10-05 19:27:59 +000033enum ActionType {
34 PrintRecords,
35 GenEmitter,
36 GenRegisterEnums, GenRegister, GenRegisterHeader,
Chris Lattner1c4ae852004-08-01 05:59:33 +000037 GenInstrEnums, GenInstrs, GenAsmWriter, GenInstrSelector,
Chris Lattner90d00042005-09-03 01:14:03 +000038 GenDAGISel,
Chris Lattnerf5bd1b72003-10-05 19:27:59 +000039 PrintEnums,
Chris Lattner87bf9182004-07-22 21:32:38 +000040 Parse
Chris Lattnerf5bd1b72003-10-05 19:27:59 +000041};
42
43namespace {
44 cl::opt<ActionType>
45 Action(cl::desc("Action to perform:"),
46 cl::values(clEnumValN(PrintRecords, "print-records",
47 "Print all records to stdout (default)"),
48 clEnumValN(GenEmitter, "gen-emitter",
49 "Generate machine code emitter"),
50 clEnumValN(GenRegisterEnums, "gen-register-enums",
51 "Generate enum values for registers"),
52 clEnumValN(GenRegister, "gen-register-desc",
53 "Generate a register info description"),
54 clEnumValN(GenRegisterHeader, "gen-register-desc-header",
55 "Generate a register info description header"),
56 clEnumValN(GenInstrEnums, "gen-instr-enums",
57 "Generate enum values for instructions"),
58 clEnumValN(GenInstrs, "gen-instr-desc",
59 "Generate instruction descriptions"),
Chris Lattner1c4ae852004-08-01 05:59:33 +000060 clEnumValN(GenAsmWriter, "gen-asm-writer",
61 "Generate assembly writer"),
Chris Lattnerf5bd1b72003-10-05 19:27:59 +000062 clEnumValN(GenInstrSelector, "gen-instr-selector",
63 "Generate an instruction selector"),
Chris Lattner90d00042005-09-03 01:14:03 +000064 clEnumValN(GenDAGISel, "gen-dag-isel",
65 "Generate a DAG instruction selector"),
Chris Lattnerf5bd1b72003-10-05 19:27:59 +000066 clEnumValN(PrintEnums, "print-enums",
67 "Print enum values for a class"),
68 clEnumValN(Parse, "parse",
69 "Interpret machine code (testing only)"),
Chris Lattner89ae1152004-07-16 00:02:21 +000070 clEnumValEnd));
Chris Lattnerf5bd1b72003-10-05 19:27:59 +000071
72 cl::opt<std::string>
73 Class("class", cl::desc("Print Enum list for this class"),
74 cl::value_desc("class name"));
75
76 cl::opt<std::string>
77 OutputFilename("o", cl::desc("Output filename"), cl::value_desc("filename"),
78 cl::init("-"));
79
80 cl::opt<std::string>
81 InputFilename(cl::Positional, cl::desc("<input file>"), cl::init("-"));
82
83 cl::opt<std::string>
84 IncludeDir("I", cl::desc("Directory of include files"),
85 cl::value_desc("directory"), cl::init(""));
86}
87
Chris Lattner68478662004-08-01 03:55:39 +000088namespace llvm {
89 void ParseFile(const std::string &Filename,
90 const std::string &IncludeDir);
91}
Chris Lattnerf5bd1b72003-10-05 19:27:59 +000092
Chris Lattner68478662004-08-01 03:55:39 +000093RecordKeeper llvm::Records;
Chris Lattnerf5bd1b72003-10-05 19:27:59 +000094
95static Init *getBit(Record *R, unsigned BitNo) {
96 const std::vector<RecordVal> &V = R->getValues();
97 for (unsigned i = 0, e = V.size(); i != e; ++i)
98 if (V[i].getPrefix()) {
99 assert(dynamic_cast<BitsInit*>(V[i].getValue()) &&
Jeff Cohen88e7b722005-04-22 04:13:13 +0000100 "Can only handle fields of bits<> type!");
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000101 BitsInit *I = (BitsInit*)V[i].getValue();
102 if (BitNo < I->getNumBits())
Jeff Cohen88e7b722005-04-22 04:13:13 +0000103 return I->getBit(BitNo);
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000104 BitNo -= I->getNumBits();
105 }
106
107 std::cerr << "Cannot find requested bit!\n";
Chris Lattner564251e2004-02-13 16:37:43 +0000108 exit(1);
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000109 return 0;
110}
111
112static unsigned getNumBits(Record *R) {
113 const std::vector<RecordVal> &V = R->getValues();
114 unsigned Num = 0;
115 for (unsigned i = 0, e = V.size(); i != e; ++i)
116 if (V[i].getPrefix()) {
117 assert(dynamic_cast<BitsInit*>(V[i].getValue()) &&
Jeff Cohen88e7b722005-04-22 04:13:13 +0000118 "Can only handle fields of bits<> type!");
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000119 Num += ((BitsInit*)V[i].getValue())->getNumBits();
120 }
121 return Num;
122}
123
124static bool BitsAreFixed(Record *I1, Record *I2, unsigned BitNo) {
125 return dynamic_cast<BitInit*>(getBit(I1, BitNo)) &&
126 dynamic_cast<BitInit*>(getBit(I2, BitNo));
127}
128
129static bool BitsAreEqual(Record *I1, Record *I2, unsigned BitNo) {
130 BitInit *Bit1 = dynamic_cast<BitInit*>(getBit(I1, BitNo));
131 BitInit *Bit2 = dynamic_cast<BitInit*>(getBit(I2, BitNo));
132
133 return Bit1 && Bit2 && Bit1->getValue() == Bit2->getValue();
134}
135
136static bool BitRangesEqual(Record *I1, Record *I2,
Jeff Cohen88e7b722005-04-22 04:13:13 +0000137 unsigned Start, unsigned End) {
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000138 for (unsigned i = Start; i != End; ++i)
139 if (!BitsAreEqual(I1, I2, i))
140 return false;
141 return true;
142}
143
144static unsigned getFirstFixedBit(Record *R, unsigned FirstFixedBit) {
145 // Look for the first bit of the pair that are required to be 0 or 1.
146 while (!dynamic_cast<BitInit*>(getBit(R, FirstFixedBit)))
147 ++FirstFixedBit;
148 return FirstFixedBit;
149}
150
151static void FindInstDifferences(Record *I1, Record *I2,
Jeff Cohen88e7b722005-04-22 04:13:13 +0000152 unsigned FirstFixedBit, unsigned MaxBits,
153 unsigned &FirstVaryingBitOverall,
154 unsigned &LastFixedBitOverall) {
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000155 // Compare the first instruction to the rest of the instructions, looking for
156 // fields that differ.
157 //
158 unsigned FirstVaryingBit = FirstFixedBit;
159 while (FirstVaryingBit < MaxBits && BitsAreEqual(I1, I2, FirstVaryingBit))
160 ++FirstVaryingBit;
161
162 unsigned LastFixedBit = FirstVaryingBit;
163 while (LastFixedBit < MaxBits && BitsAreFixed(I1, I2, LastFixedBit))
164 ++LastFixedBit;
Misha Brukman650ba8e2005-04-22 00:00:37 +0000165
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000166 if (FirstVaryingBit < FirstVaryingBitOverall)
167 FirstVaryingBitOverall = FirstVaryingBit;
168 if (LastFixedBit < LastFixedBitOverall)
169 LastFixedBitOverall = LastFixedBit;
170}
171
172static bool getBitValue(Record *R, unsigned BitNo) {
173 Init *I = getBit(R, BitNo);
174 assert(dynamic_cast<BitInit*>(I) && "Bit should be fixed!");
175 return ((BitInit*)I)->getValue();
176}
177
178struct BitComparator {
179 unsigned BitBegin, BitEnd;
180 BitComparator(unsigned B, unsigned E) : BitBegin(B), BitEnd(E) {}
181
182 bool operator()(Record *R1, Record *R2) { // Return true if R1 is less than R2
183 for (unsigned i = BitBegin; i != BitEnd; ++i) {
184 bool V1 = getBitValue(R1, i), V2 = getBitValue(R2, i);
185 if (V1 < V2)
Jeff Cohen88e7b722005-04-22 04:13:13 +0000186 return true;
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000187 else if (V2 < V1)
Jeff Cohen88e7b722005-04-22 04:13:13 +0000188 return false;
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000189 }
190 return false;
191 }
192};
193
Misha Brukman650ba8e2005-04-22 00:00:37 +0000194static void PrintRange(std::vector<Record*>::iterator I,
Jeff Cohen88e7b722005-04-22 04:13:13 +0000195 std::vector<Record*>::iterator E) {
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000196 while (I != E) std::cerr << **I++;
197}
198
199static bool getMemoryBit(unsigned char *M, unsigned i) {
200 return (M[i/8] & (1 << (i&7))) != 0;
201}
202
203static unsigned getFirstFixedBitInSequence(std::vector<Record*>::iterator IB,
Jeff Cohen88e7b722005-04-22 04:13:13 +0000204 std::vector<Record*>::iterator IE,
205 unsigned StartBit) {
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000206 unsigned FirstFixedBit = 0;
207 for (std::vector<Record*>::iterator I = IB; I != IE; ++I)
208 FirstFixedBit = std::max(FirstFixedBit, getFirstFixedBit(*I, StartBit));
209 return FirstFixedBit;
210}
211
212// ParseMachineCode - Try to split the vector of instructions (which is
213// intentionally taken by-copy) in half, narrowing down the possible
214// instructions that we may have found. Eventually, this list will get pared
215// down to zero or one instruction, in which case we have a match or failure.
216//
Misha Brukman650ba8e2005-04-22 00:00:37 +0000217static Record *ParseMachineCode(std::vector<Record*>::iterator InstsB,
Jeff Cohen88e7b722005-04-22 04:13:13 +0000218 std::vector<Record*>::iterator InstsE,
219 unsigned char *M) {
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000220 assert(InstsB != InstsE && "Empty range?");
221 if (InstsB+1 == InstsE) {
222 // Only a single instruction, see if we match it...
223 Record *Inst = *InstsB;
224 for (unsigned i = 0, e = getNumBits(Inst); i != e; ++i)
225 if (BitInit *BI = dynamic_cast<BitInit*>(getBit(Inst, i)))
Jeff Cohen88e7b722005-04-22 04:13:13 +0000226 if (getMemoryBit(M, i) != BI->getValue())
227 throw std::string("Parse failed!\n");
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000228 return Inst;
229 }
230
231 unsigned MaxBits = ~0;
232 for (std::vector<Record*>::iterator I = InstsB; I != InstsE; ++I)
233 MaxBits = std::min(MaxBits, getNumBits(*I));
234
235 unsigned FirstFixedBit = getFirstFixedBitInSequence(InstsB, InstsE, 0);
236 unsigned FirstVaryingBit, LastFixedBit;
237 do {
238 FirstVaryingBit = ~0;
239 LastFixedBit = ~0;
240 for (std::vector<Record*>::iterator I = InstsB+1; I != InstsE; ++I)
241 FindInstDifferences(*InstsB, *I, FirstFixedBit, MaxBits,
Jeff Cohen88e7b722005-04-22 04:13:13 +0000242 FirstVaryingBit, LastFixedBit);
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000243 if (FirstVaryingBit == MaxBits) {
244 std::cerr << "ERROR: Could not find bit to distinguish between "
Jeff Cohen88e7b722005-04-22 04:13:13 +0000245 << "the following entries!\n";
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000246 PrintRange(InstsB, InstsE);
247 }
248
249#if 0
250 std::cerr << "FVB: " << FirstVaryingBit << " - " << LastFixedBit
Jeff Cohen88e7b722005-04-22 04:13:13 +0000251 << ": " << InstsE-InstsB << "\n";
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000252#endif
253
254 FirstFixedBit = getFirstFixedBitInSequence(InstsB, InstsE, FirstVaryingBit);
255 } while (FirstVaryingBit != FirstFixedBit);
256
257 //std::cerr << "\n\nXXXXXXXXXXXXXXXXX\n\n";
258 //PrintRange(InstsB, InstsE);
259
260 // Sort the Insts list so that the entries have all of the bits in the range
261 // [FirstVaryingBit,LastFixedBit) sorted. These bits are all guaranteed to be
262 // set to either 0 or 1 (BitInit values), which simplifies things.
263 //
264 std::sort(InstsB, InstsE, BitComparator(FirstVaryingBit, LastFixedBit));
265
266 // Once the list is sorted by these bits, split the bit list into smaller
267 // lists, and recurse on each one.
268 //
269 std::vector<Record*>::iterator RangeBegin = InstsB;
270 Record *Match = 0;
271 while (RangeBegin != InstsE) {
272 std::vector<Record*>::iterator RangeEnd = RangeBegin+1;
273 while (RangeEnd != InstsE &&
274 BitRangesEqual(*RangeBegin, *RangeEnd, FirstVaryingBit, LastFixedBit))
275 ++RangeEnd;
Misha Brukman650ba8e2005-04-22 00:00:37 +0000276
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000277 // We just identified a range of equal instructions. If this range is the
278 // input range, we were not able to distinguish between the instructions in
279 // the set. Print an error and exit!
280 //
281 if (RangeBegin == InstsB && RangeEnd == InstsE) {
282 std::cerr << "Error: Could not distinguish among the following insts!:\n";
283 PrintRange(InstsB, InstsE);
Chris Lattner564251e2004-02-13 16:37:43 +0000284 exit(1);
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000285 }
Misha Brukman650ba8e2005-04-22 00:00:37 +0000286
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000287#if 0
288 std::cerr << "FVB: " << FirstVaryingBit << " - " << LastFixedBit
Jeff Cohen88e7b722005-04-22 04:13:13 +0000289 << ": [" << RangeEnd-RangeBegin << "] - ";
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000290 for (int i = LastFixedBit-1; i >= (int)FirstVaryingBit; --i)
291 std::cerr << (int)((BitInit*)getBit(*RangeBegin, i))->getValue() << " ";
292 std::cerr << "\n";
293#endif
294
295 if (Record *R = ParseMachineCode(RangeBegin, RangeEnd, M)) {
296 if (Match) {
Jeff Cohen88e7b722005-04-22 04:13:13 +0000297 std::cerr << "Error: Multiple matches found:\n";
298 PrintRange(InstsB, InstsE);
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000299 }
300
301 assert(Match == 0 && "Multiple matches??");
302 Match = R;
303 }
304 RangeBegin = RangeEnd;
305 }
306
307 return Match;
308}
309
310static void PrintValue(Record *I, unsigned char *Ptr, const RecordVal &Val) {
311 assert(dynamic_cast<BitsInit*>(Val.getValue()) &&
Jeff Cohen88e7b722005-04-22 04:13:13 +0000312 "Can only handle undefined bits<> types!");
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000313 BitsInit *BI = (BitsInit*)Val.getValue();
314 assert(BI->getNumBits() <= 32 && "Can only handle fields up to 32 bits!");
315
316 unsigned Value = 0;
317 const std::vector<RecordVal> &Vals = I->getValues();
318
319 // Start by filling in fixed values...
320 for (unsigned i = 0, e = BI->getNumBits(); i != e; ++i)
321 if (BitInit *B = dynamic_cast<BitInit*>(BI->getBit(i)))
322 Value |= B->getValue() << i;
Misha Brukman650ba8e2005-04-22 00:00:37 +0000323
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000324 // Loop over all of the fields in the instruction adding in any
325 // contributions to this value (due to bit references).
326 //
327 unsigned Offset = 0;
328 for (unsigned f = 0, e = Vals.size(); f != e; ++f)
329 if (Vals[f].getPrefix()) {
330 BitsInit *FieldInitializer = (BitsInit*)Vals[f].getValue();
331 if (&Vals[f] == &Val) {
Jeff Cohen88e7b722005-04-22 04:13:13 +0000332 // Read the bits directly now...
333 for (unsigned i = 0, e = BI->getNumBits(); i != e; ++i)
334 Value |= getMemoryBit(Ptr, Offset+i) << i;
335 break;
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000336 }
Misha Brukman650ba8e2005-04-22 00:00:37 +0000337
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000338 // Scan through the field looking for bit initializers of the current
339 // variable...
340 for (unsigned i = 0, e = FieldInitializer->getNumBits(); i != e; ++i)
Jeff Cohen88e7b722005-04-22 04:13:13 +0000341 if (VarBitInit *VBI =
342 dynamic_cast<VarBitInit*>(FieldInitializer->getBit(i))) {
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000343 TypedInit *TI = VBI->getVariable();
344 if (VarInit *VI = dynamic_cast<VarInit*>(TI)) {
345 if (VI->getName() == Val.getName())
346 Value |= getMemoryBit(Ptr, Offset+i) << VBI->getBitNum();
347 } else if (FieldInit *FI = dynamic_cast<FieldInit*>(TI)) {
348 // FIXME: implement this!
349 std::cerr << "FIELD INIT not implemented yet!\n";
350 }
Jeff Cohen88e7b722005-04-22 04:13:13 +0000351 }
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000352 Offset += FieldInitializer->getNumBits();
353 }
354
355 std::cout << "0x" << std::hex << Value << std::dec;
356}
357
358static void PrintInstruction(Record *I, unsigned char *Ptr) {
359 std::cout << "Inst " << getNumBits(I)/8 << " bytes: "
Jeff Cohen88e7b722005-04-22 04:13:13 +0000360 << "\t" << I->getName() << "\t" << *I->getValue("Name")->getValue()
361 << "\t";
Misha Brukman650ba8e2005-04-22 00:00:37 +0000362
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000363 const std::vector<RecordVal> &Vals = I->getValues();
364 for (unsigned i = 0, e = Vals.size(); i != e; ++i)
365 if (!Vals[i].getValue()->isComplete()) {
366 std::cout << Vals[i].getName() << "=";
367 PrintValue(I, Ptr, Vals[i]);
368 std::cout << "\t";
369 }
Misha Brukman650ba8e2005-04-22 00:00:37 +0000370
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000371 std::cout << "\n";// << *I;
372}
373
374static void ParseMachineCode() {
375 // X86 code
376 unsigned char Buffer[] = {
377 0x55, // push EBP
Jeff Cohen88e7b722005-04-22 04:13:13 +0000378 0x89, 0xE5, // mov EBP, ESP
379 //0x83, 0xEC, 0x08, // sub ESP, 0x8
380 0xE8, 1, 2, 3, 4, // call +0x04030201
381 0x89, 0xEC, // mov ESP, EBP
382 0x5D, // pop EBP
383 0xC3, // ret
384 0x90, // nop
385 0xC9, // leave
386 0x89, 0xF6, // mov ESI, ESI
387 0x68, 1, 2, 3, 4, // push 0x04030201
388 0x5e, // pop ESI
389 0xFF, 0xD0, // call EAX
390 0xB8, 1, 2, 3, 4, // mov EAX, 0x04030201
391 0x85, 0xC0, // test EAX, EAX
392 0xF4, // hlt
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000393 };
394
395#if 0
396 // SparcV9 code
Misha Brukman650ba8e2005-04-22 00:00:37 +0000397 unsigned char Buffer[] = { 0xbf, 0xe0, 0x20, 0x1f, 0x1, 0x0, 0x0, 0x1,
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000398 0x0, 0x0, 0x0, 0x0, 0xc1, 0x0, 0x20, 0x1, 0x1,
399 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
400 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x0, 0x0, 0x0, 0x1,
401 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
402 0x0, 0x0, 0xaf, 0xe8, 0x20, 0x17
403 };
404#endif
405
406 std::vector<Record*> Insts = Records.getAllDerivedDefinitions("Instruction");
407
408 unsigned char *BuffPtr = Buffer;
409 while (1) {
410 Record *R = ParseMachineCode(Insts.begin(), Insts.end(), BuffPtr);
411 PrintInstruction(R, BuffPtr);
412
413 unsigned Bits = getNumBits(R);
414 assert((Bits & 7) == 0 && "Instruction is not an even number of bytes!");
415 BuffPtr += Bits/8;
416 }
417}
418
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000419int main(int argc, char **argv) {
420 cl::ParseCommandLineOptions(argc, argv);
421 ParseFile(InputFilename, IncludeDir);
422
423 std::ostream *Out = &std::cout;
424 if (OutputFilename != "-") {
Chris Lattner8e30a4d2004-07-13 06:11:46 +0000425 Out = new std::ofstream(OutputFilename.c_str());
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000426
427 if (!Out->good()) {
Chris Lattner8e30a4d2004-07-13 06:11:46 +0000428 std::cerr << argv[0] << ": error opening " << OutputFilename << "!\n";
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000429 return 1;
430 }
431
432 // Make sure the file gets removed if *gasp* tablegen crashes...
Reid Spencerb2d0fa02004-11-14 22:30:54 +0000433 sys::RemoveFileOnSignal(sys::Path(OutputFilename));
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000434 }
435
436 try {
437 switch (Action) {
438 case PrintRecords:
439 *Out << Records; // No argument, dump all contents
440 break;
441 case Parse:
442 ParseMachineCode();
443 break;
444 case GenEmitter:
445 CodeEmitterGen(Records).run(*Out);
446 break;
447
448 case GenRegisterEnums:
449 RegisterInfoEmitter(Records).runEnums(*Out);
450 break;
451 case GenRegister:
452 RegisterInfoEmitter(Records).run(*Out);
453 break;
454 case GenRegisterHeader:
455 RegisterInfoEmitter(Records).runHeader(*Out);
456 break;
457
458 case GenInstrEnums:
459 InstrInfoEmitter(Records).runEnums(*Out);
460 break;
461 case GenInstrs:
462 InstrInfoEmitter(Records).run(*Out);
463 break;
Chris Lattner1c4ae852004-08-01 05:59:33 +0000464
465 case GenAsmWriter:
466 AsmWriterEmitter(Records).run(*Out);
467 break;
468
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000469 case GenInstrSelector:
470 InstrSelectorEmitter(Records).run(*Out);
471 break;
Chris Lattner90d00042005-09-03 01:14:03 +0000472 case GenDAGISel:
473 DAGISelEmitter(Records).run(*Out);
474 break;
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000475 case PrintEnums:
Brian Gaeke960707c2003-11-11 22:41:34 +0000476 {
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000477 std::vector<Record*> Recs = Records.getAllDerivedDefinitions(Class);
478 for (unsigned i = 0, e = Recs.size(); i != e; ++i)
Chris Lattnere6540162004-02-06 03:19:17 +0000479 *Out << Recs[i]->getName() << ", ";
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000480 *Out << "\n";
481 break;
482 }
Brian Gaeke960707c2003-11-11 22:41:34 +0000483 default:
484 assert(1 && "Invalid Action");
485 return 1;
486 }
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000487 } catch (const std::string &Error) {
Reid Spencerc8ec1332004-09-03 23:17:54 +0000488 std::cerr << argv[0] << ": " << Error << "\n";
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000489 if (Out != &std::cout) {
490 delete Out; // Close the file
491 std::remove(OutputFilename.c_str()); // Remove the file, it's broken
492 }
493 return 1;
Reid Spencerc8ec1332004-09-03 23:17:54 +0000494 } catch (...) {
495 std::cerr << argv[0] << ": Unknown unexpected exception occurred.\n";
496 if (Out != &std::cout) {
497 delete Out; // Close the file
498 std::remove(OutputFilename.c_str()); // Remove the file, it's broken
499 }
500 return 2;
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000501 }
502
503 if (Out != &std::cout) {
504 delete Out; // Close the file
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000505 }
506 return 0;
507}