1//===- OptParserEmitter.cpp - Table Driven Command Line Parsing -----------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "OptEmitter.h"
10#include "llvm/ADT/STLExtras.h"
11#include "llvm/ADT/SmallString.h"
12#include "llvm/ADT/Twine.h"
13#include "llvm/Support/raw_ostream.h"
14#include "llvm/TableGen/Record.h"
15#include "llvm/TableGen/TableGenBackend.h"
16#include <cctype>
17#include <cstring>
18#include <map>
19#include <memory>
20
21using namespace llvm;
22
23static const std::string getOptionName(const Record &R) {
24  // Use the record name unless EnumName is defined.
25  if (isa<UnsetInit>(R.getValueInit("EnumName")))
26    return std::string(R.getName());
27
28  return std::string(R.getValueAsString("EnumName"));
29}
30
31static raw_ostream &write_cstring(raw_ostream &OS, llvm::StringRef Str) {
32  OS << '"';
33  OS.write_escaped(Str);
34  OS << '"';
35  return OS;
36}
37
38static const std::string getOptionSpelling(const Record &R,
39                                           size_t &PrefixLength) {
40  std::vector<StringRef> Prefixes = R.getValueAsListOfStrings("Prefixes");
41  StringRef Name = R.getValueAsString("Name");
42  if (Prefixes.empty()) {
43    PrefixLength = 0;
44    return Name.str();
45  }
46  PrefixLength = Prefixes[0].size();
47  return (Twine(Prefixes[0]) + Twine(Name)).str();
48}
49
50static const std::string getOptionSpelling(const Record &R) {
51  size_t PrefixLength;
52  return getOptionSpelling(R, PrefixLength);
53}
54
55static void emitNameUsingSpelling(raw_ostream &OS, const Record &R) {
56  size_t PrefixLength;
57  OS << "&";
58  write_cstring(OS, StringRef(getOptionSpelling(R, PrefixLength)));
59  OS << "[" << PrefixLength << "]";
60}
61
62class MarshallingKindInfo {
63public:
64  const Record &R;
65  const char *MacroName;
66  bool ShouldAlwaysEmit;
67  StringRef KeyPath;
68  StringRef DefaultValue;
69  StringRef NormalizedValuesScope;
70
71  void emit(raw_ostream &OS) const {
72    write_cstring(OS, StringRef(getOptionSpelling(R)));
73    OS << ", ";
74    OS << ShouldAlwaysEmit;
75    OS << ", ";
76    OS << KeyPath;
77    OS << ", ";
78    emitScopedNormalizedValue(OS, DefaultValue);
79    OS << ", ";
80    emitSpecific(OS);
81  }
82
83  virtual Optional<StringRef> emitValueTable(raw_ostream &OS) const {
84    return None;
85  }
86
87  virtual ~MarshallingKindInfo() = default;
88
89  static std::unique_ptr<MarshallingKindInfo> create(const Record &R);
90
91protected:
92  void emitScopedNormalizedValue(raw_ostream &OS,
93                                 StringRef NormalizedValue) const {
94    if (!NormalizedValuesScope.empty())
95      OS << NormalizedValuesScope << "::";
96    OS << NormalizedValue;
97  }
98
99  virtual void emitSpecific(raw_ostream &OS) const = 0;
100  MarshallingKindInfo(const Record &R, const char *MacroName)
101      : R(R), MacroName(MacroName) {}
102};
103
104class MarshallingFlagInfo final : public MarshallingKindInfo {
105public:
106  bool IsPositive;
107
108  void emitSpecific(raw_ostream &OS) const override { OS << IsPositive; }
109
110  static std::unique_ptr<MarshallingKindInfo> create(const Record &R) {
111    std::unique_ptr<MarshallingFlagInfo> Ret(new MarshallingFlagInfo(R));
112    Ret->IsPositive = R.getValueAsBit("IsPositive");
113    return Ret;
114  }
115
116private:
117  MarshallingFlagInfo(const Record &R)
118      : MarshallingKindInfo(R, "OPTION_WITH_MARSHALLING_FLAG") {}
119};
120
121class MarshallingStringInfo final : public MarshallingKindInfo {
122public:
123  StringRef NormalizerRetTy;
124  StringRef Normalizer;
125  StringRef Denormalizer;
126  int TableIndex = -1;
127  std::vector<StringRef> Values;
128  std::vector<StringRef> NormalizedValues;
129  std::string ValueTableName;
130
131  static constexpr const char *ValueTablePreamble = R"(
132struct SimpleEnumValue {
133  const char *Name;
134  unsigned Value;
135};
136
137struct SimpleEnumValueTable {
138  const SimpleEnumValue *Table;
139  unsigned Size;
140};
141)";
142
143  static constexpr const char *ValueTablesDecl =
144      "static const SimpleEnumValueTable SimpleEnumValueTables[] = ";
145
146  void emitSpecific(raw_ostream &OS) const override {
147    emitScopedNormalizedValue(OS, NormalizerRetTy);
148    OS << ", ";
149    OS << Normalizer;
150    OS << ", ";
151    OS << Denormalizer;
152    OS << ", ";
153    OS << TableIndex;
154  }
155
156  Optional<StringRef> emitValueTable(raw_ostream &OS) const override {
157    if (TableIndex == -1)
158      return {};
159    OS << "static const SimpleEnumValue " << ValueTableName << "[] = {\n";
160    for (unsigned I = 0, E = Values.size(); I != E; ++I) {
161      OS << "{";
162      write_cstring(OS, Values[I]);
163      OS << ",";
164      OS << "static_cast<unsigned>(";
165      emitScopedNormalizedValue(OS, NormalizedValues[I]);
166      OS << ")},";
167    }
168    OS << "};\n";
169    return StringRef(ValueTableName);
170  }
171
172  static std::unique_ptr<MarshallingKindInfo> create(const Record &R) {
173    assert(!isa<UnsetInit>(R.getValueInit("NormalizerRetTy")) &&
174           "String options must have a type");
175
176    std::unique_ptr<MarshallingStringInfo> Ret(new MarshallingStringInfo(R));
177    Ret->NormalizerRetTy = R.getValueAsString("NormalizerRetTy");
178
179    Ret->Normalizer = R.getValueAsString("Normalizer");
180    Ret->Denormalizer = R.getValueAsString("Denormalizer");
181
182    if (!isa<UnsetInit>(R.getValueInit("NormalizedValues"))) {
183      assert(!isa<UnsetInit>(R.getValueInit("Values")) &&
184             "Cannot provide normalized values for value-less options");
185      Ret->TableIndex = NextTableIndex++;
186      Ret->NormalizedValues = R.getValueAsListOfStrings("NormalizedValues");
187      Ret->Values.reserve(Ret->NormalizedValues.size());
188      Ret->ValueTableName = getOptionName(R) + "ValueTable";
189
190      StringRef ValuesStr = R.getValueAsString("Values");
191      for (;;) {
192        size_t Idx = ValuesStr.find(',');
193        if (Idx == StringRef::npos)
194          break;
195        if (Idx > 0)
196          Ret->Values.push_back(ValuesStr.slice(0, Idx));
197        ValuesStr = ValuesStr.slice(Idx + 1, StringRef::npos);
198      }
199      if (!ValuesStr.empty())
200        Ret->Values.push_back(ValuesStr);
201
202      assert(Ret->Values.size() == Ret->NormalizedValues.size() &&
203             "The number of normalized values doesn't match the number of "
204             "values");
205    }
206
207    return Ret;
208  }
209
210private:
211  MarshallingStringInfo(const Record &R)
212      : MarshallingKindInfo(R, "OPTION_WITH_MARSHALLING_STRING") {}
213
214  static size_t NextTableIndex;
215};
216
217size_t MarshallingStringInfo::NextTableIndex = 0;
218
219std::unique_ptr<MarshallingKindInfo>
220MarshallingKindInfo::create(const Record &R) {
221  assert(!isa<UnsetInit>(R.getValueInit("KeyPath")) &&
222         !isa<UnsetInit>(R.getValueInit("DefaultValue")) &&
223         "Must provide at least a key-path and a default value for emitting "
224         "marshalling information");
225
226  std::unique_ptr<MarshallingKindInfo> Ret = nullptr;
227  StringRef MarshallingKindStr = R.getValueAsString("MarshallingKind");
228
229  if (MarshallingKindStr == "flag")
230    Ret = MarshallingFlagInfo::create(R);
231  else if (MarshallingKindStr == "string")
232    Ret = MarshallingStringInfo::create(R);
233
234  Ret->ShouldAlwaysEmit = R.getValueAsBit("ShouldAlwaysEmit");
235  Ret->KeyPath = R.getValueAsString("KeyPath");
236  Ret->DefaultValue = R.getValueAsString("DefaultValue");
237  if (!isa<UnsetInit>(R.getValueInit("NormalizedValuesScope")))
238    Ret->NormalizedValuesScope = R.getValueAsString("NormalizedValuesScope");
239  return Ret;
240}
241
242/// OptParserEmitter - This tablegen backend takes an input .td file
243/// describing a list of options and emits a data structure for parsing and
244/// working with those options when given an input command line.
245namespace llvm {
246void EmitOptParser(RecordKeeper &Records, raw_ostream &OS) {
247  // Get the option groups and options.
248  const std::vector<Record*> &Groups =
249    Records.getAllDerivedDefinitions("OptionGroup");
250  std::vector<Record*> Opts = Records.getAllDerivedDefinitions("Option");
251
252  emitSourceFileHeader("Option Parsing Definitions", OS);
253
254  array_pod_sort(Opts.begin(), Opts.end(), CompareOptionRecords);
255  // Generate prefix groups.
256  typedef SmallVector<SmallString<2>, 2> PrefixKeyT;
257  typedef std::map<PrefixKeyT, std::string> PrefixesT;
258  PrefixesT Prefixes;
259  Prefixes.insert(std::make_pair(PrefixKeyT(), "prefix_0"));
260  unsigned CurPrefix = 0;
261  for (unsigned i = 0, e = Opts.size(); i != e; ++i) {
262    const Record &R = *Opts[i];
263    std::vector<StringRef> prf = R.getValueAsListOfStrings("Prefixes");
264    PrefixKeyT prfkey(prf.begin(), prf.end());
265    unsigned NewPrefix = CurPrefix + 1;
266    if (Prefixes.insert(std::make_pair(prfkey, (Twine("prefix_") +
267                                              Twine(NewPrefix)).str())).second)
268      CurPrefix = NewPrefix;
269  }
270
271  // Dump prefixes.
272
273  OS << "/////////\n";
274  OS << "// Prefixes\n\n";
275  OS << "#ifdef PREFIX\n";
276  OS << "#define COMMA ,\n";
277  for (PrefixesT::const_iterator I = Prefixes.begin(), E = Prefixes.end();
278                                  I != E; ++I) {
279    OS << "PREFIX(";
280
281    // Prefix name.
282    OS << I->second;
283
284    // Prefix values.
285    OS << ", {";
286    for (PrefixKeyT::const_iterator PI = I->first.begin(),
287                                    PE = I->first.end(); PI != PE; ++PI) {
288      OS << "\"" << *PI << "\" COMMA ";
289    }
290    OS << "nullptr})\n";
291  }
292  OS << "#undef COMMA\n";
293  OS << "#endif // PREFIX\n\n";
294
295  OS << "/////////\n";
296  OS << "// Groups\n\n";
297  OS << "#ifdef OPTION\n";
298  for (unsigned i = 0, e = Groups.size(); i != e; ++i) {
299    const Record &R = *Groups[i];
300
301    // Start a single option entry.
302    OS << "OPTION(";
303
304    // The option prefix;
305    OS << "nullptr";
306
307    // The option string.
308    OS << ", \"" << R.getValueAsString("Name") << '"';
309
310    // The option identifier name.
311    OS << ", " << getOptionName(R);
312
313    // The option kind.
314    OS << ", Group";
315
316    // The containing option group (if any).
317    OS << ", ";
318    if (const DefInit *DI = dyn_cast<DefInit>(R.getValueInit("Group")))
319      OS << getOptionName(*DI->getDef());
320    else
321      OS << "INVALID";
322
323    // The other option arguments (unused for groups).
324    OS << ", INVALID, nullptr, 0, 0";
325
326    // The option help text.
327    if (!isa<UnsetInit>(R.getValueInit("HelpText"))) {
328      OS << ",\n";
329      OS << "       ";
330      write_cstring(OS, R.getValueAsString("HelpText"));
331    } else
332      OS << ", nullptr";
333
334    // The option meta-variable name (unused).
335    OS << ", nullptr";
336
337    // The option Values (unused for groups).
338    OS << ", nullptr)\n";
339  }
340  OS << "\n";
341
342  OS << "//////////\n";
343  OS << "// Options\n\n";
344
345  auto WriteOptRecordFields = [&](raw_ostream &OS, const Record &R) {
346    // The option prefix;
347    std::vector<StringRef> prf = R.getValueAsListOfStrings("Prefixes");
348    OS << Prefixes[PrefixKeyT(prf.begin(), prf.end())] << ", ";
349
350    // The option string.
351    emitNameUsingSpelling(OS, R);
352
353    // The option identifier name.
354    OS << ", " << getOptionName(R);
355
356    // The option kind.
357    OS << ", " << R.getValueAsDef("Kind")->getValueAsString("Name");
358
359    // The containing option group (if any).
360    OS << ", ";
361    const ListInit *GroupFlags = nullptr;
362    if (const DefInit *DI = dyn_cast<DefInit>(R.getValueInit("Group"))) {
363      GroupFlags = DI->getDef()->getValueAsListInit("Flags");
364      OS << getOptionName(*DI->getDef());
365    } else
366      OS << "INVALID";
367
368    // The option alias (if any).
369    OS << ", ";
370    if (const DefInit *DI = dyn_cast<DefInit>(R.getValueInit("Alias")))
371      OS << getOptionName(*DI->getDef());
372    else
373      OS << "INVALID";
374
375    // The option alias arguments (if any).
376    // Emitted as a \0 separated list in a string, e.g. ["foo", "bar"]
377    // would become "foo\0bar\0". Note that the compiler adds an implicit
378    // terminating \0 at the end.
379    OS << ", ";
380    std::vector<StringRef> AliasArgs = R.getValueAsListOfStrings("AliasArgs");
381    if (AliasArgs.size() == 0) {
382      OS << "nullptr";
383    } else {
384      OS << "\"";
385      for (size_t i = 0, e = AliasArgs.size(); i != e; ++i)
386        OS << AliasArgs[i] << "\\0";
387      OS << "\"";
388    }
389
390    // The option flags.
391    OS << ", ";
392    int NumFlags = 0;
393    const ListInit *LI = R.getValueAsListInit("Flags");
394    for (Init *I : *LI)
395      OS << (NumFlags++ ? " | " : "") << cast<DefInit>(I)->getDef()->getName();
396    if (GroupFlags) {
397      for (Init *I : *GroupFlags)
398        OS << (NumFlags++ ? " | " : "")
399           << cast<DefInit>(I)->getDef()->getName();
400    }
401    if (NumFlags == 0)
402      OS << '0';
403
404    // The option parameter field.
405    OS << ", " << R.getValueAsInt("NumArgs");
406
407    // The option help text.
408    if (!isa<UnsetInit>(R.getValueInit("HelpText"))) {
409      OS << ",\n";
410      OS << "       ";
411      write_cstring(OS, R.getValueAsString("HelpText"));
412    } else
413      OS << ", nullptr";
414
415    // The option meta-variable name.
416    OS << ", ";
417    if (!isa<UnsetInit>(R.getValueInit("MetaVarName")))
418      write_cstring(OS, R.getValueAsString("MetaVarName"));
419    else
420      OS << "nullptr";
421
422    // The option Values. Used for shell autocompletion.
423    OS << ", ";
424    if (!isa<UnsetInit>(R.getValueInit("Values")))
425      write_cstring(OS, R.getValueAsString("Values"));
426    else
427      OS << "nullptr";
428  };
429
430  std::vector<std::unique_ptr<MarshallingKindInfo>> OptsWithMarshalling;
431  for (unsigned I = 0, E = Opts.size(); I != E; ++I) {
432    const Record &R = *Opts[I];
433
434    // Start a single option entry.
435    OS << "OPTION(";
436    WriteOptRecordFields(OS, R);
437    OS << ")\n";
438    if (!isa<UnsetInit>(R.getValueInit("MarshallingKind")))
439      OptsWithMarshalling.push_back(MarshallingKindInfo::create(R));
440  }
441  OS << "#endif // OPTION\n";
442
443  for (const auto &KindInfo : OptsWithMarshalling) {
444    OS << "#ifdef " << KindInfo->MacroName << "\n";
445    OS << KindInfo->MacroName << "(";
446    WriteOptRecordFields(OS, KindInfo->R);
447    OS << ", ";
448    KindInfo->emit(OS);
449    OS << ")\n";
450    OS << "#endif // " << KindInfo->MacroName << "\n";
451  }
452
453  OS << "\n";
454  OS << "#ifdef SIMPLE_ENUM_VALUE_TABLE";
455  OS << "\n";
456  OS << MarshallingStringInfo::ValueTablePreamble;
457  std::vector<StringRef> ValueTableNames;
458  for (const auto &KindInfo : OptsWithMarshalling)
459    if (auto MaybeValueTableName = KindInfo->emitValueTable(OS))
460      ValueTableNames.push_back(*MaybeValueTableName);
461
462  OS << MarshallingStringInfo::ValueTablesDecl << "{";
463  for (auto ValueTableName : ValueTableNames)
464    OS << "{" << ValueTableName << ", sizeof(" << ValueTableName
465       << ") / sizeof(SimpleEnumValue)"
466       << "},\n";
467  OS << "};\n";
468  OS << "static const unsigned SimpleEnumValueTablesSize = "
469        "sizeof(SimpleEnumValueTables) / sizeof(SimpleEnumValueTable);\n";
470
471  OS << "#endif // SIMPLE_ENUM_VALUE_TABLE\n";
472  OS << "\n";
473
474  OS << "\n";
475  OS << "#ifdef OPTTABLE_ARG_INIT\n";
476  OS << "//////////\n";
477  OS << "// Option Values\n\n";
478  for (unsigned I = 0, E = Opts.size(); I != E; ++I) {
479    const Record &R = *Opts[I];
480    if (isa<UnsetInit>(R.getValueInit("ValuesCode")))
481      continue;
482    OS << "{\n";
483    OS << "bool ValuesWereAdded;\n";
484    OS << R.getValueAsString("ValuesCode");
485    OS << "\n";
486    for (StringRef Prefix : R.getValueAsListOfStrings("Prefixes")) {
487      OS << "ValuesWereAdded = Opt.addValues(";
488      std::string S(Prefix);
489      S += R.getValueAsString("Name");
490      write_cstring(OS, S);
491      OS << ", Values);\n";
492      OS << "(void)ValuesWereAdded;\n";
493      OS << "assert(ValuesWereAdded && \"Couldn't add values to "
494            "OptTable!\");\n";
495    }
496    OS << "}\n";
497  }
498  OS << "\n";
499  OS << "#endif // OPTTABLE_ARG_INIT\n";
500}
501} // end namespace llvm
502