xref: /freebsd/contrib/llvm-project/llvm/utils/TableGen/OptParserEmitter.cpp (revision 81ad626541db97eb356e2c1d4a20eb2a26a766ab)
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 
37e8d8bef9SDimitry Andric static std::string getOptionSpelling(const Record &R, size_t &PrefixLength) {
385ffd83dbSDimitry Andric   std::vector<StringRef> Prefixes = R.getValueAsListOfStrings("Prefixes");
395ffd83dbSDimitry Andric   StringRef Name = R.getValueAsString("Name");
40e8d8bef9SDimitry Andric 
415ffd83dbSDimitry Andric   if (Prefixes.empty()) {
425ffd83dbSDimitry Andric     PrefixLength = 0;
435ffd83dbSDimitry Andric     return Name.str();
445ffd83dbSDimitry Andric   }
45e8d8bef9SDimitry Andric 
465ffd83dbSDimitry Andric   PrefixLength = Prefixes[0].size();
475ffd83dbSDimitry Andric   return (Twine(Prefixes[0]) + Twine(Name)).str();
485ffd83dbSDimitry Andric }
495ffd83dbSDimitry Andric 
50e8d8bef9SDimitry Andric static std::string getOptionSpelling(const Record &R) {
515ffd83dbSDimitry Andric   size_t PrefixLength;
525ffd83dbSDimitry Andric   return getOptionSpelling(R, PrefixLength);
535ffd83dbSDimitry Andric }
545ffd83dbSDimitry Andric 
555ffd83dbSDimitry Andric static void emitNameUsingSpelling(raw_ostream &OS, const Record &R) {
565ffd83dbSDimitry Andric   size_t PrefixLength;
575ffd83dbSDimitry Andric   OS << "&";
585ffd83dbSDimitry Andric   write_cstring(OS, StringRef(getOptionSpelling(R, PrefixLength)));
595ffd83dbSDimitry Andric   OS << "[" << PrefixLength << "]";
605ffd83dbSDimitry Andric }
615ffd83dbSDimitry Andric 
62e8d8bef9SDimitry Andric class MarshallingInfo {
635ffd83dbSDimitry Andric public:
64e8d8bef9SDimitry Andric   static constexpr const char *MacroName = "OPTION_WITH_MARSHALLING";
655ffd83dbSDimitry Andric   const Record &R;
665ffd83dbSDimitry Andric   bool ShouldAlwaysEmit;
67e8d8bef9SDimitry Andric   StringRef MacroPrefix;
685ffd83dbSDimitry Andric   StringRef KeyPath;
695ffd83dbSDimitry Andric   StringRef DefaultValue;
705ffd83dbSDimitry Andric   StringRef NormalizedValuesScope;
71e8d8bef9SDimitry Andric   StringRef ImpliedCheck;
72e8d8bef9SDimitry Andric   StringRef ImpliedValue;
73e8d8bef9SDimitry Andric   StringRef ShouldParse;
745ffd83dbSDimitry Andric   StringRef Normalizer;
755ffd83dbSDimitry Andric   StringRef Denormalizer;
76e8d8bef9SDimitry Andric   StringRef ValueMerger;
77e8d8bef9SDimitry Andric   StringRef ValueExtractor;
785ffd83dbSDimitry Andric   int TableIndex = -1;
795ffd83dbSDimitry Andric   std::vector<StringRef> Values;
805ffd83dbSDimitry Andric   std::vector<StringRef> NormalizedValues;
815ffd83dbSDimitry Andric   std::string ValueTableName;
825ffd83dbSDimitry Andric 
83e8d8bef9SDimitry Andric   static size_t NextTableIndex;
84e8d8bef9SDimitry Andric 
855ffd83dbSDimitry Andric   static constexpr const char *ValueTablePreamble = R"(
865ffd83dbSDimitry Andric struct SimpleEnumValue {
875ffd83dbSDimitry Andric   const char *Name;
885ffd83dbSDimitry Andric   unsigned Value;
895ffd83dbSDimitry Andric };
905ffd83dbSDimitry Andric 
915ffd83dbSDimitry Andric struct SimpleEnumValueTable {
925ffd83dbSDimitry Andric   const SimpleEnumValue *Table;
935ffd83dbSDimitry Andric   unsigned Size;
945ffd83dbSDimitry Andric };
955ffd83dbSDimitry Andric )";
965ffd83dbSDimitry Andric 
975ffd83dbSDimitry Andric   static constexpr const char *ValueTablesDecl =
985ffd83dbSDimitry Andric       "static const SimpleEnumValueTable SimpleEnumValueTables[] = ";
995ffd83dbSDimitry Andric 
100e8d8bef9SDimitry Andric   MarshallingInfo(const Record &R) : R(R) {}
101e8d8bef9SDimitry Andric 
102e8d8bef9SDimitry Andric   std::string getMacroName() const {
103e8d8bef9SDimitry Andric     return (MacroPrefix + MarshallingInfo::MacroName).str();
104e8d8bef9SDimitry Andric   }
105e8d8bef9SDimitry Andric 
106e8d8bef9SDimitry Andric   void emit(raw_ostream &OS) const {
107e8d8bef9SDimitry Andric     write_cstring(OS, StringRef(getOptionSpelling(R)));
108e8d8bef9SDimitry Andric     OS << ", ";
109e8d8bef9SDimitry Andric     OS << ShouldParse;
110e8d8bef9SDimitry Andric     OS << ", ";
111e8d8bef9SDimitry Andric     OS << ShouldAlwaysEmit;
112e8d8bef9SDimitry Andric     OS << ", ";
113e8d8bef9SDimitry Andric     OS << KeyPath;
114e8d8bef9SDimitry Andric     OS << ", ";
115e8d8bef9SDimitry Andric     emitScopedNormalizedValue(OS, DefaultValue);
116e8d8bef9SDimitry Andric     OS << ", ";
117e8d8bef9SDimitry Andric     OS << ImpliedCheck;
118e8d8bef9SDimitry Andric     OS << ", ";
119e8d8bef9SDimitry Andric     emitScopedNormalizedValue(OS, ImpliedValue);
1205ffd83dbSDimitry Andric     OS << ", ";
1215ffd83dbSDimitry Andric     OS << Normalizer;
1225ffd83dbSDimitry Andric     OS << ", ";
1235ffd83dbSDimitry Andric     OS << Denormalizer;
1245ffd83dbSDimitry Andric     OS << ", ";
125e8d8bef9SDimitry Andric     OS << ValueMerger;
126e8d8bef9SDimitry Andric     OS << ", ";
127e8d8bef9SDimitry Andric     OS << ValueExtractor;
128e8d8bef9SDimitry Andric     OS << ", ";
1295ffd83dbSDimitry Andric     OS << TableIndex;
1305ffd83dbSDimitry Andric   }
1315ffd83dbSDimitry Andric 
132e8d8bef9SDimitry Andric   Optional<StringRef> emitValueTable(raw_ostream &OS) const {
1335ffd83dbSDimitry Andric     if (TableIndex == -1)
1345ffd83dbSDimitry Andric       return {};
1355ffd83dbSDimitry Andric     OS << "static const SimpleEnumValue " << ValueTableName << "[] = {\n";
1365ffd83dbSDimitry Andric     for (unsigned I = 0, E = Values.size(); I != E; ++I) {
1375ffd83dbSDimitry Andric       OS << "{";
1385ffd83dbSDimitry Andric       write_cstring(OS, Values[I]);
1395ffd83dbSDimitry Andric       OS << ",";
1405ffd83dbSDimitry Andric       OS << "static_cast<unsigned>(";
1415ffd83dbSDimitry Andric       emitScopedNormalizedValue(OS, NormalizedValues[I]);
1425ffd83dbSDimitry Andric       OS << ")},";
1435ffd83dbSDimitry Andric     }
1445ffd83dbSDimitry Andric     OS << "};\n";
1455ffd83dbSDimitry Andric     return StringRef(ValueTableName);
1465ffd83dbSDimitry Andric   }
1475ffd83dbSDimitry Andric 
148e8d8bef9SDimitry Andric private:
149e8d8bef9SDimitry Andric   void emitScopedNormalizedValue(raw_ostream &OS,
150e8d8bef9SDimitry Andric                                  StringRef NormalizedValue) const {
151e8d8bef9SDimitry Andric     if (!NormalizedValuesScope.empty())
152e8d8bef9SDimitry Andric       OS << NormalizedValuesScope << "::";
153e8d8bef9SDimitry Andric     OS << NormalizedValue;
154e8d8bef9SDimitry Andric   }
155e8d8bef9SDimitry Andric };
1565ffd83dbSDimitry Andric 
157e8d8bef9SDimitry Andric size_t MarshallingInfo::NextTableIndex = 0;
1585ffd83dbSDimitry Andric 
159e8d8bef9SDimitry Andric static MarshallingInfo createMarshallingInfo(const Record &R) {
160e8d8bef9SDimitry Andric   assert(!isa<UnsetInit>(R.getValueInit("KeyPath")) &&
161e8d8bef9SDimitry Andric          !isa<UnsetInit>(R.getValueInit("DefaultValue")) &&
162e8d8bef9SDimitry Andric          !isa<UnsetInit>(R.getValueInit("ValueMerger")) &&
163e8d8bef9SDimitry Andric          "MarshallingInfo must have a provide a keypath, default value and a "
164e8d8bef9SDimitry Andric          "value merger");
165e8d8bef9SDimitry Andric 
166e8d8bef9SDimitry Andric   MarshallingInfo Ret(R);
167e8d8bef9SDimitry Andric 
168e8d8bef9SDimitry Andric   Ret.ShouldAlwaysEmit = R.getValueAsBit("ShouldAlwaysEmit");
169e8d8bef9SDimitry Andric   Ret.MacroPrefix = R.getValueAsString("MacroPrefix");
170e8d8bef9SDimitry Andric   Ret.KeyPath = R.getValueAsString("KeyPath");
171e8d8bef9SDimitry Andric   Ret.DefaultValue = R.getValueAsString("DefaultValue");
172e8d8bef9SDimitry Andric   Ret.NormalizedValuesScope = R.getValueAsString("NormalizedValuesScope");
173e8d8bef9SDimitry Andric   Ret.ImpliedCheck = R.getValueAsString("ImpliedCheck");
174e8d8bef9SDimitry Andric   Ret.ImpliedValue =
175*81ad6265SDimitry Andric       R.getValueAsOptionalString("ImpliedValue").value_or(Ret.DefaultValue);
176e8d8bef9SDimitry Andric 
177e8d8bef9SDimitry Andric   Ret.ShouldParse = R.getValueAsString("ShouldParse");
178e8d8bef9SDimitry Andric   Ret.Normalizer = R.getValueAsString("Normalizer");
179e8d8bef9SDimitry Andric   Ret.Denormalizer = R.getValueAsString("Denormalizer");
180e8d8bef9SDimitry Andric   Ret.ValueMerger = R.getValueAsString("ValueMerger");
181e8d8bef9SDimitry Andric   Ret.ValueExtractor = R.getValueAsString("ValueExtractor");
1825ffd83dbSDimitry Andric 
1835ffd83dbSDimitry Andric   if (!isa<UnsetInit>(R.getValueInit("NormalizedValues"))) {
1845ffd83dbSDimitry Andric     assert(!isa<UnsetInit>(R.getValueInit("Values")) &&
1855ffd83dbSDimitry Andric            "Cannot provide normalized values for value-less options");
186e8d8bef9SDimitry Andric     Ret.TableIndex = MarshallingInfo::NextTableIndex++;
187e8d8bef9SDimitry Andric     Ret.NormalizedValues = R.getValueAsListOfStrings("NormalizedValues");
188e8d8bef9SDimitry Andric     Ret.Values.reserve(Ret.NormalizedValues.size());
189e8d8bef9SDimitry Andric     Ret.ValueTableName = getOptionName(R) + "ValueTable";
1905ffd83dbSDimitry Andric 
1915ffd83dbSDimitry Andric     StringRef ValuesStr = R.getValueAsString("Values");
1925ffd83dbSDimitry Andric     for (;;) {
1935ffd83dbSDimitry Andric       size_t Idx = ValuesStr.find(',');
1945ffd83dbSDimitry Andric       if (Idx == StringRef::npos)
1955ffd83dbSDimitry Andric         break;
1965ffd83dbSDimitry Andric       if (Idx > 0)
197e8d8bef9SDimitry Andric         Ret.Values.push_back(ValuesStr.slice(0, Idx));
1985ffd83dbSDimitry Andric       ValuesStr = ValuesStr.slice(Idx + 1, StringRef::npos);
1995ffd83dbSDimitry Andric     }
2005ffd83dbSDimitry Andric     if (!ValuesStr.empty())
201e8d8bef9SDimitry Andric       Ret.Values.push_back(ValuesStr);
2025ffd83dbSDimitry Andric 
203e8d8bef9SDimitry Andric     assert(Ret.Values.size() == Ret.NormalizedValues.size() &&
2045ffd83dbSDimitry Andric            "The number of normalized values doesn't match the number of "
2055ffd83dbSDimitry Andric            "values");
2065ffd83dbSDimitry Andric   }
2075ffd83dbSDimitry Andric 
2085ffd83dbSDimitry Andric   return Ret;
2095ffd83dbSDimitry Andric }
2105ffd83dbSDimitry Andric 
2110b57cec5SDimitry Andric /// OptParserEmitter - This tablegen backend takes an input .td file
2120b57cec5SDimitry Andric /// describing a list of options and emits a data structure for parsing and
2130b57cec5SDimitry Andric /// working with those options when given an input command line.
2140b57cec5SDimitry Andric namespace llvm {
2150b57cec5SDimitry Andric void EmitOptParser(RecordKeeper &Records, raw_ostream &OS) {
2160b57cec5SDimitry Andric   // Get the option groups and options.
2170b57cec5SDimitry Andric   const std::vector<Record*> &Groups =
2180b57cec5SDimitry Andric     Records.getAllDerivedDefinitions("OptionGroup");
2190b57cec5SDimitry Andric   std::vector<Record*> Opts = Records.getAllDerivedDefinitions("Option");
2200b57cec5SDimitry Andric 
2210b57cec5SDimitry Andric   emitSourceFileHeader("Option Parsing Definitions", OS);
2220b57cec5SDimitry Andric 
2230b57cec5SDimitry Andric   array_pod_sort(Opts.begin(), Opts.end(), CompareOptionRecords);
2240b57cec5SDimitry Andric   // Generate prefix groups.
2250b57cec5SDimitry Andric   typedef SmallVector<SmallString<2>, 2> PrefixKeyT;
2260b57cec5SDimitry Andric   typedef std::map<PrefixKeyT, std::string> PrefixesT;
2270b57cec5SDimitry Andric   PrefixesT Prefixes;
2280b57cec5SDimitry Andric   Prefixes.insert(std::make_pair(PrefixKeyT(), "prefix_0"));
2290b57cec5SDimitry Andric   unsigned CurPrefix = 0;
230e8d8bef9SDimitry Andric   for (const Record &R : llvm::make_pointee_range(Opts)) {
231e8d8bef9SDimitry Andric     std::vector<StringRef> RPrefixes = R.getValueAsListOfStrings("Prefixes");
232e8d8bef9SDimitry Andric     PrefixKeyT PrefixKey(RPrefixes.begin(), RPrefixes.end());
2330b57cec5SDimitry Andric     unsigned NewPrefix = CurPrefix + 1;
234e8d8bef9SDimitry Andric     std::string Prefix = (Twine("prefix_") + Twine(NewPrefix)).str();
235e8d8bef9SDimitry Andric     if (Prefixes.insert(std::make_pair(PrefixKey, Prefix)).second)
2360b57cec5SDimitry Andric       CurPrefix = NewPrefix;
2370b57cec5SDimitry Andric   }
2380b57cec5SDimitry Andric 
2390b57cec5SDimitry Andric   // Dump prefixes.
2400b57cec5SDimitry Andric 
2410b57cec5SDimitry Andric   OS << "/////////\n";
2420b57cec5SDimitry Andric   OS << "// Prefixes\n\n";
2430b57cec5SDimitry Andric   OS << "#ifdef PREFIX\n";
2440b57cec5SDimitry Andric   OS << "#define COMMA ,\n";
245e8d8bef9SDimitry Andric   for (const auto &Prefix : Prefixes) {
2460b57cec5SDimitry Andric     OS << "PREFIX(";
2470b57cec5SDimitry Andric 
2480b57cec5SDimitry Andric     // Prefix name.
249e8d8bef9SDimitry Andric     OS << Prefix.second;
2500b57cec5SDimitry Andric 
2510b57cec5SDimitry Andric     // Prefix values.
2520b57cec5SDimitry Andric     OS << ", {";
253fe6060f1SDimitry Andric     for (const auto &PrefixKey : Prefix.first)
254e8d8bef9SDimitry Andric       OS << "\"" << PrefixKey << "\" COMMA ";
2550b57cec5SDimitry Andric     OS << "nullptr})\n";
2560b57cec5SDimitry Andric   }
2570b57cec5SDimitry Andric   OS << "#undef COMMA\n";
2580b57cec5SDimitry Andric   OS << "#endif // PREFIX\n\n";
2590b57cec5SDimitry Andric 
2600b57cec5SDimitry Andric   OS << "/////////\n";
2610b57cec5SDimitry Andric   OS << "// Groups\n\n";
2620b57cec5SDimitry Andric   OS << "#ifdef OPTION\n";
263e8d8bef9SDimitry Andric   for (const Record &R : llvm::make_pointee_range(Groups)) {
2640b57cec5SDimitry Andric     // Start a single option entry.
2650b57cec5SDimitry Andric     OS << "OPTION(";
2660b57cec5SDimitry Andric 
2670b57cec5SDimitry Andric     // The option prefix;
2680b57cec5SDimitry Andric     OS << "nullptr";
2690b57cec5SDimitry Andric 
2700b57cec5SDimitry Andric     // The option string.
2710b57cec5SDimitry Andric     OS << ", \"" << R.getValueAsString("Name") << '"';
2720b57cec5SDimitry Andric 
2730b57cec5SDimitry Andric     // The option identifier name.
2740b57cec5SDimitry Andric     OS << ", " << getOptionName(R);
2750b57cec5SDimitry Andric 
2760b57cec5SDimitry Andric     // The option kind.
2770b57cec5SDimitry Andric     OS << ", Group";
2780b57cec5SDimitry Andric 
2790b57cec5SDimitry Andric     // The containing option group (if any).
2800b57cec5SDimitry Andric     OS << ", ";
2810b57cec5SDimitry Andric     if (const DefInit *DI = dyn_cast<DefInit>(R.getValueInit("Group")))
2820b57cec5SDimitry Andric       OS << getOptionName(*DI->getDef());
2830b57cec5SDimitry Andric     else
2840b57cec5SDimitry Andric       OS << "INVALID";
2850b57cec5SDimitry Andric 
2860b57cec5SDimitry Andric     // The other option arguments (unused for groups).
2870b57cec5SDimitry Andric     OS << ", INVALID, nullptr, 0, 0";
2880b57cec5SDimitry Andric 
2890b57cec5SDimitry Andric     // The option help text.
2900b57cec5SDimitry Andric     if (!isa<UnsetInit>(R.getValueInit("HelpText"))) {
2910b57cec5SDimitry Andric       OS << ",\n";
2920b57cec5SDimitry Andric       OS << "       ";
2930b57cec5SDimitry Andric       write_cstring(OS, R.getValueAsString("HelpText"));
2940b57cec5SDimitry Andric     } else
2950b57cec5SDimitry Andric       OS << ", nullptr";
2960b57cec5SDimitry Andric 
2970b57cec5SDimitry Andric     // The option meta-variable name (unused).
2980b57cec5SDimitry Andric     OS << ", nullptr";
2990b57cec5SDimitry Andric 
3000b57cec5SDimitry Andric     // The option Values (unused for groups).
3010b57cec5SDimitry Andric     OS << ", nullptr)\n";
3020b57cec5SDimitry Andric   }
3030b57cec5SDimitry Andric   OS << "\n";
3040b57cec5SDimitry Andric 
3050b57cec5SDimitry Andric   OS << "//////////\n";
3060b57cec5SDimitry Andric   OS << "// Options\n\n";
3070b57cec5SDimitry Andric 
3085ffd83dbSDimitry Andric   auto WriteOptRecordFields = [&](raw_ostream &OS, const Record &R) {
3090b57cec5SDimitry Andric     // The option prefix;
310e8d8bef9SDimitry Andric     std::vector<StringRef> RPrefixes = R.getValueAsListOfStrings("Prefixes");
311e8d8bef9SDimitry Andric     OS << Prefixes[PrefixKeyT(RPrefixes.begin(), RPrefixes.end())] << ", ";
3120b57cec5SDimitry Andric 
3130b57cec5SDimitry Andric     // The option string.
3145ffd83dbSDimitry Andric     emitNameUsingSpelling(OS, R);
3150b57cec5SDimitry Andric 
3160b57cec5SDimitry Andric     // The option identifier name.
3170b57cec5SDimitry Andric     OS << ", " << getOptionName(R);
3180b57cec5SDimitry Andric 
3190b57cec5SDimitry Andric     // The option kind.
3200b57cec5SDimitry Andric     OS << ", " << R.getValueAsDef("Kind")->getValueAsString("Name");
3210b57cec5SDimitry Andric 
3220b57cec5SDimitry Andric     // The containing option group (if any).
3230b57cec5SDimitry Andric     OS << ", ";
3240b57cec5SDimitry Andric     const ListInit *GroupFlags = nullptr;
3250b57cec5SDimitry Andric     if (const DefInit *DI = dyn_cast<DefInit>(R.getValueInit("Group"))) {
3260b57cec5SDimitry Andric       GroupFlags = DI->getDef()->getValueAsListInit("Flags");
3270b57cec5SDimitry Andric       OS << getOptionName(*DI->getDef());
3280b57cec5SDimitry Andric     } else
3290b57cec5SDimitry Andric       OS << "INVALID";
3300b57cec5SDimitry Andric 
3310b57cec5SDimitry Andric     // The option alias (if any).
3320b57cec5SDimitry Andric     OS << ", ";
3330b57cec5SDimitry Andric     if (const DefInit *DI = dyn_cast<DefInit>(R.getValueInit("Alias")))
3340b57cec5SDimitry Andric       OS << getOptionName(*DI->getDef());
3350b57cec5SDimitry Andric     else
3360b57cec5SDimitry Andric       OS << "INVALID";
3370b57cec5SDimitry Andric 
3380b57cec5SDimitry Andric     // The option alias arguments (if any).
3390b57cec5SDimitry Andric     // Emitted as a \0 separated list in a string, e.g. ["foo", "bar"]
3400b57cec5SDimitry Andric     // would become "foo\0bar\0". Note that the compiler adds an implicit
3410b57cec5SDimitry Andric     // terminating \0 at the end.
3420b57cec5SDimitry Andric     OS << ", ";
3430b57cec5SDimitry Andric     std::vector<StringRef> AliasArgs = R.getValueAsListOfStrings("AliasArgs");
3440b57cec5SDimitry Andric     if (AliasArgs.size() == 0) {
3450b57cec5SDimitry Andric       OS << "nullptr";
3460b57cec5SDimitry Andric     } else {
3470b57cec5SDimitry Andric       OS << "\"";
348e8d8bef9SDimitry Andric       for (StringRef AliasArg : AliasArgs)
349e8d8bef9SDimitry Andric         OS << AliasArg << "\\0";
3500b57cec5SDimitry Andric       OS << "\"";
3510b57cec5SDimitry Andric     }
3520b57cec5SDimitry Andric 
3530b57cec5SDimitry Andric     // The option flags.
3540b57cec5SDimitry Andric     OS << ", ";
3550b57cec5SDimitry Andric     int NumFlags = 0;
3560b57cec5SDimitry Andric     const ListInit *LI = R.getValueAsListInit("Flags");
3570b57cec5SDimitry Andric     for (Init *I : *LI)
3585ffd83dbSDimitry Andric       OS << (NumFlags++ ? " | " : "") << cast<DefInit>(I)->getDef()->getName();
3590b57cec5SDimitry Andric     if (GroupFlags) {
3600b57cec5SDimitry Andric       for (Init *I : *GroupFlags)
3610b57cec5SDimitry Andric         OS << (NumFlags++ ? " | " : "")
3620b57cec5SDimitry Andric            << cast<DefInit>(I)->getDef()->getName();
3630b57cec5SDimitry Andric     }
3640b57cec5SDimitry Andric     if (NumFlags == 0)
3650b57cec5SDimitry Andric       OS << '0';
3660b57cec5SDimitry Andric 
3670b57cec5SDimitry Andric     // The option parameter field.
3680b57cec5SDimitry Andric     OS << ", " << R.getValueAsInt("NumArgs");
3690b57cec5SDimitry Andric 
3700b57cec5SDimitry Andric     // The option help text.
3710b57cec5SDimitry Andric     if (!isa<UnsetInit>(R.getValueInit("HelpText"))) {
3720b57cec5SDimitry Andric       OS << ",\n";
3730b57cec5SDimitry Andric       OS << "       ";
3740b57cec5SDimitry Andric       write_cstring(OS, R.getValueAsString("HelpText"));
3750b57cec5SDimitry Andric     } else
3760b57cec5SDimitry Andric       OS << ", nullptr";
3770b57cec5SDimitry Andric 
3780b57cec5SDimitry Andric     // The option meta-variable name.
3790b57cec5SDimitry Andric     OS << ", ";
3800b57cec5SDimitry Andric     if (!isa<UnsetInit>(R.getValueInit("MetaVarName")))
3810b57cec5SDimitry Andric       write_cstring(OS, R.getValueAsString("MetaVarName"));
3820b57cec5SDimitry Andric     else
3830b57cec5SDimitry Andric       OS << "nullptr";
3840b57cec5SDimitry Andric 
3850b57cec5SDimitry Andric     // The option Values. Used for shell autocompletion.
3860b57cec5SDimitry Andric     OS << ", ";
3870b57cec5SDimitry Andric     if (!isa<UnsetInit>(R.getValueInit("Values")))
3880b57cec5SDimitry Andric       write_cstring(OS, R.getValueAsString("Values"));
3890b57cec5SDimitry Andric     else
3900b57cec5SDimitry Andric       OS << "nullptr";
3915ffd83dbSDimitry Andric   };
3920b57cec5SDimitry Andric 
393e8d8bef9SDimitry Andric   auto IsMarshallingOption = [](const Record &R) {
394e8d8bef9SDimitry Andric     return !isa<UnsetInit>(R.getValueInit("KeyPath")) &&
395e8d8bef9SDimitry Andric            !R.getValueAsString("KeyPath").empty();
396e8d8bef9SDimitry Andric   };
3975ffd83dbSDimitry Andric 
398e8d8bef9SDimitry Andric   std::vector<const Record *> OptsWithMarshalling;
399e8d8bef9SDimitry Andric   for (const Record &R : llvm::make_pointee_range(Opts)) {
4005ffd83dbSDimitry Andric     // Start a single option entry.
4015ffd83dbSDimitry Andric     OS << "OPTION(";
4025ffd83dbSDimitry Andric     WriteOptRecordFields(OS, R);
4030b57cec5SDimitry Andric     OS << ")\n";
404e8d8bef9SDimitry Andric     if (IsMarshallingOption(R))
405e8d8bef9SDimitry Andric       OptsWithMarshalling.push_back(&R);
4060b57cec5SDimitry Andric   }
4070b57cec5SDimitry Andric   OS << "#endif // OPTION\n";
4080b57cec5SDimitry Andric 
409e8d8bef9SDimitry Andric   auto CmpMarshallingOpts = [](const Record *const *A, const Record *const *B) {
410e8d8bef9SDimitry Andric     unsigned AID = (*A)->getID();
411e8d8bef9SDimitry Andric     unsigned BID = (*B)->getID();
412e8d8bef9SDimitry Andric 
413e8d8bef9SDimitry Andric     if (AID < BID)
414e8d8bef9SDimitry Andric       return -1;
415e8d8bef9SDimitry Andric     if (AID > BID)
416e8d8bef9SDimitry Andric       return 1;
417e8d8bef9SDimitry Andric     return 0;
418e8d8bef9SDimitry Andric   };
419e8d8bef9SDimitry Andric   // The RecordKeeper stores records (options) in lexicographical order, and we
420e8d8bef9SDimitry Andric   // have reordered the options again when generating prefix groups. We need to
421e8d8bef9SDimitry Andric   // restore the original definition order of options with marshalling to honor
422e8d8bef9SDimitry Andric   // the topology of the dependency graph implied by `DefaultAnyOf`.
423e8d8bef9SDimitry Andric   array_pod_sort(OptsWithMarshalling.begin(), OptsWithMarshalling.end(),
424e8d8bef9SDimitry Andric                  CmpMarshallingOpts);
425e8d8bef9SDimitry Andric 
426e8d8bef9SDimitry Andric   std::vector<MarshallingInfo> MarshallingInfos;
427e8d8bef9SDimitry Andric   for (const auto *R : OptsWithMarshalling)
428e8d8bef9SDimitry Andric     MarshallingInfos.push_back(createMarshallingInfo(*R));
429e8d8bef9SDimitry Andric 
430e8d8bef9SDimitry Andric   for (const auto &MI : MarshallingInfos) {
431e8d8bef9SDimitry Andric     OS << "#ifdef " << MI.getMacroName() << "\n";
432e8d8bef9SDimitry Andric     OS << MI.getMacroName() << "(";
433e8d8bef9SDimitry Andric     WriteOptRecordFields(OS, MI.R);
4345ffd83dbSDimitry Andric     OS << ", ";
435e8d8bef9SDimitry Andric     MI.emit(OS);
4365ffd83dbSDimitry Andric     OS << ")\n";
437e8d8bef9SDimitry Andric     OS << "#endif // " << MI.getMacroName() << "\n";
4385ffd83dbSDimitry Andric   }
4395ffd83dbSDimitry Andric 
4405ffd83dbSDimitry Andric   OS << "\n";
4415ffd83dbSDimitry Andric   OS << "#ifdef SIMPLE_ENUM_VALUE_TABLE";
4425ffd83dbSDimitry Andric   OS << "\n";
443e8d8bef9SDimitry Andric   OS << MarshallingInfo::ValueTablePreamble;
4445ffd83dbSDimitry Andric   std::vector<StringRef> ValueTableNames;
445e8d8bef9SDimitry Andric   for (const auto &MI : MarshallingInfos)
446e8d8bef9SDimitry Andric     if (auto MaybeValueTableName = MI.emitValueTable(OS))
4475ffd83dbSDimitry Andric       ValueTableNames.push_back(*MaybeValueTableName);
4485ffd83dbSDimitry Andric 
449e8d8bef9SDimitry Andric   OS << MarshallingInfo::ValueTablesDecl << "{";
4505ffd83dbSDimitry Andric   for (auto ValueTableName : ValueTableNames)
4515ffd83dbSDimitry Andric     OS << "{" << ValueTableName << ", sizeof(" << ValueTableName
4525ffd83dbSDimitry Andric        << ") / sizeof(SimpleEnumValue)"
4535ffd83dbSDimitry Andric        << "},\n";
4545ffd83dbSDimitry Andric   OS << "};\n";
4555ffd83dbSDimitry Andric   OS << "static const unsigned SimpleEnumValueTablesSize = "
4565ffd83dbSDimitry Andric         "sizeof(SimpleEnumValueTables) / sizeof(SimpleEnumValueTable);\n";
4575ffd83dbSDimitry Andric 
4585ffd83dbSDimitry Andric   OS << "#endif // SIMPLE_ENUM_VALUE_TABLE\n";
4595ffd83dbSDimitry Andric   OS << "\n";
4605ffd83dbSDimitry Andric 
4610b57cec5SDimitry Andric   OS << "\n";
4620b57cec5SDimitry Andric   OS << "#ifdef OPTTABLE_ARG_INIT\n";
4630b57cec5SDimitry Andric   OS << "//////////\n";
4640b57cec5SDimitry Andric   OS << "// Option Values\n\n";
465e8d8bef9SDimitry Andric   for (const Record &R : llvm::make_pointee_range(Opts)) {
4660b57cec5SDimitry Andric     if (isa<UnsetInit>(R.getValueInit("ValuesCode")))
4670b57cec5SDimitry Andric       continue;
4680b57cec5SDimitry Andric     OS << "{\n";
4690b57cec5SDimitry Andric     OS << "bool ValuesWereAdded;\n";
4700b57cec5SDimitry Andric     OS << R.getValueAsString("ValuesCode");
4710b57cec5SDimitry Andric     OS << "\n";
4725ffd83dbSDimitry Andric     for (StringRef Prefix : R.getValueAsListOfStrings("Prefixes")) {
4730b57cec5SDimitry Andric       OS << "ValuesWereAdded = Opt.addValues(";
4745ffd83dbSDimitry Andric       std::string S(Prefix);
475480093f4SDimitry Andric       S += R.getValueAsString("Name");
4760b57cec5SDimitry Andric       write_cstring(OS, S);
4770b57cec5SDimitry Andric       OS << ", Values);\n";
4780b57cec5SDimitry Andric       OS << "(void)ValuesWereAdded;\n";
4790b57cec5SDimitry Andric       OS << "assert(ValuesWereAdded && \"Couldn't add values to "
4800b57cec5SDimitry Andric             "OptTable!\");\n";
4810b57cec5SDimitry Andric     }
4820b57cec5SDimitry Andric     OS << "}\n";
4830b57cec5SDimitry Andric   }
4840b57cec5SDimitry Andric   OS << "\n";
4850b57cec5SDimitry Andric   OS << "#endif // OPTTABLE_ARG_INIT\n";
4860b57cec5SDimitry Andric }
4870b57cec5SDimitry Andric } // end namespace llvm
488