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 @@ -449,7 +449,9 @@ HelpText<"Treat source input files as Objective-C++ inputs">; def ObjC : Flag<["-"], "ObjC">, Flags<[DriverOption]>, HelpText<"Treat source input files as Objective-C inputs">; -def O : Joined<["-"], "O">, Group, Flags<[CC1Option]>; +def O : Joined<["-"], "O">, Group, Flags<[CC1Option]>, + MarshallingInfoString<"CodeGenOpts.OptimizationLevel", "llvm::CodeGenOpt::Default">, + AlwaysEmit, Denormalizer<"denormalizeOptimizationLevel">; def O_flag : Flag<["-"], "O">, Flags<[CC1Option]>, Alias, AliasArgs<["1"]>; def Ofast : Joined<["-"], "Ofast">, Group, Flags<[CC1Option]>; def P : Flag<["-"], "P">, Flags<[CC1Option]>, Group, 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 @@ -258,6 +258,14 @@ return llvm::Triple::normalize(Arg->getValue()); } +static void denormalizeOptimizationLevel(SmallVectorImpl &Args, + const char *Spelling, + CompilerInvocation::StringAllocator SA, + unsigned TableIndex, + const unsigned Value) { + Args.push_back(SA(Twine(Spelling) + Twine(Value))); +} + template static T mergeForwardValue(T KeyPath, U Value) { return Value; @@ -3659,10 +3667,10 @@ bool CompilerInvocation::parseSimpleArgs(const ArgList &Args, DiagnosticsEngine &Diags) { -#define OPTION_WITH_MARSHALLING( \ - PREFIX_TYPE, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \ - HELPTEXT, METAVAR, VALUES, SPELLING, ALWAYS_EMIT, KEYPATH, DEFAULT_VALUE, \ - NORMALIZER, DENORMALIZER, MERGER, EXTRACTOR, TABLE_INDEX) \ +#define OPTION_WITH_PARSING(PREFIX_TYPE, NAME, ID, KIND, GROUP, ALIAS, \ + ALIASARGS, FLAGS, PARAM, HELPTEXT, METAVAR, \ + VALUES, KEYPATH, DEFAULT_VALUE, NORMALIZER, \ + MERGER, TABLE_INDEX) \ { \ if (auto MaybeValue = NORMALIZER(OPT_##ID, TABLE_INDEX, Args, Diags)) \ this->KEYPATH = MERGER( \ @@ -3671,11 +3679,10 @@ this->KEYPATH = MERGER(this->KEYPATH, DEFAULT_VALUE); \ } -#define OPTION_WITH_MARSHALLING_BOOLEAN( \ - PREFIX_TYPE, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \ - HELPTEXT, METAVAR, VALUES, SPELLING, ALWAYS_EMIT, KEYPATH, DEFAULT_VALUE, \ - NORMALIZER, DENORMALIZER, MERGER, EXTRACTOR, TABLE_INDEX, NEG_ID, \ - NEG_SPELLING) \ +#define OPTION_WITH_PARSING_BOOLEAN(PREFIX_TYPE, NAME, ID, KIND, GROUP, ALIAS, \ + ALIASARGS, FLAGS, PARAM, HELPTEXT, \ + METAVAR, VALUES, KEYPATH, DEFAULT_VALUE, \ + NORMALIZER, MERGER, TABLE_INDEX, NEG_ID) \ { \ if (auto MaybeValue = \ NORMALIZER(OPT_##ID, OPT_##NEG_ID, TABLE_INDEX, Args, Diags)) \ @@ -3686,8 +3693,8 @@ } #include "clang/Driver/Options.inc" -#undef OPTION_WITH_MARSHALLING_BOOLEAN -#undef OPTION_WITH_MARSHALLING +#undef OPTION_WITH_PARSING_BOOLEAN +#undef OPTION_WITH_PARSING return true; } @@ -3936,21 +3943,20 @@ void CompilerInvocation::generateCC1CommandLine( SmallVectorImpl &Args, StringAllocator SA) const { -#define OPTION_WITH_MARSHALLING( \ +#define OPTION_WITH_SERIALIZING( \ PREFIX_TYPE, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \ - HELPTEXT, METAVAR, VALUES, SPELLING, ALWAYS_EMIT, KEYPATH, DEFAULT_VALUE, \ - NORMALIZER, DENORMALIZER, MERGER, EXTRACTOR, TABLE_INDEX) \ + HELPTEXT, METAVAR, VALUES, KEYPATH, DEFAULT_VALUE, SPELLING, ALWAYS_EMIT, \ + DENORMALIZER, EXTRACTOR, TABLE_INDEX) \ if ((FLAGS)&options::CC1Option) { \ const auto &Extracted = EXTRACTOR(this->KEYPATH); \ if (ALWAYS_EMIT || Extracted != DEFAULT_VALUE) \ DENORMALIZER(Args, SPELLING, SA, TABLE_INDEX, Extracted); \ } -#define OPTION_WITH_MARSHALLING_BOOLEAN( \ +#define OPTION_WITH_SERIALIZING_BOOLEAN( \ PREFIX_TYPE, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \ - HELPTEXT, METAVAR, VALUES, SPELLING, ALWAYS_EMIT, KEYPATH, DEFAULT_VALUE, \ - NORMALIZER, DENORMALIZER, MERGER, EXTRACTOR, TABLE_INDEX, NEG_ID, \ - NEG_SPELLING) \ + HELPTEXT, METAVAR, VALUES, KEYPATH, DEFAULT_VALUE, SPELLING, ALWAYS_EMIT, \ + DENORMALIZER, EXTRACTOR, TABLE_INDEX, NEG_SPELLING) \ if ((FLAGS)&options::CC1Option) { \ const auto &Extracted = EXTRACTOR(this->KEYPATH); \ if (ALWAYS_EMIT || Extracted != DEFAULT_VALUE) \ @@ -3958,8 +3964,8 @@ } #include "clang/Driver/Options.inc" -#undef OPTION_WITH_MARSHALLING_BOOLEAN -#undef OPTION_WITH_MARSHALLING +#undef OPTION_WITH_SERIALIZING_BOOLEAN +#undef OPTION_WITH_SERIALIZING } 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 @@ -103,8 +103,8 @@ bit ShouldAlwaysEmit = 0; code NormalizerRetTy = ?; code NormalizedValuesScope = ""; - code Normalizer = ""; - code Denormalizer = ""; + code Normalizer = ?; + code Denormalizer = ?; code ValueMerger = "mergeForwardValue"; code ValueExtractor = "extractForwardValue"; list NormalizedValues = ?; 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 @@ -63,8 +63,11 @@ public: using Ptr = std::unique_ptr; - const char *MacroName; + static constexpr const char *MacroNameSerializing = "OPTION_WITH_SERIALIZING"; + static constexpr const char *MacroNameParsing = "OPTION_WITH_PARSING"; + const Record &R; + bool CanParse; bool ShouldAlwaysEmit; StringRef KeyPath; StringRef DefaultValue; @@ -95,31 +98,36 @@ static constexpr const char *ValueTablesDecl = "static const SimpleEnumValueTable SimpleEnumValueTables[] = "; - MarshallingInfo(const Record &R) - : MacroName("OPTION_WITH_MARSHALLING"), R(R) {} - MarshallingInfo(const char *MacroName, const Record &R) - : MacroName(MacroName), R(R){}; + MarshallingInfo(const Record &R) : R(R) {} virtual ~MarshallingInfo() = default; - virtual void emit(raw_ostream &OS) const { - write_cstring(OS, StringRef(getOptionSpelling(R))); - OS << ", "; - OS << ShouldAlwaysEmit; - OS << ", "; - OS << KeyPath; - OS << ", "; - emitScopedNormalizedValue(OS, DefaultValue); - OS << ", "; - OS << Normalizer; - OS << ", "; - OS << Denormalizer; - OS << ", "; - OS << ValueMerger; + virtual void + emitParsing(raw_ostream &OS, + llvm::function_ref + WriteOptRecordFields) const { + if (!CanParse) + return; + OS << "#ifdef " << MacroNameParsing << "\n"; + OS << MacroNameParsing << "("; + WriteOptRecordFields(OS, R); OS << ", "; - OS << ValueExtractor; + emitParsingFields(OS); + OS << ")\n"; + OS << "#endif // " << MacroNameParsing << "\n"; + } + + virtual void + emitSerialiazing(raw_ostream &OS, + llvm::function_ref + WriteOptRecordFields) const { + OS << "#ifdef " << MacroNameSerializing << "\n"; + OS << MacroNameSerializing << "("; + WriteOptRecordFields(OS, R); OS << ", "; - OS << TableIndex; + emitSerializingFields(OS); + OS << ")\n"; + OS << "#endif // " << MacroNameSerializing << "\n"; } Optional emitValueTable(raw_ostream &OS) const { @@ -138,6 +146,35 @@ return StringRef(ValueTableName); } +protected: + void emitParsingFields(raw_ostream &OS) const { + OS << KeyPath; + OS << ", "; + emitScopedNormalizedValue(OS, DefaultValue); + OS << ", "; + OS << Normalizer; + OS << ", "; + OS << ValueMerger; + OS << ", "; + OS << TableIndex; + } + + void emitSerializingFields(raw_ostream &OS) const { + OS << KeyPath; + OS << ", "; + emitScopedNormalizedValue(OS, DefaultValue); + OS << ", "; + write_cstring(OS, StringRef(getOptionSpelling(R))); + OS << ", "; + OS << ShouldAlwaysEmit; + OS << ", "; + OS << Denormalizer; + OS << ", "; + OS << ValueExtractor; + OS << ", "; + OS << TableIndex; + } + private: void emitScopedNormalizedValue(raw_ostream &OS, StringRef NormalizedValue) const { @@ -154,24 +191,45 @@ const Record &NegOption; 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); + : MarshallingInfo(Option), NegOption(NegOption) {} + + void emitParsing(raw_ostream &OS, + llvm::function_ref + WriteOptRecordFields) const override { + if (!CanParse) + return; + OS << "#ifdef " << MacroNameParsing << "_BOOLEAN\n"; + OS << MacroNameParsing << "_BOOLEAN("; + WriteOptRecordFields(OS, R); + OS << ", "; + emitParsingFields(OS); OS << ", "; OS << getOptionName(NegOption); + OS << ")\n"; + OS << "#endif // " << MacroNameParsing << "_BOOLEAN\n"; + } + + void emitSerialiazing(raw_ostream &OS, + llvm::function_ref + WriteOptRecordFields) const override { + OS << "#ifdef " << MacroNameSerializing << "_BOOLEAN\n"; + OS << MacroNameSerializing << "_BOOLEAN("; + WriteOptRecordFields(OS, R); + OS << ", "; + emitSerializingFields(OS); OS << ", "; write_cstring(OS, getOptionSpelling(NegOption)); + OS << ")\n"; + OS << "#endif // " << MacroNameSerializing << "_BOOLEAN\n"; } }; static MarshallingInfo::Ptr createMarshallingInfo(const Record &R) { assert(!isa(R.getValueInit("KeyPath")) && !isa(R.getValueInit("DefaultValue")) && - !isa(R.getValueInit("ValueMerger")) && + !isa(R.getValueInit("Denormalizer")) && "MarshallingInfo must have a provide a keypath, default value and a " - "value merger"); + "denormalizer"); MarshallingInfo::Ptr Ret; if (Record *MaybeNegOption = R.getValueAsOptionalDef("NegOption")) { @@ -183,10 +241,14 @@ Ret->ShouldAlwaysEmit = R.getValueAsBit("ShouldAlwaysEmit"); Ret->KeyPath = R.getValueAsString("KeyPath"); Ret->DefaultValue = R.getValueAsString("DefaultValue"); - Ret->NormalizedValuesScope = R.getValueAsString("NormalizedValuesScope"); - - Ret->Normalizer = R.getValueAsString("Normalizer"); Ret->Denormalizer = R.getValueAsString("Denormalizer"); + + Ret->CanParse = false; + if (!isa(R.getValueInit("Normalizer"))) { + Ret->Normalizer = R.getValueAsString("Normalizer"); + Ret->CanParse = true; + } + Ret->NormalizedValuesScope = R.getValueAsString("NormalizedValuesScope"); Ret->ValueMerger = R.getValueAsString("ValueMerger"); Ret->ValueExtractor = R.getValueAsString("ValueExtractor"); @@ -421,13 +483,8 @@ OS << "#endif // OPTION\n"; for (const auto &KindInfo : OptsWithMarshalling) { - OS << "#ifdef " << KindInfo->MacroName << "\n"; - OS << KindInfo->MacroName << "("; - WriteOptRecordFields(OS, KindInfo->R); - OS << ", "; - KindInfo->emit(OS); - OS << ")\n"; - OS << "#endif // " << KindInfo->MacroName << "\n"; + KindInfo->emitParsing(OS, WriteOptRecordFields); + KindInfo->emitSerialiazing(OS, WriteOptRecordFields); } OS << "\n";