OSDN Git Service

Add -mabi=n32 support.
[pf3gnuchains/gcc-fork.git] / gcc / toplev.c
index d10c38b..5d5eb45 100644 (file)
@@ -1,5 +1,5 @@
 /* Top level of GNU C compiler
-   Copyright (C) 1987, 88, 89, 92, 93, 1994 Free Software Foundation, Inc.
+   Copyright (C) 1987, 88, 89, 92-5, 1996 Free Software Foundation, Inc.
 
 This file is part of GNU CC.
 
@@ -15,8 +15,8 @@ GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with GNU CC; see the file COPYING.  If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
-
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
 
 /* This is the top level of cc1/c++.
    It parses command args, opens files, invokes the various passes
@@ -36,6 +36,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include <ctype.h>
 #include <sys/stat.h>
 
+#ifndef _WIN32
 #ifdef USG
 #undef FLOAT
 #include <sys/param.h>
@@ -50,35 +51,42 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include <sys/resource.h>
 #endif
 #endif
+#endif
 
 #include "input.h"
 #include "tree.h"
-/* #include "c-tree.h" */
 #include "rtl.h"
 #include "flags.h"
 #include "insn-attr.h"
 #include "defaults.h"
+#include "output.h"
+#include "bytecode.h"
+#include "bc-emit.h"
 
 #ifdef XCOFF_DEBUGGING_INFO
 #include "xcoffout.h"
 #endif
-
-#include "bytecode.h"
-#include "bc-emit.h"
 \f
 #ifdef VMS
 /* The extra parameters substantially improve the I/O performance.  */
 static FILE *
-VMS_fopen (fname, type)
+vms_fopen (fname, type)
      char * fname;
      char * type;
 {
-  if (strcmp (type, "w") == 0)
-    return fopen (fname, type, "mbc=16", "deq=64", "fop=tef", "shr=nil");
-  return fopen (fname, type, "mbc=16");
+  /* The <stdio.h> in the gcc-vms-1.42 distribution prototypes fopen with two
+     fixed arguments, which matches ANSI's specification but not VAXCRTL's
+     pre-ANSI implementation.  This hack circumvents the mismatch problem.  */
+  FILE *(*vmslib_fopen)() = (FILE *(*)()) fopen;
+
+  if (*type == 'w')
+    return (*vmslib_fopen) (fname, type, "mbc=32",
+                           "deq=64", "fop=tef", "shr=nil");
+  else
+    return (*vmslib_fopen) (fname, type, "mbc=32");
 }
-#define fopen VMS_fopen
-#endif
+#define fopen vms_fopen
+#endif /* VMS */
 
 #ifndef DEFAULT_GDB_EXTENSIONS
 #define DEFAULT_GDB_EXTENSIONS 1
@@ -130,9 +138,18 @@ void fancy_abort ();
 void abort ();
 #endif
 void set_target_switch ();
-static void print_switch_values ();
 static char *decl_name ();
 
+void print_version ();
+int print_single_switch ();
+void print_switch_values ();
+/* Length of line when printing switch values.  */
+#define MAX_LINE 75
+
+#ifdef __alpha
+extern char *sbrk ();
+#endif
+
 /* Name of program invoked, sans directories.  */
 
 char *progname;
@@ -254,6 +271,16 @@ struct rtx_def *(*lang_expand_expr) ();
 
 void (*incomplete_decl_finalize_hook) () = 0;
 
+/* Pointer to function for interim exception handling implementation.
+   This interface will change, and it is only here until a better interface
+   replaces it.  */
+
+void (*interim_eh_hook)        PROTO((tree));
+
+/* Highest label number used at the end of reload.  */
+
+int max_label_num_after_reload;
+
 /* Nonzero if generating code to do profiling.  */
 
 int profile_flag = 0;
@@ -385,6 +412,11 @@ int flag_no_function_cse = 0;
 
 int flag_omit_frame_pointer = 0;
 
+/* Nonzero means place each function into its own section on those platforms
+   which support arbitrary section names and unlimited numbers of sections.  */
+
+int flag_function_sections = 0;
+
 /* Nonzero to inhibit use of define_optimization peephole opts.  */
 
 int flag_no_peephole = 0;
@@ -424,11 +456,7 @@ int flag_inline_functions;
 
 int flag_keep_inline_functions;
 
-/* Nonzero means that functions declared `inline' will be treated
-   as `static'.  Prevents generation of zillions of copies of unused
-   static inline functions; instead, `inlines' are written out
-   only when actually used.  Used in conjunction with -g.  Also
-   does the right thing with #pragma interface.  */
+/* Nonzero means that functions will not be inlined.  */
 
 int flag_no_inline;
 
@@ -459,7 +487,8 @@ int flag_short_temps;
 
 int flag_pic;
 
-/* Nonzero means place uninitialized global data in the bss section. */
+/* Nonzero means don't place uninitialized global data in common storage
+   by default. */
 
 int flag_no_common;
 
@@ -491,9 +520,20 @@ int flag_inhibit_size_directive = 0;
 /* -fverbose-asm causes extra commentary information to be produced in
    the generated assembly code (to make it more readable).  This option
    is generally only of use to those who actually need to read the
-   generated assembly code (perhaps while debugging the compiler itself).  */
+   generated assembly code (perhaps while debugging the compiler itself).
+   -fverbose-asm is the default.  -fno-verbose-asm causes the extra information
+   to be omitted and is useful when comparing two assembler files.  */
+
+int flag_verbose_asm = 1;
+
+/* -dA causes debug commentary information to be produced in
+   the generated assembly code (to make it more readable).  This option
+   is generally only of use to those who actually need to read the
+   generated assembly code (perhaps while debugging the compiler itself).
+   Currently, this switch is only used by dwarfout.c; however, it is intended
+   to be a catchall for printing debug information in the assembler file.  */
 
-int flag_verbose_asm = 0;
+int flag_debug_asm = 0;
 
 /* -fgnu-linker specifies use of the GNU linker for initializations.
    (Or, more generally, a linker that handles initializations.)
@@ -504,6 +544,9 @@ int flag_gnu_linker = 0;
 int flag_gnu_linker = 1;
 #endif
 
+/* Tag all structures with __attribute__(packed) */
+int flag_pack_struct = 0;
+
 /* Table of language-independent -f options.
    STRING is the option name.  VARIABLE is the address of the variable.
    ON_VALUE is the value to store in VARIABLE
@@ -547,8 +590,10 @@ struct { char *string; int *variable; int on_value;} f_options[] =
   {"fast-math", &flag_fast_math, 1},
   {"common", &flag_no_common, 0},
   {"inhibit-size-directive", &flag_inhibit_size_directive, 1},
+  {"function-sections", &flag_function_sections, 1},
   {"verbose-asm", &flag_verbose_asm, 1},
   {"gnu-linker", &flag_gnu_linker, 1},
+  {"pack-struct", &flag_pack_struct, 1},
   {"bytecode", &output_bytecode, 1}
 };
 
@@ -589,6 +634,8 @@ char *lang_options[] =
   "-fno-short-enums",
 
   "-Wall",
+  "-Wbad-function-cast",
+  "-Wno-bad-function-cast",
   "-Wcast-qual",
   "-Wno-cast-qual",
   "-Wchar-subscripts",
@@ -619,6 +666,8 @@ char *lang_options[] =
   "-Wno-pointer-arith",
   "-Wredundant-decls",
   "-Wno-redundant-decls",
+  "-Wsign-compare",
+  "-Wno-sign-compare",
   "-Wstrict-prototypes",
   "-Wno-strict-prototypes",
   "-Wtraditional",
@@ -628,76 +677,6 @@ char *lang_options[] =
   "-Wwrite-strings",
   "-Wno-write-strings",
 
-  /* These are for C++.  */
-  "-+e0",                      /* gcc.c tacks the `-' on the front.  */
-  "-+e1",
-  "-+e2",
-  "-fall-virtual",
-  "-fno-all-virtual",
-  "-falt-external-templates",
-  "-fno-alt-external-templates",
-  "-fansi-overloading",
-  "-fno-ansi-overloading",
-  "-fcadillac",
-  "-fno-cadillac",
-  "-fconserve-space",
-  "-fno-conserve-space",
-  "-fdefault-inline",
-  "-fno-default-inline",
-  "-fdossier",
-  "-fno-dossier",
-  "-felide-constructors",
-  "-fno-elide-constructors",
-  "-fenum-int-equiv",
-  "-fno-enum-int-equiv",
-  "-fexternal-templates",
-  "-fno-external-templates",
-  "-fgc",
-  "-fno-gc",
-  "-fhandle-exceptions",
-  "-fno-handle-exceptions",
-  "-fhandle-signatures",
-  "-fno-handle-signatures",
-  "-fhuge-objects",
-  "-fno-huge-objects",
-  "-fimplement-inlines",
-  "-fno-implement-inlines",
-  "-fimplicit-templates",
-  "-fno-implicit-templates",
-  "-flabels-ok",
-  "-fno-labels-ok",
-  "-fmemoize-lookups",
-  "-fno-memoize-lookups",
-  "-fnonnull-objects",
-  "-fno-nonnull-objects",
-  "-fsave-memoized",
-  "-fno-save-memoized",
-  "-fshort-temps",
-  "-fno-short-temps",
-  "-fstats",
-  "-fno-stats",
-  "-fstrict-prototype",
-  "-fno-strict-prototype",
-  "-fthis-is-variable",
-  "-fno-this-is-variable",
-  "-fvtable-thunks",
-  "-fno-vtable-thunks",
-  "-fxref",
-  "-fno-xref",
-
-  "-Wreturn-type",
-  "-Wno-return-type",
-  "-Woverloaded-virtual",
-  "-Wno-overloaded-virtual",
-  "-Wenum-clash",
-  "-Wno-enum-clash",
-  "-Wtemplate-debugging",
-  "-Wno-template-debugging",
-  "-Wctor-dtor-privacy",
-  "-Wno-ctor-dtor-privacy",
-  "-Wextern-inline",
-  "-Wno-extern-inline",
-
   /* these are for obj c */
   "-lang-objc",
   "-gen-decls",
@@ -710,8 +689,7 @@ char *lang_options[] =
   "-Wprotocol",
   "-Wno-protocol",
 
-  /* This is for GNAT and is temporary.  */
-  "-gnat",
+#include "options.h"
   0
 };
 \f
@@ -839,12 +817,13 @@ int dump_time;
 int
 get_run_time ()
 {
+#ifndef _WIN32
 #ifdef USG
   struct tms tms;
 #else
 #ifndef VMS
   struct rusage rusage;
-#else /* VMS */
+#else
   struct
     {
       int proc_user_time;
@@ -854,10 +833,16 @@ get_run_time ()
     } vms_times;
 #endif
 #endif
+#endif
 
   if (quiet_flag)
     return 0;
-
+#ifdef _WIN32
+  if (clock() < 0)
+    return 0;
+  else
+    return (clock() * 1000);
+#else /* not _WIN32 */
 #ifdef USG
   times (&tms);
   return (tms.tms_utime + tms.tms_stime) * (1000000 / HZ);
@@ -871,6 +856,7 @@ get_run_time ()
   return (vms_times.proc_user_time + vms_times.proc_system_time) * 10000;
 #endif
 #endif
+#endif
 }
 
 #define TIMEVAR(VAR, BODY)    \
@@ -921,7 +907,7 @@ pfatal_with_name (name)
 {
   fprintf (stderr, "%s: ", progname);
   perror (name);
-  exit (35);
+  exit (FATAL_EXIT_CODE);
 }
 
 void
@@ -929,23 +915,20 @@ fatal_io_error (name)
      char *name;
 {
   fprintf (stderr, "%s: %s: I/O error\n", progname, name);
-  exit (35);
+  exit (FATAL_EXIT_CODE);
 }
 
-/* Called to give a better error message when we don't have an insn to match
-   what we are looking for or if the insn's constraints aren't satisfied,
-   rather than just calling abort().  */
+/* Called to give a better error message for a bad insn rather than
+   just calling abort().  */
 
 void
-fatal_insn_not_found (insn)
+fatal_insn (message, insn)
+     char *message;
      rtx insn;
 {
   if (!output_bytecode)
     {
-      if (INSN_CODE (insn) < 0)
-       error ("internal error--unrecognizable insn:");
-      else
-       error ("internal error--insn does not satisfy its constraints:");
+      error (message);
       debug_rtx (insn);
     }
   if (asm_out_file)
@@ -980,9 +963,25 @@ fatal_insn_not_found (insn)
     fflush (dbr_sched_dump_file);
   if (stack_reg_dump_file)
     fflush (stack_reg_dump_file);
+  fflush (stdout);
+  fflush (stderr);
   abort ();
 }
 
+/* Called to give a better error message when we don't have an insn to match
+   what we are looking for or if the insn's constraints aren't satisfied,
+   rather than just calling abort().  */
+
+void
+fatal_insn_not_found (insn)
+     rtx insn;
+{
+  if (INSN_CODE (insn) < 0)
+    fatal_insn ("internal error--unrecognizable insn:", insn);
+  else
+    fatal_insn ("internal error--insn does not satisfy its constraints:", insn);
+}
+
 /* This is the default decl_printable_name function.  */
 
 static char *
@@ -992,6 +991,15 @@ decl_name (decl, kind)
 {
   return IDENTIFIER_POINTER (DECL_NAME (decl));
 }
+
+/* This is the default interim_eh_hook function.  */
+
+void
+interim_eh (finalization)
+     tree finalization;
+{
+  /* Don't do anything by default.  */
+}
 \f
 static int need_error_newline;
 
@@ -1023,21 +1031,13 @@ announce_function (decl)
     }
 }
 
-/* Prints out, if necessary, the name of the current function
-   which caused an error.  Called from all error and warning functions.  */
+/* The default function to print out name of current function that caused
+   an error.  */
 
 void
-report_error_function (file)
+default_print_error_function (file)
      char *file;
 {
-  struct file_stack *p;
-
-  if (need_error_newline)
-    {
-      fprintf (stderr, "\n");
-      need_error_newline = 0;
-    }
-
   if (last_error_function != current_function_decl)
     {
       char *kind = "function";
@@ -1058,8 +1058,33 @@ report_error_function (file)
 
       last_error_function = current_function_decl;
     }
+}
+
+/* Called by report_error_function to print out function name.
+ * Default may be overridden by language front-ends. */
+
+void (*print_error_function) PROTO((char*)) = default_print_error_function;
+
+/* Prints out, if necessary, the name of the current function
+  that caused an error.  Called from all error and warning functions.  */
+
+void
+report_error_function (file)
+     char *file;
+{
+  struct file_stack *p;
+
+  if (need_error_newline)
+    {
+      fprintf (stderr, "\n");
+      need_error_newline = 0;
+    }
+
+  (*print_error_function) (file);
+
   if (input_file_stack && input_file_stack->next != 0
-      && input_file_stack_tick != last_error_tick)
+      && input_file_stack_tick != last_error_tick
+      && file == input_filename)
     {
       fprintf (stderr, "In file included");
       for (p = input_file_stack->next; p; p = p->next)
@@ -1091,7 +1116,8 @@ vmessage (prefix, s, ap)
     HOST_WIDE_INT v1 = va_arg(ap, HOST_WIDE_INT);
     HOST_WIDE_INT v2 = va_arg(ap, HOST_WIDE_INT);
     HOST_WIDE_INT v3 = va_arg(ap, HOST_WIDE_INT);
-    fprintf (stderr, s, v1, v2, v3);
+    HOST_WIDE_INT v4 = va_arg(ap, HOST_WIDE_INT);
+    fprintf (stderr, s, v1, v2, v3, v4);
   }
 #endif
 }
@@ -1147,10 +1173,17 @@ v_message_with_decl (decl, prefix, s, ap)
        }
     }
 
-  if (p > s)
-    fwrite (s, p - s, 1, stderr);
+  if (p > s)                   /* Print the left-hand substring.  */
+    {
+      char fmt[sizeof "%.255s"];
+      long width = p - s;
+             
+      if (width > 255L) width = 255L;  /* arbitrary */
+      sprintf (fmt, "%%.%lds", width);
+      fprintf (stderr, fmt, s);
+    }
 
-  if (*p == '%')
+  if (*p == '%')               /* Print the name.  */
     {
       char *n = (DECL_NAME (decl)
                 ? (*decl_printable_name) (decl, &junk)
@@ -1164,7 +1197,7 @@ v_message_with_decl (decl, prefix, s, ap)
        }
     }
 
-  if (*p)
+  if (*p)                      /* Print the rest of the message.  */
     vmessage ((char *)NULL, p, ap);
 
   fputc ('\n', stderr);
@@ -1353,7 +1386,7 @@ vfatal (s, ap)
      va_list ap;
 {
   verror (s, ap);
-  exit (34);
+  exit (FATAL_EXIT_CODE);
 }
 
 void
@@ -1751,6 +1784,20 @@ xrealloc (ptr, size)
     fatal ("virtual memory exhausted");
   return result;
 }
+
+/* Same as `strdup' but report error if no memory available.  */
+
+char *
+xstrdup (s)
+     register char *s;
+{
+  register char *result = (char *) malloc (strlen (s) + 1);
+
+  if (! result)
+    fatal ("virtual memory exhausted");
+  strcpy (result, s);
+  return result;
+}
 \f
 /* Return the logarithm of X, base 2, considering X unsigned,
    if X is a power of 2.  Otherwise, returns -1.
@@ -1861,39 +1908,21 @@ pipe_closed (signo)
 }
 
 /* Strip off a legitimate source ending from the input string NAME of
-   length LEN. */
+   length LEN.  Rather than having to know the names used by all of
+   our front ends, we strip off an ending of a period followed by one,
+   two, or three characters.  */
 
 void
 strip_off_ending (name, len)
      char *name;
      int len;
 {
-  if (len > 2 && ! strcmp (".c", name + len - 2))
-    name[len - 2] = 0;
-  else if (len > 2 && ! strcmp (".m", name + len - 2))
-    name[len - 2] = 0;
-  else if (len > 2 && ! strcmp (".i", name + len - 2))
-    name[len - 2] = 0;
-  else if (len > 3 && ! strcmp (".ii", name + len - 3))
-    name[len - 3] = 0;
-  else if (len > 3 && ! strcmp (".co", name + len - 3))
-    name[len - 3] = 0;
-  else if (len > 3 && ! strcmp (".cc", name + len - 3))
-    name[len - 3] = 0;
-  else if (len > 2 && ! strcmp (".C", name + len - 2))
-    name[len - 2] = 0;
-  else if (len > 4 && ! strcmp (".cxx", name + len - 4))
-    name[len - 4] = 0;
-  else if (len > 4 && ! strcmp (".cpp", name + len - 4))
-    name[len - 4] = 0;
-  else if (len > 2 && ! strcmp (".f", name + len - 2))
-    name[len - 2] = 0;
-  /* Ada will use extensions like .ada, .adb, and .ads, so just test
-     for "ad".  */
-  else if (len > 4 && ! strncmp (".ad", name + len - 4, 3))
-    name[len - 4] = 0;
-  else if (len > 4 && ! strcmp (".atr", name + len - 4))
-    name[len - 4] = 0;
+  if (len > 2 && name[len - 2] == '.')
+    name[len - 2] = '\0';
+  else if (len > 3 && name[len - 3] == '.')
+    name[len - 3] = '\0';
+  else if (len > 4 && name[len - 4] == '.')
+    name[len - 4] = '\0';
 }
 
 /* Output a quoted string.  */
@@ -2147,6 +2176,12 @@ compile_file (name)
 
   input_filename = name;
 
+  /* Put an entry on the input file stack for the main input file.  */
+  input_file_stack
+    = (struct file_stack *) xmalloc (sizeof (struct file_stack));
+  input_file_stack->next = 0;
+  input_file_stack->name = input_filename;
+
   /* Perform language-specific initialization.
      This may set main_input_filename.  */
   lang_init ();
@@ -2156,15 +2191,22 @@ compile_file (name)
   if (main_input_filename == 0)
     main_input_filename = name;
 
-  /* Put an entry on the input file stack for the main input file.  */
-  input_file_stack
-    = (struct file_stack *) xmalloc (sizeof (struct file_stack));
-  input_file_stack->next = 0;
-  input_file_stack->name = input_filename;
-
   if (!output_bytecode)
     {
       ASM_FILE_START (asm_out_file);
+
+#ifdef ASM_COMMENT_START
+      if (flag_verbose_asm)
+       {
+         /* Print the list of options in effect.  */
+         print_version (asm_out_file, ASM_COMMENT_START);
+         print_switch_values (asm_out_file, 0, MAX_LINE,
+                              ASM_COMMENT_START, " ", "\n");
+         /* Add a blank line here so it appears in assembler output but not
+            screen output.  */
+         fprintf (asm_out_file, "\n");
+       }
+#endif
     }
 
   /* Output something to inform GDB that this compilation was by GCC.  Also
@@ -2185,6 +2227,24 @@ compile_file (name)
   ASM_IDENTIFY_LANGUAGE (asm_out_file);
 #endif
 
+#ifndef ASM_OUTPUT_SECTION_NAME
+  if (flag_function_sections)
+    {
+      warning ("-ffunction-sections not supported for this target.");
+      flag_function_sections = 0;
+    }
+#endif
+
+  if (flag_function_sections
+      && (profile_flag || profile_block_flag))
+    {
+      warning ("-ffunction-sections disabled; it makes profiling impossible.");
+      flag_function_sections = 0;
+    }
+
+  if (flag_function_sections && write_symbols != NO_DEBUG)
+    warning ("-ffunction-sections may affect debugging on some targets.");
+
   if (output_bytecode)
     {
       if (profile_flag || profile_block_flag)
@@ -2265,6 +2325,7 @@ compile_file (name)
     tree *vec = (tree *) alloca (sizeof (tree) * len);
     int i;
     tree decl;
+    int reconsider = 1;
 
     /* Process the decls in reverse order--earliest first.
        Put them into VEC from back to front, then take out from front.  */
@@ -2282,10 +2343,21 @@ compile_file (name)
        if (TREE_CODE (decl) == VAR_DECL && DECL_SIZE (decl) == 0
            && incomplete_decl_finalize_hook != 0)
          (*incomplete_decl_finalize_hook) (decl);
+      }
 
-       if (TREE_CODE (decl) == VAR_DECL && TREE_STATIC (decl)
-           && ! TREE_ASM_WRITTEN (decl))
+    /* Now emit any global variables or functions that we have been putting
+       off.  We need to loop in case one of the things emitted here
+       references another one which comes earlier in the list.  */
+    while (reconsider)
+      {
+       reconsider = 0;
+       for (i = 0; i < len; i++)
          {
+           decl = vec[i];
+
+           if (TREE_ASM_WRITTEN (decl) || DECL_EXTERNAL (decl))
+             continue;
+
            /* Don't write out static consts, unless we still need them.
 
               We also keep static consts if not optimizing (for debugging).
@@ -2310,57 +2382,61 @@ compile_file (name)
               to force a constant to be written if and only if it is
               defined in a main file, as opposed to an include file. */
 
-           if (! TREE_READONLY (decl)
-               || TREE_PUBLIC (decl)
-               || !optimize
-               || TREE_ADDRESSABLE (decl)
-               || TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (decl)))
-             rest_of_decl_compilation (decl, NULL_PTR, 1, 1);
-           else
-             /* Cancel the RTL for this decl so that, if debugging info
-                output for global variables is still to come,
-                this one will be omitted.  */
-             DECL_RTL (decl) = NULL;
+           if (TREE_CODE (decl) == VAR_DECL && TREE_STATIC (decl)
+               && (! TREE_READONLY (decl)
+                   || TREE_PUBLIC (decl)
+                   || !optimize
+                   || TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))))
+             {
+               reconsider = 1;
+               rest_of_decl_compilation (decl, NULL_PTR, 1, 1);
+             }
+
+           if (TREE_CODE (decl) == FUNCTION_DECL
+               && DECL_INITIAL (decl) != 0
+               && DECL_SAVED_INSNS (decl) != 0
+               && (flag_keep_inline_functions
+                   || TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))))
+             {
+               reconsider = 1;
+               temporary_allocation ();
+               output_inline_function (decl);
+               permanent_allocation (1);
+             }
          }
+      }
 
-       if (TREE_CODE (decl) == FUNCTION_DECL
-           && ! TREE_ASM_WRITTEN (decl)
-           && DECL_INITIAL (decl) != 0
-           && DECL_SAVED_INSNS (decl) != 0
-           && (TREE_ADDRESSABLE (decl)
-               || flag_keep_inline_functions
-               || TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (decl)))
-           && ! DECL_EXTERNAL (decl))
-         {
-           temporary_allocation ();
-           output_inline_function (decl);
-           permanent_allocation (1);
-         }
+    for (i = 0; i < len; i++)
+      {
+       decl = vec[i];
+
+       if (TREE_CODE (decl) == VAR_DECL && TREE_STATIC (decl)
+           && ! TREE_ASM_WRITTEN (decl))
+         /* Cancel the RTL for this decl so that, if debugging info
+            output for global variables is still to come,
+            this one will be omitted.  */
+         DECL_RTL (decl) = NULL;
 
        /* Warn about any function
           declared static but not defined.
           We don't warn about variables,
           because many programs have static variables
           that exist only to get some text into the object file.  */
-       if ((warn_unused
-            || TREE_USED (decl)
-            || (DECL_NAME (decl) && TREE_USED (DECL_NAME (decl))))
-           && TREE_CODE (decl) == FUNCTION_DECL
+       if (TREE_CODE (decl) == FUNCTION_DECL
+           && (warn_unused
+               || TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)))
            && DECL_INITIAL (decl) == 0
            && DECL_EXTERNAL (decl)
+           && ! DECL_ARTIFICIAL (decl)
            && ! TREE_PUBLIC (decl))
          {
-           /* This should be a pedwarn, except that there is
-              no easy way to prevent it from happening when the
-              name is used only inside a sizeof.
-              This at least avoids being incorrect.  */
-           warning_with_decl (decl, 
+           pedwarn_with_decl (decl, 
                               "`%s' declared `static' but never defined");
            /* This symbol is effectively an "extern" declaration now.  */
            TREE_PUBLIC (decl) = 1;
            assemble_external (decl);
-
          }
+
        /* Warn about static fns or vars defined but not used,
           but not about inline functions or static consts
           since defining those in header files is normal practice.  */
@@ -2371,7 +2447,7 @@ compile_file (name)
            && ! DECL_EXTERNAL (decl)
            && ! TREE_PUBLIC (decl)
            && ! TREE_USED (decl)
-           && ! DECL_REGISTER (decl)
+           && (TREE_CODE (decl) == FUNCTION_DECL || ! DECL_REGISTER (decl))
            /* The TREE_USED bit for file-scope decls
               is kept in the identifier, to handle multiple
               external decls in different scopes.  */
@@ -2412,6 +2488,10 @@ compile_file (name)
       }
   }
 
+  /* Write out any pending weak symbol declarations.  */
+
+  weak_finish ();
+
   /* Do dbx symbols */
 #if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO)
   if (write_symbols == DBX_DEBUG || write_symbols == XCOFF_DEBUG)
@@ -2589,7 +2669,8 @@ rest_of_decl_compilation (decl, asmspec, top_level, at_end)
                        && (DECL_INITIAL (decl) == 0
                            || DECL_INITIAL (decl) == error_mark_node)))
                   assemble_variable (decl, top_level, at_end, 0);
-              if (decl == last_assemble_variable_decl)
+              if (!output_bytecode
+                  && decl == last_assemble_variable_decl)
                 {
                   ASM_FINISH_DECLARE_OBJECT (asm_out_file, decl,
                                              top_level, at_end);
@@ -2663,21 +2744,19 @@ rest_of_compilation (decl)
 
   if (DECL_SAVED_INSNS (decl) == 0)
     {
-      int specd = DECL_INLINE (decl);
+      int inlineable = 0;
       char *lose;
 
       /* If requested, consider whether to make this function inline.  */
-      if (specd || flag_inline_functions)
+      if (DECL_INLINE (decl) || flag_inline_functions)
        TIMEVAR (integration_time,
                 {
                   lose = function_cannot_inline_p (decl);
-                  /* If not optimzing, then make sure the DECL_INLINE
-                     bit is off.  */
                   if (lose || ! optimize)
                     {
-                      if (warn_inline && specd)
+                      if (warn_inline && DECL_INLINE (decl))
                         warning_with_decl (decl, lose);
-                      DECL_INLINE (decl) = 0;
+                      DECL_ABSTRACT_ORIGIN (decl) = 0;
                       /* Don't really compile an extern inline function.
                          If we can't make it inline, pretend
                          it was only declared.  */
@@ -2688,7 +2767,11 @@ rest_of_compilation (decl)
                         }
                     }
                   else
-                    DECL_INLINE (decl) = 1;
+                    /* ??? Note that this has the effect of making it look
+                       like "inline" was specified for a function if we choose
+                       to inline it.  This isn't quite right, but it's
+                       probably not worth the trouble to fix.  */
+                    inlineable = DECL_INLINE (decl) = 1;
                 });
 
       insns = get_insns ();
@@ -2710,33 +2793,42 @@ rest_of_compilation (decl)
         compile it by itself, defer decision till end of compilation.
         finish_compilation will call rest_of_compilation again
         for those functions that need to be output.  Also defer those
-        functions that were marked inline but weren't inlined; they
-        may never be used.  */
-
-      if ((specd || DECL_INLINE (decl))
-         && ((! TREE_PUBLIC (decl) && ! TREE_ADDRESSABLE (decl)
-              && ! flag_keep_inline_functions)
-             || DECL_DEFER_OUTPUT (decl)
-             || DECL_EXTERNAL (decl)))
+        functions that we are supposed to defer.  We cannot defer
+        functions containing nested functions since the nested function
+        data is in our non-saved obstack.  */
+
+      if (! current_function_contains_functions
+         && (DECL_DEFER_OUTPUT (decl)
+             || (DECL_INLINE (decl)
+                 && ((! TREE_PUBLIC (decl) && ! TREE_ADDRESSABLE (decl)
+                      && ! flag_keep_inline_functions)
+                     || DECL_EXTERNAL (decl)))))
        {
-#ifdef DWARF_DEBUGGING_INFO
-         /* Generate the DWARF info for the "abstract" instance
-            of a function which we may later generate inlined and/or
-            out-of-line instances of.  */
-         if (write_symbols == DWARF_DEBUG)
+         DECL_DEFER_OUTPUT (decl) = 1;
+
+         /* If -Wreturn-type, we have to do a bit of compilation.  */
+         if (! warn_return_type)
            {
-             set_decl_abstract_flags (decl, 1);
-             TIMEVAR (symout_time, dwarfout_file_scope_decl (decl, 0));
-             set_decl_abstract_flags (decl, 0);
-           }
+#ifdef DWARF_DEBUGGING_INFO
+             /* Generate the DWARF info for the "abstract" instance
+                of a function which we may later generate inlined and/or
+                out-of-line instances of.  */
+             if (write_symbols == DWARF_DEBUG)
+               {
+                 set_decl_abstract_flags (decl, 1);
+                 TIMEVAR (symout_time, dwarfout_file_scope_decl (decl, 0));
+                 set_decl_abstract_flags (decl, 0);
+               }
 #endif
-         TIMEVAR (integration_time, save_for_inline_nocopy (decl));
-         goto exit_rest_of_compilation;
+             TIMEVAR (integration_time, save_for_inline_nocopy (decl));
+             RTX_INTEGRATED_P (DECL_SAVED_INSNS (decl)) = inlineable;
+             goto exit_rest_of_compilation;
+           }
        }
 
       /* If we have to compile the function now, save its rtl and subdecls
         so that its compilation will not affect what others get.  */
-      if (DECL_INLINE (decl))
+      if (inlineable || DECL_DEFER_OUTPUT (decl))
        {
 #ifdef DWARF_DEBUGGING_INFO
          /* Generate the DWARF info for the "abstract" instance of
@@ -2753,13 +2845,17 @@ rest_of_compilation (decl)
          saved_block_tree = DECL_INITIAL (decl);
          saved_arguments = DECL_ARGUMENTS (decl);
          TIMEVAR (integration_time, save_for_inline_copying (decl));
+         RTX_INTEGRATED_P (DECL_SAVED_INSNS (decl)) = inlineable;
        }
-    }
 
-  if (DECL_DEFER_OUTPUT (decl))
-    goto exit_rest_of_compilation;
+      /* If specified extern inline but we aren't inlining it, we are
+        done.  */
+      if (DECL_INLINE (decl) && DECL_EXTERNAL (decl))
+       goto exit_rest_of_compilation;
+    }
 
-  TREE_ASM_WRITTEN (decl) = 1;
+  if (! DECL_DEFER_OUTPUT (decl))
+    TREE_ASM_WRITTEN (decl) = 1;
 
   /* Now that integrate will no longer see our rtl, we need not distinguish
      between the return value of this function and the return value of called
@@ -2803,20 +2899,14 @@ rest_of_compilation (decl)
      for all references to such slots.  */
 /*   fixup_stack_slots (); */
 
-  /* Do jump optimization the first time, if -opt.
-     Also do it if -W, but in that case it doesn't change the rtl code,
-     it only computes whether control can drop off the end of the function.  */
-
-  if (optimize > 0 || extra_warnings || warn_return_type
-      /* If function is `noreturn', we should warn if it tries to return.  */
-      || TREE_THIS_VOLATILE (decl))
-    {
-      TIMEVAR (jump_time, reg_scan (insns, max_reg_num (), 0));
-      TIMEVAR (jump_time, jump_optimize (insns, 0, 0, 1));
-    }
+  /* Always do one jump optimization pass to ensure that JUMP_LABEL fields
+     are initialized and to compute whether control can drop off the end
+     of the function.  */
+  TIMEVAR (jump_time, reg_scan (insns, max_reg_num (), 0));
+  TIMEVAR (jump_time, jump_optimize (insns, 0, 0, 1));
 
   /* Now is when we stop if -fsyntax-only and -Wreturn-type.  */
-  if (rtl_dump_and_exit || flag_syntax_only)
+  if (rtl_dump_and_exit || flag_syntax_only || DECL_DEFER_OUTPUT (decl))
     goto exit_rest_of_compilation;
 
   /* Dump rtl code after jump, if we are doing that.  */
@@ -2854,7 +2944,7 @@ rest_of_compilation (decl)
                                         0, cse_dump_file));
       TIMEVAR (cse_time, delete_dead_from_cse (insns, max_reg_num ()));
 
-      if (tem)
+      if (tem || optimize > 1)
        TIMEVAR (jump_time, jump_optimize (insns, 0, 0, 0));
     }
 
@@ -3058,6 +3148,10 @@ rest_of_compilation (decl)
             fprintf (global_reg_dump_file, "\n;; Function %s\n\n",
                      IDENTIFIER_POINTER (DECL_NAME (decl))));
 
+  /* Save the last label number used so far, so reorg can tell
+     when it's safe to kill spill regs.  */
+  max_label_num_after_reload = max_label_num ();
+
   /* Unless we did stupid register allocation,
      allocate remaining pseudo-regs, then do the reload pass
      fixing up any insns that are invalid.  */
@@ -3166,12 +3260,11 @@ rest_of_compilation (decl)
     }
 #endif
 
-  if (optimize > 0)
-    /* Shorten branches.  */
-    TIMEVAR (shorten_branch_time,
-            {
-              shorten_branches (get_insns ());
-            });
+  /* Shorten branches.  */
+  TIMEVAR (shorten_branch_time,
+          {
+            shorten_branches (get_insns ());
+          });
 
 #ifdef STACK_REGS
   TIMEVAR (stack_reg_time, reg_to_stack (insns, stack_reg_dump_file));
@@ -3256,6 +3349,9 @@ rest_of_compilation (decl)
 
   reload_completed = 0;
 
+  /* Clear out the insn_length contents now that they are no longer valid.  */
+  init_insn_lengths ();
+
   /* Clear out the real_constant_chain before some of the rtx's
      it runs through become garbage.  */
 
@@ -3265,6 +3361,10 @@ rest_of_compilation (decl)
 
   resume_temporary_allocation ();
 
+  /* Show no temporary slots allocated.  */
+
+  init_temp_slots ();
+
   /* The parsing time is all the time spent in yyparse
      *except* what is spent in this function.  */
 
@@ -3292,7 +3392,12 @@ main (argc, argv, envp)
   save_argv = argv;
 
   p = argv[0] + strlen (argv[0]);
-  while (p != argv[0] && p[-1] != '/') --p;
+  while (p != argv[0] && p[-1] != '/'
+#ifdef DIR_SEPARATOR
+        && p[-1] != DIR_SEPARATOR
+#endif
+        )
+    --p;
   progname = p;
 
 #ifdef RLIMIT_STACK
@@ -3315,6 +3420,7 @@ main (argc, argv, envp)
 
   decl_printable_name = decl_name;
   lang_expand_expr = (struct rtx_def *(*)()) do_abort;
+  interim_eh_hook = interim_eh;
 
   /* Initialize whether `char' is signed.  */
   flag_signed_char = DEFAULT_SIGNED_CHAR;
@@ -3372,6 +3478,7 @@ main (argc, argv, envp)
       flag_strength_reduce = 1;
       flag_rerun_cse_after_loop = 1;
       flag_caller_saves = 1;
+      flag_force_mem = 1;
 #ifdef INSN_SCHEDULING
       flag_schedule_insns = 1;
       flag_schedule_insns_after_reload = 1;
@@ -3383,6 +3490,11 @@ main (argc, argv, envp)
       flag_inline_functions = 1;
     }
 
+  /* Initialize target_flags before OPTIMIZATION_OPTIONS so the latter can
+     modify it.  */
+  target_flags = 0;
+  set_target_switch ("");
+
 #ifdef OPTIMIZATION_OPTIONS
   /* Allow default optimizations to be specified on a per-machine basis.  */
   OPTIMIZATION_OPTIONS (optimize);
@@ -3391,9 +3503,6 @@ main (argc, argv, envp)
   /* Initialize register usage now so switches may override.  */
   init_reg_sets ();
 
-  target_flags = 0;
-  set_target_switch ("");
-
   for (i = 1; i < argc; i++)
     {
       int j;
@@ -3491,10 +3600,12 @@ main (argc, argv, envp)
                  case 'y':
                    set_yydebug (1);
                    break;
-
                  case 'x':
                    rtl_dump_and_exit = 1;
                    break;
+                 case 'A':
+                   flag_debug_asm = 1;
+                   break;
                  }
            }
          else if (str[0] == 'f')
@@ -3636,17 +3747,23 @@ main (argc, argv, envp)
            }
          else if (!strcmp (str, "p"))
            {
-             if (!output_bytecode)
-               profile_flag = 1;
-             else
-               error ("profiling not supported in bytecode compilation");
+             profile_flag = 1;
            }
          else if (!strcmp (str, "a"))
            {
 #if !defined (BLOCK_PROFILER) || !defined (FUNCTION_BLOCK_PROFILER)
              warning ("`-a' option (basic block profile) not supported");
 #else
-             profile_block_flag = 1;
+              profile_block_flag = (profile_block_flag < 2) ? 1 : 3;
+#endif
+           }
+         else if (!strcmp (str, "ax"))
+           {
+#if !defined (FUNCTION_BLOCK_PROFILER_EXIT) || !defined (BLOCK_PROFILER) || !defined (FUNCTION_BLOCK_PROFILER)
+             warning ("`-ax' option (jump profiling) not supported");
+#else
+             profile_block_flag = (!profile_block_flag 
+                                      || profile_block_flag == 2) ? 2 : 3;
 #endif
            }
          else if (str[0] == 'g')
@@ -3770,7 +3887,8 @@ You Lose!  You must define PREFERRED_DEBUGGING_TYPE!
                use_gnu_debug_info_extensions = DEFAULT_GDB_EXTENSIONS;
 #endif       
              if (write_symbols == NO_DEBUG)
-               warning ("`-%s' option not supported on this version of GCC", str);
+               warning ("`-%s' not supported by this configuration of GCC",
+                        str);
              else if (level == 0)
                write_symbols = NO_DEBUG;
              else
@@ -3829,7 +3947,7 @@ You Lose!  You must define PREFERRED_DEBUGGING_TYPE!
   if (write_symbols == DWARF_DEBUG
       && strcmp (language_string, "GNU C++") == 0)
     {
-      warning ("-g option not supported for C++ on SVR4 systems");
+      warning ("-g option not supported for C++ on systems using the DWARF debugging format");
       write_symbols = NO_DEBUG;
     }
 #endif /* defined(DWARF_DEBUGGING_INFO) */
@@ -3839,6 +3957,12 @@ You Lose!  You must define PREFERRED_DEBUGGING_TYPE!
   OVERRIDE_OPTIONS;
 #endif
 
+  if (profile_block_flag == 3)
+    {
+      warning ("`-ax' and `-a' are conflicting options. `-a' ignored.");
+      profile_block_flag = 2;
+    }
+
   /* Unrolling all loops implies that standard loop unrolling must also
      be done.  */
   if (flag_unroll_all_loops)
@@ -3867,31 +3991,16 @@ You Lose!  You must define PREFERRED_DEBUGGING_TYPE!
      option flags in use.  */
   if (version_flag)
     {
-      fprintf (stderr, "%s version %s", language_string, version_string);
-#ifdef TARGET_VERSION
-      TARGET_VERSION;
-#endif
-#ifdef __GNUC__
-#ifndef __VERSION__
-#define __VERSION__ "[unknown]"
-#endif
-      fprintf (stderr, " compiled by GNU C version %s.\n", __VERSION__);
-#else
-      fprintf (stderr, " compiled by CC.\n");
-#endif
+      print_version (stderr, "");
       if (! quiet_flag)
-       print_switch_values ();
+       print_switch_values (stderr, 0, MAX_LINE, "", " ", "\n");
     }
 
   compile_file (filename);
 
-#ifndef OS2
-#ifndef VMS
+#if !defined(OS2) && !defined(VMS) && !defined(_WIN32)
   if (flag_print_mem)
     {
-#ifdef __alpha
-      char *sbrk ();
-#endif
       char *lim = (char *) sbrk (0);
 
       fprintf (stderr, "Data size %d.\n",
@@ -3904,15 +4013,14 @@ You Lose!  You must define PREFERRED_DEBUGGING_TYPE!
       system ("ps v");
 #endif /* not USG */
     }
-#endif /* not VMS */
-#endif /* not OS2 */
+#endif /* not OS2 and not VMS and not _WIN32 */
 
   if (errorcount)
     exit (FATAL_EXIT_CODE);
   if (sorrycount)
     exit (FATAL_EXIT_CODE);
   exit (SUCCESS_EXIT_CODE);
-  return 34;
+  return 0;
 }
 \f
 /* Decode -m switches.  */
@@ -3969,51 +4077,128 @@ set_target_switch (name)
     error ("Invalid option `%s'", name);
 }
 \f
-/* Variable used for communication between the following two routines.  */
-
-static int line_position;
-
-/* Print an option value and adjust the position in the line.  */
+/* Print version information to FILE.
+   Each line begins with INDENT (for the case where FILE is the
+   assembler output file).  */
 
-static void
-print_single_switch (type, name)
-     char *type, *name;
+void
+print_version (file, indent)
+     FILE *file;
+     char *indent;
 {
-  fprintf (stderr, " %s%s", type, name);
+  fprintf (file, "%s%s%s version %s", indent, *indent != 0 ? " " : "",
+          language_string, version_string);
+  fprintf (file, " (%s)", TARGET_NAME);
+#ifdef __GNUC__
+#ifndef __VERSION__
+#define __VERSION__ "[unknown]"
+#endif
+  fprintf (file, " compiled by GNU C version %s.\n", __VERSION__);
+#else
+  fprintf (file, " compiled by CC.\n");
+#endif
+}
 
-  line_position += strlen (type) + strlen (name) + 1;
+/* Print an option value and return the adjusted position in the line.
+   ??? We don't handle error returns from fprintf (disk full).  */
 
-  if (line_position > 65)
+int
+print_single_switch (file, pos, max, indent, sep, term, type, name)
+     FILE *file;
+     int pos, max;
+     char *indent, *sep, *term, *type, *name;
+{
+  if (pos != 0
+      && pos + strlen (sep) + strlen (type) + strlen (name) > max)
+    {
+      fprintf (file, "%s", term);
+      pos = 0;
+    }
+  if (pos == 0)
     {
-      fprintf (stderr, "\n\t");
-      line_position = 8;
+      pos = fprintf (file, "%s", indent);
     }
+  pos += fprintf (file, "%s%s%s", sep, type, name);
+  return pos;
 }
      
-/* Print default target switches for -version.  */
+/* Print active target switches to FILE.
+   POS is the current cursor position and MAX is the size of a "line".
+   Each line begins with INDENT and ends with TERM.
+   Each switch is separated from the next by SEP.  */
 
-static void
-print_switch_values ()
+void
+print_switch_values (file, pos, max, indent, sep, term)
+     FILE *file;
+     int pos, max;
+     char *indent, *sep, *term;
 {
-  register int j;
+  int j, flags;
+  char **p;
+
+  /* Print the options as passed.  */
 
-  fprintf (stderr, "enabled:");
-  line_position = 8;
+  pos = print_single_switch (file, pos, max, indent, *indent ? " " : "", term,
+                            "options passed: ", "");
+
+  for (p = &save_argv[1]; *p != NULL; p++)
+    if (**p == '-')
+      {
+       /* Ignore these.  */
+       if (strcmp (*p, "-o") == 0)
+         {
+           if (p[1] != NULL)
+             p++;
+           continue;
+         }
+       if (strcmp (*p, "-quiet") == 0)
+         continue;
+       if (strcmp (*p, "-version") == 0)
+         continue;
+       if ((*p)[1] == 'd')
+         continue;
+
+       pos = print_single_switch (file, pos, max, indent, sep, term, *p, "");
+      }
+  if (pos > 0)
+    fprintf (file, "%s", term);
+
+  /* Print the -f and -m options that have been enabled.
+     We don't handle language specific options but printing argv
+     should suffice.  */
+
+  pos = print_single_switch (file, 0, max, indent, *indent ? " " : "", term,
+                            "options enabled: ", "");
 
   for (j = 0; j < sizeof f_options / sizeof f_options[0]; j++)
     if (*f_options[j].variable == f_options[j].on_value)
-      print_single_switch ("-f", f_options[j].string);
+      pos = print_single_switch (file, pos, max, indent, sep, term,
+                                "-f", f_options[j].string);
 
-  for (j = 0; j < sizeof W_options / sizeof W_options[0]; j++)
-    if (*W_options[j].variable == W_options[j].on_value)
-      print_single_switch ("-W", W_options[j].string);
+  /* Print target specific options.  */
 
+  flags = target_flags;
   for (j = 0; j < sizeof target_switches / sizeof target_switches[0]; j++)
     if (target_switches[j].name[0] != '\0'
        && target_switches[j].value > 0
        && ((target_switches[j].value & target_flags)
            == target_switches[j].value))
-      print_single_switch ("-m", target_switches[j].name);
+      {
+       pos = print_single_switch (file, pos, max, indent, sep, term,
+                                  "-m", target_switches[j].name);
+       flags &= ~ target_switches[j].value;
+      }
+
+#ifdef TARGET_OPTIONS
+  for (j = 0; j < sizeof target_options / sizeof target_options[0]; j++)
+    if (*target_options[j].variable != NULL)
+      {
+       char prefix[256];
+       sprintf (prefix, "-m%s", target_options[j].prefix);
+       pos = print_single_switch (file, pos, max, indent, sep, term,
+                                  prefix, *target_options[j].variable);
+      }
+#endif
 
-  fprintf (stderr, "\n");
+  fprintf (file, "%s", term);
 }