diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -323,36 +323,83 @@ 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">; + HelpText<"Enable migration to modern ObjC literals">, + MarshallingInfoFlag<"FrontendOpts.ObjCMTAction", "0", "unsigned">, Normalizer<"normalizeFlagToValue">, + ValueMerger<"MERGE_VALUE_MASK">, ValueExtractor<"EXTRACT_VALUE_MASK">, + NormalizerCookie<"FrontendOptions::ObjCMT_Literals">; def objcmt_migrate_subscripting : Flag<["-"], "objcmt-migrate-subscripting">, Flags<[CC1Option]>, - HelpText<"Enable migration to modern ObjC subscripting">; + HelpText<"Enable migration to modern ObjC subscripting">, + MarshallingInfoFlag<"FrontendOpts.ObjCMTAction", "0", "unsigned">, Normalizer<"normalizeFlagToValue">, + ValueMerger<"MERGE_VALUE_MASK">, ValueExtractor<"EXTRACT_VALUE_MASK">, + NormalizerCookie<"FrontendOptions::ObjCMT_Subscripting">; +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">, + MarshallingInfoFlag<"FrontendOpts.ObjCMTAction", "0", "unsigned">, Normalizer<"normalizeFlagToValue">, + ValueMerger<"MERGE_VALUE_MASK">, ValueExtractor<"EXTRACT_VALUE_MASK">, + NormalizerCookie<"FrontendOptions::ObjCMT_PropertyDotSyntax">; def objcmt_migrate_property : Flag<["-"], "objcmt-migrate-property">, Flags<[CC1Option]>, - HelpText<"Enable migration to modern ObjC property">; -def objcmt_migrate_all : Flag<["-"], "objcmt-migrate-all">, Flags<[CC1Option]>, - HelpText<"Enable migration to modern ObjC">; + HelpText<"Enable migration to modern ObjC property">, + MarshallingInfoFlag<"FrontendOpts.ObjCMTAction", "0", "unsigned">, Normalizer<"normalizeFlagToValue">, + ValueMerger<"MERGE_VALUE_MASK">, ValueExtractor<"EXTRACT_VALUE_MASK">, + NormalizerCookie<"FrontendOptions::ObjCMT_Property">; def objcmt_migrate_readonly_property : Flag<["-"], "objcmt-migrate-readonly-property">, Flags<[CC1Option]>, - HelpText<"Enable migration to modern ObjC readonly property">; + HelpText<"Enable migration to modern ObjC readonly property">, + MarshallingInfoFlag<"FrontendOpts.ObjCMTAction", "0", "unsigned">, Normalizer<"normalizeFlagToValue">, + ValueMerger<"MERGE_VALUE_MASK">, ValueExtractor<"EXTRACT_VALUE_MASK">, + NormalizerCookie<"FrontendOptions::ObjCMT_ReadonlyProperty">; def objcmt_migrate_readwrite_property : Flag<["-"], "objcmt-migrate-readwrite-property">, Flags<[CC1Option]>, - 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">; + HelpText<"Enable migration to modern ObjC readwrite property">, + MarshallingInfoFlag<"FrontendOpts.ObjCMTAction", "0", "unsigned">, Normalizer<"normalizeFlagToValue">, + ValueMerger<"MERGE_VALUE_MASK">, ValueExtractor<"EXTRACT_VALUE_MASK">, + NormalizerCookie<"FrontendOptions::ObjCMT_ReadwriteProperty">; def objcmt_migrate_annotation : Flag<["-"], "objcmt-migrate-annotation">, Flags<[CC1Option]>, - HelpText<"Enable migration to property and method annotations">; + HelpText<"Enable migration to property and method annotations">, + MarshallingInfoFlag<"FrontendOpts.ObjCMTAction", "0", "unsigned">, Normalizer<"normalizeFlagToValue">, + ValueMerger<"MERGE_VALUE_MASK">, ValueExtractor<"EXTRACT_VALUE_MASK">, + NormalizerCookie<"FrontendOptions::ObjCMT_Annotation">; +def objcmt_returns_innerpointer_property : Flag<["-"], "objcmt-returns-innerpointer-property">, Flags<[CC1Option]>, + HelpText<"Enable migration to annotate property with NS_RETURNS_INNER_POINTER">, + MarshallingInfoFlag<"FrontendOpts.ObjCMTAction", "0", "unsigned">, Normalizer<"normalizeFlagToValue">, + ValueMerger<"MERGE_VALUE_MASK">, ValueExtractor<"EXTRACT_VALUE_MASK">, + NormalizerCookie<"FrontendOptions::ObjCMT_ReturnsInnerPointerProperty">; def objcmt_migrate_instancetype : Flag<["-"], "objcmt-migrate-instancetype">, Flags<[CC1Option]>, - HelpText<"Enable migration to infer instancetype for method result type">; + HelpText<"Enable migration to infer instancetype for method result type">, + MarshallingInfoFlag<"FrontendOpts.ObjCMTAction", "0", "unsigned">, Normalizer<"normalizeFlagToValue">, + ValueMerger<"MERGE_VALUE_MASK">, ValueExtractor<"EXTRACT_VALUE_MASK">, + NormalizerCookie<"FrontendOptions::ObjCMT_Instancetype">; def objcmt_migrate_nsmacros : Flag<["-"], "objcmt-migrate-ns-macros">, Flags<[CC1Option]>, - HelpText<"Enable migration to NS_ENUM/NS_OPTIONS macros">; + HelpText<"Enable migration to NS_ENUM/NS_OPTIONS macros">, + MarshallingInfoFlag<"FrontendOpts.ObjCMTAction", "0", "unsigned">, Normalizer<"normalizeFlagToValue">, + ValueMerger<"MERGE_VALUE_MASK">, ValueExtractor<"EXTRACT_VALUE_MASK">, + NormalizerCookie<"FrontendOptions::ObjCMT_NsMacros">; def objcmt_migrate_protocol_conformance : Flag<["-"], "objcmt-migrate-protocol-conformance">, Flags<[CC1Option]>, - HelpText<"Enable migration to add protocol conformance on classes">; + HelpText<"Enable migration to add protocol conformance on classes">, + MarshallingInfoFlag<"FrontendOpts.ObjCMTAction", "0", "unsigned">, Normalizer<"normalizeFlagToValue">, + ValueMerger<"MERGE_VALUE_MASK">, ValueExtractor<"EXTRACT_VALUE_MASK">, + NormalizerCookie<"FrontendOptions::ObjCMT_ProtocolConformance">; def objcmt_atomic_property : Flag<["-"], "objcmt-atomic-property">, Flags<[CC1Option]>, - 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">; + HelpText<"Make migration to 'atomic' properties">, + MarshallingInfoFlag<"FrontendOpts.ObjCMTAction", "0", "unsigned">, Normalizer<"normalizeFlagToValue">, + ValueMerger<"MERGE_VALUE_MASK">, ValueExtractor<"EXTRACT_VALUE_MASK">, + NormalizerCookie<"FrontendOptions::ObjCMT_AtomicProperty">; 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">; + HelpText<"Enable migration to use NS_NONATOMIC_IOSONLY macro for setting property's 'atomic' attribute">, + MarshallingInfoFlag<"FrontendOpts.ObjCMTAction", "0", "unsigned">, Normalizer<"normalizeFlagToValue">, + ValueMerger<"MERGE_VALUE_MASK">, ValueExtractor<"EXTRACT_VALUE_MASK">, + NormalizerCookie<"FrontendOptions::ObjCMT_NsAtomicIOSOnlyProperty">; def objcmt_migrate_designated_init : Flag<["-"], "objcmt-migrate-designated-init">, Flags<[CC1Option]>, - HelpText<"Enable migration to infer NS_DESIGNATED_INITIALIZER for initializer methods">; + HelpText<"Enable migration to infer NS_DESIGNATED_INITIALIZER for initializer methods">, + MarshallingInfoFlag<"FrontendOpts.ObjCMTAction", "0", "unsigned">, Normalizer<"normalizeFlagToValue">, + ValueMerger<"MERGE_VALUE_MASK">, ValueExtractor<"EXTRACT_VALUE_MASK">, + NormalizerCookie<"FrontendOptions::ObjCMT_DesignatedInitializer">; +def objcmt_migrate_all : Flag<["-"], "objcmt-migrate-all">, Flags<[CC1Option]>, + HelpText<"Enable migration to modern ObjC">, + MarshallingInfoFlag<"FrontendOpts.ObjCMTAction", "0", "unsigned">, Normalizer<"normalizeFlagToValue">, + ValueMerger<"MERGE_VALUE_MASK">, ValueExtractor<"EXTRACT_VALUE_MASK">, + NormalizerCookie<"FrontendOptions::ObjCMT_MigrateDecls">; + 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 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -125,10 +125,31 @@ #include "clang/Driver/Options.inc" #undef SIMPLE_ENUM_VALUE_TABLE -static llvm::Optional normalizeSimpleEnum(OptSpecifier Opt, - unsigned TableIndex, - const ArgList &Args, - DiagnosticsEngine &Diags) { +static llvm::Optional +normalizeSimpleFlag(OptSpecifier Opt, unsigned TableIndex, const ArgList &Args, + DiagnosticsEngine &Diags, void *Cookie) { + return Args.hasArg(Opt); +} + +static llvm::Optional +normalizeSimpleNegativeFlag(OptSpecifier Opt, unsigned TableIndex, + const ArgList &Args, DiagnosticsEngine &Diags, + void *Cookie) { + return !Args.hasArg(Opt); +} + +template +static llvm::Optional +normalizeFlagToValue(OptSpecifier Opt, unsigned TableIndex, const ArgList &Args, + DiagnosticsEngine &Diags, T Cookie) { + if (Args.hasArg(Opt)) + return Cookie; + return None; +} + +static llvm::Optional +normalizeSimpleEnum(OptSpecifier Opt, unsigned TableIndex, const ArgList &Args, + DiagnosticsEngine &Diags, void *Cookie) { assert(TableIndex < SimpleEnumValueTablesSize); const SimpleEnumValueTable &Table = SimpleEnumValueTables[TableIndex]; @@ -146,27 +167,32 @@ return None; } -static const char *denormalizeSimpleEnum(CompilerInvocation::StringAllocator SA, - unsigned TableIndex, unsigned Value) { +static void denormalizeSimpleEnum(SmallVectorImpl &Args, + 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) - return Table.Table[I].Name; + for (int I = 0, E = Table.Size; I != E; ++I) { + if (Value == Table.Table[I].Value) { + Args.push_back(Table.Table[I].Name); + return; + } + } llvm_unreachable("The simple enum value was not correctly defined in " "the tablegen option description"); } -static const char *denormalizeString(CompilerInvocation::StringAllocator SA, - unsigned TableIndex, - const std::string &Value) { - return SA(Value); +static void denormalizeString(SmallVectorImpl &Args, + CompilerInvocation::StringAllocator SA, + unsigned TableIndex, const std::string &Value) { + Args.push_back(SA(Value)); } static Optional normalizeTriple(OptSpecifier Opt, int TableIndex, const ArgList &Args, - DiagnosticsEngine &Diags) { + DiagnosticsEngine &Diags, + void *Cookie) { auto *Arg = Args.getLastArg(Opt); if (!Arg) return None; @@ -1968,37 +1994,6 @@ 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)); @@ -3614,26 +3609,25 @@ bool CompilerInvocation::parseSimpleArgs(const ArgList &Args, DiagnosticsEngine &Diags) { -#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; +#define MERGE_ASSIGN_VALUE(KEYPATH, VALUE) (KEYPATH) = (VALUE) +#define MERGE_VALUE_MASK(KEYPATH, VALUE) (KEYPATH) |= (VALUE) -#define OPTION_WITH_MARSHALLING_STRING( \ +#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, TABLE_INDEX) \ + TYPE, NORMALIZER, DENORMALIZER, COOKIE, MERGER, EXTRACTOR, TABLE_INDEX) \ { \ - if (auto MaybeValue = NORMALIZER(OPT_##ID, TABLE_INDEX, Args, Diags)) \ - this->KEYPATH = static_cast(*MaybeValue); \ + if (auto MaybeValue = \ + NORMALIZER(OPT_##ID, TABLE_INDEX, Args, Diags, COOKIE)) \ + MERGER(this->KEYPATH, static_cast(*MaybeValue)); \ else \ - this->KEYPATH = DEFAULT_VALUE; \ + MERGER(this->KEYPATH, DEFAULT_VALUE); \ } #include "clang/Driver/Options.inc" -#undef OPTION_WITH_MARSHALLING_STRING -#undef OPTION_WITH_MARSHALLING_FLAG +#undef OPTION_WITH_MARSHALLING +#undef MERGE_VALUE_MASK +#undef MERGE_ASSIGN_VALUE return true; } @@ -3880,29 +3874,28 @@ void CompilerInvocation::generateCC1CommandLine( SmallVectorImpl &Args, StringAllocator SA) const { -#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( \ +#define EXTRACT_VALUE(KEYPATH, COOKIE) (KEYPATH) +#define EXTRACT_VALUE_MASK(KEYPATH, COOKIE) ((KEYPATH) & (COOKIE)) + +#define OPTION_WITH_MARSHALLING( \ PREFIX_TYPE, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \ HELPTEXT, METAVAR, VALUES, SPELLING, ALWAYS_EMIT, KEYPATH, DEFAULT_VALUE, \ - NORMALIZER_RET_TY, NORMALIZER, DENORMALIZER, TABLE_INDEX) \ - if (((FLAGS) & options::CC1Option) && \ - (ALWAYS_EMIT || this->KEYPATH != DEFAULT_VALUE)) { \ + TYPE, NORMALIZER, DENORMALIZER, COOKIE, MERGER, EXTRACTOR, TABLE_INDEX) \ + if (((FLAGS)&options::CC1Option) && \ + (ALWAYS_EMIT || EXTRACTOR(this->KEYPATH, COOKIE) != DEFAULT_VALUE)) { \ + if (Option::KIND##Class == Option::FlagClass) { \ + Args.push_back(SPELLING); \ + } \ if (Option::KIND##Class == Option::SeparateClass) { \ Args.push_back(SPELLING); \ - Args.push_back(DENORMALIZER(SA, TABLE_INDEX, this->KEYPATH)); \ + DENORMALIZER(Args, SA, TABLE_INDEX, EXTRACTOR(this->KEYPATH, COOKIE)); \ } \ } #include "clang/Driver/Options.inc" -#undef OPTION_WITH_MARSHALLING_STRING -#undef OPTION_WITH_MARSHALLING_FLAG +#undef OPTION_WITH_MARSHALLING +#undef EXTRACT_VALUE_MASK +#undef EXTRACT_VALUE } namespace clang { diff --git a/llvm/include/llvm/Option/OptParser.td b/llvm/include/llvm/Option/OptParser.td --- a/llvm/include/llvm/Option/OptParser.td +++ b/llvm/include/llvm/Option/OptParser.td @@ -97,17 +97,16 @@ 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 NormalizerCookie = "nullptr"; + code ValueMerger = "MERGE_ASSIGN_VALUE"; + code ValueExtractor = "EXTRACT_VALUE"; list NormalizedValues = ?; } @@ -148,23 +147,27 @@ code KeyPath = keypath; code DefaultValue = defaultvalue; } + class MarshallingInfoString : MarshallingInfo { - string MarshallingKind = "string"; code NormalizerRetTy = normalizerretty; } -class MarshallingInfoFlag +class MarshallingInfoFlag : MarshallingInfo { - string MarshallingKind = "flag"; + code NormalizerRetTy = ty; + code Normalizer = "normalizeSimpleFlag"; } // Mixins for additional marshalling attributes. -class IsNegative { bit IsPositive = 0; } +class IsNegative { + code Normalizer = "normalizeSimpleNegativeFlag"; +} class AlwaysEmit { bit ShouldAlwaysEmit = 1; } class Normalizer { code Normalizer = normalizer; } class Denormalizer { code Denormalizer = denormalizer; } +class NormalizerCookie { code NormalizerCookie = cookie; } class NormalizedValuesScope { code NormalizedValuesScope = scope; } class NormalizedValues definitions> { list NormalizedValues = definitions; } class DenormalizeString { code Denormalizer = "denormalizeString"; } @@ -172,6 +175,8 @@ code Normalizer = "normalizeSimpleEnum"; code Denormalizer = "denormalizeSimpleEnum"; } +class ValueMerger { code ValueMerger = merger; } +class ValueExtractor { code ValueExtractor = extractor; } // Predefined options. diff --git a/llvm/utils/TableGen/OptParserEmitter.cpp b/llvm/utils/TableGen/OptParserEmitter.cpp --- a/llvm/utils/TableGen/OptParserEmitter.cpp +++ b/llvm/utils/TableGen/OptParserEmitter.cpp @@ -59,70 +59,21 @@ OS << "[" << PrefixLength << "]"; } -class MarshallingKindInfo { +class MarshallingInfo { 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"); - return Ret; - } - -private: - MarshallingFlagInfo(const Record &R) - : MarshallingKindInfo(R, "OPTION_WITH_MARSHALLING_FLAG") {} -}; - -class MarshallingStringInfo final : public MarshallingKindInfo { -public: StringRef NormalizerRetTy; StringRef Normalizer; + StringRef NormalizerCookie; StringRef Denormalizer; + StringRef ValueMerger; + StringRef ValueExtractor; int TableIndex = -1; std::vector Values; std::vector NormalizedValues; @@ -143,17 +94,31 @@ static constexpr const char *ValueTablesDecl = "static const SimpleEnumValueTable SimpleEnumValueTables[] = "; - void emitSpecific(raw_ostream &OS) const override { + void emit(raw_ostream &OS) const { + write_cstring(OS, StringRef(getOptionSpelling(R))); + OS << ", "; + OS << ShouldAlwaysEmit; + OS << ", "; + OS << KeyPath; + OS << ", "; + emitScopedNormalizedValue(OS, DefaultValue); + OS << ", "; emitScopedNormalizedValue(OS, NormalizerRetTy); OS << ", "; OS << Normalizer; OS << ", "; OS << Denormalizer; OS << ", "; + OS << NormalizerCookie; + OS << ", "; + OS << ValueMerger; + OS << ", "; + OS << ValueExtractor; + OS << ", "; OS << TableIndex; } - Optional emitValueTable(raw_ostream &OS) const override { + Optional emitValueTable(raw_ostream &OS) const { if (TableIndex == -1) return {}; OS << "static const SimpleEnumValue " << ValueTableName << "[] = {\n"; @@ -169,23 +134,33 @@ return StringRef(ValueTableName); } - static std::unique_ptr create(const Record &R) { - assert(!isa(R.getValueInit("NormalizerRetTy")) && - "String options must have a type"); - - std::unique_ptr Ret(new MarshallingStringInfo(R)); - Ret->NormalizerRetTy = R.getValueAsString("NormalizerRetTy"); - - Ret->Normalizer = R.getValueAsString("Normalizer"); - Ret->Denormalizer = R.getValueAsString("Denormalizer"); + 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"); + + 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"); + + Ret.Normalizer = R.getValueAsString("Normalizer"); + Ret.Denormalizer = R.getValueAsString("Denormalizer"); + Ret.NormalizerCookie = R.getValueAsString("NormalizerCookie"); + Ret.ValueMerger = R.getValueAsString("ValueMerger"); + Ret.ValueExtractor = R.getValueAsString("ValueExtractor"); 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 (;;) { @@ -193,13 +168,13 @@ 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"); } @@ -208,36 +183,19 @@ } private: - MarshallingStringInfo(const Record &R) - : MarshallingKindInfo(R, "OPTION_WITH_MARSHALLING_STRING") {} + void emitScopedNormalizedValue(raw_ostream &OS, + StringRef NormalizedValue) const { + if (!NormalizedValuesScope.empty()) + OS << NormalizedValuesScope << "::"; + OS << NormalizedValue; + } + + MarshallingInfo(const Record &R) : R(R){}; static size_t NextTableIndex; }; -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; -} +size_t MarshallingInfo::NextTableIndex = 0; /// OptParserEmitter - This tablegen backend takes an input .td file /// describing a list of options and emits a data structure for parsing and @@ -427,7 +385,7 @@ OS << "nullptr"; }; - std::vector> OptsWithMarshalling; + std::vector OptsWithMarshalling; for (unsigned I = 0, E = Opts.size(); I != E; ++I) { const Record &R = *Opts[I]; @@ -435,32 +393,32 @@ OS << "OPTION("; WriteOptRecordFields(OS, R); OS << ")\n"; - if (!isa(R.getValueInit("MarshallingKind")) && + if (!isa(R.getValueInit("KeyPath")) && !R.getValueAsString("KeyPath").empty()) - OptsWithMarshalling.push_back(MarshallingKindInfo::create(R)); + OptsWithMarshalling.push_back(MarshallingInfo::create(R)); } OS << "#endif // OPTION\n"; for (const auto &KindInfo : OptsWithMarshalling) { - OS << "#ifdef " << KindInfo->MacroName << "\n"; - OS << KindInfo->MacroName << "("; - WriteOptRecordFields(OS, KindInfo->R); + OS << "#ifdef " << KindInfo.MacroName << "\n"; + OS << KindInfo.MacroName << "("; + WriteOptRecordFields(OS, KindInfo.R); OS << ", "; - KindInfo->emit(OS); + KindInfo.emit(OS); OS << ")\n"; - OS << "#endif // " << KindInfo->MacroName << "\n"; + OS << "#endif // " << KindInfo.MacroName << "\n"; } OS << "\n"; OS << "#ifdef SIMPLE_ENUM_VALUE_TABLE"; OS << "\n"; - OS << MarshallingStringInfo::ValueTablePreamble; + OS << MarshallingInfo::ValueTablePreamble; std::vector ValueTableNames; for (const auto &KindInfo : OptsWithMarshalling) - if (auto MaybeValueTableName = KindInfo->emitValueTable(OS)) + if (auto MaybeValueTableName = KindInfo.emitValueTable(OS)) ValueTableNames.push_back(*MaybeValueTableName); - OS << MarshallingStringInfo::ValueTablesDecl << "{"; + OS << MarshallingInfo::ValueTablesDecl << "{"; for (auto ValueTableName : ValueTableNames) OS << "{" << ValueTableName << ", sizeof(" << ValueTableName << ") / sizeof(SimpleEnumValue)"