aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog28
-rw-r--r--gcc/common.opt10
-rw-r--r--gcc/doc/invoke.texi12
-rw-r--r--gcc/doc/tm.texi52
-rw-r--r--gcc/target-def.h9
-rw-r--r--gcc/target.h28
-rw-r--r--gcc/toplev.c194
-rw-r--r--gcc/varasm.c101
8 files changed, 374 insertions, 60 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index e341047..33bd102 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/common.opt b/gcc/common.opt
index e73fbac..2251b86 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -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
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index cd03c92..2baf3c3 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -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
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index 634f5f1..52305478 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -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
diff --git a/gcc/target-def.h b/gcc/target-def.h
index 580c327..8cb5d26 100644
--- a/gcc/target-def.h
+++ b/gcc/target-def.h
@@ -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}
diff --git a/gcc/target.h b/gcc/target.h
index 1147142..b59f561 100644
--- a/gcc/target.h
+++ b/gcc/target.h
@@ -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. */
diff --git a/gcc/toplev.c b/gcc/toplev.c
index 9cc814d..5fd8c4d 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -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)
diff --git a/gcc/varasm.c b/gcc/varasm.c
index 819add8..1e7af0e 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -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"