TableGen.cpp revision 199511
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 "AsmMatcherEmitter.h"
19#include "AsmWriterEmitter.h"
20#include "CallingConvEmitter.h"
21#include "ClangDiagnosticsEmitter.h"
22#include "CodeEmitterGen.h"
23#include "DAGISelEmitter.h"
24#include "FastISelEmitter.h"
25#include "InstrEnumEmitter.h"
26#include "InstrInfoEmitter.h"
27#include "IntrinsicEmitter.h"
28#include "LLVMCConfigurationEmitter.h"
29#include "OptParserEmitter.h"
30#include "Record.h"
31#include "RegisterInfoEmitter.h"
32#include "SubtargetEmitter.h"
33#include "TGParser.h"
34#include "llvm/Support/CommandLine.h"
35#include "llvm/Support/FileUtilities.h"
36#include "llvm/Support/MemoryBuffer.h"
37#include "llvm/Support/PrettyStackTrace.h"
38#include "llvm/Support/raw_ostream.h"
39#include "llvm/System/Signals.h"
40#include <algorithm>
41#include <cstdio>
42using namespace llvm;
43
44enum ActionType {
45  PrintRecords,
46  GenEmitter,
47  GenRegisterEnums, GenRegister, GenRegisterHeader,
48  GenInstrEnums, GenInstrs, GenAsmWriter, GenAsmMatcher,
49  GenCallingConv,
50  GenClangDiagsDefs,
51  GenClangDiagGroups,
52  GenDAGISel,
53  GenFastISel,
54  GenOptParserDefs, GenOptParserImpl,
55  GenSubtarget,
56  GenIntrinsic,
57  GenTgtIntrinsic,
58  GenLLVMCConf,
59  PrintEnums
60};
61
62namespace {
63  cl::opt<ActionType>
64  Action(cl::desc("Action to perform:"),
65         cl::values(clEnumValN(PrintRecords, "print-records",
66                               "Print all records to stdout (default)"),
67                    clEnumValN(GenEmitter, "gen-emitter",
68                               "Generate machine code emitter"),
69                    clEnumValN(GenRegisterEnums, "gen-register-enums",
70                               "Generate enum values for registers"),
71                    clEnumValN(GenRegister, "gen-register-desc",
72                               "Generate a register info description"),
73                    clEnumValN(GenRegisterHeader, "gen-register-desc-header",
74                               "Generate a register info description header"),
75                    clEnumValN(GenInstrEnums, "gen-instr-enums",
76                               "Generate enum values for instructions"),
77                    clEnumValN(GenInstrs, "gen-instr-desc",
78                               "Generate instruction descriptions"),
79                    clEnumValN(GenCallingConv, "gen-callingconv",
80                               "Generate calling convention descriptions"),
81                    clEnumValN(GenAsmWriter, "gen-asm-writer",
82                               "Generate assembly writer"),
83                    clEnumValN(GenAsmMatcher, "gen-asm-matcher",
84                               "Generate assembly instruction matcher"),
85                    clEnumValN(GenDAGISel, "gen-dag-isel",
86                               "Generate a DAG instruction selector"),
87                    clEnumValN(GenFastISel, "gen-fast-isel",
88                               "Generate a \"fast\" instruction selector"),
89                    clEnumValN(GenOptParserDefs, "gen-opt-parser-defs",
90                               "Generate option definitions"),
91                    clEnumValN(GenOptParserImpl, "gen-opt-parser-impl",
92                               "Generate option parser implementation"),
93                    clEnumValN(GenSubtarget, "gen-subtarget",
94                               "Generate subtarget enumerations"),
95                    clEnumValN(GenIntrinsic, "gen-intrinsic",
96                               "Generate intrinsic information"),
97                    clEnumValN(GenTgtIntrinsic, "gen-tgt-intrinsic",
98                               "Generate target intrinsic information"),
99                    clEnumValN(GenClangDiagsDefs, "gen-clang-diags-defs",
100                               "Generate Clang diagnostics definitions"),
101                    clEnumValN(GenClangDiagGroups, "gen-clang-diag-groups",
102                               "Generate Clang diagnostic groups"),
103                    clEnumValN(GenLLVMCConf, "gen-llvmc",
104                               "Generate LLVMC configuration library"),
105                    clEnumValN(PrintEnums, "print-enums",
106                               "Print enum values for a class"),
107                    clEnumValEnd));
108
109  cl::opt<std::string>
110  Class("class", cl::desc("Print Enum list for this class"),
111        cl::value_desc("class name"));
112
113  cl::opt<std::string>
114  OutputFilename("o", cl::desc("Output filename"), cl::value_desc("filename"),
115                 cl::init("-"));
116
117  cl::opt<std::string>
118  InputFilename(cl::Positional, cl::desc("<input file>"), cl::init("-"));
119
120  cl::list<std::string>
121  IncludeDirs("I", cl::desc("Directory of include files"),
122              cl::value_desc("directory"), cl::Prefix);
123
124  cl::opt<std::string>
125  ClangComponent("clang-component",
126                 cl::desc("Only use warnings from specified component"),
127                 cl::value_desc("component"), cl::Hidden);
128}
129
130
131// FIXME: Eliminate globals from tblgen.
132RecordKeeper llvm::Records;
133
134static SourceMgr SrcMgr;
135
136void llvm::PrintError(SMLoc ErrorLoc, const std::string &Msg) {
137  SrcMgr.PrintMessage(ErrorLoc, Msg, "error");
138}
139
140
141
142/// ParseFile - this function begins the parsing of the specified tablegen
143/// file.
144static bool ParseFile(const std::string &Filename,
145                      const std::vector<std::string> &IncludeDirs,
146                      SourceMgr &SrcMgr) {
147  std::string ErrorStr;
148  MemoryBuffer *F = MemoryBuffer::getFileOrSTDIN(Filename.c_str(), &ErrorStr);
149  if (F == 0) {
150    errs() << "Could not open input file '" << Filename << "': "
151           << ErrorStr <<"\n";
152    return true;
153  }
154
155  // Tell SrcMgr about this buffer, which is what TGParser will pick up.
156  SrcMgr.AddNewSourceBuffer(F, SMLoc());
157
158  // Record the location of the include directory so that the lexer can find
159  // it later.
160  SrcMgr.setIncludeDirs(IncludeDirs);
161
162  TGParser Parser(SrcMgr);
163
164  return Parser.ParseFile();
165}
166
167int main(int argc, char **argv) {
168  sys::PrintStackTraceOnErrorSignal();
169  PrettyStackTraceProgram X(argc, argv);
170  cl::ParseCommandLineOptions(argc, argv);
171
172
173  // Parse the input file.
174  if (ParseFile(InputFilename, IncludeDirs, SrcMgr))
175    return 1;
176
177  raw_ostream *Out = &outs();
178  if (OutputFilename != "-") {
179    std::string Error;
180    Out = new raw_fd_ostream(OutputFilename.c_str(), Error);
181
182    if (!Error.empty()) {
183      errs() << argv[0] << ": error opening " << OutputFilename
184             << ":" << Error << "\n";
185      return 1;
186    }
187
188    // Make sure the file gets removed if *gasp* tablegen crashes...
189    sys::RemoveFileOnSignal(sys::Path(OutputFilename));
190  }
191
192  try {
193    switch (Action) {
194    case PrintRecords:
195      *Out << Records;           // No argument, dump all contents
196      break;
197    case GenEmitter:
198      CodeEmitterGen(Records).run(*Out);
199      break;
200
201    case GenRegisterEnums:
202      RegisterInfoEmitter(Records).runEnums(*Out);
203      break;
204    case GenRegister:
205      RegisterInfoEmitter(Records).run(*Out);
206      break;
207    case GenRegisterHeader:
208      RegisterInfoEmitter(Records).runHeader(*Out);
209      break;
210    case GenInstrEnums:
211      InstrEnumEmitter(Records).run(*Out);
212      break;
213    case GenInstrs:
214      InstrInfoEmitter(Records).run(*Out);
215      break;
216    case GenCallingConv:
217      CallingConvEmitter(Records).run(*Out);
218      break;
219    case GenAsmWriter:
220      AsmWriterEmitter(Records).run(*Out);
221      break;
222    case GenAsmMatcher:
223      AsmMatcherEmitter(Records).run(*Out);
224      break;
225    case GenClangDiagsDefs:
226      ClangDiagsDefsEmitter(Records, ClangComponent).run(*Out);
227      break;
228    case GenClangDiagGroups:
229      ClangDiagGroupsEmitter(Records).run(*Out);
230      break;
231    case GenOptParserDefs:
232      OptParserEmitter(Records, true).run(*Out);
233      break;
234    case GenOptParserImpl:
235      OptParserEmitter(Records, false).run(*Out);
236      break;
237    case GenDAGISel:
238      DAGISelEmitter(Records).run(*Out);
239      break;
240    case GenFastISel:
241      FastISelEmitter(Records).run(*Out);
242      break;
243    case GenSubtarget:
244      SubtargetEmitter(Records).run(*Out);
245      break;
246    case GenIntrinsic:
247      IntrinsicEmitter(Records).run(*Out);
248      break;
249    case GenTgtIntrinsic:
250      IntrinsicEmitter(Records, true).run(*Out);
251      break;
252    case GenLLVMCConf:
253      LLVMCConfigurationEmitter(Records).run(*Out);
254      break;
255    case PrintEnums:
256    {
257      std::vector<Record*> Recs = Records.getAllDerivedDefinitions(Class);
258      for (unsigned i = 0, e = Recs.size(); i != e; ++i)
259        *Out << Recs[i]->getName() << ", ";
260      *Out << "\n";
261      break;
262    }
263    default:
264      assert(1 && "Invalid Action");
265      return 1;
266    }
267
268    if (Out != &outs())
269      delete Out;                               // Close the file
270    return 0;
271
272  } catch (const TGError &Error) {
273    errs() << argv[0] << ": error:\n";
274    PrintError(Error.getLoc(), Error.getMessage());
275
276  } catch (const std::string &Error) {
277    errs() << argv[0] << ": " << Error << "\n";
278  } catch (const char *Error) {
279    errs() << argv[0] << ": " << Error << "\n";
280  } catch (...) {
281    errs() << argv[0] << ": Unknown unexpected exception occurred.\n";
282  }
283
284  if (Out != &outs()) {
285    delete Out;                             // Close the file
286    std::remove(OutputFilename.c_str());    // Remove the file, it's broken
287  }
288  return 1;
289}
290