common.opt (fcompare-debug=, [...]): New.

gcc/ChangeLog:
* common.opt (fcompare-debug=, fcompare-debug-second): New.
(fdump-final-insns=, gtoggle): New.
* doc/invoke.texi: Document them.
* final.c (rest_of_clean_state): Dump final insn stream.
* gcc.c (invoke_as): Hook in -fcompare-debug.
(static_spec_functions): Add compare-debug-dump-opt,
compare-debug-self-opt and compare-debug-auxbase-opt.
(compare_debug, compare_debug_second, compare_debug_opt): New.
(switches_debug_check, n_switches_debug_check): New.
(debug_auxbase_opt, debug_check_temp_file): New.
(process_command): Handle -fno-compare-debug, -fcompare-debug and
-fcompare-debug=*.
(do_self_spec): Handle arguments after switches.
(do_spec_1): Add .gk extension to temp file basenames for compare.
(check_live_switch): Take SWITCH_IGNORE into account, and earlier.
(cc1_options): Use it instead of normal auxbase computation for
the second compare-debug compilation.
(compare_files): New.
(main): Set up and implement compare debug mode.
(compare_debug_dump_opt_spec_function): New.
(compare_debug_self_opt_spec_function): New.
(compare_debug_auxbase_opt_spec_function): New.
* toplev.c (process_options): Handle flag_gtoggle,
flag_dump_final_insns.
* coverage.c (coverage_begin_output): Don't overwrite .gcno file
during -fcompare-debug-second compilation.
gcc/cp/ChangeLog:
* repo.c (get_base_filename): Use aux_base_name rather than
alternate temporary file during second compare debug compilation.
(finish_repo): Skip during -fcompare-debug-second.
gcc/ada/ChangeLog:
* lib-writ.adb (flag_compare_debug): Import.
(Write_ALI): Skip during -fcompare-debug-second.
gcc/fortran/ChangeLog:
* options.c (gfc_post_options): Disable dump_parse_tree
during -fcompare-debug-second.
gcc/objc/ChangeLog:
* objc-act.c (objc_init): Skip print_struct_values during
-fcompare-debug-second.

From-SVN: r148271
This commit is contained in:
Alexandre Oliva 2009-06-08 07:46:02 +00:00 committed by Alexandre Oliva
parent cdb884681d
commit 2153915d0a
15 changed files with 741 additions and 25 deletions

View File

@ -1,3 +1,32 @@
2009-06-08 Alexandre Oliva <aoliva@redhat.com>
* common.opt (fcompare-debug=, fcompare-debug-second): New.
(fdump-final-insns=, gtoggle): New.
* doc/invoke.texi: Document them.
* final.c (rest_of_clean_state): Dump final insn stream.
* gcc.c (invoke_as): Hook in -fcompare-debug.
(static_spec_functions): Add compare-debug-dump-opt,
compare-debug-self-opt and compare-debug-auxbase-opt.
(compare_debug, compare_debug_second, compare_debug_opt): New.
(switches_debug_check, n_switches_debug_check): New.
(debug_auxbase_opt, debug_check_temp_file): New.
(process_command): Handle -fno-compare-debug, -fcompare-debug and
-fcompare-debug=*.
(do_self_spec): Handle arguments after switches.
(do_spec_1): Add .gk extension to temp file basenames for compare.
(check_live_switch): Take SWITCH_IGNORE into account, and earlier.
(cc1_options): Use it instead of normal auxbase computation for
the second compare-debug compilation.
(compare_files): New.
(main): Set up and implement compare debug mode.
(compare_debug_dump_opt_spec_function): New.
(compare_debug_self_opt_spec_function): New.
(compare_debug_auxbase_opt_spec_function): New.
* toplev.c (process_options): Handle flag_gtoggle,
flag_dump_final_insns.
* coverage.c (coverage_begin_output): Don't overwrite .gcno file
during -fcompare-debug-second compilation.
2009-06-07 Ian Lance Taylor <iant@google.com>
* dwarf2.h (enum dwarf_location_atom): Add

View File

@ -1,3 +1,8 @@
2009-06-08 Alexandre Oliva <aoliva@redhat.com>
* lib-writ.adb (flag_compare_debug): Import.
(Write_ALI): Skip during -fcompare-debug-second.
2009-06-03 Eric Botcazou <ebotcazou@adacore.com>
* gcc-interface/decl.c (gnat_to_gnu_entity) <E_Record_Type>: When

View File

@ -197,6 +197,10 @@ package body Lib.Writ is
Num_Sdep : Nat := 0;
-- Number of active entries in Sdep_Table
flag_compare_debug : Int;
pragma Import (C, flag_compare_debug);
-- Import from toplev.c
-----------------------
-- Local Subprograms --
-----------------------
@ -800,7 +804,9 @@ package body Lib.Writ is
-- We never write an ALI file if the original operating mode was
-- syntax-only (-gnats switch used in compiler invocation line)
if Original_Operating_Mode = Check_Syntax then
if Original_Operating_Mode = Check_Syntax
or flag_compare_debug /= 0
then
return;
end if;

View File

@ -384,6 +384,14 @@ fconserve-stack
Common Var(flag_conserve_stack) Optimization
Do not perform optimizations increasing noticeably stack usage
fcompare-debug=
Common JoinedOrMissing RejectNegative Var(flag_compare_debug_opt)
-fcompare-debug[=<opts>] Compile with and without e.g. -gtoggle, and compare the final-insns dump
fcompare-debug-second
Common RejectNegative Var(flag_compare_debug)
Run only the second compilation of -fcompare-debug
fcprop-registers
Common Report Var(flag_cprop_registers) Optimization
Perform a register copy-propagation optimization pass
@ -450,6 +458,10 @@ fdump-
Common Joined RejectNegative
-fdump-<type> Dump various compiler internals to a file
fdump-final-insns=
Common RejectNegative Joined Var(flag_dump_final_insns)
-fdump-final-insns=filename Dump to filename the insns at the end of translation
fdump-noaddr
Common Report Var(flag_dump_noaddr)
Suppress output of addresses in debugging dumps
@ -1417,6 +1429,10 @@ gstabs+
Common JoinedOrMissing Negative(gvms)
Generate debug information in extended STABS format
gtoggle
Common Report Var(flag_gtoggle)
Toggle debug information generation
gvms
Common JoinedOrMissing Negative(gxcoff)
Generate debug information in VMS format

View File

@ -554,7 +554,7 @@ coverage_begin_output (void)
{
/* We don't need to output .gcno file unless we're under -ftest-coverage
(e.g. -fprofile-arcs/generate/use don't need .gcno to work). */
if (no_coverage || !flag_test_coverage)
if (no_coverage || !flag_test_coverage || flag_compare_debug)
return 0;
if (!bbg_function_announced)

View File

@ -1,3 +1,9 @@
2009-06-08 Alexandre Oliva <aoliva@redhat.com>
* repo.c (get_base_filename): Use aux_base_name rather than
alternate temporary file during second compare debug compilation.
(finish_repo): Skip during -fcompare-debug-second.
2009-06-06 Ian Lance Taylor <iant@google.com>
* parser.c (cp_parser_label_for_labeled_statement): Support

View File

@ -90,7 +90,7 @@ static const char *
get_base_filename (const char *filename)
{
char *p = getenv ("COLLECT_GCC_OPTIONS");
char *output = NULL;
const char *output = NULL;
int compiling = 0;
while (p && *p)
@ -98,7 +98,15 @@ get_base_filename (const char *filename)
char *q = extract_string (&p);
if (strcmp (q, "-o") == 0)
output = extract_string (&p);
{
if (flag_compare_debug)
/* Just in case aux_base_name was based on a name with two
or more '.'s, add an arbitrary extension that will be
stripped by the caller. */
output = concat (aux_base_name, ".o", NULL);
else
output = extract_string (&p);
}
else if (strcmp (q, "-c") == 0)
compiling = 1;
}
@ -231,7 +239,7 @@ finish_repo (void)
char *dir, *args;
FILE *repo_file;
if (!flag_use_repository)
if (!flag_use_repository || flag_compare_debug)
return;
if (errorcount || sorrycount)

View File

@ -302,13 +302,15 @@ Objective-C and Objective-C++ Dialects}.
-fdump-tree-vrp@r{[}-@var{n}@r{]} @gol
-ftree-vectorizer-verbose=@var{n} @gol
-fdump-tree-storeccp@r{[}-@var{n}@r{]} @gol
-fdump-final-insns=@var{file} @gol
-fcompare-debug@r{[}=@var{opts}@r{]} -fcompare-debug-second @gol
-feliminate-dwarf2-dups -feliminate-unused-debug-types @gol
-feliminate-unused-debug-symbols -femit-class-debug-always @gol
-fmem-report -fpre-ipa-mem-report -fpost-ipa-mem-report -fprofile-arcs @gol
-frandom-seed=@var{string} -fsched-verbose=@var{n} @gol
-fsel-sched-verbose -fsel-sched-dump-cfg -fsel-sched-pipelining-verbose @gol
-ftest-coverage -ftime-report -fvar-tracking @gol
-g -g@var{level} -gcoff -gdwarf-2 @gol
-g -g@var{level} -gtoggle -gcoff -gdwarf-2 @gol
-ggdb -gstabs -gstabs+ -gvms -gxcoff -gxcoff+ @gol
-fno-merge-debug-strings -fno-dwarf2-cfi-asm @gol
-fdebug-prefix-map=@var{old}=@var{new} @gol
@ -4384,6 +4386,61 @@ debug format is long obsolete, but the option cannot be changed now.
Instead use an additional @option{-g@var{level}} option to change the
debug level for DWARF2.
@item -gtoggle
@opindex gtoggle
Turn off generation of debug info, if leaving out this option would have
generated it, or turn it on at level 2 otherwise. The position of this
argument in the command line does not matter, it takes effect after all
other options are processed, and it does so only once, no matter how
many times it is given. This is mainly intended to be used with
@option{-fcompare-debug}.
@item -fdump-final-insns=@var{file}
@opindex fdump-final-insns=
Dump the final internal representation (RTL) to @var{file}.
@item -fcompare-debug@r{[}=@var{opts}@r{]}
@opindex fcompare-debug
@opindex fno-compare-debug
If no error occurs during compilation, run the compiler a second time,
adding @var{opts} and @option{-fcompare-debug-second} to the arguments
passed to the second compilation. Dump the final internal
representation in both compilations, and print an error if they differ.
If the equal sign is omitted, the default @option{-gtoggle} is used.
The environment variable @env{GCC_COMPARE_DEBUG}, if defined, non-empty
and nonzero, implicitly enables @option{-fcompare-debug}. If
@env{GCC_COMPARE_DEBUG} is defined to a string starting with a dash,
then it is used for @var{opts}, otherwise the default @option{-gtoggle}
is used.
@option{-fcompare-debug=}, with the equal sign but without @var{opts},
is equivalent to @option{-fno-compare-debug}, which disables the dumping
of the final representation and the second compilation, preventing even
@env{GCC_COMPARE_DEBUG} from taking effect.
To verify full coverage during @option{-fcompare-debug} testing, set
@env{GCC_COMPARE_DEBUG} to say @samp{-fcompare-debug-not-overridden},
which GCC will reject as an invalid option in any actual compilation
(rather than preprocessing, assembly or linking). To get just a
warning, setting @env{GCC_COMPARE_DEBUG} to @samp{-w%n-fcompare-debug
not overridden} will do.
@item -fcompare-debug-second
@opindex fcompare-debug-second
This option is implicitly passed to the compiler for the second
compilation requested by @option{-fcompare-debug}, along with options to
silence warnings, and omitting other options that would cause
side-effect compiler outputs to files or to the standard output. Dump
files and preserved temporary files are renamed so as to contain the
@code{.gk} additional extension during the second compilation, to avoid
overwriting those generated by the first.
When this option is passed to the compiler driver, it causes the
@emph{first} compilation to be skipped, which makes it useful for little
other than debugging the compiler proper.
@item -feliminate-dwarf2-dups
@opindex feliminate-dwarf2-dups
Compress DWARF2 debugging information by eliminating duplicated

View File

@ -4313,6 +4313,41 @@ static unsigned int
rest_of_clean_state (void)
{
rtx insn, next;
FILE *final_output = NULL;
int save_unnumbered = flag_dump_unnumbered;
int save_noaddr = flag_dump_noaddr;
if (flag_dump_final_insns)
{
final_output = fopen (flag_dump_final_insns, "a");
if (!final_output)
{
error ("could not open final insn dump file %qs: %s",
flag_dump_final_insns, strerror (errno));
flag_dump_final_insns = NULL;
}
else
{
const char *aname;
aname = (IDENTIFIER_POINTER
(DECL_ASSEMBLER_NAME (current_function_decl)));
fprintf (final_output, "\n;; Function (%s) %s\n\n", aname,
cfun->function_frequency == FUNCTION_FREQUENCY_HOT
? " (hot)"
: cfun->function_frequency == FUNCTION_FREQUENCY_UNLIKELY_EXECUTED
? " (unlikely executed)"
: "");
flag_dump_noaddr = flag_dump_unnumbered = 1;
for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
if (LABEL_P (insn))
INSN_UID (insn) = CODE_LABEL_NUMBER (insn);
else
INSN_UID (insn) = 0;
}
}
/* It is very important to decompose the RTL instruction chain here:
debug information keeps pointing into CODE_LABEL insns inside the function
@ -4323,6 +4358,27 @@ rest_of_clean_state (void)
next = NEXT_INSN (insn);
NEXT_INSN (insn) = NULL;
PREV_INSN (insn) = NULL;
if (final_output
&& (!NOTE_P (insn) ||
(NOTE_KIND (insn) != NOTE_INSN_VAR_LOCATION
&& NOTE_KIND (insn) != NOTE_INSN_BLOCK_BEG
&& NOTE_KIND (insn) != NOTE_INSN_BLOCK_END)))
print_rtl_single (final_output, insn);
}
if (final_output)
{
flag_dump_noaddr = save_noaddr;
flag_dump_unnumbered = save_unnumbered;
if (fclose (final_output))
{
error ("could not close final insn dump file %qs: %s",
flag_dump_final_insns, strerror (errno));
flag_dump_final_insns = NULL;
}
}
/* In case the function was not output,

View File

@ -1,3 +1,8 @@
2009-06-08 Alexandre Oliva <aoliva@redhat.com>
* options.c (gfc_post_options): Disable dump_parse_tree
during -fcompare-debug-second.
2009-06-07 Jerry DeLisle <jvdelisle@gcc.gnu.org>
PR fortran/40008

View File

@ -246,6 +246,9 @@ gfc_post_options (const char **pfilename)
if (flag_bounds_check)
gfc_option.rtcheck |= GFC_RTCHECK_BOUNDS;
if (flag_compare_debug)
gfc_option.dump_parse_tree = 0;
/* Verify the input file name. */
if (!filename || strcmp (filename, "-") == 0)
{

531
gcc/gcc.c
View File

@ -84,6 +84,18 @@ compilation is specified by a string called a "spec". */
#include "flags.h"
#include "opts.h"
#ifdef HAVE_MMAP_FILE
# include <sys/mman.h>
# ifdef HAVE_MINCORE
/* This is on Solaris. */
# include <sys/types.h>
# endif
#endif
#ifndef MAP_FAILED
# define MAP_FAILED ((void *)-1)
#endif
/* By default there is no special suffix for target executables. */
/* FIXME: when autoconf is fixed, remove the host check - dj */
#if defined(TARGET_EXECUTABLE_SUFFIX) && defined(HOST_EXECUTABLE_SUFFIX)
@ -391,6 +403,9 @@ static const char *replace_outfile_spec_function (int, const char **);
static const char *version_compare_spec_function (int, const char **);
static const char *include_spec_function (int, const char **);
static const char *print_asm_header_spec_function (int, const char **);
static const char *compare_debug_dump_opt_spec_function (int, const char **);
static const char *compare_debug_self_opt_spec_function (int, const char **);
static const char *compare_debug_auxbase_opt_spec_function (int, const char **);
/* The Specs Language
@ -853,7 +868,8 @@ static const char *cpp_debug_options = "%{d*}";
static const char *cc1_options =
"%{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\
%1 %{!Q:-quiet} -dumpbase %B %{d*} %{m*} %{a*}\
%{c|S:%{o*:-auxbase-strip %*}%{!o*:-auxbase %b}}%{!c:%{!S:-auxbase %b}}\
%{fcompare-debug-second:%:compare-debug-auxbase-opt(%b)} \
%{!fcompare-debug-second:%{c|S:%{o*:-auxbase-strip %*}%{!o*:-auxbase %b}}}%{!c:%{!S:-auxbase %b}} \
%{g*} %{O*} %{W*&pedantic*} %{w} %{std*&ansi&trigraphs}\
%{v:-version} %{pg:-p} %{p} %{f*} %{undef}\
%{Qn:-fno-ident} %{--help:--help}\
@ -875,9 +891,11 @@ static const char *asm_options =
static const char *invoke_as =
#ifdef AS_NEEDS_DASH_FOR_PIPED_INPUT
"%{!S:-o %|.s |\n as %(asm_options) %|.s %A }";
"%{fcompare-debug=*:%:compare-debug-dump-opt()}\
%{!S:-o %|.s |\n as %(asm_options) %|.s %A }";
#else
"%{!S:-o %|.s |\n as %(asm_options) %m.s %A }";
"%{fcompare-debug=*:%:compare-debug-dump-opt()}\
%{!S:-o %|.s |\n as %(asm_options) %m.s %A }";
#endif
/* Some compilers have limits on line lengths, and the multilib_select
@ -1673,6 +1691,9 @@ static const struct spec_function static_spec_functions[] =
{ "version-compare", version_compare_spec_function },
{ "include", include_spec_function },
{ "print-asm-header", print_asm_header_spec_function },
{ "compare-debug-dump-opt", compare_debug_dump_opt_spec_function },
{ "compare-debug-self-opt", compare_debug_self_opt_spec_function },
{ "compare-debug-auxbase-opt", compare_debug_auxbase_opt_spec_function },
#ifdef EXTRA_SPEC_FUNCTIONS
EXTRA_SPEC_FUNCTIONS
#endif
@ -3196,6 +3217,29 @@ static struct switchstr *switches;
static int n_switches;
/* Set to zero if -fcompare-debug is disabled, positive if it's
enabled and we're running the first compilation, negative if it's
enabled and we're running the second compilation. For most of the
time, it's in the range -1..1, but it can be temporarily set to 2
or 3 to indicate that the -fcompare-debug flags didn't come from
the command-line, but rather from the GCC_COMPARE_DEBUG environment
variable, until a synthesized -fcompare-debug flag is added to the
command line. */
int compare_debug;
/* Set to nonzero if we've seen the -fcompare-debug-second flag. */
int compare_debug_second;
/* Set to the flags that should be passed to the second compilation in
a -fcompare-debug compilation. */
const char *compare_debug_opt;
static struct switchstr *switches_debug_check[2];
static int n_switches_debug_check[2];
static char *debug_check_temp_file[2];
/* Language is one of three things:
1) The name of a real programming language.
@ -3790,6 +3834,38 @@ process_command (int argc, const char **argv)
print_multi_os_directory = 1;
else if (! strcmp (argv[i], "-print-sysroot-headers-suffix"))
print_sysroot_headers_suffix = 1;
else if (! strcmp (argv[i], "-fcompare-debug-second"))
{
compare_debug_second = 1;
n_switches++;
}
else if (! strcmp (argv[i], "-fno-compare-debug"))
{
argv[i] = "-fcompare-debug=";
goto compare_debug_with_arg;
}
else if (! strcmp (argv[i], "-fcompare-debug"))
{
argv[i] = "-fcompare-debug=-gtoggle";
goto compare_debug_with_arg;
}
#define OPT "-fcompare-debug="
else if (! strncmp (argv[i], OPT, sizeof (OPT) - 1))
{
const char *opt;
compare_debug_with_arg:
opt = argv[i] + sizeof (OPT) - 1;
#undef OPT
if (*opt)
compare_debug = 1;
else
compare_debug = -1;
if (compare_debug < 0)
compare_debug_opt = NULL;
else
compare_debug_opt = opt;
n_switches++;
}
else if (! strncmp (argv[i], "-Wa,", 4))
{
int prev, j;
@ -4147,6 +4223,29 @@ process_command (int argc, const char **argv)
use_pipes = 0;
}
if (!compare_debug)
{
const char *gcd = getenv ("GCC_COMPARE_DEBUG");
if (gcd && gcd[0] == '-')
{
compare_debug = 2;
compare_debug_opt = gcd;
n_switches++;
}
else if (gcd && *gcd && strcmp (gcd, "0"))
{
compare_debug = 3;
compare_debug_opt = "-gtoggle";
n_switches++;
}
}
else if (compare_debug < 0)
{
compare_debug = 0;
gcc_assert (!compare_debug_opt);
}
/* Set up the search paths. We add directories that we expect to
contain GNU Toolchain components before directories specified by
the machine description so that we will find GNU components (like
@ -4440,6 +4539,19 @@ process_command (int argc, const char **argv)
if (n_infiles == last_language_n_infiles && spec_lang != 0)
error ("warning: '-x %s' after last input file has no effect", spec_lang);
if (compare_debug == 2 || compare_debug == 3)
{
switches[n_switches].part1 = concat ("fcompare-debug=",
compare_debug_opt,
NULL);
switches[n_switches].args = 0;
switches[n_switches].live_cond = 0;
switches[n_switches].validated = 0;
switches[n_switches].ordering = 0;
n_switches++;
compare_debug = 1;
}
/* Ensure we only invoke each subprocess once. */
if (print_subprocess_help || print_help_list || print_version)
{
@ -4740,28 +4852,69 @@ do_self_spec (const char *spec)
if (argbuf_index > 0)
{
int i, first;
int i;
first = n_switches;
n_switches += argbuf_index;
switches = XRESIZEVEC (struct switchstr, switches, n_switches + 1);
switches = XRESIZEVEC (struct switchstr, switches,
n_switches + argbuf_index + 1);
switches[n_switches] = switches[first];
for (i = 0; i < argbuf_index; i++)
{
struct switchstr *sw;
const char *p = argbuf[i];
int c = *p;
/* Each switch should start with '-'. */
if (argbuf[i][0] != '-')
if (c != '-')
fatal ("switch '%s' does not start with '-'", argbuf[i]);
sw = &switches[i + first];
sw->part1 = &argbuf[i][1];
sw->args = 0;
p++;
c = *p;
sw = &switches[n_switches++];
sw->part1 = p;
sw->live_cond = 0;
sw->validated = 0;
sw->ordering = 0;
/* Deal with option arguments in separate argv elements. */
if ((SWITCH_TAKES_ARG (c) > (p[1] != 0))
|| WORD_SWITCH_TAKES_ARG (p))
{
int j = 0;
int n_args = WORD_SWITCH_TAKES_ARG (p);
if (n_args == 0)
{
/* Count only the option arguments in separate argv elements. */
n_args = SWITCH_TAKES_ARG (c) - (p[1] != 0);
}
if (i + n_args >= argbuf_index)
fatal ("argument to '-%s' is missing", p);
sw->args
= XNEWVEC (const char *, n_args + 1);
while (j < n_args)
sw->args[j++] = argbuf[++i];
/* Null-terminate the vector. */
sw->args[j] = 0;
}
else if (strchr (switches_need_spaces, c))
{
/* On some systems, ld cannot handle some options without
a space. So split the option from its argument. */
char *part1 = XNEWVEC (char, 2);
part1[0] = c;
part1[1] = '\0';
sw->part1 = part1;
sw->args = XNEWVEC (const char *, 2);
sw->args[0] = xstrdup (p+1);
sw->args[1] = 0;
}
else
sw->args = 0;
}
switches[n_switches].part1 = 0;
}
}
@ -4947,6 +5100,8 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part)
obstack_grow (&obstack, save_temps_prefix, save_temps_length);
else
obstack_grow (&obstack, input_basename, basename_length);
if (compare_debug < 0)
obstack_grow (&obstack, ".gk", 3);
arg_going = 1;
break;
@ -4955,6 +5110,8 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part)
obstack_grow (&obstack, save_temps_prefix, save_temps_length);
else
obstack_grow (&obstack, input_basename, suffixed_basename_length);
if (compare_debug < 0)
obstack_grow (&obstack, ".gk", 3);
arg_going = 1;
break;
@ -5100,6 +5257,12 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part)
suffix_length += strlen (TARGET_OBJECT_SUFFIX);
}
if (compare_debug < 0)
{
suffix = concat (".gk", suffix, NULL);
suffix_length += 3;
}
/* If -save-temps=obj and -o were specified, use that for the
temp file. */
if (save_temps_length)
@ -6190,18 +6353,19 @@ check_live_switch (int switchnum, int prefix_length)
const char *name = switches[switchnum].part1;
int i;
/* If we already processed this switch and determined if it was
live or not, return our past determination. */
if (switches[switchnum].live_cond != 0)
return ((switches[switchnum].live_cond & SWITCH_LIVE) != 0
&& (switches[switchnum].live_cond & SWITCH_FALSE) == 0
&& (switches[switchnum].live_cond & SWITCH_IGNORE) == 0);
/* In the common case of {<at-most-one-letter>*}, a negating
switch would always match, so ignore that case. We will just
send the conflicting switches to the compiler phase. */
if (prefix_length >= 0 && prefix_length <= 1)
return 1;
/* If we already processed this switch and determined if it was
live or not, return our past determination. */
if (switches[switchnum].live_cond != 0)
return ((switches[switchnum].live_cond & SWITCH_LIVE) != 0
&& (switches[switchnum].live_cond & SWITCH_FALSE) == 0);
/* Now search for duplicate in a manner that depends on the name. */
switch (*name)
{
@ -6398,6 +6562,125 @@ fatal_error (int signum)
kill (getpid (), signum);
}
/* Compare the contents of the two files named CMPFILE[0] and
CMPFILE[1]. Return zero if they're identical, nonzero
otherwise. */
static int
compare_files (char *cmpfile[])
{
int ret = 0;
FILE *temp[2] = { NULL, NULL };
int i;
#if HAVE_MMAP_FILE
{
size_t length[2];
void *map[2] = { NULL, NULL };
for (i = 0; i < 2; i++)
{
struct stat st;
if (stat (cmpfile[i], &st) < 0 || !S_ISREG (st.st_mode))
{
error ("%s: could not determine length of compare-debug file %s",
input_filename, cmpfile[i]);
ret = 1;
break;
}
length[i] = st.st_size;
}
if (!ret && length[0] != length[1])
{
error ("%s: -fcompare-debug failure (length)", input_filename);
ret = 1;
}
if (!ret)
for (i = 0; i < 2; i++)
{
int fd = open (cmpfile[i], O_RDONLY);
if (fd < 0)
{
error ("%s: could not open compare-debug file %s",
input_filename, cmpfile[i]);
ret = 1;
break;
}
map[i] = mmap (NULL, length[i], PROT_READ, MAP_PRIVATE, fd, 0);
close (fd);
if (map[i] == (void *) MAP_FAILED)
{
ret = -1;
break;
}
}
if (!ret)
{
if (memcmp (map[0], map[1], length[0]) != 0)
{
error ("%s: -fcompare-debug failure", input_filename);
ret = 1;
}
}
for (i = 0; i < 2; i++)
if (map[i])
munmap (map[i], length[i]);
if (ret >= 0)
return ret;
ret = 0;
}
#endif
for (i = 0; i < 2; i++)
{
temp[i] = fopen (cmpfile[i], "r");
if (!temp[i])
{
error ("%s: could not open compare-debug file %s",
input_filename, cmpfile[i]);
ret = 1;
break;
}
}
if (!ret && temp[0] && temp[1])
for (;;)
{
int c0, c1;
c0 = fgetc (temp[0]);
c1 = fgetc (temp[1]);
if (c0 != c1)
{
error ("%s: -fcompare-debug failure",
input_filename);
ret = 1;
break;
}
if (c0 == EOF)
break;
}
for (i = 1; i >= 0; i--)
{
if (temp[i])
fclose (temp[i]);
}
return ret;
}
extern int main (int, char **);
int
@ -6570,6 +6853,43 @@ main (int argc, char **argv)
for (i = 0; i < ARRAY_SIZE (driver_self_specs); i++)
do_self_spec (driver_self_specs[i]);
if (compare_debug)
{
enum save_temps save;
if (!compare_debug_second)
{
n_switches_debug_check[1] = n_switches;
switches_debug_check[1] = XDUPVEC (struct switchstr, switches,
n_switches + 1);
do_self_spec ("%:compare-debug-self-opt()");
n_switches_debug_check[0] = n_switches;
switches_debug_check[0] = switches;
n_switches = n_switches_debug_check[1];
switches = switches_debug_check[1];
}
/* Avoid crash when computing %j in this early. */
save = save_temps_flag;
save_temps_flag = SAVE_TEMPS_NONE;
compare_debug = -compare_debug;
do_self_spec ("%:compare-debug-self-opt()");
save_temps_flag = save;
if (!compare_debug_second)
{
n_switches_debug_check[1] = n_switches;
switches_debug_check[1] = switches;
compare_debug = -compare_debug;
n_switches = n_switches_debug_check[0];
switches = switches_debug_check[0];
}
}
/* If not cross-compiling, look for executables in the standard
places. */
if (*cross_compile == '0')
@ -6998,10 +7318,63 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
}
else
{
if (compare_debug)
{
if (debug_check_temp_file[0])
free (debug_check_temp_file[0]);
debug_check_temp_file[0] = NULL;
if (debug_check_temp_file[1])
free (debug_check_temp_file[1]);
debug_check_temp_file[1] = NULL;
}
value = do_spec (input_file_compiler->spec);
infiles[i].compiled = true;
if (value < 0)
this_file_error = 1;
else if (compare_debug && debug_check_temp_file[0])
{
if (verbose_flag)
error ("Recompiling with -fcompare-debug");
compare_debug = -compare_debug;
n_switches = n_switches_debug_check[1];
switches = switches_debug_check[1];
value = do_spec (input_file_compiler->spec);
compare_debug = -compare_debug;
n_switches = n_switches_debug_check[0];
switches = switches_debug_check[0];
if (value < 0)
{
error ("during -fcompare-debug recompilation");
this_file_error = 1;
}
gcc_assert (debug_check_temp_file[1]
&& strcmp (debug_check_temp_file[0],
debug_check_temp_file[1]));
if (verbose_flag)
error ("Comparing final insns dumps");
if (compare_files (debug_check_temp_file))
this_file_error = 1;
}
if (compare_debug)
{
if (debug_check_temp_file[0])
free (debug_check_temp_file[0]);
debug_check_temp_file[0] = NULL;
if (debug_check_temp_file[1])
free (debug_check_temp_file[1]);
debug_check_temp_file[1] = NULL;
}
}
}
@ -8286,3 +8659,125 @@ print_asm_header_spec_function (int arg ATTRIBUTE_UNUSED,
fflush (stdout);
return NULL;
}
/* %:compare-debug-dump-opt spec function. Save the last argument,
expected to be the last -fdump-final-insns option, or generate a
temporary. */
static const char *
compare_debug_dump_opt_spec_function (int arg,
const char **argv ATTRIBUTE_UNUSED)
{
const char *ret;
char *name;
int which;
if (arg != 0)
fatal ("too many arguments to %%:compare-debug-dump-opt");
if (!compare_debug)
return NULL;
do_spec_2 ("%{fdump-final-insns=*:%*}");
do_spec_1 (" ", 0, NULL);
if (argbuf_index > 0)
{
name = xstrdup (argv[argbuf_index - 1]);
ret = NULL;
}
else
{
#define OPT "-fdump-final-insns="
ret = "-fdump-final-insns=%g.gkd";
do_spec_2 (ret + sizeof (OPT) - 1);
do_spec_1 (" ", 0, NULL);
#undef OPT
gcc_assert (argbuf_index > 0);
name = xstrdup (argbuf[argbuf_index - 1]);
}
which = compare_debug < 0;
debug_check_temp_file[which] = name;
#if 0
error ("compare-debug: [%i]=\"%s\", ret %s", which, name, ret);
#endif
return ret;
}
static const char *debug_auxbase_opt;
/* %:compare-debug-self-opt spec function. Expands to the options
that are to be passed in the second compilation of
compare-debug. */
static const char *
compare_debug_self_opt_spec_function (int arg,
const char **argv ATTRIBUTE_UNUSED)
{
if (arg != 0)
fatal ("too many arguments to %%:compare-debug-self-opt");
if (compare_debug >= 0)
return NULL;
do_spec_2 ("%{c|S:%{o*:%*}}");
do_spec_1 (" ", 0, NULL);
if (argbuf_index > 0)
debug_auxbase_opt = concat ("-auxbase-strip ",
argbuf[argbuf_index - 1],
NULL);
else
debug_auxbase_opt = NULL;
return concat ("\
%<o %<MD %<MMD %<MF* %<MG %<MP %<MQ* %<MT* \
%<fdump-final-insns=* -w -S -o %j \
%{!fcompare-debug-second:-fcompare-debug-second} \
", compare_debug_opt, NULL);
}
/* %:compare-debug-auxbase-opt spec function. Expands to the auxbase
options that are to be passed in the second compilation of
compare-debug. It expects, as an argument, the basename of the
current input file name, with the .gk suffix appended to it. */
static const char *
compare_debug_auxbase_opt_spec_function (int arg,
const char **argv)
{
char *name;
int len;
if (arg == 0)
fatal ("too few arguments to %%:compare-debug-auxbase-opt");
if (arg != 1)
fatal ("too many arguments to %%:compare-debug-auxbase-opt");
if (compare_debug >= 0)
return NULL;
len = strlen (argv[0]);
if (len < 3 || strcmp (argv[0] + len - 3, ".gk") != 0)
fatal ("argument to %%:compare-debug-auxbase-opt does not end in .gk");
if (debug_auxbase_opt)
return debug_auxbase_opt;
#define OPT "-auxbase "
len -= 3;
name = (char*) xmalloc (sizeof (OPT) + len);
memcpy (name, OPT, sizeof (OPT) - 1);
memcpy (name + sizeof (OPT) - 1, argv[0], len);
name[sizeof (OPT) - 1 + len] = '\0';
return name;
}

View File

@ -1,3 +1,8 @@
2009-06-08 Alexandre Oliva <aoliva@redhat.com>
* objc-act.c (objc_init): Skip print_struct_values during
-fcompare-debug-second.
2009-06-03 Ian Lance Taylor <iant@google.com>
* Make-lang.in (cc1obj-checksum.o): Depend upon $(CONFIG_H) and

View File

@ -550,7 +550,7 @@ objc_init (void)
init_objc ();
if (print_struct_values)
if (print_struct_values && !flag_compare_debug)
generate_struct_by_value_array ();
return true;

View File

@ -1870,6 +1870,31 @@ process_options (void)
profile_flag = 0;
}
if (flag_gtoggle)
{
if (debug_info_level == DINFO_LEVEL_NONE)
debug_info_level = DINFO_LEVEL_NORMAL;
else
debug_info_level = DINFO_LEVEL_NONE;
}
if (flag_dump_final_insns)
{
FILE *final_output = fopen (flag_dump_final_insns, "w");
if (!final_output)
{
error ("could not open final insn dump file %qs: %s",
flag_dump_final_insns, strerror (errno));
flag_dump_final_insns = NULL;
}
else if (fclose (final_output))
{
error ("could not close zeroed insn dump file %qs: %s",
flag_dump_final_insns, strerror (errno));
flag_dump_final_insns = NULL;
}
}
/* A lot of code assumes write_symbols == NO_DEBUG if the debugging
level is 0. */
if (debug_info_level == DINFO_LEVEL_NONE)