TableGen.cpp revision 208954
155682Smarkm//===- TableGen.cpp - Top-Level TableGen implementation -------------------===//
255682Smarkm//
355682Smarkm//                     The LLVM Compiler Infrastructure
455682Smarkm//
555682Smarkm// This file is distributed under the University of Illinois Open Source
655682Smarkm// License. See LICENSE.TXT for details.
755682Smarkm//
8233294Sstas//===----------------------------------------------------------------------===//
9102644Snectar//
10102644Snectar// TableGen is a tool which can be used to build up a description of something,
11178825Sdfr// then invoke one or more "tablegen backends" to emit information about the
12102644Snectar// description in some predefined format.  In practice, this is used by the LLVM
13233294Sstas// code generators to automate generation of a code generator through a
14178825Sdfr// high-level description of the target.
1555682Smarkm//
16178825Sdfr//===----------------------------------------------------------------------===//
17178825Sdfr
18178825Sdfr#include "AsmMatcherEmitter.h"
19178825Sdfr#include "AsmWriterEmitter.h"
20178825Sdfr#include "CallingConvEmitter.h"
21233294Sstas#include "ClangASTNodesEmitter.h"
22233294Sstas#include "ClangDiagnosticsEmitter.h"
23233294Sstas#include "CodeEmitterGen.h"
24233294Sstas#include "DAGISelEmitter.h"
25233294Sstas#include "DisassemblerEmitter.h"
26233294Sstas#include "EDEmitter.h"
27178825Sdfr#include "FastISelEmitter.h"
28178825Sdfr#include "InstrEnumEmitter.h"
29178825Sdfr#include "InstrInfoEmitter.h"
30178825Sdfr#include "IntrinsicEmitter.h"
31178825Sdfr#include "LLVMCConfigurationEmitter.h"
32178825Sdfr#include "OptParserEmitter.h"
33178825Sdfr#include "Record.h"
34178825Sdfr#include "RegisterInfoEmitter.h"
35178825Sdfr#include "ARMDecoderEmitter.h"
36178825Sdfr#include "SubtargetEmitter.h"
37178825Sdfr#include "TGParser.h"
38178825Sdfr#include "llvm/Support/CommandLine.h"
39178825Sdfr#include "llvm/Support/MemoryBuffer.h"
40178825Sdfr#include "llvm/Support/PrettyStackTrace.h"
41178825Sdfr#include "llvm/Support/raw_ostream.h"
42178825Sdfr#include "llvm/System/Signals.h"
43178825Sdfr#include <algorithm>
44178825Sdfr#include <cstdio>
45178825Sdfrusing namespace llvm;
46178825Sdfr
47178825Sdfrenum ActionType {
4855682Smarkm  PrintRecords,
49102644Snectar  GenEmitter,
50102644Snectar  GenRegisterEnums, GenRegister, GenRegisterHeader,
51102644Snectar  GenInstrEnums, GenInstrs, GenAsmWriter, GenAsmMatcher,
52178825Sdfr  GenARMDecoder,
5355682Smarkm  GenDisassembler,
5455682Smarkm  GenCallingConv,
55102644Snectar  GenClangDiagsDefs,
56102644Snectar  GenClangDiagGroups,
57102644Snectar  GenClangStmtNodes,
58102644Snectar  GenDAGISel,
59178825Sdfr  GenFastISel,
6055682Smarkm  GenOptParserDefs, GenOptParserImpl,
6155682Smarkm  GenSubtarget,
62  GenIntrinsic,
63  GenTgtIntrinsic,
64  GenLLVMCConf,
65  GenEDHeader, GenEDInfo,
66  PrintEnums
67};
68
69namespace {
70  cl::opt<ActionType>
71  Action(cl::desc("Action to perform:"),
72         cl::values(clEnumValN(PrintRecords, "print-records",
73                               "Print all records to stdout (default)"),
74                    clEnumValN(GenEmitter, "gen-emitter",
75                               "Generate machine code emitter"),
76                    clEnumValN(GenRegisterEnums, "gen-register-enums",
77                               "Generate enum values for registers"),
78                    clEnumValN(GenRegister, "gen-register-desc",
79                               "Generate a register info description"),
80                    clEnumValN(GenRegisterHeader, "gen-register-desc-header",
81                               "Generate a register info description header"),
82                    clEnumValN(GenInstrEnums, "gen-instr-enums",
83                               "Generate enum values for instructions"),
84                    clEnumValN(GenInstrs, "gen-instr-desc",
85                               "Generate instruction descriptions"),
86                    clEnumValN(GenCallingConv, "gen-callingconv",
87                               "Generate calling convention descriptions"),
88                    clEnumValN(GenAsmWriter, "gen-asm-writer",
89                               "Generate assembly writer"),
90                    clEnumValN(GenARMDecoder, "gen-arm-decoder",
91                               "Generate decoders for ARM/Thumb"),
92                    clEnumValN(GenDisassembler, "gen-disassembler",
93                               "Generate disassembler"),
94                    clEnumValN(GenAsmMatcher, "gen-asm-matcher",
95                               "Generate assembly instruction matcher"),
96                    clEnumValN(GenDAGISel, "gen-dag-isel",
97                               "Generate a DAG instruction selector"),
98                    clEnumValN(GenFastISel, "gen-fast-isel",
99                               "Generate a \"fast\" instruction selector"),
100                    clEnumValN(GenOptParserDefs, "gen-opt-parser-defs",
101                               "Generate option definitions"),
102                    clEnumValN(GenOptParserImpl, "gen-opt-parser-impl",
103                               "Generate option parser implementation"),
104                    clEnumValN(GenSubtarget, "gen-subtarget",
105                               "Generate subtarget enumerations"),
106                    clEnumValN(GenIntrinsic, "gen-intrinsic",
107                               "Generate intrinsic information"),
108                    clEnumValN(GenTgtIntrinsic, "gen-tgt-intrinsic",
109                               "Generate target intrinsic information"),
110                    clEnumValN(GenClangDiagsDefs, "gen-clang-diags-defs",
111                               "Generate Clang diagnostics definitions"),
112                    clEnumValN(GenClangDiagGroups, "gen-clang-diag-groups",
113                               "Generate Clang diagnostic groups"),
114                    clEnumValN(GenClangStmtNodes, "gen-clang-stmt-nodes",
115                               "Generate Clang AST statement nodes"),
116                    clEnumValN(GenLLVMCConf, "gen-llvmc",
117                               "Generate LLVMC configuration library"),
118                    clEnumValN(GenEDHeader, "gen-enhanced-disassembly-header",
119                               "Generate enhanced disassembly info header"),
120                    clEnumValN(GenEDInfo, "gen-enhanced-disassembly-info",
121                               "Generate enhanced disassembly info"),
122                    clEnumValN(PrintEnums, "print-enums",
123                               "Print enum values for a class"),
124                    clEnumValEnd));
125
126  cl::opt<std::string>
127  Class("class", cl::desc("Print Enum list for this class"),
128        cl::value_desc("class name"));
129
130  cl::opt<std::string>
131  OutputFilename("o", cl::desc("Output filename"), cl::value_desc("filename"),
132                 cl::init("-"));
133
134  cl::opt<std::string>
135  InputFilename(cl::Positional, cl::desc("<input file>"), cl::init("-"));
136
137  cl::list<std::string>
138  IncludeDirs("I", cl::desc("Directory of include files"),
139              cl::value_desc("directory"), cl::Prefix);
140
141  cl::opt<std::string>
142  ClangComponent("clang-component",
143                 cl::desc("Only use warnings from specified component"),
144                 cl::value_desc("component"), cl::Hidden);
145}
146
147
148// FIXME: Eliminate globals from tblgen.
149RecordKeeper llvm::Records;
150
151static SourceMgr SrcMgr;
152
153void llvm::PrintError(SMLoc ErrorLoc, const std::string &Msg) {
154  SrcMgr.PrintMessage(ErrorLoc, Msg, "error");
155}
156
157
158
159/// ParseFile - this function begins the parsing of the specified tablegen
160/// file.
161static bool ParseFile(const std::string &Filename,
162                      const std::vector<std::string> &IncludeDirs,
163                      SourceMgr &SrcMgr) {
164  std::string ErrorStr;
165  MemoryBuffer *F = MemoryBuffer::getFileOrSTDIN(Filename.c_str(), &ErrorStr);
166  if (F == 0) {
167    errs() << "Could not open input file '" << Filename << "': "
168           << ErrorStr <<"\n";
169    return true;
170  }
171
172  // Tell SrcMgr about this buffer, which is what TGParser will pick up.
173  SrcMgr.AddNewSourceBuffer(F, SMLoc());
174
175  // Record the location of the include directory so that the lexer can find
176  // it later.
177  SrcMgr.setIncludeDirs(IncludeDirs);
178
179  TGParser Parser(SrcMgr);
180
181  return Parser.ParseFile();
182}
183
184int main(int argc, char **argv) {
185  sys::PrintStackTraceOnErrorSignal();
186  PrettyStackTraceProgram X(argc, argv);
187  cl::ParseCommandLineOptions(argc, argv);
188
189
190  // Parse the input file.
191  if (ParseFile(InputFilename, IncludeDirs, SrcMgr))
192    return 1;
193
194  raw_ostream *Out = &outs();
195  if (OutputFilename != "-") {
196    std::string Error;
197    Out = new raw_fd_ostream(OutputFilename.c_str(), Error);
198
199    if (!Error.empty()) {
200      errs() << argv[0] << ": error opening " << OutputFilename
201             << ":" << Error << "\n";
202      return 1;
203    }
204
205    // Make sure the file gets removed if *gasp* tablegen crashes...
206    sys::RemoveFileOnSignal(sys::Path(OutputFilename));
207  }
208
209  try {
210    switch (Action) {
211    case PrintRecords:
212      *Out << Records;           // No argument, dump all contents
213      break;
214    case GenEmitter:
215      CodeEmitterGen(Records).run(*Out);
216      break;
217
218    case GenRegisterEnums:
219      RegisterInfoEmitter(Records).runEnums(*Out);
220      break;
221    case GenRegister:
222      RegisterInfoEmitter(Records).run(*Out);
223      break;
224    case GenRegisterHeader:
225      RegisterInfoEmitter(Records).runHeader(*Out);
226      break;
227    case GenInstrEnums:
228      InstrEnumEmitter(Records).run(*Out);
229      break;
230    case GenInstrs:
231      InstrInfoEmitter(Records).run(*Out);
232      break;
233    case GenCallingConv:
234      CallingConvEmitter(Records).run(*Out);
235      break;
236    case GenAsmWriter:
237      AsmWriterEmitter(Records).run(*Out);
238      break;
239    case GenARMDecoder:
240      ARMDecoderEmitter(Records).run(*Out);
241      break;
242    case GenAsmMatcher:
243      AsmMatcherEmitter(Records).run(*Out);
244      break;
245    case GenClangDiagsDefs:
246      ClangDiagsDefsEmitter(Records, ClangComponent).run(*Out);
247      break;
248    case GenClangDiagGroups:
249      ClangDiagGroupsEmitter(Records).run(*Out);
250      break;
251    case GenClangStmtNodes:
252      ClangStmtNodesEmitter(Records).run(*Out);
253      break;
254    case GenDisassembler:
255      DisassemblerEmitter(Records).run(*Out);
256      break;
257    case GenOptParserDefs:
258      OptParserEmitter(Records, true).run(*Out);
259      break;
260    case GenOptParserImpl:
261      OptParserEmitter(Records, false).run(*Out);
262      break;
263    case GenDAGISel:
264      DAGISelEmitter(Records).run(*Out);
265      break;
266    case GenFastISel:
267      FastISelEmitter(Records).run(*Out);
268      break;
269    case GenSubtarget:
270      SubtargetEmitter(Records).run(*Out);
271      break;
272    case GenIntrinsic:
273      IntrinsicEmitter(Records).run(*Out);
274      break;
275    case GenTgtIntrinsic:
276      IntrinsicEmitter(Records, true).run(*Out);
277      break;
278    case GenLLVMCConf:
279      LLVMCConfigurationEmitter(Records).run(*Out);
280      break;
281    case GenEDHeader:
282      EDEmitter(Records).runHeader(*Out);
283      break;
284    case GenEDInfo:
285      EDEmitter(Records).run(*Out);
286      break;
287    case PrintEnums:
288    {
289      std::vector<Record*> Recs = Records.getAllDerivedDefinitions(Class);
290      for (unsigned i = 0, e = Recs.size(); i != e; ++i)
291        *Out << Recs[i]->getName() << ", ";
292      *Out << "\n";
293      break;
294    }
295    default:
296      assert(1 && "Invalid Action");
297      return 1;
298    }
299
300    if (Out != &outs())
301      delete Out;                               // Close the file
302    return 0;
303
304  } catch (const TGError &Error) {
305    errs() << argv[0] << ": error:\n";
306    PrintError(Error.getLoc(), Error.getMessage());
307
308  } catch (const std::string &Error) {
309    errs() << argv[0] << ": " << Error << "\n";
310  } catch (const char *Error) {
311    errs() << argv[0] << ": " << Error << "\n";
312  } catch (...) {
313    errs() << argv[0] << ": Unknown unexpected exception occurred.\n";
314  }
315
316  if (Out != &outs()) {
317    delete Out;                             // Close the file
318    std::remove(OutputFilename.c_str());    // Remove the file, it's broken
319  }
320  return 1;
321}
322