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