diff options
author | aoliva <aoliva@138bc75d-0d04-0410-961f-82ee72b054a4> | 2009-06-08 07:46:02 +0000 |
---|---|---|
committer | aoliva <aoliva@138bc75d-0d04-0410-961f-82ee72b054a4> | 2009-06-08 07:46:02 +0000 |
commit | 71278019268ed867212742e9b787e4504522e244 (patch) | |
tree | 4b2c9076dc8fb9da65d110bb248b0fd2c5b7f0bc /gcc | |
parent | 561017b56be056393775e0713919a4f8c6210daf (diff) | |
download | gcc-71278019268ed867212742e9b787e4504522e244.tar.gz |
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.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@148271 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 29 | ||||
-rw-r--r-- | gcc/ada/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/ada/lib-writ.adb | 8 | ||||
-rw-r--r-- | gcc/common.opt | 16 | ||||
-rw-r--r-- | gcc/coverage.c | 2 | ||||
-rw-r--r-- | gcc/cp/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/cp/repo.c | 14 | ||||
-rw-r--r-- | gcc/doc/invoke.texi | 59 | ||||
-rw-r--r-- | gcc/final.c | 56 | ||||
-rw-r--r-- | gcc/fortran/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/fortran/options.c | 3 | ||||
-rw-r--r-- | gcc/gcc.c | 531 | ||||
-rw-r--r-- | gcc/objc/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/objc/objc-act.c | 2 | ||||
-rw-r--r-- | gcc/toplev.c | 25 |
15 files changed, 741 insertions, 25 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 80751b59ade..da9ddd720c4 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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 diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index d439a19c2f2..f6ca7d7d0ec 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -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 diff --git a/gcc/ada/lib-writ.adb b/gcc/ada/lib-writ.adb index 7ebfc7d3d51..f248c05cedc 100644 --- a/gcc/ada/lib-writ.adb +++ b/gcc/ada/lib-writ.adb @@ -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; diff --git a/gcc/common.opt b/gcc/common.opt index ee7e0bd7cea..f7248907e1a 100644 --- a/gcc/common.opt +++ b/gcc/common.opt @@ -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 diff --git a/gcc/coverage.c b/gcc/coverage.c index 9240241f9c1..47bc71e4df1 100644 --- a/gcc/coverage.c +++ b/gcc/coverage.c @@ -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) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 200ce5a64c9..12020e84bea 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -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 diff --git a/gcc/cp/repo.c b/gcc/cp/repo.c index 4501ba88a9d..0f531e2627c 100644 --- a/gcc/cp/repo.c +++ b/gcc/cp/repo.c @@ -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) diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index c669c21175f..99aa2caeb17 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -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 diff --git a/gcc/final.c b/gcc/final.c index 1fae1b4e238..b113bc90a39 100644 --- a/gcc/final.c +++ b/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, diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index 6192c375793..c8515fc4cd7 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -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 diff --git a/gcc/fortran/options.c b/gcc/fortran/options.c index 2d899f546ab..3654e9261a1 100644 --- a/gcc/fortran/options.c +++ b/gcc/fortran/options.c @@ -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) { diff --git a/gcc/gcc.c b/gcc/gcc.c index 7d211ca2dd5..d652530b6a1 100644 --- a/gcc/gcc.c +++ b/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; +} diff --git a/gcc/objc/ChangeLog b/gcc/objc/ChangeLog index afe61caba08..ec012fd7111 100644 --- a/gcc/objc/ChangeLog +++ b/gcc/objc/ChangeLog @@ -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 diff --git a/gcc/objc/objc-act.c b/gcc/objc/objc-act.c index d4624bb5439..23715cba486 100644 --- a/gcc/objc/objc-act.c +++ b/gcc/objc/objc-act.c @@ -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; diff --git a/gcc/toplev.c b/gcc/toplev.c index eb47d99b8ed..267df5906ec 100644 --- a/gcc/toplev.c +++ b/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) |