blob: 4c8b3a0fcd33336b1a804c4075879037f2efc6bc [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 Lattner9e493cf2006-03-03 02:32:46 +000028#include "IntrinsicEmitter.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>
Duraid Madina6fb9a842005-12-26 05:08:55 +000032#include <ios>
Chris Lattner2082ebe2004-08-01 03:55:39 +000033using namespace llvm;
Brian Gaeked0fde302003-11-11 22:41:34 +000034
Chris Lattnerbc520132003-06-03 04:56:29 +000035enum ActionType {
36 PrintRecords,
37 GenEmitter,
Chris Lattner54d156d2003-08-01 05:59:20 +000038 GenRegisterEnums, GenRegister, GenRegisterHeader,
Chris Lattner2dc74dd2005-10-23 05:47:52 +000039 GenInstrEnums, GenInstrs, GenAsmWriter,
Chris Lattner4a24c642005-09-03 01:14:03 +000040 GenDAGISel,
Jim Laskeyf5fc2cb2005-10-21 19:05:19 +000041 GenSubtarget,
Chris Lattner9e493cf2006-03-03 02:32:46 +000042 GenIntrinsic,
Chris Lattnerbc520132003-06-03 04:56:29 +000043 PrintEnums,
Chris Lattner9879aa92004-07-22 21:32:38 +000044 Parse
Chris Lattnerbc520132003-06-03 04:56:29 +000045};
46
47namespace {
48 cl::opt<ActionType>
49 Action(cl::desc("Action to perform:"),
50 cl::values(clEnumValN(PrintRecords, "print-records",
Chris Lattner85df2252003-06-03 05:07:28 +000051 "Print all records to stdout (default)"),
Chris Lattnerbc520132003-06-03 04:56:29 +000052 clEnumValN(GenEmitter, "gen-emitter",
53 "Generate machine code emitter"),
Chris Lattner54d156d2003-08-01 05:59:20 +000054 clEnumValN(GenRegisterEnums, "gen-register-enums",
55 "Generate enum values for registers"),
Chris Lattner1d1adea2003-08-01 04:39:05 +000056 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"),
Chris Lattner169e66b2003-08-03 17:24:20 +000060 clEnumValN(GenInstrEnums, "gen-instr-enums",
61 "Generate enum values for instructions"),
Chris Lattner15de32d2003-08-03 21:58:28 +000062 clEnumValN(GenInstrs, "gen-instr-desc",
63 "Generate instruction descriptions"),
Chris Lattner2e1f51b2004-08-01 05:59:33 +000064 clEnumValN(GenAsmWriter, "gen-asm-writer",
65 "Generate assembly writer"),
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 Lattner9e493cf2006-03-03 02:32:46 +000070 clEnumValN(GenIntrinsic, "gen-intrinsic",
71 "Generate intrinsic information"),
Chris Lattnerbc520132003-06-03 04:56:29 +000072 clEnumValN(PrintEnums, "print-enums",
73 "Print enum values for a class"),
74 clEnumValN(Parse, "parse",
75 "Interpret machine code (testing only)"),
Chris Lattnerbd935332004-07-16 00:02:21 +000076 clEnumValEnd));
Chris Lattnerbc520132003-06-03 04:56:29 +000077
78 cl::opt<std::string>
Chris Lattner85df2252003-06-03 05:07:28 +000079 Class("class", cl::desc("Print Enum list for this class"),
80 cl::value_desc("class name"));
Chris Lattner9a886382003-06-03 05:04:42 +000081
Chris Lattner90523902003-07-30 19:48:02 +000082 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("-"));
John Criswell96b4bed2003-08-27 13:41:57 +000088
Chris Lattnerd9f5d902006-03-03 01:47:14 +000089 cl::list<std::string>
90 IncludeDirs("I", cl::desc("Directory of include files"),
Chris Lattnered542412006-03-03 01:53:40 +000091 cl::value_desc("directory"), cl::Prefix);
Chris Lattnerbc520132003-06-03 04:56:29 +000092}
93
Chris Lattner2082ebe2004-08-01 03:55:39 +000094namespace llvm {
95 void ParseFile(const std::string &Filename,
Chris Lattnerd9f5d902006-03-03 01:47:14 +000096 const std::vector<std::string> &IncludeDirs);
Chris Lattner2082ebe2004-08-01 03:55:39 +000097}
Chris Lattnere62c1182002-12-02 01:23:04 +000098
Chris Lattner2082ebe2004-08-01 03:55:39 +000099RecordKeeper llvm::Records;
Chris Lattnere62c1182002-12-02 01:23:04 +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 Cohenea3e5e52005-04-22 04:13:13 +0000106 "Can only handle fields of bits<> type!");
Chris Lattnere62c1182002-12-02 01:23:04 +0000107 BitsInit *I = (BitsInit*)V[i].getValue();
108 if (BitNo < I->getNumBits())
Jeff Cohenea3e5e52005-04-22 04:13:13 +0000109 return I->getBit(BitNo);
Chris Lattnere62c1182002-12-02 01:23:04 +0000110 BitNo -= I->getNumBits();
111 }
112
113 std::cerr << "Cannot find requested bit!\n";
Chris Lattnerf5761a52004-02-13 16:37:43 +0000114 exit(1);
Chris Lattnere62c1182002-12-02 01:23:04 +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 Cohenea3e5e52005-04-22 04:13:13 +0000124 "Can only handle fields of bits<> type!");
Chris Lattnere62c1182002-12-02 01:23:04 +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 Cohenea3e5e52005-04-22 04:13:13 +0000143 unsigned Start, unsigned End) {
Chris Lattnere62c1182002-12-02 01:23:04 +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 Cohenea3e5e52005-04-22 04:13:13 +0000158 unsigned FirstFixedBit, unsigned MaxBits,
159 unsigned &FirstVaryingBitOverall,
160 unsigned &LastFixedBitOverall) {
Chris Lattnere62c1182002-12-02 01:23:04 +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 Brukman3da94ae2005-04-22 00:00:37 +0000171
Chris Lattnere62c1182002-12-02 01:23:04 +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 Cohenea3e5e52005-04-22 04:13:13 +0000192 return true;
Chris Lattnere62c1182002-12-02 01:23:04 +0000193 else if (V2 < V1)
Jeff Cohenea3e5e52005-04-22 04:13:13 +0000194 return false;
Chris Lattnere62c1182002-12-02 01:23:04 +0000195 }
196 return false;
197 }
198};
199
Misha Brukman3da94ae2005-04-22 00:00:37 +0000200static void PrintRange(std::vector<Record*>::iterator I,
Jeff Cohenea3e5e52005-04-22 04:13:13 +0000201 std::vector<Record*>::iterator E) {
Chris Lattnere62c1182002-12-02 01:23:04 +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 Cohenea3e5e52005-04-22 04:13:13 +0000210 std::vector<Record*>::iterator IE,
211 unsigned StartBit) {
Chris Lattnere62c1182002-12-02 01:23:04 +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
Misha Brukman737af822003-09-07 20:12:52 +0000219// 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.
Chris Lattnere62c1182002-12-02 01:23:04 +0000222//
Misha Brukman3da94ae2005-04-22 00:00:37 +0000223static Record *ParseMachineCode(std::vector<Record*>::iterator InstsB,
Jeff Cohenea3e5e52005-04-22 04:13:13 +0000224 std::vector<Record*>::iterator InstsE,
225 unsigned char *M) {
Chris Lattnere62c1182002-12-02 01:23:04 +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 Cohenea3e5e52005-04-22 04:13:13 +0000232 if (getMemoryBit(M, i) != BI->getValue())
233 throw std::string("Parse failed!\n");
Chris Lattnere62c1182002-12-02 01:23:04 +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 Cohenea3e5e52005-04-22 04:13:13 +0000248 FirstVaryingBit, LastFixedBit);
Chris Lattnere62c1182002-12-02 01:23:04 +0000249 if (FirstVaryingBit == MaxBits) {
250 std::cerr << "ERROR: Could not find bit to distinguish between "
Jeff Cohenea3e5e52005-04-22 04:13:13 +0000251 << "the following entries!\n";
Chris Lattnere62c1182002-12-02 01:23:04 +0000252 PrintRange(InstsB, InstsE);
253 }
254
255#if 0
256 std::cerr << "FVB: " << FirstVaryingBit << " - " << LastFixedBit
Jeff Cohenea3e5e52005-04-22 04:13:13 +0000257 << ": " << InstsE-InstsB << "\n";
Chris Lattnere62c1182002-12-02 01:23:04 +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 Brukman3da94ae2005-04-22 00:00:37 +0000282
Chris Lattnere62c1182002-12-02 01:23:04 +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 Lattnerf5761a52004-02-13 16:37:43 +0000290 exit(1);
Chris Lattnere62c1182002-12-02 01:23:04 +0000291 }
Misha Brukman3da94ae2005-04-22 00:00:37 +0000292
Chris Lattner7b1d49b2002-12-03 20:01:04 +0000293#if 0
294 std::cerr << "FVB: " << FirstVaryingBit << " - " << LastFixedBit
Jeff Cohenea3e5e52005-04-22 04:13:13 +0000295 << ": [" << RangeEnd-RangeBegin << "] - ";
Chris Lattner7b1d49b2002-12-03 20:01:04 +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
Chris Lattnere62c1182002-12-02 01:23:04 +0000301 if (Record *R = ParseMachineCode(RangeBegin, RangeEnd, M)) {
302 if (Match) {
Jeff Cohenea3e5e52005-04-22 04:13:13 +0000303 std::cerr << "Error: Multiple matches found:\n";
304 PrintRange(InstsB, InstsE);
Chris Lattnere62c1182002-12-02 01:23:04 +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 Cohenea3e5e52005-04-22 04:13:13 +0000318 "Can only handle undefined bits<> types!");
Chris Lattnere62c1182002-12-02 01:23:04 +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 Brukman3da94ae2005-04-22 00:00:37 +0000329
Chris Lattnere62c1182002-12-02 01:23:04 +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()) {
Chris Lattner98334932002-12-02 17:43:43 +0000336 BitsInit *FieldInitializer = (BitsInit*)Vals[f].getValue();
Chris Lattnere62c1182002-12-02 01:23:04 +0000337 if (&Vals[f] == &Val) {
Jeff Cohenea3e5e52005-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 Lattnere62c1182002-12-02 01:23:04 +0000342 }
Misha Brukman3da94ae2005-04-22 00:00:37 +0000343
Chris Lattnere62c1182002-12-02 01:23:04 +0000344 // Scan through the field looking for bit initializers of the current
345 // variable...
Chris Lattner98334932002-12-02 17:43:43 +0000346 for (unsigned i = 0, e = FieldInitializer->getNumBits(); i != e; ++i)
Jeff Cohenea3e5e52005-04-22 04:13:13 +0000347 if (VarBitInit *VBI =
348 dynamic_cast<VarBitInit*>(FieldInitializer->getBit(i))) {
Chris Lattner98334932002-12-02 17:43:43 +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 Cohenea3e5e52005-04-22 04:13:13 +0000357 }
Chris Lattner98334932002-12-02 17:43:43 +0000358 Offset += FieldInitializer->getNumBits();
Chris Lattnere62c1182002-12-02 01:23:04 +0000359 }
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 Cohenea3e5e52005-04-22 04:13:13 +0000366 << "\t" << I->getName() << "\t" << *I->getValue("Name")->getValue()
367 << "\t";
Misha Brukman3da94ae2005-04-22 00:00:37 +0000368
Chris Lattnere62c1182002-12-02 01:23:04 +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 Brukman3da94ae2005-04-22 00:00:37 +0000376
Chris Lattnere62c1182002-12-02 01:23:04 +0000377 std::cout << "\n";// << *I;
378}
379
380static void ParseMachineCode() {
Misha Brukmanf00ce8b2003-05-24 00:17:12 +0000381 // X86 code
Chris Lattner7b1d49b2002-12-03 20:01:04 +0000382 unsigned char Buffer[] = {
383 0x55, // push EBP
Jeff Cohenea3e5e52005-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 Lattnere62c1182002-12-02 01:23:04 +0000399 };
Misha Brukmanf00ce8b2003-05-24 00:17:12 +0000400
401#if 0
402 // SparcV9 code
Misha Brukman3da94ae2005-04-22 00:00:37 +0000403 unsigned char Buffer[] = { 0xbf, 0xe0, 0x20, 0x1f, 0x1, 0x0, 0x0, 0x1,
Misha Brukmanf00ce8b2003-05-24 00:17:12 +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
Chris Lattner1d1adea2003-08-01 04:39:05 +0000412 std::vector<Record*> Insts = Records.getAllDerivedDefinitions("Instruction");
Chris Lattnere62c1182002-12-02 01:23:04 +0000413
414 unsigned char *BuffPtr = Buffer;
415 while (1) {
416 Record *R = ParseMachineCode(Insts.begin(), Insts.end(), BuffPtr);
Chris Lattnere62c1182002-12-02 01:23:04 +0000417 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 Lattnere62c1182002-12-02 01:23:04 +0000425int main(int argc, char **argv) {
426 cl::ParseCommandLineOptions(argc, argv);
Chris Lattnerd9f5d902006-03-03 01:47:14 +0000427 ParseFile(InputFilename, IncludeDirs);
Chris Lattnere62c1182002-12-02 01:23:04 +0000428
Chris Lattner9a886382003-06-03 05:04:42 +0000429 std::ostream *Out = &std::cout;
430 if (OutputFilename != "-") {
Chris Lattner42df6d12004-07-13 06:11:46 +0000431 Out = new std::ofstream(OutputFilename.c_str());
Chris Lattner9a886382003-06-03 05:04:42 +0000432
433 if (!Out->good()) {
Chris Lattner42df6d12004-07-13 06:11:46 +0000434 std::cerr << argv[0] << ": error opening " << OutputFilename << "!\n";
Chris Lattner9a886382003-06-03 05:04:42 +0000435 return 1;
436 }
437
438 // Make sure the file gets removed if *gasp* tablegen crashes...
Reid Spencer227b6d02004-11-14 22:30:54 +0000439 sys::RemoveFileOnSignal(sys::Path(OutputFilename));
Chris Lattner9a886382003-06-03 05:04:42 +0000440 }
441
Chris Lattner1d1adea2003-08-01 04:39:05 +0000442 try {
443 switch (Action) {
Chris Lattneraccd8ab2003-08-01 04:47:20 +0000444 case PrintRecords:
445 *Out << Records; // No argument, dump all contents
446 break;
Chris Lattner1d1adea2003-08-01 04:39:05 +0000447 case Parse:
448 ParseMachineCode();
449 break;
450 case GenEmitter:
451 CodeEmitterGen(Records).run(*Out);
452 break;
Chris Lattner169e66b2003-08-03 17:24:20 +0000453
Chris Lattner54d156d2003-08-01 05:59:20 +0000454 case GenRegisterEnums:
455 RegisterInfoEmitter(Records).runEnums(*Out);
456 break;
Chris Lattner1d1adea2003-08-01 04:39:05 +0000457 case GenRegister:
458 RegisterInfoEmitter(Records).run(*Out);
459 break;
460 case GenRegisterHeader:
461 RegisterInfoEmitter(Records).runHeader(*Out);
462 break;
Chris Lattner169e66b2003-08-03 17:24:20 +0000463
464 case GenInstrEnums:
465 InstrInfoEmitter(Records).runEnums(*Out);
466 break;
Chris Lattner15de32d2003-08-03 21:58:28 +0000467 case GenInstrs:
468 InstrInfoEmitter(Records).run(*Out);
469 break;
Chris Lattner2e1f51b2004-08-01 05:59:33 +0000470
471 case GenAsmWriter:
472 AsmWriterEmitter(Records).run(*Out);
473 break;
474
Chris Lattner4a24c642005-09-03 01:14:03 +0000475 case GenDAGISel:
476 DAGISelEmitter(Records).run(*Out);
477 break;
Jim Laskeyf5fc2cb2005-10-21 19:05:19 +0000478 case GenSubtarget:
479 SubtargetEmitter(Records).run(*Out);
480 break;
Chris Lattner9e493cf2006-03-03 02:32:46 +0000481 case GenIntrinsic:
482 IntrinsicEmitter(Records).run(*Out);
483 break;
Chris Lattner1d1adea2003-08-01 04:39:05 +0000484 case PrintEnums:
Brian Gaeked0fde302003-11-11 22:41:34 +0000485 {
Chris Lattner1d1adea2003-08-01 04:39:05 +0000486 std::vector<Record*> Recs = Records.getAllDerivedDefinitions(Class);
Chris Lattner1d1adea2003-08-01 04:39:05 +0000487 for (unsigned i = 0, e = Recs.size(); i != e; ++i)
Chris Lattner7b9ee512004-02-06 03:19:17 +0000488 *Out << Recs[i]->getName() << ", ";
Chris Lattner1d1adea2003-08-01 04:39:05 +0000489 *Out << "\n";
490 break;
Chris Lattnere62c1182002-12-02 01:23:04 +0000491 }
Brian Gaeked0fde302003-11-11 22:41:34 +0000492 default:
493 assert(1 && "Invalid Action");
494 return 1;
495 }
Chris Lattner1d1adea2003-08-01 04:39:05 +0000496 } catch (const std::string &Error) {
Reid Spencer23f7d512004-09-03 23:17:54 +0000497 std::cerr << argv[0] << ": " << Error << "\n";
Chris Lattnerf1e366a2003-08-01 19:21:43 +0000498 if (Out != &std::cout) {
499 delete Out; // Close the file
500 std::remove(OutputFilename.c_str()); // Remove the file, it's broken
501 }
Chris Lattner1d1adea2003-08-01 04:39:05 +0000502 return 1;
Reid Spencer23f7d512004-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 Lattnere62c1182002-12-02 01:23:04 +0000510 }
Chris Lattner9a886382003-06-03 05:04:42 +0000511
Chris Lattnere79c72d2003-08-01 20:35:01 +0000512 if (Out != &std::cout) {
513 delete Out; // Close the file
Chris Lattnere79c72d2003-08-01 20:35:01 +0000514 }
Chris Lattner1d1adea2003-08-01 04:39:05 +0000515 return 0;
Chris Lattnere62c1182002-12-02 01:23:04 +0000516}