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