[llvm] e721bc9 - [clang][cli] Generate and round-trip CodeGen options

Jan Svoboda via llvm-commits llvm-commits at lists.llvm.org
Tue Feb 9 02:43:49 PST 2021


Author: Jan Svoboda
Date: 2021-02-09T11:43:38+01:00
New Revision: e721bc9effefab8a625e913e7391bdd340693ddc

URL: https://github.com/llvm/llvm-project/commit/e721bc9effefab8a625e913e7391bdd340693ddc
DIFF: https://github.com/llvm/llvm-project/commit/e721bc9effefab8a625e913e7391bdd340693ddc.diff

LOG: [clang][cli] Generate and round-trip CodeGen options

This patch implements generation of remaining codegen options and tests it by performing parse-generate-parse round trip.

Reviewed By: dexonsmith

Differential Revision: https://reviews.llvm.org/D96056

Added: 
    

Modified: 
    clang/include/clang/Basic/XRayInstr.h
    clang/include/clang/Driver/Options.td
    clang/include/clang/Frontend/CompilerInvocation.h
    clang/lib/Basic/XRayInstr.cpp
    clang/lib/Frontend/CompilerInvocation.cpp
    llvm/include/llvm/Option/OptParser.td

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Basic/XRayInstr.h b/clang/include/clang/Basic/XRayInstr.h
index 42ca7773fcceb..23ca2c75fc997 100644
--- a/clang/include/clang/Basic/XRayInstr.h
+++ b/clang/include/clang/Basic/XRayInstr.h
@@ -65,8 +65,13 @@ struct XRayInstrSet {
   XRayInstrMask Mask = 0;
 };
 
+/// Parses a command line argument into a mask.
 XRayInstrMask parseXRayInstrValue(StringRef Value);
 
+/// Serializes a set into a list of command line arguments.
+void serializeXRayInstrValue(XRayInstrSet Set,
+                             SmallVectorImpl<StringRef> &Values);
+
 } // namespace clang
 
 #endif // LLVM_CLANG_BASIC_XRAYINSTR_H

diff  --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index baea96df5829b..544f5771861ab 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -4453,12 +4453,7 @@ def migrator_no_finalize_removal : Flag<["-"], "no-finalize-removal">,
 //===----------------------------------------------------------------------===//
 
 let Flags = [CC1Option, CC1AsOption, NoDriverOption] in {
-def debug_info_kind_EQ : Joined<["-"], "debug-info-kind=">,
-  Values<"line-tables-only,line-directives-only,constructor,limited,standalone,unused-types">,
-  NormalizedValuesScope<"codegenoptions">,
-  NormalizedValues<["DebugLineTablesOnly", "DebugDirectivesOnly", "DebugInfoConstructor",
-                    "LimitedDebugInfo", "FullDebugInfo", "UnusedTypeInfo"]>,
-  MarshallingInfoString<CodeGenOpts<"DebugInfo">, "NoDebugInfo">, AutoNormalizeEnum;
+def debug_info_kind_EQ : Joined<["-"], "debug-info-kind=">;
 def debug_info_macro : Flag<["-"], "debug-info-macro">,
   HelpText<"Emit macro debug information">,
   MarshallingInfoFlag<CodeGenOpts<"MacroDebugInfo">>;

diff  --git a/clang/include/clang/Frontend/CompilerInvocation.h b/clang/include/clang/Frontend/CompilerInvocation.h
index 0b53c867cd98d..8cd512cbfd89e 100644
--- a/clang/include/clang/Frontend/CompilerInvocation.h
+++ b/clang/include/clang/Frontend/CompilerInvocation.h
@@ -266,12 +266,26 @@ class CompilerInvocation : public CompilerInvocationBase {
                                StringAllocator SA, const llvm::Triple &T);
 
   /// Parse command line options that map to CodeGenOptions.
-  static bool ParseCodeGenArgs(CodeGenOptions &Opts, llvm::opt::ArgList &Args,
-                               InputKind IK, DiagnosticsEngine &Diags,
-                               const llvm::Triple &T,
+  static bool ParseCodeGenArgsImpl(CodeGenOptions &Opts,
+                                   llvm::opt::ArgList &Args, InputKind IK,
+                                   DiagnosticsEngine &Diags,
+                                   const llvm::Triple &T,
+                                   const std::string &OutputFile,
+                                   const LangOptions &LangOptsRef);
+
+  static bool ParseCodeGenArgs(CompilerInvocation &Res, CodeGenOptions &Opts,
+                               llvm::opt::ArgList &Args, InputKind IK,
+                               DiagnosticsEngine &Diags, const llvm::Triple &T,
                                const std::string &OutputFile,
                                const LangOptions &LangOptsRef);
 
+  // Generate command line options from CodeGenOptions.
+  static void GenerateCodeGenArgs(const CodeGenOptions &Opts,
+                                  SmallVectorImpl<const char *> &Args,
+                                  StringAllocator SA, const llvm::Triple &T,
+                                  const std::string &OutputFile,
+                                  const LangOptions *LangOpts);
+
   /// Parse command line options that map to HeaderSearchOptions.
   static void ParseHeaderSearchArgs(CompilerInvocation &Res,
                                     HeaderSearchOptions &Opts,

diff  --git a/clang/lib/Basic/XRayInstr.cpp b/clang/lib/Basic/XRayInstr.cpp
index 79052e05860ea..822e14bbb622d 100644
--- a/clang/lib/Basic/XRayInstr.cpp
+++ b/clang/lib/Basic/XRayInstr.cpp
@@ -11,6 +11,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "clang/Basic/XRayInstr.h"
+#include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/StringSwitch.h"
 
 namespace clang {
@@ -30,4 +31,30 @@ XRayInstrMask parseXRayInstrValue(StringRef Value) {
   return ParsedKind;
 }
 
+void serializeXRayInstrValue(XRayInstrSet Set,
+                             SmallVectorImpl<StringRef> &Values) {
+  if (Set.Mask == XRayInstrKind::All) {
+    Values.push_back("all");
+    return;
+  }
+
+  if (Set.Mask == XRayInstrKind::None) {
+    Values.push_back("none");
+    return;
+  }
+
+  if (Set.has(XRayInstrKind::Custom))
+    Values.push_back("custom");
+
+  if (Set.has(XRayInstrKind::Typed))
+    Values.push_back("typed");
+
+  if (Set.has(XRayInstrKind::FunctionEntry) &&
+      Set.has(XRayInstrKind::FunctionExit))
+    Values.push_back("function");
+  else if (Set.has(XRayInstrKind::FunctionEntry))
+    Values.push_back("function-entry");
+  else if (Set.has(XRayInstrKind::FunctionExit))
+    Values.push_back("function-exit");
+}
 } // namespace clang

diff  --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp
index 658dad54532ea..020cbf0f176ec 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -54,6 +54,7 @@
 #include "llvm/ADT/Hashing.h"
 #include "llvm/ADT/None.h"
 #include "llvm/ADT/Optional.h"
+#include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/StringRef.h"
@@ -625,14 +626,17 @@ static bool RoundTrip(ParseFn Parse, GenerateFn Generate, SwapOptsFn SwapOpts,
   // Run the first parse on the original arguments with dummy options and
   // diagnostics.
   SwapOpts(Res);
-  if (!Parse(Res, OriginalArgs, DummyDiags)) {
+  if (!Parse(Res, OriginalArgs, DummyDiags) ||
+      DummyDiags.getNumWarnings() != 0) {
     // If the first parse did not succeed, it must be user mistake (invalid
     // command line arguments). We won't be able to generate arguments that
     // would reproduce the same result. Let's fail again with the original
     // options and diagnostics, so all side-effects of parsing are visible.
+    unsigned NumWarningsBefore = Diags.getNumWarnings();
     SwapOpts(Res);
-    if (!Parse(Res, OriginalArgs, Diags))
-      return false;
+    auto Success = Parse(Res, OriginalArgs, Diags);
+    if (!Success || Diags.getNumWarnings() != NumWarningsBefore)
+      return Success;
 
     // Parse with original options and diagnostics succeeded even though it
     // shouldn't have. Something is off.
@@ -749,16 +753,11 @@ static void parseAnalyzerConfigs(AnalyzerOptions &AnOpts,
 
 static void getAllNoBuiltinFuncValues(ArgList &Args,
                                       std::vector<std::string> &Funcs) {
-  SmallVector<const char *, 8> Values;
-  for (const auto &Arg : Args) {
-    const Option &O = Arg->getOption();
-    if (O.matches(options::OPT_fno_builtin_)) {
-      const char *FuncName = Arg->getValue();
-      if (Builtin::Context::isBuiltinFunc(FuncName))
-        Values.push_back(FuncName);
-    }
-  }
-  Funcs.insert(Funcs.end(), Values.begin(), Values.end());
+  std::vector<std::string> Values = Args.getAllArgValues(OPT_fno_builtin_);
+  auto BuiltinEnd = llvm::partition(Values, [](const std::string FuncName) {
+    return Builtin::Context::isBuiltinFunc(FuncName);
+  });
+  Funcs.insert(Funcs.end(), Values.begin(), BuiltinEnd);
 }
 
 static void GenerateAnalyzerArgs(AnalyzerOptions &Opts,
@@ -1238,6 +1237,15 @@ static void parseXRayInstrumentationBundle(StringRef FlagName, StringRef Bundle,
   }
 }
 
+static std::string serializeXRayInstrumentationBundle(const XRayInstrSet &S) {
+  llvm::SmallVector<StringRef, 2> BundleParts;
+  serializeXRayInstrValue(S, BundleParts);
+  std::string Buffer;
+  llvm::raw_string_ostream OS(Buffer);
+  llvm::interleave(BundleParts, OS, [&OS](StringRef Part) { OS << Part; }, ",");
+  return OS.str();
+}
+
 // Set the profile kind using fprofile-instrument-use-path.
 static void setPGOUseInstrumentor(CodeGenOptions &Opts,
                                   const Twine &ProfileName) {
@@ -1259,12 +1267,258 @@ static void setPGOUseInstrumentor(CodeGenOptions &Opts,
     Opts.setProfileUse(CodeGenOptions::ProfileClangInstr);
 }
 
-bool CompilerInvocation::ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args,
-                                          InputKind IK,
-                                          DiagnosticsEngine &Diags,
-                                          const llvm::Triple &T,
-                                          const std::string &OutputFile,
-                                          const LangOptions &LangOptsRef) {
+void CompilerInvocation::GenerateCodeGenArgs(
+    const CodeGenOptions &Opts, SmallVectorImpl<const char *> &Args,
+    StringAllocator SA, const llvm::Triple &T, const std::string &OutputFile,
+    const LangOptions *LangOpts) {
+  const CodeGenOptions &CodeGenOpts = Opts;
+
+  if (Opts.OptimizationLevel == 0)
+    GenerateArg(Args, OPT_O0, SA);
+  else
+    GenerateArg(Args, OPT_O, Twine(Opts.OptimizationLevel), SA);
+
+#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)                                            \
+  GENERATE_OPTION_WITH_MARSHALLING(                                            \
+      Args, SA, KIND, FLAGS, SPELLING, ALWAYS_EMIT, KEYPATH, DEFAULT_VALUE,    \
+      IMPLIED_CHECK, IMPLIED_VALUE, DENORMALIZER, EXTRACTOR, TABLE_INDEX)
+#include "clang/Driver/Options.inc"
+#undef CODEGEN_OPTION_WITH_MARSHALLING
+
+  if (Opts.OptimizationLevel > 0) {
+    if (Opts.Inlining == CodeGenOptions::NormalInlining)
+      GenerateArg(Args, OPT_finline_functions, SA);
+    else if (Opts.Inlining == CodeGenOptions::OnlyHintInlining)
+      GenerateArg(Args, OPT_finline_hint_functions, SA);
+    else if (Opts.Inlining == CodeGenOptions::OnlyAlwaysInlining)
+      GenerateArg(Args, OPT_fno_inline, SA);
+  }
+
+  if (Opts.DirectAccessExternalData && LangOpts->PICLevel != 0)
+    GenerateArg(Args, OPT_fdirect_access_external_data, SA);
+  else if (!Opts.DirectAccessExternalData && LangOpts->PICLevel == 0)
+    GenerateArg(Args, OPT_fno_direct_access_external_data, SA);
+
+  Optional<StringRef> DebugInfoVal;
+  switch (Opts.DebugInfo) {
+  case codegenoptions::DebugLineTablesOnly:
+    DebugInfoVal = "line-tables-only";
+    break;
+  case codegenoptions::DebugDirectivesOnly:
+    DebugInfoVal = "line-directives-only";
+    break;
+  case codegenoptions::DebugInfoConstructor:
+    DebugInfoVal = "constructor";
+    break;
+  case codegenoptions::LimitedDebugInfo:
+    DebugInfoVal = "limited";
+    break;
+  case codegenoptions::FullDebugInfo:
+    DebugInfoVal = "standalone";
+    break;
+  case codegenoptions::UnusedTypeInfo:
+    DebugInfoVal = "unused-types";
+    break;
+  case codegenoptions::NoDebugInfo: // default value
+    DebugInfoVal = None;
+    break;
+  case codegenoptions::LocTrackingOnly: // implied value
+    DebugInfoVal = None;
+    break;
+  }
+  if (DebugInfoVal)
+    GenerateArg(Args, OPT_debug_info_kind_EQ, *DebugInfoVal, SA);
+
+  if (Opts.DebugInfo == codegenoptions::DebugInfoConstructor)
+    GenerateArg(Args, OPT_fuse_ctor_homing, SA);
+
+  for (const auto &Prefix : Opts.DebugPrefixMap)
+    GenerateArg(Args, OPT_fdebug_prefix_map_EQ,
+                Prefix.first + "=" + Prefix.second, SA);
+
+  for (const auto &Prefix : Opts.ProfilePrefixMap)
+    GenerateArg(Args, OPT_fprofile_prefix_map_EQ,
+                Prefix.first + "=" + Prefix.second, SA);
+
+  if (Opts.NewStructPathTBAA)
+    GenerateArg(Args, OPT_new_struct_path_tbaa, SA);
+
+  if (Opts.OptimizeSize == 1)
+    GenerateArg(Args, OPT_O, "s", SA);
+  else if (Opts.OptimizeSize == 2)
+    GenerateArg(Args, OPT_O, "z", SA);
+
+  // SimplifyLibCalls is set only in the absence of -fno-builtin and
+  // -ffreestanding. We'll consider that when generating them.
+
+  // NoBuiltinFuncs are generated by LangOptions.
+
+  if (Opts.UnrollLoops && Opts.OptimizationLevel <= 1)
+    GenerateArg(Args, OPT_funroll_loops, SA);
+  else if (!Opts.UnrollLoops && Opts.OptimizationLevel > 1)
+    GenerateArg(Args, OPT_fno_unroll_loops, SA);
+
+  if (!Opts.BinutilsVersion.empty())
+    GenerateArg(Args, OPT_fbinutils_version_EQ, Opts.BinutilsVersion, SA);
+
+  if (Opts.DebugNameTable ==
+      static_cast<unsigned>(llvm::DICompileUnit::DebugNameTableKind::GNU))
+    GenerateArg(Args, OPT_ggnu_pubnames, SA);
+  else if (Opts.DebugNameTable ==
+           static_cast<unsigned>(
+               llvm::DICompileUnit::DebugNameTableKind::Default))
+    GenerateArg(Args, OPT_gpubnames, SA);
+
+  // ProfileInstrumentUsePath is marshalled automatically, no need to generate
+  // it or PGOUseInstrumentor.
+
+  if (Opts.TimePasses) {
+    if (Opts.TimePassesPerRun)
+      GenerateArg(Args, OPT_ftime_report_EQ, "per-pass-run", SA);
+    else
+      GenerateArg(Args, OPT_ftime_report, SA);
+  }
+
+  if (Opts.FunctionSections &&
+      (Opts.BBSections == "none" || Opts.BBSections == "labels"))
+    GenerateArg(Args, OPT_ffunction_sections, SA);
+
+  if (Opts.PrepareForLTO && !Opts.PrepareForThinLTO)
+    GenerateArg(Args, OPT_flto, SA);
+
+  if (Opts.PrepareForThinLTO)
+    GenerateArg(Args, OPT_flto_EQ, "thin", SA);
+
+  if (!Opts.ThinLTOIndexFile.empty())
+    GenerateArg(Args, OPT_fthinlto_index_EQ, Opts.ThinLTOIndexFile, SA);
+
+  if (Opts.SaveTempsFilePrefix == OutputFile)
+    GenerateArg(Args, OPT_save_temps_EQ, "obj", SA);
+
+  StringRef MemProfileBasename("memprof.profraw");
+  if (!Opts.MemoryProfileOutput.empty()) {
+    if (Opts.MemoryProfileOutput == MemProfileBasename) {
+      GenerateArg(Args, OPT_fmemory_profile, SA);
+    } else {
+      size_t ArgLength =
+          Opts.MemoryProfileOutput.size() - MemProfileBasename.size();
+      GenerateArg(Args, OPT_fmemory_profile_EQ,
+                  Opts.MemoryProfileOutput.substr(0, ArgLength), SA);
+    }
+  }
+
+  if (memcmp(Opts.CoverageVersion, "408*", 4) != 0)
+    GenerateArg(Args, OPT_coverage_version_EQ, Opts.CoverageVersion, SA);
+
+  // TODO: Check if we need to generate arguments stored in CmdArgs. (Namely
+  //  '-fembed_bitcode', which does not map to any CompilerInvocation field and
+  //  won't be generated.)
+
+  if (Opts.XRayInstrumentationBundle.Mask != XRayInstrKind::All) {
+    std::string InstrBundle =
+        serializeXRayInstrumentationBundle(Opts.XRayInstrumentationBundle);
+    if (!InstrBundle.empty())
+      GenerateArg(Args, OPT_fxray_instrumentation_bundle, InstrBundle, SA);
+  }
+
+  if (Opts.CFProtectionReturn && Opts.CFProtectionBranch)
+    GenerateArg(Args, OPT_fcf_protection_EQ, "full", SA);
+  else if (Opts.CFProtectionReturn)
+    GenerateArg(Args, OPT_fcf_protection_EQ, "return", SA);
+  else if (Opts.CFProtectionBranch)
+    GenerateArg(Args, OPT_fcf_protection_EQ, "branch", SA);
+
+  for (const auto &F : Opts.LinkBitcodeFiles) {
+    bool Builtint = F.LinkFlags == llvm::Linker::Flags::LinkOnlyNeeded &&
+                    F.PropagateAttrs && F.Internalize;
+    GenerateArg(Args,
+                Builtint ? OPT_mlink_builtin_bitcode : OPT_mlink_bitcode_file,
+                F.Filename, SA);
+  }
+
+  // TODO: Consider removing marshalling annotations from f[no_]emulated_tls.
+  //  That would make it easy to generate the option only **once** if it was
+  //  explicitly set to non-default value.
+  if (Opts.ExplicitEmulatedTLS) {
+    GenerateArg(
+        Args, Opts.EmulatedTLS ? OPT_femulated_tls : OPT_fno_emulated_tls, SA);
+  }
+
+  if (Opts.FPDenormalMode != llvm::DenormalMode::getIEEE()) {
+    std::string Buffer;
+    llvm::raw_string_ostream OS(Buffer);
+    Opts.FPDenormalMode.print(OS);
+    GenerateArg(Args, OPT_fdenormal_fp_math_EQ, OS.str(), SA);
+  }
+
+  if (Opts.FP32DenormalMode != llvm::DenormalMode::getIEEE()) {
+    std::string Buffer;
+    llvm::raw_string_ostream OS(Buffer);
+    Opts.FP32DenormalMode.print(OS);
+    GenerateArg(Args, OPT_fdenormal_fp_math_f32_EQ, OS.str(), SA);
+  }
+
+  if (Opts.StructReturnConvention == CodeGenOptions::SRCK_OnStack) {
+    OptSpecifier Opt =
+        T.isPPC32() ? OPT_maix_struct_return : OPT_fpcc_struct_return;
+    GenerateArg(Args, Opt, SA);
+  } else if (Opts.StructReturnConvention == CodeGenOptions::SRCK_InRegs) {
+    OptSpecifier Opt =
+        T.isPPC32() ? OPT_msvr4_struct_return : OPT_freg_struct_return;
+    GenerateArg(Args, Opt, SA);
+  }
+
+  if (Opts.IgnoreXCOFFVisibility)
+    GenerateArg(Args, OPT_mignore_xcoff_visibility, SA);
+
+  if (Opts.EnableAIXExtendedAltivecABI)
+    GenerateArg(Args, OPT_mabi_EQ_vec_extabi, SA);
+
+  if (!Opts.OptRecordPasses.empty())
+    GenerateArg(Args, OPT_opt_record_passes, Opts.OptRecordPasses, SA);
+
+  if (!Opts.OptRecordFormat.empty())
+    GenerateArg(Args, OPT_opt_record_format, Opts.OptRecordFormat, SA);
+
+  if (Opts.OptimizationRemarkPattern)
+    GenerateArg(Args, OPT_Rpass_EQ, Opts.OptimizationRemarkPattern.Pattern, SA);
+
+  if (Opts.OptimizationRemarkMissedPattern)
+    GenerateArg(Args, OPT_Rpass_missed_EQ,
+                Opts.OptimizationRemarkMissedPattern.Pattern, SA);
+
+  if (Opts.OptimizationRemarkAnalysisPattern)
+    GenerateArg(Args, OPT_Rpass_analysis_EQ,
+                Opts.OptimizationRemarkAnalysisPattern.Pattern, SA);
+
+  GenerateArg(Args, OPT_fdiagnostics_hotness_threshold_EQ,
+              Opts.DiagnosticsHotnessThreshold
+                  ? Twine(*Opts.DiagnosticsHotnessThreshold)
+                  : "auto",
+              SA);
+
+  for (StringRef Sanitizer : serializeSanitizerKinds(Opts.SanitizeRecover))
+    GenerateArg(Args, OPT_fsanitize_recover_EQ, Sanitizer, SA);
+
+  for (StringRef Sanitizer : serializeSanitizerKinds(Opts.SanitizeTrap))
+    GenerateArg(Args, OPT_fsanitize_trap_EQ, Sanitizer, SA);
+
+  if (!Opts.EmitVersionIdentMetadata)
+    GenerateArg(Args, OPT_Qn, SA);
+}
+
+bool CompilerInvocation::ParseCodeGenArgsImpl(CodeGenOptions &Opts,
+                                              ArgList &Args, InputKind IK,
+                                              DiagnosticsEngine &Diags,
+                                              const llvm::Triple &T,
+                                              const std::string &OutputFile,
+                                              const LangOptions &LangOptsRef) {
+  unsigned NumErrorsBefore = Diags.getNumErrors();
+
   bool Success = true;
 
   unsigned OptimizationLevel = getOptimizationLevel(Args, IK, Diags);
@@ -1324,7 +1578,24 @@ bool CompilerInvocation::ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args,
   Opts.DirectAccessExternalData =
       Args.hasArg(OPT_fdirect_access_external_data) ||
       (!Args.hasArg(OPT_fno_direct_access_external_data) &&
-       getLastArgIntValue(Args, OPT_pic_level, 0, Diags) == 0);
+       LangOpts->PICLevel == 0);
+
+  if (Arg *A = Args.getLastArg(OPT_debug_info_kind_EQ)) {
+    unsigned Val =
+        llvm::StringSwitch<unsigned>(A->getValue())
+            .Case("line-tables-only", codegenoptions::DebugLineTablesOnly)
+            .Case("line-directives-only", codegenoptions::DebugDirectivesOnly)
+            .Case("constructor", codegenoptions::DebugInfoConstructor)
+            .Case("limited", codegenoptions::LimitedDebugInfo)
+            .Case("standalone", codegenoptions::FullDebugInfo)
+            .Case("unused-types", codegenoptions::UnusedTypeInfo)
+            .Default(~0U);
+    if (Val == ~0U)
+      Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args)
+                                                << A->getValue();
+    else
+      Opts.setDebugInfo(static_cast<codegenoptions::DebugInfoKind>(Val));
+  }
 
   // If -fuse-ctor-homing is set and limited debug info is already on, then use
   // constructor homing.
@@ -1356,10 +1627,9 @@ bool CompilerInvocation::ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args,
   Opts.NewStructPathTBAA = !Args.hasArg(OPT_no_struct_path_tbaa) &&
                            Args.hasArg(OPT_new_struct_path_tbaa);
   Opts.OptimizeSize = getOptimizationLevelSize(Args);
-  Opts.SimplifyLibCalls = !(Args.hasArg(OPT_fno_builtin) ||
-                            Args.hasArg(OPT_ffreestanding));
+  Opts.SimplifyLibCalls = !LangOpts->NoBuiltin;
   if (Opts.SimplifyLibCalls)
-    getAllNoBuiltinFuncValues(Args, Opts.NoBuiltinFuncs);
+    Opts.NoBuiltinFuncs = LangOpts->NoBuiltinFuncs;
   Opts.UnrollLoops =
       Args.hasFlag(OPT_funroll_loops, OPT_fno_unroll_loops,
                    (Opts.OptimizationLevel > 1));
@@ -1434,6 +1704,7 @@ bool CompilerInvocation::ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args,
   } else if (Args.hasArg(OPT_fmemory_profile))
     Opts.MemoryProfileOutput = MemProfileBasename;
 
+  memcpy(Opts.CoverageVersion, "408*", 4);
   if (Opts.EmitGcovArcs || Opts.EmitGcovNotes) {
     if (Args.hasArg(OPT_coverage_version_EQ)) {
       StringRef CoverageVersion = Args.getLastArgValue(OPT_coverage_version_EQ);
@@ -1650,7 +1921,30 @@ bool CompilerInvocation::ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args,
 
   Opts.EmitVersionIdentMetadata = Args.hasFlag(OPT_Qy, OPT_Qn, true);
 
-  return Success;
+  return Success && Diags.getNumErrors() == NumErrorsBefore;
+}
+
+bool CompilerInvocation::ParseCodeGenArgs(
+    CompilerInvocation &Res, CodeGenOptions &Opts, ArgList &Args, InputKind IK,
+    DiagnosticsEngine &Diags, const llvm::Triple &T,
+    const std::string &OutputFile, const LangOptions &LangOptsRef) {
+  CodeGenOptions DummyOpts;
+
+  return RoundTrip(
+      [&](CompilerInvocation &Res, ArgList &Args, DiagnosticsEngine &Diags) {
+        Args.getLastArg(OPT_O0, OPT_O4, OPT_O, OPT_Ofast);
+        return ParseCodeGenArgsImpl(Res.getCodeGenOpts(), Args, IK, Diags, T,
+                                    OutputFile, LangOptsRef);
+      },
+      [&](CompilerInvocation &Res, SmallVectorImpl<const char *> &GeneratedArgs,
+          StringAllocator SA) {
+        GenerateCodeGenArgs(Res.getCodeGenOpts(), GeneratedArgs, SA, T,
+                            OutputFile, &LangOptsRef);
+      },
+      [&DummyOpts](CompilerInvocation &Res) {
+        std::swap(Res.CodeGenOpts, DummyOpts);
+      },
+      Res, Args, Diags, "CodeGenOptions");
 }
 
 static void ParseDependencyOutputArgs(DependencyOutputOptions &Opts,
@@ -2746,8 +3040,9 @@ void CompilerInvocation::GenerateLangArgs(const LangOptions &Opts,
   if (Opts.NoBuiltin && !Opts.Freestanding)
     GenerateArg(Args, OPT_fno_builtin, SA);
 
-  // Not generating '-fno-builtin-xxx'. It's handled for CodeGenOptions, that
-  // also read OPT_fno_builtin_.
+  if (!Opts.NoBuiltin)
+    for (const auto &Func : Opts.NoBuiltinFuncs)
+      GenerateArg(Args, OPT_fno_builtin_, Func, SA);
 
   if (Opts.LongDoubleSize == 128)
     GenerateArg(Args, OPT_mlong_double_128, SA);
@@ -3719,7 +4014,7 @@ bool CompilerInvocation::CreateFromArgs(CompilerInvocation &Res,
   if (LangOpts.OpenMPIsDevice)
     Res.getTargetOpts().HostTriple = Res.getFrontendOpts().AuxTriple;
 
-  Success &= ParseCodeGenArgs(Res.getCodeGenOpts(), Args, DashX, Diags, T,
+  Success &= ParseCodeGenArgs(Res, Res.getCodeGenOpts(), Args, DashX, Diags, T,
                               Res.getFrontendOpts().OutputFile, LangOpts);
 
   // FIXME: Override value name discarding when asan or msan is used because the
@@ -3883,11 +4178,9 @@ void CompilerInvocation::generateCC1CommandLine(
                                    EXTRACTOR, TABLE_INDEX)
 
 #define DIAG_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 DIAG_OPTION_WITH_MARSHALLING
 #undef OPTION_WITH_MARSHALLING
 
@@ -3896,6 +4189,8 @@ void CompilerInvocation::generateCC1CommandLine(
   GenerateAnalyzerArgs(*AnalyzerOpts, Args, SA);
   GenerateHeaderSearchArgs(*HeaderSearchOpts, Args, SA);
   GenerateLangArgs(*LangOpts, Args, SA, T);
+  GenerateCodeGenArgs(CodeGenOpts, Args, SA, T, FrontendOpts.OutputFile,
+                      &*LangOpts);
   GeneratePreprocessorArgs(*PreprocessorOpts, Args, SA, *LangOpts,
                            FrontendOpts, CodeGenOpts);
 }

diff  --git a/llvm/include/llvm/Option/OptParser.td b/llvm/include/llvm/Option/OptParser.td
index 9a179c511bd6c..c85c6c56c8ea9 100644
--- a/llvm/include/llvm/Option/OptParser.td
+++ b/llvm/include/llvm/Option/OptParser.td
@@ -175,7 +175,7 @@ class MarshallingInfoString<KeyPathAndMacro kpm, code defaultvalue="std::string(
 class MarshallingInfoStringInt<KeyPathAndMacro kpm, code defaultvalue="0", code type="unsigned">
   : MarshallingInfo<kpm, defaultvalue> {
   code Normalizer = "normalizeStringIntegral<"#type#">";
-  code Denormalizer = "denormalizeString";
+  code Denormalizer = "denormalizeString<"#type#">";
 }
 
 class MarshallingInfoStringVector<KeyPathAndMacro kpm>


        


More information about the llvm-commits mailing list