From 39a2a233f88443e865758ba73c156787c77ead2c Mon Sep 17 00:00:00 2001 From: Jan Svoboda Date: Fri, 15 Jan 2021 17:55:03 +0100 Subject: [PATCH] [clang][cli] Parse Lang and CodeGen options separately This patch moves the parsing of `{Lang,CodeGen}Options` from `parseSimpleArgs` to the original `Parse{Lang,CodeGen}Args` functions. This ensures all marshalled `LangOptions` are being parsed **after** the call `setLangDefaults`, which in turn enables us to marshall `LangOptions` that somehow depend on the defaults. (In a future patch.) Now, `CodeGenOptions` need to be parsed **after** `LangOptions`, because `-cl-mad-enable` (a `CodeGenOpt`) depends on the value of `-cl-fast-relaxed-math` and `-cl-unsafe-math-optimizations` (`LangOpts`). Unfortunately, this removes the nice property that marshalled options get parsed in the exact order they appear in the `.td` file. Now we cannot be sure that a TableGen record referenced in `ImpliedByAnyOf` has already been parsed. This might cause an ordering issues (i.e. reading value of uninitialized variable). I plan to mitigate this by moving each `XxxOpt` group from `parseSimpleArgs` back to their original parsing function. With this setup, if an option from group `A` references option from group `B` in TableGen, the compiler will require us to make the `CompilerInvocation` member for `B` visible in the parsing function for `A`. That's where we notice that `B` didn't get parsed yet. Reviewed By: Bigcheese Differential Revision: https://reviews.llvm.org/D94682 --- clang/include/clang/Driver/Options.td | 17 +++-- clang/include/clang/Frontend/CompilerInvocation.h | 3 +- clang/lib/Frontend/CompilerInvocation.cpp | 81 +++++++++++++++++------ clang/test/Frontend/diagnostics-order.c | 2 +- 4 files changed, 75 insertions(+), 28 deletions(-) diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 3722192..e50c313 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -244,7 +244,7 @@ def clang_ignored_gcc_optimization_f_Group : OptionGroup< class DiagnosticOpts : KeyPathAndMacro<"DiagnosticOpts->", base, "DIAG_"> {} class LangOpts - : KeyPathAndMacro<"LangOpts->", base> {} + : KeyPathAndMacro<"LangOpts->", base, "LANG_"> {} class TargetOpts : KeyPathAndMacro<"TargetOpts->", base> {} class FrontendOpts @@ -254,7 +254,7 @@ class PreprocessorOutputOpts class DependencyOutputOpts : KeyPathAndMacro<"DependencyOutputOpts.", base> {} class CodeGenOpts - : KeyPathAndMacro<"CodeGenOpts.", base> {} + : KeyPathAndMacro<"CodeGenOpts.", base, "CODEGEN_"> {} class HeaderSearchOpts : KeyPathAndMacro<"HeaderSearchOpts->", base> {} class PreprocessorOpts @@ -510,6 +510,9 @@ multiclass BoolGOption; } +// Key paths that are constant during parsing of options with the same key path prefix. +defvar open_cl = LangOpts<"OpenCL">; + ///////// // Options @@ -1820,9 +1823,13 @@ defm experimental_relative_cxx_abi_vtables : BoolFOption<"experimental-relative- def flat__namespace : Flag<["-"], "flat_namespace">; def flax_vector_conversions_EQ : Joined<["-"], "flax-vector-conversions=">, Group, HelpText<"Enable implicit vector bit-casts">, Values<"none,integer,all">, Flags<[CC1Option]>, - NormalizedValuesScope<"LangOptions::LaxVectorConversionKind">, - NormalizedValues<["None", "Integer", "All"]>, - MarshallingInfoString, "All">, AutoNormalizeEnum; + NormalizedValues<["LangOptions::LaxVectorConversionKind::None", + "LangOptions::LaxVectorConversionKind::Integer", + "LangOptions::LaxVectorConversionKind::All"]>, + MarshallingInfoString, + !strconcat(open_cl.KeyPath, " ? LangOptions::LaxVectorConversionKind::None" + " : LangOptions::LaxVectorConversionKind::All")>, + AutoNormalizeEnum; def flax_vector_conversions : Flag<["-"], "flax-vector-conversions">, Group, Alias, AliasArgs<["integer"]>; def flimited_precision_EQ : Joined<["-"], "flimited-precision=">, Group; diff --git a/clang/include/clang/Frontend/CompilerInvocation.h b/clang/include/clang/Frontend/CompilerInvocation.h index b65b087..0d83a22 100644 --- a/clang/include/clang/Frontend/CompilerInvocation.h +++ b/clang/include/clang/Frontend/CompilerInvocation.h @@ -258,7 +258,8 @@ private: static bool ParseCodeGenArgs(CodeGenOptions &Opts, llvm::opt::ArgList &Args, InputKind IK, DiagnosticsEngine &Diags, const llvm::Triple &T, - const std::string &OutputFile); + const std::string &OutputFile, + const LangOptions &LangOptsRef); }; IntrusiveRefCntPtr diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 25b3610..dac0dc6 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -385,6 +385,21 @@ static T extractMaskValue(T KeyPath) { return KeyPath & Value; } +#define PARSE_OPTION_WITH_MARSHALLING(ARGS, DIAGS, SUCCESS, ID, FLAGS, PARAM, \ + SHOULD_PARSE, KEYPATH, DEFAULT_VALUE, \ + IMPLIED_CHECK, IMPLIED_VALUE, \ + NORMALIZER, MERGER, TABLE_INDEX) \ + if ((FLAGS)&options::CC1Option) { \ + KEYPATH = MERGER(KEYPATH, DEFAULT_VALUE); \ + if (IMPLIED_CHECK) \ + KEYPATH = MERGER(KEYPATH, IMPLIED_VALUE); \ + if (SHOULD_PARSE) \ + if (auto MaybeValue = \ + NORMALIZER(OPT_##ID, TABLE_INDEX, ARGS, DIAGS, SUCCESS)) \ + KEYPATH = \ + MERGER(KEYPATH, static_cast(*MaybeValue)); \ + } + static void FixupInvocation(CompilerInvocation &Invocation, DiagnosticsEngine &Diags, const InputArgList &Args) { @@ -911,7 +926,8 @@ bool CompilerInvocation::ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, DiagnosticsEngine &Diags, const llvm::Triple &T, - const std::string &OutputFile) { + const std::string &OutputFile, + const LangOptions &LangOptsRef) { bool Success = true; unsigned OptimizationLevel = getOptimizationLevel(Args, IK, Diags); @@ -926,6 +942,25 @@ bool CompilerInvocation::ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, } Opts.OptimizationLevel = OptimizationLevel; + // The key paths of codegen options defined in Options.td start with + // "CodeGenOpts.". Let's provide the expected variable name and type. + CodeGenOptions &CodeGenOpts = Opts; + // Some codegen options depend on language options. Let's provide the expected + // variable name and type. + const LangOptions *LangOpts = &LangOptsRef; + +#define CODEGEN_OPTION_WITH_MARSHALLING( \ + PREFIX_TYPE, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \ + HELPTEXT, METAVAR, VALUES, SPELLING, SHOULD_PARSE, ALWAYS_EMIT, KEYPATH, \ + DEFAULT_VALUE, IMPLIED_CHECK, IMPLIED_VALUE, NORMALIZER, DENORMALIZER, \ + MERGER, EXTRACTOR, TABLE_INDEX) \ + PARSE_OPTION_WITH_MARSHALLING(Args, Diags, Success, ID, FLAGS, PARAM, \ + SHOULD_PARSE, KEYPATH, DEFAULT_VALUE, \ + IMPLIED_CHECK, IMPLIED_VALUE, NORMALIZER, \ + MERGER, TABLE_INDEX) +#include "clang/Driver/Options.inc" +#undef CODEGEN_OPTION_WITH_MARSHALLING + // At O0 we want to fully disable inlining outside of cases marked with // 'alwaysinline' that are required for correctness. Opts.setInlining((Opts.OptimizationLevel == 0) @@ -1367,21 +1402,6 @@ static bool checkVerifyPrefixes(const std::vector &VerifyPrefixes, return Success; } -#define PARSE_OPTION_WITH_MARSHALLING(ARGS, DIAGS, SUCCESS, ID, FLAGS, PARAM, \ - SHOULD_PARSE, KEYPATH, DEFAULT_VALUE, \ - IMPLIED_CHECK, IMPLIED_VALUE, \ - NORMALIZER, MERGER, TABLE_INDEX) \ - if ((FLAGS)&options::CC1Option) { \ - KEYPATH = MERGER(KEYPATH, DEFAULT_VALUE); \ - if (IMPLIED_CHECK) \ - KEYPATH = MERGER(KEYPATH, IMPLIED_VALUE); \ - if (SHOULD_PARSE) \ - if (auto MaybeValue = \ - NORMALIZER(OPT_##ID, TABLE_INDEX, ARGS, DIAGS, SUCCESS)) \ - KEYPATH = \ - MERGER(KEYPATH, static_cast(*MaybeValue)); \ - } - bool CompilerInvocation::parseSimpleArgs(const ArgList &Args, DiagnosticsEngine &Diags) { bool Success = true; @@ -1468,8 +1488,6 @@ bool clang::ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args, return Success; } -#undef PARSE_OPTION_WITH_MARSHALLING - /// Parse the argument to the -ftest-module-file-extension /// command-line argument. /// @@ -1997,7 +2015,6 @@ void CompilerInvocation::setLangDefaults(LangOptions &Opts, InputKind IK, if (Opts.OpenCL) { Opts.AltiVec = 0; Opts.ZVector = 0; - Opts.setLaxVectorConversions(LangOptions::LaxVectorConversionKind::None); Opts.setDefaultFPContractMode(LangOptions::FPM_On); Opts.NativeHalfType = 1; Opts.NativeHalfArgsAndReturns = 1; @@ -2226,6 +2243,23 @@ void CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args, CompilerInvocation::setLangDefaults(Opts, IK, T, Includes, LangStd); + // The key paths of codegen options defined in Options.td start with + // "LangOpts->". Let's provide the expected variable name and type. + LangOptions *LangOpts = &Opts; + bool Success = true; + +#define LANG_OPTION_WITH_MARSHALLING( \ + PREFIX_TYPE, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \ + HELPTEXT, METAVAR, VALUES, SPELLING, SHOULD_PARSE, ALWAYS_EMIT, KEYPATH, \ + DEFAULT_VALUE, IMPLIED_CHECK, IMPLIED_VALUE, NORMALIZER, DENORMALIZER, \ + MERGER, EXTRACTOR, TABLE_INDEX) \ + PARSE_OPTION_WITH_MARSHALLING(Args, Diags, Success, ID, FLAGS, PARAM, \ + SHOULD_PARSE, KEYPATH, DEFAULT_VALUE, \ + IMPLIED_CHECK, IMPLIED_VALUE, NORMALIZER, \ + MERGER, TABLE_INDEX) +#include "clang/Driver/Options.inc" +#undef LANG_OPTION_WITH_MARSHALLING + if (const Arg *A = Args.getLastArg(OPT_fcf_protection_EQ)) { StringRef Name = A->getValue(); if (Name == "full" || Name == "branch") { @@ -2959,8 +2993,6 @@ bool CompilerInvocation::CreateFromArgs(CompilerInvocation &Res, LangOpts.IsHeaderFile); ParseTargetArgs(Res.getTargetOpts(), Args, Diags); llvm::Triple T(Res.getTargetOpts().Triple); - Success &= ParseCodeGenArgs(Res.getCodeGenOpts(), Args, DashX, Diags, T, - Res.getFrontendOpts().OutputFile); ParseHeaderSearchArgs(Res.getHeaderSearchOpts(), Args, Res.getFileSystemOpts().WorkingDir); if (DashX.getFormat() == InputKind::Precompiled || @@ -3002,6 +3034,9 @@ bool CompilerInvocation::CreateFromArgs(CompilerInvocation &Res, if (LangOpts.OpenMPIsDevice) Res.getTargetOpts().HostTriple = Res.getFrontendOpts().AuxTriple; + Success &= ParseCodeGenArgs(Res.getCodeGenOpts(), Args, DashX, Diags, T, + Res.getFrontendOpts().OutputFile, LangOpts); + // FIXME: Override value name discarding when asan or msan is used because the // backend passes depend on the name of the alloca in order to print out // names. @@ -3179,9 +3214,13 @@ void CompilerInvocation::generateCC1CommandLine( EXTRACTOR, TABLE_INDEX) #define DIAG_OPTION_WITH_MARSHALLING OPTION_WITH_MARSHALLING +#define LANG_OPTION_WITH_MARSHALLING OPTION_WITH_MARSHALLING +#define CODEGEN_OPTION_WITH_MARSHALLING OPTION_WITH_MARSHALLING #include "clang/Driver/Options.inc" +#undef CODEGEN_OPTION_WITH_MARSHALLING +#undef LANG_OPTION_WITH_MARSHALLING #undef DIAG_OPTION_WITH_MARSHALLING #undef OPTION_WITH_MARSHALLING #undef GENERATE_OPTION_WITH_MARSHALLING diff --git a/clang/test/Frontend/diagnostics-order.c b/clang/test/Frontend/diagnostics-order.c index 37c0cd9..bd0aa71 100644 --- a/clang/test/Frontend/diagnostics-order.c +++ b/clang/test/Frontend/diagnostics-order.c @@ -7,6 +7,6 @@ // // CHECK: error: invalid value '-foo' in '-verify=' // CHECK-NEXT: note: -verify prefixes must start with a letter and contain only alphanumeric characters, hyphens, and underscores -// CHECK-NEXT: warning: optimization level '-O999' is not supported // CHECK-NEXT: error: invalid value 'bogus' in '-std=bogus' // CHECK-NEXT: note: use {{.*}} for {{.*}} standard +// CHECK: warning: optimization level '-O999' is not supported -- 2.7.4