blob: 366af85bc6e8c4e9c439ff2b71fdc497ff9b5f9f [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>
Duraid Madina6fb9a842005-12-26 05:08:55 +000031#include <ios>
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 Lattner2dc74dd2005-10-23 05:47:52 +000038 GenInstrEnums, GenInstrs, GenAsmWriter,
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 Lattner4a24c642005-09-03 01:14:03 +000064 clEnumValN(GenDAGISel, "gen-dag-isel",
65 "Generate a DAG instruction selector"),
Jim Laskeyf5fc2cb2005-10-21 19:05:19 +000066 clEnumValN(GenSubtarget, "gen-subtarget",
67 "Generate subtarget enumerations"),
Chris Lattnerbc520132003-06-03 04:56:29 +000068 clEnumValN(PrintEnums, "print-enums",
69 "Print enum values for a class"),
70 clEnumValN(Parse, "parse",
71 "Interpret machine code (testing only)"),
Chris Lattnerbd935332004-07-16 00:02:21 +000072 clEnumValEnd));
Chris Lattnerbc520132003-06-03 04:56:29 +000073
74 cl::opt<std::string>
Chris Lattner85df2252003-06-03 05:07:28 +000075 Class("class", cl::desc("Print Enum list for this class"),
76 cl::value_desc("class name"));
Chris Lattner9a886382003-06-03 05:04:42 +000077
Chris Lattner90523902003-07-30 19:48:02 +000078 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("-"));
John Criswell96b4bed2003-08-27 13:41:57 +000084
Chris Lattnerd9f5d902006-03-03 01:47:14 +000085 cl::list<std::string>
86 IncludeDirs("I", cl::desc("Directory of include files"),
Chris Lattnered542412006-03-03 01:53:40 +000087 cl::value_desc("directory"), cl::Prefix);
Chris Lattnerbc520132003-06-03 04:56:29 +000088}
89
Chris Lattner2082ebe2004-08-01 03:55:39 +000090namespace llvm {
91 void ParseFile(const std::string &Filename,
Chris Lattnerd9f5d902006-03-03 01:47:14 +000092 const std::vector<std::string> &IncludeDirs);
Chris Lattner2082ebe2004-08-01 03:55:39 +000093}
Chris Lattnere62c1182002-12-02 01:23:04 +000094
Chris Lattner2082ebe2004-08-01 03:55:39 +000095RecordKeeper llvm::Records;
Chris Lattnere62c1182002-12-02 01:23:04 +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 Cohenea3e5e52005-04-22 04:13:13 +0000102 "Can only handle fields of bits<> type!");
Chris Lattnere62c1182002-12-02 01:23:04 +0000103 BitsInit *I = (BitsInit*)V[i].getValue();
104 if (BitNo < I->getNumBits())
Jeff Cohenea3e5e52005-04-22 04:13:13 +0000105 return I->getBit(BitNo);
Chris Lattnere62c1182002-12-02 01:23:04 +0000106 BitNo -= I->getNumBits();
107 }
108
109 std::cerr << "Cannot find requested bit!\n";
Chris Lattnerf5761a52004-02-13 16:37:43 +0000110 exit(1);
Chris Lattnere62c1182002-12-02 01:23:04 +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 Cohenea3e5e52005-04-22 04:13:13 +0000120 "Can only handle fields of bits<> type!");
Chris Lattnere62c1182002-12-02 01:23:04 +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 Cohenea3e5e52005-04-22 04:13:13 +0000139 unsigned Start, unsigned End) {
Chris Lattnere62c1182002-12-02 01:23:04 +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 Cohenea3e5e52005-04-22 04:13:13 +0000154 unsigned FirstFixedBit, unsigned MaxBits,
155 unsigned &FirstVaryingBitOverall,
156 unsigned &LastFixedBitOverall) {
Chris Lattnere62c1182002-12-02 01:23:04 +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 Brukman3da94ae2005-04-22 00:00:37 +0000167
Chris Lattnere62c1182002-12-02 01:23:04 +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 Cohenea3e5e52005-04-22 04:13:13 +0000188 return true;
Chris Lattnere62c1182002-12-02 01:23:04 +0000189 else if (V2 < V1)
Jeff Cohenea3e5e52005-04-22 04:13:13 +0000190 return false;
Chris Lattnere62c1182002-12-02 01:23:04 +0000191 }
192 return false;
193 }
194};
195
Misha Brukman3da94ae2005-04-22 00:00:37 +0000196static void PrintRange(std::vector<Record*>::iterator I,
Jeff Cohenea3e5e52005-04-22 04:13:13 +0000197 std::vector<Record*>::iterator E) {
Chris Lattnere62c1182002-12-02 01:23:04 +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 Cohenea3e5e52005-04-22 04:13:13 +0000206 std::vector<Record*>::iterator IE,
207 unsigned StartBit) {
Chris Lattnere62c1182002-12-02 01:23:04 +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
Misha Brukman737af822003-09-07 20:12:52 +0000215// 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.
Chris Lattnere62c1182002-12-02 01:23:04 +0000218//
Misha Brukman3da94ae2005-04-22 00:00:37 +0000219static Record *ParseMachineCode(std::vector<Record*>::iterator InstsB,
Jeff Cohenea3e5e52005-04-22 04:13:13 +0000220 std::vector<Record*>::iterator InstsE,
221 unsigned char *M) {
Chris Lattnere62c1182002-12-02 01:23:04 +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 Cohenea3e5e52005-04-22 04:13:13 +0000228 if (getMemoryBit(M, i) != BI->getValue())
229 throw std::string("Parse failed!\n");
Chris Lattnere62c1182002-12-02 01:23:04 +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 Cohenea3e5e52005-04-22 04:13:13 +0000244 FirstVaryingBit, LastFixedBit);
Chris Lattnere62c1182002-12-02 01:23:04 +0000245 if (FirstVaryingBit == MaxBits) {
246 std::cerr << "ERROR: Could not find bit to distinguish between "
Jeff Cohenea3e5e52005-04-22 04:13:13 +0000247 << "the following entries!\n";
Chris Lattnere62c1182002-12-02 01:23:04 +0000248 PrintRange(InstsB, InstsE);
249 }
250
251#if 0
252 std::cerr << "FVB: " << FirstVaryingBit << " - " << LastFixedBit
Jeff Cohenea3e5e52005-04-22 04:13:13 +0000253 << ": " << InstsE-InstsB << "\n";
Chris Lattnere62c1182002-12-02 01:23:04 +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 Brukman3da94ae2005-04-22 00:00:37 +0000278
Chris Lattnere62c1182002-12-02 01:23:04 +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 Lattnerf5761a52004-02-13 16:37:43 +0000286 exit(1);
Chris Lattnere62c1182002-12-02 01:23:04 +0000287 }
Misha Brukman3da94ae2005-04-22 00:00:37 +0000288
Chris Lattner7b1d49b2002-12-03 20:01:04 +0000289#if 0
290 std::cerr << "FVB: " << FirstVaryingBit << " - " << LastFixedBit
Jeff Cohenea3e5e52005-04-22 04:13:13 +0000291 << ": [" << RangeEnd-RangeBegin << "] - ";
Chris Lattner7b1d49b2002-12-03 20:01:04 +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
Chris Lattnere62c1182002-12-02 01:23:04 +0000297 if (Record *R = ParseMachineCode(RangeBegin, RangeEnd, M)) {
298 if (Match) {
Jeff Cohenea3e5e52005-04-22 04:13:13 +0000299 std::cerr << "Error: Multiple matches found:\n";
300 PrintRange(InstsB, InstsE);
Chris Lattnere62c1182002-12-02 01:23:04 +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 Cohenea3e5e52005-04-22 04:13:13 +0000314 "Can only handle undefined bits<> types!");
Chris Lattnere62c1182002-12-02 01:23:04 +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 Brukman3da94ae2005-04-22 00:00:37 +0000325
Chris Lattnere62c1182002-12-02 01:23:04 +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()) {
Chris Lattner98334932002-12-02 17:43:43 +0000332 BitsInit *FieldInitializer = (BitsInit*)Vals[f].getValue();
Chris Lattnere62c1182002-12-02 01:23:04 +0000333 if (&Vals[f] == &Val) {
Jeff Cohenea3e5e52005-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 Lattnere62c1182002-12-02 01:23:04 +0000338 }
Misha Brukman3da94ae2005-04-22 00:00:37 +0000339
Chris Lattnere62c1182002-12-02 01:23:04 +0000340 // Scan through the field looking for bit initializers of the current
341 // variable...
Chris Lattner98334932002-12-02 17:43:43 +0000342 for (unsigned i = 0, e = FieldInitializer->getNumBits(); i != e; ++i)
Jeff Cohenea3e5e52005-04-22 04:13:13 +0000343 if (VarBitInit *VBI =
344 dynamic_cast<VarBitInit*>(FieldInitializer->getBit(i))) {
Chris Lattner98334932002-12-02 17:43:43 +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 Cohenea3e5e52005-04-22 04:13:13 +0000353 }
Chris Lattner98334932002-12-02 17:43:43 +0000354 Offset += FieldInitializer->getNumBits();
Chris Lattnere62c1182002-12-02 01:23:04 +0000355 }
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 Cohenea3e5e52005-04-22 04:13:13 +0000362 << "\t" << I->getName() << "\t" << *I->getValue("Name")->getValue()
363 << "\t";
Misha Brukman3da94ae2005-04-22 00:00:37 +0000364
Chris Lattnere62c1182002-12-02 01:23:04 +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 Brukman3da94ae2005-04-22 00:00:37 +0000372
Chris Lattnere62c1182002-12-02 01:23:04 +0000373 std::cout << "\n";// << *I;
374}
375
376static void ParseMachineCode() {
Misha Brukmanf00ce8b2003-05-24 00:17:12 +0000377 // X86 code
Chris Lattner7b1d49b2002-12-03 20:01:04 +0000378 unsigned char Buffer[] = {
379 0x55, // push EBP
Jeff Cohenea3e5e52005-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 Lattnere62c1182002-12-02 01:23:04 +0000395 };
Misha Brukmanf00ce8b2003-05-24 00:17:12 +0000396
397#if 0
398 // SparcV9 code
Misha Brukman3da94ae2005-04-22 00:00:37 +0000399 unsigned char Buffer[] = { 0xbf, 0xe0, 0x20, 0x1f, 0x1, 0x0, 0x0, 0x1,
Misha Brukmanf00ce8b2003-05-24 00:17:12 +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
Chris Lattner1d1adea2003-08-01 04:39:05 +0000408 std::vector<Record*> Insts = Records.getAllDerivedDefinitions("Instruction");
Chris Lattnere62c1182002-12-02 01:23:04 +0000409
410 unsigned char *BuffPtr = Buffer;
411 while (1) {
412 Record *R = ParseMachineCode(Insts.begin(), Insts.end(), BuffPtr);
Chris Lattnere62c1182002-12-02 01:23:04 +0000413 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 Lattnere62c1182002-12-02 01:23:04 +0000421int main(int argc, char **argv) {
422 cl::ParseCommandLineOptions(argc, argv);
Chris Lattnerd9f5d902006-03-03 01:47:14 +0000423 ParseFile(InputFilename, IncludeDirs);
Chris Lattnere62c1182002-12-02 01:23:04 +0000424
Chris Lattner9a886382003-06-03 05:04:42 +0000425 std::ostream *Out = &std::cout;
426 if (OutputFilename != "-") {
Chris Lattner42df6d12004-07-13 06:11:46 +0000427 Out = new std::ofstream(OutputFilename.c_str());
Chris Lattner9a886382003-06-03 05:04:42 +0000428
429 if (!Out->good()) {
Chris Lattner42df6d12004-07-13 06:11:46 +0000430 std::cerr << argv[0] << ": error opening " << OutputFilename << "!\n";
Chris Lattner9a886382003-06-03 05:04:42 +0000431 return 1;
432 }
433
434 // Make sure the file gets removed if *gasp* tablegen crashes...
Reid Spencer227b6d02004-11-14 22:30:54 +0000435 sys::RemoveFileOnSignal(sys::Path(OutputFilename));
Chris Lattner9a886382003-06-03 05:04:42 +0000436 }
437
Chris Lattner1d1adea2003-08-01 04:39:05 +0000438 try {
439 switch (Action) {
Chris Lattneraccd8ab2003-08-01 04:47:20 +0000440 case PrintRecords:
441 *Out << Records; // No argument, dump all contents
442 break;
Chris Lattner1d1adea2003-08-01 04:39:05 +0000443 case Parse:
444 ParseMachineCode();
445 break;
446 case GenEmitter:
447 CodeEmitterGen(Records).run(*Out);
448 break;
Chris Lattner169e66b2003-08-03 17:24:20 +0000449
Chris Lattner54d156d2003-08-01 05:59:20 +0000450 case GenRegisterEnums:
451 RegisterInfoEmitter(Records).runEnums(*Out);
452 break;
Chris Lattner1d1adea2003-08-01 04:39:05 +0000453 case GenRegister:
454 RegisterInfoEmitter(Records).run(*Out);
455 break;
456 case GenRegisterHeader:
457 RegisterInfoEmitter(Records).runHeader(*Out);
458 break;
Chris Lattner169e66b2003-08-03 17:24:20 +0000459
460 case GenInstrEnums:
461 InstrInfoEmitter(Records).runEnums(*Out);
462 break;
Chris Lattner15de32d2003-08-03 21:58:28 +0000463 case GenInstrs:
464 InstrInfoEmitter(Records).run(*Out);
465 break;
Chris Lattner2e1f51b2004-08-01 05:59:33 +0000466
467 case GenAsmWriter:
468 AsmWriterEmitter(Records).run(*Out);
469 break;
470
Chris Lattner4a24c642005-09-03 01:14:03 +0000471 case GenDAGISel:
472 DAGISelEmitter(Records).run(*Out);
473 break;
Jim Laskeyf5fc2cb2005-10-21 19:05:19 +0000474 case GenSubtarget:
475 SubtargetEmitter(Records).run(*Out);
476 break;
Chris Lattner1d1adea2003-08-01 04:39:05 +0000477 case PrintEnums:
Brian Gaeked0fde302003-11-11 22:41:34 +0000478 {
Chris Lattner1d1adea2003-08-01 04:39:05 +0000479 std::vector<Record*> Recs = Records.getAllDerivedDefinitions(Class);
Chris Lattner1d1adea2003-08-01 04:39:05 +0000480 for (unsigned i = 0, e = Recs.size(); i != e; ++i)
Chris Lattner7b9ee512004-02-06 03:19:17 +0000481 *Out << Recs[i]->getName() << ", ";
Chris Lattner1d1adea2003-08-01 04:39:05 +0000482 *Out << "\n";
483 break;
Chris Lattnere62c1182002-12-02 01:23:04 +0000484 }
Brian Gaeked0fde302003-11-11 22:41:34 +0000485 default:
486 assert(1 && "Invalid Action");
487 return 1;
488 }
Chris Lattner1d1adea2003-08-01 04:39:05 +0000489 } catch (const std::string &Error) {
Reid Spencer23f7d512004-09-03 23:17:54 +0000490 std::cerr << argv[0] << ": " << Error << "\n";
Chris Lattnerf1e366a2003-08-01 19:21:43 +0000491 if (Out != &std::cout) {
492 delete Out; // Close the file
493 std::remove(OutputFilename.c_str()); // Remove the file, it's broken
494 }
Chris Lattner1d1adea2003-08-01 04:39:05 +0000495 return 1;
Reid Spencer23f7d512004-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 Lattnere62c1182002-12-02 01:23:04 +0000503 }
Chris Lattner9a886382003-06-03 05:04:42 +0000504
Chris Lattnere79c72d2003-08-01 20:35:01 +0000505 if (Out != &std::cout) {
506 delete Out; // Close the file
Chris Lattnere79c72d2003-08-01 20:35:01 +0000507 }
Chris Lattner1d1adea2003-08-01 04:39:05 +0000508 return 0;
Chris Lattnere62c1182002-12-02 01:23:04 +0000509}