blob: 5d946c20f9e1016f58103c0be8f93e8a9249e7e7 [file] [log] [blame]
Chris Lattner1d1adea2003-08-01 04:39:05 +00001//===- TableGen.cpp - Top-Level TableGen implementation -------------------===//
Misha Brukman3da94ae2005-04-22 00:00:37 +00002//
John Criswell01d45822003-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 Brukman3da94ae2005-04-22 00:00:37 +00007//
John Criswell01d45822003-10-20 20:20:30 +00008//===----------------------------------------------------------------------===//
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"
Reid Spencer551ccae2004-09-01 22:55:40 +000019#include "llvm/Support/CommandLine.h"
Chris Lattnerbed85ff2004-05-27 05:41:36 +000020#include "llvm/System/Signals.h"
Reid Spencer551ccae2004-09-01 22:55:40 +000021#include "llvm/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 Lattner2e1f51b2004-08-01 05:59:33 +000025#include "AsmWriterEmitter.h"
Chris Lattner4a24c642005-09-03 01:14:03 +000026#include "DAGISelEmitter.h"
Jim Laskeyf5fc2cb2005-10-21 19:05:19 +000027#include "SubtargetEmitter.h"
Chris Lattnere62c1182002-12-02 01:23:04 +000028#include <algorithm>
Misha Brukmanc3fe45b2003-08-14 16:05:35 +000029#include <cstdio>
Chris Lattner9a886382003-06-03 05:04:42 +000030#include <fstream>
Chris Lattner2082ebe2004-08-01 03:55:39 +000031using namespace llvm;
Brian Gaeked0fde302003-11-11 22:41:34 +000032
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 Lattner2dc74dd2005-10-23 05:47:52 +000037 GenInstrEnums, GenInstrs, GenAsmWriter,
Chris Lattner4a24c642005-09-03 01:14:03 +000038 GenDAGISel,
Jim Laskeyf5fc2cb2005-10-21 19:05:19 +000039 GenSubtarget,
Chris Lattnerbc520132003-06-03 04:56:29 +000040 PrintEnums,
Chris Lattner9879aa92004-07-22 21:32:38 +000041 Parse
Chris Lattnerbc520132003-06-03 04:56:29 +000042};
43
44namespace {
45 cl::opt<ActionType>
46 Action(cl::desc("Action to perform:"),
47 cl::values(clEnumValN(PrintRecords, "print-records",
Chris Lattner85df2252003-06-03 05:07:28 +000048 "Print all records to stdout (default)"),
Chris Lattnerbc520132003-06-03 04:56:29 +000049 clEnumValN(GenEmitter, "gen-emitter",
50 "Generate machine code emitter"),
Chris Lattner54d156d2003-08-01 05:59:20 +000051 clEnumValN(GenRegisterEnums, "gen-register-enums",
52 "Generate enum values for registers"),
Chris Lattner1d1adea2003-08-01 04:39:05 +000053 clEnumValN(GenRegister, "gen-register-desc",
54 "Generate a register info description"),
55 clEnumValN(GenRegisterHeader, "gen-register-desc-header",
56 "Generate a register info description header"),
Chris Lattner169e66b2003-08-03 17:24:20 +000057 clEnumValN(GenInstrEnums, "gen-instr-enums",
58 "Generate enum values for instructions"),
Chris Lattner15de32d2003-08-03 21:58:28 +000059 clEnumValN(GenInstrs, "gen-instr-desc",
60 "Generate instruction descriptions"),
Chris Lattner2e1f51b2004-08-01 05:59:33 +000061 clEnumValN(GenAsmWriter, "gen-asm-writer",
62 "Generate assembly writer"),
Chris Lattner4a24c642005-09-03 01:14:03 +000063 clEnumValN(GenDAGISel, "gen-dag-isel",
64 "Generate a DAG instruction selector"),
Jim Laskeyf5fc2cb2005-10-21 19:05:19 +000065 clEnumValN(GenSubtarget, "gen-subtarget",
66 "Generate subtarget enumerations"),
Chris Lattnerbc520132003-06-03 04:56:29 +000067 clEnumValN(PrintEnums, "print-enums",
68 "Print enum values for a class"),
69 clEnumValN(Parse, "parse",
70 "Interpret machine code (testing only)"),
Chris Lattnerbd935332004-07-16 00:02:21 +000071 clEnumValEnd));
Chris Lattnerbc520132003-06-03 04:56:29 +000072
73 cl::opt<std::string>
Chris Lattner85df2252003-06-03 05:07:28 +000074 Class("class", cl::desc("Print Enum list for this class"),
75 cl::value_desc("class name"));
Chris Lattner9a886382003-06-03 05:04:42 +000076
Chris Lattner90523902003-07-30 19:48:02 +000077 cl::opt<std::string>
78 OutputFilename("o", cl::desc("Output filename"), cl::value_desc("filename"),
79 cl::init("-"));
80
81 cl::opt<std::string>
82 InputFilename(cl::Positional, cl::desc("<input file>"), cl::init("-"));
John Criswell96b4bed2003-08-27 13:41:57 +000083
84 cl::opt<std::string>
85 IncludeDir("I", cl::desc("Directory of include files"),
86 cl::value_desc("directory"), cl::init(""));
Chris Lattnerbc520132003-06-03 04:56:29 +000087}
88
Chris Lattner2082ebe2004-08-01 03:55:39 +000089namespace llvm {
90 void ParseFile(const std::string &Filename,
91 const std::string &IncludeDir);
92}
Chris Lattnere62c1182002-12-02 01:23:04 +000093
Chris Lattner2082ebe2004-08-01 03:55:39 +000094RecordKeeper llvm::Records;
Chris Lattnere62c1182002-12-02 01:23:04 +000095
96static Init *getBit(Record *R, unsigned BitNo) {
97 const std::vector<RecordVal> &V = R->getValues();
98 for (unsigned i = 0, e = V.size(); i != e; ++i)
99 if (V[i].getPrefix()) {
100 assert(dynamic_cast<BitsInit*>(V[i].getValue()) &&
Jeff Cohenea3e5e52005-04-22 04:13:13 +0000101 "Can only handle fields of bits<> type!");
Chris Lattnere62c1182002-12-02 01:23:04 +0000102 BitsInit *I = (BitsInit*)V[i].getValue();
103 if (BitNo < I->getNumBits())
Jeff Cohenea3e5e52005-04-22 04:13:13 +0000104 return I->getBit(BitNo);
Chris Lattnere62c1182002-12-02 01:23:04 +0000105 BitNo -= I->getNumBits();
106 }
107
108 std::cerr << "Cannot find requested bit!\n";
Chris Lattnerf5761a52004-02-13 16:37:43 +0000109 exit(1);
Chris Lattnere62c1182002-12-02 01:23:04 +0000110 return 0;
111}
112
113static unsigned getNumBits(Record *R) {
114 const std::vector<RecordVal> &V = R->getValues();
115 unsigned Num = 0;
116 for (unsigned i = 0, e = V.size(); i != e; ++i)
117 if (V[i].getPrefix()) {
118 assert(dynamic_cast<BitsInit*>(V[i].getValue()) &&
Jeff Cohenea3e5e52005-04-22 04:13:13 +0000119 "Can only handle fields of bits<> type!");
Chris Lattnere62c1182002-12-02 01:23:04 +0000120 Num += ((BitsInit*)V[i].getValue())->getNumBits();
121 }
122 return Num;
123}
124
125static bool BitsAreFixed(Record *I1, Record *I2, unsigned BitNo) {
126 return dynamic_cast<BitInit*>(getBit(I1, BitNo)) &&
127 dynamic_cast<BitInit*>(getBit(I2, BitNo));
128}
129
130static bool BitsAreEqual(Record *I1, Record *I2, unsigned BitNo) {
131 BitInit *Bit1 = dynamic_cast<BitInit*>(getBit(I1, BitNo));
132 BitInit *Bit2 = dynamic_cast<BitInit*>(getBit(I2, BitNo));
133
134 return Bit1 && Bit2 && Bit1->getValue() == Bit2->getValue();
135}
136
137static bool BitRangesEqual(Record *I1, Record *I2,
Jeff Cohenea3e5e52005-04-22 04:13:13 +0000138 unsigned Start, unsigned End) {
Chris Lattnere62c1182002-12-02 01:23:04 +0000139 for (unsigned i = Start; i != End; ++i)
140 if (!BitsAreEqual(I1, I2, i))
141 return false;
142 return true;
143}
144
145static unsigned getFirstFixedBit(Record *R, unsigned FirstFixedBit) {
146 // Look for the first bit of the pair that are required to be 0 or 1.
147 while (!dynamic_cast<BitInit*>(getBit(R, FirstFixedBit)))
148 ++FirstFixedBit;
149 return FirstFixedBit;
150}
151
152static void FindInstDifferences(Record *I1, Record *I2,
Jeff Cohenea3e5e52005-04-22 04:13:13 +0000153 unsigned FirstFixedBit, unsigned MaxBits,
154 unsigned &FirstVaryingBitOverall,
155 unsigned &LastFixedBitOverall) {
Chris Lattnere62c1182002-12-02 01:23:04 +0000156 // Compare the first instruction to the rest of the instructions, looking for
157 // fields that differ.
158 //
159 unsigned FirstVaryingBit = FirstFixedBit;
160 while (FirstVaryingBit < MaxBits && BitsAreEqual(I1, I2, FirstVaryingBit))
161 ++FirstVaryingBit;
162
163 unsigned LastFixedBit = FirstVaryingBit;
164 while (LastFixedBit < MaxBits && BitsAreFixed(I1, I2, LastFixedBit))
165 ++LastFixedBit;
Misha Brukman3da94ae2005-04-22 00:00:37 +0000166
Chris Lattnere62c1182002-12-02 01:23:04 +0000167 if (FirstVaryingBit < FirstVaryingBitOverall)
168 FirstVaryingBitOverall = FirstVaryingBit;
169 if (LastFixedBit < LastFixedBitOverall)
170 LastFixedBitOverall = LastFixedBit;
171}
172
173static bool getBitValue(Record *R, unsigned BitNo) {
174 Init *I = getBit(R, BitNo);
175 assert(dynamic_cast<BitInit*>(I) && "Bit should be fixed!");
176 return ((BitInit*)I)->getValue();
177}
178
179struct BitComparator {
180 unsigned BitBegin, BitEnd;
181 BitComparator(unsigned B, unsigned E) : BitBegin(B), BitEnd(E) {}
182
183 bool operator()(Record *R1, Record *R2) { // Return true if R1 is less than R2
184 for (unsigned i = BitBegin; i != BitEnd; ++i) {
185 bool V1 = getBitValue(R1, i), V2 = getBitValue(R2, i);
186 if (V1 < V2)
Jeff Cohenea3e5e52005-04-22 04:13:13 +0000187 return true;
Chris Lattnere62c1182002-12-02 01:23:04 +0000188 else if (V2 < V1)
Jeff Cohenea3e5e52005-04-22 04:13:13 +0000189 return false;
Chris Lattnere62c1182002-12-02 01:23:04 +0000190 }
191 return false;
192 }
193};
194
Misha Brukman3da94ae2005-04-22 00:00:37 +0000195static void PrintRange(std::vector<Record*>::iterator I,
Jeff Cohenea3e5e52005-04-22 04:13:13 +0000196 std::vector<Record*>::iterator E) {
Chris Lattnere62c1182002-12-02 01:23:04 +0000197 while (I != E) std::cerr << **I++;
198}
199
200static bool getMemoryBit(unsigned char *M, unsigned i) {
201 return (M[i/8] & (1 << (i&7))) != 0;
202}
203
204static unsigned getFirstFixedBitInSequence(std::vector<Record*>::iterator IB,
Jeff Cohenea3e5e52005-04-22 04:13:13 +0000205 std::vector<Record*>::iterator IE,
206 unsigned StartBit) {
Chris Lattnere62c1182002-12-02 01:23:04 +0000207 unsigned FirstFixedBit = 0;
208 for (std::vector<Record*>::iterator I = IB; I != IE; ++I)
209 FirstFixedBit = std::max(FirstFixedBit, getFirstFixedBit(*I, StartBit));
210 return FirstFixedBit;
211}
212
213// ParseMachineCode - Try to split the vector of instructions (which is
Misha Brukman737af822003-09-07 20:12:52 +0000214// intentionally taken by-copy) in half, narrowing down the possible
215// instructions that we may have found. Eventually, this list will get pared
216// down to zero or one instruction, in which case we have a match or failure.
Chris Lattnere62c1182002-12-02 01:23:04 +0000217//
Misha Brukman3da94ae2005-04-22 00:00:37 +0000218static Record *ParseMachineCode(std::vector<Record*>::iterator InstsB,
Jeff Cohenea3e5e52005-04-22 04:13:13 +0000219 std::vector<Record*>::iterator InstsE,
220 unsigned char *M) {
Chris Lattnere62c1182002-12-02 01:23:04 +0000221 assert(InstsB != InstsE && "Empty range?");
222 if (InstsB+1 == InstsE) {
223 // Only a single instruction, see if we match it...
224 Record *Inst = *InstsB;
225 for (unsigned i = 0, e = getNumBits(Inst); i != e; ++i)
226 if (BitInit *BI = dynamic_cast<BitInit*>(getBit(Inst, i)))
Jeff Cohenea3e5e52005-04-22 04:13:13 +0000227 if (getMemoryBit(M, i) != BI->getValue())
228 throw std::string("Parse failed!\n");
Chris Lattnere62c1182002-12-02 01:23:04 +0000229 return Inst;
230 }
231
232 unsigned MaxBits = ~0;
233 for (std::vector<Record*>::iterator I = InstsB; I != InstsE; ++I)
234 MaxBits = std::min(MaxBits, getNumBits(*I));
235
236 unsigned FirstFixedBit = getFirstFixedBitInSequence(InstsB, InstsE, 0);
237 unsigned FirstVaryingBit, LastFixedBit;
238 do {
239 FirstVaryingBit = ~0;
240 LastFixedBit = ~0;
241 for (std::vector<Record*>::iterator I = InstsB+1; I != InstsE; ++I)
242 FindInstDifferences(*InstsB, *I, FirstFixedBit, MaxBits,
Jeff Cohenea3e5e52005-04-22 04:13:13 +0000243 FirstVaryingBit, LastFixedBit);
Chris Lattnere62c1182002-12-02 01:23:04 +0000244 if (FirstVaryingBit == MaxBits) {
245 std::cerr << "ERROR: Could not find bit to distinguish between "
Jeff Cohenea3e5e52005-04-22 04:13:13 +0000246 << "the following entries!\n";
Chris Lattnere62c1182002-12-02 01:23:04 +0000247 PrintRange(InstsB, InstsE);
248 }
249
250#if 0
251 std::cerr << "FVB: " << FirstVaryingBit << " - " << LastFixedBit
Jeff Cohenea3e5e52005-04-22 04:13:13 +0000252 << ": " << InstsE-InstsB << "\n";
Chris Lattnere62c1182002-12-02 01:23:04 +0000253#endif
254
255 FirstFixedBit = getFirstFixedBitInSequence(InstsB, InstsE, FirstVaryingBit);
256 } while (FirstVaryingBit != FirstFixedBit);
257
258 //std::cerr << "\n\nXXXXXXXXXXXXXXXXX\n\n";
259 //PrintRange(InstsB, InstsE);
260
261 // Sort the Insts list so that the entries have all of the bits in the range
262 // [FirstVaryingBit,LastFixedBit) sorted. These bits are all guaranteed to be
263 // set to either 0 or 1 (BitInit values), which simplifies things.
264 //
265 std::sort(InstsB, InstsE, BitComparator(FirstVaryingBit, LastFixedBit));
266
267 // Once the list is sorted by these bits, split the bit list into smaller
268 // lists, and recurse on each one.
269 //
270 std::vector<Record*>::iterator RangeBegin = InstsB;
271 Record *Match = 0;
272 while (RangeBegin != InstsE) {
273 std::vector<Record*>::iterator RangeEnd = RangeBegin+1;
274 while (RangeEnd != InstsE &&
275 BitRangesEqual(*RangeBegin, *RangeEnd, FirstVaryingBit, LastFixedBit))
276 ++RangeEnd;
Misha Brukman3da94ae2005-04-22 00:00:37 +0000277
Chris Lattnere62c1182002-12-02 01:23:04 +0000278 // We just identified a range of equal instructions. If this range is the
279 // input range, we were not able to distinguish between the instructions in
280 // the set. Print an error and exit!
281 //
282 if (RangeBegin == InstsB && RangeEnd == InstsE) {
283 std::cerr << "Error: Could not distinguish among the following insts!:\n";
284 PrintRange(InstsB, InstsE);
Chris Lattnerf5761a52004-02-13 16:37:43 +0000285 exit(1);
Chris Lattnere62c1182002-12-02 01:23:04 +0000286 }
Misha Brukman3da94ae2005-04-22 00:00:37 +0000287
Chris Lattner7b1d49b2002-12-03 20:01:04 +0000288#if 0
289 std::cerr << "FVB: " << FirstVaryingBit << " - " << LastFixedBit
Jeff Cohenea3e5e52005-04-22 04:13:13 +0000290 << ": [" << RangeEnd-RangeBegin << "] - ";
Chris Lattner7b1d49b2002-12-03 20:01:04 +0000291 for (int i = LastFixedBit-1; i >= (int)FirstVaryingBit; --i)
292 std::cerr << (int)((BitInit*)getBit(*RangeBegin, i))->getValue() << " ";
293 std::cerr << "\n";
294#endif
295
Chris Lattnere62c1182002-12-02 01:23:04 +0000296 if (Record *R = ParseMachineCode(RangeBegin, RangeEnd, M)) {
297 if (Match) {
Jeff Cohenea3e5e52005-04-22 04:13:13 +0000298 std::cerr << "Error: Multiple matches found:\n";
299 PrintRange(InstsB, InstsE);
Chris Lattnere62c1182002-12-02 01:23:04 +0000300 }
301
302 assert(Match == 0 && "Multiple matches??");
303 Match = R;
304 }
305 RangeBegin = RangeEnd;
306 }
307
308 return Match;
309}
310
311static void PrintValue(Record *I, unsigned char *Ptr, const RecordVal &Val) {
312 assert(dynamic_cast<BitsInit*>(Val.getValue()) &&
Jeff Cohenea3e5e52005-04-22 04:13:13 +0000313 "Can only handle undefined bits<> types!");
Chris Lattnere62c1182002-12-02 01:23:04 +0000314 BitsInit *BI = (BitsInit*)Val.getValue();
315 assert(BI->getNumBits() <= 32 && "Can only handle fields up to 32 bits!");
316
317 unsigned Value = 0;
318 const std::vector<RecordVal> &Vals = I->getValues();
319
320 // Start by filling in fixed values...
321 for (unsigned i = 0, e = BI->getNumBits(); i != e; ++i)
322 if (BitInit *B = dynamic_cast<BitInit*>(BI->getBit(i)))
323 Value |= B->getValue() << i;
Misha Brukman3da94ae2005-04-22 00:00:37 +0000324
Chris Lattnere62c1182002-12-02 01:23:04 +0000325 // Loop over all of the fields in the instruction adding in any
326 // contributions to this value (due to bit references).
327 //
328 unsigned Offset = 0;
329 for (unsigned f = 0, e = Vals.size(); f != e; ++f)
330 if (Vals[f].getPrefix()) {
Chris Lattner98334932002-12-02 17:43:43 +0000331 BitsInit *FieldInitializer = (BitsInit*)Vals[f].getValue();
Chris Lattnere62c1182002-12-02 01:23:04 +0000332 if (&Vals[f] == &Val) {
Jeff Cohenea3e5e52005-04-22 04:13:13 +0000333 // Read the bits directly now...
334 for (unsigned i = 0, e = BI->getNumBits(); i != e; ++i)
335 Value |= getMemoryBit(Ptr, Offset+i) << i;
336 break;
Chris Lattnere62c1182002-12-02 01:23:04 +0000337 }
Misha Brukman3da94ae2005-04-22 00:00:37 +0000338
Chris Lattnere62c1182002-12-02 01:23:04 +0000339 // Scan through the field looking for bit initializers of the current
340 // variable...
Chris Lattner98334932002-12-02 17:43:43 +0000341 for (unsigned i = 0, e = FieldInitializer->getNumBits(); i != e; ++i)
Jeff Cohenea3e5e52005-04-22 04:13:13 +0000342 if (VarBitInit *VBI =
343 dynamic_cast<VarBitInit*>(FieldInitializer->getBit(i))) {
Chris Lattner98334932002-12-02 17:43:43 +0000344 TypedInit *TI = VBI->getVariable();
345 if (VarInit *VI = dynamic_cast<VarInit*>(TI)) {
346 if (VI->getName() == Val.getName())
347 Value |= getMemoryBit(Ptr, Offset+i) << VBI->getBitNum();
348 } else if (FieldInit *FI = dynamic_cast<FieldInit*>(TI)) {
349 // FIXME: implement this!
350 std::cerr << "FIELD INIT not implemented yet!\n";
351 }
Jeff Cohenea3e5e52005-04-22 04:13:13 +0000352 }
Chris Lattner98334932002-12-02 17:43:43 +0000353 Offset += FieldInitializer->getNumBits();
Chris Lattnere62c1182002-12-02 01:23:04 +0000354 }
355
356 std::cout << "0x" << std::hex << Value << std::dec;
357}
358
359static void PrintInstruction(Record *I, unsigned char *Ptr) {
360 std::cout << "Inst " << getNumBits(I)/8 << " bytes: "
Jeff Cohenea3e5e52005-04-22 04:13:13 +0000361 << "\t" << I->getName() << "\t" << *I->getValue("Name")->getValue()
362 << "\t";
Misha Brukman3da94ae2005-04-22 00:00:37 +0000363
Chris Lattnere62c1182002-12-02 01:23:04 +0000364 const std::vector<RecordVal> &Vals = I->getValues();
365 for (unsigned i = 0, e = Vals.size(); i != e; ++i)
366 if (!Vals[i].getValue()->isComplete()) {
367 std::cout << Vals[i].getName() << "=";
368 PrintValue(I, Ptr, Vals[i]);
369 std::cout << "\t";
370 }
Misha Brukman3da94ae2005-04-22 00:00:37 +0000371
Chris Lattnere62c1182002-12-02 01:23:04 +0000372 std::cout << "\n";// << *I;
373}
374
375static void ParseMachineCode() {
Misha Brukmanf00ce8b2003-05-24 00:17:12 +0000376 // X86 code
Chris Lattner7b1d49b2002-12-03 20:01:04 +0000377 unsigned char Buffer[] = {
378 0x55, // push EBP
Jeff Cohenea3e5e52005-04-22 04:13:13 +0000379 0x89, 0xE5, // mov EBP, ESP
380 //0x83, 0xEC, 0x08, // sub ESP, 0x8
381 0xE8, 1, 2, 3, 4, // call +0x04030201
382 0x89, 0xEC, // mov ESP, EBP
383 0x5D, // pop EBP
384 0xC3, // ret
385 0x90, // nop
386 0xC9, // leave
387 0x89, 0xF6, // mov ESI, ESI
388 0x68, 1, 2, 3, 4, // push 0x04030201
389 0x5e, // pop ESI
390 0xFF, 0xD0, // call EAX
391 0xB8, 1, 2, 3, 4, // mov EAX, 0x04030201
392 0x85, 0xC0, // test EAX, EAX
393 0xF4, // hlt
Chris Lattnere62c1182002-12-02 01:23:04 +0000394 };
Misha Brukmanf00ce8b2003-05-24 00:17:12 +0000395
396#if 0
397 // SparcV9 code
Misha Brukman3da94ae2005-04-22 00:00:37 +0000398 unsigned char Buffer[] = { 0xbf, 0xe0, 0x20, 0x1f, 0x1, 0x0, 0x0, 0x1,
Misha Brukmanf00ce8b2003-05-24 00:17:12 +0000399 0x0, 0x0, 0x0, 0x0, 0xc1, 0x0, 0x20, 0x1, 0x1,
400 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
401 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x0, 0x0, 0x0, 0x1,
402 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
403 0x0, 0x0, 0xaf, 0xe8, 0x20, 0x17
404 };
405#endif
406
Chris Lattner1d1adea2003-08-01 04:39:05 +0000407 std::vector<Record*> Insts = Records.getAllDerivedDefinitions("Instruction");
Chris Lattnere62c1182002-12-02 01:23:04 +0000408
409 unsigned char *BuffPtr = Buffer;
410 while (1) {
411 Record *R = ParseMachineCode(Insts.begin(), Insts.end(), BuffPtr);
Chris Lattnere62c1182002-12-02 01:23:04 +0000412 PrintInstruction(R, BuffPtr);
413
414 unsigned Bits = getNumBits(R);
415 assert((Bits & 7) == 0 && "Instruction is not an even number of bytes!");
416 BuffPtr += Bits/8;
417 }
418}
419
Chris Lattnere62c1182002-12-02 01:23:04 +0000420int main(int argc, char **argv) {
421 cl::ParseCommandLineOptions(argc, argv);
John Criswell96b4bed2003-08-27 13:41:57 +0000422 ParseFile(InputFilename, IncludeDir);
Chris Lattnere62c1182002-12-02 01:23:04 +0000423
Chris Lattner9a886382003-06-03 05:04:42 +0000424 std::ostream *Out = &std::cout;
425 if (OutputFilename != "-") {
Chris Lattner42df6d12004-07-13 06:11:46 +0000426 Out = new std::ofstream(OutputFilename.c_str());
Chris Lattner9a886382003-06-03 05:04:42 +0000427
428 if (!Out->good()) {
Chris Lattner42df6d12004-07-13 06:11:46 +0000429 std::cerr << argv[0] << ": error opening " << OutputFilename << "!\n";
Chris Lattner9a886382003-06-03 05:04:42 +0000430 return 1;
431 }
432
433 // Make sure the file gets removed if *gasp* tablegen crashes...
Reid Spencer227b6d02004-11-14 22:30:54 +0000434 sys::RemoveFileOnSignal(sys::Path(OutputFilename));
Chris Lattner9a886382003-06-03 05:04:42 +0000435 }
436
Chris Lattner1d1adea2003-08-01 04:39:05 +0000437 try {
438 switch (Action) {
Chris Lattneraccd8ab2003-08-01 04:47:20 +0000439 case PrintRecords:
440 *Out << Records; // No argument, dump all contents
441 break;
Chris Lattner1d1adea2003-08-01 04:39:05 +0000442 case Parse:
443 ParseMachineCode();
444 break;
445 case GenEmitter:
446 CodeEmitterGen(Records).run(*Out);
447 break;
Chris Lattner169e66b2003-08-03 17:24:20 +0000448
Chris Lattner54d156d2003-08-01 05:59:20 +0000449 case GenRegisterEnums:
450 RegisterInfoEmitter(Records).runEnums(*Out);
451 break;
Chris Lattner1d1adea2003-08-01 04:39:05 +0000452 case GenRegister:
453 RegisterInfoEmitter(Records).run(*Out);
454 break;
455 case GenRegisterHeader:
456 RegisterInfoEmitter(Records).runHeader(*Out);
457 break;
Chris Lattner169e66b2003-08-03 17:24:20 +0000458
459 case GenInstrEnums:
460 InstrInfoEmitter(Records).runEnums(*Out);
461 break;
Chris Lattner15de32d2003-08-03 21:58:28 +0000462 case GenInstrs:
463 InstrInfoEmitter(Records).run(*Out);
464 break;
Chris Lattner2e1f51b2004-08-01 05:59:33 +0000465
466 case GenAsmWriter:
467 AsmWriterEmitter(Records).run(*Out);
468 break;
469
Chris Lattner4a24c642005-09-03 01:14:03 +0000470 case GenDAGISel:
471 DAGISelEmitter(Records).run(*Out);
472 break;
Jim Laskeyf5fc2cb2005-10-21 19:05:19 +0000473 case GenSubtarget:
474 SubtargetEmitter(Records).run(*Out);
475 break;
Chris Lattner1d1adea2003-08-01 04:39:05 +0000476 case PrintEnums:
Brian Gaeked0fde302003-11-11 22:41:34 +0000477 {
Chris Lattner1d1adea2003-08-01 04:39:05 +0000478 std::vector<Record*> Recs = Records.getAllDerivedDefinitions(Class);
Chris Lattner1d1adea2003-08-01 04:39:05 +0000479 for (unsigned i = 0, e = Recs.size(); i != e; ++i)
Chris Lattner7b9ee512004-02-06 03:19:17 +0000480 *Out << Recs[i]->getName() << ", ";
Chris Lattner1d1adea2003-08-01 04:39:05 +0000481 *Out << "\n";
482 break;
Chris Lattnere62c1182002-12-02 01:23:04 +0000483 }
Brian Gaeked0fde302003-11-11 22:41:34 +0000484 default:
485 assert(1 && "Invalid Action");
486 return 1;
487 }
Chris Lattner1d1adea2003-08-01 04:39:05 +0000488 } catch (const std::string &Error) {
Reid Spencer23f7d512004-09-03 23:17:54 +0000489 std::cerr << argv[0] << ": " << Error << "\n";
Chris Lattnerf1e366a2003-08-01 19:21:43 +0000490 if (Out != &std::cout) {
491 delete Out; // Close the file
492 std::remove(OutputFilename.c_str()); // Remove the file, it's broken
493 }
Chris Lattner1d1adea2003-08-01 04:39:05 +0000494 return 1;
Reid Spencer23f7d512004-09-03 23:17:54 +0000495 } catch (...) {
496 std::cerr << argv[0] << ": Unknown unexpected exception occurred.\n";
497 if (Out != &std::cout) {
498 delete Out; // Close the file
499 std::remove(OutputFilename.c_str()); // Remove the file, it's broken
500 }
501 return 2;
Chris Lattnere62c1182002-12-02 01:23:04 +0000502 }
Chris Lattner9a886382003-06-03 05:04:42 +0000503
Chris Lattnere79c72d2003-08-01 20:35:01 +0000504 if (Out != &std::cout) {
505 delete Out; // Close the file
Chris Lattnere79c72d2003-08-01 20:35:01 +0000506 }
Chris Lattner1d1adea2003-08-01 04:39:05 +0000507 return 0;
Chris Lattnere62c1182002-12-02 01:23:04 +0000508}