OSDN Git Service

* configure.ac (--with-specs): New option.
[pf3gnuchains/gcc-fork.git] / gcc / gcc.c
index 1046802..ad69de7 100644 (file)
--- a/gcc/gcc.c
+++ b/gcc/gcc.c
@@ -1,13 +1,13 @@
 /* Compiler driver program that can handle many languages.
    Copyright (C) 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
+   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
    Free Software Foundation, Inc.
 
 This file is part of GCC.
 
 GCC is free software; you can redistribute it and/or modify it under
 the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 2, or (at your option) any later
+Software Foundation; either version 3, or (at your option) any later
 version.
 
 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
@@ -16,12 +16,8 @@ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 for more details.
 
 You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING.  If not, write to the Free
-Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301, USA.
-
-This paragraph is here to try to keep Sun CC from dying.
-The number of chars here seems crucial!!!!  */
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
 
 /* This program is the user interface to the C compiler and possibly to
 other compilers.  It is used because compilation is a complicated procedure
@@ -88,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)
@@ -127,6 +135,9 @@ static const char dir_separator_str[] = { DIR_SEPARATOR, 0 };
 /* Flag set by cppspec.c to 1.  */
 int is_cpp_driver;
 
+/* Flag set to nonzero if an @file argument has been supplied to gcc.  */
+static bool at_file_supplied;
+
 /* Flag saying to pass the greatest exit code returned by a sub-process
    to the calling program.  */
 static int pass_exit_codes;
@@ -153,6 +164,8 @@ static const char *print_prog_name = NULL;
 
 static int print_multi_directory;
 
+static int print_sysroot;
+
 /* Flag saying to print the relative path we'd use to
    find OS libraries given the current compiler flags.  */
 
@@ -168,6 +181,10 @@ static int print_multi_lib;
 
 static int print_help_list;
 
+/* Flag saying to print the version of gcc and its sub-processes.  */
+
+static int print_version;
+
 /* Flag saying to print the sysroot suffix used for searching for
    headers.  */
 
@@ -193,6 +210,10 @@ static int print_subprocess_help;
 
 static int report_times;
 
+/* Whether we should report subprocess execution times to a file.  */
+
+FILE *report_times_to_file = NULL;
+
 /* Nonzero means place this string before uses of /, so that include
    and library files can be found in an alternate location.  */
 
@@ -217,7 +238,15 @@ static const char *target_sysroot_hdrs_suffix = 0;
 /* Nonzero means write "temp" files in source directory
    and use the source file's name in them, and don't delete them.  */
 
-static int save_temps_flag;
+static enum save_temps {
+  SAVE_TEMPS_NONE,             /* no -save-temps */
+  SAVE_TEMPS_CWD,              /* -save-temps in current directory */
+  SAVE_TEMPS_OBJ               /* -save-temps in object directory */
+} save_temps_flag;
+
+/* Output file to use to get the object directory for -save-temps=obj  */
+static char *save_temps_prefix = 0;
+static size_t save_temps_length = 0;
 
 /* Nonzero means pass multiple source files to the compiler at one time.  */
 
@@ -255,10 +284,12 @@ static const char *cross_compile = "0";
    switch.  The only case we support now is simply appending or deleting a
    string to or from the end of the first part of the configuration name.  */
 
+enum add_del {ADD, DELETE};
+
 static const struct modify_target
 {
   const char *const sw;
-  const enum add_del {ADD, DELETE} add_del;
+  const enum add_del add_del;
   const char *const str;
 }
 modify_target[] = MODIFY_TARGET_NAME;
@@ -283,18 +314,28 @@ static struct obstack obstack;
 
 static struct obstack collect_obstack;
 
+/* This is a list of a wrapper program and its arguments.
+   e.g. wrapper_string of "strace,-c"
+   will cause all programs to run as
+       strace -c program arguments
+   instead of just
+       program arguments */
+static const char  *wrapper_string;
+
 /* Forward declaration for prototypes.  */
 struct path_prefix;
 struct prefix_list;
 
 static void init_spec (void);
 static void store_arg (const char *, int, int);
+static void insert_wrapper (const char *);
 static char *load_specs (const char *);
 static void read_specs (const char *, int);
 static void set_spec (const char *, const char *);
 static struct compiler *lookup_compiler (const char *, size_t, const char *);
 static char *build_search_list (const struct path_prefix *, const char *,
                                bool, bool);
+static void xputenv (const char *);
 static void putenv_from_prefixes (const struct path_prefix *, const char *,
                                  bool);
 static int access_check (const char *, int);
@@ -362,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 **);
 \f
 /* The Specs Language
 
@@ -382,7 +426,8 @@ or with constant text in a single argument.
  %i     substitute the name of the input file being processed.
  %b     substitute the basename of the input file being processed.
        This is the substring up to (and not including) the last period
-       and not including the directory.
+       and not including the directory unless -save-temps was specified
+       to put temporaries in a different location.
  %B    same as %b, but include the file suffix (text after the last period).
  %gSUFFIX
        substitute a file name that has suffix SUFFIX and is chosen
@@ -425,7 +470,7 @@ or with constant text in a single argument.
         it is subsequently output with %*. SUFFIX is terminated by the next
         space or %.
  %d    marks the argument containing or following the %d as a
-       temporary file name, so that that file will be deleted if CC exits
+       temporary file name, so that that file will be deleted if GCC exits
        successfully.  Unlike %g, this contributes no text to the argument.
  %w    marks the argument containing or following the %w as the
        "output file" of this compilation.  This puts the argument
@@ -494,12 +539,12 @@ or with constant text in a single argument.
        argument vector in the usual fashion.  The function returns
        a string which is processed as if it had appeared literally
        as part of the current spec.
- %{S}   substitutes the -S switch, if that switch was given to CC.
+ %{S}   substitutes the -S switch, if that switch was given to GCC.
        If that switch was not specified, this substitutes nothing.
        Here S is a metasyntactic variable.
- %{S*}  substitutes all the switches specified to CC whose names start
+ %{S*}  substitutes all the switches specified to GCC whose names start
        with -S.  This is used for -o, -I, etc; switches that take
-       arguments.  CC considers `-o foo' as being one switch whose
+       arguments.  GCC considers `-o foo' as being one switch whose
        name starts with `o'.  %{o*} would substitute this text,
        including the space; thus, two arguments would be generated.
  %{S*&T*} likewise, but preserve order of S and T options (the order
@@ -507,10 +552,10 @@ or with constant text in a single argument.
        of ampersand-separated variables; for each the wild card is
        optional.  Useful for CPP as %{D*&U*&A*}.
 
- %{S:X}   substitutes X, if the -S switch was given to CC.
- %{!S:X}  substitutes X, if the -S switch was NOT given to CC.
+ %{S:X}   substitutes X, if the -S switch was given to GCC.
+ %{!S:X}  substitutes X, if the -S switch was NOT given to GCC.
  %{S*:X}  substitutes X if one or more switches whose names start
-          with -S was given to CC.  Normally X is substituted only
+          with -S was given to GCC.  Normally X is substituted only
           once, no matter how many such switches appeared.  However,
           if %* appears somewhere in X, then X will be substituted
           once for each matching switch, with the %* replaced by the
@@ -519,14 +564,14 @@ or with constant text in a single argument.
  %{!.S:X} substitutes X, if NOT processing a file with suffix S.
  %{,S:X}  substitutes X, if processing a file which will use spec S.
  %{!,S:X} substitutes X, if NOT processing a file which will use spec S.
-         
- %{S|T:X} substitutes X if either -S or -T was given to CC.  This may be
+
+ %{S|T:X} substitutes X if either -S or -T was given to GCC.  This may be
          combined with '!', '.', ',', and '*' as above binding stronger
          than the OR.
          If %* appears in X, all of the alternatives must be starred, and
          only the first matching alternative is substituted.
- %{S:X;   if S was given to CC, substitutes X;
-   T:Y;   else if T was given to CC, substitutes Y;
+ %{S:X;   if S was given to GCC, substitutes X;
+   T:Y;   else if T was given to GCC, substitutes Y;
     :D}   else substitutes D.  There can be as many clauses as you need.
           This may be combined with '.', '!', ',', '|', and '*' as above.
 
@@ -550,15 +595,15 @@ The character | at the beginning of the predicate text is used to indicate
 that a command should be piped to the following command, but only if -pipe
 is specified.
 
-Note that it is built into CC which switches take arguments and which
+Note that it is built into GCC which switches take arguments and which
 do not.  You might think it would be useful to generalize this to
 allow each compiler's spec to say which switches take arguments.  But
-this cannot be done in a consistent fashion.  CC cannot even decide
+this cannot be done in a consistent fashion.  GCC cannot even decide
 which input files have been specified without knowing which switches
 take arguments, and it must know which input files to compile in order
 to tell which compilers to run.
 
-CC also knows implicitly that arguments starting in `-l' are to be
+GCC also knows implicitly that arguments starting in `-l' are to be
 treated as compiler output files, and passed to the linker in their
 proper position among the other output files.  */
 \f
@@ -639,9 +684,15 @@ proper position among the other output files.  */
 #endif
 
 /* config.h can define SWITCHES_NEED_SPACES to control which options
-   require spaces between the option and the argument.  */
+   require spaces between the option and the argument.
+
+   We define SWITCHES_NEED_SPACES to include "o" by default.  This
+   causes "-ofoo.o" to be split into "-o foo.o" during the initial
+   processing of the command-line, before being seen by the specs
+   machinery.  This makes sure we record "foo.o" as the temporary file
+   to be deleted in the case of error, rather than "-ofoo.o".  */
 #ifndef SWITCHES_NEED_SPACES
-#define SWITCHES_NEED_SPACES ""
+#define SWITCHES_NEED_SPACES "o"
 #endif
 
 /* config.h can define ENDFILE_SPEC to override the default crtn files.  */
@@ -653,21 +704,27 @@ proper position among the other output files.  */
 #define LINKER_NAME "collect2"
 #endif
 
+#ifdef HAVE_AS_DEBUG_PREFIX_MAP
+#define ASM_MAP " %{fdebug-prefix-map=*:--debug-prefix-map %*}"
+#else
+#define ASM_MAP ""
+#endif
+
 /* Define ASM_DEBUG_SPEC to be a spec suitable for translating '-g'
    to the assembler.  */
 #ifndef ASM_DEBUG_SPEC
 # if defined(DBX_DEBUGGING_INFO) && defined(DWARF2_DEBUGGING_INFO) \
      && defined(HAVE_AS_GDWARF2_DEBUG_FLAG) && defined(HAVE_AS_GSTABS_DEBUG_FLAG)
-#  define ASM_DEBUG_SPEC                                       \
-      (PREFERRED_DEBUGGING_TYPE == DBX_DEBUG                   \
-       ? "%{gdwarf-2*:--gdwarf2}%{!gdwarf-2*:%{g*:--gstabs}}"  \
-       : "%{gstabs*:--gstabs}%{!gstabs*:%{g*:--gdwarf2}}")
+#  define ASM_DEBUG_SPEC                                               \
+      (PREFERRED_DEBUGGING_TYPE == DBX_DEBUG                           \
+       ? "%{!g0:%{gdwarf-2*:--gdwarf2}%{!gdwarf-2*:%{g*:--gstabs}}}" ASM_MAP   \
+       : "%{!g0:%{gstabs*:--gstabs}%{!gstabs*:%{g*:--gdwarf2}}}" ASM_MAP)
 # else
 #  if defined(DBX_DEBUGGING_INFO) && defined(HAVE_AS_GSTABS_DEBUG_FLAG)
-#   define ASM_DEBUG_SPEC "%{g*:--gstabs}"
+#   define ASM_DEBUG_SPEC "%{g*:%{!g0:--gstabs}}" ASM_MAP
 #  endif
 #  if defined(DWARF2_DEBUGGING_INFO) && defined(HAVE_AS_GDWARF2_DEBUG_FLAG)
-#   define ASM_DEBUG_SPEC "%{g*:--gdwarf2}"
+#   define ASM_DEBUG_SPEC "%{g*:%{!g0:--gdwarf2}}" ASM_MAP
 #  endif
 # endif
 #endif
@@ -700,20 +757,41 @@ proper position among the other output files.  */
 #endif
 #endif
 
+#ifndef LINK_BUILDID_SPEC
+# if defined(HAVE_LD_BUILDID) && defined(ENABLE_LD_BUILDID)
+#  define LINK_BUILDID_SPEC "%{!r:--build-id} "
+# endif
+#endif
+
+
 /* -u* was put back because both BSD and SysV seem to support it.  */
 /* %{static:} simply prevents an error message if the target machine
    doesn't handle -static.  */
 /* We want %{T*} after %{L*} and %D so that it can be used to specify linker
    scripts which exist in user specified directories, or in standard
    directories.  */
+/* We pass any -flto and -fwhopr flags on to the linker, which is expected
+   to understand them.  In practice, this means it had better be collect2.  */
 #ifndef LINK_COMMAND_SPEC
 #define LINK_COMMAND_SPEC "\
 %{!fsyntax-only:%{!c:%{!M:%{!MM:%{!E:%{!S:\
-    %(linker) %l " LINK_PIE_SPEC "%X %{o*} %{A} %{d} %{e*} %{m} %{N} %{n} %{r}\
+    %(linker) \
+    %{fuse-linker-plugin: \
+    -plugin %(linker_plugin_file) \
+    -plugin-opt=%(lto_wrapper) \
+    -plugin-opt=%(lto_gcc) \
+    %{static|static-libgcc:-plugin-opt=-pass-through=%(lto_libgcc)}    \
+    %{static:-plugin-opt=-pass-through=-lc}    \
+    %{O*:-plugin-opt=-O%*} \
+    %{w:-plugin-opt=-w} \
+    %{f*:-plugin-opt=-f%*} \
+    } \
+    %{flto} %{fwhopr} %l " LINK_PIE_SPEC \
+   "%X %{o*} %{A} %{d} %{e*} %{m} %{N} %{n} %{r}\
     %{s} %{t} %{u*} %{x} %{z} %{Z} %{!A:%{!nostdlib:%{!nostartfiles:%S}}}\
     %{static:} %{L*} %(mfwrap) %(link_libgcc) %o\
-    %{fopenmp:%:include(libgomp.spec)%(link_gomp)} %(mflib)\
-    %{fprofile-arcs|fprofile-generate|coverage:-lgcov}\
+    %{fopenmp|ftree-parallelize-loops=*:%:include(libgomp.spec)%(link_gomp)} %(mflib)\
+    %{fprofile-arcs|fprofile-generate*|coverage:-lgcov}\
     %{!nostdlib:%{!nodefaultlibs:%(link_ssp) %(link_gcc_c_sequence)}}\
     %{!A:%{!nostdlib:%{!nostartfiles:%E}}} %{T*} }}}}}}"
 #endif
@@ -757,6 +835,10 @@ static const char *endfile_spec = ENDFILE_SPEC;
 static const char *startfile_spec = STARTFILE_SPEC;
 static const char *switches_need_spaces = SWITCHES_NEED_SPACES;
 static const char *linker_name_spec = LINKER_NAME;
+static const char *linker_plugin_file_spec = "";
+static const char *lto_wrapper_spec = "";
+static const char *lto_gcc_spec = "";
+static const char *lto_libgcc_spec = "";
 static const char *link_command_spec = LINK_COMMAND_SPEC;
 static const char *link_libgcc_spec = LINK_LIBGCC_SPEC;
 static const char *startfile_prefix_spec = STARTFILE_PREFIX_SPEC;
@@ -799,18 +881,19 @@ static const char *cpp_unique_options =
    in turn cause preprocessor symbols to be defined specially.  */
 static const char *cpp_options =
 "%(cpp_unique_options) %1 %{m*} %{std*&ansi&trigraphs} %{W*&pedantic*} %{w}\
- %{f*} %{g*:%{!g0:%{!fno-working-directory:-fworking-directory}}} %{O*}\
- %{undef} %{save-temps:-fpch-preprocess}";
+ %{f*} %{g*:%{!g0:%{g*} %{!fno-working-directory:-fworking-directory}}} %{O*}\
+ %{undef} %{save-temps*:-fpch-preprocess}";
 
 /* This contains cpp options which are not passed when the preprocessor
    output will be used by another program.  */
 static const char *cpp_debug_options = "%{d*}";
 
-/* NB: This is shared amongst all front-ends.  */
+/* NB: This is shared amongst all front-ends, except for Ada.  */
 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}\
@@ -822,14 +905,25 @@ static const char *cc1_options =
  %{coverage:-fprofile-arcs -ftest-coverage}";
 
 static const char *asm_options =
-"%{ftarget-help:%:print-asm-header()} \
-%a %Y %{c:%W{o*}%{!o*:-o %w%b%O}}%{!c:-o %d%w%u%O}";
+"%{--target-help:%:print-asm-header()} "
+#if HAVE_GNU_AS
+/* If GNU AS is used, then convert -w (no warnings), -I, and -v
+   to the assembler equivalents.  */
+"%{v} %{w:-W} %{I*} "
+#endif
+"%a %Y %{c:%W{o*}%{!o*:-o %w%b%O}}%{!c:-o %d%w%u%O}";
 
 static const char *invoke_as =
 #ifdef AS_NEEDS_DASH_FOR_PIPED_INPUT
-"%{!S:-o %|.s |\n as %(asm_options) %|.s %A }";
+"%{!fwpa:\
+   %{fcompare-debug=*|fdump-final-insns=*:%:compare-debug-dump-opt()}\
+   %{!S:-o %|.s |\n as %(asm_options) %|.s %A }\
+  }";
 #else
-"%{!S:-o %|.s |\n as %(asm_options) %m.s %A }";
+"%{!fwpa:\
+   %{fcompare-debug=*|fdump-final-insns=*:%: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
@@ -856,11 +950,12 @@ static const char *const multilib_defaults_raw[] = MULTILIB_DEFAULTS;
 /* Adding -fopenmp should imply pthreads.  This is particularly important
    for targets that use different start files and suchlike.  */
 #ifndef GOMP_SELF_SPECS
-#define GOMP_SELF_SPECS "%{fopenmp: -pthread}"
+#define GOMP_SELF_SPECS "%{fopenmp|ftree-parallelize-loops=*: -pthread}"
 #endif
 
 static const char *const driver_self_specs[] = {
-  DRIVER_SELF_SPECS, GOMP_SELF_SPECS
+  "%{fdump-final-insns:-fdump-final-insns=.} %<fdump-final-insns",
+  DRIVER_SELF_SPECS, CONFIGURE_SPECS, GOMP_SELF_SPECS
 };
 
 #ifndef OPTION_DEFAULT_SPECS
@@ -895,7 +990,7 @@ static struct user_specs *user_specs_head, *user_specs_tail;
 #ifdef HAVE_TARGET_EXECUTABLE_SUFFIX
 /* This defines which switches stop a full compilation.  */
 #define DEFAULT_SWITCH_CURTAILS_COMPILATION(CHAR) \
-  ((CHAR) == 'c' || (CHAR) == 'S')
+  ((CHAR) == 'c' || (CHAR) == 'S' || (CHAR) == 'E')
 
 #ifndef SWITCH_CURTAILS_COMPILATION
 #define SWITCH_CURTAILS_COMPILATION(CHAR) \
@@ -952,11 +1047,14 @@ static const struct compiler default_compilers[] =
   {".c++", "#C++", 0, 0, 0}, {".C", "#C++", 0, 0, 0},
   {".CPP", "#C++", 0, 0, 0}, {".ii", "#C++", 0, 0, 0},
   {".ads", "#Ada", 0, 0, 0}, {".adb", "#Ada", 0, 0, 0},
-  {".f", "#Fortran", 0, 0, 0}, {".for", "#Fortran", 0, 0, 0},
-  {".fpp", "#Fortran", 0, 0, 0}, {".F", "#Fortran", 0, 0, 0},
-  {".FOR", "#Fortran", 0, 0, 0}, {".FPP", "#Fortran", 0, 0, 0},
-  {".f90", "#Fortran", 0, 0, 0}, {".f95", "#Fortran", 0, 0, 0},
-  {".F90", "#Fortran", 0, 0, 0}, {".F95", "#Fortran", 0, 0, 0},
+  {".f", "#Fortran", 0, 0, 0}, {".F", "#Fortran", 0, 0, 0},
+  {".for", "#Fortran", 0, 0, 0}, {".FOR", "#Fortran", 0, 0, 0},
+  {".ftn", "#Fortran", 0, 0, 0}, {".FTN", "#Fortran", 0, 0, 0},
+  {".fpp", "#Fortran", 0, 0, 0}, {".FPP", "#Fortran", 0, 0, 0},
+  {".f90", "#Fortran", 0, 0, 0}, {".F90", "#Fortran", 0, 0, 0},
+  {".f95", "#Fortran", 0, 0, 0}, {".F95", "#Fortran", 0, 0, 0},
+  {".f03", "#Fortran", 0, 0, 0}, {".F03", "#Fortran", 0, 0, 0},
+  {".f08", "#Fortran", 0, 0, 0}, {".F08", "#Fortran", 0, 0, 0},
   {".r", "#Ratfor", 0, 0, 0},
   {".p", "#Pascal", 0, 0, 0}, {".pas", "#Pascal", 0, 0, 0},
   {".java", "#Java", 0, 0, 0}, {".class", "#Java", 0, 0, 0},
@@ -971,17 +1069,17 @@ static const struct compiler default_compilers[] =
           %{traditional|ftraditional:\
 %eGNU C no longer supports -traditional without -E}\
        %{!combine:\
-         %{save-temps|traditional-cpp|no-integrated-cpp:%(trad_capable_cpp) \
-               %(cpp_options) -o %{save-temps:%b.i} %{!save-temps:%g.i} \n\
-                   cc1 -fpreprocessed %{save-temps:%b.i} %{!save-temps:%g.i} \
+         %{save-temps*|traditional-cpp|no-integrated-cpp:%(trad_capable_cpp) \
+               %(cpp_options) -o %{save-temps*:%b.i} %{!save-temps*:%g.i} \n\
+                   cc1 -fpreprocessed %{save-temps*:%b.i} %{!save-temps*:%g.i} \
                        %(cc1_options)}\
-         %{!save-temps:%{!traditional-cpp:%{!no-integrated-cpp:\
+         %{!save-temps*:%{!traditional-cpp:%{!no-integrated-cpp:\
                cc1 %(cpp_unique_options) %(cc1_options)}}}\
           %{!fsyntax-only:%(invoke_as)}} \
       %{combine:\
-         %{save-temps|traditional-cpp|no-integrated-cpp:%(trad_capable_cpp) \
-               %(cpp_options) -o %{save-temps:%b.i} %{!save-temps:%g.i}}\
-         %{!save-temps:%{!traditional-cpp:%{!no-integrated-cpp:\
+         %{save-temps*|traditional-cpp|no-integrated-cpp:%(trad_capable_cpp) \
+               %(cpp_options) -o %{save-temps*:%b.i} %{!save-temps*:%g.i}}\
+         %{!save-temps*:%{!traditional-cpp:%{!no-integrated-cpp:\
                cc1 %(cpp_unique_options) %(cc1_options)}}\
                 %{!fsyntax-only:%(invoke_as)}}}}}}", 0, 1, 1},
   {"-",
@@ -993,13 +1091,13 @@ static const struct compiler default_compilers[] =
       external preprocessor if -save-temps is given.  */
      "%{E|M|MM:%(trad_capable_cpp) %(cpp_options) %(cpp_debug_options)}\
       %{!E:%{!M:%{!MM:\
-         %{save-temps|traditional-cpp|no-integrated-cpp:%(trad_capable_cpp) \
-               %(cpp_options) -o %{save-temps:%b.i} %{!save-temps:%g.i} \n\
-                   cc1 -fpreprocessed %{save-temps:%b.i} %{!save-temps:%g.i} \
+         %{save-temps*|traditional-cpp|no-integrated-cpp:%(trad_capable_cpp) \
+               %(cpp_options) -o %{save-temps*:%b.i} %{!save-temps*:%g.i} \n\
+                   cc1 -fpreprocessed %{save-temps*:%b.i} %{!save-temps*:%g.i} \
                        %(cc1_options)\
                         -o %g.s %{!o*:--output-pch=%i.gch}\
                         %W{o*:--output-pch=%*}%V}\
-         %{!save-temps:%{!traditional-cpp:%{!no-integrated-cpp:\
+         %{!save-temps*:%{!traditional-cpp:%{!no-integrated-cpp:\
                cc1 %(cpp_unique_options) %(cc1_options)\
                     -o %g.s %{!o*:--output-pch=%i.gch}\
                     %W{o*:--output-pch=%*}%V}}}}}}", 0, 0, 0},
@@ -1009,15 +1107,16 @@ static const struct compiler default_compilers[] =
   {".s", "@assembler", 0, 1, 0},
   {"@assembler",
    "%{!M:%{!MM:%{!E:%{!S:as %(asm_debug) %(asm_options) %i %A }}}}", 0, 1, 0},
+  {".sx", "@assembler-with-cpp", 0, 1, 0},
   {".S", "@assembler-with-cpp", 0, 1, 0},
   {"@assembler-with-cpp",
 #ifdef AS_NEEDS_DASH_FOR_PIPED_INPUT
-   "%(trad_capable_cpp) -lang-asm %(cpp_options)\
+   "%(trad_capable_cpp) -lang-asm %(cpp_options) -fno-directives-only\
       %{E|M|MM:%(cpp_debug_options)}\
       %{!M:%{!MM:%{!E:%{!S:-o %|.s |\n\
        as %(asm_debug) %(asm_options) %|.s %A }}}}"
 #else
-   "%(trad_capable_cpp) -lang-asm %(cpp_options)\
+   "%(trad_capable_cpp) -lang-asm %(cpp_options) -fno-directives-only\
       %{E|M|MM:%(cpp_debug_options)}\
       %{!M:%{!MM:%{!E:%{!S:-o %|.s |\n\
        as %(asm_debug) %(asm_options) %m.s %A }}}}"
@@ -1110,6 +1209,7 @@ static const struct option_map option_map[] =
    {"--library-directory", "-L", "a"},
    {"--machine", "-m", "aj"},
    {"--machine-", "-m", "*j"},
+   {"--no-canonical-prefixes", "-no-canonical-prefixes", 0},
    {"--no-integrated-cpp", "-no-integrated-cpp", 0},
    {"--no-line-commands", "-P", 0},
    {"--no-precompiled-includes", "-noprecomp", 0},
@@ -1135,6 +1235,7 @@ static const struct option_map option_map[] =
    {"--print-multi-directory", "-print-multi-directory", 0},
    {"--print-multi-os-directory", "-print-multi-os-directory", 0},
    {"--print-prog-name", "-print-prog-name=", "aj"},
+   {"--print-sysroot", "-print-sysroot", 0},
    {"--print-sysroot-headers-suffix", "-print-sysroot-headers-suffix", 0},
    {"--profile", "-p", 0},
    {"--profile-blocks", "-a", 0},
@@ -1176,7 +1277,7 @@ static const struct {
 
 /* Translate the options described by *ARGCP and *ARGVP.
    Make a new vector and store it back in *ARGVP,
-   and store its length in *ARGVC.  */
+   and store its length in *ARGCP.  */
 
 static void
 translate_options (int *argcp, const char *const **argvp)
@@ -1185,7 +1286,7 @@ translate_options (int *argcp, const char *const **argvp)
   int argc = *argcp;
   const char *const *argv = *argvp;
   int newvsize = (argc + 2) * 2 * sizeof (const char *);
-  const char **newv = xmalloc (newvsize);
+  const char **newv = XNEWVAR (const char *, newvsize);
   int newindex = 0;
 
   i = 0;
@@ -1215,7 +1316,7 @@ translate_options (int *argcp, const char *const **argvp)
                }
 
              newvsize += spaces * sizeof (const char *);
-             newv =  xrealloc (newv, newvsize);
+             newv =  XRESIZEVAR (const char *, newv, newvsize);
 
              sp = target_option_translations[tott_idx].replacements;
              np = xstrdup (sp);
@@ -1500,8 +1601,6 @@ static const char *const standard_startfile_prefix = STANDARD_STARTFILE_PREFIX;
 /* For native compilers, these are well-known paths containing
    components that may be provided by the system.  For cross
    compilers, these paths are not used.  */
-static const char *const standard_exec_prefix_1 = "/usr/libexec/gcc/";
-static const char *const standard_exec_prefix_2 = "/usr/lib/gcc/";
 static const char *md_exec_prefix = MD_EXEC_PREFIX;
 static const char *md_startfile_prefix = MD_STARTFILE_PREFIX;
 static const char *md_startfile_prefix_1 = MD_STARTFILE_PREFIX_1;
@@ -1582,6 +1681,10 @@ static struct spec_list static_specs[] =
   INIT_STATIC_SPEC ("multilib_exclusions",     &multilib_exclusions),
   INIT_STATIC_SPEC ("multilib_options",                &multilib_options),
   INIT_STATIC_SPEC ("linker",                  &linker_name_spec),
+  INIT_STATIC_SPEC ("linker_plugin_file",      &linker_plugin_file_spec),
+  INIT_STATIC_SPEC ("lto_wrapper",             &lto_wrapper_spec),
+  INIT_STATIC_SPEC ("lto_gcc",                 &lto_gcc_spec),
+  INIT_STATIC_SPEC ("lto_libgcc",              &lto_libgcc_spec),
   INIT_STATIC_SPEC ("link_libgcc",             &link_libgcc_spec),
   INIT_STATIC_SPEC ("md_exec_prefix",          &md_exec_prefix),
   INIT_STATIC_SPEC ("md_startfile_prefix",     &md_startfile_prefix),
@@ -1620,6 +1723,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
@@ -1689,8 +1795,7 @@ init_spec (void)
     notice ("Using built-in specs.\n");
 
 #ifdef EXTRA_SPECS
-  extra_specs = xcalloc (sizeof (struct spec_list),
-                        ARRAY_SIZE (extra_specs_1));
+  extra_specs = XCNEWVEC (struct spec_list, ARRAY_SIZE (extra_specs_1));
 
   for (i = ARRAY_SIZE (extra_specs_1) - 1; i >= 0; i--)
     {
@@ -1704,10 +1809,6 @@ init_spec (void)
     }
 #endif
 
-  /* Initialize here, not in definition.  The IRIX 6 O32 cc sometimes chokes
-     on ?: in file-scope variable initializations.  */
-  asm_debug = ASM_DEBUG_SPEC;
-
   for (i = ARRAY_SIZE (static_specs) - 1; i >= 0; i--)
     {
       sl = &static_specs[i];
@@ -1809,9 +1910,16 @@ init_spec (void)
     asm_spec = XOBFINISH (&obstack, const char *);
   }
 #endif
-#ifdef LINK_EH_SPEC
+
+#if defined LINK_EH_SPEC || defined LINK_BUILDID_SPEC
+# ifdef LINK_BUILDID_SPEC
+  /* Prepend LINK_BUILDID_SPEC to whatever link_spec we had before.  */
+  obstack_grow (&obstack, LINK_BUILDID_SPEC, sizeof(LINK_BUILDID_SPEC) - 1);
+# endif
+# ifdef LINK_EH_SPEC
   /* Prepend LINK_EH_SPEC to whatever link_spec we had before.  */
   obstack_grow (&obstack, LINK_EH_SPEC, sizeof(LINK_EH_SPEC) - 1);
+# endif
   obstack_grow0 (&obstack, link_spec, strlen (link_spec));
   link_spec = XOBFINISH (&obstack, const char *);
 #endif
@@ -1874,7 +1982,7 @@ set_spec (const char *name, const char *spec)
 
   /* Free the old spec.  */
   if (old_spec && sl->alloc_p)
-    free ((void *) old_spec);
+    free (CONST_CAST(char *, old_spec));
 
   sl->alloc_p = 1;
 }
@@ -1898,7 +2006,7 @@ static int argbuf_index;
 
 static int have_o_argbuf_index = 0;
 
-/* Were the options -c or -S passed.  */
+/* Were the options -c, -S or -E passed.  */
 static int have_c = 0;
 
 /* Was the option -o passed.  */
@@ -1957,7 +2065,7 @@ static void
 store_arg (const char *arg, int delete_always, int delete_failure)
 {
   if (argbuf_index + 1 == argbuf_length)
-    argbuf = xrealloc (argbuf, (argbuf_length *= 2) * sizeof (const char *));
+    argbuf = XRESIZEVEC (const char *, argbuf, (argbuf_length *= 2));
 
   argbuf[argbuf_index++] = arg;
   argbuf[argbuf_index] = 0;
@@ -2179,7 +2287,7 @@ read_specs (const char *filename, int main_p)
 
              set_spec (p2, *(sl->ptr_spec));
              if (sl->alloc_p)
-               free ((void *) *(sl->ptr_spec));
+               free (CONST_CAST (char *, *(sl->ptr_spec)));
 
              *(sl->ptr_spec) = "";
              sl->alloc_p = 0;
@@ -2249,8 +2357,7 @@ read_specs (const char *filename, int main_p)
        {
          /* Add this pair to the vector.  */
          compilers
-           = xrealloc (compilers,
-                       (n_compilers + 2) * sizeof (struct compiler));
+           = XRESIZEVEC (struct compiler, compilers, n_compilers + 2);
 
          compilers[n_compilers].suffix = suffix;
          compilers[n_compilers].spec = spec;
@@ -2529,18 +2636,18 @@ for_each_path (const struct path_prefix *paths,
         Don't repeat any we have already seen.  */
       if (multi_dir)
        {
-         free ((char *) multi_dir);
+         free (CONST_CAST (char *, multi_dir));
          multi_dir = NULL;
-         free ((char *) multi_suffix);
+         free (CONST_CAST (char *, multi_suffix));
          multi_suffix = machine_suffix;
-         free ((char *) just_multi_suffix);
+         free (CONST_CAST (char *, just_multi_suffix));
          just_multi_suffix = just_machine_suffix;
        }
       else
        skip_multi_dir = true;
       if (multi_os_dir)
        {
-         free ((char *) multi_os_dir);
+         free (CONST_CAST (char *, multi_os_dir));
          multi_os_dir = NULL;
        }
       else
@@ -2549,12 +2656,12 @@ for_each_path (const struct path_prefix *paths,
 
   if (multi_dir)
     {
-      free ((char *) multi_dir);
-      free ((char *) multi_suffix);
-      free ((char *) just_multi_suffix);
+      free (CONST_CAST (char *, multi_dir));
+      free (CONST_CAST (char *, multi_suffix));
+      free (CONST_CAST (char *, just_multi_suffix));
     }
   if (multi_os_dir)
-    free ((char *) multi_os_dir);
+    free (CONST_CAST (char *, multi_os_dir));
   if (ret != path)
     free (path);
   return ret;
@@ -2571,7 +2678,7 @@ struct add_to_obstack_info {
 static void *
 add_to_obstack (char *path, void *data)
 {
-  struct add_to_obstack_info *info = data;
+  struct add_to_obstack_info *info = (struct add_to_obstack_info *) data;
 
   if (info->check_dir && !is_directory (path, false))
     return NULL;
@@ -2585,6 +2692,16 @@ add_to_obstack (char *path, void *data)
   return NULL;
 }
 
+/* Add or change the value of an environment variable, outputting the
+   change to standard error if in verbose mode.  */
+static void
+xputenv (const char *string)
+{
+  if (verbose_flag)
+    notice ("%s\n", string);
+  putenv (CONST_CAST (char *, string));
+}
+
 /* Build a list of search directories from PATHS.
    PREFIX is a string to prepend to the list.
    If CHECK_DIR_P is true we ensure the directory exists.
@@ -2619,7 +2736,7 @@ static void
 putenv_from_prefixes (const struct path_prefix *paths, const char *env_var,
                      bool do_multi)
 {
-  putenv (build_search_list (paths, env_var, true, do_multi));
+  xputenv (build_search_list (paths, env_var, true, do_multi));
 }
 \f
 /* Check whether NAME can be accessed in MODE.  This is like access,
@@ -2655,7 +2772,7 @@ struct file_at_path_info {
 static void *
 file_at_path (char *path, void *data)
 {
-  struct file_at_path_info *info = data;
+  struct file_at_path_info *info = (struct file_at_path_info *) data;
   size_t len = strlen (path);
 
   memcpy (path + len, info->name, info->name_len);
@@ -2714,8 +2831,9 @@ find_a_file (const struct path_prefix *pprefix, const char *name, int mode,
   info.suffix_len = strlen (info.suffix);
   info.mode = mode;
 
-  return for_each_path (pprefix, do_multi, info.name_len + info.suffix_len,
-                       file_at_path, &info);
+  return (char*) for_each_path (pprefix, do_multi,
+                               info.name_len + info.suffix_len,
+                               file_at_path, &info);
 }
 
 /* Ranking of prefixes in the sort list. -B prefixes are put before
@@ -2821,13 +2939,20 @@ execute (void)
 
   gcc_assert (!processing_spec_function);
 
+  if (wrapper_string)
+    {
+      string = find_a_file (&exec_prefixes, argbuf[0], X_OK, false);
+      argbuf[0] = (string) ? string : argbuf[0];
+      insert_wrapper (wrapper_string);
+    }
+
   /* Count # of piped commands.  */
   for (n_commands = 1, i = 0; i < argbuf_index; i++)
     if (strcmp (argbuf[i], "|") == 0)
       n_commands++;
 
   /* Get storage for each command.  */
-  commands = alloca (n_commands * sizeof (struct command));
+  commands = (struct command *) alloca (n_commands * sizeof (struct command));
 
   /* Split argbuf into its separate piped processes,
      and record info about each one.
@@ -2835,10 +2960,12 @@ execute (void)
 
   commands[0].prog = argbuf[0]; /* first command.  */
   commands[0].argv = &argbuf[0];
-  string = find_a_file (&exec_prefixes, commands[0].prog, X_OK, false);
 
-  if (string)
-    commands[0].argv[0] = string;
+  if (!wrapper_string)
+    {
+      string = find_a_file (&exec_prefixes, commands[0].prog, X_OK, false);
+      commands[0].argv[0] = (string) ? string : commands[0].argv[0];
+    }
 
   for (n_commands = 1, i = 0; i < argbuf_index; i++)
     if (strcmp (argbuf[i], "|") == 0)
@@ -2932,7 +3059,7 @@ execute (void)
       for (argc = 0; commands[i].argv[argc] != NULL; argc++)
        ;
 
-      argv = alloca ((argc + 3) * sizeof (char *));
+      argv = XALLOCAVEC (const char *, argc + 3);
 
       argv[0] = VALGRIND_PATH;
       argv[1] = "-q";
@@ -2947,7 +3074,8 @@ execute (void)
 
   /* Run each piped subprocess.  */
 
-  pex = pex_init (PEX_USE_PIPES | (report_times ? PEX_RECORD_TIMES : 0),
+  pex = pex_init (PEX_USE_PIPES | ((report_times || report_times_to_file)
+                                  ? PEX_RECORD_TIMES : 0),
                  programname, temp_filename);
   if (pex == NULL)
     pfatal_with_name (_("pex_init failed"));
@@ -2961,7 +3089,7 @@ execute (void)
       errmsg = pex_run (pex,
                        ((i + 1 == n_commands ? PEX_LAST : 0)
                         | (string == commands[i].prog ? PEX_SEARCH : 0)),
-                       string, (char * const *) commands[i].argv,
+                       string, CONST_CAST (char **, commands[i].argv),
                        NULL, NULL, &err);
       if (errmsg != NULL)
        {
@@ -2975,7 +3103,7 @@ execute (void)
        }
 
       if (string != commands[i].prog)
-       free ((void *) string);
+       free (CONST_CAST (char *, string));
     }
 
   execution_count++;
@@ -2987,13 +3115,13 @@ execute (void)
     struct pex_time *times = NULL;
     int ret_code = 0;
 
-    statuses = alloca (n_commands * sizeof (int));
+    statuses = (int *) alloca (n_commands * sizeof (int));
     if (!pex_get_status (pex, n_commands, statuses))
       pfatal_with_name (_("failed to get exit status"));
 
-    if (report_times)
+    if (report_times || report_times_to_file)
       {
-       times = alloca (n_commands * sizeof (struct pex_time));
+       times = (struct pex_time *) alloca (n_commands * sizeof (struct pex_time));
        if (!pex_get_times (pex, n_commands, times))
          pfatal_with_name (_("failed to get process times"));
       }
@@ -3036,7 +3164,7 @@ See %s for instructions.",
            ret_code = -1;
          }
 
-       if (report_times)
+       if (report_times || report_times_to_file)
          {
            struct pex_time *pt = &times[i];
            double ut, st;
@@ -3047,7 +3175,43 @@ See %s for instructions.",
                  + (double) pt->system_microseconds / 1.0e6);
 
            if (ut + st != 0)
-             notice ("# %s %.2f %.2f\n", commands[i].prog, ut, st);
+             {
+               if (report_times)
+                 notice ("# %s %.2f %.2f\n", commands[i].prog, ut, st);
+
+               if (report_times_to_file)
+                 {
+                   int c = 0;
+                   const char *const *j;
+
+                   fprintf (report_times_to_file, "%g %g", ut, st);
+
+                   for (j = &commands[i].prog; *j; j = &commands[i].argv[++c])
+                     {
+                       const char *p;
+                       for (p = *j; *p; ++p)
+                         if (*p == '"' || *p == '\\' || *p == '$'
+                             || ISSPACE (*p))
+                           break;
+
+                       if (*p)
+                         {
+                           fprintf (report_times_to_file, " \"");
+                           for (p = *j; *p; ++p)
+                             {
+                               if (*p == '"' || *p == '\\' || *p == '$')
+                                 fputc ('\\', report_times_to_file);
+                               fputc (*p, report_times_to_file);
+                             }
+                           fputc ('"', report_times_to_file);
+                         }
+                       else
+                         fprintf (report_times_to_file, " %s", *j);
+                     }
+
+                   fputc ('\n', report_times_to_file);
+                 }
+             }
          }
       }
 
@@ -3061,24 +3225,22 @@ See %s for instructions.",
    If a switch uses following arguments, then the `part1' field
    is the switch itself and the `args' field
    is a null-terminated vector containing the following arguments.
-   The `live_cond' field is:
-   0 when initialized
-   1 if the switch is true in a conditional spec,
-   -1 if false (overridden by a later switch)
-   -2 if this switch should be ignored (used in %<S)
+   Bits in the `live_cond' field are:
+   SWITCH_LIVE to indicate this switch is true in a conditional spec.
+   SWITCH_FALSE to indicate this switch is overridden by a later switch.
+   SWITCH_IGNORE to indicate this switch should be ignored (used in %<S).
    The `validated' field is nonzero if any spec has looked at this switch;
    if it remains zero at the end of the run, it must be meaningless.  */
 
-#define SWITCH_OK       0
-#define SWITCH_FALSE   -1
-#define SWITCH_IGNORE  -2
-#define SWITCH_LIVE     1
+#define SWITCH_LIVE    0x1
+#define SWITCH_FALSE   0x2
+#define SWITCH_IGNORE  0x4
 
 struct switchstr
 {
   const char *part1;
   const char **args;
-  int live_cond;
+  unsigned int live_cond;
   unsigned char validated;
   unsigned char ordering;
 };
@@ -3087,6 +3249,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.
@@ -3189,10 +3374,11 @@ display_help (void)
   fputs (_("  -pass-exit-codes         Exit with highest error code from a phase\n"), stdout);
   fputs (_("  --help                   Display this information\n"), stdout);
   fputs (_("  --target-help            Display target specific command line options\n"), stdout);
-  fputs (_("  --help={target|optimizers|warnings|undocumented|params}[,{[^]joined|[^]separate}]\n"), stdout);
+  fputs (_("  --help={target|optimizers|warnings|params|[^]{joined|separate|undocumented}}[,...]\n"), stdout);
   fputs (_("                           Display specific types of command line options\n"), stdout);
   if (! verbose_flag)
     fputs (_("  (Use '-v --help' to display command line options of sub-processes)\n"), stdout);
+  fputs (_("  --version                Display compiler version information\n"), stdout);
   fputs (_("  -dumpspecs               Display all of the built in spec strings\n"), stdout);
   fputs (_("  -dumpversion             Display the version of the compiler\n"), stdout);
   fputs (_("  -dumpmachine             Display the compiler's target processor\n"), stdout);
@@ -3205,6 +3391,7 @@ display_help (void)
   -print-multi-lib         Display the mapping between command line options and\n\
                            multiple library search directories\n"), stdout);
   fputs (_("  -print-multi-os-directory Display the relative path to OS libraries\n"), stdout);
+  fputs (_("  -print-sysroot           Display the target libraries directory\n"), stdout);
   fputs (_("  -print-sysroot-headers-suffix Display the sysroot suffix used to find headers\n"), stdout);
   fputs (_("  -Wa,<options>            Pass comma-separated <options> on to the assembler\n"), stdout);
   fputs (_("  -Wp,<options>            Pass comma-separated <options> on to the preprocessor\n"), stdout);
@@ -3214,6 +3401,10 @@ display_help (void)
   fputs (_("  -Xlinker <arg>           Pass <arg> on to the linker\n"), stdout);
   fputs (_("  -combine                 Pass multiple source files to compiler at once\n"), stdout);
   fputs (_("  -save-temps              Do not delete intermediate files\n"), stdout);
+  fputs (_("  -save-temps=<arg>        Do not delete intermediate files\n"), stdout);
+  fputs (_("\
+  -no-canonical-prefixes   Do not canonicalize paths when building relative\n\
+                           prefixes to other gcc components\n"), stdout);
   fputs (_("  -pipe                    Use pipes rather than intermediate files\n"), stdout);
   fputs (_("  -time                    Time the execution of each subprocess\n"), stdout);
   fputs (_("  -specs=<file>            Override built-in specs with the contents of <file>\n"), stdout);
@@ -3255,8 +3446,8 @@ add_preprocessor_option (const char *option, int len)
   if (! preprocessor_options)
     preprocessor_options = XNEWVEC (char *, n_preprocessor_options);
   else
-    preprocessor_options = xrealloc (preprocessor_options,
-                                    n_preprocessor_options * sizeof (char *));
+    preprocessor_options = XRESIZEVEC (char *, preprocessor_options,
+                                      n_preprocessor_options);
 
   preprocessor_options [n_preprocessor_options - 1] =
     save_string (option, len);
@@ -3270,8 +3461,8 @@ add_assembler_option (const char *option, int len)
   if (! assembler_options)
     assembler_options = XNEWVEC (char *, n_assembler_options);
   else
-    assembler_options = xrealloc (assembler_options,
-                                 n_assembler_options * sizeof (char *));
+    assembler_options = XRESIZEVEC (char *, assembler_options,
+                                   n_assembler_options);
 
   assembler_options [n_assembler_options - 1] = save_string (option, len);
 }
@@ -3284,8 +3475,7 @@ add_linker_option (const char *option, int len)
   if (! linker_options)
     linker_options = XNEWVEC (char *, n_linker_options);
   else
-    linker_options = xrealloc (linker_options,
-                              n_linker_options * sizeof (char *));
+    linker_options = XRESIZEVEC (char *, linker_options, n_linker_options);
 
   linker_options [n_linker_options - 1] = save_string (option, len);
 }
@@ -3307,6 +3497,8 @@ process_command (int argc, const char **argv)
   unsigned int j;
 #endif
   const char *tooldir_prefix;
+  char *(*get_relative_prefix) (const char *, const char *,
+                               const char *) = NULL;
 
   GET_ENVIRONMENT (gcc_exec_prefix, "GCC_EXEC_PREFIX");
 
@@ -3332,8 +3524,10 @@ process_command (int argc, const char **argv)
      Use heuristic that all configuration names must have at least
      one dash '-'. This allows us to pass options starting with -b.  */
   if (argc > 1 && argv[1][0] == '-'
-      && (argv[1][1] == 'V' ||
-        ((argv[1][1] == 'b') && (NULL != strchr(argv[1] + 2,'-')))))
+      && (argv[1][1] == 'V'
+         || (argv[1][1] == 'b'
+             && (argv[1][2] == '\0'
+                 || NULL != strchr (argv[1] + 2, '-')))))
     {
       const char *new_version = DEFAULT_TARGET_VERSION;
       const char *new_machine = DEFAULT_TARGET_MACHINE;
@@ -3341,10 +3535,15 @@ process_command (int argc, const char **argv)
       char **new_argv;
       char *new_argv0;
       int baselen;
+      int status = 0;
+      int err = 0;
+      const char *errmsg;
 
       while (argc > 1 && argv[1][0] == '-'
-            && (argv[1][1] == 'V' ||
-               ((argv[1][1] == 'b') && ( NULL != strchr(argv[1] + 2,'-')))))
+            && (argv[1][1] == 'V'
+                || (argv[1][1] == 'b'
+                    && (argv[1][2] == '\0'
+                        || NULL != strchr (argv[1] + 2, '-')))))
        {
          char opt = argv[1][1];
          const char *arg;
@@ -3371,20 +3570,55 @@ process_command (int argc, const char **argv)
       for (baselen = strlen (progname); baselen > 0; baselen--)
        if (IS_DIR_SEPARATOR (progname[baselen-1]))
          break;
-      new_argv0 = xmemdup (progname, baselen,
+      new_argv0 = XDUPVAR (char, progname, baselen,
                           baselen + concat_length (new_version, new_machine,
                                                    "-gcc-", NULL) + 1);
       strcpy (new_argv0 + baselen, new_machine);
       strcat (new_argv0, "-gcc-");
       strcat (new_argv0, new_version);
 
-      new_argv = xmemdup (argv, (argc + 1) * sizeof (argv[0]),
-                         (argc + 1) * sizeof (argv[0]));
+      new_argv = XDUPVEC (char *, argv, argc + 1);
       new_argv[0] = new_argv0;
 
-      execvp (new_argv0, new_argv);
-      fatal ("couldn't run '%s': %s", new_argv0, xstrerror (errno));
+      errmsg = pex_one (PEX_SEARCH, new_argv0, new_argv, progname, NULL,
+                       NULL, &status, &err);
+
+      if (errmsg)
+       {
+         if (err == 0)
+           fatal ("couldn't run '%s': %s", new_argv0, errmsg);
+         else
+           fatal ("couldn't run '%s': %s: %s", new_argv0, errmsg,
+                   xstrerror (err));
+        }
+      exit (status);
+    }
+
+  /* Convert new-style -- options to old-style.  */
+  translate_options (&argc,
+                    CONST_CAST2 (const char *const **, const char ***,
+                                 &argv));
+
+  /* Do language-specific adjustment/addition of flags.  */
+  lang_specific_driver (&argc,
+                       CONST_CAST2 (const char *const **, const char ***,
+                                    &argv),
+                       &added_libraries);
+
+  /* Handle any -no-canonical-prefixes flag early, to assign the function
+     that builds relative prefixes.  This function creates default search
+     paths that are needed later in normal option handling.  */
+
+  for (i = 1; i < argc; i++)
+    {
+      if (! strcmp (argv[i], "-no-canonical-prefixes"))
+       {
+         get_relative_prefix = make_relative_prefix_ignore_links;
+         break;
+       }
     }
+  if (! get_relative_prefix)
+    get_relative_prefix = make_relative_prefix;
 
   /* Set up the default search paths.  If there is no GCC_EXEC_PREFIX,
      see if we can create it from the pathname specified in argv[0].  */
@@ -3394,13 +3628,14 @@ process_command (int argc, const char **argv)
   /* FIXME: make_relative_prefix doesn't yet work for VMS.  */
   if (!gcc_exec_prefix)
     {
-      gcc_exec_prefix = make_relative_prefix (argv[0], standard_bindir_prefix,
-                                             standard_exec_prefix);
-      gcc_libexec_prefix = make_relative_prefix (argv[0],
-                                                standard_bindir_prefix,
-                                                standard_libexec_prefix);
+      gcc_exec_prefix = get_relative_prefix (argv[0],
+                                            standard_bindir_prefix,
+                                            standard_exec_prefix);
+      gcc_libexec_prefix = get_relative_prefix (argv[0],
+                                            standard_bindir_prefix,
+                                            standard_libexec_prefix);
       if (gcc_exec_prefix)
-       putenv (concat ("GCC_EXEC_PREFIX=", gcc_exec_prefix, NULL));
+       xputenv (concat ("GCC_EXEC_PREFIX=", gcc_exec_prefix, NULL));
     }
   else
     {
@@ -3409,9 +3644,9 @@ process_command (int argc, const char **argv)
         / (which is ignored by make_relative_prefix), so append a
         program name.  */
       char *tmp_prefix = concat (gcc_exec_prefix, "gcc", NULL);
-      gcc_libexec_prefix = make_relative_prefix (tmp_prefix,
-                                                standard_exec_prefix,
-                                                standard_libexec_prefix);
+      gcc_libexec_prefix = get_relative_prefix (tmp_prefix,
+                                               standard_exec_prefix,
+                                               standard_libexec_prefix);
 
       /* The path is unrelocated, so fallback to the original setting.  */
       if (!gcc_libexec_prefix)
@@ -3454,7 +3689,7 @@ process_command (int argc, const char **argv)
   if (temp)
     {
       const char *startp, *endp;
-      char *nstore = alloca (strlen (temp) + 3);
+      char *nstore = (char *) alloca (strlen (temp) + 3);
 
       startp = endp = temp;
       while (1)
@@ -3488,7 +3723,7 @@ process_command (int argc, const char **argv)
   if (temp && *cross_compile == '0')
     {
       const char *startp, *endp;
-      char *nstore = alloca (strlen (temp) + 3);
+      char *nstore = (char *) alloca (strlen (temp) + 3);
 
       startp = endp = temp;
       while (1)
@@ -3521,7 +3756,7 @@ process_command (int argc, const char **argv)
   if (temp && *cross_compile == '0')
     {
       const char *startp, *endp;
-      char *nstore = alloca (strlen (temp) + 3);
+      char *nstore = (char *) alloca (strlen (temp) + 3);
 
       startp = endp = temp;
       while (1)
@@ -3549,12 +3784,6 @@ process_command (int argc, const char **argv)
        }
     }
 
-  /* Convert new-style -- options to old-style.  */
-  translate_options (&argc, (const char *const **) &argv);
-
-  /* Do language-specific adjustment/addition of flags.  */
-  lang_specific_driver (&argc, (const char *const **) &argv, &added_libraries);
-
   /* Scan argv twice.  Here, the first time, just count how many switches
      there will be in their vector, and how many input files in theirs.
      Here we also parse the switches that cc itself uses (e.g. -v).  */
@@ -3584,13 +3813,17 @@ process_command (int argc, const char **argv)
       else if (strcmp (argv[i], "-fversion") == 0)
        {
          /* translate_options () has turned --version into -fversion.  */
-         printf (_("%s (GCC) %s\n"), programname, version_string);
-         printf ("Copyright %s 2007 Free Software Foundation, Inc.\n",
-                 _("(C)"));
-         fputs (_("This is free software; see the source for copying conditions.  There is NO\n\
-warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"),
-                stdout);
-         exit (0);
+         print_version = 1;
+
+         /* We will be passing a dummy file on to the sub-processes.  */
+         n_infiles++;
+         n_switches++;
+
+         /* CPP driver cannot obtain switch from cc1_options.  */
+         if (is_cpp_driver)
+           add_preprocessor_option ("--version", strlen ("--version"));
+         add_assembler_option ("--version", strlen ("--version"));
+         add_linker_option ("--version", strlen ("--version"));
        }
       else if (strcmp (argv[i], "-fhelp") == 0)
        {
@@ -3648,10 +3881,44 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
        print_multi_lib = 1;
       else if (! strcmp (argv[i], "-print-multi-directory"))
        print_multi_directory = 1;
+      else if (! strcmp (argv[i], "-print-sysroot"))
+       print_sysroot = 1;
       else if (! strcmp (argv[i], "-print-multi-os-directory"))
        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;
@@ -3730,9 +3997,23 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
        n_infiles++;
       else if (strcmp (argv[i], "-save-temps") == 0)
        {
-         save_temps_flag = 1;
+         save_temps_flag = SAVE_TEMPS_CWD;
          n_switches++;
        }
+      else if (strncmp (argv[i], "-save-temps=", 12) == 0)
+       {
+         n_switches++;
+         if (strcmp (argv[i]+12, "cwd") == 0)
+           save_temps_flag = SAVE_TEMPS_CWD;
+         else if (strcmp (argv[i]+12, "obj") == 0
+                  || strcmp (argv[i]+12, "object") == 0)
+           save_temps_flag = SAVE_TEMPS_OBJ;
+         else
+           fatal ("'%s' is an unknown -save-temps option", argv[i]);
+       }
+      else if (strcmp (argv[i], "-no-canonical-prefixes") == 0)
+       /* Already handled as a special case, so ignored here.  */
+       ;
       else if (strcmp (argv[i], "-combine") == 0)
        {
          combine_flag = 1;
@@ -3768,6 +4049,12 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
        }
       else if (strcmp (argv[i], "-time") == 0)
        report_times = 1;
+      else if (strncmp (argv[i], "-time=", sizeof ("-time=") - 1) == 0)
+       {
+         if (report_times_to_file)
+           fclose (report_times_to_file);
+         report_times_to_file = fopen (argv[i] + sizeof ("-time=") - 1, "a");
+       }
       else if (strcmp (argv[i], "-pipe") == 0)
        {
          /* -pipe has to go into the switches array as well as
@@ -3775,6 +4062,15 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
          use_pipes = 1;
          n_switches++;
        }
+      else if (strcmp (argv[i], "-wrapper") == 0)
+        {
+         if (++i >= argc)
+           fatal ("argument to '-wrapper' is missing");
+
+          wrapper_string = argv[i];
+         n_switches++;
+         n_switches++;
+        }
       else if (strcmp (argv[i], "-###") == 0)
        {
          /* This is similar to -v except that there is no execution
@@ -3792,7 +4088,7 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
          switch (c)
            {
            case 'b':
-             if (NULL == strchr(argv[i] + 2, '-'))
+             if (p[1] && NULL == strchr (argv[i] + 2, '-'))
                goto normal_switch;
 
              /* Fall through.  */
@@ -3852,6 +4148,7 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
 
            case 'S':
            case 'c':
+           case 'E':
              if (p[1] == 0)
                {
                  have_c = 1;
@@ -3867,7 +4164,7 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
                {
                  int skip;
 
-                 /* Forward scan, just in case -S or -c is specified
+                 /* Forward scan, just in case -S, -E or -c is specified
                     after -o.  */
                  int j = i + 1;
                  if (p[1] == 0)
@@ -3897,6 +4194,11 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
              else
                argv[i] = convert_filename (argv[i], ! have_c, 0);
 #endif
+             /* Save the output name in case -save-temps=obj was used.  */
+             if ((p[1] == 0) && argv[i + 1])
+               save_temps_prefix = xstrdup(argv[i + 1]);
+             else
+               save_temps_prefix = xstrdup(argv[i] + 1);
              goto normal_switch;
 
            default:
@@ -3908,7 +4210,7 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
              for (j = 0; j < ARRAY_SIZE (modify_target); j++)
                if (! strcmp (argv[i], modify_target[j].sw))
                  {
-                   char *new_name = xmalloc (strlen (modify_target[j].str)
+                   char *new_name = XNEWVEC (char, strlen (modify_target[j].str)
                                              + strlen (spec_machine));
                    const char *p, *r;
                    char *q;
@@ -3954,6 +4256,25 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
        }
     }
 
+  /* If -save-temps=obj and -o name, create the prefix to use for %b.
+     Otherwise just make -save-temps=obj the same as -save-temps=cwd.  */
+  if (save_temps_flag == SAVE_TEMPS_OBJ && save_temps_prefix != NULL)
+    {
+      save_temps_length = strlen (save_temps_prefix);
+      temp = strrchr (lbasename (save_temps_prefix), '.');
+      if (temp)
+       {
+         save_temps_length -= strlen (temp);
+         save_temps_prefix[save_temps_length] = '\0';
+       }
+
+    }
+  else if (save_temps_prefix != NULL)
+    {
+      free (save_temps_prefix);
+      save_temps_prefix = NULL;
+    }
+
   if (save_temps_flag && use_pipes)
     {
       /* -save-temps overrides -pipe, so that temp files are produced */
@@ -3962,10 +4283,33 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
       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
-     the GNU assembler) before those of the host system.  */ 
+     the GNU assembler) before those of the host system.  */
 
   /* If we don't know where the toolchain has been installed, use the
      configured-in locations.  */
@@ -3983,19 +4327,6 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
                  PREFIX_PRIORITY_LAST, 1, 0);
     }
 
-  /* If not cross-compiling, search well-known system locations.  */
-  if (*cross_compile == '0')
-    {
-#ifndef OS2
-      add_prefix (&exec_prefixes, standard_exec_prefix_1, "BINUTILS",
-                 PREFIX_PRIORITY_LAST, 2, 0);
-      add_prefix (&exec_prefixes, standard_exec_prefix_2, "BINUTILS",
-                 PREFIX_PRIORITY_LAST, 2, 0);
-#endif
-      add_prefix (&startfile_prefixes, standard_exec_prefix_2, "BINUTILS",
-                 PREFIX_PRIORITY_LAST, 1, 0);
-    }
-
   gcc_assert (!IS_ABSOLUTE_PATH (tooldir_base_prefix));
   tooldir_prefix = concat (tooldir_base_prefix, spec_machine,
                           dir_separator_str, NULL);
@@ -4021,9 +4352,9 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
      ``make_relative_prefix'' is not compiled for VMS, so don't call it.  */
   if (target_system_root && gcc_exec_prefix)
     {
-      char *tmp_prefix = make_relative_prefix (argv[0],
-                                              standard_bindir_prefix,
-                                              target_system_root);
+      char *tmp_prefix = get_relative_prefix (argv[0],
+                                             standard_bindir_prefix,
+                                             target_system_root);
       if (tmp_prefix && access_check (tmp_prefix, F_OK) == 0)
        {
          target_system_root = tmp_prefix;
@@ -4065,6 +4396,8 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
        ;
       else if (! strncmp (argv[i], "-Wp,", 4))
        ;
+      else if (! strcmp (argv[i], "-no-canonical-prefixes"))
+       ;
       else if (! strcmp (argv[i], "-pass-exit-codes"))
        ;
       else if (! strcmp (argv[i], "-print-search-dirs"))
@@ -4079,6 +4412,8 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
        ;
       else if (! strcmp (argv[i], "-print-multi-directory"))
        ;
+      else if (! strcmp (argv[i], "-print-sysroot"))
+       ;
       else if (! strcmp (argv[i], "-print-multi-os-directory"))
        ;
       else if (! strcmp (argv[i], "-print-sysroot-headers-suffix"))
@@ -4097,7 +4432,7 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
             -e0 or -e1 down into the linker.  */
          switches[n_switches].part1 = &argv[i][0];
          switches[n_switches].args = 0;
-         switches[n_switches].live_cond = SWITCH_OK;
+         switches[n_switches].live_cond = 0;
          switches[n_switches].validated = 0;
          n_switches++;
        }
@@ -4140,12 +4475,16 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
          infiles[n_infiles].language = "*";
          infiles[n_infiles++].name = argv[i];
        }
+      else if (strcmp (argv[i], "-wrapper") == 0)
+        i++;
       else if (strcmp (argv[i], "-specs") == 0)
        i++;
       else if (strncmp (argv[i], "-specs=", 7) == 0)
        ;
       else if (strcmp (argv[i], "-time") == 0)
        ;
+      else if (strncmp (argv[i], "-time=", sizeof ("-time=") - 1) == 0)
+       ;
       else if (strcmp (argv[i], "-###") == 0)
        ;
       else if (argv[i][0] == '-' && argv[i][1] != 0)
@@ -4208,14 +4547,16 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
          else
            switches[n_switches].args = 0;
 
-         switches[n_switches].live_cond = SWITCH_OK;
+         switches[n_switches].live_cond = 0;
          switches[n_switches].validated = 0;
          switches[n_switches].ordering = 0;
-         /* These are always valid, since gcc.c itself understands them.  */
+         /* These are always valid, since gcc.c itself understands the
+            first four and gfortranspec.c understands -static-libgfortran.  */
          if (!strcmp (p, "save-temps")
              || !strcmp (p, "static-libgcc")
              || !strcmp (p, "shared-libgcc")
-             || !strcmp (p, "pipe"))
+             || !strcmp (p, "pipe")
+             || !strcmp (p, "static-libgfortran"))
            switches[n_switches].validated = 1;
          else
            {
@@ -4227,28 +4568,53 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
        }
       else
        {
+          const char *p = strchr (argv[i], '@');
+          char *fname;
 #ifdef HAVE_TARGET_OBJECT_SUFFIX
          argv[i] = convert_filename (argv[i], 0, access (argv[i], F_OK));
 #endif
-
-         if (strcmp (argv[i], "-") != 0 && access (argv[i], F_OK) < 0)
-           {
-             perror_with_name (argv[i]);
-             error_count++;
-           }
-         else
-           {
-             infiles[n_infiles].language = spec_lang;
-             infiles[n_infiles++].name = argv[i];
-           }
+          if (!p)
+            fname = xstrdup (argv[i]);
+          else
+            {
+              fname = (char *)xmalloc (p - argv[i] + 1);
+              memcpy (fname, argv[i], p - argv[i]);
+              fname[p - argv[i]] = '\0';
+            }
+
+          if (strcmp (fname, "-") != 0 && access (fname, F_OK) < 0)
+            {
+              perror_with_name (fname);
+              error_count++;
+            }
+          else
+            {
+              infiles[n_infiles].language = spec_lang;
+              infiles[n_infiles++].name = argv[i];
+            }
+
+          free (fname);
        }
     }
 
   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)
+  if (print_subprocess_help || print_help_list || print_version)
     {
       n_infiles = 1;
 
@@ -4287,7 +4653,7 @@ set_collect_gcc_options (void)
       first_time = FALSE;
 
       /* Ignore elided switches.  */
-      if (switches[i].live_cond == SWITCH_IGNORE)
+      if ((switches[i].live_cond & SWITCH_IGNORE) != 0)
        continue;
 
       obstack_grow (&collect_obstack, "'-", 2);
@@ -4316,7 +4682,7 @@ set_collect_gcc_options (void)
        }
     }
   obstack_grow (&collect_obstack, "\0", 1);
-  putenv (XOBFINISH (&collect_obstack, char *));
+  xputenv (XOBFINISH (&collect_obstack, char *));
 }
 \f
 /* Process a spec string, accumulating and running commands.  */
@@ -4362,6 +4728,13 @@ static int this_is_output_file;
    search dirs for it.  */
 static int this_is_library_file;
 
+/* Nonzero means %T has been seen; the next arg to be terminated
+   is the name of a linker script and we should try all of the
+   standard search dirs for it.  If it is found insert a --script
+   command line switch and then substitute the full path in place,
+   otherwise generate an error message.  */
+static int this_is_linker_script;
+
 /* Nonzero means that the input of this command is coming from a pipe.  */
 static int input_from_pipe;
 
@@ -4369,6 +4742,85 @@ static int input_from_pipe;
    arguments.  */
 static const char *suffix_subst;
 
+/* If there is an argument being accumulated, terminate it and store it.  */
+
+static void
+end_going_arg (void)
+{
+  if (arg_going)
+    {
+      const char *string;
+
+      obstack_1grow (&obstack, 0);
+      string = XOBFINISH (&obstack, const char *);
+      if (this_is_library_file)
+       string = find_file (string);
+      if (this_is_linker_script)
+       {
+         char * full_script_path = find_a_file (&startfile_prefixes, string, R_OK, true);
+
+         if (full_script_path == NULL)
+           {
+             error (_("unable to locate default linker script '%s' in the library search paths"), string);
+             /* Script was not found on search path.  */
+             return;
+           }
+         store_arg ("--script", false, false);
+         string = full_script_path;
+       }
+      store_arg (string, delete_this_arg, this_is_output_file);
+      if (this_is_output_file)
+       outfiles[input_file_number] = string;
+      arg_going = 0;
+    }
+}
+
+
+/* Parse the WRAPPER string which is a comma separated list of the command line
+   and insert them into the beginning of argbuf.  */
+
+static void
+insert_wrapper (const char *wrapper)
+{
+  int n = 0;
+  int i;
+  char *buf = xstrdup (wrapper);
+  char *p = buf;
+
+  do
+    {
+      n++;
+      while (*p == ',')
+        p++;
+    }
+  while ((p = strchr (p, ',')) != NULL);
+
+  if (argbuf_index + n >= argbuf_length)
+    {
+      argbuf_length = argbuf_length * 2;
+      while (argbuf_length < argbuf_index + n)
+       argbuf_length *= 2;
+      argbuf = XRESIZEVEC (const char *, argbuf, argbuf_length);
+    }
+  for (i = argbuf_index - 1; i >= 0; i--)
+    argbuf[i + n] = argbuf[i];
+
+  i = 0;
+  p = buf;
+  do
+    {
+      while (*p == ',')
+        {
+          *p = 0;
+          p++;
+        }
+      argbuf[i++] = p;
+    }
+  while ((p = strchr (p, ',')) != NULL);
+  gcc_assert (i == n);
+  argbuf_index += n;
+}
+
 /* Process the spec SPEC and run the commands specified therein.
    Returns 0 if the spec is successfully processed; -1 if failed.  */
 
@@ -4398,7 +4850,6 @@ do_spec (const char *spec)
 static int
 do_spec_2 (const char *spec)
 {
-  const char *string;
   int result;
 
   clear_args ();
@@ -4406,23 +4857,13 @@ do_spec_2 (const char *spec)
   delete_this_arg = 0;
   this_is_output_file = 0;
   this_is_library_file = 0;
+  this_is_linker_script = 0;
   input_from_pipe = 0;
   suffix_subst = NULL;
 
   result = do_spec_1 (spec, 0, NULL);
 
-  /* End any pending argument.  */
-  if (arg_going)
-    {
-      obstack_1grow (&obstack, 0);
-      string = XOBFINISH (&obstack, const char *);
-      if (this_is_library_file)
-       string = find_file (string);
-      store_arg (string, delete_this_arg, this_is_output_file);
-      if (this_is_output_file)
-       outfiles[input_file_number] = string;
-      arg_going = 0;
-    }
+  end_going_arg ();
 
   return result;
 }
@@ -4460,7 +4901,7 @@ do_option_spec (const char *name, const char *spec)
     }
 
   /* Replace each %(VALUE) by the specified value.  */
-  tmp_spec = alloca (strlen (spec) + 1
+  tmp_spec = (char *) alloca (strlen (spec) + 1
                     + value_count * (value_len - strlen ("%(VALUE)")));
   tmp_spec_p = tmp_spec;
   q = spec;
@@ -4488,29 +4929,69 @@ do_self_spec (const char *spec)
 
   if (argbuf_index > 0)
     {
-      int i, first;
+      int i;
 
-      first = n_switches;
-      n_switches += argbuf_index;
-      switches = xrealloc (switches,
-                          sizeof (struct switchstr) * (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;
-         sw->live_cond = SWITCH_OK;
+         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;
     }
 }
 
@@ -4527,7 +5008,7 @@ struct spec_path_info {
 static void *
 spec_path (char *path, void *data)
 {
-  struct spec_path_info *info = data;
+  struct spec_path_info *info = (struct spec_path_info *) data;
   size_t len = 0;
   char save = 0;
 
@@ -4565,10 +5046,53 @@ spec_path (char *path, void *data)
   return NULL;
 }
 
-/* Process the sub-spec SPEC as a portion of a larger spec.
-   This is like processing a whole spec except that we do
-   not initialize at the beginning and we do not supply a
-   newline by default at the end.
+/* Create a temporary FILE with the contents of ARGV. Add @FILE to the
+   argument list. */
+
+static void
+create_at_file (char **argv)
+{
+  char *temp_file = make_temp_file ("");
+  char *at_argument = concat ("@", temp_file, NULL);
+  FILE *f = fopen (temp_file, "w");
+  int status;
+
+  if (f == NULL)
+    fatal ("could not open temporary response file %s",
+          temp_file);
+
+  status = writeargv (argv, f);
+
+  if (status)
+    fatal ("could not write to temporary response file %s",
+          temp_file);
+
+  status = fclose (f);
+
+  if (EOF == status)
+    fatal ("could not close temporary response file %s",
+          temp_file);
+
+  store_arg (at_argument, 0, 0);
+
+  record_temp_file (temp_file, !save_temps_flag, !save_temps_flag);
+}
+
+/* True if we should compile INFILE. */
+
+static bool
+compile_input_file_p (struct infile *infile)
+{
+  if ((!infile->language) || (infile->language[0] != '*'))
+    if (infile->incompiler == input_file_compiler)
+      return true;
+  return false;
+}
+
+/* Process the sub-spec SPEC as a portion of a larger spec.
+   This is like processing a whole spec except that we do
+   not initialize at the beginning and we do not supply a
+   newline by default at the end.
    INSWITCH nonzero means don't process %-sequences in SPEC;
    in this case, % is treated as an ordinary character.
    This is used while substituting switches.
@@ -4583,7 +5107,6 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part)
   const char *p = spec;
   int c;
   int i;
-  const char *string;
   int value;
 
   while ((c = *p++))
@@ -4592,19 +5115,7 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part)
     switch (inswitch ? 'a' : c)
       {
       case '\n':
-       /* End of line: finish any pending argument,
-          then run the pending command if one has been started.  */
-       if (arg_going)
-         {
-           obstack_1grow (&obstack, 0);
-           string = XOBFINISH (&obstack, const char *);
-           if (this_is_library_file)
-             string = find_file (string);
-           store_arg (string, delete_this_arg, this_is_output_file);
-           if (this_is_output_file)
-             outfiles[input_file_number] = string;
-         }
-       arg_going = 0;
+       end_going_arg ();
 
        if (argbuf_index > 0 && !strcmp (argbuf[argbuf_index - 1], "|"))
          {
@@ -4634,21 +5145,12 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part)
        delete_this_arg = 0;
        this_is_output_file = 0;
        this_is_library_file = 0;
+       this_is_linker_script = 0;
        input_from_pipe = 0;
        break;
 
       case '|':
-       /* End any pending argument.  */
-       if (arg_going)
-         {
-           obstack_1grow (&obstack, 0);
-           string = XOBFINISH (&obstack, const char *);
-           if (this_is_library_file)
-             string = find_file (string);
-           store_arg (string, delete_this_arg, this_is_output_file);
-           if (this_is_output_file)
-             outfiles[input_file_number] = string;
-         }
+       end_going_arg ();
 
        /* Use pipe */
        obstack_1grow (&obstack, c);
@@ -4657,22 +5159,13 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part)
 
       case '\t':
       case ' ':
-       /* Space or tab ends an argument if one is pending.  */
-       if (arg_going)
-         {
-           obstack_1grow (&obstack, 0);
-           string = XOBFINISH (&obstack, const char *);
-           if (this_is_library_file)
-             string = find_file (string);
-           store_arg (string, delete_this_arg, this_is_output_file);
-           if (this_is_output_file)
-             outfiles[input_file_number] = string;
-         }
+       end_going_arg ();
+
        /* Reinitialize for a new argument.  */
-       arg_going = 0;
        delete_this_arg = 0;
        this_is_output_file = 0;
        this_is_library_file = 0;
+       this_is_linker_script = 0;
        break;
 
       case '%':
@@ -4682,12 +5175,22 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part)
            fatal ("spec '%s' invalid", spec);
 
          case 'b':
-           obstack_grow (&obstack, input_basename, basename_length);
+           if (save_temps_length)
+             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;
 
          case 'B':
-           obstack_grow (&obstack, input_basename, suffixed_basename_length);
+           if (save_temps_length)
+             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;
 
@@ -4728,7 +5231,7 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part)
              char *buf;
              while (*p != 0 && *p != '\n')
                p++;
-             buf = alloca (p - q + 1);
+             buf = (char *) alloca (p - q + 1);
              strncpy (buf, q, p - q);
              buf[p - q] = 0;
              error ("%s", buf);
@@ -4742,7 +5245,7 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part)
              char *buf;
              while (*p != 0 && *p != '\n')
                p++;
-             buf = alloca (p - q + 1);
+             buf = (char *) alloca (p - q + 1);
              strncpy (buf, q, p - q);
              buf[p - q] = 0;
              notice ("%s\n", buf);
@@ -4833,6 +5336,32 @@ 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)
+                 {
+                   char *tmp;
+                   temp_filename_length
+                     = save_temps_length + suffix_length + 1;
+                   tmp = (char *) alloca (temp_filename_length);
+                   memcpy (tmp, save_temps_prefix, save_temps_length);
+                   memcpy (tmp + save_temps_length, suffix, suffix_length);
+                   tmp[save_temps_length + suffix_length] = '\0';
+                   temp_filename = save_string (tmp,
+                                                temp_filename_length + 1);
+                   obstack_grow (&obstack, temp_filename,
+                                 temp_filename_length);
+                   arg_going = 1;
+                   delete_this_arg = 0;
+                   break;
+                 }
+
                /* If the input_filename has the same suffix specified
                   for the %g, %u, or %U, and -save-temps is specified,
                   we could end up using that file as an intermediate
@@ -4843,12 +5372,14 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part)
 
                if (save_temps_flag)
                  {
-                   temp_filename_length = basename_length + suffix_length;
-                   temp_filename = alloca (temp_filename_length + 1);
-                   strncpy ((char *) temp_filename, input_basename, basename_length);
-                   strncpy ((char *) temp_filename + basename_length, suffix,
-                            suffix_length);
-                   *((char *) temp_filename + temp_filename_length) = '\0';
+                   char *tmp;
+                   temp_filename_length = basename_length + suffix_length + 1;
+                   tmp = (char *) alloca (temp_filename_length);
+                   memcpy (tmp, input_basename, basename_length);
+                   memcpy (tmp + basename_length, suffix, suffix_length);
+                   tmp[basename_length + suffix_length] = '\0';
+                   temp_filename = tmp;
+
                    if (strcmp (temp_filename, input_filename) != 0)
                      {
 #ifndef HOST_LACKS_INODE_NUMBERS
@@ -4905,7 +5436,7 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part)
                  {
                    if (t == 0)
                      {
-                       t = xmalloc (sizeof (struct temp_name));
+                       t = XNEW (struct temp_name);
                        t->next = temp_names;
                        temp_names = t;
                      }
@@ -4936,9 +5467,37 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part)
          case 'i':
            if (combine_inputs)
              {
-               for (i = 0; (int) i < n_infiles; i++)
-                 if ((!infiles[i].language) || (infiles[i].language[0] != '*'))
-                   if (infiles[i].incompiler == input_file_compiler)
+               if (at_file_supplied)
+                 {
+                   /* We are going to expand `%i' to `@FILE', where FILE
+                      is a newly-created temporary filename.  The filenames
+                      that would usually be expanded in place of %o will be
+                      written to the temporary file.  */
+                   char **argv;
+                   int n_files = 0;
+                   int j;
+
+                   for (i = 0; i < n_infiles; i++)
+                     if (compile_input_file_p (&infiles[i]))
+                       n_files++;
+
+                   argv = (char **) alloca (sizeof (char *) * (n_files + 1));
+
+                   /* Copy the strings over.  */
+                   for (i = 0, j = 0; i < n_infiles; i++)
+                     if (compile_input_file_p (&infiles[i]))
+                       {
+                         argv[j] = CONST_CAST (char *, infiles[i].name);
+                         infiles[i].compiled = true;
+                         j++;
+                       }
+                   argv[j] = NULL;
+
+                   create_at_file (argv);
+                 }
+               else
+                 for (i = 0; (int) i < n_infiles; i++)
+                   if (compile_input_file_p (&infiles[i]))
                      {
                        store_arg (infiles[i].name, 0, 0);
                        infiles[i].compiled = true;
@@ -5009,9 +5568,39 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part)
              int max = n_infiles;
              max += lang_specific_extra_outfiles;
 
-             for (i = 0; i < max; i++)
-               if (outfiles[i])
-                 store_arg (outfiles[i], 0, 0);
+              if (HAVE_GNU_LD && at_file_supplied)
+                {
+                  /* We are going to expand `%o' to `@FILE', where FILE
+                     is a newly-created temporary filename.  The filenames
+                     that would usually be expanded in place of %o will be
+                     written to the temporary file.  */
+
+                  char **argv;
+                  int n_files, j;
+
+                  /* Convert OUTFILES into a form suitable for writeargv.  */
+
+                  /* Determine how many are non-NULL.  */
+                  for (n_files = 0, i = 0; i < max; i++)
+                    n_files += outfiles[i] != NULL;
+
+                  argv = (char **) alloca (sizeof (char *) * (n_files + 1));
+
+                  /* Copy the strings over.  */
+                  for (i = 0, j = 0; i < max; i++)
+                    if (outfiles[i])
+                      {
+                        argv[j] = CONST_CAST (char *, outfiles[i]);
+                        j++;
+                      }
+                  argv[j] = NULL;
+
+                 create_at_file (argv);
+                }
+              else
+                for (i = 0; i < max; i++)
+                 if (outfiles[i])
+                   store_arg (outfiles[i], 0, 0);
              break;
            }
 
@@ -5024,6 +5613,10 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part)
            this_is_library_file = 1;
            break;
 
+         case 'T':
+           this_is_linker_script = 1;
+           break;
+
          case 'V':
            outfiles[input_file_number] = NULL;
            break;
@@ -5041,18 +5634,7 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part)
              p = handle_braces (p + 1);
              if (p == 0)
                return -1;
-             /* End any pending argument.  */
-             if (arg_going)
-               {
-                 obstack_1grow (&obstack, 0);
-                 string = XOBFINISH (&obstack, const char *);
-                 if (this_is_library_file)
-                   string = find_file (string);
-                 store_arg (string, delete_this_arg, this_is_output_file);
-                 if (this_is_output_file)
-                   outfiles[input_file_number] = string;
-                 arg_going = 0;
-               }
+             end_going_arg ();
              /* If any args were output, mark the last one for deletion
                 on failure.  */
              if (argbuf_index != cur_index)
@@ -5245,7 +5827,7 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part)
                if (!strncmp (switches[i].part1, p, len - have_wildcard)
                    && (have_wildcard || switches[i].part1[len] == '\0'))
                  {
-                   switches[i].live_cond = SWITCH_IGNORE;
+                   switches[i].live_cond |= SWITCH_IGNORE;
                    switches[i].validated = 1;
                  }
 
@@ -5306,7 +5888,7 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part)
                    }
                  else
                    {
-                     char *x = alloca (strlen (name) * 2 + 1);
+                     char *x = (char *) alloca (strlen (name) * 2 + 1);
                      char *buf = x;
                      const char *y = name;
                      int flag = 0;
@@ -5371,17 +5953,8 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part)
 
   /* End of string.  If we are processing a spec function, we need to
      end any pending argument.  */
-  if (processing_spec_function && arg_going)
-    {
-      obstack_1grow (&obstack, 0);
-      string = XOBFINISH (&obstack, const char *);
-      if (this_is_library_file)
-        string = find_file (string);
-      store_arg (string, delete_this_arg, this_is_output_file);
-      if (this_is_output_file)
-        outfiles[input_file_number] = string;
-      arg_going = 0;
-    }
+  if (processing_spec_function)
+    end_going_arg ();
 
   return 0;
 }
@@ -5418,6 +5991,7 @@ eval_spec_function (const char *func, const char *args)
   int save_this_is_output_file;
   int save_this_is_library_file;
   int save_input_from_pipe;
+  int save_this_is_linker_script;
   const char *save_suffix_subst;
 
 
@@ -5434,6 +6008,7 @@ eval_spec_function (const char *func, const char *args)
   save_delete_this_arg = delete_this_arg;
   save_this_is_output_file = this_is_output_file;
   save_this_is_library_file = this_is_library_file;
+  save_this_is_linker_script = this_is_linker_script;
   save_input_from_pipe = input_from_pipe;
   save_suffix_subst = suffix_subst;
 
@@ -5459,6 +6034,7 @@ eval_spec_function (const char *func, const char *args)
   delete_this_arg = save_delete_this_arg;
   this_is_output_file = save_this_is_output_file;
   this_is_library_file = save_this_is_library_file;
+  this_is_linker_script = save_this_is_linker_script;
   input_from_pipe = save_input_from_pipe;
   suffix_subst = save_suffix_subst;
 
@@ -5689,7 +6265,7 @@ handle_braces (const char *p)
          if (atom == end_atom)
            {
              if (!n_way_choice || disj_matched || *p == '|'
-                 || a_is_negated || a_is_suffix || a_is_spectype 
+                 || a_is_negated || a_is_suffix || a_is_spectype
                  || a_is_starred)
                goto invalid;
 
@@ -5703,7 +6279,7 @@ handle_braces (const char *p)
            {
              if ((a_is_suffix || a_is_spectype) && a_is_starred)
                goto invalid;
-             
+
              if (!a_is_starred)
                disj_starred = false;
 
@@ -5717,7 +6293,7 @@ handle_braces (const char *p)
                    a_matched = input_spec_matches (atom, end_atom);
                  else
                    a_matched = switch_matches (atom, end_atom, a_is_starred);
-                 
+
                  if (a_matched != a_is_negated)
                    {
                      disj_matched = true;
@@ -5863,17 +6439,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 > 0;
-
   /* Now search for duplicate in a manner that depends on the name.  */
   switch (*name)
     {
@@ -5919,7 +6497,7 @@ check_live_switch (int switchnum, int prefix_length)
     }
 
   /* Otherwise the switch is live.  */
-  switches[switchnum].live_cond = SWITCH_LIVE;
+  switches[switchnum].live_cond |= SWITCH_LIVE;
   return 1;
 }
 \f
@@ -5934,7 +6512,7 @@ check_live_switch (int switchnum, int prefix_length)
 static void
 give_switch (int switchnum, int omit_first_word)
 {
-  if (switches[switchnum].live_cond == SWITCH_IGNORE)
+  if ((switches[switchnum].live_cond & SWITCH_IGNORE) != 0)
     return;
 
   if (!omit_first_word)
@@ -5959,13 +6537,13 @@ give_switch (int switchnum, int omit_first_word)
              while (length-- && !IS_DIR_SEPARATOR (arg[length]))
                if (arg[length] == '.')
                  {
-                   ((char *)arg)[length] = 0;
+                   (CONST_CAST(char *, arg))[length] = 0;
                    dot = 1;
                    break;
                  }
              do_spec_1 (arg, 1, NULL);
              if (dot)
-               ((char *)arg)[length] = '.';
+               (CONST_CAST(char *, arg))[length] = '.';
              do_spec_1 (suffix_subst, 1, NULL);
            }
          else
@@ -6002,7 +6580,7 @@ is_directory (const char *path1, bool linker)
   /* Ensure the string ends with "/.".  The resulting path will be a
      directory even if the given path is a symbolic link.  */
   len1 = strlen (path1);
-  path = alloca (3 + len1);
+  path = (char *) alloca (3 + len1);
   memcpy (path, path1, len1);
   cp = path + len1;
   if (!IS_DIR_SEPARATOR (cp[-1]))
@@ -6034,16 +6612,7 @@ set_input (const char *filename)
 
   input_filename = filename;
   input_filename_length = strlen (input_filename);
-
-  input_basename = input_filename;
-#ifdef HAVE_DOS_BASED_FILE_SYSTEM
-  /* Skip drive name so 'x:foo' is handled properly.  */
-  if (input_basename[1] == ':')
-    input_basename += 2;
-#endif
-  for (p = input_basename; *p; p++)
-    if (IS_DIR_SEPARATOR (*p))
-      input_basename = p + 1;
+  input_basename = lbasename (input_filename);
 
   /* Find a suffix starting with the last period,
      and set basename_length to exclude that suffix.  */
@@ -6079,6 +6648,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 ((caddr_t) 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
@@ -6093,6 +6781,11 @@ main (int argc, char **argv)
   char *specs_file;
   const char *p;
   struct user_specs *uptr;
+  char **old_argv = argv;
+
+  /* Initialize here, not in definition.  The IRIX 6 O32 cc sometimes chokes
+     on ?: in file-scope variable initializations.  */
+  asm_debug = ASM_DEBUG_SPEC;
 
   p = argv[0] + strlen (argv[0]);
   while (p != argv[0] && !IS_DIR_SEPARATOR (p[-1]))
@@ -6103,6 +6796,10 @@ main (int argc, char **argv)
 
   expandargv (&argc, &argv);
 
+  /* Determine if any expansions were made.  */
+  if (argv != old_argv)
+    at_file_supplied = true;
+
   prune_options (&argc, &argv);
 
 #ifdef GCC_DRIVER_HOST_INITIALIZATION
@@ -6180,29 +6877,21 @@ main (int argc, char **argv)
     multilib_defaults = XOBFINISH (&multilib_obstack, const char *);
   }
 
-  /* Set up to remember the pathname of gcc and any options
-     needed for collect.  We use argv[0] instead of programname because
-     we need the complete pathname.  */
-  obstack_init (&collect_obstack);
-  obstack_grow (&collect_obstack, "COLLECT_GCC=", sizeof ("COLLECT_GCC=") - 1);
-  obstack_grow (&collect_obstack, argv[0], strlen (argv[0]) + 1);
-  putenv (XOBFINISH (&collect_obstack, char *));
-
 #ifdef INIT_ENVIRONMENT
   /* Set up any other necessary machine specific environment variables.  */
-  putenv (INIT_ENVIRONMENT);
+  xputenv (INIT_ENVIRONMENT);
 #endif
 
   /* Make a table of what switches there are (switches, n_switches).
      Make a table of specified input files (infiles, n_infiles).
      Decode switches that are handled locally.  */
 
-  process_command (argc, (const char **) argv);
+  process_command (argc, CONST_CAST2 (const char **, char **, argv));
 
   /* Initialize the vector of specs to just the default.
      This means one element containing 0s, as a terminator.  */
 
-  compilers = xmalloc (sizeof default_compilers);
+  compilers = XNEWVAR (struct compiler, sizeof default_compilers);
   memcpy (compilers, default_compilers, sizeof default_compilers);
   n_compilers = n_default_compilers;
 
@@ -6221,7 +6910,7 @@ main (int argc, char **argv)
 
   /* We need to check standard_exec_prefix/just_machine_suffix/specs
      for any override of as, ld and libraries.  */
-  specs_file = alloca (strlen (standard_exec_prefix)
+  specs_file = (char *) alloca (strlen (standard_exec_prefix)
                       + strlen (just_machine_suffix) + sizeof ("specs"));
 
   strcpy (specs_file, standard_exec_prefix);
@@ -6242,6 +6931,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')
@@ -6322,9 +7048,9 @@ main (int argc, char **argv)
       else if (*cross_compile == '0')
        {
          add_prefix (&startfile_prefixes,
-                     concat (gcc_exec_prefix 
-                             ? gcc_exec_prefix : standard_exec_prefix, 
-                             machine_suffix, 
+                     concat (gcc_exec_prefix
+                             ? gcc_exec_prefix : standard_exec_prefix,
+                             machine_suffix,
                              standard_startfile_prefix, NULL),
                      NULL, PREFIX_PRIORITY_LAST, 0, 1);
        }
@@ -6364,6 +7090,27 @@ main (int argc, char **argv)
      the subdirectory based on the options.  */
   set_multilib_dir ();
 
+  /* Set up to remember the pathname of gcc and any options
+     needed for collect.  We use argv[0] instead of programname because
+     we need the complete pathname.  */
+  obstack_init (&collect_obstack);
+  obstack_grow (&collect_obstack, "COLLECT_GCC=", sizeof ("COLLECT_GCC=") - 1);
+  obstack_grow (&collect_obstack, argv[0], strlen (argv[0]) + 1);
+  xputenv (XOBFINISH (&collect_obstack, char *));
+
+  /* Set up to remember the pathname of the lto wrapper. */
+
+  lto_wrapper_spec = find_a_file (&exec_prefixes, "lto-wrapper", X_OK, false);
+  if (lto_wrapper_spec)
+    {
+      obstack_init (&collect_obstack);
+      obstack_grow (&collect_obstack, "COLLECT_LTO_WRAPPER=",
+                   sizeof ("COLLECT_LTO_WRAPPER=") - 1);
+      obstack_grow (&collect_obstack, lto_wrapper_spec,
+                   strlen (lto_wrapper_spec) + 1);
+      xputenv (XOBFINISH (&collect_obstack, char *));
+    }
+
   /* Warn about any switches that no pass was interested in.  */
 
   for (i = 0; (int) i < n_switches; i++)
@@ -6412,6 +7159,18 @@ main (int argc, char **argv)
       return (0);
     }
 
+  if (print_sysroot)
+    {
+      if (target_system_root)
+       {
+          if (target_sysroot_suffix)
+           printf ("%s%s\n", target_system_root, target_sysroot_suffix);
+          else
+           printf ("%s\n", target_system_root);
+       }
+      return (0);
+    }
+
   if (print_multi_os_directory)
     {
       if (multilib_os_dir == NULL)
@@ -6450,7 +7209,28 @@ main (int argc, char **argv)
 
       /* We do not exit here.  Instead we have created a fake input file
         called 'help-dummy' which needs to be compiled, and we pass this
-        on the various sub-processes, along with the --help switch.  */
+        on the various sub-processes, along with the --help switch.
+        Ensure their output appears after ours.  */
+      fputc ('\n', stdout);
+      fflush (stdout);
+    }
+
+  if (print_version)
+    {
+      printf (_("%s %s%s\n"), programname, pkgversion_string,
+             version_string);
+      printf ("Copyright %s 2009 Free Software Foundation, Inc.\n",
+             _("(C)"));
+      fputs (_("This is free software; see the source for copying conditions.  There is NO\n\
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"),
+            stdout);
+      if (! verbose_flag)
+       return 0;
+
+      /* We do not exit here. We use the same mechanism of --help to print
+        the version of the sub-processes. */
+      fputc ('\n', stdout);
+      fflush (stdout);
     }
 
   if (verbose_flag)
@@ -6484,10 +7264,10 @@ main (int argc, char **argv)
 
       if (! strncmp (version_string, compiler_version, n)
          && compiler_version[n] == 0)
-       notice ("gcc version %s\n", version_string);
+       notice ("gcc version %s %s\n", version_string, pkgversion_string);
       else
-       notice ("gcc driver version %s executing gcc version %s\n",
-               version_string, compiler_version);
+       notice ("gcc driver version %s %sexecuting gcc version %s\n",
+               version_string, pkgversion_string, compiler_version);
 
       if (n_infiles == 0)
        return (0);
@@ -6543,7 +7323,7 @@ main (int argc, char **argv)
     }
 
   if (!combine_inputs && have_c && have_o && lang_n_infiles > 1)
-   fatal ("cannot specify -o with -c or -S with multiple files");
+   fatal ("cannot specify -o with -c, -S or -E with multiple files");
 
   if (combine_flag && save_temps_flag)
     {
@@ -6637,10 +7417,63 @@ main (int argc, char **argv)
            }
          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;
+               }
            }
        }
 
@@ -6698,6 +7531,7 @@ main (int argc, char **argv)
   if (num_linker_inputs > 0 && error_count == 0 && print_subprocess_help < 2)
     {
       int tmp = execution_count;
+      const char *fuse_linker_plugin = "fuse-linker-plugin";
 
       /* We'll use ld if we can't find collect2.  */
       if (! strcmp (linker_name_spec, "collect2"))
@@ -6706,6 +7540,23 @@ main (int argc, char **argv)
          if (s == NULL)
            linker_name_spec = "ld";
        }
+
+      if (switch_matches (fuse_linker_plugin,
+                         fuse_linker_plugin + strlen (fuse_linker_plugin), 0))
+       {
+         linker_plugin_file_spec = find_a_file (&exec_prefixes,
+                                                "liblto_plugin.so", X_OK,
+                                                false);
+         if (!linker_plugin_file_spec)
+           fatal ("-fuse-linker-plugin, but liblto_plugin.so not found");
+
+         lto_libgcc_spec = find_a_file (&startfile_prefixes, "libgcc.a",
+                                        R_OK, true);
+         if (!lto_libgcc_spec)
+           fatal ("could not find libgcc.a");
+       }
+      lto_gcc_spec = argv[0];
+
       /* Rebuild the COMPILER_PATH and LIBRARY_PATH environment variables
         for collect.  */
       putenv_from_prefixes (&exec_prefixes, "COMPILER_PATH", false);
@@ -6729,7 +7580,8 @@ main (int argc, char **argv)
 
   if (! linker_was_run && error_count == 0)
     for (i = 0; (int) i < n_infiles; i++)
-      if (explicit_link_files[i])
+      if (explicit_link_files[i]
+         && !(infiles[i].language && infiles[i].language[0] == '*'))
        error ("%s: linker input file unused because linking not done",
               outfiles[i]);
 
@@ -7053,7 +7905,8 @@ used_arg (const char *p, int len)
        if (*q == ';')
          cnt++;
 
-      matches = alloca ((sizeof (struct mswitchstr)) * cnt);
+      matches
+       = (struct mswitchstr *) alloca ((sizeof (struct mswitchstr)) * cnt);
       i = 0;
       q = multilib_matches;
       while (*q != '\0')
@@ -7090,7 +7943,7 @@ used_arg (const char *p, int len)
       mswitches
        = XNEWVEC (struct mswitchstr, n_mdswitches + (n_switches ? n_switches : 1));
       for (i = 0; i < n_switches; i++)
-       if (switches[i].live_cond != SWITCH_IGNORE)
+       if ((switches[i].live_cond & SWITCH_IGNORE) == 0)
          {
            int xlen = strlen (switches[i].part1);
            for (j = 0; j < cnt; j++)
@@ -7412,7 +8265,7 @@ set_multilib_dir (void)
   if (multilib_dir == NULL && multilib_os_dir != NULL
       && strcmp (multilib_os_dir, ".") == 0)
     {
-      free ((char *) multilib_os_dir);
+      free (CONST_CAST (char *, multilib_os_dir));
       multilib_os_dir = NULL;
     }
   else if (multilib_dir != NULL && multilib_os_dir == NULL)
@@ -7689,6 +8542,9 @@ static const char *
 getenv_spec_function (int argc, const char **argv)
 {
   char *value;
+  char *result;
+  char *ptr;
+  size_t len;
 
   if (argc != 2)
     return NULL;
@@ -7697,7 +8553,21 @@ getenv_spec_function (int argc, const char **argv)
   if (!value)
     fatal ("environment variable \"%s\" not defined", argv[0]);
 
-  return concat (value, argv[1], NULL);
+  /* We have to escape every character of the environment variable so
+     they are not interpreted as active spec characters.  A
+     particularly painful case is when we are reading a variable
+     holding a windows path complete with \ separators.  */
+  len = strlen (value) * 2 + strlen (argv[1]) + 1;
+  result = XNEWVAR (char, len);
+  for (ptr = result; *value; ptr += 2)
+    {
+      ptr[0] = '\\';
+      ptr[1] = *value++;
+    }
+
+  strcpy (ptr, argv[1]);
+
+  return result;
 }
 
 /* if-exists built-in spec function.
@@ -7888,7 +8758,7 @@ include_spec_function (int argc, const char **argv)
   if (argc != 1)
     abort ();
 
-  file = find_a_file (&startfile_prefixes, argv[0], R_OK, 0);
+  file = find_a_file (&startfile_prefixes, argv[0], R_OK, true);
   read_specs (file ? file : argv[0], FALSE);
 
   return NULL;
@@ -7901,8 +8771,179 @@ static const char *
 print_asm_header_spec_function (int arg ATTRIBUTE_UNUSED,
                                const char **argv ATTRIBUTE_UNUSED)
 {
-  printf (_("Assember options\n================\n\n"));
+  printf (_("Assembler options\n=================\n\n"));
   printf (_("Use \"-Wa,OPTION\" to pass \"OPTION\" to the assembler.\n\n"));
   fflush (stdout);
   return NULL;
 }
+
+/* Compute a timestamp to initialize flag_random_seed.  */
+
+static unsigned
+get_local_tick (void)
+{
+  unsigned ret = 0;
+
+  /* Get some more or less random data.  */
+#ifdef HAVE_GETTIMEOFDAY
+  {
+    struct timeval tv;
+
+    gettimeofday (&tv, NULL);
+    ret = tv.tv_sec * 1000 + tv.tv_usec / 1000;
+  }
+#else
+  {
+    time_t now = time (NULL);
+
+    if (now != (time_t)-1)
+      ret = (unsigned) now;
+  }
+#endif
+
+  return ret;
+}
+
+/* %: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;
+  static char random_seed[HOST_BITS_PER_WIDE_INT / 4 + 3];
+
+  if (arg != 0)
+    fatal ("too many arguments to %%:compare-debug-dump-opt");
+
+  do_spec_2 ("%{fdump-final-insns=*:%*}");
+  do_spec_1 (" ", 0, NULL);
+
+  if (argbuf_index > 0 && strcmp (argv[argbuf_index - 1], "."))
+    {
+      if (!compare_debug)
+       return NULL;
+
+      name = xstrdup (argv[argbuf_index - 1]);
+      ret = NULL;
+    }
+  else
+    {
+      const char *ext = NULL;
+
+      if (argbuf_index > 0)
+       {
+         do_spec_2 ("%{o*:%*}%{!o:%{!S:%b%O}%{S:%b.s}}");
+         ext = ".gkd";
+       }
+      else if (!compare_debug)
+       return NULL;
+      else
+       do_spec_2 ("%g.gkd");
+
+      do_spec_1 (" ", 0, NULL);
+
+      gcc_assert (argbuf_index > 0);
+
+      name = concat (argbuf[argbuf_index - 1], ext, NULL);
+
+      ret = concat ("-fdump-final-insns=", name, NULL);
+    }
+
+  which = compare_debug < 0;
+  debug_check_temp_file[which] = name;
+
+  if (!which)
+    {
+      unsigned HOST_WIDE_INT value = get_local_tick () ^ getpid ();
+
+      sprintf (random_seed, HOST_WIDE_INT_PRINT_HEX, value);
+    }
+
+  if (*random_seed)
+    ret = concat ("%{!frandom-seed=*:-frandom-seed=", random_seed, "} ",
+                 ret, NULL);
+
+  if (which)
+    *random_seed = 0;
+
+  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';
+
+#undef OPT
+
+  return name;
+}