Introduce -grecord-gcc-switches=default|all|none alongside the existing
-grecord-gcc-switches option. The all mode records all command line
switches in DW_AT_producer, while default preserves current filtering.
Update producer-string generation and documentation accordingly.

This allows this option to be used like `-grecord-command-line` in
LLVM for more complete recording of compiler invocations. For
performance analysis use cases, having all switches recorded like `-D`
and `-I` can help tools better understand the build context. It can be
beneficial to let analyzer tools understand the full context of the
compilation from the DWARF info.

Signed-off-by: Yangyu Chen <[email protected]>

gcc/ChangeLog:

        * common.opt: Add -grecord-gcc-switches option with modes.
        * doc/invoke.texi: Document -grecord-gcc-switches option.
        * dwarf2out.cc (dwarf2out_early_finish): Pass new mode to
        gen_producer_string.
        * opts.cc (gen_command_line_string): Ditto.
        (gen_producer_string): Add new parameter for record-gcc-switches
        mode and implement filtering for 'all' mode.
        * opts.h (gen_command_line_string): Ditto.
        * toplev.cc (init_asm_output): Pass new mode to
        gen_producer_string.
        (process_options): Ditto.
---
 gcc/common.opt      |  17 ++++
 gcc/doc/invoke.texi |   5 ++
 gcc/dwarf2out.cc    |   3 +-
 gcc/opts.cc         | 202 ++++++++++++++++++++++++--------------------
 gcc/opts.h          |   6 +-
 gcc/toplev.cc       |   9 +-
 6 files changed, 146 insertions(+), 96 deletions(-)

diff --git a/gcc/common.opt b/gcc/common.opt
index 88b79bbf8f5..7fc3b341541 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -3770,6 +3770,23 @@ grecord-gcc-switches
 Common Driver Var(dwarf_record_gcc_switches) Init(1)
 Record gcc command line switches in DWARF DW_AT_producer.
 
+grecord-gcc-switches=
+Common Driver Joined RejectNegative Var(dwarf_record_gcc_switches) 
Enum(record_gcc_switches)
+-grecord-gcc-switches[=default|all|none]       Record gcc command line
+switches in DWARF DW_AT_producer.
+
+Enum
+Name(record_gcc_switches) Type(int)
+
+EnumValue
+Enum(record_gcc_switches) String(none) Value(0)
+
+EnumValue
+Enum(record_gcc_switches) String(default) Value(1)
+
+EnumValue
+Enum(record_gcc_switches) String(all) Value(2)
+
 gsplit-dwarf
 Common Driver Var(dwarf_split_debug_info) Init(0)
 Generate debug information in separate .dwo files.
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 58254b82b0e..098235dd525 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -13069,6 +13069,7 @@ debugging information.
 @opindex grecord-gcc-switches
 @opindex gno-record-gcc-switches
 @item -grecord-gcc-switches
+@itemx -grecord-gcc-switches=@var{mode}
 @itemx -gno-record-gcc-switches
 This switch causes the command-line options used to invoke the
 compiler that may affect code generation to be appended to the
@@ -13076,6 +13077,10 @@ DW_AT_producer attribute in DWARF debugging 
information.  The options
 are concatenated with spaces separating them from each other and from
 the compiler version.
 It is enabled by default.
+The @var{mode} value may be @samp{default} (the existing filtering),
+@samp{all} (record all command-line switches, including preprocessor
+options such as @option{-I}, @option{-D}, and @option{-U}), or
+@samp{none} (equivalent to @option{-gno-record-gcc-switches}).
 See also @option{-frecord-gcc-switches} for another
 way of storing compiler options into the object file.
 
diff --git a/gcc/dwarf2out.cc b/gcc/dwarf2out.cc
index 31ff7ff1905..cd1e10e5562 100644
--- a/gcc/dwarf2out.cc
+++ b/gcc/dwarf2out.cc
@@ -33610,7 +33610,8 @@ dwarf2out_early_finish (const char *filename)
   if (dwarf_record_gcc_switches)
     producer_string = gen_producer_string (lang_hooks.name,
                                           save_decoded_options,
-                                          save_decoded_options_count);
+                                          save_decoded_options_count,
+                                          dwarf_record_gcc_switches);
   else
     producer_string = concat (lang_hooks.name, " ", version_string, NULL);
 
diff --git a/gcc/opts.cc b/gcc/opts.cc
index 6323fd58801..78fedccac71 100644
--- a/gcc/opts.cc
+++ b/gcc/opts.cc
@@ -3895,107 +3895,127 @@ make_option_url (diagnostics::option_id option_id) 
const
 
 char *
 gen_command_line_string (cl_decoded_option *options,
-                        unsigned int options_count)
+                        unsigned int options_count,
+                        int record_gcc_switches_mode)
 {
   auto_vec<const char *> switches;
   char *options_string, *tail;
   const char *p;
   size_t len = 0;
+  const bool record_all_switches = (record_gcc_switches_mode > 1);
 
   for (unsigned i = 0; i < options_count; i++)
-    switch (options[i].opt_index)
-      {
-      case OPT_o:
-      case OPT_d:
-      case OPT_dumpbase:
-      case OPT_dumpbase_ext:
-      case OPT_dumpdir:
-      case OPT_quiet:
-      case OPT_version:
-      case OPT_v:
-      case OPT_w:
-      case OPT_L:
-      case OPT_I:
-      case OPT_SPECIAL_unknown:
-      case OPT_SPECIAL_ignore:
-      case OPT_SPECIAL_warn_removed:
-      case OPT_SPECIAL_program_name:
-      case OPT_SPECIAL_input_file:
-      case OPT_grecord_gcc_switches:
-      case OPT_frecord_gcc_switches:
-      case OPT__output_pch:
-      case OPT_fdiagnostics_show_highlight_colors:
-      case OPT_fdiagnostics_show_location_:
-      case OPT_fdiagnostics_show_option:
-      case OPT_fdiagnostics_show_caret:
-      case OPT_fdiagnostics_show_event_links:
-      case OPT_fdiagnostics_show_labels:
-      case OPT_fdiagnostics_show_line_numbers:
-      case OPT_fdiagnostics_color_:
-      case OPT_fdiagnostics_format_:
-      case OPT_fdiagnostics_show_nesting:
-      case OPT_fdiagnostics_show_nesting_locations:
-      case OPT_fdiagnostics_show_nesting_levels:
-      case OPT_fverbose_asm:
-      case OPT____:
-      case OPT__sysroot_:
-      case OPT_nostdinc:
-      case OPT_nostdinc__:
-      case OPT_fpreprocessed:
-      case OPT_fltrans_output_list_:
-      case OPT_fresolution_:
-      case OPT_fdebug_prefix_map_:
-      case OPT_fmacro_prefix_map_:
-      case OPT_ffile_prefix_map_:
-      case OPT_fprofile_prefix_map_:
-      case OPT_fcanon_prefix_map:
-      case OPT_fcompare_debug:
-      case OPT_fchecking:
-      case OPT_fchecking_:
-       /* Ignore these.  */
-       continue;
-      case OPT_D:
-      case OPT_U:
-       if (startswith (options[i].arg, "_FORTIFY_SOURCE")
-           && (options[i].arg[sizeof ("_FORTIFY_SOURCE") - 1] == '\0'
-               || (options[i].opt_index == OPT_D
-                   && options[i].arg[sizeof ("_FORTIFY_SOURCE") - 1] == '=')))
-         {
-           switches.safe_push (options[i].orig_option_with_args_text);
-           len += strlen (options[i].orig_option_with_args_text) + 1;
-         }
-       /* Otherwise ignore these. */
-       continue;
-      case OPT_flto_:
+    {
+      if (record_all_switches)
        {
-         const char *lto_canonical = "-flto";
-         switches.safe_push (lto_canonical);
-         len += strlen (lto_canonical) + 1;
-         break;
+         switch (options[i].opt_index)
+           {
+           case OPT_SPECIAL_unknown:
+           case OPT_SPECIAL_ignore:
+           case OPT_SPECIAL_warn_removed:
+           case OPT_SPECIAL_program_name:
+           case OPT_SPECIAL_input_file:
+             continue;
+           default:
+             switches.safe_push (options[i].orig_option_with_args_text);
+             len += strlen (options[i].orig_option_with_args_text) + 1;
+             continue;
+           }
        }
-      default:
-       if (cl_options[options[i].opt_index].flags
-           & CL_NO_DWARF_RECORD)
+
+      switch (options[i].opt_index)
+       {
+       case OPT_o:
+       case OPT_d:
+       case OPT_dumpbase:
+       case OPT_dumpbase_ext:
+       case OPT_dumpdir:
+       case OPT_quiet:
+       case OPT_version:
+       case OPT_v:
+       case OPT_w:
+       case OPT_L:
+       case OPT_I:
+       case OPT_SPECIAL_unknown:
+       case OPT_SPECIAL_ignore:
+       case OPT_SPECIAL_warn_removed:
+       case OPT_SPECIAL_program_name:
+       case OPT_SPECIAL_input_file:
+       case OPT_grecord_gcc_switches_:
+       case OPT_frecord_gcc_switches:
+       case OPT__output_pch:
+       case OPT_fdiagnostics_show_highlight_colors:
+       case OPT_fdiagnostics_show_location_:
+       case OPT_fdiagnostics_show_option:
+       case OPT_fdiagnostics_show_caret:
+       case OPT_fdiagnostics_show_event_links:
+       case OPT_fdiagnostics_show_labels:
+       case OPT_fdiagnostics_show_line_numbers:
+       case OPT_fdiagnostics_color_:
+       case OPT_fdiagnostics_format_:
+       case OPT_fdiagnostics_show_nesting:
+       case OPT_fdiagnostics_show_nesting_locations:
+       case OPT_fdiagnostics_show_nesting_levels:
+       case OPT_fverbose_asm:
+       case OPT____:
+       case OPT__sysroot_:
+       case OPT_nostdinc:
+       case OPT_nostdinc__:
+       case OPT_fpreprocessed:
+       case OPT_fltrans_output_list_:
+       case OPT_fresolution_:
+       case OPT_fdebug_prefix_map_:
+       case OPT_fmacro_prefix_map_:
+       case OPT_ffile_prefix_map_:
+       case OPT_fprofile_prefix_map_:
+       case OPT_fcanon_prefix_map:
+       case OPT_fcompare_debug:
+       case OPT_fchecking:
+       case OPT_fchecking_:
+         /* Ignore these.  */
+         continue;
+       case OPT_D:
+       case OPT_U:
+         if (startswith (options[i].arg, "_FORTIFY_SOURCE")
+             && (options[i].arg[sizeof ("_FORTIFY_SOURCE") - 1] == '\0'
+                 || (options[i].opt_index == OPT_D
+                     && options[i].arg[sizeof ("_FORTIFY_SOURCE") - 1]
+                            == '=')))
+           {
+             switches.safe_push (options[i].orig_option_with_args_text);
+             len += strlen (options[i].orig_option_with_args_text) + 1;
+           }
+         /* Otherwise ignore these.  */
          continue;
-       gcc_checking_assert (options[i].canonical_option[0][0] == '-');
-       switch (options[i].canonical_option[0][1])
+       case OPT_flto_:
          {
-         case 'M':
-         case 'i':
-         case 'W':
-           continue;
-         case 'f':
-           if (strncmp (options[i].canonical_option[0] + 2,
-                        "dump", 4) == 0)
-             continue;
-           break;
-         default:
+           const char *lto_canonical = "-flto";
+           switches.safe_push (lto_canonical);
+           len += strlen (lto_canonical) + 1;
            break;
          }
-       switches.safe_push (options[i].orig_option_with_args_text);
-       len += strlen (options[i].orig_option_with_args_text) + 1;
-       break;
-      }
+       default:
+         if (cl_options[options[i].opt_index].flags & CL_NO_DWARF_RECORD)
+           continue;
+         gcc_checking_assert (options[i].canonical_option[0][0] == '-');
+         switch (options[i].canonical_option[0][1])
+           {
+           case 'M':
+           case 'i':
+           case 'W':
+             continue;
+           case 'f':
+             if (strncmp (options[i].canonical_option[0] + 2, "dump", 4) == 0)
+               continue;
+             break;
+           default:
+             break;
+           }
+         switches.safe_push (options[i].orig_option_with_args_text);
+         len += strlen (options[i].orig_option_with_args_text) + 1;
+         break;
+       }
+    }
 
   options_string = XNEWVEC (char, len + 1);
   tail = options_string;
@@ -4021,9 +4041,11 @@ gen_command_line_string (cl_decoded_option *options,
 
 char *
 gen_producer_string (const char *language_string, cl_decoded_option *options,
-                    unsigned int options_count)
+                    unsigned int options_count,
+                    int record_gcc_switches_mode)
 {
-  char *cmdline = gen_command_line_string (options, options_count);
+  char *cmdline = gen_command_line_string (options, options_count,
+                                          record_gcc_switches_mode);
   char *combined = concat (language_string, " ", version_string, " ",
                           cmdline, NULL);
   free (cmdline);
diff --git a/gcc/opts.h b/gcc/opts.h
index a59475b1daf..f26e6cea581 100644
--- a/gcc/opts.h
+++ b/gcc/opts.h
@@ -519,10 +519,12 @@ extern void parse_options_from_collect_gcc_options (const 
char *, obstack *,
 extern void prepend_xassembler_to_collect_as_options (const char *, obstack *);
 
 extern char *gen_command_line_string (cl_decoded_option *options,
-                                     unsigned int options_count);
+                                     unsigned int options_count,
+                                     int record_gcc_switches_mode);
 extern char *gen_producer_string (const char *language_string,
                                  cl_decoded_option *options,
-                                 unsigned int options_count);
+                                 unsigned int options_count,
+                                 int record_gcc_switches_mode);
 
 /* Set OPTION in OPTS to VALUE if the option is not set in OPTS_SET.  */
 
diff --git a/gcc/toplev.cc b/gcc/toplev.cc
index 9c93eb8ce1d..da8436eecf8 100644
--- a/gcc/toplev.cc
+++ b/gcc/toplev.cc
@@ -735,7 +735,8 @@ init_asm_output (const char *name)
              const char *str
                = gen_producer_string (lang_hooks.name,
                                       save_decoded_options,
-                                      save_decoded_options_count);
+                                      save_decoded_options_count,
+                                      1);
              targetm.asm_out.record_gcc_switches (str);
            }
          else
@@ -750,7 +751,8 @@ init_asm_output (const char *name)
          fputs (ASM_COMMENT_START, asm_out_file);
          fputs (" options passed: ", asm_out_file);
          char *cmdline = gen_command_line_string (save_decoded_options,
-                                                  save_decoded_options_count);
+                                                  save_decoded_options_count,
+                                                  1);
          fputs (cmdline, asm_out_file);
          free (cmdline);
          fputc ('\n', asm_out_file);
@@ -1426,7 +1428,8 @@ process_options ()
        {
          fputs ("options passed: ", stderr);
          char *cmdline = gen_command_line_string (save_decoded_options,
-                                                  save_decoded_options_count);
+                                                  save_decoded_options_count,
+                                                  1);
 
          fputs (cmdline, stderr);
          free (cmdline);
-- 
2.51.0

Reply via email to