xref: /freebsd/contrib/llvm-project/llvm/utils/TableGen/OptParserEmitter.cpp (revision 5ca8e32633c4ffbbcd6762e5888b6a4ba0708c6c)
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 <cstring>
17 #include <map>
18 #include <memory>
19 
20 using namespace llvm;
21 
22 static std::string getOptionName(const Record &R) {
23   // Use the record name unless EnumName is defined.
24   if (isa<UnsetInit>(R.getValueInit("EnumName")))
25     return std::string(R.getName());
26 
27   return std::string(R.getValueAsString("EnumName"));
28 }
29 
30 static raw_ostream &write_cstring(raw_ostream &OS, llvm::StringRef Str) {
31   OS << '"';
32   OS.write_escaped(Str);
33   OS << '"';
34   return OS;
35 }
36 
37 static std::string getOptionSpelling(const Record &R, size_t &PrefixLength) {
38   std::vector<StringRef> Prefixes = R.getValueAsListOfStrings("Prefixes");
39   StringRef Name = R.getValueAsString("Name");
40 
41   if (Prefixes.empty()) {
42     PrefixLength = 0;
43     return Name.str();
44   }
45 
46   PrefixLength = Prefixes[0].size();
47   return (Twine(Prefixes[0]) + Twine(Name)).str();
48 }
49 
50 static std::string getOptionSpelling(const Record &R) {
51   size_t PrefixLength;
52   return getOptionSpelling(R, PrefixLength);
53 }
54 
55 static void emitNameUsingSpelling(raw_ostream &OS, const Record &R) {
56   size_t PrefixLength;
57   OS << "llvm::StringLiteral(";
58   write_cstring(
59       OS, StringRef(getOptionSpelling(R, PrefixLength)).substr(PrefixLength));
60   OS << ")";
61 }
62 
63 class MarshallingInfo {
64 public:
65   static constexpr const char *MacroName = "OPTION_WITH_MARSHALLING";
66   const Record &R;
67   bool ShouldAlwaysEmit = false;
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   std::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").value_or(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 static void EmitOptParser(RecordKeeper &Records, raw_ostream &OS) {
216   // Get the option groups and options.
217   const std::vector<Record*> &Groups =
218     Records.getAllDerivedDefinitions("OptionGroup");
219   std::vector<Record*> Opts = Records.getAllDerivedDefinitions("Option");
220 
221   emitSourceFileHeader("Option Parsing Definitions", OS);
222 
223   array_pod_sort(Opts.begin(), Opts.end(), CompareOptionRecords);
224   // Generate prefix groups.
225   typedef SmallVector<SmallString<2>, 2> PrefixKeyT;
226   typedef std::map<PrefixKeyT, std::string> PrefixesT;
227   PrefixesT Prefixes;
228   Prefixes.insert(std::make_pair(PrefixKeyT(), "prefix_0"));
229   unsigned CurPrefix = 0;
230   for (const Record &R : llvm::make_pointee_range(Opts)) {
231     std::vector<StringRef> RPrefixes = R.getValueAsListOfStrings("Prefixes");
232     PrefixKeyT PrefixKey(RPrefixes.begin(), RPrefixes.end());
233     unsigned NewPrefix = CurPrefix + 1;
234     std::string Prefix = (Twine("prefix_") + Twine(NewPrefix)).str();
235     if (Prefixes.insert(std::make_pair(PrefixKey, Prefix)).second)
236       CurPrefix = NewPrefix;
237   }
238 
239   DenseSet<StringRef> PrefixesUnionSet;
240   for (const auto &Prefix : Prefixes)
241     PrefixesUnionSet.insert(Prefix.first.begin(), Prefix.first.end());
242   SmallVector<StringRef> PrefixesUnion(PrefixesUnionSet.begin(),
243                                        PrefixesUnionSet.end());
244   array_pod_sort(PrefixesUnion.begin(), PrefixesUnion.end());
245 
246   // Dump prefixes.
247   OS << "/////////\n";
248   OS << "// Prefixes\n\n";
249   OS << "#ifdef PREFIX\n";
250   OS << "#define COMMA ,\n";
251   for (const auto &Prefix : Prefixes) {
252     OS << "PREFIX(";
253 
254     // Prefix name.
255     OS << Prefix.second;
256 
257     // Prefix values.
258     OS << ", {";
259     for (const auto &PrefixKey : Prefix.first)
260       OS << "llvm::StringLiteral(\"" << PrefixKey << "\") COMMA ";
261     // Append an empty element to avoid ending up with an empty array.
262     OS << "llvm::StringLiteral(\"\")})\n";
263   }
264   OS << "#undef COMMA\n";
265   OS << "#endif // PREFIX\n\n";
266 
267   // Dump prefix unions.
268   OS << "/////////\n";
269   OS << "// Prefix Union\n\n";
270   OS << "#ifdef PREFIX_UNION\n";
271   OS << "#define COMMA ,\n";
272   OS << "PREFIX_UNION({\n";
273   for (const auto &Prefix : PrefixesUnion) {
274     OS << "llvm::StringLiteral(\"" << Prefix << "\") COMMA ";
275   }
276   OS << "llvm::StringLiteral(\"\")})\n";
277   OS << "#undef COMMA\n";
278   OS << "#endif // PREFIX_UNION\n\n";
279 
280   // Dump groups.
281   OS << "/////////\n";
282   OS << "// ValuesCode\n\n";
283   OS << "#ifdef OPTTABLE_VALUES_CODE\n";
284   for (const Record &R : llvm::make_pointee_range(Opts)) {
285     // The option values, if any;
286     if (!isa<UnsetInit>(R.getValueInit("ValuesCode"))) {
287       assert(isa<UnsetInit>(R.getValueInit("Values")) &&
288              "Cannot choose between Values and ValuesCode");
289       OS << "#define VALUES_CODE " << getOptionName(R) << "_Values\n";
290       OS << R.getValueAsString("ValuesCode") << "\n";
291       OS << "#undef VALUES_CODE\n";
292     }
293   }
294   OS << "#endif\n";
295 
296   OS << "/////////\n";
297   OS << "// Groups\n\n";
298   OS << "#ifdef OPTION\n";
299   for (const Record &R : llvm::make_pointee_range(Groups)) {
300     // Start a single option entry.
301     OS << "OPTION(";
302 
303     // The option prefix;
304     OS << "llvm::ArrayRef<llvm::StringLiteral>()";
305 
306     // The option string.
307     OS << ", \"" << R.getValueAsString("Name") << '"';
308 
309     // The option identifier name.
310     OS << ", " << getOptionName(R);
311 
312     // The option kind.
313     OS << ", Group";
314 
315     // The containing option group (if any).
316     OS << ", ";
317     if (const DefInit *DI = dyn_cast<DefInit>(R.getValueInit("Group")))
318       OS << getOptionName(*DI->getDef());
319     else
320       OS << "INVALID";
321 
322     // The other option arguments (unused for groups).
323     OS << ", INVALID, nullptr, 0, 0";
324 
325     // The option help text.
326     if (!isa<UnsetInit>(R.getValueInit("HelpText"))) {
327       OS << ",\n";
328       OS << "       ";
329       write_cstring(OS, R.getValueAsString("HelpText"));
330     } else
331       OS << ", nullptr";
332 
333     // The option meta-variable name (unused).
334     OS << ", nullptr";
335 
336     // The option Values (unused for groups).
337     OS << ", nullptr)\n";
338   }
339   OS << "\n";
340 
341   OS << "//////////\n";
342   OS << "// Options\n\n";
343 
344   auto WriteOptRecordFields = [&](raw_ostream &OS, const Record &R) {
345     // The option prefix;
346     std::vector<StringRef> RPrefixes = R.getValueAsListOfStrings("Prefixes");
347     OS << Prefixes[PrefixKeyT(RPrefixes.begin(), RPrefixes.end())] << ", ";
348 
349     // The option string.
350     emitNameUsingSpelling(OS, R);
351 
352     // The option identifier name.
353     OS << ", " << getOptionName(R);
354 
355     // The option kind.
356     OS << ", " << R.getValueAsDef("Kind")->getValueAsString("Name");
357 
358     // The containing option group (if any).
359     OS << ", ";
360     const ListInit *GroupFlags = nullptr;
361     if (const DefInit *DI = dyn_cast<DefInit>(R.getValueInit("Group"))) {
362       GroupFlags = DI->getDef()->getValueAsListInit("Flags");
363       OS << getOptionName(*DI->getDef());
364     } else
365       OS << "INVALID";
366 
367     // The option alias (if any).
368     OS << ", ";
369     if (const DefInit *DI = dyn_cast<DefInit>(R.getValueInit("Alias")))
370       OS << getOptionName(*DI->getDef());
371     else
372       OS << "INVALID";
373 
374     // The option alias arguments (if any).
375     // Emitted as a \0 separated list in a string, e.g. ["foo", "bar"]
376     // would become "foo\0bar\0". Note that the compiler adds an implicit
377     // terminating \0 at the end.
378     OS << ", ";
379     std::vector<StringRef> AliasArgs = R.getValueAsListOfStrings("AliasArgs");
380     if (AliasArgs.size() == 0) {
381       OS << "nullptr";
382     } else {
383       OS << "\"";
384       for (StringRef AliasArg : AliasArgs)
385         OS << AliasArg << "\\0";
386       OS << "\"";
387     }
388 
389     // The option flags.
390     OS << ", ";
391     int NumFlags = 0;
392     const ListInit *LI = R.getValueAsListInit("Flags");
393     for (Init *I : *LI)
394       OS << (NumFlags++ ? " | " : "") << cast<DefInit>(I)->getDef()->getName();
395     if (GroupFlags) {
396       for (Init *I : *GroupFlags)
397         OS << (NumFlags++ ? " | " : "")
398            << cast<DefInit>(I)->getDef()->getName();
399     }
400     if (NumFlags == 0)
401       OS << '0';
402 
403     // The option parameter field.
404     OS << ", " << R.getValueAsInt("NumArgs");
405 
406     // The option help text.
407     if (!isa<UnsetInit>(R.getValueInit("HelpText"))) {
408       OS << ",\n";
409       OS << "       ";
410       write_cstring(OS, R.getValueAsString("HelpText"));
411     } else
412       OS << ", nullptr";
413 
414     // The option meta-variable name.
415     OS << ", ";
416     if (!isa<UnsetInit>(R.getValueInit("MetaVarName")))
417       write_cstring(OS, R.getValueAsString("MetaVarName"));
418     else
419       OS << "nullptr";
420 
421     // The option Values. Used for shell autocompletion.
422     OS << ", ";
423     if (!isa<UnsetInit>(R.getValueInit("Values")))
424       write_cstring(OS, R.getValueAsString("Values"));
425     else if (!isa<UnsetInit>(R.getValueInit("ValuesCode"))) {
426       OS << getOptionName(R) << "_Values";
427     }
428     else
429       OS << "nullptr";
430   };
431 
432   auto IsMarshallingOption = [](const Record &R) {
433     return !isa<UnsetInit>(R.getValueInit("KeyPath")) &&
434            !R.getValueAsString("KeyPath").empty();
435   };
436 
437   std::vector<const Record *> OptsWithMarshalling;
438   for (const Record &R : llvm::make_pointee_range(Opts)) {
439     // Start a single option entry.
440     OS << "OPTION(";
441     WriteOptRecordFields(OS, R);
442     OS << ")\n";
443     if (IsMarshallingOption(R))
444       OptsWithMarshalling.push_back(&R);
445   }
446   OS << "#endif // OPTION\n";
447 
448   auto CmpMarshallingOpts = [](const Record *const *A, const Record *const *B) {
449     unsigned AID = (*A)->getID();
450     unsigned BID = (*B)->getID();
451 
452     if (AID < BID)
453       return -1;
454     if (AID > BID)
455       return 1;
456     return 0;
457   };
458   // The RecordKeeper stores records (options) in lexicographical order, and we
459   // have reordered the options again when generating prefix groups. We need to
460   // restore the original definition order of options with marshalling to honor
461   // the topology of the dependency graph implied by `DefaultAnyOf`.
462   array_pod_sort(OptsWithMarshalling.begin(), OptsWithMarshalling.end(),
463                  CmpMarshallingOpts);
464 
465   std::vector<MarshallingInfo> MarshallingInfos;
466   MarshallingInfos.reserve(OptsWithMarshalling.size());
467   for (const auto *R : OptsWithMarshalling)
468     MarshallingInfos.push_back(createMarshallingInfo(*R));
469 
470   for (const auto &MI : MarshallingInfos) {
471     OS << "#ifdef " << MI.getMacroName() << "\n";
472     OS << MI.getMacroName() << "(";
473     WriteOptRecordFields(OS, MI.R);
474     OS << ", ";
475     MI.emit(OS);
476     OS << ")\n";
477     OS << "#endif // " << MI.getMacroName() << "\n";
478   }
479 
480   OS << "\n";
481   OS << "#ifdef SIMPLE_ENUM_VALUE_TABLE";
482   OS << "\n";
483   OS << MarshallingInfo::ValueTablePreamble;
484   std::vector<StringRef> ValueTableNames;
485   for (const auto &MI : MarshallingInfos)
486     if (auto MaybeValueTableName = MI.emitValueTable(OS))
487       ValueTableNames.push_back(*MaybeValueTableName);
488 
489   OS << MarshallingInfo::ValueTablesDecl << "{";
490   for (auto ValueTableName : ValueTableNames)
491     OS << "{" << ValueTableName << ", std::size(" << ValueTableName << ")},\n";
492   OS << "};\n";
493   OS << "static const unsigned SimpleEnumValueTablesSize = "
494         "std::size(SimpleEnumValueTables);\n";
495 
496   OS << "#endif // SIMPLE_ENUM_VALUE_TABLE\n";
497   OS << "\n";
498 
499   OS << "\n";
500 }
501 
502 static TableGen::Emitter::Opt X("gen-opt-parser-defs", EmitOptParser,
503                                 "Generate option definitions");
504