mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-23 04:10:26 +08:00
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:
parent
cdb884681d
commit
2153915d0a
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
56
gcc/final.c
56
gcc/final.c
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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
531
gcc/gcc.c
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
25
gcc/toplev.c
25
gcc/toplev.c
@ -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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user