blob: 83bc66f46080b012dbc79bc42d43a3bec03fda39 [file] [log] [blame]
Peter Collingbourne7c788882011-10-01 16:41:13 +00001//===- Main.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 "TGParser.h"
19#include "llvm/ADT/OwningPtr.h"
20#include "llvm/Support/CommandLine.h"
21#include "llvm/Support/MemoryBuffer.h"
22#include "llvm/Support/ToolOutputFile.h"
23#include "llvm/Support/system_error.h"
24#include "llvm/TableGen/Error.h"
Sean Silvaf42a6742012-10-03 21:29:18 +000025#include "llvm/TableGen/Main.h"
Peter Collingbourne7c788882011-10-01 16:41:13 +000026#include "llvm/TableGen/Record.h"
27#include "llvm/TableGen/TableGenAction.h"
28#include <algorithm>
29#include <cstdio>
30using namespace llvm;
31
32namespace {
33 cl::opt<std::string>
34 OutputFilename("o", cl::desc("Output filename"), cl::value_desc("filename"),
35 cl::init("-"));
36
37 cl::opt<std::string>
Michael J. Spencercdd6b2d2012-06-01 00:58:41 +000038 DependFilename("d",
39 cl::desc("Dependency filename"),
40 cl::value_desc("filename"),
Peter Collingbourne7c788882011-10-01 16:41:13 +000041 cl::init(""));
42
43 cl::opt<std::string>
44 InputFilename(cl::Positional, cl::desc("<input file>"), cl::init("-"));
45
46 cl::list<std::string>
47 IncludeDirs("I", cl::desc("Directory of include files"),
48 cl::value_desc("directory"), cl::Prefix);
49}
50
Sean Silvaf42a6742012-10-03 21:29:18 +000051namespace {
52// XXX: this is a crutch for transitioning to the new TableGenMain API
53// (with a TableGenMainFn* instead of a pointless class).
54class StubTransitionalTableGenAction : public TableGenAction {
55 TableGenMainFn *MainFn;
56public:
57 StubTransitionalTableGenAction(TableGenMainFn *M) : MainFn(M) {}
58 bool operator()(raw_ostream &OS, RecordKeeper &Records) {
59 return MainFn(OS, Records);
60 }
61};
62}
63
Peter Collingbourne7c788882011-10-01 16:41:13 +000064namespace llvm {
65
Sean Silvaf42a6742012-10-03 21:29:18 +000066int TableGenMain(char *argv0, TableGenMainFn *MainFn) {
67 StubTransitionalTableGenAction Action(MainFn);
68 return TableGenMain(argv0, Action);
69}
70
Peter Collingbourne7c788882011-10-01 16:41:13 +000071int TableGenMain(char *argv0, TableGenAction &Action) {
72 RecordKeeper Records;
73
74 try {
75 // Parse the input file.
76 OwningPtr<MemoryBuffer> File;
Michael J. Spencercdd6b2d2012-06-01 00:58:41 +000077 if (error_code ec =
78 MemoryBuffer::getFileOrSTDIN(InputFilename.c_str(), File)) {
Peter Collingbourne7c788882011-10-01 16:41:13 +000079 errs() << "Could not open input file '" << InputFilename << "': "
80 << ec.message() <<"\n";
81 return 1;
82 }
83 MemoryBuffer *F = File.take();
84
85 // Tell SrcMgr about this buffer, which is what TGParser will pick up.
86 SrcMgr.AddNewSourceBuffer(F, SMLoc());
87
88 // Record the location of the include directory so that the lexer can find
89 // it later.
90 SrcMgr.setIncludeDirs(IncludeDirs);
91
Peter Collingbourne7c788882011-10-01 16:41:13 +000092 TGParser Parser(SrcMgr, Records);
93
94 if (Parser.ParseFile())
95 return 1;
96
97 std::string Error;
98 tool_output_file Out(OutputFilename.c_str(), Error);
99 if (!Error.empty()) {
100 errs() << argv0 << ": error opening " << OutputFilename
101 << ":" << Error << "\n";
102 return 1;
103 }
104 if (!DependFilename.empty()) {
105 if (OutputFilename == "-") {
106 errs() << argv0 << ": the option -d must be used together with -o\n";
107 return 1;
108 }
109 tool_output_file DepOut(DependFilename.c_str(), Error);
110 if (!Error.empty()) {
111 errs() << argv0 << ": error opening " << DependFilename
112 << ":" << Error << "\n";
113 return 1;
114 }
115 DepOut.os() << OutputFilename << ":";
116 const std::vector<std::string> &Dependencies = Parser.getDependencies();
117 for (std::vector<std::string>::const_iterator I = Dependencies.begin(),
Michael J. Spencercdd6b2d2012-06-01 00:58:41 +0000118 E = Dependencies.end();
Peter Collingbourne7c788882011-10-01 16:41:13 +0000119 I != E; ++I) {
120 DepOut.os() << " " << (*I);
121 }
122 DepOut.os() << "\n";
123 DepOut.keep();
124 }
125
126 if (Action(Out.os(), Records))
127 return 1;
128
129 // Declare success.
130 Out.keep();
131 return 0;
132
133 } catch (const TGError &Error) {
134 PrintError(Error);
135 } catch (const std::string &Error) {
136 PrintError(Error);
137 } catch (const char *Error) {
138 PrintError(Error);
139 } catch (...) {
140 errs() << argv0 << ": Unknown unexpected exception occurred.\n";
141 }
142
143 return 1;
144}
145
146}