This revision was landed with ongoing or failed builds. This revision was automatically updated to reflect the committed changes. Closed by commit rG2f3055c543f8: [clang][cli] Add support for options with two flags for controlling the same⦠(authored by jansvoboda11).
Changed prior to commit: https://reviews.llvm.org/D83071?vs=304491&id=305428#toc Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D83071/new/ https://reviews.llvm.org/D83071 Files: clang/include/clang/Driver/Options.td clang/lib/Frontend/CompilerInvocation.cpp llvm/include/llvm/Option/OptParser.td llvm/utils/TableGen/OptParserEmitter.cpp
Index: llvm/utils/TableGen/OptParserEmitter.cpp =================================================================== --- llvm/utils/TableGen/OptParserEmitter.cpp +++ llvm/utils/TableGen/OptParserEmitter.cpp @@ -63,8 +63,9 @@ class MarshallingInfo { public: - static constexpr const char *MacroName = "OPTION_WITH_MARSHALLING"; + using Ptr = std::unique_ptr<MarshallingInfo>; + const char *MacroName; const Record &R; bool ShouldAlwaysEmit; StringRef KeyPath; @@ -80,6 +81,8 @@ std::vector<StringRef> NormalizedValues; std::string ValueTableName; + static size_t NextTableIndex; + static constexpr const char *ValueTablePreamble = R"( struct SimpleEnumValue { const char *Name; @@ -95,7 +98,14 @@ static constexpr const char *ValueTablesDecl = "static const SimpleEnumValueTable SimpleEnumValueTables[] = "; - void emit(raw_ostream &OS) const { + MarshallingInfo(const Record &R) + : MacroName("OPTION_WITH_MARSHALLING"), R(R) {} + MarshallingInfo(const char *MacroName, const Record &R) + : MacroName(MacroName), R(R){}; + + virtual ~MarshallingInfo() = default; + + virtual void emit(raw_ostream &OS) const { write_cstring(OS, StringRef(getOptionSpelling(R))); OS << ", "; OS << ShouldAlwaysEmit; @@ -133,53 +143,6 @@ return StringRef(ValueTableName); } - static MarshallingInfo create(const Record &R) { - assert(!isa<UnsetInit>(R.getValueInit("KeyPath")) && - !isa<UnsetInit>(R.getValueInit("DefaultValue")) && - !isa<UnsetInit>(R.getValueInit("NormalizerRetTy")) && - !isa<UnsetInit>(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.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 = 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: void emitScopedNormalizedValue(raw_ostream &OS, StringRef NormalizedValue) const { @@ -187,13 +150,85 @@ OS << NormalizedValuesScope << "::"; OS << NormalizedValue; } +}; + +size_t MarshallingInfo::NextTableIndex = 0; - MarshallingInfo(const Record &R) : R(R){}; +class MarshallingInfoBooleanFlag : public MarshallingInfo { +public: + const Record &NegOption; - static size_t NextTableIndex; + MarshallingInfoBooleanFlag(const Record &Option, const Record &NegOption) + : MarshallingInfo("OPTION_WITH_MARSHALLING_BOOLEAN", Option), + NegOption(NegOption) {} + + void emit(raw_ostream &OS) const override { + MarshallingInfo::emit(OS); + OS << ", "; + OS << getOptionName(NegOption); + OS << ", "; + write_cstring(OS, getOptionSpelling(NegOption)); + } }; -size_t MarshallingInfo::NextTableIndex = 0; +static MarshallingInfo::Ptr createMarshallingInfo(const Record &R) { + assert(!isa<UnsetInit>(R.getValueInit("KeyPath")) && + !isa<UnsetInit>(R.getValueInit("DefaultValue")) && + !isa<UnsetInit>(R.getValueInit("NormalizerRetTy")) && + !isa<UnsetInit>(R.getValueInit("ValueMerger")) && + "MarshallingInfo must have a type"); + + MarshallingInfo::Ptr Ret; + StringRef KindString = R.getValueAsString("MarshallingInfoKind"); + if (KindString == "Default") { + Ret = std::make_unique<MarshallingInfo>(R); + } else if (KindString == "BooleanFlag") { + Ret = std::make_unique<MarshallingInfoBooleanFlag>( + R, *R.getValueAsDef("NegOption")); + } + + 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->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"); + } + + // 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 MarshallingInfo::Ptr(Ret.release()); +} /// OptParserEmitter - This tablegen backend takes an input .td file /// describing a list of options and emits a data structure for parsing and @@ -418,18 +453,18 @@ array_pod_sort(OptsWithMarshalling.begin(), OptsWithMarshalling.end(), CmpMarshallingOpts); - std::vector<MarshallingInfo> MarshallingInfos; + std::vector<MarshallingInfo::Ptr> MarshallingInfos; for (const auto *R : OptsWithMarshalling) - MarshallingInfos.push_back(MarshallingInfo::create(*R)); + MarshallingInfos.push_back(createMarshallingInfo(*R)); for (const auto &MI : MarshallingInfos) { - OS << "#ifdef " << MarshallingInfo::MacroName << "\n"; - OS << MarshallingInfo::MacroName << "("; - WriteOptRecordFields(OS, MI.R); + OS << "#ifdef " << MI->MacroName << "\n"; + OS << MI->MacroName << "("; + WriteOptRecordFields(OS, MI->R); OS << ", "; - MI.emit(OS); + MI->emit(OS); OS << ")\n"; - OS << "#endif // " << MarshallingInfo::MacroName << "\n"; + OS << "#endif // " << MI->MacroName << "\n"; } OS << "\n"; @@ -438,7 +473,7 @@ OS << MarshallingInfo::ValueTablePreamble; std::vector<StringRef> ValueTableNames; for (const auto &MI : MarshallingInfos) - if (auto MaybeValueTableName = MI.emitValueTable(OS)) + if (auto MaybeValueTableName = MI->emitValueTable(OS)) ValueTableNames.push_back(*MaybeValueTableName); OS << MarshallingInfo::ValueTablesDecl << "{"; Index: llvm/include/llvm/Option/OptParser.td =================================================================== --- llvm/include/llvm/Option/OptParser.td +++ llvm/include/llvm/Option/OptParser.td @@ -97,6 +97,7 @@ OptionGroup Group = ?; Option Alias = ?; list<string> AliasArgs = []; + string MarshallingInfoKind = ?; code KeyPath = ?; code DefaultValue = ?; bit ShouldAlwaysEmit = false; @@ -107,6 +108,8 @@ code ValueMerger = "mergeForwardValue"; code ValueExtractor = "extractForwardValue"; list<code> NormalizedValues = ?; + // Used for BooleanFlagKind + Option NegOption = ?; } // Helpers for defining options. @@ -148,6 +151,7 @@ } class MarshallingInfo<code keypath, code defaultvalue> { + string MarshallingInfoKind = "Default"; code KeyPath = keypath; code DefaultValue = defaultvalue; } @@ -161,6 +165,7 @@ : MarshallingInfo<keypath, defaults.DefaultValue> { code NormalizerRetTy = ty; code Normalizer = "normalizeSimpleFlag"; + code Denormalizer = "denormalizeSimpleFlag"; } class MarshallingInfoBitfieldFlag<code keypath, code value> @@ -170,6 +175,15 @@ code ValueExtractor = "(extractMaskValue<unsigned, decltype("#value#"), "#value#">)"; } +class MarshallingInfoBooleanFlag<code keypath, code defaultvalue, Option negopt> + : MarshallingInfoFlag<keypath, DefaultAnyOf<[], defaultvalue>> { + bit ShouldAlwaysEmit = 1; + string MarshallingInfoKind = "BooleanFlag"; + code Normalizer = "normalizeBooleanFlag"; + code Denormalizer = "denormalizeBooleanFlag"; + Option NegOption = negopt; +} + // Mixins for additional marshalling attributes. class IsNegative { Index: clang/lib/Frontend/CompilerInvocation.cpp =================================================================== --- clang/lib/Frontend/CompilerInvocation.cpp +++ clang/lib/Frontend/CompilerInvocation.cpp @@ -134,6 +134,13 @@ return None; } +void denormalizeSimpleFlag(SmallVectorImpl<const char *> &Args, + const char *Spelling, + CompilerInvocation::StringAllocator SA, + unsigned TableIndex, unsigned Value) { + Args.push_back(Spelling); +} + template <typename T, T Value> static llvm::Optional<T> normalizeFlagToValue(OptSpecifier Opt, unsigned TableIndex, const ArgList &Args, @@ -143,6 +150,27 @@ return None; } +static Optional<bool> normalizeBooleanFlag(OptSpecifier PosOpt, + OptSpecifier NegOpt, + unsigned TableIndex, + const ArgList &Args, + DiagnosticsEngine &Diags) { + if (const Arg *A = Args.getLastArg(PosOpt, NegOpt)) + return A->getOption().matches(PosOpt); + return None; +} + +static void denormalizeBooleanFlag(SmallVectorImpl<const char *> &Args, + const char *Spelling, + const char *NegSpelling, + CompilerInvocation::StringAllocator SA, + unsigned TableIndex, unsigned Value) { + if (Value) + Args.push_back(Spelling); + else + Args.push_back(NegSpelling); +} + static llvm::Optional<unsigned> normalizeSimpleEnum(OptSpecifier Opt, unsigned TableIndex, const ArgList &Args, @@ -165,12 +193,14 @@ } static void denormalizeSimpleEnum(SmallVectorImpl<const char *> &Args, + const char *Spelling, 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(Spelling); Args.push_back(Table.Table[I].Name); return; } @@ -181,8 +211,10 @@ } static void denormalizeString(SmallVectorImpl<const char *> &Args, + const char *Spelling, CompilerInvocation::StringAllocator SA, unsigned TableIndex, const std::string &Value) { + Args.push_back(Spelling); Args.push_back(SA(Value)); } @@ -777,10 +809,6 @@ } } - Opts.ExperimentalNewPassManager = Args.hasFlag( - OPT_fexperimental_new_pass_manager, OPT_fno_experimental_new_pass_manager, - /* Default */ ENABLE_EXPERIMENTAL_NEW_PASS_MANAGER); - Opts.DebugPassManager = Args.hasFlag(OPT_fdebug_pass_manager, OPT_fno_debug_pass_manager, /* Default */ false); @@ -3741,7 +3769,21 @@ this->KEYPATH = MERGER(this->KEYPATH, static_cast<TYPE>(*MaybeValue)); \ } +#define OPTION_WITH_MARSHALLING_BOOLEAN( \ + 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, NEG_ID, \ + NEG_SPELLING) \ + { \ + if (auto MaybeValue = \ + NORMALIZER(OPT_##ID, OPT_##NEG_ID, TABLE_INDEX, Args, Diags)) \ + this->KEYPATH = MERGER(this->KEYPATH, static_cast<TYPE>(*MaybeValue)); \ + else \ + this->KEYPATH = MERGER(this->KEYPATH, DEFAULT_VALUE); \ + } + #include "clang/Driver/Options.inc" +#undef OPTION_WITH_MARSHALLING_BOOLEAN #undef OPTION_WITH_MARSHALLING return true; } @@ -4000,16 +4042,22 @@ TYPE, NORMALIZER, DENORMALIZER, MERGER, EXTRACTOR, TABLE_INDEX) \ if (((FLAGS) & options::CC1Option) && \ (ALWAYS_EMIT || EXTRACTOR(this->KEYPATH) != (DEFAULT_VALUE))) { \ - if (Option::KIND##Class == Option::FlagClass) { \ - Args.push_back(SPELLING); \ - } \ - if (Option::KIND##Class == Option::SeparateClass) { \ - Args.push_back(SPELLING); \ - DENORMALIZER(Args, SA, TABLE_INDEX, EXTRACTOR(this->KEYPATH)); \ - } \ + DENORMALIZER(Args, SPELLING, SA, TABLE_INDEX, EXTRACTOR(this->KEYPATH)); \ + } + +#define OPTION_WITH_MARSHALLING_BOOLEAN( \ + 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, NEG_ID, \ + NEG_SPELLING) \ + if (((FLAGS)&options::CC1Option) && \ + (ALWAYS_EMIT || EXTRACTOR(this->KEYPATH) != DEFAULT_VALUE)) { \ + DENORMALIZER(Args, SPELLING, NEG_SPELLING, SA, TABLE_INDEX, \ + EXTRACTOR(this->KEYPATH)); \ } #include "clang/Driver/Options.inc" +#undef OPTION_WITH_MARSHALLING_BOOLEAN #undef OPTION_WITH_MARSHALLING } Index: clang/include/clang/Driver/Options.td =================================================================== --- clang/include/clang/Driver/Options.td +++ clang/include/clang/Driver/Options.td @@ -266,6 +266,12 @@ MarshallingInfoFlag<keypath, defaults>; } +multiclass BooleanMarshalledFFlag<string name, code keypath, code default_value, string pos_help = "", string neg_help=""> { + def fno_#NAME : Flag<["-"], "fno-"#name>, HelpText<neg_help>; + def f#NAME : Flag<["-"], "f"#name>, HelpText<pos_help>, + MarshallingInfoBooleanFlag<keypath, default_value, !cast<Option>("fno_"#NAME)>; +} + ///////// // Options @@ -1320,9 +1326,9 @@ HelpText<"Enables the global instruction selector">; def fexperimental_isel : Flag<["-"], "fexperimental-isel">, Group<f_clang_Group>, Alias<fglobal_isel>; -def fexperimental_new_pass_manager : Flag<["-"], "fexperimental-new-pass-manager">, - Group<f_clang_Group>, Flags<[CC1Option]>, - HelpText<"Enables an experimental new pass manager in LLVM.">; +defm experimental_new_pass_manager : BooleanMarshalledFFlag<"experimental-new-pass-manager", "CodeGenOpts.ExperimentalNewPassManager", + "static_cast<unsigned>(ENABLE_EXPERIMENTAL_NEW_PASS_MANAGER)", "Enables an experimental new pass manager in LLVM.", + "Disables an experimental new pass manager in LLVM.">, Group<f_clang_Group>, Flags<[CC1Option]>; def fexperimental_strict_floating_point : Flag<["-"], "fexperimental-strict-floating-point">, Group<f_clang_Group>, Flags<[CC1Option]>, HelpText<"Enables experimental strict floating point in LLVM.">, @@ -1624,9 +1630,6 @@ HelpText<"Disables the global instruction selector">; def fno_experimental_isel : Flag<["-"], "fno-experimental-isel">, Group<f_clang_Group>, Alias<fno_global_isel>; -def fno_experimental_new_pass_manager : Flag<["-"], "fno-experimental-new-pass-manager">, - Group<f_clang_Group>, Flags<[CC1Option]>, - HelpText<"Disables an experimental new pass manager in LLVM.">; def fveclib : Joined<["-"], "fveclib=">, Group<f_Group>, Flags<[CC1Option]>, HelpText<"Use the given vector functions library">, Values<"Accelerate,libmvec,MASSV,SVML,none">; def fno_lax_vector_conversions : Flag<["-"], "fno-lax-vector-conversions">, Group<f_Group>,
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits