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