diff options
Diffstat (limited to 'contrib/llvm-project/llvm/utils/TableGen/OptParserEmitter.cpp')
-rw-r--r-- | contrib/llvm-project/llvm/utils/TableGen/OptParserEmitter.cpp | 309 |
1 files changed, 148 insertions, 161 deletions
diff --git a/contrib/llvm-project/llvm/utils/TableGen/OptParserEmitter.cpp b/contrib/llvm-project/llvm/utils/TableGen/OptParserEmitter.cpp index 251533a8d154..8e6c05885e5b 100644 --- a/contrib/llvm-project/llvm/utils/TableGen/OptParserEmitter.cpp +++ b/contrib/llvm-project/llvm/utils/TableGen/OptParserEmitter.cpp @@ -20,7 +20,7 @@ using namespace llvm; -static const std::string getOptionName(const Record &R) { +static std::string getOptionName(const Record &R) { // Use the record name unless EnumName is defined. if (isa<UnsetInit>(R.getValueInit("EnumName"))) return std::string(R.getName()); @@ -35,19 +35,20 @@ static raw_ostream &write_cstring(raw_ostream &OS, llvm::StringRef Str) { return OS; } -static const std::string getOptionSpelling(const Record &R, - size_t &PrefixLength) { +static std::string getOptionSpelling(const Record &R, size_t &PrefixLength) { std::vector<StringRef> Prefixes = R.getValueAsListOfStrings("Prefixes"); StringRef Name = R.getValueAsString("Name"); + if (Prefixes.empty()) { PrefixLength = 0; return Name.str(); } + PrefixLength = Prefixes[0].size(); return (Twine(Prefixes[0]) + Twine(Name)).str(); } -static const std::string getOptionSpelling(const Record &R) { +static std::string getOptionSpelling(const Record &R) { size_t PrefixLength; return getOptionSpelling(R, PrefixLength); } @@ -59,75 +60,29 @@ static void emitNameUsingSpelling(raw_ostream &OS, const Record &R) { OS << "[" << PrefixLength << "]"; } -class MarshallingKindInfo { +class MarshallingInfo { public: + static constexpr const char *MacroName = "OPTION_WITH_MARSHALLING"; const Record &R; - const char *MacroName; bool ShouldAlwaysEmit; + StringRef MacroPrefix; StringRef KeyPath; StringRef DefaultValue; StringRef NormalizedValuesScope; - - void emit(raw_ostream &OS) const { - write_cstring(OS, StringRef(getOptionSpelling(R))); - OS << ", "; - OS << ShouldAlwaysEmit; - OS << ", "; - OS << KeyPath; - OS << ", "; - emitScopedNormalizedValue(OS, DefaultValue); - OS << ", "; - emitSpecific(OS); - } - - virtual Optional<StringRef> emitValueTable(raw_ostream &OS) const { - return None; - } - - virtual ~MarshallingKindInfo() = default; - - static std::unique_ptr<MarshallingKindInfo> create(const Record &R); - -protected: - void emitScopedNormalizedValue(raw_ostream &OS, - StringRef NormalizedValue) const { - if (!NormalizedValuesScope.empty()) - OS << NormalizedValuesScope << "::"; - OS << NormalizedValue; - } - - virtual void emitSpecific(raw_ostream &OS) const = 0; - MarshallingKindInfo(const Record &R, const char *MacroName) - : R(R), MacroName(MacroName) {} -}; - -class MarshallingFlagInfo final : public MarshallingKindInfo { -public: - bool IsPositive; - - void emitSpecific(raw_ostream &OS) const override { OS << IsPositive; } - - static std::unique_ptr<MarshallingKindInfo> create(const Record &R) { - std::unique_ptr<MarshallingFlagInfo> Ret(new MarshallingFlagInfo(R)); - Ret->IsPositive = R.getValueAsBit("IsPositive"); - return Ret; - } - -private: - MarshallingFlagInfo(const Record &R) - : MarshallingKindInfo(R, "OPTION_WITH_MARSHALLING_FLAG") {} -}; - -class MarshallingStringInfo final : public MarshallingKindInfo { -public: - StringRef NormalizerRetTy; + StringRef ImpliedCheck; + StringRef ImpliedValue; + StringRef ShouldParse; StringRef Normalizer; StringRef Denormalizer; + StringRef ValueMerger; + StringRef ValueExtractor; int TableIndex = -1; std::vector<StringRef> Values; std::vector<StringRef> NormalizedValues; std::string ValueTableName; + static size_t NextTableIndex; + static constexpr const char *ValueTablePreamble = R"( struct SimpleEnumValue { const char *Name; @@ -143,17 +98,39 @@ struct SimpleEnumValueTable { static constexpr const char *ValueTablesDecl = "static const SimpleEnumValueTable SimpleEnumValueTables[] = "; - void emitSpecific(raw_ostream &OS) const override { - emitScopedNormalizedValue(OS, NormalizerRetTy); + MarshallingInfo(const Record &R) : R(R) {} + + std::string getMacroName() const { + return (MacroPrefix + MarshallingInfo::MacroName).str(); + } + + void emit(raw_ostream &OS) const { + write_cstring(OS, StringRef(getOptionSpelling(R))); + OS << ", "; + OS << ShouldParse; + OS << ", "; + OS << ShouldAlwaysEmit; + OS << ", "; + OS << KeyPath; + OS << ", "; + emitScopedNormalizedValue(OS, DefaultValue); + OS << ", "; + OS << ImpliedCheck; + OS << ", "; + emitScopedNormalizedValue(OS, ImpliedValue); OS << ", "; OS << Normalizer; OS << ", "; OS << Denormalizer; OS << ", "; + OS << ValueMerger; + OS << ", "; + OS << ValueExtractor; + OS << ", "; OS << TableIndex; } - Optional<StringRef> emitValueTable(raw_ostream &OS) const override { + Optional<StringRef> emitValueTable(raw_ostream &OS) const { if (TableIndex == -1) return {}; OS << "static const SimpleEnumValue " << ValueTableName << "[] = {\n"; @@ -169,73 +146,66 @@ struct SimpleEnumValueTable { return StringRef(ValueTableName); } - static std::unique_ptr<MarshallingKindInfo> create(const Record &R) { - assert(!isa<UnsetInit>(R.getValueInit("NormalizerRetTy")) && - "String options must have a type"); - - std::unique_ptr<MarshallingStringInfo> Ret(new MarshallingStringInfo(R)); - Ret->NormalizerRetTy = R.getValueAsString("NormalizerRetTy"); - - Ret->Normalizer = R.getValueAsString("Normalizer"); - Ret->Denormalizer = R.getValueAsString("Denormalizer"); - - if (!isa<UnsetInit>(R.getValueInit("NormalizedValues"))) { - assert(!isa<UnsetInit>(R.getValueInit("Values")) && - "Cannot provide normalized values for value-less options"); - Ret->TableIndex = NextTableIndex++; - Ret->NormalizedValues = R.getValueAsListOfStrings("NormalizedValues"); - Ret->Values.reserve(Ret->NormalizedValues.size()); - Ret->ValueTableName = getOptionName(R) + "ValueTable"; - - StringRef ValuesStr = R.getValueAsString("Values"); - for (;;) { - size_t Idx = ValuesStr.find(','); - if (Idx == StringRef::npos) - break; - if (Idx > 0) - Ret->Values.push_back(ValuesStr.slice(0, Idx)); - ValuesStr = ValuesStr.slice(Idx + 1, StringRef::npos); - } - if (!ValuesStr.empty()) - Ret->Values.push_back(ValuesStr); - - assert(Ret->Values.size() == Ret->NormalizedValues.size() && - "The number of normalized values doesn't match the number of " - "values"); - } - - return Ret; - } - private: - MarshallingStringInfo(const Record &R) - : MarshallingKindInfo(R, "OPTION_WITH_MARSHALLING_STRING") {} - - static size_t NextTableIndex; + void emitScopedNormalizedValue(raw_ostream &OS, + StringRef NormalizedValue) const { + if (!NormalizedValuesScope.empty()) + OS << NormalizedValuesScope << "::"; + OS << NormalizedValue; + } }; -size_t MarshallingStringInfo::NextTableIndex = 0; +size_t MarshallingInfo::NextTableIndex = 0; -std::unique_ptr<MarshallingKindInfo> -MarshallingKindInfo::create(const Record &R) { +static MarshallingInfo createMarshallingInfo(const Record &R) { assert(!isa<UnsetInit>(R.getValueInit("KeyPath")) && !isa<UnsetInit>(R.getValueInit("DefaultValue")) && - "Must provide at least a key-path and a default value for emitting " - "marshalling information"); - - std::unique_ptr<MarshallingKindInfo> Ret = nullptr; - StringRef MarshallingKindStr = R.getValueAsString("MarshallingKind"); - - if (MarshallingKindStr == "flag") - Ret = MarshallingFlagInfo::create(R); - else if (MarshallingKindStr == "string") - Ret = MarshallingStringInfo::create(R); - - Ret->ShouldAlwaysEmit = R.getValueAsBit("ShouldAlwaysEmit"); - Ret->KeyPath = R.getValueAsString("KeyPath"); - Ret->DefaultValue = R.getValueAsString("DefaultValue"); - if (!isa<UnsetInit>(R.getValueInit("NormalizedValuesScope"))) - Ret->NormalizedValuesScope = R.getValueAsString("NormalizedValuesScope"); + !isa<UnsetInit>(R.getValueInit("ValueMerger")) && + "MarshallingInfo must have a provide a keypath, default value and a " + "value merger"); + + MarshallingInfo Ret(R); + + Ret.ShouldAlwaysEmit = R.getValueAsBit("ShouldAlwaysEmit"); + Ret.MacroPrefix = R.getValueAsString("MacroPrefix"); + Ret.KeyPath = R.getValueAsString("KeyPath"); + Ret.DefaultValue = R.getValueAsString("DefaultValue"); + Ret.NormalizedValuesScope = R.getValueAsString("NormalizedValuesScope"); + Ret.ImpliedCheck = R.getValueAsString("ImpliedCheck"); + Ret.ImpliedValue = + R.getValueAsOptionalString("ImpliedValue").getValueOr(Ret.DefaultValue); + + Ret.ShouldParse = R.getValueAsString("ShouldParse"); + Ret.Normalizer = R.getValueAsString("Normalizer"); + Ret.Denormalizer = R.getValueAsString("Denormalizer"); + Ret.ValueMerger = R.getValueAsString("ValueMerger"); + Ret.ValueExtractor = R.getValueAsString("ValueExtractor"); + + if (!isa<UnsetInit>(R.getValueInit("NormalizedValues"))) { + assert(!isa<UnsetInit>(R.getValueInit("Values")) && + "Cannot provide normalized values for value-less options"); + Ret.TableIndex = MarshallingInfo::NextTableIndex++; + Ret.NormalizedValues = R.getValueAsListOfStrings("NormalizedValues"); + Ret.Values.reserve(Ret.NormalizedValues.size()); + Ret.ValueTableName = getOptionName(R) + "ValueTable"; + + StringRef ValuesStr = R.getValueAsString("Values"); + for (;;) { + size_t Idx = ValuesStr.find(','); + if (Idx == StringRef::npos) + break; + if (Idx > 0) + Ret.Values.push_back(ValuesStr.slice(0, Idx)); + ValuesStr = ValuesStr.slice(Idx + 1, StringRef::npos); + } + if (!ValuesStr.empty()) + Ret.Values.push_back(ValuesStr); + + assert(Ret.Values.size() == Ret.NormalizedValues.size() && + "The number of normalized values doesn't match the number of " + "values"); + } + return Ret; } @@ -258,13 +228,12 @@ void EmitOptParser(RecordKeeper &Records, raw_ostream &OS) { PrefixesT Prefixes; Prefixes.insert(std::make_pair(PrefixKeyT(), "prefix_0")); unsigned CurPrefix = 0; - for (unsigned i = 0, e = Opts.size(); i != e; ++i) { - const Record &R = *Opts[i]; - std::vector<StringRef> prf = R.getValueAsListOfStrings("Prefixes"); - PrefixKeyT prfkey(prf.begin(), prf.end()); + for (const Record &R : llvm::make_pointee_range(Opts)) { + std::vector<StringRef> RPrefixes = R.getValueAsListOfStrings("Prefixes"); + PrefixKeyT PrefixKey(RPrefixes.begin(), RPrefixes.end()); unsigned NewPrefix = CurPrefix + 1; - if (Prefixes.insert(std::make_pair(prfkey, (Twine("prefix_") + - Twine(NewPrefix)).str())).second) + std::string Prefix = (Twine("prefix_") + Twine(NewPrefix)).str(); + if (Prefixes.insert(std::make_pair(PrefixKey, Prefix)).second) CurPrefix = NewPrefix; } @@ -274,19 +243,16 @@ void EmitOptParser(RecordKeeper &Records, raw_ostream &OS) { OS << "// Prefixes\n\n"; OS << "#ifdef PREFIX\n"; OS << "#define COMMA ,\n"; - for (PrefixesT::const_iterator I = Prefixes.begin(), E = Prefixes.end(); - I != E; ++I) { + for (const auto &Prefix : Prefixes) { OS << "PREFIX("; // Prefix name. - OS << I->second; + OS << Prefix.second; // Prefix values. OS << ", {"; - for (PrefixKeyT::const_iterator PI = I->first.begin(), - PE = I->first.end(); PI != PE; ++PI) { - OS << "\"" << *PI << "\" COMMA "; - } + for (StringRef PrefixKey : Prefix.first) + OS << "\"" << PrefixKey << "\" COMMA "; OS << "nullptr})\n"; } OS << "#undef COMMA\n"; @@ -295,9 +261,7 @@ void EmitOptParser(RecordKeeper &Records, raw_ostream &OS) { OS << "/////////\n"; OS << "// Groups\n\n"; OS << "#ifdef OPTION\n"; - for (unsigned i = 0, e = Groups.size(); i != e; ++i) { - const Record &R = *Groups[i]; - + for (const Record &R : llvm::make_pointee_range(Groups)) { // Start a single option entry. OS << "OPTION("; @@ -344,8 +308,8 @@ void EmitOptParser(RecordKeeper &Records, raw_ostream &OS) { auto WriteOptRecordFields = [&](raw_ostream &OS, const Record &R) { // The option prefix; - std::vector<StringRef> prf = R.getValueAsListOfStrings("Prefixes"); - OS << Prefixes[PrefixKeyT(prf.begin(), prf.end())] << ", "; + std::vector<StringRef> RPrefixes = R.getValueAsListOfStrings("Prefixes"); + OS << Prefixes[PrefixKeyT(RPrefixes.begin(), RPrefixes.end())] << ", "; // The option string. emitNameUsingSpelling(OS, R); @@ -382,8 +346,8 @@ void EmitOptParser(RecordKeeper &Records, raw_ostream &OS) { OS << "nullptr"; } else { OS << "\""; - for (size_t i = 0, e = AliasArgs.size(); i != e; ++i) - OS << AliasArgs[i] << "\\0"; + for (StringRef AliasArg : AliasArgs) + OS << AliasArg << "\\0"; OS << "\""; } @@ -427,39 +391,63 @@ void EmitOptParser(RecordKeeper &Records, raw_ostream &OS) { OS << "nullptr"; }; - std::vector<std::unique_ptr<MarshallingKindInfo>> OptsWithMarshalling; - for (unsigned I = 0, E = Opts.size(); I != E; ++I) { - const Record &R = *Opts[I]; + auto IsMarshallingOption = [](const Record &R) { + return !isa<UnsetInit>(R.getValueInit("KeyPath")) && + !R.getValueAsString("KeyPath").empty(); + }; + std::vector<const Record *> OptsWithMarshalling; + for (const Record &R : llvm::make_pointee_range(Opts)) { // Start a single option entry. OS << "OPTION("; WriteOptRecordFields(OS, R); OS << ")\n"; - if (!isa<UnsetInit>(R.getValueInit("MarshallingKind"))) - OptsWithMarshalling.push_back(MarshallingKindInfo::create(R)); + if (IsMarshallingOption(R)) + OptsWithMarshalling.push_back(&R); } OS << "#endif // OPTION\n"; - for (const auto &KindInfo : OptsWithMarshalling) { - OS << "#ifdef " << KindInfo->MacroName << "\n"; - OS << KindInfo->MacroName << "("; - WriteOptRecordFields(OS, KindInfo->R); + auto CmpMarshallingOpts = [](const Record *const *A, const Record *const *B) { + unsigned AID = (*A)->getID(); + unsigned BID = (*B)->getID(); + + if (AID < BID) + return -1; + if (AID > BID) + return 1; + return 0; + }; + // The RecordKeeper stores records (options) in lexicographical order, and we + // have reordered the options again when generating prefix groups. We need to + // restore the original definition order of options with marshalling to honor + // the topology of the dependency graph implied by `DefaultAnyOf`. + array_pod_sort(OptsWithMarshalling.begin(), OptsWithMarshalling.end(), + CmpMarshallingOpts); + + std::vector<MarshallingInfo> MarshallingInfos; + for (const auto *R : OptsWithMarshalling) + MarshallingInfos.push_back(createMarshallingInfo(*R)); + + for (const auto &MI : MarshallingInfos) { + OS << "#ifdef " << MI.getMacroName() << "\n"; + OS << MI.getMacroName() << "("; + WriteOptRecordFields(OS, MI.R); OS << ", "; - KindInfo->emit(OS); + MI.emit(OS); OS << ")\n"; - OS << "#endif // " << KindInfo->MacroName << "\n"; + OS << "#endif // " << MI.getMacroName() << "\n"; } OS << "\n"; OS << "#ifdef SIMPLE_ENUM_VALUE_TABLE"; OS << "\n"; - OS << MarshallingStringInfo::ValueTablePreamble; + OS << MarshallingInfo::ValueTablePreamble; std::vector<StringRef> ValueTableNames; - for (const auto &KindInfo : OptsWithMarshalling) - if (auto MaybeValueTableName = KindInfo->emitValueTable(OS)) + for (const auto &MI : MarshallingInfos) + if (auto MaybeValueTableName = MI.emitValueTable(OS)) ValueTableNames.push_back(*MaybeValueTableName); - OS << MarshallingStringInfo::ValueTablesDecl << "{"; + OS << MarshallingInfo::ValueTablesDecl << "{"; for (auto ValueTableName : ValueTableNames) OS << "{" << ValueTableName << ", sizeof(" << ValueTableName << ") / sizeof(SimpleEnumValue)" @@ -475,8 +463,7 @@ void EmitOptParser(RecordKeeper &Records, raw_ostream &OS) { OS << "#ifdef OPTTABLE_ARG_INIT\n"; OS << "//////////\n"; OS << "// Option Values\n\n"; - for (unsigned I = 0, E = Opts.size(); I != E; ++I) { - const Record &R = *Opts[I]; + for (const Record &R : llvm::make_pointee_range(Opts)) { if (isa<UnsetInit>(R.getValueInit("ValuesCode"))) continue; OS << "{\n"; |