xref: /freebsd-src/contrib/llvm-project/llvm/utils/TableGen/OptParserEmitter.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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 
9*0fca6ea1SDimitry Andric #include "Common/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 
375f757f3fSDimitry 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 
415f757f3fSDimitry Andric   if (Prefixes.empty())
425ffd83dbSDimitry Andric     return Name.str();
43e8d8bef9SDimitry Andric 
445f757f3fSDimitry 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 
194*0fca6ea1SDimitry Andric static void EmitHelpTextsForVariants(
195*0fca6ea1SDimitry Andric     raw_ostream &OS, std::vector<std::pair<std::vector<std::string>, StringRef>>
196*0fca6ea1SDimitry Andric                          HelpTextsForVariants) {
197*0fca6ea1SDimitry Andric   // OptTable must be constexpr so it uses std::arrays with these capacities.
198*0fca6ea1SDimitry Andric   const unsigned MaxVisibilityPerHelp = 2;
199*0fca6ea1SDimitry Andric   const unsigned MaxVisibilityHelp = 1;
200*0fca6ea1SDimitry Andric 
201*0fca6ea1SDimitry Andric   assert(HelpTextsForVariants.size() <= MaxVisibilityHelp &&
202*0fca6ea1SDimitry Andric          "Too many help text variants to store in "
203*0fca6ea1SDimitry Andric          "OptTable::HelpTextsForVariants");
204*0fca6ea1SDimitry Andric 
205*0fca6ea1SDimitry Andric   // This function must initialise any unused elements of those arrays.
206*0fca6ea1SDimitry Andric   for (auto [Visibilities, _] : HelpTextsForVariants)
207*0fca6ea1SDimitry Andric     while (Visibilities.size() < MaxVisibilityPerHelp)
208*0fca6ea1SDimitry Andric       Visibilities.push_back("0");
209*0fca6ea1SDimitry Andric 
210*0fca6ea1SDimitry Andric   while (HelpTextsForVariants.size() < MaxVisibilityHelp)
211*0fca6ea1SDimitry Andric     HelpTextsForVariants.push_back(
212*0fca6ea1SDimitry Andric         {std::vector<std::string>(MaxVisibilityPerHelp, "0"), ""});
213*0fca6ea1SDimitry Andric 
214*0fca6ea1SDimitry Andric   OS << ", (std::array<std::pair<std::array<unsigned, " << MaxVisibilityPerHelp
215*0fca6ea1SDimitry Andric      << ">, const char*>, " << MaxVisibilityHelp << ">{{ ";
216*0fca6ea1SDimitry Andric 
217*0fca6ea1SDimitry Andric   auto VisibilityHelpEnd = HelpTextsForVariants.cend();
218*0fca6ea1SDimitry Andric   for (auto VisibilityHelp = HelpTextsForVariants.cbegin();
219*0fca6ea1SDimitry Andric        VisibilityHelp != VisibilityHelpEnd; ++VisibilityHelp) {
220*0fca6ea1SDimitry Andric     auto [Visibilities, Help] = *VisibilityHelp;
221*0fca6ea1SDimitry Andric 
222*0fca6ea1SDimitry Andric     assert(Visibilities.size() <= MaxVisibilityPerHelp &&
223*0fca6ea1SDimitry Andric            "Too many visibilities to store in an "
224*0fca6ea1SDimitry Andric            "OptTable::HelpTextsForVariants entry");
225*0fca6ea1SDimitry Andric     OS << "std::make_pair(std::array<unsigned, " << MaxVisibilityPerHelp
226*0fca6ea1SDimitry Andric        << ">{{";
227*0fca6ea1SDimitry Andric 
228*0fca6ea1SDimitry Andric     auto VisibilityEnd = Visibilities.cend();
229*0fca6ea1SDimitry Andric     for (auto Visibility = Visibilities.cbegin(); Visibility != VisibilityEnd;
230*0fca6ea1SDimitry Andric          ++Visibility) {
231*0fca6ea1SDimitry Andric       OS << *Visibility;
232*0fca6ea1SDimitry Andric       if (std::next(Visibility) != VisibilityEnd)
233*0fca6ea1SDimitry Andric         OS << ", ";
234*0fca6ea1SDimitry Andric     }
235*0fca6ea1SDimitry Andric 
236*0fca6ea1SDimitry Andric     OS << "}}, ";
237*0fca6ea1SDimitry Andric 
238*0fca6ea1SDimitry Andric     if (Help.size())
239*0fca6ea1SDimitry Andric       write_cstring(OS, Help);
240*0fca6ea1SDimitry Andric     else
241*0fca6ea1SDimitry Andric       OS << "nullptr";
242*0fca6ea1SDimitry Andric     OS << ")";
243*0fca6ea1SDimitry Andric 
244*0fca6ea1SDimitry Andric     if (std::next(VisibilityHelp) != VisibilityHelpEnd)
245*0fca6ea1SDimitry Andric       OS << ", ";
246*0fca6ea1SDimitry Andric   }
247*0fca6ea1SDimitry Andric   OS << " }})";
248*0fca6ea1SDimitry Andric }
249*0fca6ea1SDimitry Andric 
2500b57cec5SDimitry Andric /// OptParserEmitter - This tablegen backend takes an input .td file
2510b57cec5SDimitry Andric /// describing a list of options and emits a data structure for parsing and
2520b57cec5SDimitry Andric /// working with those options when given an input command line.
25306c3fb27SDimitry Andric static void EmitOptParser(RecordKeeper &Records, raw_ostream &OS) {
2540b57cec5SDimitry Andric   // Get the option groups and options.
2550b57cec5SDimitry Andric   const std::vector<Record *> &Groups =
2560b57cec5SDimitry Andric       Records.getAllDerivedDefinitions("OptionGroup");
2570b57cec5SDimitry Andric   std::vector<Record *> Opts = Records.getAllDerivedDefinitions("Option");
2580b57cec5SDimitry Andric 
2590b57cec5SDimitry Andric   emitSourceFileHeader("Option Parsing Definitions", OS);
2600b57cec5SDimitry Andric 
2610b57cec5SDimitry Andric   array_pod_sort(Opts.begin(), Opts.end(), CompareOptionRecords);
2620b57cec5SDimitry Andric   // Generate prefix groups.
2630b57cec5SDimitry Andric   typedef SmallVector<SmallString<2>, 2> PrefixKeyT;
2640b57cec5SDimitry Andric   typedef std::map<PrefixKeyT, std::string> PrefixesT;
2650b57cec5SDimitry Andric   PrefixesT Prefixes;
266*0fca6ea1SDimitry Andric   Prefixes.insert(std::pair(PrefixKeyT(), "prefix_0"));
2670b57cec5SDimitry Andric   unsigned CurPrefix = 0;
268e8d8bef9SDimitry Andric   for (const Record &R : llvm::make_pointee_range(Opts)) {
269e8d8bef9SDimitry Andric     std::vector<StringRef> RPrefixes = R.getValueAsListOfStrings("Prefixes");
270e8d8bef9SDimitry Andric     PrefixKeyT PrefixKey(RPrefixes.begin(), RPrefixes.end());
2710b57cec5SDimitry Andric     unsigned NewPrefix = CurPrefix + 1;
272e8d8bef9SDimitry Andric     std::string Prefix = (Twine("prefix_") + Twine(NewPrefix)).str();
273*0fca6ea1SDimitry Andric     if (Prefixes.insert(std::pair(PrefixKey, Prefix)).second)
2740b57cec5SDimitry Andric       CurPrefix = NewPrefix;
2750b57cec5SDimitry Andric   }
2760b57cec5SDimitry Andric 
277bdd1243dSDimitry Andric   DenseSet<StringRef> PrefixesUnionSet;
278bdd1243dSDimitry Andric   for (const auto &Prefix : Prefixes)
279bdd1243dSDimitry Andric     PrefixesUnionSet.insert(Prefix.first.begin(), Prefix.first.end());
280bdd1243dSDimitry Andric   SmallVector<StringRef> PrefixesUnion(PrefixesUnionSet.begin(),
281bdd1243dSDimitry Andric                                        PrefixesUnionSet.end());
282bdd1243dSDimitry Andric   array_pod_sort(PrefixesUnion.begin(), PrefixesUnion.end());
2830b57cec5SDimitry Andric 
284bdd1243dSDimitry Andric   // Dump prefixes.
2850b57cec5SDimitry Andric   OS << "/////////\n";
2860b57cec5SDimitry Andric   OS << "// Prefixes\n\n";
2870b57cec5SDimitry Andric   OS << "#ifdef PREFIX\n";
2880b57cec5SDimitry Andric   OS << "#define COMMA ,\n";
289e8d8bef9SDimitry Andric   for (const auto &Prefix : Prefixes) {
2900b57cec5SDimitry Andric     OS << "PREFIX(";
2910b57cec5SDimitry Andric 
2920b57cec5SDimitry Andric     // Prefix name.
293e8d8bef9SDimitry Andric     OS << Prefix.second;
2940b57cec5SDimitry Andric 
2950b57cec5SDimitry Andric     // Prefix values.
2960b57cec5SDimitry Andric     OS << ", {";
297fe6060f1SDimitry Andric     for (const auto &PrefixKey : Prefix.first)
298bdd1243dSDimitry Andric       OS << "llvm::StringLiteral(\"" << PrefixKey << "\") COMMA ";
299bdd1243dSDimitry Andric     // Append an empty element to avoid ending up with an empty array.
300bdd1243dSDimitry Andric     OS << "llvm::StringLiteral(\"\")})\n";
3010b57cec5SDimitry Andric   }
3020b57cec5SDimitry Andric   OS << "#undef COMMA\n";
3030b57cec5SDimitry Andric   OS << "#endif // PREFIX\n\n";
3040b57cec5SDimitry Andric 
305bdd1243dSDimitry Andric   // Dump prefix unions.
306bdd1243dSDimitry Andric   OS << "/////////\n";
307bdd1243dSDimitry Andric   OS << "// Prefix Union\n\n";
308bdd1243dSDimitry Andric   OS << "#ifdef PREFIX_UNION\n";
309bdd1243dSDimitry Andric   OS << "#define COMMA ,\n";
310bdd1243dSDimitry Andric   OS << "PREFIX_UNION({\n";
311bdd1243dSDimitry Andric   for (const auto &Prefix : PrefixesUnion) {
312bdd1243dSDimitry Andric     OS << "llvm::StringLiteral(\"" << Prefix << "\") COMMA ";
313bdd1243dSDimitry Andric   }
314bdd1243dSDimitry Andric   OS << "llvm::StringLiteral(\"\")})\n";
315bdd1243dSDimitry Andric   OS << "#undef COMMA\n";
316bdd1243dSDimitry Andric   OS << "#endif // PREFIX_UNION\n\n";
317bdd1243dSDimitry Andric 
318bdd1243dSDimitry Andric   // Dump groups.
319bdd1243dSDimitry Andric   OS << "/////////\n";
320bdd1243dSDimitry Andric   OS << "// ValuesCode\n\n";
321bdd1243dSDimitry Andric   OS << "#ifdef OPTTABLE_VALUES_CODE\n";
322bdd1243dSDimitry Andric   for (const Record &R : llvm::make_pointee_range(Opts)) {
323bdd1243dSDimitry Andric     // The option values, if any;
324bdd1243dSDimitry Andric     if (!isa<UnsetInit>(R.getValueInit("ValuesCode"))) {
325bdd1243dSDimitry Andric       assert(isa<UnsetInit>(R.getValueInit("Values")) &&
326bdd1243dSDimitry Andric              "Cannot choose between Values and ValuesCode");
327bdd1243dSDimitry Andric       OS << "#define VALUES_CODE " << getOptionName(R) << "_Values\n";
328bdd1243dSDimitry Andric       OS << R.getValueAsString("ValuesCode") << "\n";
329bdd1243dSDimitry Andric       OS << "#undef VALUES_CODE\n";
330bdd1243dSDimitry Andric     }
331bdd1243dSDimitry Andric   }
332bdd1243dSDimitry Andric   OS << "#endif\n";
333bdd1243dSDimitry Andric 
3340b57cec5SDimitry Andric   OS << "/////////\n";
3350b57cec5SDimitry Andric   OS << "// Groups\n\n";
3360b57cec5SDimitry Andric   OS << "#ifdef OPTION\n";
337e8d8bef9SDimitry Andric   for (const Record &R : llvm::make_pointee_range(Groups)) {
3380b57cec5SDimitry Andric     // Start a single option entry.
3390b57cec5SDimitry Andric     OS << "OPTION(";
3400b57cec5SDimitry Andric 
3410b57cec5SDimitry Andric     // The option prefix;
342bdd1243dSDimitry Andric     OS << "llvm::ArrayRef<llvm::StringLiteral>()";
3430b57cec5SDimitry Andric 
3440b57cec5SDimitry Andric     // The option string.
3450b57cec5SDimitry Andric     OS << ", \"" << R.getValueAsString("Name") << '"';
3460b57cec5SDimitry Andric 
3470b57cec5SDimitry Andric     // The option identifier name.
3480b57cec5SDimitry Andric     OS << ", " << getOptionName(R);
3490b57cec5SDimitry Andric 
3500b57cec5SDimitry Andric     // The option kind.
3510b57cec5SDimitry Andric     OS << ", Group";
3520b57cec5SDimitry Andric 
3530b57cec5SDimitry Andric     // The containing option group (if any).
3540b57cec5SDimitry Andric     OS << ", ";
3550b57cec5SDimitry Andric     if (const DefInit *DI = dyn_cast<DefInit>(R.getValueInit("Group")))
3560b57cec5SDimitry Andric       OS << getOptionName(*DI->getDef());
3570b57cec5SDimitry Andric     else
3580b57cec5SDimitry Andric       OS << "INVALID";
3590b57cec5SDimitry Andric 
3600b57cec5SDimitry Andric     // The other option arguments (unused for groups).
3615f757f3fSDimitry Andric     OS << ", INVALID, nullptr, 0, 0, 0";
3620b57cec5SDimitry Andric 
3630b57cec5SDimitry Andric     // The option help text.
3640b57cec5SDimitry Andric     if (!isa<UnsetInit>(R.getValueInit("HelpText"))) {
3650b57cec5SDimitry Andric       OS << ",\n";
3660b57cec5SDimitry Andric       OS << "       ";
3670b57cec5SDimitry Andric       write_cstring(OS, R.getValueAsString("HelpText"));
3680b57cec5SDimitry Andric     } else
3690b57cec5SDimitry Andric       OS << ", nullptr";
3700b57cec5SDimitry Andric 
371*0fca6ea1SDimitry Andric     // Not using Visibility specific text for group help.
372*0fca6ea1SDimitry Andric     EmitHelpTextsForVariants(OS, {});
373*0fca6ea1SDimitry Andric 
3740b57cec5SDimitry Andric     // The option meta-variable name (unused).
3750b57cec5SDimitry Andric     OS << ", nullptr";
3760b57cec5SDimitry Andric 
3770b57cec5SDimitry Andric     // The option Values (unused for groups).
3780b57cec5SDimitry Andric     OS << ", nullptr)\n";
3790b57cec5SDimitry Andric   }
3800b57cec5SDimitry Andric   OS << "\n";
3810b57cec5SDimitry Andric 
3820b57cec5SDimitry Andric   OS << "//////////\n";
3830b57cec5SDimitry Andric   OS << "// Options\n\n";
3840b57cec5SDimitry Andric 
3855ffd83dbSDimitry Andric   auto WriteOptRecordFields = [&](raw_ostream &OS, const Record &R) {
3860b57cec5SDimitry Andric     // The option prefix;
387e8d8bef9SDimitry Andric     std::vector<StringRef> RPrefixes = R.getValueAsListOfStrings("Prefixes");
388e8d8bef9SDimitry Andric     OS << Prefixes[PrefixKeyT(RPrefixes.begin(), RPrefixes.end())] << ", ";
3890b57cec5SDimitry Andric 
3905f757f3fSDimitry Andric     // The option prefixed name.
3915f757f3fSDimitry Andric     write_cstring(OS, getOptionPrefixedName(R));
3920b57cec5SDimitry Andric 
3930b57cec5SDimitry Andric     // The option identifier name.
3940b57cec5SDimitry Andric     OS << ", " << getOptionName(R);
3950b57cec5SDimitry Andric 
3960b57cec5SDimitry Andric     // The option kind.
3970b57cec5SDimitry Andric     OS << ", " << R.getValueAsDef("Kind")->getValueAsString("Name");
3980b57cec5SDimitry Andric 
3990b57cec5SDimitry Andric     // The containing option group (if any).
4000b57cec5SDimitry Andric     OS << ", ";
4010b57cec5SDimitry Andric     const ListInit *GroupFlags = nullptr;
4025f757f3fSDimitry Andric     const ListInit *GroupVis = nullptr;
4030b57cec5SDimitry Andric     if (const DefInit *DI = dyn_cast<DefInit>(R.getValueInit("Group"))) {
4040b57cec5SDimitry Andric       GroupFlags = DI->getDef()->getValueAsListInit("Flags");
4055f757f3fSDimitry Andric       GroupVis = DI->getDef()->getValueAsListInit("Visibility");
4060b57cec5SDimitry Andric       OS << getOptionName(*DI->getDef());
4070b57cec5SDimitry Andric     } else
4080b57cec5SDimitry Andric       OS << "INVALID";
4090b57cec5SDimitry Andric 
4100b57cec5SDimitry Andric     // The option alias (if any).
4110b57cec5SDimitry Andric     OS << ", ";
4120b57cec5SDimitry Andric     if (const DefInit *DI = dyn_cast<DefInit>(R.getValueInit("Alias")))
4130b57cec5SDimitry Andric       OS << getOptionName(*DI->getDef());
4140b57cec5SDimitry Andric     else
4150b57cec5SDimitry Andric       OS << "INVALID";
4160b57cec5SDimitry Andric 
4170b57cec5SDimitry Andric     // The option alias arguments (if any).
4180b57cec5SDimitry Andric     // Emitted as a \0 separated list in a string, e.g. ["foo", "bar"]
4190b57cec5SDimitry Andric     // would become "foo\0bar\0". Note that the compiler adds an implicit
4200b57cec5SDimitry Andric     // terminating \0 at the end.
4210b57cec5SDimitry Andric     OS << ", ";
4220b57cec5SDimitry Andric     std::vector<StringRef> AliasArgs = R.getValueAsListOfStrings("AliasArgs");
4230b57cec5SDimitry Andric     if (AliasArgs.size() == 0) {
4240b57cec5SDimitry Andric       OS << "nullptr";
4250b57cec5SDimitry Andric     } else {
4260b57cec5SDimitry Andric       OS << "\"";
427e8d8bef9SDimitry Andric       for (StringRef AliasArg : AliasArgs)
428e8d8bef9SDimitry Andric         OS << AliasArg << "\\0";
4290b57cec5SDimitry Andric       OS << "\"";
4300b57cec5SDimitry Andric     }
4310b57cec5SDimitry Andric 
4325f757f3fSDimitry Andric     // "Flags" for the option, such as HelpHidden and Render*
4330b57cec5SDimitry Andric     OS << ", ";
4340b57cec5SDimitry Andric     int NumFlags = 0;
4350b57cec5SDimitry Andric     const ListInit *LI = R.getValueAsListInit("Flags");
4360b57cec5SDimitry Andric     for (Init *I : *LI)
4375ffd83dbSDimitry Andric       OS << (NumFlags++ ? " | " : "") << cast<DefInit>(I)->getDef()->getName();
4380b57cec5SDimitry Andric     if (GroupFlags) {
4390b57cec5SDimitry Andric       for (Init *I : *GroupFlags)
4400b57cec5SDimitry Andric         OS << (NumFlags++ ? " | " : "")
4410b57cec5SDimitry Andric            << cast<DefInit>(I)->getDef()->getName();
4420b57cec5SDimitry Andric     }
4430b57cec5SDimitry Andric     if (NumFlags == 0)
4440b57cec5SDimitry Andric       OS << '0';
4450b57cec5SDimitry Andric 
4465f757f3fSDimitry Andric     // Option visibility, for sharing options between drivers.
4475f757f3fSDimitry Andric     OS << ", ";
4485f757f3fSDimitry Andric     int NumVisFlags = 0;
4495f757f3fSDimitry Andric     LI = R.getValueAsListInit("Visibility");
4505f757f3fSDimitry Andric     for (Init *I : *LI)
4515f757f3fSDimitry Andric       OS << (NumVisFlags++ ? " | " : "")
4525f757f3fSDimitry Andric          << cast<DefInit>(I)->getDef()->getName();
4535f757f3fSDimitry Andric     if (GroupVis) {
4545f757f3fSDimitry Andric       for (Init *I : *GroupVis)
4555f757f3fSDimitry Andric         OS << (NumVisFlags++ ? " | " : "")
4565f757f3fSDimitry Andric            << cast<DefInit>(I)->getDef()->getName();
4575f757f3fSDimitry Andric     }
4585f757f3fSDimitry Andric     if (NumVisFlags == 0)
4595f757f3fSDimitry Andric       OS << '0';
4605f757f3fSDimitry Andric 
4610b57cec5SDimitry Andric     // The option parameter field.
4620b57cec5SDimitry Andric     OS << ", " << R.getValueAsInt("NumArgs");
4630b57cec5SDimitry Andric 
4640b57cec5SDimitry Andric     // The option help text.
4650b57cec5SDimitry Andric     if (!isa<UnsetInit>(R.getValueInit("HelpText"))) {
4660b57cec5SDimitry Andric       OS << ",\n";
4670b57cec5SDimitry Andric       OS << "       ";
4680b57cec5SDimitry Andric       write_cstring(OS, R.getValueAsString("HelpText"));
4690b57cec5SDimitry Andric     } else
4700b57cec5SDimitry Andric       OS << ", nullptr";
4710b57cec5SDimitry Andric 
472*0fca6ea1SDimitry Andric     std::vector<std::pair<std::vector<std::string>, StringRef>>
473*0fca6ea1SDimitry Andric         HelpTextsForVariants;
474*0fca6ea1SDimitry Andric     for (Record *VisibilityHelp :
475*0fca6ea1SDimitry Andric          R.getValueAsListOfDefs("HelpTextsForVariants")) {
476*0fca6ea1SDimitry Andric       ArrayRef<Init *> Visibilities =
477*0fca6ea1SDimitry Andric           VisibilityHelp->getValueAsListInit("Visibilities")->getValues();
478*0fca6ea1SDimitry Andric 
479*0fca6ea1SDimitry Andric       std::vector<std::string> VisibilityNames;
480*0fca6ea1SDimitry Andric       for (Init *Visibility : Visibilities)
481*0fca6ea1SDimitry Andric         VisibilityNames.push_back(Visibility->getAsUnquotedString());
482*0fca6ea1SDimitry Andric 
483*0fca6ea1SDimitry Andric       HelpTextsForVariants.push_back(std::make_pair(
484*0fca6ea1SDimitry Andric           VisibilityNames, VisibilityHelp->getValueAsString("Text")));
485*0fca6ea1SDimitry Andric     }
486*0fca6ea1SDimitry Andric     EmitHelpTextsForVariants(OS, HelpTextsForVariants);
487*0fca6ea1SDimitry Andric 
4880b57cec5SDimitry Andric     // The option meta-variable name.
4890b57cec5SDimitry Andric     OS << ", ";
4900b57cec5SDimitry Andric     if (!isa<UnsetInit>(R.getValueInit("MetaVarName")))
4910b57cec5SDimitry Andric       write_cstring(OS, R.getValueAsString("MetaVarName"));
4920b57cec5SDimitry Andric     else
4930b57cec5SDimitry Andric       OS << "nullptr";
4940b57cec5SDimitry Andric 
4950b57cec5SDimitry Andric     // The option Values. Used for shell autocompletion.
4960b57cec5SDimitry Andric     OS << ", ";
4970b57cec5SDimitry Andric     if (!isa<UnsetInit>(R.getValueInit("Values")))
4980b57cec5SDimitry Andric       write_cstring(OS, R.getValueAsString("Values"));
499bdd1243dSDimitry Andric     else if (!isa<UnsetInit>(R.getValueInit("ValuesCode"))) {
500bdd1243dSDimitry Andric       OS << getOptionName(R) << "_Values";
501*0fca6ea1SDimitry Andric     } else
5020b57cec5SDimitry Andric       OS << "nullptr";
5035ffd83dbSDimitry Andric   };
5040b57cec5SDimitry Andric 
505e8d8bef9SDimitry Andric   auto IsMarshallingOption = [](const Record &R) {
506e8d8bef9SDimitry Andric     return !isa<UnsetInit>(R.getValueInit("KeyPath")) &&
507e8d8bef9SDimitry Andric            !R.getValueAsString("KeyPath").empty();
508e8d8bef9SDimitry Andric   };
5095ffd83dbSDimitry Andric 
510e8d8bef9SDimitry Andric   std::vector<const Record *> OptsWithMarshalling;
511e8d8bef9SDimitry Andric   for (const Record &R : llvm::make_pointee_range(Opts)) {
5125ffd83dbSDimitry Andric     // Start a single option entry.
5135ffd83dbSDimitry Andric     OS << "OPTION(";
5145ffd83dbSDimitry Andric     WriteOptRecordFields(OS, R);
5150b57cec5SDimitry Andric     OS << ")\n";
516e8d8bef9SDimitry Andric     if (IsMarshallingOption(R))
517e8d8bef9SDimitry Andric       OptsWithMarshalling.push_back(&R);
5180b57cec5SDimitry Andric   }
5190b57cec5SDimitry Andric   OS << "#endif // OPTION\n";
5200b57cec5SDimitry Andric 
521e8d8bef9SDimitry Andric   auto CmpMarshallingOpts = [](const Record *const *A, const Record *const *B) {
522e8d8bef9SDimitry Andric     unsigned AID = (*A)->getID();
523e8d8bef9SDimitry Andric     unsigned BID = (*B)->getID();
524e8d8bef9SDimitry Andric 
525e8d8bef9SDimitry Andric     if (AID < BID)
526e8d8bef9SDimitry Andric       return -1;
527e8d8bef9SDimitry Andric     if (AID > BID)
528e8d8bef9SDimitry Andric       return 1;
529e8d8bef9SDimitry Andric     return 0;
530e8d8bef9SDimitry Andric   };
531e8d8bef9SDimitry Andric   // The RecordKeeper stores records (options) in lexicographical order, and we
532e8d8bef9SDimitry Andric   // have reordered the options again when generating prefix groups. We need to
533e8d8bef9SDimitry Andric   // restore the original definition order of options with marshalling to honor
534e8d8bef9SDimitry Andric   // the topology of the dependency graph implied by `DefaultAnyOf`.
535e8d8bef9SDimitry Andric   array_pod_sort(OptsWithMarshalling.begin(), OptsWithMarshalling.end(),
536e8d8bef9SDimitry Andric                  CmpMarshallingOpts);
537e8d8bef9SDimitry Andric 
538e8d8bef9SDimitry Andric   std::vector<MarshallingInfo> MarshallingInfos;
539bdd1243dSDimitry Andric   MarshallingInfos.reserve(OptsWithMarshalling.size());
540e8d8bef9SDimitry Andric   for (const auto *R : OptsWithMarshalling)
541e8d8bef9SDimitry Andric     MarshallingInfos.push_back(createMarshallingInfo(*R));
542e8d8bef9SDimitry Andric 
543e8d8bef9SDimitry Andric   for (const auto &MI : MarshallingInfos) {
544e8d8bef9SDimitry Andric     OS << "#ifdef " << MI.getMacroName() << "\n";
545e8d8bef9SDimitry Andric     OS << MI.getMacroName() << "(";
546e8d8bef9SDimitry Andric     WriteOptRecordFields(OS, MI.R);
5475ffd83dbSDimitry Andric     OS << ", ";
548e8d8bef9SDimitry Andric     MI.emit(OS);
5495ffd83dbSDimitry Andric     OS << ")\n";
550e8d8bef9SDimitry Andric     OS << "#endif // " << MI.getMacroName() << "\n";
5515ffd83dbSDimitry Andric   }
5525ffd83dbSDimitry Andric 
5535ffd83dbSDimitry Andric   OS << "\n";
5545ffd83dbSDimitry Andric   OS << "#ifdef SIMPLE_ENUM_VALUE_TABLE";
5555ffd83dbSDimitry Andric   OS << "\n";
556e8d8bef9SDimitry Andric   OS << MarshallingInfo::ValueTablePreamble;
5575ffd83dbSDimitry Andric   std::vector<StringRef> ValueTableNames;
558e8d8bef9SDimitry Andric   for (const auto &MI : MarshallingInfos)
559e8d8bef9SDimitry Andric     if (auto MaybeValueTableName = MI.emitValueTable(OS))
5605ffd83dbSDimitry Andric       ValueTableNames.push_back(*MaybeValueTableName);
5615ffd83dbSDimitry Andric 
562e8d8bef9SDimitry Andric   OS << MarshallingInfo::ValueTablesDecl << "{";
5635ffd83dbSDimitry Andric   for (auto ValueTableName : ValueTableNames)
564bdd1243dSDimitry Andric     OS << "{" << ValueTableName << ", std::size(" << ValueTableName << ")},\n";
5655ffd83dbSDimitry Andric   OS << "};\n";
5665ffd83dbSDimitry Andric   OS << "static const unsigned SimpleEnumValueTablesSize = "
567bdd1243dSDimitry Andric         "std::size(SimpleEnumValueTables);\n";
5685ffd83dbSDimitry Andric 
5695ffd83dbSDimitry Andric   OS << "#endif // SIMPLE_ENUM_VALUE_TABLE\n";
5705ffd83dbSDimitry Andric   OS << "\n";
5715ffd83dbSDimitry Andric 
5720b57cec5SDimitry Andric   OS << "\n";
5730b57cec5SDimitry Andric }
57406c3fb27SDimitry Andric 
57506c3fb27SDimitry Andric static TableGen::Emitter::Opt X("gen-opt-parser-defs", EmitOptParser,
57606c3fb27SDimitry Andric                                 "Generate option definitions");
577