From f917356f9ce026f9be9972b8c75cd3ba00e43497 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). --- clang/include/clang/Driver/Options.td | 47 ++--- clang/lib/Frontend/CompilerInvocation.cpp | 129 ++++++------ llvm/include/llvm/Option/OptParser.td | 32 ++- .../Option/OptionMarshallingTest.cpp | 34 ++-- llvm/unittests/Option/Opts.td | 16 +- llvm/utils/TableGen/OptParserEmitter.cpp | 184 +++++++++++------- 6 files changed, 237 insertions(+), 205 deletions(-) diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 05a218ca09f0..6df4a0222484 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -340,53 +340,36 @@ def ccc_objcmt_migrate : Separate<["-"], "ccc-objcmt-migrate">, InternalDriverOpt, HelpText<"Apply modifications and produces temporary files to migrate to " "modern ObjC syntax">; - def objcmt_migrate_literals : Flag<["-"], "objcmt-migrate-literals">, Flags<[CC1Option]>, - HelpText<"Enable migration to modern ObjC literals">, - MarshallingInfoBitfieldFlag<"FrontendOpts.ObjCMTAction", "FrontendOptions::ObjCMT_Literals">; + HelpText<"Enable migration to modern ObjC literals">; def objcmt_migrate_subscripting : Flag<["-"], "objcmt-migrate-subscripting">, Flags<[CC1Option]>, - HelpText<"Enable migration to modern ObjC subscripting">, - MarshallingInfoBitfieldFlag<"FrontendOpts.ObjCMTAction", "FrontendOptions::ObjCMT_Subscripting">; + HelpText<"Enable migration to modern ObjC subscripting">; def objcmt_migrate_property : Flag<["-"], "objcmt-migrate-property">, Flags<[CC1Option]>, - HelpText<"Enable migration to modern ObjC property">, - MarshallingInfoBitfieldFlag<"FrontendOpts.ObjCMTAction", "FrontendOptions::ObjCMT_Property">; + HelpText<"Enable migration to modern ObjC property">; def objcmt_migrate_all : Flag<["-"], "objcmt-migrate-all">, Flags<[CC1Option]>, - HelpText<"Enable migration to modern ObjC">, - MarshallingInfoBitfieldFlag<"FrontendOpts.ObjCMTAction", "FrontendOptions::ObjCMT_MigrateDecls">; + HelpText<"Enable migration to modern ObjC">; def objcmt_migrate_readonly_property : Flag<["-"], "objcmt-migrate-readonly-property">, Flags<[CC1Option]>, - HelpText<"Enable migration to modern ObjC readonly property">, - MarshallingInfoBitfieldFlag<"FrontendOpts.ObjCMTAction", "FrontendOptions::ObjCMT_ReadonlyProperty">; + HelpText<"Enable migration to modern ObjC readonly property">; def objcmt_migrate_readwrite_property : Flag<["-"], "objcmt-migrate-readwrite-property">, Flags<[CC1Option]>, - HelpText<"Enable migration to modern ObjC readwrite property">, - MarshallingInfoBitfieldFlag<"FrontendOpts.ObjCMTAction", "FrontendOptions::ObjCMT_ReadwriteProperty">; + HelpText<"Enable migration to modern ObjC readwrite property">; def objcmt_migrate_property_dot_syntax : Flag<["-"], "objcmt-migrate-property-dot-syntax">, Flags<[CC1Option]>, - HelpText<"Enable migration of setter/getter messages to property-dot syntax">, - MarshallingInfoBitfieldFlag<"FrontendOpts.ObjCMTAction", "FrontendOptions::ObjCMT_PropertyDotSyntax">; + HelpText<"Enable migration of setter/getter messages to property-dot syntax">; def objcmt_migrate_annotation : Flag<["-"], "objcmt-migrate-annotation">, Flags<[CC1Option]>, - HelpText<"Enable migration to property and method annotations">, - MarshallingInfoBitfieldFlag<"FrontendOpts.ObjCMTAction", "FrontendOptions::ObjCMT_Annotation">; + HelpText<"Enable migration to property and method annotations">; def objcmt_migrate_instancetype : Flag<["-"], "objcmt-migrate-instancetype">, Flags<[CC1Option]>, - HelpText<"Enable migration to infer instancetype for method result type">, - MarshallingInfoBitfieldFlag<"FrontendOpts.ObjCMTAction", "FrontendOptions::ObjCMT_Instancetype">; + HelpText<"Enable migration to infer instancetype for method result type">; def objcmt_migrate_nsmacros : Flag<["-"], "objcmt-migrate-ns-macros">, Flags<[CC1Option]>, - HelpText<"Enable migration to NS_ENUM/NS_OPTIONS macros">, - MarshallingInfoBitfieldFlag<"FrontendOpts.ObjCMTAction", "FrontendOptions::ObjCMT_NsMacros">; + HelpText<"Enable migration to NS_ENUM/NS_OPTIONS macros">; def objcmt_migrate_protocol_conformance : Flag<["-"], "objcmt-migrate-protocol-conformance">, Flags<[CC1Option]>, - HelpText<"Enable migration to add protocol conformance on classes">, - MarshallingInfoBitfieldFlag<"FrontendOpts.ObjCMTAction", "FrontendOptions::ObjCMT_ProtocolConformance">; + HelpText<"Enable migration to add protocol conformance on classes">; def objcmt_atomic_property : Flag<["-"], "objcmt-atomic-property">, Flags<[CC1Option]>, - HelpText<"Make migration to 'atomic' properties">, - MarshallingInfoBitfieldFlag<"FrontendOpts.ObjCMTAction", "FrontendOptions::ObjCMT_AtomicProperty">; + HelpText<"Make migration to 'atomic' properties">; def objcmt_returns_innerpointer_property : Flag<["-"], "objcmt-returns-innerpointer-property">, Flags<[CC1Option]>, - HelpText<"Enable migration to annotate property with NS_RETURNS_INNER_POINTER">, - MarshallingInfoBitfieldFlag<"FrontendOpts.ObjCMTAction", "FrontendOptions::ObjCMT_ReturnsInnerPointerProperty">; + HelpText<"Enable migration to annotate property with NS_RETURNS_INNER_POINTER">; def objcmt_ns_nonatomic_iosonly: Flag<["-"], "objcmt-ns-nonatomic-iosonly">, Flags<[CC1Option]>, - HelpText<"Enable migration to use NS_NONATOMIC_IOSONLY macro for setting property's 'atomic' attribute">, - MarshallingInfoBitfieldFlag<"FrontendOpts.ObjCMTAction", "FrontendOptions::ObjCMT_NsAtomicIOSOnlyProperty">; + HelpText<"Enable migration to use NS_NONATOMIC_IOSONLY macro for setting property's 'atomic' attribute">; def objcmt_migrate_designated_init : Flag<["-"], "objcmt-migrate-designated-init">, Flags<[CC1Option]>, - HelpText<"Enable migration to infer NS_DESIGNATED_INITIALIZER for initializer methods">, - MarshallingInfoBitfieldFlag<"FrontendOpts.ObjCMTAction", "FrontendOptions::ObjCMT_DesignatedInitializer">; - + HelpText<"Enable migration to infer NS_DESIGNATED_INITIALIZER for initializer methods">; def objcmt_whitelist_dir_path: Joined<["-"], "objcmt-whitelist-dir-path=">, Flags<[CC1Option]>, HelpText<"Only modify files with a filename contained in the provided directory path">; // The misspelt "white-list" [sic] alias is due for removal. diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 0a776bfe4518..d3516f5bf1a4 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -125,24 +125,6 @@ CompilerInvocationBase::~CompilerInvocationBase() = default; #include "clang/Driver/Options.inc" #undef SIMPLE_ENUM_VALUE_TABLE -static llvm::Optional normalizeSimpleFlag(OptSpecifier Opt, - unsigned TableIndex, - const ArgList &Args, - DiagnosticsEngine &Diags) { - if (Args.hasArg(Opt)) - return true; - return None; -} - -template -static llvm::Optional -normalizeFlagToValue(OptSpecifier Opt, unsigned TableIndex, const ArgList &Args, - DiagnosticsEngine &Diags) { - if (Args.hasArg(Opt)) - return Value; - return None; -} - static llvm::Optional normalizeSimpleEnum(OptSpecifier Opt, unsigned TableIndex, const ArgList &Args, @@ -164,26 +146,22 @@ static llvm::Optional normalizeSimpleEnum(OptSpecifier Opt, return None; } -static void denormalizeSimpleEnum(SmallVectorImpl &Args, - CompilerInvocation::StringAllocator SA, - unsigned TableIndex, unsigned Value) { +static const char *denormalizeSimpleEnum(CompilerInvocation::StringAllocator SA, + unsigned TableIndex, unsigned Value) { assert(TableIndex < SimpleEnumValueTablesSize); const SimpleEnumValueTable &Table = SimpleEnumValueTables[TableIndex]; - for (int I = 0, E = Table.Size; I != E; ++I) { - if (Value == Table.Table[I].Value) { - Args.push_back(Table.Table[I].Name); - return; - } - } + for (int I = 0, E = Table.Size; I != E; ++I) + if (Value == Table.Table[I].Value) + return Table.Table[I].Name; llvm_unreachable("The simple enum value was not correctly defined in " "the tablegen option description"); } -static void denormalizeString(SmallVectorImpl &Args, - CompilerInvocation::StringAllocator SA, - unsigned TableIndex, const std::string &Value) { - Args.push_back(SA(Value)); +static const char *denormalizeString(CompilerInvocation::StringAllocator SA, + unsigned TableIndex, + const std::string &Value) { + return SA(Value); } static Optional normalizeTriple(OptSpecifier Opt, int TableIndex, @@ -195,24 +173,6 @@ static Optional normalizeTriple(OptSpecifier Opt, int TableIndex, return llvm::Triple::normalize(Arg->getValue()); } -template -static T mergeForwardValue(T KeyPath, U Value) { - return Value; -} - -template static T mergeMaskValue(T KeyPath, U Value) { - return KeyPath | Value; -} - -template static T extractForwardValue(T KeyPath) { - return KeyPath; -} - -template -static T extractMaskValue(T KeyPath) { - return KeyPath & Value; -} - //===----------------------------------------------------------------------===// // Deserialization (from args) //===----------------------------------------------------------------------===// @@ -2050,6 +2010,37 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, Opts.ARCMTMigrateEmitARCErrors = Args.hasArg(OPT_arcmt_migrate_emit_arc_errors); + if (Args.hasArg(OPT_objcmt_migrate_literals)) + Opts.ObjCMTAction |= FrontendOptions::ObjCMT_Literals; + if (Args.hasArg(OPT_objcmt_migrate_subscripting)) + Opts.ObjCMTAction |= FrontendOptions::ObjCMT_Subscripting; + if (Args.hasArg(OPT_objcmt_migrate_property_dot_syntax)) + Opts.ObjCMTAction |= FrontendOptions::ObjCMT_PropertyDotSyntax; + if (Args.hasArg(OPT_objcmt_migrate_property)) + Opts.ObjCMTAction |= FrontendOptions::ObjCMT_Property; + if (Args.hasArg(OPT_objcmt_migrate_readonly_property)) + Opts.ObjCMTAction |= FrontendOptions::ObjCMT_ReadonlyProperty; + if (Args.hasArg(OPT_objcmt_migrate_readwrite_property)) + Opts.ObjCMTAction |= FrontendOptions::ObjCMT_ReadwriteProperty; + if (Args.hasArg(OPT_objcmt_migrate_annotation)) + Opts.ObjCMTAction |= FrontendOptions::ObjCMT_Annotation; + if (Args.hasArg(OPT_objcmt_returns_innerpointer_property)) + Opts.ObjCMTAction |= FrontendOptions::ObjCMT_ReturnsInnerPointerProperty; + if (Args.hasArg(OPT_objcmt_migrate_instancetype)) + Opts.ObjCMTAction |= FrontendOptions::ObjCMT_Instancetype; + if (Args.hasArg(OPT_objcmt_migrate_nsmacros)) + Opts.ObjCMTAction |= FrontendOptions::ObjCMT_NsMacros; + if (Args.hasArg(OPT_objcmt_migrate_protocol_conformance)) + Opts.ObjCMTAction |= FrontendOptions::ObjCMT_ProtocolConformance; + if (Args.hasArg(OPT_objcmt_atomic_property)) + Opts.ObjCMTAction |= FrontendOptions::ObjCMT_AtomicProperty; + if (Args.hasArg(OPT_objcmt_ns_nonatomic_iosonly)) + Opts.ObjCMTAction |= FrontendOptions::ObjCMT_NsAtomicIOSOnlyProperty; + if (Args.hasArg(OPT_objcmt_migrate_designated_init)) + Opts.ObjCMTAction |= FrontendOptions::ObjCMT_DesignatedInitializer; + if (Args.hasArg(OPT_objcmt_migrate_all)) + Opts.ObjCMTAction |= FrontendOptions::ObjCMT_MigrateDecls; + Opts.ObjCMTWhiteListPath = std::string(Args.getLastArgValue(OPT_objcmt_whitelist_dir_path)); @@ -3734,18 +3725,26 @@ static void ParseTargetArgs(TargetOptions &Opts, ArgList &Args, bool CompilerInvocation::parseSimpleArgs(const ArgList &Args, DiagnosticsEngine &Diags) { -#define OPTION_WITH_MARSHALLING( \ +#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) \ + this->KEYPATH = (Args.hasArg(OPT_##ID) && IS_POSITIVE) || (DEFAULT_VALUE); + +#define OPTION_WITH_MARSHALLING_STRING( \ 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) \ + TYPE, NORMALIZER, DENORMALIZER, TABLE_INDEX) \ { \ - this->KEYPATH = MERGER(this->KEYPATH, DEFAULT_VALUE); \ if (auto MaybeValue = NORMALIZER(OPT_##ID, TABLE_INDEX, Args, Diags)) \ - this->KEYPATH = MERGER(this->KEYPATH, static_cast(*MaybeValue)); \ + this->KEYPATH = static_cast(*MaybeValue); \ + else \ + this->KEYPATH = DEFAULT_VALUE; \ } #include "clang/Driver/Options.inc" -#undef OPTION_WITH_MARSHALLING +#undef OPTION_WITH_MARSHALLING_STRING +#undef OPTION_WITH_MARSHALLING_FLAG return true; } @@ -4000,23 +3999,29 @@ std::string CompilerInvocation::getModuleHash() const { void CompilerInvocation::generateCC1CommandLine( SmallVectorImpl &Args, StringAllocator SA) const { -#define OPTION_WITH_MARSHALLING( \ +#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) \ + if ((FLAGS) & options::CC1Option && \ + (ALWAYS_EMIT || this->KEYPATH != (DEFAULT_VALUE))) \ + Args.push_back(SPELLING); + +#define OPTION_WITH_MARSHALLING_STRING( \ 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) \ + NORMALIZER_RET_TY, NORMALIZER, DENORMALIZER, TABLE_INDEX) \ if (((FLAGS) & options::CC1Option) && \ - (ALWAYS_EMIT || EXTRACTOR(this->KEYPATH) != (DEFAULT_VALUE))) { \ - if (Option::KIND##Class == Option::FlagClass) { \ - Args.push_back(SPELLING); \ - } \ + (ALWAYS_EMIT || this->KEYPATH != DEFAULT_VALUE)) { \ if (Option::KIND##Class == Option::SeparateClass) { \ Args.push_back(SPELLING); \ - DENORMALIZER(Args, SA, TABLE_INDEX, EXTRACTOR(this->KEYPATH)); \ + Args.push_back(DENORMALIZER(SA, TABLE_INDEX, this->KEYPATH)); \ } \ } #include "clang/Driver/Options.inc" -#undef OPTION_WITH_MARSHALLING +#undef OPTION_WITH_MARSHALLING_STRING +#undef OPTION_WITH_MARSHALLING_FLAG } namespace clang { diff --git a/llvm/include/llvm/Option/OptParser.td b/llvm/include/llvm/Option/OptParser.td index 005a9524699f..47b4788b2209 100644 --- a/llvm/include/llvm/Option/OptParser.td +++ b/llvm/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/llvm/unittests/Option/OptionMarshallingTest.cpp b/llvm/unittests/Option/OptionMarshallingTest.cpp index e8582f1bbbd0..bf26a767bba1 100644 --- a/llvm/unittests/Option/OptionMarshallingTest.cpp +++ b/llvm/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/llvm/unittests/Option/Opts.td b/llvm/unittests/Option/Opts.td index 62cd6151ea9e..3bbf210b0b74 100644 --- a/llvm/unittests/Option/Opts.td +++ b/llvm/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/llvm/utils/TableGen/OptParserEmitter.cpp b/llvm/utils/TableGen/OptParserEmitter.cpp index a3387896e541..d791bd8032c2 100644 --- a/llvm/utils/TableGen/OptParserEmitter.cpp +++ b/llvm/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)"