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