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