xref: /freebsd/contrib/llvm-project/llvm/utils/TableGen/OptParserEmitter.cpp (revision 5ffd83dbcc34f10e07f6d3e968ae6365869615f4)
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"
13*5ffd83dbSDimitry Andric #include "llvm/Support/raw_ostream.h"
140b57cec5SDimitry Andric #include "llvm/TableGen/Record.h"
150b57cec5SDimitry Andric #include "llvm/TableGen/TableGenBackend.h"
160b57cec5SDimitry Andric #include <cctype>
170b57cec5SDimitry Andric #include <cstring>
180b57cec5SDimitry Andric #include <map>
19*5ffd83dbSDimitry Andric #include <memory>
200b57cec5SDimitry Andric 
210b57cec5SDimitry Andric using namespace llvm;
220b57cec5SDimitry Andric 
230b57cec5SDimitry Andric static const std::string getOptionName(const Record &R) {
240b57cec5SDimitry Andric   // Use the record name unless EnumName is defined.
250b57cec5SDimitry Andric   if (isa<UnsetInit>(R.getValueInit("EnumName")))
26*5ffd83dbSDimitry Andric     return std::string(R.getName());
270b57cec5SDimitry Andric 
28*5ffd83dbSDimitry Andric   return std::string(R.getValueAsString("EnumName"));
290b57cec5SDimitry Andric }
300b57cec5SDimitry Andric 
310b57cec5SDimitry Andric static raw_ostream &write_cstring(raw_ostream &OS, llvm::StringRef Str) {
320b57cec5SDimitry Andric   OS << '"';
330b57cec5SDimitry Andric   OS.write_escaped(Str);
340b57cec5SDimitry Andric   OS << '"';
350b57cec5SDimitry Andric   return OS;
360b57cec5SDimitry Andric }
370b57cec5SDimitry Andric 
38*5ffd83dbSDimitry Andric static const std::string getOptionSpelling(const Record &R,
39*5ffd83dbSDimitry Andric                                            size_t &PrefixLength) {
40*5ffd83dbSDimitry Andric   std::vector<StringRef> Prefixes = R.getValueAsListOfStrings("Prefixes");
41*5ffd83dbSDimitry Andric   StringRef Name = R.getValueAsString("Name");
42*5ffd83dbSDimitry Andric   if (Prefixes.empty()) {
43*5ffd83dbSDimitry Andric     PrefixLength = 0;
44*5ffd83dbSDimitry Andric     return Name.str();
45*5ffd83dbSDimitry Andric   }
46*5ffd83dbSDimitry Andric   PrefixLength = Prefixes[0].size();
47*5ffd83dbSDimitry Andric   return (Twine(Prefixes[0]) + Twine(Name)).str();
48*5ffd83dbSDimitry Andric }
49*5ffd83dbSDimitry Andric 
50*5ffd83dbSDimitry Andric static const std::string getOptionSpelling(const Record &R) {
51*5ffd83dbSDimitry Andric   size_t PrefixLength;
52*5ffd83dbSDimitry Andric   return getOptionSpelling(R, PrefixLength);
53*5ffd83dbSDimitry Andric }
54*5ffd83dbSDimitry Andric 
55*5ffd83dbSDimitry Andric static void emitNameUsingSpelling(raw_ostream &OS, const Record &R) {
56*5ffd83dbSDimitry Andric   size_t PrefixLength;
57*5ffd83dbSDimitry Andric   OS << "&";
58*5ffd83dbSDimitry Andric   write_cstring(OS, StringRef(getOptionSpelling(R, PrefixLength)));
59*5ffd83dbSDimitry Andric   OS << "[" << PrefixLength << "]";
60*5ffd83dbSDimitry Andric }
61*5ffd83dbSDimitry Andric 
62*5ffd83dbSDimitry Andric class MarshallingKindInfo {
63*5ffd83dbSDimitry Andric public:
64*5ffd83dbSDimitry Andric   const Record &R;
65*5ffd83dbSDimitry Andric   const char *MacroName;
66*5ffd83dbSDimitry Andric   bool ShouldAlwaysEmit;
67*5ffd83dbSDimitry Andric   StringRef KeyPath;
68*5ffd83dbSDimitry Andric   StringRef DefaultValue;
69*5ffd83dbSDimitry Andric   StringRef NormalizedValuesScope;
70*5ffd83dbSDimitry Andric 
71*5ffd83dbSDimitry Andric   void emit(raw_ostream &OS) const {
72*5ffd83dbSDimitry Andric     write_cstring(OS, StringRef(getOptionSpelling(R)));
73*5ffd83dbSDimitry Andric     OS << ", ";
74*5ffd83dbSDimitry Andric     OS << ShouldAlwaysEmit;
75*5ffd83dbSDimitry Andric     OS << ", ";
76*5ffd83dbSDimitry Andric     OS << KeyPath;
77*5ffd83dbSDimitry Andric     OS << ", ";
78*5ffd83dbSDimitry Andric     emitScopedNormalizedValue(OS, DefaultValue);
79*5ffd83dbSDimitry Andric     OS << ", ";
80*5ffd83dbSDimitry Andric     emitSpecific(OS);
81*5ffd83dbSDimitry Andric   }
82*5ffd83dbSDimitry Andric 
83*5ffd83dbSDimitry Andric   virtual Optional<StringRef> emitValueTable(raw_ostream &OS) const {
84*5ffd83dbSDimitry Andric     return None;
85*5ffd83dbSDimitry Andric   }
86*5ffd83dbSDimitry Andric 
87*5ffd83dbSDimitry Andric   virtual ~MarshallingKindInfo() = default;
88*5ffd83dbSDimitry Andric 
89*5ffd83dbSDimitry Andric   static std::unique_ptr<MarshallingKindInfo> create(const Record &R);
90*5ffd83dbSDimitry Andric 
91*5ffd83dbSDimitry Andric protected:
92*5ffd83dbSDimitry Andric   void emitScopedNormalizedValue(raw_ostream &OS,
93*5ffd83dbSDimitry Andric                                  StringRef NormalizedValue) const {
94*5ffd83dbSDimitry Andric     if (!NormalizedValuesScope.empty())
95*5ffd83dbSDimitry Andric       OS << NormalizedValuesScope << "::";
96*5ffd83dbSDimitry Andric     OS << NormalizedValue;
97*5ffd83dbSDimitry Andric   }
98*5ffd83dbSDimitry Andric 
99*5ffd83dbSDimitry Andric   virtual void emitSpecific(raw_ostream &OS) const = 0;
100*5ffd83dbSDimitry Andric   MarshallingKindInfo(const Record &R, const char *MacroName)
101*5ffd83dbSDimitry Andric       : R(R), MacroName(MacroName) {}
102*5ffd83dbSDimitry Andric };
103*5ffd83dbSDimitry Andric 
104*5ffd83dbSDimitry Andric class MarshallingFlagInfo final : public MarshallingKindInfo {
105*5ffd83dbSDimitry Andric public:
106*5ffd83dbSDimitry Andric   bool IsPositive;
107*5ffd83dbSDimitry Andric 
108*5ffd83dbSDimitry Andric   void emitSpecific(raw_ostream &OS) const override { OS << IsPositive; }
109*5ffd83dbSDimitry Andric 
110*5ffd83dbSDimitry Andric   static std::unique_ptr<MarshallingKindInfo> create(const Record &R) {
111*5ffd83dbSDimitry Andric     std::unique_ptr<MarshallingFlagInfo> Ret(new MarshallingFlagInfo(R));
112*5ffd83dbSDimitry Andric     Ret->IsPositive = R.getValueAsBit("IsPositive");
113*5ffd83dbSDimitry Andric     return Ret;
114*5ffd83dbSDimitry Andric   }
115*5ffd83dbSDimitry Andric 
116*5ffd83dbSDimitry Andric private:
117*5ffd83dbSDimitry Andric   MarshallingFlagInfo(const Record &R)
118*5ffd83dbSDimitry Andric       : MarshallingKindInfo(R, "OPTION_WITH_MARSHALLING_FLAG") {}
119*5ffd83dbSDimitry Andric };
120*5ffd83dbSDimitry Andric 
121*5ffd83dbSDimitry Andric class MarshallingStringInfo final : public MarshallingKindInfo {
122*5ffd83dbSDimitry Andric public:
123*5ffd83dbSDimitry Andric   StringRef NormalizerRetTy;
124*5ffd83dbSDimitry Andric   StringRef Normalizer;
125*5ffd83dbSDimitry Andric   StringRef Denormalizer;
126*5ffd83dbSDimitry Andric   int TableIndex = -1;
127*5ffd83dbSDimitry Andric   std::vector<StringRef> Values;
128*5ffd83dbSDimitry Andric   std::vector<StringRef> NormalizedValues;
129*5ffd83dbSDimitry Andric   std::string ValueTableName;
130*5ffd83dbSDimitry Andric 
131*5ffd83dbSDimitry Andric   static constexpr const char *ValueTablePreamble = R"(
132*5ffd83dbSDimitry Andric struct SimpleEnumValue {
133*5ffd83dbSDimitry Andric   const char *Name;
134*5ffd83dbSDimitry Andric   unsigned Value;
135*5ffd83dbSDimitry Andric };
136*5ffd83dbSDimitry Andric 
137*5ffd83dbSDimitry Andric struct SimpleEnumValueTable {
138*5ffd83dbSDimitry Andric   const SimpleEnumValue *Table;
139*5ffd83dbSDimitry Andric   unsigned Size;
140*5ffd83dbSDimitry Andric };
141*5ffd83dbSDimitry Andric )";
142*5ffd83dbSDimitry Andric 
143*5ffd83dbSDimitry Andric   static constexpr const char *ValueTablesDecl =
144*5ffd83dbSDimitry Andric       "static const SimpleEnumValueTable SimpleEnumValueTables[] = ";
145*5ffd83dbSDimitry Andric 
146*5ffd83dbSDimitry Andric   void emitSpecific(raw_ostream &OS) const override {
147*5ffd83dbSDimitry Andric     emitScopedNormalizedValue(OS, NormalizerRetTy);
148*5ffd83dbSDimitry Andric     OS << ", ";
149*5ffd83dbSDimitry Andric     OS << Normalizer;
150*5ffd83dbSDimitry Andric     OS << ", ";
151*5ffd83dbSDimitry Andric     OS << Denormalizer;
152*5ffd83dbSDimitry Andric     OS << ", ";
153*5ffd83dbSDimitry Andric     OS << TableIndex;
154*5ffd83dbSDimitry Andric   }
155*5ffd83dbSDimitry Andric 
156*5ffd83dbSDimitry Andric   Optional<StringRef> emitValueTable(raw_ostream &OS) const override {
157*5ffd83dbSDimitry Andric     if (TableIndex == -1)
158*5ffd83dbSDimitry Andric       return {};
159*5ffd83dbSDimitry Andric     OS << "static const SimpleEnumValue " << ValueTableName << "[] = {\n";
160*5ffd83dbSDimitry Andric     for (unsigned I = 0, E = Values.size(); I != E; ++I) {
161*5ffd83dbSDimitry Andric       OS << "{";
162*5ffd83dbSDimitry Andric       write_cstring(OS, Values[I]);
163*5ffd83dbSDimitry Andric       OS << ",";
164*5ffd83dbSDimitry Andric       OS << "static_cast<unsigned>(";
165*5ffd83dbSDimitry Andric       emitScopedNormalizedValue(OS, NormalizedValues[I]);
166*5ffd83dbSDimitry Andric       OS << ")},";
167*5ffd83dbSDimitry Andric     }
168*5ffd83dbSDimitry Andric     OS << "};\n";
169*5ffd83dbSDimitry Andric     return StringRef(ValueTableName);
170*5ffd83dbSDimitry Andric   }
171*5ffd83dbSDimitry Andric 
172*5ffd83dbSDimitry Andric   static std::unique_ptr<MarshallingKindInfo> create(const Record &R) {
173*5ffd83dbSDimitry Andric     assert(!isa<UnsetInit>(R.getValueInit("NormalizerRetTy")) &&
174*5ffd83dbSDimitry Andric            "String options must have a type");
175*5ffd83dbSDimitry Andric 
176*5ffd83dbSDimitry Andric     std::unique_ptr<MarshallingStringInfo> Ret(new MarshallingStringInfo(R));
177*5ffd83dbSDimitry Andric     Ret->NormalizerRetTy = R.getValueAsString("NormalizerRetTy");
178*5ffd83dbSDimitry Andric 
179*5ffd83dbSDimitry Andric     Ret->Normalizer = R.getValueAsString("Normalizer");
180*5ffd83dbSDimitry Andric     Ret->Denormalizer = R.getValueAsString("Denormalizer");
181*5ffd83dbSDimitry Andric 
182*5ffd83dbSDimitry Andric     if (!isa<UnsetInit>(R.getValueInit("NormalizedValues"))) {
183*5ffd83dbSDimitry Andric       assert(!isa<UnsetInit>(R.getValueInit("Values")) &&
184*5ffd83dbSDimitry Andric              "Cannot provide normalized values for value-less options");
185*5ffd83dbSDimitry Andric       Ret->TableIndex = NextTableIndex++;
186*5ffd83dbSDimitry Andric       Ret->NormalizedValues = R.getValueAsListOfStrings("NormalizedValues");
187*5ffd83dbSDimitry Andric       Ret->Values.reserve(Ret->NormalizedValues.size());
188*5ffd83dbSDimitry Andric       Ret->ValueTableName = getOptionName(R) + "ValueTable";
189*5ffd83dbSDimitry Andric 
190*5ffd83dbSDimitry Andric       StringRef ValuesStr = R.getValueAsString("Values");
191*5ffd83dbSDimitry Andric       for (;;) {
192*5ffd83dbSDimitry Andric         size_t Idx = ValuesStr.find(',');
193*5ffd83dbSDimitry Andric         if (Idx == StringRef::npos)
194*5ffd83dbSDimitry Andric           break;
195*5ffd83dbSDimitry Andric         if (Idx > 0)
196*5ffd83dbSDimitry Andric           Ret->Values.push_back(ValuesStr.slice(0, Idx));
197*5ffd83dbSDimitry Andric         ValuesStr = ValuesStr.slice(Idx + 1, StringRef::npos);
198*5ffd83dbSDimitry Andric       }
199*5ffd83dbSDimitry Andric       if (!ValuesStr.empty())
200*5ffd83dbSDimitry Andric         Ret->Values.push_back(ValuesStr);
201*5ffd83dbSDimitry Andric 
202*5ffd83dbSDimitry Andric       assert(Ret->Values.size() == Ret->NormalizedValues.size() &&
203*5ffd83dbSDimitry Andric              "The number of normalized values doesn't match the number of "
204*5ffd83dbSDimitry Andric              "values");
205*5ffd83dbSDimitry Andric     }
206*5ffd83dbSDimitry Andric 
207*5ffd83dbSDimitry Andric     return Ret;
208*5ffd83dbSDimitry Andric   }
209*5ffd83dbSDimitry Andric 
210*5ffd83dbSDimitry Andric private:
211*5ffd83dbSDimitry Andric   MarshallingStringInfo(const Record &R)
212*5ffd83dbSDimitry Andric       : MarshallingKindInfo(R, "OPTION_WITH_MARSHALLING_STRING") {}
213*5ffd83dbSDimitry Andric 
214*5ffd83dbSDimitry Andric   static size_t NextTableIndex;
215*5ffd83dbSDimitry Andric };
216*5ffd83dbSDimitry Andric 
217*5ffd83dbSDimitry Andric size_t MarshallingStringInfo::NextTableIndex = 0;
218*5ffd83dbSDimitry Andric 
219*5ffd83dbSDimitry Andric std::unique_ptr<MarshallingKindInfo>
220*5ffd83dbSDimitry Andric MarshallingKindInfo::create(const Record &R) {
221*5ffd83dbSDimitry Andric   assert(!isa<UnsetInit>(R.getValueInit("KeyPath")) &&
222*5ffd83dbSDimitry Andric          !isa<UnsetInit>(R.getValueInit("DefaultValue")) &&
223*5ffd83dbSDimitry Andric          "Must provide at least a key-path and a default value for emitting "
224*5ffd83dbSDimitry Andric          "marshalling information");
225*5ffd83dbSDimitry Andric 
226*5ffd83dbSDimitry Andric   std::unique_ptr<MarshallingKindInfo> Ret = nullptr;
227*5ffd83dbSDimitry Andric   StringRef MarshallingKindStr = R.getValueAsString("MarshallingKind");
228*5ffd83dbSDimitry Andric 
229*5ffd83dbSDimitry Andric   if (MarshallingKindStr == "flag")
230*5ffd83dbSDimitry Andric     Ret = MarshallingFlagInfo::create(R);
231*5ffd83dbSDimitry Andric   else if (MarshallingKindStr == "string")
232*5ffd83dbSDimitry Andric     Ret = MarshallingStringInfo::create(R);
233*5ffd83dbSDimitry Andric 
234*5ffd83dbSDimitry Andric   Ret->ShouldAlwaysEmit = R.getValueAsBit("ShouldAlwaysEmit");
235*5ffd83dbSDimitry Andric   Ret->KeyPath = R.getValueAsString("KeyPath");
236*5ffd83dbSDimitry Andric   Ret->DefaultValue = R.getValueAsString("DefaultValue");
237*5ffd83dbSDimitry Andric   if (!isa<UnsetInit>(R.getValueInit("NormalizedValuesScope")))
238*5ffd83dbSDimitry Andric     Ret->NormalizedValuesScope = R.getValueAsString("NormalizedValuesScope");
239*5ffd83dbSDimitry Andric   return Ret;
240*5ffd83dbSDimitry Andric }
241*5ffd83dbSDimitry Andric 
2420b57cec5SDimitry Andric /// OptParserEmitter - This tablegen backend takes an input .td file
2430b57cec5SDimitry Andric /// describing a list of options and emits a data structure for parsing and
2440b57cec5SDimitry Andric /// working with those options when given an input command line.
2450b57cec5SDimitry Andric namespace llvm {
2460b57cec5SDimitry Andric void EmitOptParser(RecordKeeper &Records, raw_ostream &OS) {
2470b57cec5SDimitry Andric   // Get the option groups and options.
2480b57cec5SDimitry Andric   const std::vector<Record*> &Groups =
2490b57cec5SDimitry Andric     Records.getAllDerivedDefinitions("OptionGroup");
2500b57cec5SDimitry Andric   std::vector<Record*> Opts = Records.getAllDerivedDefinitions("Option");
2510b57cec5SDimitry Andric 
2520b57cec5SDimitry Andric   emitSourceFileHeader("Option Parsing Definitions", OS);
2530b57cec5SDimitry Andric 
2540b57cec5SDimitry Andric   array_pod_sort(Opts.begin(), Opts.end(), CompareOptionRecords);
2550b57cec5SDimitry Andric   // Generate prefix groups.
2560b57cec5SDimitry Andric   typedef SmallVector<SmallString<2>, 2> PrefixKeyT;
2570b57cec5SDimitry Andric   typedef std::map<PrefixKeyT, std::string> PrefixesT;
2580b57cec5SDimitry Andric   PrefixesT Prefixes;
2590b57cec5SDimitry Andric   Prefixes.insert(std::make_pair(PrefixKeyT(), "prefix_0"));
2600b57cec5SDimitry Andric   unsigned CurPrefix = 0;
2610b57cec5SDimitry Andric   for (unsigned i = 0, e = Opts.size(); i != e; ++i) {
2620b57cec5SDimitry Andric     const Record &R = *Opts[i];
2630b57cec5SDimitry Andric     std::vector<StringRef> prf = R.getValueAsListOfStrings("Prefixes");
2640b57cec5SDimitry Andric     PrefixKeyT prfkey(prf.begin(), prf.end());
2650b57cec5SDimitry Andric     unsigned NewPrefix = CurPrefix + 1;
2660b57cec5SDimitry Andric     if (Prefixes.insert(std::make_pair(prfkey, (Twine("prefix_") +
2670b57cec5SDimitry Andric                                               Twine(NewPrefix)).str())).second)
2680b57cec5SDimitry Andric       CurPrefix = NewPrefix;
2690b57cec5SDimitry Andric   }
2700b57cec5SDimitry Andric 
2710b57cec5SDimitry Andric   // Dump prefixes.
2720b57cec5SDimitry Andric 
2730b57cec5SDimitry Andric   OS << "/////////\n";
2740b57cec5SDimitry Andric   OS << "// Prefixes\n\n";
2750b57cec5SDimitry Andric   OS << "#ifdef PREFIX\n";
2760b57cec5SDimitry Andric   OS << "#define COMMA ,\n";
2770b57cec5SDimitry Andric   for (PrefixesT::const_iterator I = Prefixes.begin(), E = Prefixes.end();
2780b57cec5SDimitry Andric                                   I != E; ++I) {
2790b57cec5SDimitry Andric     OS << "PREFIX(";
2800b57cec5SDimitry Andric 
2810b57cec5SDimitry Andric     // Prefix name.
2820b57cec5SDimitry Andric     OS << I->second;
2830b57cec5SDimitry Andric 
2840b57cec5SDimitry Andric     // Prefix values.
2850b57cec5SDimitry Andric     OS << ", {";
2860b57cec5SDimitry Andric     for (PrefixKeyT::const_iterator PI = I->first.begin(),
2870b57cec5SDimitry Andric                                     PE = I->first.end(); PI != PE; ++PI) {
2880b57cec5SDimitry Andric       OS << "\"" << *PI << "\" COMMA ";
2890b57cec5SDimitry Andric     }
2900b57cec5SDimitry Andric     OS << "nullptr})\n";
2910b57cec5SDimitry Andric   }
2920b57cec5SDimitry Andric   OS << "#undef COMMA\n";
2930b57cec5SDimitry Andric   OS << "#endif // PREFIX\n\n";
2940b57cec5SDimitry Andric 
2950b57cec5SDimitry Andric   OS << "/////////\n";
2960b57cec5SDimitry Andric   OS << "// Groups\n\n";
2970b57cec5SDimitry Andric   OS << "#ifdef OPTION\n";
2980b57cec5SDimitry Andric   for (unsigned i = 0, e = Groups.size(); i != e; ++i) {
2990b57cec5SDimitry Andric     const Record &R = *Groups[i];
3000b57cec5SDimitry Andric 
3010b57cec5SDimitry Andric     // Start a single option entry.
3020b57cec5SDimitry Andric     OS << "OPTION(";
3030b57cec5SDimitry Andric 
3040b57cec5SDimitry Andric     // The option prefix;
3050b57cec5SDimitry Andric     OS << "nullptr";
3060b57cec5SDimitry Andric 
3070b57cec5SDimitry Andric     // The option string.
3080b57cec5SDimitry Andric     OS << ", \"" << R.getValueAsString("Name") << '"';
3090b57cec5SDimitry Andric 
3100b57cec5SDimitry Andric     // The option identifier name.
3110b57cec5SDimitry Andric     OS << ", " << getOptionName(R);
3120b57cec5SDimitry Andric 
3130b57cec5SDimitry Andric     // The option kind.
3140b57cec5SDimitry Andric     OS << ", Group";
3150b57cec5SDimitry Andric 
3160b57cec5SDimitry Andric     // The containing option group (if any).
3170b57cec5SDimitry Andric     OS << ", ";
3180b57cec5SDimitry Andric     if (const DefInit *DI = dyn_cast<DefInit>(R.getValueInit("Group")))
3190b57cec5SDimitry Andric       OS << getOptionName(*DI->getDef());
3200b57cec5SDimitry Andric     else
3210b57cec5SDimitry Andric       OS << "INVALID";
3220b57cec5SDimitry Andric 
3230b57cec5SDimitry Andric     // The other option arguments (unused for groups).
3240b57cec5SDimitry Andric     OS << ", INVALID, nullptr, 0, 0";
3250b57cec5SDimitry Andric 
3260b57cec5SDimitry Andric     // The option help text.
3270b57cec5SDimitry Andric     if (!isa<UnsetInit>(R.getValueInit("HelpText"))) {
3280b57cec5SDimitry Andric       OS << ",\n";
3290b57cec5SDimitry Andric       OS << "       ";
3300b57cec5SDimitry Andric       write_cstring(OS, R.getValueAsString("HelpText"));
3310b57cec5SDimitry Andric     } else
3320b57cec5SDimitry Andric       OS << ", nullptr";
3330b57cec5SDimitry Andric 
3340b57cec5SDimitry Andric     // The option meta-variable name (unused).
3350b57cec5SDimitry Andric     OS << ", nullptr";
3360b57cec5SDimitry Andric 
3370b57cec5SDimitry Andric     // The option Values (unused for groups).
3380b57cec5SDimitry Andric     OS << ", nullptr)\n";
3390b57cec5SDimitry Andric   }
3400b57cec5SDimitry Andric   OS << "\n";
3410b57cec5SDimitry Andric 
3420b57cec5SDimitry Andric   OS << "//////////\n";
3430b57cec5SDimitry Andric   OS << "// Options\n\n";
3440b57cec5SDimitry Andric 
345*5ffd83dbSDimitry Andric   auto WriteOptRecordFields = [&](raw_ostream &OS, const Record &R) {
3460b57cec5SDimitry Andric     // The option prefix;
3470b57cec5SDimitry Andric     std::vector<StringRef> prf = R.getValueAsListOfStrings("Prefixes");
3480b57cec5SDimitry Andric     OS << Prefixes[PrefixKeyT(prf.begin(), prf.end())] << ", ";
3490b57cec5SDimitry Andric 
3500b57cec5SDimitry Andric     // The option string.
351*5ffd83dbSDimitry Andric     emitNameUsingSpelling(OS, R);
3520b57cec5SDimitry Andric 
3530b57cec5SDimitry Andric     // The option identifier name.
3540b57cec5SDimitry Andric     OS << ", " << getOptionName(R);
3550b57cec5SDimitry Andric 
3560b57cec5SDimitry Andric     // The option kind.
3570b57cec5SDimitry Andric     OS << ", " << R.getValueAsDef("Kind")->getValueAsString("Name");
3580b57cec5SDimitry Andric 
3590b57cec5SDimitry Andric     // The containing option group (if any).
3600b57cec5SDimitry Andric     OS << ", ";
3610b57cec5SDimitry Andric     const ListInit *GroupFlags = nullptr;
3620b57cec5SDimitry Andric     if (const DefInit *DI = dyn_cast<DefInit>(R.getValueInit("Group"))) {
3630b57cec5SDimitry Andric       GroupFlags = DI->getDef()->getValueAsListInit("Flags");
3640b57cec5SDimitry Andric       OS << getOptionName(*DI->getDef());
3650b57cec5SDimitry Andric     } else
3660b57cec5SDimitry Andric       OS << "INVALID";
3670b57cec5SDimitry Andric 
3680b57cec5SDimitry Andric     // The option alias (if any).
3690b57cec5SDimitry Andric     OS << ", ";
3700b57cec5SDimitry Andric     if (const DefInit *DI = dyn_cast<DefInit>(R.getValueInit("Alias")))
3710b57cec5SDimitry Andric       OS << getOptionName(*DI->getDef());
3720b57cec5SDimitry Andric     else
3730b57cec5SDimitry Andric       OS << "INVALID";
3740b57cec5SDimitry Andric 
3750b57cec5SDimitry Andric     // The option alias arguments (if any).
3760b57cec5SDimitry Andric     // Emitted as a \0 separated list in a string, e.g. ["foo", "bar"]
3770b57cec5SDimitry Andric     // would become "foo\0bar\0". Note that the compiler adds an implicit
3780b57cec5SDimitry Andric     // terminating \0 at the end.
3790b57cec5SDimitry Andric     OS << ", ";
3800b57cec5SDimitry Andric     std::vector<StringRef> AliasArgs = R.getValueAsListOfStrings("AliasArgs");
3810b57cec5SDimitry Andric     if (AliasArgs.size() == 0) {
3820b57cec5SDimitry Andric       OS << "nullptr";
3830b57cec5SDimitry Andric     } else {
3840b57cec5SDimitry Andric       OS << "\"";
3850b57cec5SDimitry Andric       for (size_t i = 0, e = AliasArgs.size(); i != e; ++i)
3860b57cec5SDimitry Andric         OS << AliasArgs[i] << "\\0";
3870b57cec5SDimitry Andric       OS << "\"";
3880b57cec5SDimitry Andric     }
3890b57cec5SDimitry Andric 
3900b57cec5SDimitry Andric     // The option flags.
3910b57cec5SDimitry Andric     OS << ", ";
3920b57cec5SDimitry Andric     int NumFlags = 0;
3930b57cec5SDimitry Andric     const ListInit *LI = R.getValueAsListInit("Flags");
3940b57cec5SDimitry Andric     for (Init *I : *LI)
395*5ffd83dbSDimitry Andric       OS << (NumFlags++ ? " | " : "") << cast<DefInit>(I)->getDef()->getName();
3960b57cec5SDimitry Andric     if (GroupFlags) {
3970b57cec5SDimitry Andric       for (Init *I : *GroupFlags)
3980b57cec5SDimitry Andric         OS << (NumFlags++ ? " | " : "")
3990b57cec5SDimitry Andric            << cast<DefInit>(I)->getDef()->getName();
4000b57cec5SDimitry Andric     }
4010b57cec5SDimitry Andric     if (NumFlags == 0)
4020b57cec5SDimitry Andric       OS << '0';
4030b57cec5SDimitry Andric 
4040b57cec5SDimitry Andric     // The option parameter field.
4050b57cec5SDimitry Andric     OS << ", " << R.getValueAsInt("NumArgs");
4060b57cec5SDimitry Andric 
4070b57cec5SDimitry Andric     // The option help text.
4080b57cec5SDimitry Andric     if (!isa<UnsetInit>(R.getValueInit("HelpText"))) {
4090b57cec5SDimitry Andric       OS << ",\n";
4100b57cec5SDimitry Andric       OS << "       ";
4110b57cec5SDimitry Andric       write_cstring(OS, R.getValueAsString("HelpText"));
4120b57cec5SDimitry Andric     } else
4130b57cec5SDimitry Andric       OS << ", nullptr";
4140b57cec5SDimitry Andric 
4150b57cec5SDimitry Andric     // The option meta-variable name.
4160b57cec5SDimitry Andric     OS << ", ";
4170b57cec5SDimitry Andric     if (!isa<UnsetInit>(R.getValueInit("MetaVarName")))
4180b57cec5SDimitry Andric       write_cstring(OS, R.getValueAsString("MetaVarName"));
4190b57cec5SDimitry Andric     else
4200b57cec5SDimitry Andric       OS << "nullptr";
4210b57cec5SDimitry Andric 
4220b57cec5SDimitry Andric     // The option Values. Used for shell autocompletion.
4230b57cec5SDimitry Andric     OS << ", ";
4240b57cec5SDimitry Andric     if (!isa<UnsetInit>(R.getValueInit("Values")))
4250b57cec5SDimitry Andric       write_cstring(OS, R.getValueAsString("Values"));
4260b57cec5SDimitry Andric     else
4270b57cec5SDimitry Andric       OS << "nullptr";
428*5ffd83dbSDimitry Andric   };
4290b57cec5SDimitry Andric 
430*5ffd83dbSDimitry Andric   std::vector<std::unique_ptr<MarshallingKindInfo>> OptsWithMarshalling;
431*5ffd83dbSDimitry Andric   for (unsigned I = 0, E = Opts.size(); I != E; ++I) {
432*5ffd83dbSDimitry Andric     const Record &R = *Opts[I];
433*5ffd83dbSDimitry Andric 
434*5ffd83dbSDimitry Andric     // Start a single option entry.
435*5ffd83dbSDimitry Andric     OS << "OPTION(";
436*5ffd83dbSDimitry Andric     WriteOptRecordFields(OS, R);
4370b57cec5SDimitry Andric     OS << ")\n";
438*5ffd83dbSDimitry Andric     if (!isa<UnsetInit>(R.getValueInit("MarshallingKind")))
439*5ffd83dbSDimitry Andric       OptsWithMarshalling.push_back(MarshallingKindInfo::create(R));
4400b57cec5SDimitry Andric   }
4410b57cec5SDimitry Andric   OS << "#endif // OPTION\n";
4420b57cec5SDimitry Andric 
443*5ffd83dbSDimitry Andric   for (const auto &KindInfo : OptsWithMarshalling) {
444*5ffd83dbSDimitry Andric     OS << "#ifdef " << KindInfo->MacroName << "\n";
445*5ffd83dbSDimitry Andric     OS << KindInfo->MacroName << "(";
446*5ffd83dbSDimitry Andric     WriteOptRecordFields(OS, KindInfo->R);
447*5ffd83dbSDimitry Andric     OS << ", ";
448*5ffd83dbSDimitry Andric     KindInfo->emit(OS);
449*5ffd83dbSDimitry Andric     OS << ")\n";
450*5ffd83dbSDimitry Andric     OS << "#endif // " << KindInfo->MacroName << "\n";
451*5ffd83dbSDimitry Andric   }
452*5ffd83dbSDimitry Andric 
453*5ffd83dbSDimitry Andric   OS << "\n";
454*5ffd83dbSDimitry Andric   OS << "#ifdef SIMPLE_ENUM_VALUE_TABLE";
455*5ffd83dbSDimitry Andric   OS << "\n";
456*5ffd83dbSDimitry Andric   OS << MarshallingStringInfo::ValueTablePreamble;
457*5ffd83dbSDimitry Andric   std::vector<StringRef> ValueTableNames;
458*5ffd83dbSDimitry Andric   for (const auto &KindInfo : OptsWithMarshalling)
459*5ffd83dbSDimitry Andric     if (auto MaybeValueTableName = KindInfo->emitValueTable(OS))
460*5ffd83dbSDimitry Andric       ValueTableNames.push_back(*MaybeValueTableName);
461*5ffd83dbSDimitry Andric 
462*5ffd83dbSDimitry Andric   OS << MarshallingStringInfo::ValueTablesDecl << "{";
463*5ffd83dbSDimitry Andric   for (auto ValueTableName : ValueTableNames)
464*5ffd83dbSDimitry Andric     OS << "{" << ValueTableName << ", sizeof(" << ValueTableName
465*5ffd83dbSDimitry Andric        << ") / sizeof(SimpleEnumValue)"
466*5ffd83dbSDimitry Andric        << "},\n";
467*5ffd83dbSDimitry Andric   OS << "};\n";
468*5ffd83dbSDimitry Andric   OS << "static const unsigned SimpleEnumValueTablesSize = "
469*5ffd83dbSDimitry Andric         "sizeof(SimpleEnumValueTables) / sizeof(SimpleEnumValueTable);\n";
470*5ffd83dbSDimitry Andric 
471*5ffd83dbSDimitry Andric   OS << "#endif // SIMPLE_ENUM_VALUE_TABLE\n";
472*5ffd83dbSDimitry Andric   OS << "\n";
473*5ffd83dbSDimitry Andric 
4740b57cec5SDimitry Andric   OS << "\n";
4750b57cec5SDimitry Andric   OS << "#ifdef OPTTABLE_ARG_INIT\n";
4760b57cec5SDimitry Andric   OS << "//////////\n";
4770b57cec5SDimitry Andric   OS << "// Option Values\n\n";
4780b57cec5SDimitry Andric   for (unsigned I = 0, E = Opts.size(); I != E; ++I) {
4790b57cec5SDimitry Andric     const Record &R = *Opts[I];
4800b57cec5SDimitry Andric     if (isa<UnsetInit>(R.getValueInit("ValuesCode")))
4810b57cec5SDimitry Andric       continue;
4820b57cec5SDimitry Andric     OS << "{\n";
4830b57cec5SDimitry Andric     OS << "bool ValuesWereAdded;\n";
4840b57cec5SDimitry Andric     OS << R.getValueAsString("ValuesCode");
4850b57cec5SDimitry Andric     OS << "\n";
486*5ffd83dbSDimitry Andric     for (StringRef Prefix : R.getValueAsListOfStrings("Prefixes")) {
4870b57cec5SDimitry Andric       OS << "ValuesWereAdded = Opt.addValues(";
488*5ffd83dbSDimitry Andric       std::string S(Prefix);
489480093f4SDimitry Andric       S += R.getValueAsString("Name");
4900b57cec5SDimitry Andric       write_cstring(OS, S);
4910b57cec5SDimitry Andric       OS << ", Values);\n";
4920b57cec5SDimitry Andric       OS << "(void)ValuesWereAdded;\n";
4930b57cec5SDimitry Andric       OS << "assert(ValuesWereAdded && \"Couldn't add values to "
4940b57cec5SDimitry Andric             "OptTable!\");\n";
4950b57cec5SDimitry Andric     }
4960b57cec5SDimitry Andric     OS << "}\n";
4970b57cec5SDimitry Andric   }
4980b57cec5SDimitry Andric   OS << "\n";
4990b57cec5SDimitry Andric   OS << "#endif // OPTTABLE_ARG_INIT\n";
5000b57cec5SDimitry Andric }
5010b57cec5SDimitry Andric } // end namespace llvm
502