Commit e0d9d0dd by Nick Clifton Committed by Nick Clifton

common.opt (record-gcc-switches): New command line switch.

* 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
parent 1d49ee6a
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
......
......@@ -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
......
......@@ -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
......
......@@ -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
......
......@@ -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}
......
......@@ -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. */
......
......@@ -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)
......
......@@ -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"
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment