blob: 3f8547d599ca2f4a5ba12f330c6efb104e7fe8b0 [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 Lattner90d00042005-09-03 01:14:03 +000026#include "DAGISelEmitter.h"
Jim Laskey9ed90322005-10-21 19:05:19 +000027#include "SubtargetEmitter.h"
Chris Lattnerf5bd1b72003-10-05 19:27:59 +000028#include <algorithm>
29#include <cstdio>
30#include <fstream>
Duraid Madina14492af2005-12-26 05:08:55 +000031#include <ios>
Chris Lattner68478662004-08-01 03:55:39 +000032using namespace llvm;
Brian Gaeke960707c2003-11-11 22:41:34 +000033
Chris Lattnerf5bd1b72003-10-05 19:27:59 +000034enum ActionType {
35 PrintRecords,
36 GenEmitter,
37 GenRegisterEnums, GenRegister, GenRegisterHeader,
Chris Lattner49f7b692005-10-23 05:47:52 +000038 GenInstrEnums, GenInstrs, GenAsmWriter,
Chris Lattner90d00042005-09-03 01:14:03 +000039 GenDAGISel,
Jim Laskey9ed90322005-10-21 19:05:19 +000040 GenSubtarget,
Chris Lattnerf5bd1b72003-10-05 19:27:59 +000041 PrintEnums,
Chris Lattner87bf9182004-07-22 21:32:38 +000042 Parse
Chris Lattnerf5bd1b72003-10-05 19:27:59 +000043};
44
45namespace {
46 cl::opt<ActionType>
47 Action(cl::desc("Action to perform:"),
48 cl::values(clEnumValN(PrintRecords, "print-records",
49 "Print all records to stdout (default)"),
50 clEnumValN(GenEmitter, "gen-emitter",
51 "Generate machine code emitter"),
52 clEnumValN(GenRegisterEnums, "gen-register-enums",
53 "Generate enum values for registers"),
54 clEnumValN(GenRegister, "gen-register-desc",
55 "Generate a register info description"),
56 clEnumValN(GenRegisterHeader, "gen-register-desc-header",
57 "Generate a register info description header"),
58 clEnumValN(GenInstrEnums, "gen-instr-enums",
59 "Generate enum values for instructions"),
60 clEnumValN(GenInstrs, "gen-instr-desc",
61 "Generate instruction descriptions"),
Chris Lattner1c4ae852004-08-01 05:59:33 +000062 clEnumValN(GenAsmWriter, "gen-asm-writer",
63 "Generate assembly writer"),
Chris Lattner90d00042005-09-03 01:14:03 +000064 clEnumValN(GenDAGISel, "gen-dag-isel",
65 "Generate a DAG instruction selector"),
Jim Laskey9ed90322005-10-21 19:05:19 +000066 clEnumValN(GenSubtarget, "gen-subtarget",
67 "Generate subtarget enumerations"),
Chris Lattnerf5bd1b72003-10-05 19:27:59 +000068 clEnumValN(PrintEnums, "print-enums",
69 "Print enum values for a class"),
70 clEnumValN(Parse, "parse",
71 "Interpret machine code (testing only)"),
Chris Lattner89ae1152004-07-16 00:02:21 +000072 clEnumValEnd));
Chris Lattnerf5bd1b72003-10-05 19:27:59 +000073
74 cl::opt<std::string>
75 Class("class", cl::desc("Print Enum list for this class"),
76 cl::value_desc("class name"));
77
78 cl::opt<std::string>
79 OutputFilename("o", cl::desc("Output filename"), cl::value_desc("filename"),
80 cl::init("-"));
81
82 cl::opt<std::string>
83 InputFilename(cl::Positional, cl::desc("<input file>"), cl::init("-"));
84
85 cl::opt<std::string>
86 IncludeDir("I", cl::desc("Directory of include files"),
87 cl::value_desc("directory"), cl::init(""));
88}
89
Chris Lattner68478662004-08-01 03:55:39 +000090namespace llvm {
91 void ParseFile(const std::string &Filename,
92 const std::string &IncludeDir);
93}
Chris Lattnerf5bd1b72003-10-05 19:27:59 +000094
Chris Lattner68478662004-08-01 03:55:39 +000095RecordKeeper llvm::Records;
Chris Lattnerf5bd1b72003-10-05 19:27:59 +000096
97static Init *getBit(Record *R, unsigned BitNo) {
98 const std::vector<RecordVal> &V = R->getValues();
99 for (unsigned i = 0, e = V.size(); i != e; ++i)
100 if (V[i].getPrefix()) {
101 assert(dynamic_cast<BitsInit*>(V[i].getValue()) &&
Jeff Cohen88e7b722005-04-22 04:13:13 +0000102 "Can only handle fields of bits<> type!");
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000103 BitsInit *I = (BitsInit*)V[i].getValue();
104 if (BitNo < I->getNumBits())
Jeff Cohen88e7b722005-04-22 04:13:13 +0000105 return I->getBit(BitNo);
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000106 BitNo -= I->getNumBits();
107 }
108
109 std::cerr << "Cannot find requested bit!\n";
Chris Lattner564251e2004-02-13 16:37:43 +0000110 exit(1);
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000111 return 0;
112}
113
114static unsigned getNumBits(Record *R) {
115 const std::vector<RecordVal> &V = R->getValues();
116 unsigned Num = 0;
117 for (unsigned i = 0, e = V.size(); i != e; ++i)
118 if (V[i].getPrefix()) {
119 assert(dynamic_cast<BitsInit*>(V[i].getValue()) &&
Jeff Cohen88e7b722005-04-22 04:13:13 +0000120 "Can only handle fields of bits<> type!");
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000121 Num += ((BitsInit*)V[i].getValue())->getNumBits();
122 }
123 return Num;
124}
125
126static bool BitsAreFixed(Record *I1, Record *I2, unsigned BitNo) {
127 return dynamic_cast<BitInit*>(getBit(I1, BitNo)) &&
128 dynamic_cast<BitInit*>(getBit(I2, BitNo));
129}
130
131static bool BitsAreEqual(Record *I1, Record *I2, unsigned BitNo) {
132 BitInit *Bit1 = dynamic_cast<BitInit*>(getBit(I1, BitNo));
133 BitInit *Bit2 = dynamic_cast<BitInit*>(getBit(I2, BitNo));
134
135 return Bit1 && Bit2 && Bit1->getValue() == Bit2->getValue();
136}
137
138static bool BitRangesEqual(Record *I1, Record *I2,
Jeff Cohen88e7b722005-04-22 04:13:13 +0000139 unsigned Start, unsigned End) {
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000140 for (unsigned i = Start; i != End; ++i)
141 if (!BitsAreEqual(I1, I2, i))
142 return false;
143 return true;
144}
145
146static unsigned getFirstFixedBit(Record *R, unsigned FirstFixedBit) {
147 // Look for the first bit of the pair that are required to be 0 or 1.
148 while (!dynamic_cast<BitInit*>(getBit(R, FirstFixedBit)))
149 ++FirstFixedBit;
150 return FirstFixedBit;
151}
152
153static void FindInstDifferences(Record *I1, Record *I2,
Jeff Cohen88e7b722005-04-22 04:13:13 +0000154 unsigned FirstFixedBit, unsigned MaxBits,
155 unsigned &FirstVaryingBitOverall,
156 unsigned &LastFixedBitOverall) {
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000157 // Compare the first instruction to the rest of the instructions, looking for
158 // fields that differ.
159 //
160 unsigned FirstVaryingBit = FirstFixedBit;
161 while (FirstVaryingBit < MaxBits && BitsAreEqual(I1, I2, FirstVaryingBit))
162 ++FirstVaryingBit;
163
164 unsigned LastFixedBit = FirstVaryingBit;
165 while (LastFixedBit < MaxBits && BitsAreFixed(I1, I2, LastFixedBit))
166 ++LastFixedBit;
Misha Brukman650ba8e2005-04-22 00:00:37 +0000167
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000168 if (FirstVaryingBit < FirstVaryingBitOverall)
169 FirstVaryingBitOverall = FirstVaryingBit;
170 if (LastFixedBit < LastFixedBitOverall)
171 LastFixedBitOverall = LastFixedBit;
172}
173
174static bool getBitValue(Record *R, unsigned BitNo) {
175 Init *I = getBit(R, BitNo);
176 assert(dynamic_cast<BitInit*>(I) && "Bit should be fixed!");
177 return ((BitInit*)I)->getValue();
178}
179
180struct BitComparator {
181 unsigned BitBegin, BitEnd;
182 BitComparator(unsigned B, unsigned E) : BitBegin(B), BitEnd(E) {}
183
184 bool operator()(Record *R1, Record *R2) { // Return true if R1 is less than R2
185 for (unsigned i = BitBegin; i != BitEnd; ++i) {
186 bool V1 = getBitValue(R1, i), V2 = getBitValue(R2, i);
187 if (V1 < V2)
Jeff Cohen88e7b722005-04-22 04:13:13 +0000188 return true;
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000189 else if (V2 < V1)
Jeff Cohen88e7b722005-04-22 04:13:13 +0000190 return false;
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000191 }
192 return false;
193 }
194};
195
Misha Brukman650ba8e2005-04-22 00:00:37 +0000196static void PrintRange(std::vector<Record*>::iterator I,
Jeff Cohen88e7b722005-04-22 04:13:13 +0000197 std::vector<Record*>::iterator E) {
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000198 while (I != E) std::cerr << **I++;
199}
200
201static bool getMemoryBit(unsigned char *M, unsigned i) {
202 return (M[i/8] & (1 << (i&7))) != 0;
203}
204
205static unsigned getFirstFixedBitInSequence(std::vector<Record*>::iterator IB,
Jeff Cohen88e7b722005-04-22 04:13:13 +0000206 std::vector<Record*>::iterator IE,
207 unsigned StartBit) {
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000208 unsigned FirstFixedBit = 0;
209 for (std::vector<Record*>::iterator I = IB; I != IE; ++I)
210 FirstFixedBit = std::max(FirstFixedBit, getFirstFixedBit(*I, StartBit));
211 return FirstFixedBit;
212}
213
214// ParseMachineCode - Try to split the vector of instructions (which is
215// intentionally taken by-copy) in half, narrowing down the possible
216// instructions that we may have found. Eventually, this list will get pared
217// down to zero or one instruction, in which case we have a match or failure.
218//
Misha Brukman650ba8e2005-04-22 00:00:37 +0000219static Record *ParseMachineCode(std::vector<Record*>::iterator InstsB,
Jeff Cohen88e7b722005-04-22 04:13:13 +0000220 std::vector<Record*>::iterator InstsE,
221 unsigned char *M) {
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000222 assert(InstsB != InstsE && "Empty range?");
223 if (InstsB+1 == InstsE) {
224 // Only a single instruction, see if we match it...
225 Record *Inst = *InstsB;
226 for (unsigned i = 0, e = getNumBits(Inst); i != e; ++i)
227 if (BitInit *BI = dynamic_cast<BitInit*>(getBit(Inst, i)))
Jeff Cohen88e7b722005-04-22 04:13:13 +0000228 if (getMemoryBit(M, i) != BI->getValue())
229 throw std::string("Parse failed!\n");
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000230 return Inst;
231 }
232
233 unsigned MaxBits = ~0;
234 for (std::vector<Record*>::iterator I = InstsB; I != InstsE; ++I)
235 MaxBits = std::min(MaxBits, getNumBits(*I));
236
237 unsigned FirstFixedBit = getFirstFixedBitInSequence(InstsB, InstsE, 0);
238 unsigned FirstVaryingBit, LastFixedBit;
239 do {
240 FirstVaryingBit = ~0;
241 LastFixedBit = ~0;
242 for (std::vector<Record*>::iterator I = InstsB+1; I != InstsE; ++I)
243 FindInstDifferences(*InstsB, *I, FirstFixedBit, MaxBits,
Jeff Cohen88e7b722005-04-22 04:13:13 +0000244 FirstVaryingBit, LastFixedBit);
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000245 if (FirstVaryingBit == MaxBits) {
246 std::cerr << "ERROR: Could not find bit to distinguish between "
Jeff Cohen88e7b722005-04-22 04:13:13 +0000247 << "the following entries!\n";
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000248 PrintRange(InstsB, InstsE);
249 }
250
251#if 0
252 std::cerr << "FVB: " << FirstVaryingBit << " - " << LastFixedBit
Jeff Cohen88e7b722005-04-22 04:13:13 +0000253 << ": " << InstsE-InstsB << "\n";
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000254#endif
255
256 FirstFixedBit = getFirstFixedBitInSequence(InstsB, InstsE, FirstVaryingBit);
257 } while (FirstVaryingBit != FirstFixedBit);
258
259 //std::cerr << "\n\nXXXXXXXXXXXXXXXXX\n\n";
260 //PrintRange(InstsB, InstsE);
261
262 // Sort the Insts list so that the entries have all of the bits in the range
263 // [FirstVaryingBit,LastFixedBit) sorted. These bits are all guaranteed to be
264 // set to either 0 or 1 (BitInit values), which simplifies things.
265 //
266 std::sort(InstsB, InstsE, BitComparator(FirstVaryingBit, LastFixedBit));
267
268 // Once the list is sorted by these bits, split the bit list into smaller
269 // lists, and recurse on each one.
270 //
271 std::vector<Record*>::iterator RangeBegin = InstsB;
272 Record *Match = 0;
273 while (RangeBegin != InstsE) {
274 std::vector<Record*>::iterator RangeEnd = RangeBegin+1;
275 while (RangeEnd != InstsE &&
276 BitRangesEqual(*RangeBegin, *RangeEnd, FirstVaryingBit, LastFixedBit))
277 ++RangeEnd;
Misha Brukman650ba8e2005-04-22 00:00:37 +0000278
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000279 // We just identified a range of equal instructions. If this range is the
280 // input range, we were not able to distinguish between the instructions in
281 // the set. Print an error and exit!
282 //
283 if (RangeBegin == InstsB && RangeEnd == InstsE) {
284 std::cerr << "Error: Could not distinguish among the following insts!:\n";
285 PrintRange(InstsB, InstsE);
Chris Lattner564251e2004-02-13 16:37:43 +0000286 exit(1);
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000287 }
Misha Brukman650ba8e2005-04-22 00:00:37 +0000288
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000289#if 0
290 std::cerr << "FVB: " << FirstVaryingBit << " - " << LastFixedBit
Jeff Cohen88e7b722005-04-22 04:13:13 +0000291 << ": [" << RangeEnd-RangeBegin << "] - ";
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000292 for (int i = LastFixedBit-1; i >= (int)FirstVaryingBit; --i)
293 std::cerr << (int)((BitInit*)getBit(*RangeBegin, i))->getValue() << " ";
294 std::cerr << "\n";
295#endif
296
297 if (Record *R = ParseMachineCode(RangeBegin, RangeEnd, M)) {
298 if (Match) {
Jeff Cohen88e7b722005-04-22 04:13:13 +0000299 std::cerr << "Error: Multiple matches found:\n";
300 PrintRange(InstsB, InstsE);
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000301 }
302
303 assert(Match == 0 && "Multiple matches??");
304 Match = R;
305 }
306 RangeBegin = RangeEnd;
307 }
308
309 return Match;
310}
311
312static void PrintValue(Record *I, unsigned char *Ptr, const RecordVal &Val) {
313 assert(dynamic_cast<BitsInit*>(Val.getValue()) &&
Jeff Cohen88e7b722005-04-22 04:13:13 +0000314 "Can only handle undefined bits<> types!");
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000315 BitsInit *BI = (BitsInit*)Val.getValue();
316 assert(BI->getNumBits() <= 32 && "Can only handle fields up to 32 bits!");
317
318 unsigned Value = 0;
319 const std::vector<RecordVal> &Vals = I->getValues();
320
321 // Start by filling in fixed values...
322 for (unsigned i = 0, e = BI->getNumBits(); i != e; ++i)
323 if (BitInit *B = dynamic_cast<BitInit*>(BI->getBit(i)))
324 Value |= B->getValue() << i;
Misha Brukman650ba8e2005-04-22 00:00:37 +0000325
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000326 // Loop over all of the fields in the instruction adding in any
327 // contributions to this value (due to bit references).
328 //
329 unsigned Offset = 0;
330 for (unsigned f = 0, e = Vals.size(); f != e; ++f)
331 if (Vals[f].getPrefix()) {
332 BitsInit *FieldInitializer = (BitsInit*)Vals[f].getValue();
333 if (&Vals[f] == &Val) {
Jeff Cohen88e7b722005-04-22 04:13:13 +0000334 // Read the bits directly now...
335 for (unsigned i = 0, e = BI->getNumBits(); i != e; ++i)
336 Value |= getMemoryBit(Ptr, Offset+i) << i;
337 break;
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000338 }
Misha Brukman650ba8e2005-04-22 00:00:37 +0000339
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000340 // Scan through the field looking for bit initializers of the current
341 // variable...
342 for (unsigned i = 0, e = FieldInitializer->getNumBits(); i != e; ++i)
Jeff Cohen88e7b722005-04-22 04:13:13 +0000343 if (VarBitInit *VBI =
344 dynamic_cast<VarBitInit*>(FieldInitializer->getBit(i))) {
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000345 TypedInit *TI = VBI->getVariable();
346 if (VarInit *VI = dynamic_cast<VarInit*>(TI)) {
347 if (VI->getName() == Val.getName())
348 Value |= getMemoryBit(Ptr, Offset+i) << VBI->getBitNum();
349 } else if (FieldInit *FI = dynamic_cast<FieldInit*>(TI)) {
350 // FIXME: implement this!
351 std::cerr << "FIELD INIT not implemented yet!\n";
352 }
Jeff Cohen88e7b722005-04-22 04:13:13 +0000353 }
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000354 Offset += FieldInitializer->getNumBits();
355 }
356
357 std::cout << "0x" << std::hex << Value << std::dec;
358}
359
360static void PrintInstruction(Record *I, unsigned char *Ptr) {
361 std::cout << "Inst " << getNumBits(I)/8 << " bytes: "
Jeff Cohen88e7b722005-04-22 04:13:13 +0000362 << "\t" << I->getName() << "\t" << *I->getValue("Name")->getValue()
363 << "\t";
Misha Brukman650ba8e2005-04-22 00:00:37 +0000364
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000365 const std::vector<RecordVal> &Vals = I->getValues();
366 for (unsigned i = 0, e = Vals.size(); i != e; ++i)
367 if (!Vals[i].getValue()->isComplete()) {
368 std::cout << Vals[i].getName() << "=";
369 PrintValue(I, Ptr, Vals[i]);
370 std::cout << "\t";
371 }
Misha Brukman650ba8e2005-04-22 00:00:37 +0000372
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000373 std::cout << "\n";// << *I;
374}
375
376static void ParseMachineCode() {
377 // X86 code
378 unsigned char Buffer[] = {
379 0x55, // push EBP
Jeff Cohen88e7b722005-04-22 04:13:13 +0000380 0x89, 0xE5, // mov EBP, ESP
381 //0x83, 0xEC, 0x08, // sub ESP, 0x8
382 0xE8, 1, 2, 3, 4, // call +0x04030201
383 0x89, 0xEC, // mov ESP, EBP
384 0x5D, // pop EBP
385 0xC3, // ret
386 0x90, // nop
387 0xC9, // leave
388 0x89, 0xF6, // mov ESI, ESI
389 0x68, 1, 2, 3, 4, // push 0x04030201
390 0x5e, // pop ESI
391 0xFF, 0xD0, // call EAX
392 0xB8, 1, 2, 3, 4, // mov EAX, 0x04030201
393 0x85, 0xC0, // test EAX, EAX
394 0xF4, // hlt
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000395 };
396
397#if 0
398 // SparcV9 code
Misha Brukman650ba8e2005-04-22 00:00:37 +0000399 unsigned char Buffer[] = { 0xbf, 0xe0, 0x20, 0x1f, 0x1, 0x0, 0x0, 0x1,
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000400 0x0, 0x0, 0x0, 0x0, 0xc1, 0x0, 0x20, 0x1, 0x1,
401 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
402 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x0, 0x0, 0x0, 0x1,
403 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
404 0x0, 0x0, 0xaf, 0xe8, 0x20, 0x17
405 };
406#endif
407
408 std::vector<Record*> Insts = Records.getAllDerivedDefinitions("Instruction");
409
410 unsigned char *BuffPtr = Buffer;
411 while (1) {
412 Record *R = ParseMachineCode(Insts.begin(), Insts.end(), BuffPtr);
413 PrintInstruction(R, BuffPtr);
414
415 unsigned Bits = getNumBits(R);
416 assert((Bits & 7) == 0 && "Instruction is not an even number of bytes!");
417 BuffPtr += Bits/8;
418 }
419}
420
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000421int main(int argc, char **argv) {
422 cl::ParseCommandLineOptions(argc, argv);
423 ParseFile(InputFilename, IncludeDir);
424
425 std::ostream *Out = &std::cout;
426 if (OutputFilename != "-") {
Chris Lattner8e30a4d2004-07-13 06:11:46 +0000427 Out = new std::ofstream(OutputFilename.c_str());
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000428
429 if (!Out->good()) {
Chris Lattner8e30a4d2004-07-13 06:11:46 +0000430 std::cerr << argv[0] << ": error opening " << OutputFilename << "!\n";
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000431 return 1;
432 }
433
434 // Make sure the file gets removed if *gasp* tablegen crashes...
Reid Spencerb2d0fa02004-11-14 22:30:54 +0000435 sys::RemoveFileOnSignal(sys::Path(OutputFilename));
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000436 }
437
438 try {
439 switch (Action) {
440 case PrintRecords:
441 *Out << Records; // No argument, dump all contents
442 break;
443 case Parse:
444 ParseMachineCode();
445 break;
446 case GenEmitter:
447 CodeEmitterGen(Records).run(*Out);
448 break;
449
450 case GenRegisterEnums:
451 RegisterInfoEmitter(Records).runEnums(*Out);
452 break;
453 case GenRegister:
454 RegisterInfoEmitter(Records).run(*Out);
455 break;
456 case GenRegisterHeader:
457 RegisterInfoEmitter(Records).runHeader(*Out);
458 break;
459
460 case GenInstrEnums:
461 InstrInfoEmitter(Records).runEnums(*Out);
462 break;
463 case GenInstrs:
464 InstrInfoEmitter(Records).run(*Out);
465 break;
Chris Lattner1c4ae852004-08-01 05:59:33 +0000466
467 case GenAsmWriter:
468 AsmWriterEmitter(Records).run(*Out);
469 break;
470
Chris Lattner90d00042005-09-03 01:14:03 +0000471 case GenDAGISel:
472 DAGISelEmitter(Records).run(*Out);
473 break;
Jim Laskey9ed90322005-10-21 19:05:19 +0000474 case GenSubtarget:
475 SubtargetEmitter(Records).run(*Out);
476 break;
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000477 case PrintEnums:
Brian Gaeke960707c2003-11-11 22:41:34 +0000478 {
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000479 std::vector<Record*> Recs = Records.getAllDerivedDefinitions(Class);
480 for (unsigned i = 0, e = Recs.size(); i != e; ++i)
Chris Lattnere6540162004-02-06 03:19:17 +0000481 *Out << Recs[i]->getName() << ", ";
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000482 *Out << "\n";
483 break;
484 }
Brian Gaeke960707c2003-11-11 22:41:34 +0000485 default:
486 assert(1 && "Invalid Action");
487 return 1;
488 }
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000489 } catch (const std::string &Error) {
Reid Spencerc8ec1332004-09-03 23:17:54 +0000490 std::cerr << argv[0] << ": " << Error << "\n";
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000491 if (Out != &std::cout) {
492 delete Out; // Close the file
493 std::remove(OutputFilename.c_str()); // Remove the file, it's broken
494 }
495 return 1;
Reid Spencerc8ec1332004-09-03 23:17:54 +0000496 } catch (...) {
497 std::cerr << argv[0] << ": Unknown unexpected exception occurred.\n";
498 if (Out != &std::cout) {
499 delete Out; // Close the file
500 std::remove(OutputFilename.c_str()); // Remove the file, it's broken
501 }
502 return 2;
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000503 }
504
505 if (Out != &std::cout) {
506 delete Out; // Close the file
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000507 }
508 return 0;
509}