28e4a8a86f6d6c967b7500569246ab462e099e8f
[oota-llvm.git] / utils / TableGen / TableGen.cpp
1 //===- TableGen.cpp - Top-Level TableGen implementation -------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
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
18 #include "Record.h"
19 #include "TGParser.h"
20 #include "llvm/Support/CommandLine.h"
21 #include "llvm/Support/Streams.h"
22 #include "llvm/System/Signals.h"
23 #include "llvm/Support/FileUtilities.h"
24 #include "llvm/Support/MemoryBuffer.h"
25 #include "CallingConvEmitter.h"
26 #include "CodeEmitterGen.h"
27 #include "RegisterInfoEmitter.h"
28 #include "InstrInfoEmitter.h"
29 #include "AsmWriterEmitter.h"
30 #include "DAGISelEmitter.h"
31 #include "SubtargetEmitter.h"
32 #include "IntrinsicEmitter.h"
33 #include <algorithm>
34 #include <cstdio>
35 #include <fstream>
36 #include <ios>
37 using namespace llvm;
38
39 enum ActionType {
40   PrintRecords,
41   GenEmitter,
42   GenRegisterEnums, GenRegister, GenRegisterHeader,
43   GenInstrEnums, GenInstrs, GenAsmWriter, 
44   GenCallingConv,
45   GenDAGISel,
46   GenSubtarget,
47   GenIntrinsic,
48   PrintEnums
49 };
50
51 namespace {
52   cl::opt<ActionType>
53   Action(cl::desc("Action to perform:"),
54          cl::values(clEnumValN(PrintRecords, "print-records",
55                                "Print all records to stdout (default)"),
56                     clEnumValN(GenEmitter, "gen-emitter",
57                                "Generate machine code emitter"),
58                     clEnumValN(GenRegisterEnums, "gen-register-enums",
59                                "Generate enum values for registers"),
60                     clEnumValN(GenRegister, "gen-register-desc",
61                                "Generate a register info description"),
62                     clEnumValN(GenRegisterHeader, "gen-register-desc-header",
63                                "Generate a register info description header"),
64                     clEnumValN(GenInstrEnums, "gen-instr-enums",
65                                "Generate enum values for instructions"),
66                     clEnumValN(GenInstrs, "gen-instr-desc",
67                                "Generate instruction descriptions"),
68                     clEnumValN(GenCallingConv, "gen-callingconv",
69                                "Generate calling convention descriptions"),
70                     clEnumValN(GenAsmWriter, "gen-asm-writer",
71                                "Generate assembly writer"),
72                     clEnumValN(GenDAGISel, "gen-dag-isel",
73                                "Generate a DAG instruction selector"),
74                     clEnumValN(GenSubtarget, "gen-subtarget",
75                                "Generate subtarget enumerations"),
76                     clEnumValN(GenIntrinsic, "gen-intrinsic",
77                                "Generate intrinsic information"),
78                     clEnumValN(PrintEnums, "print-enums",
79                                "Print enum values for a class"),
80                     clEnumValEnd));
81
82   cl::opt<std::string>
83   Class("class", cl::desc("Print Enum list for this class"),
84         cl::value_desc("class name"));
85
86   cl::opt<std::string>
87   OutputFilename("o", cl::desc("Output filename"), cl::value_desc("filename"),
88                  cl::init("-"));
89
90   cl::opt<std::string>
91   InputFilename(cl::Positional, cl::desc("<input file>"), cl::init("-"));
92
93   cl::list<std::string>
94   IncludeDirs("I", cl::desc("Directory of include files"),
95               cl::value_desc("directory"), cl::Prefix);
96 }
97
98 RecordKeeper llvm::Records;
99
100 /// ParseFile - this function begins the parsing of the specified tablegen
101 /// file.
102 static bool ParseFile(const std::string &Filename, 
103                       const std::vector<std::string> &IncludeDirs) {
104   std::string ErrorStr;
105   MemoryBuffer *F = MemoryBuffer::getFileOrSTDIN(&Filename[0], Filename.size(),
106                                                  &ErrorStr);
107   if (F == 0) {
108     cerr << "Could not open input file '" + Filename + "': " << ErrorStr <<"\n";
109     return true;
110   }
111   
112   TGParser Parser(F);
113   
114   // Record the location of the include directory so that the lexer can find
115   // it later.
116   Parser.setIncludeDirs(IncludeDirs);
117   
118   return Parser.ParseFile();
119 }
120
121 int main(int argc, char **argv) {
122   cl::ParseCommandLineOptions(argc, argv);
123
124   // Parse the input file.
125   if (ParseFile(InputFilename, IncludeDirs))
126     return 1;
127
128   std::ostream *Out = cout.stream();
129   if (OutputFilename != "-") {
130     Out = new std::ofstream(OutputFilename.c_str());
131
132     if (!Out->good()) {
133       cerr << argv[0] << ": error opening " << OutputFilename << "!\n";
134       return 1;
135     }
136
137     // Make sure the file gets removed if *gasp* tablegen crashes...
138     sys::RemoveFileOnSignal(sys::Path(OutputFilename));
139   }
140
141   try {
142     switch (Action) {
143     case PrintRecords:
144       *Out << Records;           // No argument, dump all contents
145       break;
146     case GenEmitter:
147       CodeEmitterGen(Records).run(*Out);
148       break;
149
150     case GenRegisterEnums:
151       RegisterInfoEmitter(Records).runEnums(*Out);
152       break;
153     case GenRegister:
154       RegisterInfoEmitter(Records).run(*Out);
155       break;
156     case GenRegisterHeader:
157       RegisterInfoEmitter(Records).runHeader(*Out);
158       break;
159
160     case GenInstrEnums:
161       InstrInfoEmitter(Records).runEnums(*Out);
162       break;
163     case GenInstrs:
164       InstrInfoEmitter(Records).run(*Out);
165       break;
166     case GenCallingConv:
167       CallingConvEmitter(Records).run(*Out);
168       break;
169     case GenAsmWriter:
170       AsmWriterEmitter(Records).run(*Out);
171       break;
172
173     case GenDAGISel:
174       DAGISelEmitter(Records).run(*Out);
175       break;
176     case GenSubtarget:
177       SubtargetEmitter(Records).run(*Out);
178       break;
179     case GenIntrinsic:
180       IntrinsicEmitter(Records).run(*Out);
181       break;
182     case PrintEnums:
183     {
184       std::vector<Record*> Recs = Records.getAllDerivedDefinitions(Class);
185       for (unsigned i = 0, e = Recs.size(); i != e; ++i)
186         *Out << Recs[i]->getName() << ", ";
187       *Out << "\n";
188       break;
189     }
190     default:
191       assert(1 && "Invalid Action");
192       return 1;
193     }
194   } catch (const std::string &Error) {
195     cerr << argv[0] << ": " << Error << "\n";
196     if (Out != cout.stream()) {
197       delete Out;                             // Close the file
198       std::remove(OutputFilename.c_str());    // Remove the file, it's broken
199     }
200     return 1;
201   } catch (...) {
202     cerr << argv[0] << ": Unknown unexpected exception occurred.\n";
203     if (Out != cout.stream()) {
204       delete Out;                             // Close the file
205       std::remove(OutputFilename.c_str());    // Remove the file, it's broken
206     }
207     return 2;
208   }
209
210   if (Out != cout.stream()) {
211     delete Out;                               // Close the file
212   }
213   return 0;
214 }