From e9ac5bd316bec6d5c68b8a2a1f9a3e05b6e4778f Mon Sep 17 00:00:00 2001 From: Mehdi Amini Date: Wed, 11 Nov 2020 20:00:21 +0000 Subject: [PATCH] Revert "[clang][cli] Port ObjCMTAction to new option parsing system" This reverts commit 09248a5d25bb1c9f357247fa3da8fbe4470e9c67. Some builds are broken. I suspect a `static constexpr` in a class missing a definition out of class (required pre-c++17). --- include/llvm/Option/OptParser.td | 32 ++-- unittests/Option/OptionMarshallingTest.cpp | 34 ++-- unittests/Option/Opts.td | 16 +- utils/TableGen/OptParserEmitter.cpp | 184 +++++++++++++-------- 4 files changed, 155 insertions(+), 111 deletions(-) diff --git a/include/llvm/Option/OptParser.td b/include/llvm/Option/OptParser.td index 005a9524699..47b4788b220 100644 --- a/include/llvm/Option/OptParser.td +++ b/include/llvm/Option/OptParser.td @@ -97,15 +97,17 @@ class Option prefixes, string name, OptionKind kind> { OptionGroup Group = ?; Option Alias = ?; list AliasArgs = []; + string MarshallingKind = ?; code KeyPath = ?; code DefaultValue = ?; bit ShouldAlwaysEmit = 0; + // Used by the Flag option kind. + bit IsPositive = 1; + // Used by the String option kind. code NormalizerRetTy = ?; code NormalizedValuesScope = ""; code Normalizer = ""; code Denormalizer = ""; - code ValueMerger = "mergeForwardValue"; - code ValueExtractor = "extractForwardValue"; list NormalizedValues = ?; } @@ -142,39 +144,29 @@ class ValuesCode { code ValuesCode = valuecode; } // Helpers for defining marshalling information. -class DefaultAnyOf options, string default = "false", string separator = " || "> { - code DefaultValue = !foldl(default, options, accumulator, option, - !strconcat(accumulator, separator, !cast(option.KeyPath))); +class DefaultAnyOf defaults> { + code DefaultValue = !foldl("false", defaults, accumulator, option, + !strconcat(accumulator, " || ", !cast(option.KeyPath))); } class MarshallingInfo { code KeyPath = keypath; code DefaultValue = defaultvalue; } - class MarshallingInfoString : MarshallingInfo { + string MarshallingKind = "string"; code NormalizerRetTy = normalizerretty; } -class MarshallingInfoFlag, code ty="unsigned"> +class MarshallingInfoFlag> : MarshallingInfo { - code NormalizerRetTy = ty; - code Normalizer = "normalizeSimpleFlag"; -} - -class MarshallingInfoBitfieldFlag - : MarshallingInfoFlag, "unsigned"> { - code Normalizer = "(normalizeFlagToValue)"; - code ValueMerger = "mergeMaskValue"; - code ValueExtractor = "(extractMaskValue)"; + string MarshallingKind = "flag"; } // Mixins for additional marshalling attributes. -class IsNegative { - // todo: create & apply a normalizer for negative flags -} +class IsNegative { bit IsPositive = 0; } class AlwaysEmit { bit ShouldAlwaysEmit = 1; } class Normalizer { code Normalizer = normalizer; } class Denormalizer { code Denormalizer = denormalizer; } @@ -185,8 +177,6 @@ class AutoNormalizeEnum { code Normalizer = "normalizeSimpleEnum"; code Denormalizer = "denormalizeSimpleEnum"; } -class ValueMerger { code ValueMerger = merger; } -class ValueExtractor { code ValueExtractor = extractor; } // Predefined options. diff --git a/unittests/Option/OptionMarshallingTest.cpp b/unittests/Option/OptionMarshallingTest.cpp index e8582f1bbbd..bf26a767bba 100644 --- a/unittests/Option/OptionMarshallingTest.cpp +++ b/unittests/Option/OptionMarshallingTest.cpp @@ -15,33 +15,33 @@ struct OptionWithMarshallingInfo { }; static const OptionWithMarshallingInfo MarshallingTable[] = { -#define OPTION_WITH_MARSHALLING( \ - PREFIX_TYPE, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \ - HELPTEXT, METAVAR, VALUES, SPELLING, ALWAYS_EMIT, KEYPATH, DEFAULT_VALUE, \ - TYPE, NORMALIZER, DENORMALIZER, MERGER, EXTRACTOR, TABLE_INDEX) \ - {NAME, #KEYPATH, #DEFAULT_VALUE}, +#define OPTION_WITH_MARSHALLING_FLAG(PREFIX_TYPE, NAME, ID, KIND, GROUP, \ + ALIAS, ALIASARGS, FLAGS, PARAM, HELPTEXT, \ + METAVAR, VALUES, SPELLING, ALWAYS_EMIT, \ + KEYPATH, DEFAULT_VALUE, IS_POSITIVE) \ + { NAME, #KEYPATH, #DEFAULT_VALUE }, #include "Opts.inc" -#undef OPTION_WITH_MARSHALLING +#undef OPTION_WITH_MARSHALLING_FLAG }; TEST(OptionMarshalling, EmittedOrderSameAsDefinitionOrder) { - ASSERT_STREQ(MarshallingTable[0].Name, "marshalled-flag-d"); - ASSERT_STREQ(MarshallingTable[1].Name, "marshalled-flag-c"); - ASSERT_STREQ(MarshallingTable[2].Name, "marshalled-flag-b"); - ASSERT_STREQ(MarshallingTable[3].Name, "marshalled-flag-a"); + ASSERT_STREQ(MarshallingTable[0].Name, "marshalled-flag-0"); + ASSERT_STREQ(MarshallingTable[1].Name, "marshalled-flag-1"); + ASSERT_STREQ(MarshallingTable[2].Name, "marshalled-flag-2"); + ASSERT_STREQ(MarshallingTable[3].Name, "marshalled-flag-3"); } TEST(OptionMarshalling, EmittedSpecifiedKeyPath) { - ASSERT_STREQ(MarshallingTable[0].KeyPath, "MarshalledFlagD"); - ASSERT_STREQ(MarshallingTable[1].KeyPath, "MarshalledFlagC"); - ASSERT_STREQ(MarshallingTable[2].KeyPath, "MarshalledFlagB"); - ASSERT_STREQ(MarshallingTable[3].KeyPath, "MarshalledFlagA"); + ASSERT_STREQ(MarshallingTable[0].KeyPath, "MarshalledFlag0"); + ASSERT_STREQ(MarshallingTable[1].KeyPath, "MarshalledFlag1"); + ASSERT_STREQ(MarshallingTable[2].KeyPath, "MarshalledFlag2"); + ASSERT_STREQ(MarshallingTable[3].KeyPath, "MarshalledFlag3"); } TEST(OptionMarshalling, DefaultAnyOfConstructedDisjunctionOfKeypaths) { ASSERT_STREQ(MarshallingTable[0].DefaultValue, "false"); - ASSERT_STREQ(MarshallingTable[1].DefaultValue, "false || MarshalledFlagD"); - ASSERT_STREQ(MarshallingTable[2].DefaultValue, "false || MarshalledFlagD"); + ASSERT_STREQ(MarshallingTable[1].DefaultValue, "false || MarshalledFlag0"); + ASSERT_STREQ(MarshallingTable[2].DefaultValue, "false || MarshalledFlag0"); ASSERT_STREQ(MarshallingTable[3].DefaultValue, - "false || MarshalledFlagC || MarshalledFlagB"); + "false || MarshalledFlag1 || MarshalledFlag2"); } diff --git a/unittests/Option/Opts.td b/unittests/Option/Opts.td index 62cd6151ea9..3bbf210b0b7 100644 --- a/unittests/Option/Opts.td +++ b/unittests/Option/Opts.td @@ -45,11 +45,11 @@ def Blurmpq_eq : Flag<["--"], "blurmp=">; def DashDash : Option<["--"], "", KIND_REMAINING_ARGS>; -def marshalled_flag_d : Flag<["-"], "marshalled-flag-d">, - MarshallingInfoFlag<"MarshalledFlagD", DefaultAnyOf<[]>>; -def marshalled_flag_c : Flag<["-"], "marshalled-flag-c">, - MarshallingInfoFlag<"MarshalledFlagC", DefaultAnyOf<[marshalled_flag_d]>>; -def marshalled_flag_b : Flag<["-"], "marshalled-flag-b">, - MarshallingInfoFlag<"MarshalledFlagB", DefaultAnyOf<[marshalled_flag_d]>>; -def marshalled_flag_a : Flag<["-"], "marshalled-flag-a">, - MarshallingInfoFlag<"MarshalledFlagA", DefaultAnyOf<[marshalled_flag_c, marshalled_flag_b]>>; +def marshalled_flag_0 : Flag<["-"], "marshalled-flag-0">, + MarshallingInfoFlag<"MarshalledFlag0", DefaultAnyOf<[]>>; +def marshalled_flag_1 : Flag<["-"], "marshalled-flag-1">, + MarshallingInfoFlag<"MarshalledFlag1", DefaultAnyOf<[marshalled_flag_0]>>; +def marshalled_flag_2 : Flag<["-"], "marshalled-flag-2">, + MarshallingInfoFlag<"MarshalledFlag2", DefaultAnyOf<[marshalled_flag_0]>>; +def marshalled_flag_3 : Flag<["-"], "marshalled-flag-3">, + MarshallingInfoFlag<"MarshalledFlag3", DefaultAnyOf<[marshalled_flag_1, marshalled_flag_2]>>; diff --git a/utils/TableGen/OptParserEmitter.cpp b/utils/TableGen/OptParserEmitter.cpp index a3387896e54..d791bd8032c 100644 --- a/utils/TableGen/OptParserEmitter.cpp +++ b/utils/TableGen/OptParserEmitter.cpp @@ -61,20 +61,74 @@ static void emitNameUsingSpelling(raw_ostream &OS, const Record &R) { OS << "[" << PrefixLength << "]"; } -class MarshallingInfo { +class MarshallingKindInfo { public: - static constexpr const char *MacroName = "OPTION_WITH_MARSHALLING"; - const Record &R; + const char *MacroName; bool ShouldAlwaysEmit; 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 emitValueTable(raw_ostream &OS) const { + return None; + } + + virtual ~MarshallingKindInfo() = default; + + static std::unique_ptr 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 create(const Record &R) { + std::unique_ptr Ret(new MarshallingFlagInfo(R)); + Ret->IsPositive = R.getValueAsBit("IsPositive"); + // FIXME: This is a workaround for a bug in older versions of clang (< 3.9) + // The constructor that is supposed to allow for Derived to Base + // conversion does not work. Remove this if we drop support for such + // configurations. + return std::unique_ptr(Ret.release()); + } + +private: + MarshallingFlagInfo(const Record &R) + : MarshallingKindInfo(R, "OPTION_WITH_MARSHALLING_FLAG") {} +}; + +class MarshallingStringInfo final : public MarshallingKindInfo { +public: StringRef NormalizerRetTy; StringRef Normalizer; StringRef Denormalizer; - StringRef ValueMerger; - StringRef ValueExtractor; int TableIndex = -1; std::vector Values; std::vector NormalizedValues; @@ -95,29 +149,17 @@ struct SimpleEnumValueTable { static constexpr const char *ValueTablesDecl = "static const SimpleEnumValueTable SimpleEnumValueTables[] = "; - void emit(raw_ostream &OS) const { - write_cstring(OS, StringRef(getOptionSpelling(R))); - OS << ", "; - OS << ShouldAlwaysEmit; - OS << ", "; - OS << KeyPath; - OS << ", "; - emitScopedNormalizedValue(OS, DefaultValue); - OS << ", "; + void emitSpecific(raw_ostream &OS) const override { emitScopedNormalizedValue(OS, NormalizerRetTy); OS << ", "; OS << Normalizer; OS << ", "; OS << Denormalizer; OS << ", "; - OS << ValueMerger; - OS << ", "; - OS << ValueExtractor; - OS << ", "; OS << TableIndex; } - Optional emitValueTable(raw_ostream &OS) const { + Optional emitValueTable(raw_ostream &OS) const override { if (TableIndex == -1) return {}; OS << "static const SimpleEnumValue " << ValueTableName << "[] = {\n"; @@ -133,32 +175,23 @@ struct SimpleEnumValueTable { return StringRef(ValueTableName); } - static MarshallingInfo create(const Record &R) { - assert(!isa(R.getValueInit("KeyPath")) && - !isa(R.getValueInit("DefaultValue")) && - !isa(R.getValueInit("NormalizerRetTy")) && - !isa(R.getValueInit("ValueMerger")) && - "MarshallingInfo must have a type"); + static std::unique_ptr create(const Record &R) { + assert(!isa(R.getValueInit("NormalizerRetTy")) && + "String options must have a type"); - MarshallingInfo Ret(R); - Ret.ShouldAlwaysEmit = R.getValueAsBit("ShouldAlwaysEmit"); - Ret.KeyPath = R.getValueAsString("KeyPath"); - Ret.DefaultValue = R.getValueAsString("DefaultValue"); - Ret.NormalizedValuesScope = R.getValueAsString("NormalizedValuesScope"); - Ret.NormalizerRetTy = R.getValueAsString("NormalizerRetTy"); + std::unique_ptr Ret(new MarshallingStringInfo(R)); + Ret->NormalizerRetTy = R.getValueAsString("NormalizerRetTy"); - Ret.Normalizer = R.getValueAsString("Normalizer"); - Ret.Denormalizer = R.getValueAsString("Denormalizer"); - Ret.ValueMerger = R.getValueAsString("ValueMerger"); - Ret.ValueExtractor = R.getValueAsString("ValueExtractor"); + Ret->Normalizer = R.getValueAsString("Normalizer"); + Ret->Denormalizer = R.getValueAsString("Denormalizer"); if (!isa(R.getValueInit("NormalizedValues"))) { assert(!isa(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"; + 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 (;;) { @@ -166,34 +199,55 @@ struct SimpleEnumValueTable { if (Idx == StringRef::npos) break; if (Idx > 0) - Ret.Values.push_back(ValuesStr.slice(0, Idx)); + Ret->Values.push_back(ValuesStr.slice(0, Idx)); ValuesStr = ValuesStr.slice(Idx + 1, StringRef::npos); } if (!ValuesStr.empty()) - Ret.Values.push_back(ValuesStr); + Ret->Values.push_back(ValuesStr); - assert(Ret.Values.size() == Ret.NormalizedValues.size() && + assert(Ret->Values.size() == Ret->NormalizedValues.size() && "The number of normalized values doesn't match the number of " "values"); } - return Ret; + // FIXME: This is a workaround for a bug in older versions of clang (< 3.9) + // The constructor that is supposed to allow for Derived to Base + // conversion does not work. Remove this if we drop support for such + // configurations. + return std::unique_ptr(Ret.release()); } private: - void emitScopedNormalizedValue(raw_ostream &OS, - StringRef NormalizedValue) const { - if (!NormalizedValuesScope.empty()) - OS << NormalizedValuesScope << "::"; - OS << NormalizedValue; - } - - MarshallingInfo(const Record &R) : R(R){}; + MarshallingStringInfo(const Record &R) + : MarshallingKindInfo(R, "OPTION_WITH_MARSHALLING_STRING") {} static size_t NextTableIndex; }; -size_t MarshallingInfo::NextTableIndex = 0; +size_t MarshallingStringInfo::NextTableIndex = 0; + +std::unique_ptr +MarshallingKindInfo::create(const Record &R) { + assert(!isa(R.getValueInit("KeyPath")) && + !isa(R.getValueInit("DefaultValue")) && + "Must provide at least a key-path and a default value for emitting " + "marshalling information"); + + std::unique_ptr 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(R.getValueInit("NormalizedValuesScope"))) + Ret->NormalizedValuesScope = R.getValueAsString("NormalizedValuesScope"); + return Ret; +} /// OptParserEmitter - This tablegen backend takes an input .td file /// describing a list of options and emits a data structure for parsing and @@ -384,7 +438,7 @@ void EmitOptParser(RecordKeeper &Records, raw_ostream &OS) { }; auto IsMarshallingOption = [](const Record &R) { - return !isa(R.getValueInit("KeyPath")) && + return !isa(R.getValueInit("MarshallingKind")) && !R.getValueAsString("KeyPath").empty(); }; @@ -418,30 +472,30 @@ void EmitOptParser(RecordKeeper &Records, raw_ostream &OS) { array_pod_sort(OptsWithMarshalling.begin(), OptsWithMarshalling.end(), CmpMarshallingOpts); - std::vector MarshallingInfos; + std::vector> MarshallingKindInfos; for (const auto *R : OptsWithMarshalling) - MarshallingInfos.push_back(MarshallingInfo::create(*R)); + MarshallingKindInfos.push_back(MarshallingKindInfo::create(*R)); - for (const auto &MI : MarshallingInfos) { - OS << "#ifdef " << MI.MacroName << "\n"; - OS << MI.MacroName << "("; - WriteOptRecordFields(OS, MI.R); + for (const auto &KindInfo : MarshallingKindInfos) { + OS << "#ifdef " << KindInfo->MacroName << "\n"; + OS << KindInfo->MacroName << "("; + WriteOptRecordFields(OS, KindInfo->R); OS << ", "; - MI.emit(OS); + KindInfo->emit(OS); OS << ")\n"; - OS << "#endif // " << MI.MacroName << "\n"; + OS << "#endif // " << KindInfo->MacroName << "\n"; } OS << "\n"; OS << "#ifdef SIMPLE_ENUM_VALUE_TABLE"; OS << "\n"; - OS << MarshallingInfo::ValueTablePreamble; + OS << MarshallingStringInfo::ValueTablePreamble; std::vector ValueTableNames; - for (const auto &MI : MarshallingInfos) - if (auto MaybeValueTableName = MI.emitValueTable(OS)) + for (const auto &KindInfo : MarshallingKindInfos) + if (auto MaybeValueTableName = KindInfo->emitValueTable(OS)) ValueTableNames.push_back(*MaybeValueTableName); - OS << MarshallingInfo::ValueTablesDecl << "{"; + OS << MarshallingStringInfo::ValueTablesDecl << "{"; for (auto ValueTableName : ValueTableNames) OS << "{" << ValueTableName << ", sizeof(" << ValueTableName << ") / sizeof(SimpleEnumValue)"