blob: 4c8b3a0fcd33336b1a804c4075879037f2efc6bc [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 Lattnerc313d0b2006-03-03 02:32:46 +000028#include "IntrinsicEmitter.h"
Chris Lattnerf5bd1b72003-10-05 19:27:59 +000029#include <algorithm>
30#include <cstdio>
31#include <fstream>
Duraid Madina14492af2005-12-26 05:08:55 +000032#include <ios>
Chris Lattner68478662004-08-01 03:55:39 +000033using namespace llvm;
Brian Gaeke960707c2003-11-11 22:41:34 +000034
Chris Lattnerf5bd1b72003-10-05 19:27:59 +000035enum ActionType {
36 PrintRecords,
37 GenEmitter,
38 GenRegisterEnums, GenRegister, GenRegisterHeader,
Chris Lattner49f7b692005-10-23 05:47:52 +000039 GenInstrEnums, GenInstrs, GenAsmWriter,
Chris Lattner90d00042005-09-03 01:14:03 +000040 GenDAGISel,
Jim Laskey9ed90322005-10-21 19:05:19 +000041 GenSubtarget,
Chris Lattnerc313d0b2006-03-03 02:32:46 +000042 GenIntrinsic,
Chris Lattnerf5bd1b72003-10-05 19:27:59 +000043 PrintEnums,
Chris Lattner87bf9182004-07-22 21:32:38 +000044 Parse
Chris Lattnerf5bd1b72003-10-05 19:27:59 +000045};
46
47namespace {
48 cl::opt<ActionType>
49 Action(cl::desc("Action to perform:"),
50 cl::values(clEnumValN(PrintRecords, "print-records",
51 "Print all records to stdout (default)"),
52 clEnumValN(GenEmitter, "gen-emitter",
53 "Generate machine code emitter"),
54 clEnumValN(GenRegisterEnums, "gen-register-enums",
55 "Generate enum values for registers"),
56 clEnumValN(GenRegister, "gen-register-desc",
57 "Generate a register info description"),
58 clEnumValN(GenRegisterHeader, "gen-register-desc-header",
59 "Generate a register info description header"),
60 clEnumValN(GenInstrEnums, "gen-instr-enums",
61 "Generate enum values for instructions"),
62 clEnumValN(GenInstrs, "gen-instr-desc",
63 "Generate instruction descriptions"),
Chris Lattner1c4ae852004-08-01 05:59:33 +000064 clEnumValN(GenAsmWriter, "gen-asm-writer",
65 "Generate assembly writer"),
Chris Lattner90d00042005-09-03 01:14:03 +000066 clEnumValN(GenDAGISel, "gen-dag-isel",
67 "Generate a DAG instruction selector"),
Jim Laskey9ed90322005-10-21 19:05:19 +000068 clEnumValN(GenSubtarget, "gen-subtarget",
69 "Generate subtarget enumerations"),
Chris Lattnerc313d0b2006-03-03 02:32:46 +000070 clEnumValN(GenIntrinsic, "gen-intrinsic",
71 "Generate intrinsic information"),
Chris Lattnerf5bd1b72003-10-05 19:27:59 +000072 clEnumValN(PrintEnums, "print-enums",
73 "Print enum values for a class"),
74 clEnumValN(Parse, "parse",
75 "Interpret machine code (testing only)"),
Chris Lattner89ae1152004-07-16 00:02:21 +000076 clEnumValEnd));
Chris Lattnerf5bd1b72003-10-05 19:27:59 +000077
78 cl::opt<std::string>
79 Class("class", cl::desc("Print Enum list for this class"),
80 cl::value_desc("class name"));
81
82 cl::opt<std::string>
83 OutputFilename("o", cl::desc("Output filename"), cl::value_desc("filename"),
84 cl::init("-"));
85
86 cl::opt<std::string>
87 InputFilename(cl::Positional, cl::desc("<input file>"), cl::init("-"));
88
Chris Lattnere7b74c52006-03-03 01:47:14 +000089 cl::list<std::string>
90 IncludeDirs("I", cl::desc("Directory of include files"),
Chris Lattner1edf15e2006-03-03 01:53:40 +000091 cl::value_desc("directory"), cl::Prefix);
Chris Lattnerf5bd1b72003-10-05 19:27:59 +000092}
93
Chris Lattner68478662004-08-01 03:55:39 +000094namespace llvm {
95 void ParseFile(const std::string &Filename,
Chris Lattnere7b74c52006-03-03 01:47:14 +000096 const std::vector<std::string> &IncludeDirs);
Chris Lattner68478662004-08-01 03:55:39 +000097}
Chris Lattnerf5bd1b72003-10-05 19:27:59 +000098
Chris Lattner68478662004-08-01 03:55:39 +000099RecordKeeper llvm::Records;
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000100
101static Init *getBit(Record *R, unsigned BitNo) {
102 const std::vector<RecordVal> &V = R->getValues();
103 for (unsigned i = 0, e = V.size(); i != e; ++i)
104 if (V[i].getPrefix()) {
105 assert(dynamic_cast<BitsInit*>(V[i].getValue()) &&
Jeff Cohen88e7b722005-04-22 04:13:13 +0000106 "Can only handle fields of bits<> type!");
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000107 BitsInit *I = (BitsInit*)V[i].getValue();
108 if (BitNo < I->getNumBits())
Jeff Cohen88e7b722005-04-22 04:13:13 +0000109 return I->getBit(BitNo);
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000110 BitNo -= I->getNumBits();
111 }
112
113 std::cerr << "Cannot find requested bit!\n";
Chris Lattner564251e2004-02-13 16:37:43 +0000114 exit(1);
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000115 return 0;
116}
117
118static unsigned getNumBits(Record *R) {
119 const std::vector<RecordVal> &V = R->getValues();
120 unsigned Num = 0;
121 for (unsigned i = 0, e = V.size(); i != e; ++i)
122 if (V[i].getPrefix()) {
123 assert(dynamic_cast<BitsInit*>(V[i].getValue()) &&
Jeff Cohen88e7b722005-04-22 04:13:13 +0000124 "Can only handle fields of bits<> type!");
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000125 Num += ((BitsInit*)V[i].getValue())->getNumBits();
126 }
127 return Num;
128}
129
130static bool BitsAreFixed(Record *I1, Record *I2, unsigned BitNo) {
131 return dynamic_cast<BitInit*>(getBit(I1, BitNo)) &&
132 dynamic_cast<BitInit*>(getBit(I2, BitNo));
133}
134
135static bool BitsAreEqual(Record *I1, Record *I2, unsigned BitNo) {
136 BitInit *Bit1 = dynamic_cast<BitInit*>(getBit(I1, BitNo));
137 BitInit *Bit2 = dynamic_cast<BitInit*>(getBit(I2, BitNo));
138
139 return Bit1 && Bit2 && Bit1->getValue() == Bit2->getValue();
140}
141
142static bool BitRangesEqual(Record *I1, Record *I2,
Jeff Cohen88e7b722005-04-22 04:13:13 +0000143 unsigned Start, unsigned End) {
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000144 for (unsigned i = Start; i != End; ++i)
145 if (!BitsAreEqual(I1, I2, i))
146 return false;
147 return true;
148}
149
150static unsigned getFirstFixedBit(Record *R, unsigned FirstFixedBit) {
151 // Look for the first bit of the pair that are required to be 0 or 1.
152 while (!dynamic_cast<BitInit*>(getBit(R, FirstFixedBit)))
153 ++FirstFixedBit;
154 return FirstFixedBit;
155}
156
157static void FindInstDifferences(Record *I1, Record *I2,
Jeff Cohen88e7b722005-04-22 04:13:13 +0000158 unsigned FirstFixedBit, unsigned MaxBits,
159 unsigned &FirstVaryingBitOverall,
160 unsigned &LastFixedBitOverall) {
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000161 // Compare the first instruction to the rest of the instructions, looking for
162 // fields that differ.
163 //
164 unsigned FirstVaryingBit = FirstFixedBit;
165 while (FirstVaryingBit < MaxBits && BitsAreEqual(I1, I2, FirstVaryingBit))
166 ++FirstVaryingBit;
167
168 unsigned LastFixedBit = FirstVaryingBit;
169 while (LastFixedBit < MaxBits && BitsAreFixed(I1, I2, LastFixedBit))
170 ++LastFixedBit;
Misha Brukman650ba8e2005-04-22 00:00:37 +0000171
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000172 if (FirstVaryingBit < FirstVaryingBitOverall)
173 FirstVaryingBitOverall = FirstVaryingBit;
174 if (LastFixedBit < LastFixedBitOverall)
175 LastFixedBitOverall = LastFixedBit;
176}
177
178static bool getBitValue(Record *R, unsigned BitNo) {
179 Init *I = getBit(R, BitNo);
180 assert(dynamic_cast<BitInit*>(I) && "Bit should be fixed!");
181 return ((BitInit*)I)->getValue();
182}
183
184struct BitComparator {
185 unsigned BitBegin, BitEnd;
186 BitComparator(unsigned B, unsigned E) : BitBegin(B), BitEnd(E) {}
187
188 bool operator()(Record *R1, Record *R2) { // Return true if R1 is less than R2
189 for (unsigned i = BitBegin; i != BitEnd; ++i) {
190 bool V1 = getBitValue(R1, i), V2 = getBitValue(R2, i);
191 if (V1 < V2)
Jeff Cohen88e7b722005-04-22 04:13:13 +0000192 return true;
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000193 else if (V2 < V1)
Jeff Cohen88e7b722005-04-22 04:13:13 +0000194 return false;
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000195 }
196 return false;
197 }
198};
199
Misha Brukman650ba8e2005-04-22 00:00:37 +0000200static void PrintRange(std::vector<Record*>::iterator I,
Jeff Cohen88e7b722005-04-22 04:13:13 +0000201 std::vector<Record*>::iterator E) {
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000202 while (I != E) std::cerr << **I++;
203}
204
205static bool getMemoryBit(unsigned char *M, unsigned i) {
206 return (M[i/8] & (1 << (i&7))) != 0;
207}
208
209static unsigned getFirstFixedBitInSequence(std::vector<Record*>::iterator IB,
Jeff Cohen88e7b722005-04-22 04:13:13 +0000210 std::vector<Record*>::iterator IE,
211 unsigned StartBit) {
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000212 unsigned FirstFixedBit = 0;
213 for (std::vector<Record*>::iterator I = IB; I != IE; ++I)
214 FirstFixedBit = std::max(FirstFixedBit, getFirstFixedBit(*I, StartBit));
215 return FirstFixedBit;
216}
217
218// ParseMachineCode - Try to split the vector of instructions (which is
219// intentionally taken by-copy) in half, narrowing down the possible
220// instructions that we may have found. Eventually, this list will get pared
221// down to zero or one instruction, in which case we have a match or failure.
222//
Misha Brukman650ba8e2005-04-22 00:00:37 +0000223static Record *ParseMachineCode(std::vector<Record*>::iterator InstsB,
Jeff Cohen88e7b722005-04-22 04:13:13 +0000224 std::vector<Record*>::iterator InstsE,
225 unsigned char *M) {
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000226 assert(InstsB != InstsE && "Empty range?");
227 if (InstsB+1 == InstsE) {
228 // Only a single instruction, see if we match it...
229 Record *Inst = *InstsB;
230 for (unsigned i = 0, e = getNumBits(Inst); i != e; ++i)
231 if (BitInit *BI = dynamic_cast<BitInit*>(getBit(Inst, i)))
Jeff Cohen88e7b722005-04-22 04:13:13 +0000232 if (getMemoryBit(M, i) != BI->getValue())
233 throw std::string("Parse failed!\n");
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000234 return Inst;
235 }
236
237 unsigned MaxBits = ~0;
238 for (std::vector<Record*>::iterator I = InstsB; I != InstsE; ++I)
239 MaxBits = std::min(MaxBits, getNumBits(*I));
240
241 unsigned FirstFixedBit = getFirstFixedBitInSequence(InstsB, InstsE, 0);
242 unsigned FirstVaryingBit, LastFixedBit;
243 do {
244 FirstVaryingBit = ~0;
245 LastFixedBit = ~0;
246 for (std::vector<Record*>::iterator I = InstsB+1; I != InstsE; ++I)
247 FindInstDifferences(*InstsB, *I, FirstFixedBit, MaxBits,
Jeff Cohen88e7b722005-04-22 04:13:13 +0000248 FirstVaryingBit, LastFixedBit);
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000249 if (FirstVaryingBit == MaxBits) {
250 std::cerr << "ERROR: Could not find bit to distinguish between "
Jeff Cohen88e7b722005-04-22 04:13:13 +0000251 << "the following entries!\n";
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000252 PrintRange(InstsB, InstsE);
253 }
254
255#if 0
256 std::cerr << "FVB: " << FirstVaryingBit << " - " << LastFixedBit
Jeff Cohen88e7b722005-04-22 04:13:13 +0000257 << ": " << InstsE-InstsB << "\n";
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000258#endif
259
260 FirstFixedBit = getFirstFixedBitInSequence(InstsB, InstsE, FirstVaryingBit);
261 } while (FirstVaryingBit != FirstFixedBit);
262
263 //std::cerr << "\n\nXXXXXXXXXXXXXXXXX\n\n";
264 //PrintRange(InstsB, InstsE);
265
266 // Sort the Insts list so that the entries have all of the bits in the range
267 // [FirstVaryingBit,LastFixedBit) sorted. These bits are all guaranteed to be
268 // set to either 0 or 1 (BitInit values), which simplifies things.
269 //
270 std::sort(InstsB, InstsE, BitComparator(FirstVaryingBit, LastFixedBit));
271
272 // Once the list is sorted by these bits, split the bit list into smaller
273 // lists, and recurse on each one.
274 //
275 std::vector<Record*>::iterator RangeBegin = InstsB;
276 Record *Match = 0;
277 while (RangeBegin != InstsE) {
278 std::vector<Record*>::iterator RangeEnd = RangeBegin+1;
279 while (RangeEnd != InstsE &&
280 BitRangesEqual(*RangeBegin, *RangeEnd, FirstVaryingBit, LastFixedBit))
281 ++RangeEnd;
Misha Brukman650ba8e2005-04-22 00:00:37 +0000282
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000283 // We just identified a range of equal instructions. If this range is the
284 // input range, we were not able to distinguish between the instructions in
285 // the set. Print an error and exit!
286 //
287 if (RangeBegin == InstsB && RangeEnd == InstsE) {
288 std::cerr << "Error: Could not distinguish among the following insts!:\n";
289 PrintRange(InstsB, InstsE);
Chris Lattner564251e2004-02-13 16:37:43 +0000290 exit(1);
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000291 }
Misha Brukman650ba8e2005-04-22 00:00:37 +0000292
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000293#if 0
294 std::cerr << "FVB: " << FirstVaryingBit << " - " << LastFixedBit
Jeff Cohen88e7b722005-04-22 04:13:13 +0000295 << ": [" << RangeEnd-RangeBegin << "] - ";
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000296 for (int i = LastFixedBit-1; i >= (int)FirstVaryingBit; --i)
297 std::cerr << (int)((BitInit*)getBit(*RangeBegin, i))->getValue() << " ";
298 std::cerr << "\n";
299#endif
300
301 if (Record *R = ParseMachineCode(RangeBegin, RangeEnd, M)) {
302 if (Match) {
Jeff Cohen88e7b722005-04-22 04:13:13 +0000303 std::cerr << "Error: Multiple matches found:\n";
304 PrintRange(InstsB, InstsE);
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000305 }
306
307 assert(Match == 0 && "Multiple matches??");
308 Match = R;
309 }
310 RangeBegin = RangeEnd;
311 }
312
313 return Match;
314}
315
316static void PrintValue(Record *I, unsigned char *Ptr, const RecordVal &Val) {
317 assert(dynamic_cast<BitsInit*>(Val.getValue()) &&
Jeff Cohen88e7b722005-04-22 04:13:13 +0000318 "Can only handle undefined bits<> types!");
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000319 BitsInit *BI = (BitsInit*)Val.getValue();
320 assert(BI->getNumBits() <= 32 && "Can only handle fields up to 32 bits!");
321
322 unsigned Value = 0;
323 const std::vector<RecordVal> &Vals = I->getValues();
324
325 // Start by filling in fixed values...
326 for (unsigned i = 0, e = BI->getNumBits(); i != e; ++i)
327 if (BitInit *B = dynamic_cast<BitInit*>(BI->getBit(i)))
328 Value |= B->getValue() << i;
Misha Brukman650ba8e2005-04-22 00:00:37 +0000329
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000330 // Loop over all of the fields in the instruction adding in any
331 // contributions to this value (due to bit references).
332 //
333 unsigned Offset = 0;
334 for (unsigned f = 0, e = Vals.size(); f != e; ++f)
335 if (Vals[f].getPrefix()) {
336 BitsInit *FieldInitializer = (BitsInit*)Vals[f].getValue();
337 if (&Vals[f] == &Val) {
Jeff Cohen88e7b722005-04-22 04:13:13 +0000338 // Read the bits directly now...
339 for (unsigned i = 0, e = BI->getNumBits(); i != e; ++i)
340 Value |= getMemoryBit(Ptr, Offset+i) << i;
341 break;
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000342 }
Misha Brukman650ba8e2005-04-22 00:00:37 +0000343
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000344 // Scan through the field looking for bit initializers of the current
345 // variable...
346 for (unsigned i = 0, e = FieldInitializer->getNumBits(); i != e; ++i)
Jeff Cohen88e7b722005-04-22 04:13:13 +0000347 if (VarBitInit *VBI =
348 dynamic_cast<VarBitInit*>(FieldInitializer->getBit(i))) {
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000349 TypedInit *TI = VBI->getVariable();
350 if (VarInit *VI = dynamic_cast<VarInit*>(TI)) {
351 if (VI->getName() == Val.getName())
352 Value |= getMemoryBit(Ptr, Offset+i) << VBI->getBitNum();
353 } else if (FieldInit *FI = dynamic_cast<FieldInit*>(TI)) {
354 // FIXME: implement this!
355 std::cerr << "FIELD INIT not implemented yet!\n";
356 }
Jeff Cohen88e7b722005-04-22 04:13:13 +0000357 }
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000358 Offset += FieldInitializer->getNumBits();
359 }
360
361 std::cout << "0x" << std::hex << Value << std::dec;
362}
363
364static void PrintInstruction(Record *I, unsigned char *Ptr) {
365 std::cout << "Inst " << getNumBits(I)/8 << " bytes: "
Jeff Cohen88e7b722005-04-22 04:13:13 +0000366 << "\t" << I->getName() << "\t" << *I->getValue("Name")->getValue()
367 << "\t";
Misha Brukman650ba8e2005-04-22 00:00:37 +0000368
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000369 const std::vector<RecordVal> &Vals = I->getValues();
370 for (unsigned i = 0, e = Vals.size(); i != e; ++i)
371 if (!Vals[i].getValue()->isComplete()) {
372 std::cout << Vals[i].getName() << "=";
373 PrintValue(I, Ptr, Vals[i]);
374 std::cout << "\t";
375 }
Misha Brukman650ba8e2005-04-22 00:00:37 +0000376
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000377 std::cout << "\n";// << *I;
378}
379
380static void ParseMachineCode() {
381 // X86 code
382 unsigned char Buffer[] = {
383 0x55, // push EBP
Jeff Cohen88e7b722005-04-22 04:13:13 +0000384 0x89, 0xE5, // mov EBP, ESP
385 //0x83, 0xEC, 0x08, // sub ESP, 0x8
386 0xE8, 1, 2, 3, 4, // call +0x04030201
387 0x89, 0xEC, // mov ESP, EBP
388 0x5D, // pop EBP
389 0xC3, // ret
390 0x90, // nop
391 0xC9, // leave
392 0x89, 0xF6, // mov ESI, ESI
393 0x68, 1, 2, 3, 4, // push 0x04030201
394 0x5e, // pop ESI
395 0xFF, 0xD0, // call EAX
396 0xB8, 1, 2, 3, 4, // mov EAX, 0x04030201
397 0x85, 0xC0, // test EAX, EAX
398 0xF4, // hlt
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000399 };
400
401#if 0
402 // SparcV9 code
Misha Brukman650ba8e2005-04-22 00:00:37 +0000403 unsigned char Buffer[] = { 0xbf, 0xe0, 0x20, 0x1f, 0x1, 0x0, 0x0, 0x1,
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000404 0x0, 0x0, 0x0, 0x0, 0xc1, 0x0, 0x20, 0x1, 0x1,
405 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
406 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x0, 0x0, 0x0, 0x1,
407 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
408 0x0, 0x0, 0xaf, 0xe8, 0x20, 0x17
409 };
410#endif
411
412 std::vector<Record*> Insts = Records.getAllDerivedDefinitions("Instruction");
413
414 unsigned char *BuffPtr = Buffer;
415 while (1) {
416 Record *R = ParseMachineCode(Insts.begin(), Insts.end(), BuffPtr);
417 PrintInstruction(R, BuffPtr);
418
419 unsigned Bits = getNumBits(R);
420 assert((Bits & 7) == 0 && "Instruction is not an even number of bytes!");
421 BuffPtr += Bits/8;
422 }
423}
424
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000425int main(int argc, char **argv) {
426 cl::ParseCommandLineOptions(argc, argv);
Chris Lattnere7b74c52006-03-03 01:47:14 +0000427 ParseFile(InputFilename, IncludeDirs);
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000428
429 std::ostream *Out = &std::cout;
430 if (OutputFilename != "-") {
Chris Lattner8e30a4d2004-07-13 06:11:46 +0000431 Out = new std::ofstream(OutputFilename.c_str());
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000432
433 if (!Out->good()) {
Chris Lattner8e30a4d2004-07-13 06:11:46 +0000434 std::cerr << argv[0] << ": error opening " << OutputFilename << "!\n";
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000435 return 1;
436 }
437
438 // Make sure the file gets removed if *gasp* tablegen crashes...
Reid Spencerb2d0fa02004-11-14 22:30:54 +0000439 sys::RemoveFileOnSignal(sys::Path(OutputFilename));
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000440 }
441
442 try {
443 switch (Action) {
444 case PrintRecords:
445 *Out << Records; // No argument, dump all contents
446 break;
447 case Parse:
448 ParseMachineCode();
449 break;
450 case GenEmitter:
451 CodeEmitterGen(Records).run(*Out);
452 break;
453
454 case GenRegisterEnums:
455 RegisterInfoEmitter(Records).runEnums(*Out);
456 break;
457 case GenRegister:
458 RegisterInfoEmitter(Records).run(*Out);
459 break;
460 case GenRegisterHeader:
461 RegisterInfoEmitter(Records).runHeader(*Out);
462 break;
463
464 case GenInstrEnums:
465 InstrInfoEmitter(Records).runEnums(*Out);
466 break;
467 case GenInstrs:
468 InstrInfoEmitter(Records).run(*Out);
469 break;
Chris Lattner1c4ae852004-08-01 05:59:33 +0000470
471 case GenAsmWriter:
472 AsmWriterEmitter(Records).run(*Out);
473 break;
474
Chris Lattner90d00042005-09-03 01:14:03 +0000475 case GenDAGISel:
476 DAGISelEmitter(Records).run(*Out);
477 break;
Jim Laskey9ed90322005-10-21 19:05:19 +0000478 case GenSubtarget:
479 SubtargetEmitter(Records).run(*Out);
480 break;
Chris Lattnerc313d0b2006-03-03 02:32:46 +0000481 case GenIntrinsic:
482 IntrinsicEmitter(Records).run(*Out);
483 break;
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000484 case PrintEnums:
Brian Gaeke960707c2003-11-11 22:41:34 +0000485 {
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000486 std::vector<Record*> Recs = Records.getAllDerivedDefinitions(Class);
487 for (unsigned i = 0, e = Recs.size(); i != e; ++i)
Chris Lattnere6540162004-02-06 03:19:17 +0000488 *Out << Recs[i]->getName() << ", ";
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000489 *Out << "\n";
490 break;
491 }
Brian Gaeke960707c2003-11-11 22:41:34 +0000492 default:
493 assert(1 && "Invalid Action");
494 return 1;
495 }
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000496 } catch (const std::string &Error) {
Reid Spencerc8ec1332004-09-03 23:17:54 +0000497 std::cerr << argv[0] << ": " << Error << "\n";
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000498 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 1;
Reid Spencerc8ec1332004-09-03 23:17:54 +0000503 } catch (...) {
504 std::cerr << argv[0] << ": Unknown unexpected exception occurred.\n";
505 if (Out != &std::cout) {
506 delete Out; // Close the file
507 std::remove(OutputFilename.c_str()); // Remove the file, it's broken
508 }
509 return 2;
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000510 }
511
512 if (Out != &std::cout) {
513 delete Out; // Close the file
Chris Lattnerf5bd1b72003-10-05 19:27:59 +0000514 }
515 return 0;
516}