xref: /freebsd/contrib/llvm-project/llvm/utils/TableGen/OptParserEmitter.cpp (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
10b57cec5SDimitry Andric //===- OptParserEmitter.cpp - Table Driven Command Line Parsing -----------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
9480093f4SDimitry Andric #include "OptEmitter.h"
100b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h"
110b57cec5SDimitry Andric #include "llvm/ADT/SmallString.h"
120b57cec5SDimitry Andric #include "llvm/ADT/Twine.h"
135ffd83dbSDimitry Andric #include "llvm/Support/raw_ostream.h"
140b57cec5SDimitry Andric #include "llvm/TableGen/Record.h"
150b57cec5SDimitry Andric #include "llvm/TableGen/TableGenBackend.h"
160b57cec5SDimitry Andric #include <cstring>
170b57cec5SDimitry Andric #include <map>
185ffd83dbSDimitry Andric #include <memory>
190b57cec5SDimitry Andric 
200b57cec5SDimitry Andric using namespace llvm;
210b57cec5SDimitry Andric 
22e8d8bef9SDimitry Andric static std::string getOptionName(const Record &R) {
230b57cec5SDimitry Andric   // Use the record name unless EnumName is defined.
240b57cec5SDimitry Andric   if (isa<UnsetInit>(R.getValueInit("EnumName")))
255ffd83dbSDimitry Andric     return std::string(R.getName());
260b57cec5SDimitry Andric 
275ffd83dbSDimitry Andric   return std::string(R.getValueAsString("EnumName"));
280b57cec5SDimitry Andric }
290b57cec5SDimitry Andric 
300b57cec5SDimitry Andric static raw_ostream &write_cstring(raw_ostream &OS, llvm::StringRef Str) {
310b57cec5SDimitry Andric   OS << '"';
320b57cec5SDimitry Andric   OS.write_escaped(Str);
330b57cec5SDimitry Andric   OS << '"';
340b57cec5SDimitry Andric   return OS;
350b57cec5SDimitry Andric }
360b57cec5SDimitry Andric 
37*5f757f3fSDimitry Andric static std::string getOptionPrefixedName(const Record &R) {
385ffd83dbSDimitry Andric   std::vector<StringRef> Prefixes = R.getValueAsListOfStrings("Prefixes");
395ffd83dbSDimitry Andric   StringRef Name = R.getValueAsString("Name");
40e8d8bef9SDimitry Andric 
41*5f757f3fSDimitry Andric   if (Prefixes.empty())
425ffd83dbSDimitry Andric     return Name.str();
43e8d8bef9SDimitry Andric 
44*5f757f3fSDimitry Andric   return (Prefixes[0] + Twine(Name)).str();
455ffd83dbSDimitry Andric }
465ffd83dbSDimitry Andric 
47e8d8bef9SDimitry Andric class MarshallingInfo {
485ffd83dbSDimitry Andric public:
49e8d8bef9SDimitry Andric   static constexpr const char *MacroName = "OPTION_WITH_MARSHALLING";
505ffd83dbSDimitry Andric   const Record &R;
5106c3fb27SDimitry Andric   bool ShouldAlwaysEmit = false;
52e8d8bef9SDimitry Andric   StringRef MacroPrefix;
535ffd83dbSDimitry Andric   StringRef KeyPath;
545ffd83dbSDimitry Andric   StringRef DefaultValue;
555ffd83dbSDimitry Andric   StringRef NormalizedValuesScope;
56e8d8bef9SDimitry Andric   StringRef ImpliedCheck;
57e8d8bef9SDimitry Andric   StringRef ImpliedValue;
58e8d8bef9SDimitry Andric   StringRef ShouldParse;
595ffd83dbSDimitry Andric   StringRef Normalizer;
605ffd83dbSDimitry Andric   StringRef Denormalizer;
61e8d8bef9SDimitry Andric   StringRef ValueMerger;
62e8d8bef9SDimitry Andric   StringRef ValueExtractor;
635ffd83dbSDimitry Andric   int TableIndex = -1;
645ffd83dbSDimitry Andric   std::vector<StringRef> Values;
655ffd83dbSDimitry Andric   std::vector<StringRef> NormalizedValues;
665ffd83dbSDimitry Andric   std::string ValueTableName;
675ffd83dbSDimitry Andric 
68e8d8bef9SDimitry Andric   static size_t NextTableIndex;
69e8d8bef9SDimitry Andric 
705ffd83dbSDimitry Andric   static constexpr const char *ValueTablePreamble = R"(
715ffd83dbSDimitry Andric struct SimpleEnumValue {
725ffd83dbSDimitry Andric   const char *Name;
735ffd83dbSDimitry Andric   unsigned Value;
745ffd83dbSDimitry Andric };
755ffd83dbSDimitry Andric 
765ffd83dbSDimitry Andric struct SimpleEnumValueTable {
775ffd83dbSDimitry Andric   const SimpleEnumValue *Table;
785ffd83dbSDimitry Andric   unsigned Size;
795ffd83dbSDimitry Andric };
805ffd83dbSDimitry Andric )";
815ffd83dbSDimitry Andric 
825ffd83dbSDimitry Andric   static constexpr const char *ValueTablesDecl =
835ffd83dbSDimitry Andric       "static const SimpleEnumValueTable SimpleEnumValueTables[] = ";
845ffd83dbSDimitry Andric 
85e8d8bef9SDimitry Andric   MarshallingInfo(const Record &R) : R(R) {}
86e8d8bef9SDimitry Andric 
87e8d8bef9SDimitry Andric   std::string getMacroName() const {
88e8d8bef9SDimitry Andric     return (MacroPrefix + MarshallingInfo::MacroName).str();
89e8d8bef9SDimitry Andric   }
90e8d8bef9SDimitry Andric 
91e8d8bef9SDimitry Andric   void emit(raw_ostream &OS) const {
92e8d8bef9SDimitry Andric     OS << ShouldParse;
93e8d8bef9SDimitry Andric     OS << ", ";
94e8d8bef9SDimitry Andric     OS << ShouldAlwaysEmit;
95e8d8bef9SDimitry Andric     OS << ", ";
96e8d8bef9SDimitry Andric     OS << KeyPath;
97e8d8bef9SDimitry Andric     OS << ", ";
98e8d8bef9SDimitry Andric     emitScopedNormalizedValue(OS, DefaultValue);
99e8d8bef9SDimitry Andric     OS << ", ";
100e8d8bef9SDimitry Andric     OS << ImpliedCheck;
101e8d8bef9SDimitry Andric     OS << ", ";
102e8d8bef9SDimitry Andric     emitScopedNormalizedValue(OS, ImpliedValue);
1035ffd83dbSDimitry Andric     OS << ", ";
1045ffd83dbSDimitry Andric     OS << Normalizer;
1055ffd83dbSDimitry Andric     OS << ", ";
1065ffd83dbSDimitry Andric     OS << Denormalizer;
1075ffd83dbSDimitry Andric     OS << ", ";
108e8d8bef9SDimitry Andric     OS << ValueMerger;
109e8d8bef9SDimitry Andric     OS << ", ";
110e8d8bef9SDimitry Andric     OS << ValueExtractor;
111e8d8bef9SDimitry Andric     OS << ", ";
1125ffd83dbSDimitry Andric     OS << TableIndex;
1135ffd83dbSDimitry Andric   }
1145ffd83dbSDimitry Andric 
115bdd1243dSDimitry Andric   std::optional<StringRef> emitValueTable(raw_ostream &OS) const {
1165ffd83dbSDimitry Andric     if (TableIndex == -1)
1175ffd83dbSDimitry Andric       return {};
1185ffd83dbSDimitry Andric     OS << "static const SimpleEnumValue " << ValueTableName << "[] = {\n";
1195ffd83dbSDimitry Andric     for (unsigned I = 0, E = Values.size(); I != E; ++I) {
1205ffd83dbSDimitry Andric       OS << "{";
1215ffd83dbSDimitry Andric       write_cstring(OS, Values[I]);
1225ffd83dbSDimitry Andric       OS << ",";
1235ffd83dbSDimitry Andric       OS << "static_cast<unsigned>(";
1245ffd83dbSDimitry Andric       emitScopedNormalizedValue(OS, NormalizedValues[I]);
1255ffd83dbSDimitry Andric       OS << ")},";
1265ffd83dbSDimitry Andric     }
1275ffd83dbSDimitry Andric     OS << "};\n";
1285ffd83dbSDimitry Andric     return StringRef(ValueTableName);
1295ffd83dbSDimitry Andric   }
1305ffd83dbSDimitry Andric 
131e8d8bef9SDimitry Andric private:
132e8d8bef9SDimitry Andric   void emitScopedNormalizedValue(raw_ostream &OS,
133e8d8bef9SDimitry Andric                                  StringRef NormalizedValue) const {
134e8d8bef9SDimitry Andric     if (!NormalizedValuesScope.empty())
135e8d8bef9SDimitry Andric       OS << NormalizedValuesScope << "::";
136e8d8bef9SDimitry Andric     OS << NormalizedValue;
137e8d8bef9SDimitry Andric   }
138e8d8bef9SDimitry Andric };
1395ffd83dbSDimitry Andric 
140e8d8bef9SDimitry Andric size_t MarshallingInfo::NextTableIndex = 0;
1415ffd83dbSDimitry Andric 
142e8d8bef9SDimitry Andric static MarshallingInfo createMarshallingInfo(const Record &R) {
143e8d8bef9SDimitry Andric   assert(!isa<UnsetInit>(R.getValueInit("KeyPath")) &&
144e8d8bef9SDimitry Andric          !isa<UnsetInit>(R.getValueInit("DefaultValue")) &&
145e8d8bef9SDimitry Andric          !isa<UnsetInit>(R.getValueInit("ValueMerger")) &&
146e8d8bef9SDimitry Andric          "MarshallingInfo must have a provide a keypath, default value and a "
147e8d8bef9SDimitry Andric          "value merger");
148e8d8bef9SDimitry Andric 
149e8d8bef9SDimitry Andric   MarshallingInfo Ret(R);
150e8d8bef9SDimitry Andric 
151e8d8bef9SDimitry Andric   Ret.ShouldAlwaysEmit = R.getValueAsBit("ShouldAlwaysEmit");
152e8d8bef9SDimitry Andric   Ret.MacroPrefix = R.getValueAsString("MacroPrefix");
153e8d8bef9SDimitry Andric   Ret.KeyPath = R.getValueAsString("KeyPath");
154e8d8bef9SDimitry Andric   Ret.DefaultValue = R.getValueAsString("DefaultValue");
155e8d8bef9SDimitry Andric   Ret.NormalizedValuesScope = R.getValueAsString("NormalizedValuesScope");
156e8d8bef9SDimitry Andric   Ret.ImpliedCheck = R.getValueAsString("ImpliedCheck");
157e8d8bef9SDimitry Andric   Ret.ImpliedValue =
15881ad6265SDimitry Andric       R.getValueAsOptionalString("ImpliedValue").value_or(Ret.DefaultValue);
159e8d8bef9SDimitry Andric 
160e8d8bef9SDimitry Andric   Ret.ShouldParse = R.getValueAsString("ShouldParse");
161e8d8bef9SDimitry Andric   Ret.Normalizer = R.getValueAsString("Normalizer");
162e8d8bef9SDimitry Andric   Ret.Denormalizer = R.getValueAsString("Denormalizer");
163e8d8bef9SDimitry Andric   Ret.ValueMerger = R.getValueAsString("ValueMerger");
164e8d8bef9SDimitry Andric   Ret.ValueExtractor = R.getValueAsString("ValueExtractor");
1655ffd83dbSDimitry Andric 
1665ffd83dbSDimitry Andric   if (!isa<UnsetInit>(R.getValueInit("NormalizedValues"))) {
1675ffd83dbSDimitry Andric     assert(!isa<UnsetInit>(R.getValueInit("Values")) &&
1685ffd83dbSDimitry Andric            "Cannot provide normalized values for value-less options");
169e8d8bef9SDimitry Andric     Ret.TableIndex = MarshallingInfo::NextTableIndex++;
170e8d8bef9SDimitry Andric     Ret.NormalizedValues = R.getValueAsListOfStrings("NormalizedValues");
171e8d8bef9SDimitry Andric     Ret.Values.reserve(Ret.NormalizedValues.size());
172e8d8bef9SDimitry Andric     Ret.ValueTableName = getOptionName(R) + "ValueTable";
1735ffd83dbSDimitry Andric 
1745ffd83dbSDimitry Andric     StringRef ValuesStr = R.getValueAsString("Values");
1755ffd83dbSDimitry Andric     for (;;) {
1765ffd83dbSDimitry Andric       size_t Idx = ValuesStr.find(',');
1775ffd83dbSDimitry Andric       if (Idx == StringRef::npos)
1785ffd83dbSDimitry Andric         break;
1795ffd83dbSDimitry Andric       if (Idx > 0)
180e8d8bef9SDimitry Andric         Ret.Values.push_back(ValuesStr.slice(0, Idx));
1815ffd83dbSDimitry Andric       ValuesStr = ValuesStr.slice(Idx + 1, StringRef::npos);
1825ffd83dbSDimitry Andric     }
1835ffd83dbSDimitry Andric     if (!ValuesStr.empty())
184e8d8bef9SDimitry Andric       Ret.Values.push_back(ValuesStr);
1855ffd83dbSDimitry Andric 
186e8d8bef9SDimitry Andric     assert(Ret.Values.size() == Ret.NormalizedValues.size() &&
1875ffd83dbSDimitry Andric            "The number of normalized values doesn't match the number of "
1885ffd83dbSDimitry Andric            "values");
1895ffd83dbSDimitry Andric   }
1905ffd83dbSDimitry Andric 
1915ffd83dbSDimitry Andric   return Ret;
1925ffd83dbSDimitry Andric }
1935ffd83dbSDimitry Andric 
1940b57cec5SDimitry Andric /// OptParserEmitter - This tablegen backend takes an input .td file
1950b57cec5SDimitry Andric /// describing a list of options and emits a data structure for parsing and
1960b57cec5SDimitry Andric /// working with those options when given an input command line.
19706c3fb27SDimitry Andric static void EmitOptParser(RecordKeeper &Records, raw_ostream &OS) {
1980b57cec5SDimitry Andric   // Get the option groups and options.
1990b57cec5SDimitry Andric   const std::vector<Record*> &Groups =
2000b57cec5SDimitry Andric     Records.getAllDerivedDefinitions("OptionGroup");
2010b57cec5SDimitry Andric   std::vector<Record*> Opts = Records.getAllDerivedDefinitions("Option");
2020b57cec5SDimitry Andric 
2030b57cec5SDimitry Andric   emitSourceFileHeader("Option Parsing Definitions", OS);
2040b57cec5SDimitry Andric 
2050b57cec5SDimitry Andric   array_pod_sort(Opts.begin(), Opts.end(), CompareOptionRecords);
2060b57cec5SDimitry Andric   // Generate prefix groups.
2070b57cec5SDimitry Andric   typedef SmallVector<SmallString<2>, 2> PrefixKeyT;
2080b57cec5SDimitry Andric   typedef std::map<PrefixKeyT, std::string> PrefixesT;
2090b57cec5SDimitry Andric   PrefixesT Prefixes;
2100b57cec5SDimitry Andric   Prefixes.insert(std::make_pair(PrefixKeyT(), "prefix_0"));
2110b57cec5SDimitry Andric   unsigned CurPrefix = 0;
212e8d8bef9SDimitry Andric   for (const Record &R : llvm::make_pointee_range(Opts)) {
213e8d8bef9SDimitry Andric     std::vector<StringRef> RPrefixes = R.getValueAsListOfStrings("Prefixes");
214e8d8bef9SDimitry Andric     PrefixKeyT PrefixKey(RPrefixes.begin(), RPrefixes.end());
2150b57cec5SDimitry Andric     unsigned NewPrefix = CurPrefix + 1;
216e8d8bef9SDimitry Andric     std::string Prefix = (Twine("prefix_") + Twine(NewPrefix)).str();
217e8d8bef9SDimitry Andric     if (Prefixes.insert(std::make_pair(PrefixKey, Prefix)).second)
2180b57cec5SDimitry Andric       CurPrefix = NewPrefix;
2190b57cec5SDimitry Andric   }
2200b57cec5SDimitry Andric 
221bdd1243dSDimitry Andric   DenseSet<StringRef> PrefixesUnionSet;
222bdd1243dSDimitry Andric   for (const auto &Prefix : Prefixes)
223bdd1243dSDimitry Andric     PrefixesUnionSet.insert(Prefix.first.begin(), Prefix.first.end());
224bdd1243dSDimitry Andric   SmallVector<StringRef> PrefixesUnion(PrefixesUnionSet.begin(),
225bdd1243dSDimitry Andric                                        PrefixesUnionSet.end());
226bdd1243dSDimitry Andric   array_pod_sort(PrefixesUnion.begin(), PrefixesUnion.end());
2270b57cec5SDimitry Andric 
228bdd1243dSDimitry Andric   // Dump prefixes.
2290b57cec5SDimitry Andric   OS << "/////////\n";
2300b57cec5SDimitry Andric   OS << "// Prefixes\n\n";
2310b57cec5SDimitry Andric   OS << "#ifdef PREFIX\n";
2320b57cec5SDimitry Andric   OS << "#define COMMA ,\n";
233e8d8bef9SDimitry Andric   for (const auto &Prefix : Prefixes) {
2340b57cec5SDimitry Andric     OS << "PREFIX(";
2350b57cec5SDimitry Andric 
2360b57cec5SDimitry Andric     // Prefix name.
237e8d8bef9SDimitry Andric     OS << Prefix.second;
2380b57cec5SDimitry Andric 
2390b57cec5SDimitry Andric     // Prefix values.
2400b57cec5SDimitry Andric     OS << ", {";
241fe6060f1SDimitry Andric     for (const auto &PrefixKey : Prefix.first)
242bdd1243dSDimitry Andric       OS << "llvm::StringLiteral(\"" << PrefixKey << "\") COMMA ";
243bdd1243dSDimitry Andric     // Append an empty element to avoid ending up with an empty array.
244bdd1243dSDimitry Andric     OS << "llvm::StringLiteral(\"\")})\n";
2450b57cec5SDimitry Andric   }
2460b57cec5SDimitry Andric   OS << "#undef COMMA\n";
2470b57cec5SDimitry Andric   OS << "#endif // PREFIX\n\n";
2480b57cec5SDimitry Andric 
249bdd1243dSDimitry Andric   // Dump prefix unions.
250bdd1243dSDimitry Andric   OS << "/////////\n";
251bdd1243dSDimitry Andric   OS << "// Prefix Union\n\n";
252bdd1243dSDimitry Andric   OS << "#ifdef PREFIX_UNION\n";
253bdd1243dSDimitry Andric   OS << "#define COMMA ,\n";
254bdd1243dSDimitry Andric   OS << "PREFIX_UNION({\n";
255bdd1243dSDimitry Andric   for (const auto &Prefix : PrefixesUnion) {
256bdd1243dSDimitry Andric     OS << "llvm::StringLiteral(\"" << Prefix << "\") COMMA ";
257bdd1243dSDimitry Andric   }
258bdd1243dSDimitry Andric   OS << "llvm::StringLiteral(\"\")})\n";
259bdd1243dSDimitry Andric   OS << "#undef COMMA\n";
260bdd1243dSDimitry Andric   OS << "#endif // PREFIX_UNION\n\n";
261bdd1243dSDimitry Andric 
262bdd1243dSDimitry Andric   // Dump groups.
263bdd1243dSDimitry Andric   OS << "/////////\n";
264bdd1243dSDimitry Andric   OS << "// ValuesCode\n\n";
265bdd1243dSDimitry Andric   OS << "#ifdef OPTTABLE_VALUES_CODE\n";
266bdd1243dSDimitry Andric   for (const Record &R : llvm::make_pointee_range(Opts)) {
267bdd1243dSDimitry Andric     // The option values, if any;
268bdd1243dSDimitry Andric     if (!isa<UnsetInit>(R.getValueInit("ValuesCode"))) {
269bdd1243dSDimitry Andric       assert(isa<UnsetInit>(R.getValueInit("Values")) &&
270bdd1243dSDimitry Andric              "Cannot choose between Values and ValuesCode");
271bdd1243dSDimitry Andric       OS << "#define VALUES_CODE " << getOptionName(R) << "_Values\n";
272bdd1243dSDimitry Andric       OS << R.getValueAsString("ValuesCode") << "\n";
273bdd1243dSDimitry Andric       OS << "#undef VALUES_CODE\n";
274bdd1243dSDimitry Andric     }
275bdd1243dSDimitry Andric   }
276bdd1243dSDimitry Andric   OS << "#endif\n";
277bdd1243dSDimitry Andric 
2780b57cec5SDimitry Andric   OS << "/////////\n";
2790b57cec5SDimitry Andric   OS << "// Groups\n\n";
2800b57cec5SDimitry Andric   OS << "#ifdef OPTION\n";
281e8d8bef9SDimitry Andric   for (const Record &R : llvm::make_pointee_range(Groups)) {
2820b57cec5SDimitry Andric     // Start a single option entry.
2830b57cec5SDimitry Andric     OS << "OPTION(";
2840b57cec5SDimitry Andric 
2850b57cec5SDimitry Andric     // The option prefix;
286bdd1243dSDimitry Andric     OS << "llvm::ArrayRef<llvm::StringLiteral>()";
2870b57cec5SDimitry Andric 
2880b57cec5SDimitry Andric     // The option string.
2890b57cec5SDimitry Andric     OS << ", \"" << R.getValueAsString("Name") << '"';
2900b57cec5SDimitry Andric 
2910b57cec5SDimitry Andric     // The option identifier name.
2920b57cec5SDimitry Andric     OS << ", " << getOptionName(R);
2930b57cec5SDimitry Andric 
2940b57cec5SDimitry Andric     // The option kind.
2950b57cec5SDimitry Andric     OS << ", Group";
2960b57cec5SDimitry Andric 
2970b57cec5SDimitry Andric     // The containing option group (if any).
2980b57cec5SDimitry Andric     OS << ", ";
2990b57cec5SDimitry Andric     if (const DefInit *DI = dyn_cast<DefInit>(R.getValueInit("Group")))
3000b57cec5SDimitry Andric       OS << getOptionName(*DI->getDef());
3010b57cec5SDimitry Andric     else
3020b57cec5SDimitry Andric       OS << "INVALID";
3030b57cec5SDimitry Andric 
3040b57cec5SDimitry Andric     // The other option arguments (unused for groups).
305*5f757f3fSDimitry Andric     OS << ", INVALID, nullptr, 0, 0, 0";
3060b57cec5SDimitry Andric 
3070b57cec5SDimitry Andric     // The option help text.
3080b57cec5SDimitry Andric     if (!isa<UnsetInit>(R.getValueInit("HelpText"))) {
3090b57cec5SDimitry Andric       OS << ",\n";
3100b57cec5SDimitry Andric       OS << "       ";
3110b57cec5SDimitry Andric       write_cstring(OS, R.getValueAsString("HelpText"));
3120b57cec5SDimitry Andric     } else
3130b57cec5SDimitry Andric       OS << ", nullptr";
3140b57cec5SDimitry Andric 
3150b57cec5SDimitry Andric     // The option meta-variable name (unused).
3160b57cec5SDimitry Andric     OS << ", nullptr";
3170b57cec5SDimitry Andric 
3180b57cec5SDimitry Andric     // The option Values (unused for groups).
3190b57cec5SDimitry Andric     OS << ", nullptr)\n";
3200b57cec5SDimitry Andric   }
3210b57cec5SDimitry Andric   OS << "\n";
3220b57cec5SDimitry Andric 
3230b57cec5SDimitry Andric   OS << "//////////\n";
3240b57cec5SDimitry Andric   OS << "// Options\n\n";
3250b57cec5SDimitry Andric 
3265ffd83dbSDimitry Andric   auto WriteOptRecordFields = [&](raw_ostream &OS, const Record &R) {
3270b57cec5SDimitry Andric     // The option prefix;
328e8d8bef9SDimitry Andric     std::vector<StringRef> RPrefixes = R.getValueAsListOfStrings("Prefixes");
329e8d8bef9SDimitry Andric     OS << Prefixes[PrefixKeyT(RPrefixes.begin(), RPrefixes.end())] << ", ";
3300b57cec5SDimitry Andric 
331*5f757f3fSDimitry Andric     // The option prefixed name.
332*5f757f3fSDimitry Andric     write_cstring(OS, getOptionPrefixedName(R));
3330b57cec5SDimitry Andric 
3340b57cec5SDimitry Andric     // The option identifier name.
3350b57cec5SDimitry Andric     OS << ", " << getOptionName(R);
3360b57cec5SDimitry Andric 
3370b57cec5SDimitry Andric     // The option kind.
3380b57cec5SDimitry Andric     OS << ", " << R.getValueAsDef("Kind")->getValueAsString("Name");
3390b57cec5SDimitry Andric 
3400b57cec5SDimitry Andric     // The containing option group (if any).
3410b57cec5SDimitry Andric     OS << ", ";
3420b57cec5SDimitry Andric     const ListInit *GroupFlags = nullptr;
343*5f757f3fSDimitry Andric     const ListInit *GroupVis = nullptr;
3440b57cec5SDimitry Andric     if (const DefInit *DI = dyn_cast<DefInit>(R.getValueInit("Group"))) {
3450b57cec5SDimitry Andric       GroupFlags = DI->getDef()->getValueAsListInit("Flags");
346*5f757f3fSDimitry Andric       GroupVis = DI->getDef()->getValueAsListInit("Visibility");
3470b57cec5SDimitry Andric       OS << getOptionName(*DI->getDef());
3480b57cec5SDimitry Andric     } else
3490b57cec5SDimitry Andric       OS << "INVALID";
3500b57cec5SDimitry Andric 
3510b57cec5SDimitry Andric     // The option alias (if any).
3520b57cec5SDimitry Andric     OS << ", ";
3530b57cec5SDimitry Andric     if (const DefInit *DI = dyn_cast<DefInit>(R.getValueInit("Alias")))
3540b57cec5SDimitry Andric       OS << getOptionName(*DI->getDef());
3550b57cec5SDimitry Andric     else
3560b57cec5SDimitry Andric       OS << "INVALID";
3570b57cec5SDimitry Andric 
3580b57cec5SDimitry Andric     // The option alias arguments (if any).
3590b57cec5SDimitry Andric     // Emitted as a \0 separated list in a string, e.g. ["foo", "bar"]
3600b57cec5SDimitry Andric     // would become "foo\0bar\0". Note that the compiler adds an implicit
3610b57cec5SDimitry Andric     // terminating \0 at the end.
3620b57cec5SDimitry Andric     OS << ", ";
3630b57cec5SDimitry Andric     std::vector<StringRef> AliasArgs = R.getValueAsListOfStrings("AliasArgs");
3640b57cec5SDimitry Andric     if (AliasArgs.size() == 0) {
3650b57cec5SDimitry Andric       OS << "nullptr";
3660b57cec5SDimitry Andric     } else {
3670b57cec5SDimitry Andric       OS << "\"";
368e8d8bef9SDimitry Andric       for (StringRef AliasArg : AliasArgs)
369e8d8bef9SDimitry Andric         OS << AliasArg << "\\0";
3700b57cec5SDimitry Andric       OS << "\"";
3710b57cec5SDimitry Andric     }
3720b57cec5SDimitry Andric 
373*5f757f3fSDimitry Andric     // "Flags" for the option, such as HelpHidden and Render*
3740b57cec5SDimitry Andric     OS << ", ";
3750b57cec5SDimitry Andric     int NumFlags = 0;
3760b57cec5SDimitry Andric     const ListInit *LI = R.getValueAsListInit("Flags");
3770b57cec5SDimitry Andric     for (Init *I : *LI)
3785ffd83dbSDimitry Andric       OS << (NumFlags++ ? " | " : "") << cast<DefInit>(I)->getDef()->getName();
3790b57cec5SDimitry Andric     if (GroupFlags) {
3800b57cec5SDimitry Andric       for (Init *I : *GroupFlags)
3810b57cec5SDimitry Andric         OS << (NumFlags++ ? " | " : "")
3820b57cec5SDimitry Andric            << cast<DefInit>(I)->getDef()->getName();
3830b57cec5SDimitry Andric     }
3840b57cec5SDimitry Andric     if (NumFlags == 0)
3850b57cec5SDimitry Andric       OS << '0';
3860b57cec5SDimitry Andric 
387*5f757f3fSDimitry Andric     // Option visibility, for sharing options between drivers.
388*5f757f3fSDimitry Andric     OS << ", ";
389*5f757f3fSDimitry Andric     int NumVisFlags = 0;
390*5f757f3fSDimitry Andric     LI = R.getValueAsListInit("Visibility");
391*5f757f3fSDimitry Andric     for (Init *I : *LI)
392*5f757f3fSDimitry Andric       OS << (NumVisFlags++ ? " | " : "")
393*5f757f3fSDimitry Andric          << cast<DefInit>(I)->getDef()->getName();
394*5f757f3fSDimitry Andric     if (GroupVis) {
395*5f757f3fSDimitry Andric       for (Init *I : *GroupVis)
396*5f757f3fSDimitry Andric         OS << (NumVisFlags++ ? " | " : "")
397*5f757f3fSDimitry Andric            << cast<DefInit>(I)->getDef()->getName();
398*5f757f3fSDimitry Andric     }
399*5f757f3fSDimitry Andric     if (NumVisFlags == 0)
400*5f757f3fSDimitry Andric       OS << '0';
401*5f757f3fSDimitry Andric 
4020b57cec5SDimitry Andric     // The option parameter field.
4030b57cec5SDimitry Andric     OS << ", " << R.getValueAsInt("NumArgs");
4040b57cec5SDimitry Andric 
4050b57cec5SDimitry Andric     // The option help text.
4060b57cec5SDimitry Andric     if (!isa<UnsetInit>(R.getValueInit("HelpText"))) {
4070b57cec5SDimitry Andric       OS << ",\n";
4080b57cec5SDimitry Andric       OS << "       ";
4090b57cec5SDimitry Andric       write_cstring(OS, R.getValueAsString("HelpText"));
4100b57cec5SDimitry Andric     } else
4110b57cec5SDimitry Andric       OS << ", nullptr";
4120b57cec5SDimitry Andric 
4130b57cec5SDimitry Andric     // The option meta-variable name.
4140b57cec5SDimitry Andric     OS << ", ";
4150b57cec5SDimitry Andric     if (!isa<UnsetInit>(R.getValueInit("MetaVarName")))
4160b57cec5SDimitry Andric       write_cstring(OS, R.getValueAsString("MetaVarName"));
4170b57cec5SDimitry Andric     else
4180b57cec5SDimitry Andric       OS << "nullptr";
4190b57cec5SDimitry Andric 
4200b57cec5SDimitry Andric     // The option Values. Used for shell autocompletion.
4210b57cec5SDimitry Andric     OS << ", ";
4220b57cec5SDimitry Andric     if (!isa<UnsetInit>(R.getValueInit("Values")))
4230b57cec5SDimitry Andric       write_cstring(OS, R.getValueAsString("Values"));
424bdd1243dSDimitry Andric     else if (!isa<UnsetInit>(R.getValueInit("ValuesCode"))) {
425bdd1243dSDimitry Andric       OS << getOptionName(R) << "_Values";
426bdd1243dSDimitry Andric     }
4270b57cec5SDimitry Andric     else
4280b57cec5SDimitry Andric       OS << "nullptr";
4295ffd83dbSDimitry Andric   };
4300b57cec5SDimitry Andric 
431e8d8bef9SDimitry Andric   auto IsMarshallingOption = [](const Record &R) {
432e8d8bef9SDimitry Andric     return !isa<UnsetInit>(R.getValueInit("KeyPath")) &&
433e8d8bef9SDimitry Andric            !R.getValueAsString("KeyPath").empty();
434e8d8bef9SDimitry Andric   };
4355ffd83dbSDimitry Andric 
436e8d8bef9SDimitry Andric   std::vector<const Record *> OptsWithMarshalling;
437e8d8bef9SDimitry Andric   for (const Record &R : llvm::make_pointee_range(Opts)) {
4385ffd83dbSDimitry Andric     // Start a single option entry.
4395ffd83dbSDimitry Andric     OS << "OPTION(";
4405ffd83dbSDimitry Andric     WriteOptRecordFields(OS, R);
4410b57cec5SDimitry Andric     OS << ")\n";
442e8d8bef9SDimitry Andric     if (IsMarshallingOption(R))
443e8d8bef9SDimitry Andric       OptsWithMarshalling.push_back(&R);
4440b57cec5SDimitry Andric   }
4450b57cec5SDimitry Andric   OS << "#endif // OPTION\n";
4460b57cec5SDimitry Andric 
447e8d8bef9SDimitry Andric   auto CmpMarshallingOpts = [](const Record *const *A, const Record *const *B) {
448e8d8bef9SDimitry Andric     unsigned AID = (*A)->getID();
449e8d8bef9SDimitry Andric     unsigned BID = (*B)->getID();
450e8d8bef9SDimitry Andric 
451e8d8bef9SDimitry Andric     if (AID < BID)
452e8d8bef9SDimitry Andric       return -1;
453e8d8bef9SDimitry Andric     if (AID > BID)
454e8d8bef9SDimitry Andric       return 1;
455e8d8bef9SDimitry Andric     return 0;
456e8d8bef9SDimitry Andric   };
457e8d8bef9SDimitry Andric   // The RecordKeeper stores records (options) in lexicographical order, and we
458e8d8bef9SDimitry Andric   // have reordered the options again when generating prefix groups. We need to
459e8d8bef9SDimitry Andric   // restore the original definition order of options with marshalling to honor
460e8d8bef9SDimitry Andric   // the topology of the dependency graph implied by `DefaultAnyOf`.
461e8d8bef9SDimitry Andric   array_pod_sort(OptsWithMarshalling.begin(), OptsWithMarshalling.end(),
462e8d8bef9SDimitry Andric                  CmpMarshallingOpts);
463e8d8bef9SDimitry Andric 
464e8d8bef9SDimitry Andric   std::vector<MarshallingInfo> MarshallingInfos;
465bdd1243dSDimitry Andric   MarshallingInfos.reserve(OptsWithMarshalling.size());
466e8d8bef9SDimitry Andric   for (const auto *R : OptsWithMarshalling)
467e8d8bef9SDimitry Andric     MarshallingInfos.push_back(createMarshallingInfo(*R));
468e8d8bef9SDimitry Andric 
469e8d8bef9SDimitry Andric   for (const auto &MI : MarshallingInfos) {
470e8d8bef9SDimitry Andric     OS << "#ifdef " << MI.getMacroName() << "\n";
471e8d8bef9SDimitry Andric     OS << MI.getMacroName() << "(";
472e8d8bef9SDimitry Andric     WriteOptRecordFields(OS, MI.R);
4735ffd83dbSDimitry Andric     OS << ", ";
474e8d8bef9SDimitry Andric     MI.emit(OS);
4755ffd83dbSDimitry Andric     OS << ")\n";
476e8d8bef9SDimitry Andric     OS << "#endif // " << MI.getMacroName() << "\n";
4775ffd83dbSDimitry Andric   }
4785ffd83dbSDimitry Andric 
4795ffd83dbSDimitry Andric   OS << "\n";
4805ffd83dbSDimitry Andric   OS << "#ifdef SIMPLE_ENUM_VALUE_TABLE";
4815ffd83dbSDimitry Andric   OS << "\n";
482e8d8bef9SDimitry Andric   OS << MarshallingInfo::ValueTablePreamble;
4835ffd83dbSDimitry Andric   std::vector<StringRef> ValueTableNames;
484e8d8bef9SDimitry Andric   for (const auto &MI : MarshallingInfos)
485e8d8bef9SDimitry Andric     if (auto MaybeValueTableName = MI.emitValueTable(OS))
4865ffd83dbSDimitry Andric       ValueTableNames.push_back(*MaybeValueTableName);
4875ffd83dbSDimitry Andric 
488e8d8bef9SDimitry Andric   OS << MarshallingInfo::ValueTablesDecl << "{";
4895ffd83dbSDimitry Andric   for (auto ValueTableName : ValueTableNames)
490bdd1243dSDimitry Andric     OS << "{" << ValueTableName << ", std::size(" << ValueTableName << ")},\n";
4915ffd83dbSDimitry Andric   OS << "};\n";
4925ffd83dbSDimitry Andric   OS << "static const unsigned SimpleEnumValueTablesSize = "
493bdd1243dSDimitry Andric         "std::size(SimpleEnumValueTables);\n";
4945ffd83dbSDimitry Andric 
4955ffd83dbSDimitry Andric   OS << "#endif // SIMPLE_ENUM_VALUE_TABLE\n";
4965ffd83dbSDimitry Andric   OS << "\n";
4975ffd83dbSDimitry Andric 
4980b57cec5SDimitry Andric   OS << "\n";
4990b57cec5SDimitry Andric }
50006c3fb27SDimitry Andric 
50106c3fb27SDimitry Andric static TableGen::Emitter::Opt X("gen-opt-parser-defs", EmitOptParser,
50206c3fb27SDimitry Andric                                 "Generate option definitions");
503