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
getOptionName(const Record & R)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
write_cstring(raw_ostream & OS,llvm::StringRef Str)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
getOptionPrefixedName(const Record & R)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
MarshallingInfo(const Record & R)85e8d8bef9SDimitry Andric MarshallingInfo(const Record &R) : R(R) {}
86e8d8bef9SDimitry Andric
getMacroName() const87e8d8bef9SDimitry Andric std::string getMacroName() const {
88e8d8bef9SDimitry Andric return (MacroPrefix + MarshallingInfo::MacroName).str();
89e8d8bef9SDimitry Andric }
90e8d8bef9SDimitry Andric
emit(raw_ostream & OS) const91e8d8bef9SDimitry 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
emitValueTable(raw_ostream & OS) const115bdd1243dSDimitry 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:
emitScopedNormalizedValue(raw_ostream & OS,StringRef NormalizedValue) const132e8d8bef9SDimitry 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
createMarshallingInfo(const Record & R)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
EmitHelpTextsForVariants(raw_ostream & OS,std::vector<std::pair<std::vector<std::string>,StringRef>> HelpTextsForVariants)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.
EmitOptParser(RecordKeeper & Records,raw_ostream & OS)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