diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 28 | ||||
-rw-r--r-- | gcc/common.opt | 10 | ||||
-rw-r--r-- | gcc/doc/invoke.texi | 12 | ||||
-rw-r--r-- | gcc/doc/tm.texi | 52 | ||||
-rw-r--r-- | gcc/target-def.h | 9 | ||||
-rw-r--r-- | gcc/target.h | 28 | ||||
-rw-r--r-- | gcc/toplev.c | 194 | ||||
-rw-r--r-- | gcc/varasm.c | 101 |
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" |