blob: d356e579125c96131a9b7c7eaf0276462933c114 [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 Lattner3f781342003-08-06 04:47:56 +000026#include "InstrSelectorEmitter.h"
Chris Lattner4a24c642005-09-03 01:14:03 +000027#include "DAGISelEmitter.h"
Jim Laskeyf5fc2cb2005-10-21 19:05:19 +000028#include "SubtargetEmitter.h"
Chris Lattnere62c1182002-12-02 01:23:04 +000029#include <algorithm>
Misha Brukmanc3fe45b2003-08-14 16:05:35 +000030#include <cstdio>
Chris Lattner9a886382003-06-03 05:04:42 +000031#include <fstream>
Chris Lattner2082ebe2004-08-01 03:55:39 +000032using namespace llvm;
Brian Gaeked0fde302003-11-11 22:41:34 +000033
Chris Lattnerbc520132003-06-03 04:56:29 +000034enum ActionType {
35 PrintRecords,
36 GenEmitter,
Chris Lattner54d156d2003-08-01 05:59:20 +000037 GenRegisterEnums, GenRegister, GenRegisterHeader,
Chris Lattner2e1f51b2004-08-01 05:59:33 +000038 GenInstrEnums, GenInstrs, GenAsmWriter, GenInstrSelector,
Chris Lattner4a24c642005-09-03 01:14:03 +000039 GenDAGISel,
Jim Laskeyf5fc2cb2005-10-21 19:05:19 +000040 GenSubtarget,
Chris Lattnerbc520132003-06-03 04:56:29 +000041 PrintEnums,
Chris Lattner9879aa92004-07-22 21:32:38 +000042 Parse
Chris Lattnerbc520132003-06-03 04:56:29 +000043};
44
45namespace {
46 cl::opt<ActionType>
47 Action(cl::desc("Action to perform:"),
48 cl::values(clEnumValN(PrintRecords, "print-records",
Chris Lattner85df2252003-06-03 05:07:28 +000049 "Print all records to stdout (default)"),
Chris Lattnerbc520132003-06-03 04:56:29 +000050 clEnumValN(GenEmitter, "gen-emitter",
51 "Generate machine code emitter"),
Chris Lattner54d156d2003-08-01 05:59:20 +000052 clEnumValN(GenRegisterEnums, "gen-register-enums",
53 "Generate enum values for registers"),
Chris Lattner1d1adea2003-08-01 04:39:05 +000054 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"),
Chris Lattner169e66b2003-08-03 17:24:20 +000058 clEnumValN(GenInstrEnums, "gen-instr-enums",
59 "Generate enum values for instructions"),
Chris Lattner15de32d2003-08-03 21:58:28 +000060 clEnumValN(GenInstrs, "gen-instr-desc",
61 "Generate instruction descriptions"),
Chris Lattner2e1f51b2004-08-01 05:59:33 +000062 clEnumValN(GenAsmWriter, "gen-asm-writer",
63 "Generate assembly writer"),
Chris Lattner3f781342003-08-06 04:47:56 +000064 clEnumValN(GenInstrSelector, "gen-instr-selector",
65 "Generate an instruction selector"),
Chris Lattner4a24c642005-09-03 01:14:03 +000066 clEnumValN(GenDAGISel, "gen-dag-isel",
67 "Generate a DAG instruction selector"),
Jim Laskeyf5fc2cb2005-10-21 19:05:19 +000068 clEnumValN(GenSubtarget, "gen-subtarget",
69 "Generate subtarget enumerations"),
Chris Lattnerbc520132003-06-03 04:56:29 +000070 clEnumValN(PrintEnums, "print-enums",
71 "Print enum values for a class"),
72 clEnumValN(Parse, "parse",
73 "Interpret machine code (testing only)"),
Chris Lattnerbd935332004-07-16 00:02:21 +000074 clEnumValEnd));
Chris Lattnerbc520132003-06-03 04:56:29 +000075
76 cl::opt<std::string>
Chris Lattner85df2252003-06-03 05:07:28 +000077 Class("class", cl::desc("Print Enum list for this class"),
78 cl::value_desc("class name"));
Chris Lattner9a886382003-06-03 05:04:42 +000079
Chris Lattner90523902003-07-30 19:48:02 +000080 cl::opt<std::string>
81 OutputFilename("o", cl::desc("Output filename"), cl::value_desc("filename"),
82 cl::init("-"));
83
84 cl::opt<std::string>
85 InputFilename(cl::Positional, cl::desc("<input file>"), cl::init("-"));
John Criswell96b4bed2003-08-27 13:41:57 +000086
87 cl::opt<std::string>
88 IncludeDir("I", cl::desc("Directory of include files"),
89 cl::value_desc("directory"), cl::init(""));
Chris Lattnerbc520132003-06-03 04:56:29 +000090}
91
Chris Lattner2082ebe2004-08-01 03:55:39 +000092namespace llvm {
93 void ParseFile(const std::string &Filename,
94 const std::string &IncludeDir);
95}
Chris Lattnere62c1182002-12-02 01:23:04 +000096
Chris Lattner2082ebe2004-08-01 03:55:39 +000097RecordKeeper llvm::Records;
Chris Lattnere62c1182002-12-02 01:23:04 +000098
99static Init *getBit(Record *R, unsigned BitNo) {
100 const std::vector<RecordVal> &V = R->getValues();
101 for (unsigned i = 0, e = V.size(); i != e; ++i)
102 if (V[i].getPrefix()) {
103 assert(dynamic_cast<BitsInit*>(V[i].getValue()) &&
Jeff Cohenea3e5e52005-04-22 04:13:13 +0000104 "Can only handle fields of bits<> type!");
Chris Lattnere62c1182002-12-02 01:23:04 +0000105 BitsInit *I = (BitsInit*)V[i].getValue();
106 if (BitNo < I->getNumBits())
Jeff Cohenea3e5e52005-04-22 04:13:13 +0000107 return I->getBit(BitNo);
Chris Lattnere62c1182002-12-02 01:23:04 +0000108 BitNo -= I->getNumBits();
109 }
110
111 std::cerr << "Cannot find requested bit!\n";
Chris Lattnerf5761a52004-02-13 16:37:43 +0000112 exit(1);
Chris Lattnere62c1182002-12-02 01:23:04 +0000113 return 0;
114}
115
116static unsigned getNumBits(Record *R) {
117 const std::vector<RecordVal> &V = R->getValues();
118 unsigned Num = 0;
119 for (unsigned i = 0, e = V.size(); i != e; ++i)
120 if (V[i].getPrefix()) {
121 assert(dynamic_cast<BitsInit*>(V[i].getValue()) &&
Jeff Cohenea3e5e52005-04-22 04:13:13 +0000122 "Can only handle fields of bits<> type!");
Chris Lattnere62c1182002-12-02 01:23:04 +0000123 Num += ((BitsInit*)V[i].getValue())->getNumBits();
124 }
125 return Num;
126}
127
128static bool BitsAreFixed(Record *I1, Record *I2, unsigned BitNo) {
129 return dynamic_cast<BitInit*>(getBit(I1, BitNo)) &&
130 dynamic_cast<BitInit*>(getBit(I2, BitNo));
131}
132
133static bool BitsAreEqual(Record *I1, Record *I2, unsigned BitNo) {
134 BitInit *Bit1 = dynamic_cast<BitInit*>(getBit(I1, BitNo));
135 BitInit *Bit2 = dynamic_cast<BitInit*>(getBit(I2, BitNo));
136
137 return Bit1 && Bit2 && Bit1->getValue() == Bit2->getValue();
138}
139
140static bool BitRangesEqual(Record *I1, Record *I2,
Jeff Cohenea3e5e52005-04-22 04:13:13 +0000141 unsigned Start, unsigned End) {
Chris Lattnere62c1182002-12-02 01:23:04 +0000142 for (unsigned i = Start; i != End; ++i)
143 if (!BitsAreEqual(I1, I2, i))
144 return false;
145 return true;
146}
147
148static unsigned getFirstFixedBit(Record *R, unsigned FirstFixedBit) {
149 // Look for the first bit of the pair that are required to be 0 or 1.
150 while (!dynamic_cast<BitInit*>(getBit(R, FirstFixedBit)))
151 ++FirstFixedBit;
152 return FirstFixedBit;
153}
154
155static void FindInstDifferences(Record *I1, Record *I2,
Jeff Cohenea3e5e52005-04-22 04:13:13 +0000156 unsigned FirstFixedBit, unsigned MaxBits,
157 unsigned &FirstVaryingBitOverall,
158 unsigned &LastFixedBitOverall) {
Chris Lattnere62c1182002-12-02 01:23:04 +0000159 // Compare the first instruction to the rest of the instructions, looking for
160 // fields that differ.
161 //
162 unsigned FirstVaryingBit = FirstFixedBit;
163 while (FirstVaryingBit < MaxBits && BitsAreEqual(I1, I2, FirstVaryingBit))
164 ++FirstVaryingBit;
165
166 unsigned LastFixedBit = FirstVaryingBit;
167 while (LastFixedBit < MaxBits && BitsAreFixed(I1, I2, LastFixedBit))
168 ++LastFixedBit;
Misha Brukman3da94ae2005-04-22 00:00:37 +0000169
Chris Lattnere62c1182002-12-02 01:23:04 +0000170 if (FirstVaryingBit < FirstVaryingBitOverall)
171 FirstVaryingBitOverall = FirstVaryingBit;
172 if (LastFixedBit < LastFixedBitOverall)
173 LastFixedBitOverall = LastFixedBit;
174}
175
176static bool getBitValue(Record *R, unsigned BitNo) {
177 Init *I = getBit(R, BitNo);
178 assert(dynamic_cast<BitInit*>(I) && "Bit should be fixed!");
179 return ((BitInit*)I)->getValue();
180}
181
182struct BitComparator {
183 unsigned BitBegin, BitEnd;
184 BitComparator(unsigned B, unsigned E) : BitBegin(B), BitEnd(E) {}
185
186 bool operator()(Record *R1, Record *R2) { // Return true if R1 is less than R2
187 for (unsigned i = BitBegin; i != BitEnd; ++i) {
188 bool V1 = getBitValue(R1, i), V2 = getBitValue(R2, i);
189 if (V1 < V2)
Jeff Cohenea3e5e52005-04-22 04:13:13 +0000190 return true;
Chris Lattnere62c1182002-12-02 01:23:04 +0000191 else if (V2 < V1)
Jeff Cohenea3e5e52005-04-22 04:13:13 +0000192 return false;
Chris Lattnere62c1182002-12-02 01:23:04 +0000193 }
194 return false;
195 }
196};
197
Misha Brukman3da94ae2005-04-22 00:00:37 +0000198static void PrintRange(std::vector<Record*>::iterator I,
Jeff Cohenea3e5e52005-04-22 04:13:13 +0000199 std::vector<Record*>::iterator E) {
Chris Lattnere62c1182002-12-02 01:23:04 +0000200 while (I != E) std::cerr << **I++;
201}
202
203static bool getMemoryBit(unsigned char *M, unsigned i) {
204 return (M[i/8] & (1 << (i&7))) != 0;
205}
206
207static unsigned getFirstFixedBitInSequence(std::vector<Record*>::iterator IB,
Jeff Cohenea3e5e52005-04-22 04:13:13 +0000208 std::vector<Record*>::iterator IE,
209 unsigned StartBit) {
Chris Lattnere62c1182002-12-02 01:23:04 +0000210 unsigned FirstFixedBit = 0;
211 for (std::vector<Record*>::iterator I = IB; I != IE; ++I)
212 FirstFixedBit = std::max(FirstFixedBit, getFirstFixedBit(*I, StartBit));
213 return FirstFixedBit;
214}
215
216// ParseMachineCode - Try to split the vector of instructions (which is
Misha Brukman737af822003-09-07 20:12:52 +0000217// intentionally taken by-copy) in half, narrowing down the possible
218// instructions that we may have found. Eventually, this list will get pared
219// down to zero or one instruction, in which case we have a match or failure.
Chris Lattnere62c1182002-12-02 01:23:04 +0000220//
Misha Brukman3da94ae2005-04-22 00:00:37 +0000221static Record *ParseMachineCode(std::vector<Record*>::iterator InstsB,
Jeff Cohenea3e5e52005-04-22 04:13:13 +0000222 std::vector<Record*>::iterator InstsE,
223 unsigned char *M) {
Chris Lattnere62c1182002-12-02 01:23:04 +0000224 assert(InstsB != InstsE && "Empty range?");
225 if (InstsB+1 == InstsE) {
226 // Only a single instruction, see if we match it...
227 Record *Inst = *InstsB;
228 for (unsigned i = 0, e = getNumBits(Inst); i != e; ++i)
229 if (BitInit *BI = dynamic_cast<BitInit*>(getBit(Inst, i)))
Jeff Cohenea3e5e52005-04-22 04:13:13 +0000230 if (getMemoryBit(M, i) != BI->getValue())
231 throw std::string("Parse failed!\n");
Chris Lattnere62c1182002-12-02 01:23:04 +0000232 return Inst;
233 }
234
235 unsigned MaxBits = ~0;
236 for (std::vector<Record*>::iterator I = InstsB; I != InstsE; ++I)
237 MaxBits = std::min(MaxBits, getNumBits(*I));
238
239 unsigned FirstFixedBit = getFirstFixedBitInSequence(InstsB, InstsE, 0);
240 unsigned FirstVaryingBit, LastFixedBit;
241 do {
242 FirstVaryingBit = ~0;
243 LastFixedBit = ~0;
244 for (std::vector<Record*>::iterator I = InstsB+1; I != InstsE; ++I)
245 FindInstDifferences(*InstsB, *I, FirstFixedBit, MaxBits,
Jeff Cohenea3e5e52005-04-22 04:13:13 +0000246 FirstVaryingBit, LastFixedBit);
Chris Lattnere62c1182002-12-02 01:23:04 +0000247 if (FirstVaryingBit == MaxBits) {
248 std::cerr << "ERROR: Could not find bit to distinguish between "
Jeff Cohenea3e5e52005-04-22 04:13:13 +0000249 << "the following entries!\n";
Chris Lattnere62c1182002-12-02 01:23:04 +0000250 PrintRange(InstsB, InstsE);
251 }
252
253#if 0
254 std::cerr << "FVB: " << FirstVaryingBit << " - " << LastFixedBit
Jeff Cohenea3e5e52005-04-22 04:13:13 +0000255 << ": " << InstsE-InstsB << "\n";
Chris Lattnere62c1182002-12-02 01:23:04 +0000256#endif
257
258 FirstFixedBit = getFirstFixedBitInSequence(InstsB, InstsE, FirstVaryingBit);
259 } while (FirstVaryingBit != FirstFixedBit);
260
261 //std::cerr << "\n\nXXXXXXXXXXXXXXXXX\n\n";
262 //PrintRange(InstsB, InstsE);
263
264 // Sort the Insts list so that the entries have all of the bits in the range
265 // [FirstVaryingBit,LastFixedBit) sorted. These bits are all guaranteed to be
266 // set to either 0 or 1 (BitInit values), which simplifies things.
267 //
268 std::sort(InstsB, InstsE, BitComparator(FirstVaryingBit, LastFixedBit));
269
270 // Once the list is sorted by these bits, split the bit list into smaller
271 // lists, and recurse on each one.
272 //
273 std::vector<Record*>::iterator RangeBegin = InstsB;
274 Record *Match = 0;
275 while (RangeBegin != InstsE) {
276 std::vector<Record*>::iterator RangeEnd = RangeBegin+1;
277 while (RangeEnd != InstsE &&
278 BitRangesEqual(*RangeBegin, *RangeEnd, FirstVaryingBit, LastFixedBit))
279 ++RangeEnd;
Misha Brukman3da94ae2005-04-22 00:00:37 +0000280
Chris Lattnere62c1182002-12-02 01:23:04 +0000281 // We just identified a range of equal instructions. If this range is the
282 // input range, we were not able to distinguish between the instructions in
283 // the set. Print an error and exit!
284 //
285 if (RangeBegin == InstsB && RangeEnd == InstsE) {
286 std::cerr << "Error: Could not distinguish among the following insts!:\n";
287 PrintRange(InstsB, InstsE);
Chris Lattnerf5761a52004-02-13 16:37:43 +0000288 exit(1);
Chris Lattnere62c1182002-12-02 01:23:04 +0000289 }
Misha Brukman3da94ae2005-04-22 00:00:37 +0000290
Chris Lattner7b1d49b2002-12-03 20:01:04 +0000291#if 0
292 std::cerr << "FVB: " << FirstVaryingBit << " - " << LastFixedBit
Jeff Cohenea3e5e52005-04-22 04:13:13 +0000293 << ": [" << RangeEnd-RangeBegin << "] - ";
Chris Lattner7b1d49b2002-12-03 20:01:04 +0000294 for (int i = LastFixedBit-1; i >= (int)FirstVaryingBit; --i)
295 std::cerr << (int)((BitInit*)getBit(*RangeBegin, i))->getValue() << " ";
296 std::cerr << "\n";
297#endif
298
Chris Lattnere62c1182002-12-02 01:23:04 +0000299 if (Record *R = ParseMachineCode(RangeBegin, RangeEnd, M)) {
300 if (Match) {
Jeff Cohenea3e5e52005-04-22 04:13:13 +0000301 std::cerr << "Error: Multiple matches found:\n";
302 PrintRange(InstsB, InstsE);
Chris Lattnere62c1182002-12-02 01:23:04 +0000303 }
304
305 assert(Match == 0 && "Multiple matches??");
306 Match = R;
307 }
308 RangeBegin = RangeEnd;
309 }
310
311 return Match;
312}
313
314static void PrintValue(Record *I, unsigned char *Ptr, const RecordVal &Val) {
315 assert(dynamic_cast<BitsInit*>(Val.getValue()) &&
Jeff Cohenea3e5e52005-04-22 04:13:13 +0000316 "Can only handle undefined bits<> types!");
Chris Lattnere62c1182002-12-02 01:23:04 +0000317 BitsInit *BI = (BitsInit*)Val.getValue();
318 assert(BI->getNumBits() <= 32 && "Can only handle fields up to 32 bits!");
319
320 unsigned Value = 0;
321 const std::vector<RecordVal> &Vals = I->getValues();
322
323 // Start by filling in fixed values...
324 for (unsigned i = 0, e = BI->getNumBits(); i != e; ++i)
325 if (BitInit *B = dynamic_cast<BitInit*>(BI->getBit(i)))
326 Value |= B->getValue() << i;
Misha Brukman3da94ae2005-04-22 00:00:37 +0000327
Chris Lattnere62c1182002-12-02 01:23:04 +0000328 // Loop over all of the fields in the instruction adding in any
329 // contributions to this value (due to bit references).
330 //
331 unsigned Offset = 0;
332 for (unsigned f = 0, e = Vals.size(); f != e; ++f)
333 if (Vals[f].getPrefix()) {
Chris Lattner98334932002-12-02 17:43:43 +0000334 BitsInit *FieldInitializer = (BitsInit*)Vals[f].getValue();
Chris Lattnere62c1182002-12-02 01:23:04 +0000335 if (&Vals[f] == &Val) {
Jeff Cohenea3e5e52005-04-22 04:13:13 +0000336 // Read the bits directly now...
337 for (unsigned i = 0, e = BI->getNumBits(); i != e; ++i)
338 Value |= getMemoryBit(Ptr, Offset+i) << i;
339 break;
Chris Lattnere62c1182002-12-02 01:23:04 +0000340 }
Misha Brukman3da94ae2005-04-22 00:00:37 +0000341
Chris Lattnere62c1182002-12-02 01:23:04 +0000342 // Scan through the field looking for bit initializers of the current
343 // variable...
Chris Lattner98334932002-12-02 17:43:43 +0000344 for (unsigned i = 0, e = FieldInitializer->getNumBits(); i != e; ++i)
Jeff Cohenea3e5e52005-04-22 04:13:13 +0000345 if (VarBitInit *VBI =
346 dynamic_cast<VarBitInit*>(FieldInitializer->getBit(i))) {
Chris Lattner98334932002-12-02 17:43:43 +0000347 TypedInit *TI = VBI->getVariable();
348 if (VarInit *VI = dynamic_cast<VarInit*>(TI)) {
349 if (VI->getName() == Val.getName())
350 Value |= getMemoryBit(Ptr, Offset+i) << VBI->getBitNum();
351 } else if (FieldInit *FI = dynamic_cast<FieldInit*>(TI)) {
352 // FIXME: implement this!
353 std::cerr << "FIELD INIT not implemented yet!\n";
354 }
Jeff Cohenea3e5e52005-04-22 04:13:13 +0000355 }
Chris Lattner98334932002-12-02 17:43:43 +0000356 Offset += FieldInitializer->getNumBits();
Chris Lattnere62c1182002-12-02 01:23:04 +0000357 }
358
359 std::cout << "0x" << std::hex << Value << std::dec;
360}
361
362static void PrintInstruction(Record *I, unsigned char *Ptr) {
363 std::cout << "Inst " << getNumBits(I)/8 << " bytes: "
Jeff Cohenea3e5e52005-04-22 04:13:13 +0000364 << "\t" << I->getName() << "\t" << *I->getValue("Name")->getValue()
365 << "\t";
Misha Brukman3da94ae2005-04-22 00:00:37 +0000366
Chris Lattnere62c1182002-12-02 01:23:04 +0000367 const std::vector<RecordVal> &Vals = I->getValues();
368 for (unsigned i = 0, e = Vals.size(); i != e; ++i)
369 if (!Vals[i].getValue()->isComplete()) {
370 std::cout << Vals[i].getName() << "=";
371 PrintValue(I, Ptr, Vals[i]);
372 std::cout << "\t";
373 }
Misha Brukman3da94ae2005-04-22 00:00:37 +0000374
Chris Lattnere62c1182002-12-02 01:23:04 +0000375 std::cout << "\n";// << *I;
376}
377
378static void ParseMachineCode() {
Misha Brukmanf00ce8b2003-05-24 00:17:12 +0000379 // X86 code
Chris Lattner7b1d49b2002-12-03 20:01:04 +0000380 unsigned char Buffer[] = {
381 0x55, // push EBP
Jeff Cohenea3e5e52005-04-22 04:13:13 +0000382 0x89, 0xE5, // mov EBP, ESP
383 //0x83, 0xEC, 0x08, // sub ESP, 0x8
384 0xE8, 1, 2, 3, 4, // call +0x04030201
385 0x89, 0xEC, // mov ESP, EBP
386 0x5D, // pop EBP
387 0xC3, // ret
388 0x90, // nop
389 0xC9, // leave
390 0x89, 0xF6, // mov ESI, ESI
391 0x68, 1, 2, 3, 4, // push 0x04030201
392 0x5e, // pop ESI
393 0xFF, 0xD0, // call EAX
394 0xB8, 1, 2, 3, 4, // mov EAX, 0x04030201
395 0x85, 0xC0, // test EAX, EAX
396 0xF4, // hlt
Chris Lattnere62c1182002-12-02 01:23:04 +0000397 };
Misha Brukmanf00ce8b2003-05-24 00:17:12 +0000398
399#if 0
400 // SparcV9 code
Misha Brukman3da94ae2005-04-22 00:00:37 +0000401 unsigned char Buffer[] = { 0xbf, 0xe0, 0x20, 0x1f, 0x1, 0x0, 0x0, 0x1,
Misha Brukmanf00ce8b2003-05-24 00:17:12 +0000402 0x0, 0x0, 0x0, 0x0, 0xc1, 0x0, 0x20, 0x1, 0x1,
403 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
404 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x0, 0x0, 0x0, 0x1,
405 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
406 0x0, 0x0, 0xaf, 0xe8, 0x20, 0x17
407 };
408#endif
409
Chris Lattner1d1adea2003-08-01 04:39:05 +0000410 std::vector<Record*> Insts = Records.getAllDerivedDefinitions("Instruction");
Chris Lattnere62c1182002-12-02 01:23:04 +0000411
412 unsigned char *BuffPtr = Buffer;
413 while (1) {
414 Record *R = ParseMachineCode(Insts.begin(), Insts.end(), BuffPtr);
Chris Lattnere62c1182002-12-02 01:23:04 +0000415 PrintInstruction(R, BuffPtr);
416
417 unsigned Bits = getNumBits(R);
418 assert((Bits & 7) == 0 && "Instruction is not an even number of bytes!");
419 BuffPtr += Bits/8;
420 }
421}
422
Chris Lattnere62c1182002-12-02 01:23:04 +0000423int main(int argc, char **argv) {
424 cl::ParseCommandLineOptions(argc, argv);
John Criswell96b4bed2003-08-27 13:41:57 +0000425 ParseFile(InputFilename, IncludeDir);
Chris Lattnere62c1182002-12-02 01:23:04 +0000426
Chris Lattner9a886382003-06-03 05:04:42 +0000427 std::ostream *Out = &std::cout;
428 if (OutputFilename != "-") {
Chris Lattner42df6d12004-07-13 06:11:46 +0000429 Out = new std::ofstream(OutputFilename.c_str());
Chris Lattner9a886382003-06-03 05:04:42 +0000430
431 if (!Out->good()) {
Chris Lattner42df6d12004-07-13 06:11:46 +0000432 std::cerr << argv[0] << ": error opening " << OutputFilename << "!\n";
Chris Lattner9a886382003-06-03 05:04:42 +0000433 return 1;
434 }
435
436 // Make sure the file gets removed if *gasp* tablegen crashes...
Reid Spencer227b6d02004-11-14 22:30:54 +0000437 sys::RemoveFileOnSignal(sys::Path(OutputFilename));
Chris Lattner9a886382003-06-03 05:04:42 +0000438 }
439
Chris Lattner1d1adea2003-08-01 04:39:05 +0000440 try {
441 switch (Action) {
Chris Lattneraccd8ab2003-08-01 04:47:20 +0000442 case PrintRecords:
443 *Out << Records; // No argument, dump all contents
444 break;
Chris Lattner1d1adea2003-08-01 04:39:05 +0000445 case Parse:
446 ParseMachineCode();
447 break;
448 case GenEmitter:
449 CodeEmitterGen(Records).run(*Out);
450 break;
Chris Lattner169e66b2003-08-03 17:24:20 +0000451
Chris Lattner54d156d2003-08-01 05:59:20 +0000452 case GenRegisterEnums:
453 RegisterInfoEmitter(Records).runEnums(*Out);
454 break;
Chris Lattner1d1adea2003-08-01 04:39:05 +0000455 case GenRegister:
456 RegisterInfoEmitter(Records).run(*Out);
457 break;
458 case GenRegisterHeader:
459 RegisterInfoEmitter(Records).runHeader(*Out);
460 break;
Chris Lattner169e66b2003-08-03 17:24:20 +0000461
462 case GenInstrEnums:
463 InstrInfoEmitter(Records).runEnums(*Out);
464 break;
Chris Lattner15de32d2003-08-03 21:58:28 +0000465 case GenInstrs:
466 InstrInfoEmitter(Records).run(*Out);
467 break;
Chris Lattner2e1f51b2004-08-01 05:59:33 +0000468
469 case GenAsmWriter:
470 AsmWriterEmitter(Records).run(*Out);
471 break;
472
Chris Lattner3f781342003-08-06 04:47:56 +0000473 case GenInstrSelector:
474 InstrSelectorEmitter(Records).run(*Out);
475 break;
Chris Lattner4a24c642005-09-03 01:14:03 +0000476 case GenDAGISel:
477 DAGISelEmitter(Records).run(*Out);
478 break;
Jim Laskeyf5fc2cb2005-10-21 19:05:19 +0000479 case GenSubtarget:
480 SubtargetEmitter(Records).run(*Out);
481 break;
Chris Lattner1d1adea2003-08-01 04:39:05 +0000482 case PrintEnums:
Brian Gaeked0fde302003-11-11 22:41:34 +0000483 {
Chris Lattner1d1adea2003-08-01 04:39:05 +0000484 std::vector<Record*> Recs = Records.getAllDerivedDefinitions(Class);
Chris Lattner1d1adea2003-08-01 04:39:05 +0000485 for (unsigned i = 0, e = Recs.size(); i != e; ++i)
Chris Lattner7b9ee512004-02-06 03:19:17 +0000486 *Out << Recs[i]->getName() << ", ";
Chris Lattner1d1adea2003-08-01 04:39:05 +0000487 *Out << "\n";
488 break;
Chris Lattnere62c1182002-12-02 01:23:04 +0000489 }
Brian Gaeked0fde302003-11-11 22:41:34 +0000490 default:
491 assert(1 && "Invalid Action");
492 return 1;
493 }
Chris Lattner1d1adea2003-08-01 04:39:05 +0000494 } catch (const std::string &Error) {
Reid Spencer23f7d512004-09-03 23:17:54 +0000495 std::cerr << argv[0] << ": " << Error << "\n";
Chris Lattnerf1e366a2003-08-01 19:21:43 +0000496 if (Out != &std::cout) {
497 delete Out; // Close the file
498 std::remove(OutputFilename.c_str()); // Remove the file, it's broken
499 }
Chris Lattner1d1adea2003-08-01 04:39:05 +0000500 return 1;
Reid Spencer23f7d512004-09-03 23:17:54 +0000501 } catch (...) {
502 std::cerr << argv[0] << ": Unknown unexpected exception occurred.\n";
503 if (Out != &std::cout) {
504 delete Out; // Close the file
505 std::remove(OutputFilename.c_str()); // Remove the file, it's broken
506 }
507 return 2;
Chris Lattnere62c1182002-12-02 01:23:04 +0000508 }
Chris Lattner9a886382003-06-03 05:04:42 +0000509
Chris Lattnere79c72d2003-08-01 20:35:01 +0000510 if (Out != &std::cout) {
511 delete Out; // Close the file
Chris Lattnere79c72d2003-08-01 20:35:01 +0000512 }
Chris Lattner1d1adea2003-08-01 04:39:05 +0000513 return 0;
Chris Lattnere62c1182002-12-02 01:23:04 +0000514}