]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
common.opt (record-gcc-switches): New command line switch.
authorNick Clifton <nickc@redhat.com>
Thu, 7 Dec 2006 10:54:13 +0000 (10:54 +0000)
committerNick Clifton <nickc@gcc.gnu.org>
Thu, 7 Dec 2006 10:54:13 +0000 (10:54 +0000)
* common.opt (record-gcc-switches): New command line switch.
* target.h (print_switch_type): New enum.
  (print_switch_fn_type): New typedef for a function pointer.
  (struct gcc_target): Add record_gcc_switches and record_gcc_switches_section fields.
* target-def.h (TARGET_ASM_RECORD_GCC_SWITCHES): Provide a default definition.
  (TARGET_ASM_RECORD_GCC_SWITCHES_SECTION): Provide a default definition.
* toplev.c (print_single_switch): Simplify by providing a pointer to function that will format and output the switch appropriately.
  (print_switch_values): Likewise.
  (print_to_asm_out_file): New function.
  (print_to_stderr): New function.
  (init_asm_output): If flag_record_gcc_switches is set then if the target supports recording the switches then emit them into the assembler output file, otherwise tell the user that the switch is not supported.
* varasm.c (eld_record_gcc_switches): New function.  Example handler for the record_gcc_switches target hook.
* doc/tm.texi (TARGET_ASM_RECORD_GCC_SWITCHES): Document the new target hook.
  (TARGET_ASM_RECORD_GCC_SWITCHES_SECTION): Likewise.
* doc/invoke.texi (-frecord-gcc-switches): Document.

From-SVN: r119615

gcc/ChangeLog
gcc/common.opt
gcc/doc/invoke.texi
gcc/doc/tm.texi
gcc/target-def.h
gcc/target.h
gcc/toplev.c
gcc/varasm.c

index e3410473d09ef32975a9bd02cc02730e65fea09e..33bd10262222c2487aa4c42181373e204edfd9e1 100644 (file)
@@ -1,3 +1,31 @@
+2006-12-07  Nick Clifton  <nickc@redhat.com>
+
+       * common.opt (record-gcc-switches): New command line switch.
+       * target.h (print_switch_type): New enum.
+       (print_switch_fn_type): New typedef for a function pointer.
+       (struct gcc_target): Add record_gcc_switches and
+       record_gcc_switches_section fields.
+       * target-def.h (TARGET_ASM_RECORD_GCC_SWITCHES): Provide a
+        default definition.
+       (TARGET_ASM_RECORD_GCC_SWITCHES_SECTION): Provide a default
+       definition.
+       * toplev.c (print_single_switch): Simplify by providing a
+       pointer to function that will format and output the switch
+       appropriately.
+       (print_switch_values): Likewise.
+       (print_to_asm_out_file): New function.
+       (print_to_stderr): New function.
+       (init_asm_output): If flag_record_gcc_switches is set then if
+        the target supports recording the switches then emit them into
+        the assembler output file, otherwise tell the user that the
+        switch is not supported.
+       * varasm.c (eld_record_gcc_switches): New function.  Example
+       handler for the record_gcc_switches target hook.
+       * doc/tm.texi (TARGET_ASM_RECORD_GCC_SWITCHES): Document the new
+       target hook.
+       (TARGET_ASM_RECORD_GCC_SWITCHES_SECTION): Likewise.
+       * doc/invoke.texi (-frecord-gcc-switches): Document.
+
 2006-12-07  Maxim Kuvyrkov  <mkuvyrkov@ispras.ru>
 
        PR target/29794
index e73fbac9e9188f1c077439badb6f63edd24cc815..2251b86e34a4fea102121c42d36b4bd116d936d7 100644 (file)
@@ -715,6 +715,16 @@ frandom-seed=
 Common Joined RejectNegative
 -frandom-seed=<string> Make compile reproducible using <string>
 
+; This switch causes the command line that was used to create an
+; object file to be recorded into the object file.  The exact format
+; of this recording is target and binary file format dependent.
+; It is related to the -fverbose-asm switch, but that switch only
+; records information in the assembler output file as comments, so
+; they never reach the object file.
+frecord-gcc-switches
+Common Report Var(flag_record_gcc_switches)
+Record gcc command line switches in the object file.
+
 freg-struct-return
 Common Report Var(flag_pcc_struct_return,0) VarExists
 Return small aggregates in registers
index cd03c92b7aa8dc501aaf3125eb087d38b88c535c..2baf3c3984e3a49a1a29e4a620ca9b6eff9cab92 100644 (file)
@@ -783,6 +783,7 @@ See S/390 and zSeries Options.
 -fno-common  -fno-ident @gol
 -fpcc-struct-return  -fpic  -fPIC -fpie -fPIE @gol
 -fno-jump-tables @gol
+-frecord-gcc-switches @gol
 -freg-struct-return  -fshort-enums @gol
 -fshort-double  -fshort-wchar @gol
 -fverbose-asm  -fpack-struct[=@var{n}]  -fstack-check @gol
@@ -13508,6 +13509,17 @@ debugging the compiler itself).
 extra information to be omitted and is useful when comparing two assembler
 files.
 
+@item -frecord-gcc-switches
+@opindex frecord-gcc-switches
+This switch causes the command line that was used to invoke the
+compiler to be recorded into the object file that is being created.
+This switch is only implemented on some targets and the exact format
+of the recording is target and binary file format dependent, but it
+usually takes the form of a section containing ASCII text.  This
+switch is related to the @option{-fverbose-asm} switch, but that
+switch only records information in the assembler output file as
+comments, so it never reaches the object file.
+
 @item -fpic
 @opindex fpic
 @cindex global offset table
index 634f5f170c6703e6c40d6965172c2941841ce479..52305478d1a59b8e63b7f9dddfcf8f89d9275027 100644 (file)
@@ -6653,6 +6653,58 @@ need to override this if your target has special flags that might be
 set via @code{__attribute__}.
 @end deftypefn
 
+@deftypefn {Target Hook} {int} TARGET_ASM_RECORD_GCC_SWITCHES (print_switch_type @var{type}, const char * @var{text})
+Provides the target with the ability to record the gcc command line
+switches that have been passed to the compiler, and options that are
+enabled.  The @var{type} argument specifies what is being recorded.
+It can take the following values:
+
+@table @gcctabopt
+@item SWITCH_TYPE_PASSED
+@var{text} is a command line switch that has been set by the user.
+
+@item SWITCH_TYPE_ENABLED
+@var{text} is an option which has been enabled.  This might be as a
+direct result of a command line switch, or because it is enabled by
+default or because it has been enabled as a side effect of a different
+command line switch.  For example, the @option{-O2} switch enables
+various different individual optimization passes.
+
+@item SWITCH_TYPE_DESCRIPTIVE
+@var{text} is either NULL or some descriptive text which should be
+ignored.  If @var{text} is NULL then it is being used to warn the
+target hook that either recording is starting or ending.  The first
+time @var{type} is SWITCH_TYPE_DESCRIPTIVE and @var{text} is NULL, the
+warning is for start up and the second time the warning is for
+wind down.  This feature is to allow the target hook to make any
+necessary preparations before it starts to record switches and to
+perform any necessary tidying up after it has finished recording
+switches.
+
+@item SWITCH_TYPE_LINE_START
+This option can be ignored by this target hook.
+
+@item  SWITCH_TYPE_LINE_END
+This option can be ignored by this target hook.
+@end table
+
+The hook's return value must be zero.  Other return values may be
+supported in the future.
+
+By default this hook is set to NULL, but an example implementation is
+provided for ELF based targets.  Called @var{elf_record_gcc_switches},
+it records the switches as ASCII text inside a new, string mergeable
+section in the assembler output file.  The name of the new section is
+provided by the @code{TARGET_ASM_RECORD_GCC_SWITCHES_SECTION} target
+hook.
+@end deftypefn
+
+@deftypefn {Target Hook} {const char *} TARGET_ASM_RECORD_GCC_SWITCHES_SECTION
+This is the name of the section that will be created by the example
+ELF implementation of the @code{TARGET_ASM_RECORD_GCC_SWITCHES} target
+hook.
+@end deftypefn
+
 @need 2000
 @node Data Output
 @subsection Output of Data
index 580c3276900b66a9287388e7c3d46bcdd7f19cab..8cb5d269278c6f4a5dcda90311c2385c1f8600cb 100644 (file)
@@ -227,6 +227,13 @@ Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 #define TARGET_ASM_OUTPUT_DWARF_DTPREL NULL
 #endif
 
+#ifndef TARGET_ASM_RECORD_GCC_SWITCHES
+#define TARGET_ASM_RECORD_GCC_SWITCHES NULL
+#endif
+#ifndef TARGET_ASM_RECORD_GCC_SWITCHES_SECTION
+#define TARGET_ASM_RECORD_GCC_SWITCHES_SECTION ".GCC.command.line"
+#endif
+
 #define TARGET_ASM_ALIGNED_INT_OP                              \
                       {TARGET_ASM_ALIGNED_HI_OP,               \
                        TARGET_ASM_ALIGNED_SI_OP,               \
@@ -270,6 +277,8 @@ Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
                         TARGET_ASM_FILE_END,                   \
                        TARGET_ASM_EXTERNAL_LIBCALL,            \
                         TARGET_ASM_MARK_DECL_PRESERVED,                \
+                       TARGET_ASM_RECORD_GCC_SWITCHES,         \
+                       TARGET_ASM_RECORD_GCC_SWITCHES_SECTION, \
                        TARGET_ASM_OUTPUT_ANCHOR,               \
                        TARGET_ASM_OUTPUT_DWARF_DTPREL}
 
index 1147142f2cfa7c186fef6ab5d061bfe9be137b01..b59f561657f9e379e8fb77d7bdb7150af38b4a2f 100644 (file)
@@ -51,6 +51,22 @@ Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 #include "tm.h"
 #include "insn-modes.h"
 
+/* Types used by the record_gcc_switches() target function.  */
+typedef enum
+{
+  SWITCH_TYPE_PASSED,          /* A switch passed on the command line.  */
+  SWITCH_TYPE_ENABLED,         /* An option that is currently enabled.  */
+  SWITCH_TYPE_DESCRIPTIVE,     /* Descriptive text, not a switch or option.  */
+  SWITCH_TYPE_LINE_START,      /* Please emit any necessary text at the start of a line.  */
+  SWITCH_TYPE_LINE_END         /* Please emit a line terminator.  */
+}
+print_switch_type;
+
+typedef int (* print_switch_fn_type) (print_switch_type, const char *);
+
+/* An example implementation for ELF targets.  Defined in varasm.c  */
+extern int elf_record_gcc_switches (print_switch_type type, const char *);
+
 struct stdarg_info;
 struct spec_info_def;
 
@@ -196,10 +212,18 @@ struct gcc_target
        external.  */
     void (*external_libcall) (rtx);
 
-     /* Output an assembler directive to mark decl live. This instructs
+    /* Output an assembler directive to mark decl live. This instructs
        linker to not dead code strip this symbol.  */
     void (*mark_decl_preserved) (const char *);
 
+    /* Output a record of the command line switches that have been passed.  */
+    print_switch_fn_type record_gcc_switches;
+    /* The name of the section that the example ELF implementation of
+       record_gcc_switches will use to store the information.  Target
+       specific versions of record_gcc_switches may or may not use
+       this information.  */
+    const char * record_gcc_switches_section;
+
     /* Output the definition of a section anchor.  */
     void (*output_anchor) (rtx);
 
@@ -796,7 +820,7 @@ struct gcc_target
        target modifications).  */
     void (*adjust_class_at_definition) (tree type);
   } cxx;
-  
+
   /* For targets that need to mark extra registers as live on entry to
      the function, they should define this target hook and set their
      bits in the bitmap passed in. */  
index 9cc814d7fd001761aee157949ced1c49a2e0a6d0..5fd8c4d3b4c7c76cdb1eeffd7d59423d0f868723 100644 (file)
@@ -112,12 +112,6 @@ static void crash_signal (int) ATTRIBUTE_NORETURN;
 static void setup_core_dumping (void);
 static void compile_file (void);
 
-static int print_single_switch (FILE *, int, int, const char *,
-                               const char *, const char *,
-                               const char *, const char *);
-static void print_switch_values (FILE *, int, int, const char *,
-                                const char *, const char *);
-
 /* Nonzero to dump debug info whilst parsing (-dy option).  */
 static int set_yydebug;
 
@@ -1182,44 +1176,107 @@ print_version (FILE *file, const char *indent)
           PARAM_VALUE (GGC_MIN_EXPAND), PARAM_VALUE (GGC_MIN_HEAPSIZE));
 }
 
+#ifdef ASM_COMMENT_START
+static int
+print_to_asm_out_file (print_switch_type type, const char * text)
+{
+  bool prepend_sep = true;
+
+  switch (type)
+    {
+    case SWITCH_TYPE_LINE_END:
+      putc ('\n', asm_out_file);
+      return 1;
+
+    case SWITCH_TYPE_LINE_START:
+      fputs (ASM_COMMENT_START, asm_out_file);
+      return strlen (ASM_COMMENT_START);
+
+    case SWITCH_TYPE_DESCRIPTIVE:
+      if (ASM_COMMENT_START[0] == 0)
+       prepend_sep = false;
+      /* Drop through.  */
+    case SWITCH_TYPE_PASSED:
+    case SWITCH_TYPE_ENABLED:
+      if (prepend_sep)
+       fputc (' ', asm_out_file);
+      fprintf (asm_out_file, text);
+      /* No need to return the length here as
+        print_single_switch has already done it.  */
+      return 0;
+
+    default:
+      return -1;
+    }
+}
+#endif
+
+static int
+print_to_stderr (print_switch_type type, const char * text)
+{
+  switch (type)
+    {
+    case SWITCH_TYPE_LINE_END:
+      putc ('\n', stderr);
+      return 1;
+
+    case SWITCH_TYPE_LINE_START:
+      return 0;
+      
+    case SWITCH_TYPE_PASSED:
+    case SWITCH_TYPE_ENABLED:
+      fputc (' ', stderr);
+      /* Drop through.  */
+
+    case SWITCH_TYPE_DESCRIPTIVE:
+      fprintf (stderr, text);
+      /* No need to return the length here as
+        print_single_switch has already done it.  */
+      return 0;
+
+    default:
+      return -1;
+    }
+}
+
 /* Print an option value and return the adjusted position in the line.
-   ??? We don't handle error returns from fprintf (disk full); presumably
-   other code will catch a disk full though.  */
+   ??? print_fn doesn't handle errors, eg disk full; presumably other
+   code will catch a disk full though.  */
 
 static int
-print_single_switch (FILE *file, int pos, int max,
-                    const char *indent, const char *sep, const char *term,
-                    const char *type, const char *name)
+print_single_switch (print_switch_fn_type print_fn,
+                    int pos,
+                    print_switch_type type,
+                    const char * text)
 {
-  /* The ultrix fprintf returns 0 on success, so compute the result we want
-     here since we need it for the following test.  */
-  int len = strlen (sep) + strlen (type) + strlen (name);
+  /* The ultrix fprintf returns 0 on success, so compute the result
+     we want here since we need it for the following test.  The +1
+     is for the seperator character that will probably be emitted.  */
+  int len = strlen (text) + 1;
 
   if (pos != 0
-      && pos + len > max)
+      && pos + len > MAX_LINE)
     {
-      fprintf (file, "%s", term);
+      print_fn (SWITCH_TYPE_LINE_END, NULL);
       pos = 0;
     }
+
   if (pos == 0)
-    {
-      fprintf (file, "%s", indent);
-      pos = strlen (indent);
-    }
-  fprintf (file, "%s%s%s", sep, type, name);
-  pos += len;
-  return pos;
+    pos += print_fn (SWITCH_TYPE_LINE_START, NULL);
+
+  print_fn (type, text);
+  return pos + len;
 }
 
-/* Print active target switches to FILE.
+/* Print active target switches using PRINT_FN.
    POS is the current cursor position and MAX is the size of a "line".
    Each line begins with INDENT and ends with TERM.
    Each switch is separated from the next by SEP.  */
 
 static void
-print_switch_values (FILE *file, int pos, int max,
-                    const char *indent, const char *sep, const char *term)
+print_switch_values (print_switch_fn_type print_fn)
 {
+  int pos = 0;
   size_t j;
   const char **p;
 
@@ -1228,45 +1285,50 @@ print_switch_values (FILE *file, int pos, int max,
   randomize ();
 
   /* Print the options as passed.  */
-  pos = print_single_switch (file, pos, max, indent, *indent ? " " : "", term,
-                            _("options passed: "), "");
+  pos = print_single_switch (print_fn, pos,
+                            SWITCH_TYPE_DESCRIPTIVE, _("options passed: "));
 
   for (p = &save_argv[1]; *p != NULL; p++)
-    if (**p == '-')
-      {
-       /* Ignore these.  */
-       if (strcmp (*p, "-o") == 0)
-         {
-           if (p[1] != NULL)
-             p++;
+    {
+      if (**p == '-')
+       {
+         /* Ignore these.  */
+         if (strcmp (*p, "-o") == 0
+             || strcmp (*p, "-dumpbase") == 0
+             || strcmp (*p, "-auxbase") == 0)
+           {
+             if (p[1] != NULL)
+               p++;
+             continue;
+           }
+
+         if (strcmp (*p, "-quiet") == 0
+             || strcmp (*p, "-version") == 0)
            continue;
-         }
-       if (strcmp (*p, "-quiet") == 0)
-         continue;
-       if (strcmp (*p, "-version") == 0)
-         continue;
-       if ((*p)[1] == 'd')
-         continue;
-
-       pos = print_single_switch (file, pos, max, indent, sep, term, *p, "");
-      }
+
+         if ((*p)[1] == 'd')
+           continue;
+       }
+
+      pos = print_single_switch (print_fn, pos, SWITCH_TYPE_PASSED, *p);
+    }
+
   if (pos > 0)
-    fprintf (file, "%s", term);
+    print_fn (SWITCH_TYPE_LINE_END, NULL);
 
   /* Print the -f and -m options that have been enabled.
      We don't handle language specific options but printing argv
      should suffice.  */
-
-  pos = print_single_switch (file, 0, max, indent, *indent ? " " : "", term,
-                            _("options enabled: "), "");
+  pos = print_single_switch (print_fn, 0,
+                            SWITCH_TYPE_DESCRIPTIVE, _("options enabled: "));
 
   for (j = 0; j < cl_options_count; j++)
     if ((cl_options[j].flags & CL_REPORT)
        && option_enabled (j) > 0)
-      pos = print_single_switch (file, pos, max, indent, sep, term,
-                                "", cl_options[j].opt_text);
+      pos = print_single_switch (print_fn, pos,
+                                SWITCH_TYPE_ENABLED, cl_options[j].opt_text);
 
-  fprintf (file, "%s", term);
+  print_fn (SWITCH_TYPE_LINE_END, NULL);
 }
 
 /* Open assembly code output file.  Do this even if -fsyntax-only is
@@ -1284,6 +1346,7 @@ init_asm_output (const char *name)
        {
          int len = strlen (dump_base_name);
          char *dumpname = XNEWVEC (char, len + 6);
+
          memcpy (dumpname, dump_base_name, len + 1);
          strip_off_ending (dumpname, len);
          strcat (dumpname, ".s");
@@ -1301,15 +1364,30 @@ init_asm_output (const char *name)
     {
       targetm.asm_out.file_start ();
 
+      if (flag_record_gcc_switches)
+       {
+         if (targetm.asm_out.record_gcc_switches)
+           {
+             /* Let the target know that we are about to start recording.  */
+             targetm.asm_out.record_gcc_switches (SWITCH_TYPE_DESCRIPTIVE,
+                                                  NULL);
+             /* Now record the switches.  */
+             print_switch_values (targetm.asm_out.record_gcc_switches);
+             /* Let the target know that the recording is over.  */
+             targetm.asm_out.record_gcc_switches (SWITCH_TYPE_DESCRIPTIVE,
+                                                  NULL);
+           }
+         else
+           inform ("-frecord-gcc-switches is not supported by the current target");
+       }
+
 #ifdef ASM_COMMENT_START
       if (flag_verbose_asm)
        {
-         /* Print the list of options in effect.  */
+         /* Print the list of switches in effect
+            into the assembler file as comments.  */
          print_version (asm_out_file, ASM_COMMENT_START);
-         print_switch_values (asm_out_file, 0, MAX_LINE,
-                              ASM_COMMENT_START, " ", "\n");
-         /* Add a blank line here so it appears in assembler output but not
-            screen output.  */
+         print_switch_values (print_to_asm_out_file);
          fprintf (asm_out_file, "\n");
        }
 #endif
@@ -1677,7 +1755,7 @@ process_options (void)
     {
       print_version (stderr, "");
       if (! quiet_flag)
-       print_switch_values (stderr, 0, MAX_LINE, "", " ", "\n");
+       print_switch_values (print_to_stderr);
     }
 
   if (flag_syntax_only)
index 819add8afba633de0c219abc5c410bdf4a05a6cb..1e7af0e5b5d70391651a904fa21bdd2b72c80ff6 100644 (file)
@@ -6226,4 +6226,105 @@ output_object_blocks (void)
   htab_traverse (object_block_htab, output_object_block_htab, NULL);
 }
 
+/* This function provides a possible implementation of the
+   TARGET_ASM_RECORD_GCC_SWITCHES target hook for ELF targets.  When triggered
+   by -frecord-gcc-switches it creates a new mergeable, string section in the
+   assembler output file called TARGET_ASM_RECORD_GCC_SWITCHES_SECTION which
+   contains the switches in ASCII format.
+
+   FIXME: This code does not correctly handle double quote characters
+   that appear inside strings, (it strips them rather than preserving them).
+   FIXME: ASM_OUTPUT_ASCII, as defined in config/elfos.h will not emit NUL
+   characters - instead it treats them as sub-string separators.  Since
+   we want to emit NUL strings terminators into the object file we have to use
+   ASM_OUTPUT_SKIP.  */
+
+int
+elf_record_gcc_switches (print_switch_type type, const char * name)
+{
+  static char buffer[1024];
+
+  /* This variable is used as part of a simplistic heuristic to detect
+     command line switches which take an argument:
+
+       "If a command line option does not start with a dash then
+        it is an argument for the previous command line option."
+
+     This fails in the case of the command line option which is the name
+     of the file to compile, but otherwise it is pretty reasonable.  */
+  static bool previous_name_held_back = FALSE;
+
+  switch (type)
+    {
+    case SWITCH_TYPE_PASSED:
+      if (* name != '-')
+       {
+         if (previous_name_held_back)
+           {
+             unsigned int len = strlen (buffer);
+
+             snprintf (buffer + len, sizeof buffer - len, " %s", name);
+             ASM_OUTPUT_ASCII (asm_out_file, buffer, strlen (buffer));
+             ASM_OUTPUT_SKIP (asm_out_file, 1L);
+             previous_name_held_back = FALSE;
+           }
+         else
+           {
+             strncpy (buffer, name, sizeof buffer);
+             ASM_OUTPUT_ASCII (asm_out_file, buffer, strlen (buffer));
+             ASM_OUTPUT_SKIP (asm_out_file, 1L);
+           }
+       }
+      else
+       {
+         if (previous_name_held_back)
+           {
+             ASM_OUTPUT_ASCII (asm_out_file, buffer, strlen (buffer));
+             ASM_OUTPUT_SKIP (asm_out_file, 1L);
+           }
+
+         strncpy (buffer, name, sizeof buffer);
+         previous_name_held_back = TRUE;
+       }
+      break;
+
+    case SWITCH_TYPE_DESCRIPTIVE:
+      if (name == NULL)
+       {
+         /* Distinguish between invocations where name is NULL.  */
+         static bool started = false;
+
+         if (started)
+           {
+             if (previous_name_held_back)
+               {
+                 ASM_OUTPUT_ASCII (asm_out_file, buffer, strlen (buffer));
+                 ASM_OUTPUT_SKIP (asm_out_file, 1L);
+               }
+           }
+         else
+           {
+             section * sec;
+
+             sec = get_section (targetm.asm_out.record_gcc_switches_section,
+                                SECTION_DEBUG
+                                | SECTION_MERGE
+                                | SECTION_STRINGS
+                                | (SECTION_ENTSIZE & 1),
+                                NULL);
+             switch_to_section (sec);
+             started = true;
+           }
+       }
+
+    default:
+      break;
+    }
+
+  /* The return value is currently ignored by the caller, but must be 0.
+     For -fverbose-asm the return value would be the number of characters
+     emitted into the assembler file.  */
+  return 0;
+}
+
 #include "gt-varasm.h"