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