blob: 7bd52b37cf06eaf602f9266d0d10d18ab87d39fb [file] [log] [blame]
Chris Lattner1d1adea2003-08-01 04:39:05 +00001//===- TableGen.cpp - Top-Level TableGen implementation -------------------===//
John Criswell01d45822003-10-20 20:20:30 +00002//
3// 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.
7//
8//===----------------------------------------------------------------------===//
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"
19#include "Support/CommandLine.h"
Chris Lattnerbed85ff2004-05-27 05:41:36 +000020#include "llvm/System/Signals.h"
Chris Lattnere79c72d2003-08-01 20:35:01 +000021#include "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 Lattner3f781342003-08-06 04:47:56 +000025#include "InstrSelectorEmitter.h"
Chris Lattnere62c1182002-12-02 01:23:04 +000026#include <algorithm>
Misha Brukmanc3fe45b2003-08-14 16:05:35 +000027#include <cstdio>
Chris Lattner9a886382003-06-03 05:04:42 +000028#include <fstream>
Chris Lattner2082ebe2004-08-01 03:55:39 +000029using namespace llvm;
Brian Gaeked0fde302003-11-11 22:41:34 +000030
Chris Lattnerbc520132003-06-03 04:56:29 +000031enum ActionType {
32 PrintRecords,
33 GenEmitter,
Chris Lattner54d156d2003-08-01 05:59:20 +000034 GenRegisterEnums, GenRegister, GenRegisterHeader,
Chris Lattner3f781342003-08-06 04:47:56 +000035 GenInstrEnums, GenInstrs, GenInstrSelector,
Chris Lattnerbc520132003-06-03 04:56:29 +000036 PrintEnums,
Chris Lattner9879aa92004-07-22 21:32:38 +000037 Parse
Chris Lattnerbc520132003-06-03 04:56:29 +000038};
39
40namespace {
41 cl::opt<ActionType>
42 Action(cl::desc("Action to perform:"),
43 cl::values(clEnumValN(PrintRecords, "print-records",
Chris Lattner85df2252003-06-03 05:07:28 +000044 "Print all records to stdout (default)"),
Chris Lattnerbc520132003-06-03 04:56:29 +000045 clEnumValN(GenEmitter, "gen-emitter",
46 "Generate machine code emitter"),
Chris Lattner54d156d2003-08-01 05:59:20 +000047 clEnumValN(GenRegisterEnums, "gen-register-enums",
48 "Generate enum values for registers"),
Chris Lattner1d1adea2003-08-01 04:39:05 +000049 clEnumValN(GenRegister, "gen-register-desc",
50 "Generate a register info description"),
51 clEnumValN(GenRegisterHeader, "gen-register-desc-header",
52 "Generate a register info description header"),
Chris Lattner169e66b2003-08-03 17:24:20 +000053 clEnumValN(GenInstrEnums, "gen-instr-enums",
54 "Generate enum values for instructions"),
Chris Lattner15de32d2003-08-03 21:58:28 +000055 clEnumValN(GenInstrs, "gen-instr-desc",
56 "Generate instruction descriptions"),
Chris Lattner3f781342003-08-06 04:47:56 +000057 clEnumValN(GenInstrSelector, "gen-instr-selector",
58 "Generate an instruction selector"),
Chris Lattnerbc520132003-06-03 04:56:29 +000059 clEnumValN(PrintEnums, "print-enums",
60 "Print enum values for a class"),
61 clEnumValN(Parse, "parse",
62 "Interpret machine code (testing only)"),
Chris Lattnerbd935332004-07-16 00:02:21 +000063 clEnumValEnd));
Chris Lattnerbc520132003-06-03 04:56:29 +000064
65 cl::opt<std::string>
Chris Lattner85df2252003-06-03 05:07:28 +000066 Class("class", cl::desc("Print Enum list for this class"),
67 cl::value_desc("class name"));
Chris Lattner9a886382003-06-03 05:04:42 +000068
Chris Lattner90523902003-07-30 19:48:02 +000069 cl::opt<std::string>
70 OutputFilename("o", cl::desc("Output filename"), cl::value_desc("filename"),
71 cl::init("-"));
72
73 cl::opt<std::string>
74 InputFilename(cl::Positional, cl::desc("<input file>"), cl::init("-"));
John Criswell96b4bed2003-08-27 13:41:57 +000075
76 cl::opt<std::string>
77 IncludeDir("I", cl::desc("Directory of include files"),
78 cl::value_desc("directory"), cl::init(""));
Chris Lattnerbc520132003-06-03 04:56:29 +000079}
80
Chris Lattner2082ebe2004-08-01 03:55:39 +000081namespace llvm {
82 void ParseFile(const std::string &Filename,
83 const std::string &IncludeDir);
84}
Chris Lattnere62c1182002-12-02 01:23:04 +000085
Chris Lattner2082ebe2004-08-01 03:55:39 +000086RecordKeeper llvm::Records;
Chris Lattnere62c1182002-12-02 01:23:04 +000087
88static Init *getBit(Record *R, unsigned BitNo) {
89 const std::vector<RecordVal> &V = R->getValues();
90 for (unsigned i = 0, e = V.size(); i != e; ++i)
91 if (V[i].getPrefix()) {
92 assert(dynamic_cast<BitsInit*>(V[i].getValue()) &&
93 "Can only handle fields of bits<> type!");
94 BitsInit *I = (BitsInit*)V[i].getValue();
95 if (BitNo < I->getNumBits())
96 return I->getBit(BitNo);
97 BitNo -= I->getNumBits();
98 }
99
100 std::cerr << "Cannot find requested bit!\n";
Chris Lattnerf5761a52004-02-13 16:37:43 +0000101 exit(1);
Chris Lattnere62c1182002-12-02 01:23:04 +0000102 return 0;
103}
104
105static unsigned getNumBits(Record *R) {
106 const std::vector<RecordVal> &V = R->getValues();
107 unsigned Num = 0;
108 for (unsigned i = 0, e = V.size(); i != e; ++i)
109 if (V[i].getPrefix()) {
110 assert(dynamic_cast<BitsInit*>(V[i].getValue()) &&
111 "Can only handle fields of bits<> type!");
112 Num += ((BitsInit*)V[i].getValue())->getNumBits();
113 }
114 return Num;
115}
116
117static bool BitsAreFixed(Record *I1, Record *I2, unsigned BitNo) {
118 return dynamic_cast<BitInit*>(getBit(I1, BitNo)) &&
119 dynamic_cast<BitInit*>(getBit(I2, BitNo));
120}
121
122static bool BitsAreEqual(Record *I1, Record *I2, unsigned BitNo) {
123 BitInit *Bit1 = dynamic_cast<BitInit*>(getBit(I1, BitNo));
124 BitInit *Bit2 = dynamic_cast<BitInit*>(getBit(I2, BitNo));
125
126 return Bit1 && Bit2 && Bit1->getValue() == Bit2->getValue();
127}
128
129static bool BitRangesEqual(Record *I1, Record *I2,
130 unsigned Start, unsigned End) {
131 for (unsigned i = Start; i != End; ++i)
132 if (!BitsAreEqual(I1, I2, i))
133 return false;
134 return true;
135}
136
137static unsigned getFirstFixedBit(Record *R, unsigned FirstFixedBit) {
138 // Look for the first bit of the pair that are required to be 0 or 1.
139 while (!dynamic_cast<BitInit*>(getBit(R, FirstFixedBit)))
140 ++FirstFixedBit;
141 return FirstFixedBit;
142}
143
144static void FindInstDifferences(Record *I1, Record *I2,
145 unsigned FirstFixedBit, unsigned MaxBits,
146 unsigned &FirstVaryingBitOverall,
147 unsigned &LastFixedBitOverall) {
148 // Compare the first instruction to the rest of the instructions, looking for
149 // fields that differ.
150 //
151 unsigned FirstVaryingBit = FirstFixedBit;
152 while (FirstVaryingBit < MaxBits && BitsAreEqual(I1, I2, FirstVaryingBit))
153 ++FirstVaryingBit;
154
155 unsigned LastFixedBit = FirstVaryingBit;
156 while (LastFixedBit < MaxBits && BitsAreFixed(I1, I2, LastFixedBit))
157 ++LastFixedBit;
158
159 if (FirstVaryingBit < FirstVaryingBitOverall)
160 FirstVaryingBitOverall = FirstVaryingBit;
161 if (LastFixedBit < LastFixedBitOverall)
162 LastFixedBitOverall = LastFixedBit;
163}
164
165static bool getBitValue(Record *R, unsigned BitNo) {
166 Init *I = getBit(R, BitNo);
167 assert(dynamic_cast<BitInit*>(I) && "Bit should be fixed!");
168 return ((BitInit*)I)->getValue();
169}
170
171struct BitComparator {
172 unsigned BitBegin, BitEnd;
173 BitComparator(unsigned B, unsigned E) : BitBegin(B), BitEnd(E) {}
174
175 bool operator()(Record *R1, Record *R2) { // Return true if R1 is less than R2
176 for (unsigned i = BitBegin; i != BitEnd; ++i) {
177 bool V1 = getBitValue(R1, i), V2 = getBitValue(R2, i);
178 if (V1 < V2)
179 return true;
180 else if (V2 < V1)
181 return false;
182 }
183 return false;
184 }
185};
186
187static void PrintRange(std::vector<Record*>::iterator I,
188 std::vector<Record*>::iterator E) {
189 while (I != E) std::cerr << **I++;
190}
191
192static bool getMemoryBit(unsigned char *M, unsigned i) {
193 return (M[i/8] & (1 << (i&7))) != 0;
194}
195
196static unsigned getFirstFixedBitInSequence(std::vector<Record*>::iterator IB,
197 std::vector<Record*>::iterator IE,
198 unsigned StartBit) {
199 unsigned FirstFixedBit = 0;
200 for (std::vector<Record*>::iterator I = IB; I != IE; ++I)
201 FirstFixedBit = std::max(FirstFixedBit, getFirstFixedBit(*I, StartBit));
202 return FirstFixedBit;
203}
204
205// ParseMachineCode - Try to split the vector of instructions (which is
Misha Brukman737af822003-09-07 20:12:52 +0000206// intentionally taken by-copy) in half, narrowing down the possible
207// instructions that we may have found. Eventually, this list will get pared
208// down to zero or one instruction, in which case we have a match or failure.
Chris Lattnere62c1182002-12-02 01:23:04 +0000209//
210static Record *ParseMachineCode(std::vector<Record*>::iterator InstsB,
211 std::vector<Record*>::iterator InstsE,
212 unsigned char *M) {
213 assert(InstsB != InstsE && "Empty range?");
214 if (InstsB+1 == InstsE) {
215 // Only a single instruction, see if we match it...
216 Record *Inst = *InstsB;
217 for (unsigned i = 0, e = getNumBits(Inst); i != e; ++i)
218 if (BitInit *BI = dynamic_cast<BitInit*>(getBit(Inst, i)))
219 if (getMemoryBit(M, i) != BI->getValue())
Chris Lattner1d1adea2003-08-01 04:39:05 +0000220 throw std::string("Parse failed!\n");
Chris Lattnere62c1182002-12-02 01:23:04 +0000221 return Inst;
222 }
223
224 unsigned MaxBits = ~0;
225 for (std::vector<Record*>::iterator I = InstsB; I != InstsE; ++I)
226 MaxBits = std::min(MaxBits, getNumBits(*I));
227
228 unsigned FirstFixedBit = getFirstFixedBitInSequence(InstsB, InstsE, 0);
229 unsigned FirstVaryingBit, LastFixedBit;
230 do {
231 FirstVaryingBit = ~0;
232 LastFixedBit = ~0;
233 for (std::vector<Record*>::iterator I = InstsB+1; I != InstsE; ++I)
234 FindInstDifferences(*InstsB, *I, FirstFixedBit, MaxBits,
235 FirstVaryingBit, LastFixedBit);
236 if (FirstVaryingBit == MaxBits) {
237 std::cerr << "ERROR: Could not find bit to distinguish between "
238 << "the following entries!\n";
239 PrintRange(InstsB, InstsE);
240 }
241
242#if 0
243 std::cerr << "FVB: " << FirstVaryingBit << " - " << LastFixedBit
244 << ": " << InstsE-InstsB << "\n";
245#endif
246
247 FirstFixedBit = getFirstFixedBitInSequence(InstsB, InstsE, FirstVaryingBit);
248 } while (FirstVaryingBit != FirstFixedBit);
249
250 //std::cerr << "\n\nXXXXXXXXXXXXXXXXX\n\n";
251 //PrintRange(InstsB, InstsE);
252
253 // Sort the Insts list so that the entries have all of the bits in the range
254 // [FirstVaryingBit,LastFixedBit) sorted. These bits are all guaranteed to be
255 // set to either 0 or 1 (BitInit values), which simplifies things.
256 //
257 std::sort(InstsB, InstsE, BitComparator(FirstVaryingBit, LastFixedBit));
258
259 // Once the list is sorted by these bits, split the bit list into smaller
260 // lists, and recurse on each one.
261 //
262 std::vector<Record*>::iterator RangeBegin = InstsB;
263 Record *Match = 0;
264 while (RangeBegin != InstsE) {
265 std::vector<Record*>::iterator RangeEnd = RangeBegin+1;
266 while (RangeEnd != InstsE &&
267 BitRangesEqual(*RangeBegin, *RangeEnd, FirstVaryingBit, LastFixedBit))
268 ++RangeEnd;
269
270 // We just identified a range of equal instructions. If this range is the
271 // input range, we were not able to distinguish between the instructions in
272 // the set. Print an error and exit!
273 //
274 if (RangeBegin == InstsB && RangeEnd == InstsE) {
275 std::cerr << "Error: Could not distinguish among the following insts!:\n";
276 PrintRange(InstsB, InstsE);
Chris Lattnerf5761a52004-02-13 16:37:43 +0000277 exit(1);
Chris Lattnere62c1182002-12-02 01:23:04 +0000278 }
279
Chris Lattner7b1d49b2002-12-03 20:01:04 +0000280#if 0
281 std::cerr << "FVB: " << FirstVaryingBit << " - " << LastFixedBit
282 << ": [" << RangeEnd-RangeBegin << "] - ";
283 for (int i = LastFixedBit-1; i >= (int)FirstVaryingBit; --i)
284 std::cerr << (int)((BitInit*)getBit(*RangeBegin, i))->getValue() << " ";
285 std::cerr << "\n";
286#endif
287
Chris Lattnere62c1182002-12-02 01:23:04 +0000288 if (Record *R = ParseMachineCode(RangeBegin, RangeEnd, M)) {
289 if (Match) {
290 std::cerr << "Error: Multiple matches found:\n";
291 PrintRange(InstsB, InstsE);
292 }
293
294 assert(Match == 0 && "Multiple matches??");
295 Match = R;
296 }
297 RangeBegin = RangeEnd;
298 }
299
300 return Match;
301}
302
303static void PrintValue(Record *I, unsigned char *Ptr, const RecordVal &Val) {
304 assert(dynamic_cast<BitsInit*>(Val.getValue()) &&
305 "Can only handle undefined bits<> types!");
306 BitsInit *BI = (BitsInit*)Val.getValue();
307 assert(BI->getNumBits() <= 32 && "Can only handle fields up to 32 bits!");
308
309 unsigned Value = 0;
310 const std::vector<RecordVal> &Vals = I->getValues();
311
312 // Start by filling in fixed values...
313 for (unsigned i = 0, e = BI->getNumBits(); i != e; ++i)
314 if (BitInit *B = dynamic_cast<BitInit*>(BI->getBit(i)))
315 Value |= B->getValue() << i;
316
317 // Loop over all of the fields in the instruction adding in any
318 // contributions to this value (due to bit references).
319 //
320 unsigned Offset = 0;
321 for (unsigned f = 0, e = Vals.size(); f != e; ++f)
322 if (Vals[f].getPrefix()) {
Chris Lattner98334932002-12-02 17:43:43 +0000323 BitsInit *FieldInitializer = (BitsInit*)Vals[f].getValue();
Chris Lattnere62c1182002-12-02 01:23:04 +0000324 if (&Vals[f] == &Val) {
325 // Read the bits directly now...
326 for (unsigned i = 0, e = BI->getNumBits(); i != e; ++i)
327 Value |= getMemoryBit(Ptr, Offset+i) << i;
328 break;
329 }
330
331 // Scan through the field looking for bit initializers of the current
332 // variable...
Chris Lattner98334932002-12-02 17:43:43 +0000333 for (unsigned i = 0, e = FieldInitializer->getNumBits(); i != e; ++i)
Chris Lattnere62c1182002-12-02 01:23:04 +0000334 if (VarBitInit *VBI =
Chris Lattner98334932002-12-02 17:43:43 +0000335 dynamic_cast<VarBitInit*>(FieldInitializer->getBit(i))) {
336 TypedInit *TI = VBI->getVariable();
337 if (VarInit *VI = dynamic_cast<VarInit*>(TI)) {
338 if (VI->getName() == Val.getName())
339 Value |= getMemoryBit(Ptr, Offset+i) << VBI->getBitNum();
340 } else if (FieldInit *FI = dynamic_cast<FieldInit*>(TI)) {
341 // FIXME: implement this!
342 std::cerr << "FIELD INIT not implemented yet!\n";
343 }
Chris Lattnere62c1182002-12-02 01:23:04 +0000344 }
Chris Lattner98334932002-12-02 17:43:43 +0000345 Offset += FieldInitializer->getNumBits();
Chris Lattnere62c1182002-12-02 01:23:04 +0000346 }
347
348 std::cout << "0x" << std::hex << Value << std::dec;
349}
350
351static void PrintInstruction(Record *I, unsigned char *Ptr) {
352 std::cout << "Inst " << getNumBits(I)/8 << " bytes: "
353 << "\t" << I->getName() << "\t" << *I->getValue("Name")->getValue()
354 << "\t";
355
356 const std::vector<RecordVal> &Vals = I->getValues();
357 for (unsigned i = 0, e = Vals.size(); i != e; ++i)
358 if (!Vals[i].getValue()->isComplete()) {
359 std::cout << Vals[i].getName() << "=";
360 PrintValue(I, Ptr, Vals[i]);
361 std::cout << "\t";
362 }
363
364 std::cout << "\n";// << *I;
365}
366
367static void ParseMachineCode() {
Misha Brukmanf00ce8b2003-05-24 00:17:12 +0000368 // X86 code
Chris Lattner7b1d49b2002-12-03 20:01:04 +0000369 unsigned char Buffer[] = {
370 0x55, // push EBP
Chris Lattnere62c1182002-12-02 01:23:04 +0000371 0x89, 0xE5, // mov EBP, ESP
372 //0x83, 0xEC, 0x08, // sub ESP, 0x8
373 0xE8, 1, 2, 3, 4, // call +0x04030201
374 0x89, 0xEC, // mov ESP, EBP
375 0x5D, // pop EBP
376 0xC3, // ret
377 0x90, // nop
378 0xC9, // leave
379 0x89, 0xF6, // mov ESI, ESI
Chris Lattnere62c1182002-12-02 01:23:04 +0000380 0x68, 1, 2, 3, 4, // push 0x04030201
381 0x5e, // pop ESI
382 0xFF, 0xD0, // call EAX
Chris Lattner7b1d49b2002-12-03 20:01:04 +0000383 0xB8, 1, 2, 3, 4, // mov EAX, 0x04030201
Chris Lattnere62c1182002-12-02 01:23:04 +0000384 0x85, 0xC0, // test EAX, EAX
385 0xF4, // hlt
386 };
Misha Brukmanf00ce8b2003-05-24 00:17:12 +0000387
388#if 0
389 // SparcV9 code
390 unsigned char Buffer[] = { 0xbf, 0xe0, 0x20, 0x1f, 0x1, 0x0, 0x0, 0x1,
391 0x0, 0x0, 0x0, 0x0, 0xc1, 0x0, 0x20, 0x1, 0x1,
392 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
393 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x0, 0x0, 0x0, 0x1,
394 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
395 0x0, 0x0, 0xaf, 0xe8, 0x20, 0x17
396 };
397#endif
398
Chris Lattner1d1adea2003-08-01 04:39:05 +0000399 std::vector<Record*> Insts = Records.getAllDerivedDefinitions("Instruction");
Chris Lattnere62c1182002-12-02 01:23:04 +0000400
401 unsigned char *BuffPtr = Buffer;
402 while (1) {
403 Record *R = ParseMachineCode(Insts.begin(), Insts.end(), BuffPtr);
Chris Lattnere62c1182002-12-02 01:23:04 +0000404 PrintInstruction(R, BuffPtr);
405
406 unsigned Bits = getNumBits(R);
407 assert((Bits & 7) == 0 && "Instruction is not an even number of bytes!");
408 BuffPtr += Bits/8;
409 }
410}
411
Chris Lattnere62c1182002-12-02 01:23:04 +0000412int main(int argc, char **argv) {
413 cl::ParseCommandLineOptions(argc, argv);
John Criswell96b4bed2003-08-27 13:41:57 +0000414 ParseFile(InputFilename, IncludeDir);
Chris Lattnere62c1182002-12-02 01:23:04 +0000415
Chris Lattner9a886382003-06-03 05:04:42 +0000416 std::ostream *Out = &std::cout;
417 if (OutputFilename != "-") {
Chris Lattner42df6d12004-07-13 06:11:46 +0000418 Out = new std::ofstream(OutputFilename.c_str());
Chris Lattner9a886382003-06-03 05:04:42 +0000419
420 if (!Out->good()) {
Chris Lattner42df6d12004-07-13 06:11:46 +0000421 std::cerr << argv[0] << ": error opening " << OutputFilename << "!\n";
Chris Lattner9a886382003-06-03 05:04:42 +0000422 return 1;
423 }
424
425 // Make sure the file gets removed if *gasp* tablegen crashes...
Chris Lattner42df6d12004-07-13 06:11:46 +0000426 RemoveFileOnSignal(OutputFilename);
Chris Lattner9a886382003-06-03 05:04:42 +0000427 }
428
Chris Lattner1d1adea2003-08-01 04:39:05 +0000429 try {
430 switch (Action) {
Chris Lattneraccd8ab2003-08-01 04:47:20 +0000431 case PrintRecords:
432 *Out << Records; // No argument, dump all contents
433 break;
Chris Lattner1d1adea2003-08-01 04:39:05 +0000434 case Parse:
435 ParseMachineCode();
436 break;
437 case GenEmitter:
438 CodeEmitterGen(Records).run(*Out);
439 break;
Chris Lattner169e66b2003-08-03 17:24:20 +0000440
Chris Lattner54d156d2003-08-01 05:59:20 +0000441 case GenRegisterEnums:
442 RegisterInfoEmitter(Records).runEnums(*Out);
443 break;
Chris Lattner1d1adea2003-08-01 04:39:05 +0000444 case GenRegister:
445 RegisterInfoEmitter(Records).run(*Out);
446 break;
447 case GenRegisterHeader:
448 RegisterInfoEmitter(Records).runHeader(*Out);
449 break;
Chris Lattner169e66b2003-08-03 17:24:20 +0000450
451 case GenInstrEnums:
452 InstrInfoEmitter(Records).runEnums(*Out);
453 break;
Chris Lattner15de32d2003-08-03 21:58:28 +0000454 case GenInstrs:
455 InstrInfoEmitter(Records).run(*Out);
456 break;
Chris Lattner3f781342003-08-06 04:47:56 +0000457 case GenInstrSelector:
458 InstrSelectorEmitter(Records).run(*Out);
459 break;
Chris Lattner1d1adea2003-08-01 04:39:05 +0000460 case PrintEnums:
Brian Gaeked0fde302003-11-11 22:41:34 +0000461 {
Chris Lattner1d1adea2003-08-01 04:39:05 +0000462 std::vector<Record*> Recs = Records.getAllDerivedDefinitions(Class);
Chris Lattner1d1adea2003-08-01 04:39:05 +0000463 for (unsigned i = 0, e = Recs.size(); i != e; ++i)
Chris Lattner7b9ee512004-02-06 03:19:17 +0000464 *Out << Recs[i]->getName() << ", ";
Chris Lattner1d1adea2003-08-01 04:39:05 +0000465 *Out << "\n";
466 break;
Chris Lattnere62c1182002-12-02 01:23:04 +0000467 }
Brian Gaeked0fde302003-11-11 22:41:34 +0000468 default:
469 assert(1 && "Invalid Action");
470 return 1;
471 }
Chris Lattner1d1adea2003-08-01 04:39:05 +0000472 } catch (const std::string &Error) {
473 std::cerr << Error << "\n";
Chris Lattnerf1e366a2003-08-01 19:21:43 +0000474 if (Out != &std::cout) {
475 delete Out; // Close the file
476 std::remove(OutputFilename.c_str()); // Remove the file, it's broken
477 }
Chris Lattner1d1adea2003-08-01 04:39:05 +0000478 return 1;
Chris Lattnere62c1182002-12-02 01:23:04 +0000479 }
Chris Lattner9a886382003-06-03 05:04:42 +0000480
Chris Lattnere79c72d2003-08-01 20:35:01 +0000481 if (Out != &std::cout) {
482 delete Out; // Close the file
Chris Lattnere79c72d2003-08-01 20:35:01 +0000483 }
Chris Lattner1d1adea2003-08-01 04:39:05 +0000484 return 0;
Chris Lattnere62c1182002-12-02 01:23:04 +0000485}