1//===- OptParserEmitter.cpp - Table Driven Command Line Parsing -----------===//
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#include "llvm/TableGen/Error.h"
11#include "llvm/ADT/STLExtras.h"
12#include "llvm/ADT/SmallString.h"
13#include "llvm/ADT/Twine.h"
14#include "llvm/TableGen/Record.h"
15#include "llvm/TableGen/TableGenBackend.h"
16#include <cctype>
17#include <cstring>
18#include <map>
19
20using namespace llvm;
21
22// Ordering on Info. The logic should match with the consumer-side function in
23// llvm/Option/OptTable.h.
24static int StrCmpOptionName(const char *A, const char *B) {
25  const char *X = A, *Y = B;
26  char a = tolower(*A), b = tolower(*B);
27  while (a == b) {
28    if (a == '\0')
29      return strcmp(A, B);
30
31    a = tolower(*++X);
32    b = tolower(*++Y);
33  }
34
35  if (a == '\0') // A is a prefix of B.
36    return 1;
37  if (b == '\0') // B is a prefix of A.
38    return -1;
39
40  // Otherwise lexicographic.
41  return (a < b) ? -1 : 1;
42}
43
44static int CompareOptionRecords(Record *const *Av, Record *const *Bv) {
45  const Record *A = *Av;
46  const Record *B = *Bv;
47
48  // Sentinel options precede all others and are only ordered by precedence.
49  bool ASent = A->getValueAsDef("Kind")->getValueAsBit("Sentinel");
50  bool BSent = B->getValueAsDef("Kind")->getValueAsBit("Sentinel");
51  if (ASent != BSent)
52    return ASent ? -1 : 1;
53
54  // Compare options by name, unless they are sentinels.
55  if (!ASent)
56    if (int Cmp = StrCmpOptionName(A->getValueAsString("Name").c_str(),
57                                   B->getValueAsString("Name").c_str()))
58      return Cmp;
59
60  if (!ASent) {
61    std::vector<std::string> APrefixes = A->getValueAsListOfStrings("Prefixes");
62    std::vector<std::string> BPrefixes = B->getValueAsListOfStrings("Prefixes");
63
64    for (std::vector<std::string>::const_iterator APre = APrefixes.begin(),
65                                                  AEPre = APrefixes.end(),
66                                                  BPre = BPrefixes.begin(),
67                                                  BEPre = BPrefixes.end();
68                                                  APre != AEPre &&
69                                                  BPre != BEPre;
70                                                  ++APre, ++BPre) {
71      if (int Cmp = StrCmpOptionName(APre->c_str(), BPre->c_str()))
72        return Cmp;
73    }
74  }
75
76  // Then by the kind precedence;
77  int APrec = A->getValueAsDef("Kind")->getValueAsInt("Precedence");
78  int BPrec = B->getValueAsDef("Kind")->getValueAsInt("Precedence");
79  if (APrec == BPrec &&
80      A->getValueAsListOfStrings("Prefixes") ==
81      B->getValueAsListOfStrings("Prefixes")) {
82    PrintError(A->getLoc(), Twine("Option is equivalent to"));
83    PrintError(B->getLoc(), Twine("Other defined here"));
84    PrintFatalError("Equivalent Options found.");
85  }
86  return APrec < BPrec ? -1 : 1;
87}
88
89static const std::string getOptionName(const Record &R) {
90  // Use the record name unless EnumName is defined.
91  if (isa<UnsetInit>(R.getValueInit("EnumName")))
92    return R.getName();
93
94  return R.getValueAsString("EnumName");
95}
96
97static raw_ostream &write_cstring(raw_ostream &OS, llvm::StringRef Str) {
98  OS << '"';
99  OS.write_escaped(Str);
100  OS << '"';
101  return OS;
102}
103
104/// OptParserEmitter - This tablegen backend takes an input .td file
105/// describing a list of options and emits a data structure for parsing and
106/// working with those options when given an input command line.
107namespace llvm {
108void EmitOptParser(RecordKeeper &Records, raw_ostream &OS) {
109  // Get the option groups and options.
110  const std::vector<Record*> &Groups =
111    Records.getAllDerivedDefinitions("OptionGroup");
112  std::vector<Record*> Opts = Records.getAllDerivedDefinitions("Option");
113
114  emitSourceFileHeader("Option Parsing Definitions", OS);
115
116  array_pod_sort(Opts.begin(), Opts.end(), CompareOptionRecords);
117  // Generate prefix groups.
118  typedef SmallVector<SmallString<2>, 2> PrefixKeyT;
119  typedef std::map<PrefixKeyT, std::string> PrefixesT;
120  PrefixesT Prefixes;
121  Prefixes.insert(std::make_pair(PrefixKeyT(), "prefix_0"));
122  unsigned CurPrefix = 0;
123  for (unsigned i = 0, e = Opts.size(); i != e; ++i) {
124    const Record &R = *Opts[i];
125    std::vector<std::string> prf = R.getValueAsListOfStrings("Prefixes");
126    PrefixKeyT prfkey(prf.begin(), prf.end());
127    unsigned NewPrefix = CurPrefix + 1;
128    if (Prefixes.insert(std::make_pair(prfkey, (Twine("prefix_") +
129                                              Twine(NewPrefix)).str())).second)
130      CurPrefix = NewPrefix;
131  }
132
133  // Dump prefixes.
134
135  OS << "/////////\n";
136  OS << "// Prefixes\n\n";
137  OS << "#ifdef PREFIX\n";
138  OS << "#define COMMA ,\n";
139  for (PrefixesT::const_iterator I = Prefixes.begin(), E = Prefixes.end();
140                                  I != E; ++I) {
141    OS << "PREFIX(";
142
143    // Prefix name.
144    OS << I->second;
145
146    // Prefix values.
147    OS << ", {";
148    for (PrefixKeyT::const_iterator PI = I->first.begin(),
149                                    PE = I->first.end(); PI != PE; ++PI) {
150      OS << "\"" << *PI << "\" COMMA ";
151    }
152    OS << "nullptr})\n";
153  }
154  OS << "#undef COMMA\n";
155  OS << "#endif // PREFIX\n\n";
156
157  OS << "/////////\n";
158  OS << "// Groups\n\n";
159  OS << "#ifdef OPTION\n";
160  for (unsigned i = 0, e = Groups.size(); i != e; ++i) {
161    const Record &R = *Groups[i];
162
163    // Start a single option entry.
164    OS << "OPTION(";
165
166    // The option prefix;
167    OS << "nullptr";
168
169    // The option string.
170    OS << ", \"" << R.getValueAsString("Name") << '"';
171
172    // The option identifier name.
173    OS  << ", "<< getOptionName(R);
174
175    // The option kind.
176    OS << ", Group";
177
178    // The containing option group (if any).
179    OS << ", ";
180    if (const DefInit *DI = dyn_cast<DefInit>(R.getValueInit("Group")))
181      OS << getOptionName(*DI->getDef());
182    else
183      OS << "INVALID";
184
185    // The other option arguments (unused for groups).
186    OS << ", INVALID, nullptr, 0, 0";
187
188    // The option help text.
189    if (!isa<UnsetInit>(R.getValueInit("HelpText"))) {
190      OS << ",\n";
191      OS << "       ";
192      write_cstring(OS, R.getValueAsString("HelpText"));
193    } else
194      OS << ", nullptr";
195
196    // The option meta-variable name (unused).
197    OS << ", nullptr)\n";
198  }
199  OS << "\n";
200
201  OS << "//////////\n";
202  OS << "// Options\n\n";
203  for (unsigned i = 0, e = Opts.size(); i != e; ++i) {
204    const Record &R = *Opts[i];
205
206    // Start a single option entry.
207    OS << "OPTION(";
208
209    // The option prefix;
210    std::vector<std::string> prf = R.getValueAsListOfStrings("Prefixes");
211    OS << Prefixes[PrefixKeyT(prf.begin(), prf.end())] << ", ";
212
213    // The option string.
214    write_cstring(OS, R.getValueAsString("Name"));
215
216    // The option identifier name.
217    OS  << ", "<< getOptionName(R);
218
219    // The option kind.
220    OS << ", " << R.getValueAsDef("Kind")->getValueAsString("Name");
221
222    // The containing option group (if any).
223    OS << ", ";
224    const ListInit *GroupFlags = nullptr;
225    if (const DefInit *DI = dyn_cast<DefInit>(R.getValueInit("Group"))) {
226      GroupFlags = DI->getDef()->getValueAsListInit("Flags");
227      OS << getOptionName(*DI->getDef());
228    } else
229      OS << "INVALID";
230
231    // The option alias (if any).
232    OS << ", ";
233    if (const DefInit *DI = dyn_cast<DefInit>(R.getValueInit("Alias")))
234      OS << getOptionName(*DI->getDef());
235    else
236      OS << "INVALID";
237
238    // The option alias arguments (if any).
239    // Emitted as a \0 separated list in a string, e.g. ["foo", "bar"]
240    // would become "foo\0bar\0". Note that the compiler adds an implicit
241    // terminating \0 at the end.
242    OS << ", ";
243    std::vector<std::string> AliasArgs = R.getValueAsListOfStrings("AliasArgs");
244    if (AliasArgs.size() == 0) {
245      OS << "nullptr";
246    } else {
247      OS << "\"";
248      for (size_t i = 0, e = AliasArgs.size(); i != e; ++i)
249        OS << AliasArgs[i] << "\\0";
250      OS << "\"";
251    }
252
253    // The option flags.
254    OS << ", ";
255    int NumFlags = 0;
256    const ListInit *LI = R.getValueAsListInit("Flags");
257    for (Init *I : *LI)
258      OS << (NumFlags++ ? " | " : "")
259         << cast<DefInit>(I)->getDef()->getName();
260    if (GroupFlags) {
261      for (Init *I : *GroupFlags)
262        OS << (NumFlags++ ? " | " : "")
263           << cast<DefInit>(I)->getDef()->getName();
264    }
265    if (NumFlags == 0)
266      OS << '0';
267
268    // The option parameter field.
269    OS << ", " << R.getValueAsInt("NumArgs");
270
271    // The option help text.
272    if (!isa<UnsetInit>(R.getValueInit("HelpText"))) {
273      OS << ",\n";
274      OS << "       ";
275      write_cstring(OS, R.getValueAsString("HelpText"));
276    } else
277      OS << ", nullptr";
278
279    // The option meta-variable name.
280    OS << ", ";
281    if (!isa<UnsetInit>(R.getValueInit("MetaVarName")))
282      write_cstring(OS, R.getValueAsString("MetaVarName"));
283    else
284      OS << "nullptr";
285
286    OS << ")\n";
287  }
288  OS << "#endif // OPTION\n";
289}
290} // end namespace llvm
291