OSDN Git Service

* a29k/unix.h (ASM_FILE_START): Const-ify.
[pf3gnuchains/gcc-fork.git] / gcc / toplev.c
index e357d62..a3bdba6 100644 (file)
@@ -2,22 +2,22 @@
    Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
    1999, 2000, 2001 Free Software Foundation, Inc.
 
-This file is part of GNU CC.
+This file is part of GCC.
 
-GNU CC 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 version.
+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
+version.
 
-GNU CC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+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 GNU CC; see the file COPYING.  If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
+along with GCC; see the file COPYING.  If not, write to 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
@@ -67,10 +67,8 @@ Boston, MA 02111-1307, USA.  */
 #include "dwarf2asm.h"
 #include "integrate.h"
 #include "debug.h"
-
-#ifdef DWARF_DEBUGGING_INFO
-#include "dwarfout.h"
-#endif
+#include "target.h"
+#include "langhooks.h"
 
 #if defined (DWARF2_UNWIND_INFO) || defined (DWARF2_DEBUGGING_INFO)
 #include "dwarf2out.h"
@@ -85,7 +83,12 @@ Boston, MA 02111-1307, USA.  */
 #endif
 
 #ifdef XCOFF_DEBUGGING_INFO
-#include "xcoffout.h"
+#include "xcoffout.h"          /* Needed for external data
+                                  declarations for e.g. AIX 4.x.  */
+#endif
+
+#ifdef HALF_PIC_DEBUG
+#include "halfpic.h"
 #endif
 \f
 #ifdef VMS
@@ -158,12 +161,21 @@ extern char **environ;
 extern int size_directive_output;
 extern tree last_assemble_variable_decl;
 
+static void general_init PARAMS ((char *));
+static void parse_options_and_default_flags PARAMS ((int, char **));
+static void process_options PARAMS ((void));
+static void lang_independent_init PARAMS ((void));
+static int lang_dependent_init PARAMS ((const char *));
+static void init_asm_output PARAMS ((const char *));
+static void finalize PARAMS ((void));
+
 static void set_target_switch PARAMS ((const char *));
 static const char *decl_name PARAMS ((tree, int));
 
 static void float_signal PARAMS ((int)) ATTRIBUTE_NORETURN;
 static void crash_signal PARAMS ((int)) ATTRIBUTE_NORETURN;
-static void compile_file PARAMS ((const char *));
+static void set_float_handler PARAMS ((jmp_buf));
+static void compile_file PARAMS ((void));
 static void display_help PARAMS ((void));
 static void display_target_options PARAMS ((void));
 
@@ -228,7 +240,7 @@ extern int target_flags;
 
 /* Debug hooks - dependent upon command line options.  */
 
-struct gcc_debug_hooks *debug_hooks;
+struct gcc_debug_hooks *debug_hooks = &do_nothing_debug_hooks;
 
 /* Describes a dump file.  */
 
@@ -738,6 +750,10 @@ int flag_exceptions;
 
 int flag_unwind_tables = 0;
 
+/* Nonzero means generate frame unwind info table exact at each insn boundary */
+
+int flag_asynchronous_unwind_tables = 0;
+
 /* Nonzero means don't place uninitialized global data in common storage
    by default.  */
 
@@ -899,6 +915,11 @@ int flag_bounded_pointers = 0;
    For CHILL: defaults to off.  */
 int flag_bounds_check = 0;
 
+/* This will attempt to merge constant section constants, if 1 only
+   string constants and constants from constant pool, if 2 also constant
+   variables.  */
+int flag_merge_constants = 1;
+
 /* If one, renumber instruction UIDs to reduce the number of
    unused UIDs if there are a lot of instructions.  If greater than
    one, unconditionally renumber instruction UIDs.  */
@@ -911,22 +932,25 @@ int flag_renumber_insns = 1;
 
 int align_loops;
 int align_loops_log;
+int align_loops_max_skip;
 int align_jumps;
 int align_jumps_log;
+int align_jumps_max_skip;
 int align_labels;
 int align_labels_log;
+int align_labels_max_skip;
 int align_functions;
 int align_functions_log;
 
 /* Table of supported debugging formats.  */
-static struct
+static const struct
 {
-  const char *arg;
+  const char *const arg;
   /* Since PREFERRED_DEBUGGING_TYPE isn't necessarily a
      constant expression, we use NO_DEBUG in its place.  */
-  enum debug_info_type debug_type;
-  int use_extensions_p;
-  const char *description;
+  const enum debug_info_type debug_type;
+  const int use_extensions_p;
+  const char *const description;
 } *da,
 debug_args[] =
 {
@@ -1092,6 +1116,8 @@ lang_independent_options f_options[] =
    N_("Enable exception handling") },
   {"unwind-tables", &flag_unwind_tables, 1,
    N_("Just generate unwind tables for exception handling") },
+  {"asynchronous-unwind-tables", &flag_asynchronous_unwind_tables, 1,
+   N_("Generate unwind tables exact at each instruction boundary") },
   {"non-call-exceptions", &flag_non_call_exceptions, 1,
    N_("Support synchronous non-call exceptions") },
   {"profile-arcs", &profile_arc_flag, 1,
@@ -1105,7 +1131,7 @@ lang_independent_options f_options[] =
   {"rename-registers", &flag_rename_registers, 1,
    N_("Do the register renaming optimization pass") },
   {"common", &flag_no_common, 0,
-   N_("Do not put unitialised globals in the common section") },
+   N_("Do not put uninitialized globals in the common section") },
   {"inhibit-size-directive", &flag_inhibit_size_directive, 1,
    N_("Do not generate .size directives") },
   {"function-sections", &flag_function_sections, 1,
@@ -1140,6 +1166,10 @@ lang_independent_options f_options[] =
    N_("Align all labels") },
   {"align-functions", &align_functions, 0,
    N_("Align the start of functions") },
+  {"merge-constants", &flag_merge_constants, 1,
+   N_("Attempt to merge identical constants accross compilation units") },
+  {"merge-all-constants", &flag_merge_constants, 2,
+   N_("Attempt to merge identical constants and constant variables") },
   {"check-memory-usage", &flag_check_memory_usage, 1,
    N_("Generate code to check every memory access") },
   {"prefix-function-name", &flag_prefix_function_name, 1,
@@ -1151,7 +1181,7 @@ lang_independent_options f_options[] =
   {"ssa", &flag_ssa, 1,
    N_("Enable SSA optimizations") },
   {"ssa-ccp", &flag_ssa_ccp, 1,
-   N_("Enable SSA conditonal constant propagation") },
+   N_("Enable SSA conditional constant propagation") },
   {"ssa-dce", &flag_ssa_dce, 1,
    N_("Enable aggressive SSA dead code elimination") },
   {"leading-underscore", &flag_leading_underscore, 1,
@@ -1184,10 +1214,10 @@ lang_independent_options f_options[] =
 
 /* Table of language-specific options.  */
 
-static struct lang_opt
+static const struct lang_opt
 {
-  const char *option;
-  const char *description;
+  const char *const option;
+  const char *const description;
 }
 documented_lang_options[] =
 {
@@ -1370,22 +1400,22 @@ documented_lang_options[] =
    If VALUE is negative, -VALUE is bits to clear.
    (The sign bit is not used so there is no confusion.)  */
 
-struct
+static const struct
 {
-  const char *name;
-  int value;
-  const char *description;
+  const char *const name;
+  const int value;
+  const char *const description;
 }
 target_switches [] = TARGET_SWITCHES;
 
 /* This table is similar, but allows the switch to have a value.  */
 
 #ifdef TARGET_OPTIONS
-struct
+static const struct
 {
-  const char *prefix;
-  const char **variable;
-  const char *description;
+  const char *const prefix;
+  const char **const variable;
+  const char *const description;
 }
 target_options [] = TARGET_OPTIONS;
 #endif
@@ -1416,23 +1446,6 @@ int warn_unused_parameter;
 int warn_unused_variable;
 int warn_unused_value;
 
-void
-set_Wunused (setting)
-     int setting;
-{
-  warn_unused_function = setting;
-  warn_unused_label = setting;
-  /* Unused function parameter warnings are reported when either ``-W
-     -Wunused'' or ``-Wunused-parameter'' is specified.  Differentiate
-     -Wunused by setting WARN_UNUSED_PARAMETER to -1.  */
-  if (!setting)
-    warn_unused_parameter = 0;
-  else if (!warn_unused_parameter)
-    warn_unused_parameter = -1;
-  warn_unused_variable = setting;
-  warn_unused_value = setting;
-}
-
 /* Nonzero to warn about code which is never reached.  */
 
 int warn_notreached;
@@ -1441,7 +1454,7 @@ int warn_notreached;
 
 int warn_uninitialized;
 
-/* Nonzero means warn about all declarations which shadow others.   */
+/* Nonzero means warn about all declarations which shadow others.  */
 
 int warn_shadow;
 
@@ -1521,7 +1534,7 @@ lang_independent_options W_options[] =
   {"unreachable-code", &warn_notreached, 1,
    N_("Warn about code that will never be executed") },
   {"uninitialized", &warn_uninitialized, 1,
-   N_("Warn about unitialized automatic variables") },
+   N_("Warn about uninitialized automatic variables") },
   {"inline", &warn_inline, 1,
    N_("Warn when an inlined function cannot be inlined") },
   {"packed", &warn_packed, 1,
@@ -1534,6 +1547,23 @@ lang_independent_options W_options[] =
    N_("Warn about functions which might be candidates for attribute noreturn") }
 };
 
+void
+set_Wunused (setting)
+     int setting;
+{
+  warn_unused_function = setting;
+  warn_unused_label = setting;
+  /* Unused function parameter warnings are reported when either ``-W
+     -Wunused'' or ``-Wunused-parameter'' is specified.  Differentiate
+     -Wunused by setting WARN_UNUSED_PARAMETER to -1.  */
+  if (!setting)
+    warn_unused_parameter = 0;
+  else if (!warn_unused_parameter)
+    warn_unused_parameter = -1;
+  warn_unused_variable = setting;
+  warn_unused_value = setting;
+}
+
 /* The following routines are useful in setting all the flags that
    -ffast-math and -fno-fast-math imply.  */
 
@@ -1576,7 +1606,7 @@ read_integral_parameter (p, pname, defval)
 
   while (*endp)
     {
-      if (*endp >= '0' && *endp <= '9')
+      if (ISDIGIT (*endp))
        endp++;
       else
        break;
@@ -1630,9 +1660,9 @@ botch (s)
 
 int
 exact_log2_wide (x)
-     register unsigned HOST_WIDE_INT x;
+     unsigned HOST_WIDE_INT x;
 {
-  register int log = 0;
+  int log = 0;
   /* Test for 0 or a power of 2.  */
   if (x == 0 || x != (x & -x))
     return -1;
@@ -1648,9 +1678,9 @@ exact_log2_wide (x)
 
 int
 floor_log2_wide (x)
-     register unsigned HOST_WIDE_INT x;
+     unsigned HOST_WIDE_INT x;
 {
-  register int log = -1;
+  int log = -1;
   while (x != 0)
     log++,
     x >>= 1;
@@ -1681,7 +1711,7 @@ float_signal (signo)
 /* Specify where to longjmp to when a floating arithmetic error happens.
    If HANDLER is 0, it means don't handle the errors any more.  */
 
-void
+static void
 set_float_handler (handler)
      jmp_buf handler;
 {
@@ -1701,7 +1731,7 @@ set_float_handler (handler)
    pointer FN, and one argument DATA.  DATA is usually a struct which
    contains the real input and output for function FN.  This function
    returns 0 (failure) if longjmp was called (i.e. an exception
-   occured.)  It returns 1 (success) otherwise.  */
+   occurred.)  It returns 1 (success) otherwise.  */
 
 int
 do_float_handler (fn, data)
@@ -2059,47 +2089,7 @@ check_global_declarations (vec, len)
        warning_with_decl (decl, "`%s' defined but not used");
 
       timevar_push (TV_SYMOUT);
-#ifdef SDB_DEBUGGING_INFO
-      /* The COFF linker can move initialized global vars to the end.
-        And that can screw up the symbol ordering.
-        By putting the symbols in that order to begin with,
-        we avoid a problem.  mcsun!unido!fauern!tumuc!pes@uunet.uu.net.  */
-      if (write_symbols == SDB_DEBUG && TREE_CODE (decl) == VAR_DECL
-         && TREE_PUBLIC (decl) && DECL_INITIAL (decl)
-         && ! DECL_EXTERNAL (decl)
-         && DECL_RTL (decl) != 0)
-       sdbout_symbol (decl, 0);
-
-      /* Output COFF information for non-global
-        file-scope initialized variables.  */
-      if (write_symbols == SDB_DEBUG
-         && TREE_CODE (decl) == VAR_DECL
-         && DECL_INITIAL (decl)
-         && ! DECL_EXTERNAL (decl)
-         && DECL_RTL (decl) != 0
-         && GET_CODE (DECL_RTL (decl)) == MEM)
-       sdbout_toplevel_data (decl);
-#endif /* SDB_DEBUGGING_INFO  */
-#ifdef DWARF_DEBUGGING_INFO
-      /* Output DWARF information for file-scope tentative data object
-        declarations, file-scope (extern) function declarations (which
-        had no corresponding body) and file-scope tagged type declarations
-        and definitions which have not yet been forced out.  */
-
-      if (write_symbols == DWARF_DEBUG
-         && (TREE_CODE (decl) != FUNCTION_DECL || !DECL_INITIAL (decl)))
-       dwarfout_file_scope_decl (decl, 1);
-#endif
-#ifdef DWARF2_DEBUGGING_INFO
-      /* Output DWARF2 information for file-scope tentative data object
-        declarations, file-scope (extern) function declarations (which
-        had no corresponding body) and file-scope tagged type declarations
-        and definitions which have not yet been forced out.  */
-
-      if (write_symbols == DWARF2_DEBUG
-         && (TREE_CODE (decl) != FUNCTION_DECL || !DECL_INITIAL (decl)))
-       dwarf2out_decl (decl);
-#endif
+      (*debug_hooks->global_decl) (decl);
       timevar_pop (TV_SYMOUT);
     }
 }
@@ -2150,202 +2140,14 @@ pop_srcloc ()
   lineno = input_file_stack->line;
 }
 
-/* Compile an entire file of output from cpp, named NAME.
-   Write a file of assembly output and various debugging dumps.  */
+/* Compile an entire translation unit.  Write a file of assembly
+   output and various debugging dumps.  */
 
 static void
-compile_file (name)
-     const char *name;
+compile_file ()
 {
   tree globals;
 
-  int name_specified = name != 0;
-
-  if (dump_base_name == 0)
-    dump_base_name = name ? name : "gccdump";
-
-  if (! quiet_flag)
-    time_report = 1;
-
-  /* Start timing total execution time.  */
-
-  init_timevar ();
-  timevar_start (TV_TOTAL);
-
-  /* Open assembler code output file.  Do this even if -fsyntax-only is on,
-     because then the driver will have provided the name of a temporary
-     file or bit bucket for us.  */
-
-  if (! name_specified && asm_file_name == 0)
-    asm_out_file = stdout;
-  else
-    {
-      if (asm_file_name == 0)
-        {
-          int len = strlen (dump_base_name);
-          char *dumpname = (char *) xmalloc (len + 6);
-          memcpy (dumpname, dump_base_name, len + 1);
-          strip_off_ending (dumpname, len);
-          strcat (dumpname, ".s");
-          asm_file_name = dumpname;
-        }
-      if (!strcmp (asm_file_name, "-"))
-        asm_out_file = stdout;
-      else
-        asm_out_file = fopen (asm_file_name, "w");
-      if (asm_out_file == 0)
-       fatal_io_error ("can't open %s for writing", asm_file_name);
-    }
-
-  /* Initialize data in various passes.  */
-
-  init_obstacks ();
-  name = init_parse (name);
-  init_emit_once (debug_info_level == DINFO_LEVEL_NORMAL
-                 || debug_info_level == DINFO_LEVEL_VERBOSE
-                 || flag_test_coverage
-                 || warn_notreached);
-  init_regs ();
-  init_alias_once ();
-  init_decl_processing ();
-  init_eh ();
-  init_optabs ();
-  init_stmt ();
-  init_loop ();
-  init_reload ();
-  init_function_once ();
-  init_stor_layout_once ();
-  init_varasm_once ();
-  init_EXPR_INSN_LIST_cache ();
-
-  /* The following initialization functions need to generate rtl, so
-     provide a dummy function context for them.  */
-  init_dummy_function_start ();
-  init_expmed ();
-  init_expr_once ();
-  if (flag_caller_saves)
-    init_caller_save ();
-  expand_dummy_function_end ();
-
-  /* If auxiliary info generation is desired, open the output file.
-     This goes in the same directory as the source file--unlike
-     all the other output files.  */
-  if (flag_gen_aux_info)
-    {
-      aux_info_file = fopen (aux_info_file_name, "w");
-      if (aux_info_file == 0)
-       fatal_io_error ("can't open %s", aux_info_file_name);
-    }
-
-#ifdef IO_BUFFER_SIZE
-  setvbuf (asm_out_file, (char *) xmalloc (IO_BUFFER_SIZE),
-           _IOFBF, IO_BUFFER_SIZE);
-#endif
-
-  if (name != 0)
-    name = ggc_strdup (name);
-
-  input_filename = name;
-
-  /* Put an entry on the input file stack for the main input file.  */
-  push_srcloc (input_filename, 0);
-
-  /* Perform language-specific initialization.
-     This may set main_input_filename.  */
-  if (lang_hooks.init)
-    (*lang_hooks.init) ();
-
-  /* If the input doesn't start with a #line, use the input name
-     as the official input file name.  */
-  if (main_input_filename == 0)
-    main_input_filename = name;
-
-  if (flag_syntax_only)
-    {
-      write_symbols = NO_DEBUG;
-      profile_flag = 0;
-      profile_block_flag = 0;
-    }
-  else
-    {
-#ifdef ASM_FILE_START
-      ASM_FILE_START (asm_out_file);
-#endif
-
-#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
-    } /* ! flag_syntax_only  */
-
-  /* Set up the debug hooks based on write_symbols.  Default to doing
-     nothing.  */
-  debug_hooks = &do_nothing_debug_hooks;  
-#if defined(DBX_DEBUGGING_INFO)
-  if (write_symbols == DBX_DEBUG)
-    debug_hooks = &dbx_debug_hooks;
-#endif
-#if defined(XCOFF_DEBUGGING_INFO)
-  if (write_symbols == XCOFF_DEBUG)
-    debug_hooks = &xcoff_debug_hooks;
-#endif
-#ifdef SDB_DEBUGGING_INFO
-  if (write_symbols == SDB_DEBUG)
-    debug_hooks = &sdb_debug_hooks;
-#endif
-#ifdef DWARF_DEBUGGING_INFO
-  if (write_symbols == DWARF_DEBUG)
-    debug_hooks = &dwarf_debug_hooks;
-#endif
-#ifdef DWARF2_DEBUGGING_INFO
-  if (write_symbols == DWARF2_DEBUG)
-    debug_hooks = &dwarf2_debug_hooks;
-#endif
-
-#ifndef ASM_OUTPUT_SECTION_NAME
-  if (flag_function_sections)
-    {
-      warning ("-ffunction-sections not supported for this target.");
-      flag_function_sections = 0;
-    }
-  if (flag_data_sections)
-    {
-      warning ("-fdata-sections not supported for this target.");
-      flag_data_sections = 0;
-    }
-#endif
-
-  if (flag_function_sections
-      && (profile_flag || profile_block_flag))
-    {
-      warning ("-ffunction-sections disabled; it makes profiling impossible.");
-      flag_function_sections = 0;
-    }
-
-#ifndef OBJECT_FORMAT_ELF
-  if (flag_function_sections && write_symbols != NO_DEBUG)
-    warning ("-ffunction-sections may affect debugging on some targets.");
-#endif
-
-  /* If dbx symbol table desired, initialize writing it
-     and output the predefined types.  */
-  timevar_push (TV_SYMOUT);
-#ifdef DWARF2_UNWIND_INFO
-  if (dwarf2out_do_frame ())
-    dwarf2out_frame_init ();
-#endif
-
-  (*debug_hooks->init) (main_input_filename);
-  timevar_pop (TV_SYMOUT);
-
   /* Initialize yet another pass.  */
 
   init_final (main_input_filename);
@@ -2355,17 +2157,11 @@ compile_file (name)
 
   /* Call the parser, which parses the entire file
      (calling rest_of_compilation for each function).  */
+  yyparse ();
 
-  if (yyparse () != 0)
-    {
-      if (errorcount == 0)
-       fnotice (stderr, "Errors detected in input file (your bison.simple is out of date)\n");
-
-      /* In case there were missing closebraces,
-        get us back to the global binding level.  */
-      while (! global_bindings_p ())
-       poplevel (0, 0, 0);
-    }
+  /* In case there were missing block closers,
+     get us back to the global binding level.  */
+  (*lang_hooks.clear_binding_stack) ();
 
   /* Compilation is now finished except for writing
      what's left of the symbol table output.  */
@@ -2373,7 +2169,7 @@ compile_file (name)
   timevar_pop (TV_PARSE);
 
   if (flag_syntax_only)
-    goto finish_syntax;
+    return;
 
   globals = getdecls ();
 
@@ -2455,20 +2251,6 @@ compile_file (name)
             IDENT_ASM_OP, version_string);
 #endif
 
-  /* Language-specific end of compilation actions.  */
- finish_syntax:
-  if (lang_hooks.finish)
-    (*lang_hooks.finish) ();
-
-  /* Close the dump files.  */
-
-  if (flag_gen_aux_info)
-    {
-      fclose (aux_info_file);
-      if (errorcount)
-       unlink (aux_info_file_name);
-    }
-
   if (optimize > 0 && open_dump_file (DFI_combine, NULL))
     {
       timevar_push (TV_DUMP);
@@ -2476,74 +2258,29 @@ compile_file (name)
       close_dump_file (DFI_combine, NULL, NULL_RTX);
       timevar_pop (TV_DUMP);
     }
+}
+\f
+/* This is called from various places for FUNCTION_DECL, VAR_DECL,
+   and TYPE_DECL nodes.
 
-  /* Close non-debugging input and output files.  Take special care to note
-     whether fclose returns an error, since the pages might still be on the
-     buffer chain while the file is open.  */
-
-  finish_parse ();
+   This does nothing for local (non-static) variables, unless the
+   variable is a register variable with an ASMSPEC.  In that case, or
+   if the variable is not an automatic, it sets up the RTL and
+   outputs any assembler code (label definition, storage allocation
+   and initialization).
 
-  if (ferror (asm_out_file) != 0)
-    fatal_io_error ("error writing to %s", asm_file_name);
-  if (fclose (asm_out_file) != 0)
-    fatal_io_error ("error closing %s", asm_file_name);
+   DECL is the declaration.  If ASMSPEC is nonzero, it specifies
+   the assembler symbol name to be used.  TOP_LEVEL is nonzero
+   if this declaration is not within a function.  */
 
-  /* Do whatever is necessary to finish printing the graphs.  */
-  if (graph_dump_format != no_graph)
-    {
-      int i;
-
-      for (i = 0; i < (int) DFI_MAX; ++i)
-       if (dump_file[i].initialized && dump_file[i].graph_dump_p)
-         {
-           char seq[16];
-           char *suffix;
-
-           sprintf (seq, ".%02d.", i);
-           suffix = concat (seq, dump_file[i].extension, NULL);
-           finish_graph_dump_file (dump_base_name, suffix);
-           free (suffix);
-         }
-    }
-
-  if (mem_report)
-    {
-      ggc_print_statistics ();
-      stringpool_statistics ();
-    }
-
-  /* Free up memory for the benefit of leak detectors.  */
-  free_reg_info ();
-
-  /* Stop timing total execution time.  */
-  timevar_stop (TV_TOTAL);
-
-  /* Print the times.  */
-
-  timevar_print (stderr);
-}
-\f
-/* This is called from various places for FUNCTION_DECL, VAR_DECL,
-   and TYPE_DECL nodes.
-
-   This does nothing for local (non-static) variables, unless the
-   variable is a register variable with an ASMSPEC.  In that case, or
-   if the variable is not an automatic, it sets up the RTL and
-   outputs any assembler code (label definition, storage allocation
-   and initialization).
-
-   DECL is the declaration.  If ASMSPEC is nonzero, it specifies
-   the assembler symbol name to be used.  TOP_LEVEL is nonzero
-   if this declaration is not within a function.  */
-
-void
-rest_of_decl_compilation (decl, asmspec, top_level, at_end)
-     tree decl;
-     const char *asmspec;
-     int top_level;
-     int at_end;
-{
-  /* Declarations of variables, and of functions defined elsewhere.  */
+void
+rest_of_decl_compilation (decl, asmspec, top_level, at_end)
+     tree decl;
+     const char *asmspec;
+     int top_level;
+     int at_end;
+{
+  /* Declarations of variables, and of functions defined elsewhere.  */
 
 /* The most obvious approach, to put an #ifndef around where
    this macro is used, doesn't work since it's inside a macro call.  */
@@ -2634,64 +2371,6 @@ rest_of_type_compilation (type, toplev)
   timevar_pop (TV_SYMOUT);
 }
 
-/* DECL is an inline function, whose body is present, but which is not
-   being output at this point.  (We're putting that off until we need
-   to do it.)  If there are any actions that need to take place,
-   including the emission of debugging information for the function,
-   this is where they should go.  This function may be called by
-   language-dependent code for front-ends that do not even generate
-   RTL for functions that don't need to be put out.  */
-
-void
-note_deferral_of_defined_inline_function (decl)
-     tree decl ATTRIBUTE_UNUSED;
-{
-#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_INLINE (decl) || DECL_ABSTRACT (decl))
-      && ! DECL_ABSTRACT_ORIGIN (decl))
-    {
-      /* The front-end may not have set CURRENT_FUNCTION_DECL, but the
-        DWARF code expects it to be set in this case.  Intuitively,
-        DECL is the function we just finished defining, so setting
-        CURRENT_FUNCTION_DECL is sensible.  */
-      tree saved_cfd = current_function_decl;
-      int was_abstract = DECL_ABSTRACT (decl);
-      current_function_decl = decl;
-
-      /* Let the DWARF code do its work.  */
-      set_decl_abstract_flags (decl, 1);
-      dwarfout_file_scope_decl (decl, 0);
-      if (! was_abstract)
-       set_decl_abstract_flags (decl, 0);
-
-      /* Reset CURRENT_FUNCTION_DECL.  */
-      current_function_decl = saved_cfd;
-    }
-#endif
-}
-
-/* FNDECL is an inline function which is about to be emitted out of line.
-   Do any preparation, such as emitting abstract debug info for the inline
-   before it gets mangled by optimization.  */
-
-void
-note_outlining_of_inline_function (fndecl)
-     tree fndecl ATTRIBUTE_UNUSED;
-{
-#ifdef DWARF2_DEBUGGING_INFO
-  /* The DWARF 2 backend tries to reduce debugging bloat by not emitting
-     the abstract description of inline functions until something tries to
-     reference them.  Force it out now, before optimizations mangle the
-     block tree.  */
-  if (write_symbols == DWARF2_DEBUG)
-    dwarf2out_abstract_function (fndecl);
-#endif
-}
-
 /* This is called from finish_function (within yyparse)
    after each top-level definition is parsed.
    It is supposed to compile that function or variable
@@ -2702,7 +2381,7 @@ void
 rest_of_compilation (decl)
      tree decl;
 {
-  register rtx insns;
+  rtx insns;
   int tem;
   int failure = 0;
   int rebuild_label_notes_after_reload;
@@ -2817,12 +2496,12 @@ rest_of_compilation (decl)
        DECL_DEFER_OUTPUT (decl) = 1;
 
       if (DECL_INLINE (decl))
-       /* DWARF wants seperate debugging info for abstract and
+       /* DWARF wants separate debugging info for abstract and
           concrete instances of all inline functions, including those
           declared inline but not inlined, and those inlined even
           though they weren't declared inline.  Conveniently, that's
           what DECL_INLINE means at this point.  */
-       note_deferral_of_defined_inline_function (decl);
+       (*debug_hooks->deferred_inline_function) (decl);
 
       if (DECL_DEFER_OUTPUT (decl))
        {
@@ -2838,8 +2517,11 @@ rest_of_compilation (decl)
              rebuild_jump_labels (insns);
              find_exception_handler_labels ();
              find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
-             cleanup_cfg (CLEANUP_PRE_SIBCALL);
+             cleanup_cfg (CLEANUP_PRE_SIBCALL | CLEANUP_PRE_LOOP);
              optimize = saved_optimize;
+
+             /* CFG is no longer maintained up-to-date.  */
+             free_bb_for_insn ();
            }
 
          current_function_nothrow = nothrow_function_p ();
@@ -2880,7 +2562,7 @@ rest_of_compilation (decl)
   purge_hard_subreg_sets (get_insns ());
   emit_initial_value_sets ();
 
-  /* Don't return yet if -Wreturn-type; we need to do jump_optimize.  */
+  /* Don't return yet if -Wreturn-type; we need to do cleanup_cfg.  */
   if ((rtl_dump_and_exit || flag_syntax_only) && !warn_return_type)
     goto exit_rest_of_compilation;
 
@@ -2925,7 +2607,7 @@ rest_of_compilation (decl)
   unshare_all_rtl (current_function_decl, insns);
 
 #ifdef SETJMP_VIA_SAVE_AREA
-  /* This must be performed before virutal register instantiation.  */
+  /* This must be performed before virtual register instantiation.  */
   if (current_function_calls_alloca)
     optimize_save_area_alloca (insns);
 #endif
@@ -2945,7 +2627,14 @@ rest_of_compilation (decl)
   expected_value_to_br_prob ();
 
   reg_scan (insns, max_reg_num (), 0);
-  jump_optimize (insns, !JUMP_NOOP_MOVES, JUMP_AFTER_REGSCAN);
+  rebuild_jump_labels (insns);
+  find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
+  cleanup_cfg ((optimize ? CLEANUP_EXPENSIVE : 0) | CLEANUP_PRE_LOOP);
+
+  /* CFG is no longer maintained up-to-date.  */
+  free_bb_for_insn ();
+  copy_loop_headers (insns);
+  purge_line_number_notes (insns);
 
   timevar_pop (TV_JUMP);
 
@@ -2967,7 +2656,7 @@ rest_of_compilation (decl)
       open_dump_file (DFI_ssa, decl);
 
       find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
-      cleanup_cfg (CLEANUP_EXPENSIVE);
+      cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP);
       convert_to_ssa ();
 
       close_dump_file (DFI_ssa, print_rtl_with_bb, insns);
@@ -2996,7 +2685,7 @@ rest_of_compilation (decl)
 
       if (flag_ssa_dce)
        {
-         /* Remove dead code. */
+         /* Remove dead code.  */
 
          timevar_push (TV_SSA_DCE);
          open_dump_file (DFI_ssa_dce, decl);
@@ -3016,15 +2705,13 @@ rest_of_compilation (decl)
       convert_from_ssa ();
       /* New registers have been created.  Rescan their usage.  */
       reg_scan (insns, max_reg_num (), 1);
-      /* Life analysis used in SSA adds log_links but these
-        shouldn't be there until the flow stage, so clear
-        them away.  */
-      clear_log_links (insns);
 
       close_dump_file (DFI_ussa, print_rtl_with_bb, insns);
       timevar_pop (TV_FROM_SSA);
 
       ggc_collect ();
+      /* CFG is no longer maintained up-to-date.  */
+      free_bb_for_insn ();
     }
 
   timevar_push (TV_JUMP);
@@ -3032,7 +2719,7 @@ rest_of_compilation (decl)
   if (optimize > 0)
     {
       find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
-      cleanup_cfg (CLEANUP_EXPENSIVE);
+      cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP);
 
       /* ??? Run if-conversion before delete_null_pointer_checks,
          since the later does not preserve the CFG.  This should
@@ -3042,6 +2729,8 @@ rest_of_compilation (decl)
       if_convert (0);
       timevar_pop (TV_IFCVT);
 
+      /* CFG is no longer maintained up-to-date.  */
+      free_bb_for_insn ();
       /* Try to identify useless null pointer tests and delete them.  */
       if (flag_delete_null_pointer_checks)
        delete_null_pointer_checks (insns);
@@ -3087,8 +2776,12 @@ rest_of_compilation (decl)
       if (tem || optimize > 1)
        {
          timevar_push (TV_JUMP);
-         jump_optimize (insns, !JUMP_NOOP_MOVES, !JUMP_AFTER_REGSCAN);
+         rebuild_jump_labels (insns);
+         find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
+         cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP);
          timevar_pop (TV_JUMP);
+         /* CFG is no longer maintained up-to-date.  */
+         free_bb_for_insn ();
        }
 
       /* Run this after jump optmizations remove all the unreachable code
@@ -3101,9 +2794,11 @@ rest_of_compilation (decl)
          timevar_push (TV_JUMP);
          find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
 
-         cleanup_cfg (CLEANUP_EXPENSIVE);
+         cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP);
 
          delete_null_pointer_checks (insns);
+         /* CFG is no longer maintained up-to-date.  */
+         free_bb_for_insn ();
          timevar_pop (TV_JUMP);
        }
 
@@ -3135,13 +2830,15 @@ rest_of_compilation (decl)
       open_dump_file (DFI_gcse, decl);
 
       find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
-      cleanup_cfg (CLEANUP_EXPENSIVE);
+      cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP);
       tem = gcse_main (insns, rtl_dump_file);
 
       save_csb = flag_cse_skip_blocks;
       save_cfj = flag_cse_follow_jumps;
       flag_cse_skip_blocks = flag_cse_follow_jumps = 0;
 
+      /* CFG is no longer maintained up-to-date.  */
+      free_bb_for_insn ();
       /* If -fexpensive-optimizations, re-run CSE to clean up things done
         by gcse.  */
       if (flag_expensive_optimizations)
@@ -3159,7 +2856,12 @@ rest_of_compilation (decl)
        {
          tem = tem2 = 0;
          timevar_push (TV_JUMP);
-         jump_optimize (insns, !JUMP_NOOP_MOVES, !JUMP_AFTER_REGSCAN);
+         rebuild_jump_labels (insns);
+         delete_trivially_dead_insns (insns, max_reg_num (), 0);
+         find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
+         cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP);
+         /* CFG is no longer maintained up-to-date.  */
+         free_bb_for_insn ();
          timevar_pop (TV_JUMP);
 
          if (flag_expensive_optimizations)
@@ -3185,9 +2887,12 @@ rest_of_compilation (decl)
     {
       timevar_push (TV_LOOP);
       open_dump_file (DFI_loop, decl);
+      free_bb_for_insn ();
 
       if (flag_rerun_loop_opt)
        {
+         cleanup_barriers ();
+
          /* We only want to perform unrolling once.  */
 
          loop_optimize (insns, rtl_dump_file, 0);
@@ -3202,6 +2907,7 @@ rest_of_compilation (decl)
                  analysis code depends on this information.  */
          reg_scan (insns, max_reg_num (), 1);
        }
+      cleanup_barriers ();
       loop_optimize (insns, rtl_dump_file,
                     (flag_unroll_loops ? LOOP_UNROLL : 0) | LOOP_BCT);
 
@@ -3232,7 +2938,6 @@ rest_of_compilation (decl)
          delete_trivially_dead_insns (insns, max_reg_num (), 0);
 
          reg_scan (insns, max_reg_num (), 0);
-         jump_optimize (insns, !JUMP_NOOP_MOVES, JUMP_AFTER_REGSCAN);
 
          timevar_push (TV_IFCVT);
 
@@ -3244,13 +2949,19 @@ rest_of_compilation (decl)
 
          timevar_pop (TV_JUMP);
 
+         /* CFG is no longer maintained up-to-date.  */
+         free_bb_for_insn ();
          reg_scan (insns, max_reg_num (), 0);
          tem = cse_main (insns, max_reg_num (), 1, rtl_dump_file);
 
          if (tem)
            {
              timevar_push (TV_JUMP);
-             jump_optimize (insns, !JUMP_NOOP_MOVES, !JUMP_AFTER_REGSCAN);
+             rebuild_jump_labels (insns);
+             find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
+             cleanup_cfg (CLEANUP_EXPENSIVE);
+             /* CFG is no longer maintained up-to-date.  */
+             free_bb_for_insn ();
              timevar_pop (TV_JUMP);
            }
        }
@@ -3353,6 +3064,10 @@ rest_of_compilation (decl)
       rebuild_jump_labels_after_combine
        = combine_instructions (insns, max_reg_num ());
 
+      /* Always purge dead edges, as we may eliminate an insn throwing
+         exception.  */
+      rebuild_jump_labels_after_combine |= purge_all_dead_edges (true);
+
       /* Combining insns may have turned an indirect jump into a
         direct jump.  Rebuid the JUMP_LABEL fields of jumping
         instructions.  */
@@ -3362,21 +3077,7 @@ rest_of_compilation (decl)
          rebuild_jump_labels (insns);
          timevar_pop (TV_JUMP);
 
-         timevar_push (TV_FLOW);
-         find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
-         cleanup_cfg (CLEANUP_EXPENSIVE);
-
-         /* Blimey.  We've got to have the CFG up to date for the call to
-            if_convert below.  However, the random deletion of blocks
-            without updating life info can wind up with Wierd Stuff in
-            global_live_at_end.  We then run sched1, which updates things
-            properly, discovers the wierdness and aborts.  */
-         allocate_bb_life_data ();
-         update_life_info (NULL, UPDATE_LIFE_GLOBAL_RM_NOTES,
-                           PROP_DEATH_NOTES | PROP_KILL_DEAD_CODE
-                           | PROP_SCAN_DEAD_CODE);
-
-         timevar_pop (TV_FLOW);
+         cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_UPDATE_LIFE);
        }
 
       close_dump_file (DFI_combine, print_rtl_with_bb, insns);
@@ -3424,7 +3125,7 @@ rest_of_compilation (decl)
   register_life_up_to_date = 0;
 
 #ifdef OPTIMIZE_MODE_SWITCHING
-  timevar_push (TV_GCSE);
+  timevar_push (TV_MODE_SWITCH);
 
   no_new_pseudos = 0;
   if (optimize_mode_switching (NULL))
@@ -3436,7 +3137,7 @@ rest_of_compilation (decl)
     }
   no_new_pseudos = 1;
 
-  timevar_pop (TV_GCSE);
+  timevar_pop (TV_MODE_SWITCH);
 #endif
 
   timevar_push (TV_SCHED);
@@ -3480,6 +3181,15 @@ rest_of_compilation (decl)
 
   if (! register_life_up_to_date)
     recompute_reg_usage (insns, ! optimize_size);
+
+  /* Allocate the reg_renumber array.  */
+  allocate_reg_info (max_regno, FALSE, TRUE);
+
+  /* And the reg_equiv_memory_loc array.  */
+  reg_equiv_memory_loc = (rtx *) xcalloc (max_regno, sizeof (rtx));
+
+  allocate_initial_values (reg_equiv_memory_loc);
+
   regclass (insns, max_reg_num (), rtl_dump_file);
   rebuild_label_notes_after_reload = local_alloc ();
 
@@ -3539,16 +3249,6 @@ rest_of_compilation (decl)
       timevar_pop (TV_RELOAD_CSE_REGS);
     }
 
-  /* If optimizing, then go ahead and split insns now since we are about
-     to recompute flow information anyway.  */
-  if (optimize > 0)
-    {
-      int old_labelnum = max_label_num ();
-
-      split_all_insns (0);
-      rebuild_label_notes_after_reload |= old_labelnum != max_label_num ();
-    }
-
   /* Register allocation and reloading may have turned an indirect jump into
      a direct jump.  If so, we must rebuild the JUMP_LABEL fields of
      jumping instructions.  */
@@ -3567,8 +3267,15 @@ rest_of_compilation (decl)
   timevar_push (TV_FLOW2);
   open_dump_file (DFI_flow2, decl);
 
-  jump_optimize (insns, JUMP_NOOP_MOVES, !JUMP_AFTER_REGSCAN);
-  find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
+#ifdef ENABLE_CHECKING
+  verify_flow_info ();
+#endif
+
+  /* If optimizing, then go ahead and split insns now.  */
+  if (optimize > 0)
+    split_all_insns (0);
+
+  cleanup_cfg (optimize ? CLEANUP_EXPENSIVE : 0);
 
   /* On some machines, the prologue and epilogue code, or parts thereof,
      can be represented as RTL.  Doing so lets us schedule insns between
@@ -3668,7 +3375,7 @@ rest_of_compilation (decl)
 
   reg_to_stack (insns, rtl_dump_file);
 
-  close_dump_file (DFI_stack, print_rtl, insns);
+  close_dump_file (DFI_stack, print_rtl_with_bb, insns);
   timevar_pop (TV_REG_STACK);
 
   ggc_collect ();
@@ -3691,19 +3398,26 @@ rest_of_compilation (decl)
       close_dump_file (DFI_bbro, print_rtl_with_bb, insns);
       timevar_pop (TV_REORDER_BLOCKS);
     }
+  compute_alignments ();
+
+  /* CFG is no longer maintained up-to-date.  */
+  free_bb_for_insn ();
 
   /* If a machine dependent reorganization is needed, call it.  */
 #ifdef MACHINE_DEPENDENT_REORG
+  timevar_push (TV_MACH_DEP);
   open_dump_file (DFI_mach, decl);
 
   MACHINE_DEPENDENT_REORG (insns);
 
   close_dump_file (DFI_mach, print_rtl, insns);
+  timevar_pop (TV_MACH_DEP);
 
   ggc_collect ();
 #endif
 
-  /* CFG no longer kept up to date.  */
+  purge_line_number_notes (insns);
+  cleanup_barriers ();
 
   /* If a scheduling pass for delayed branches is to be done,
      call the scheduling code.  */
@@ -3725,7 +3439,7 @@ rest_of_compilation (decl)
 
 #if defined (HAVE_ATTR_length) && !defined (STACK_REGS)
   timevar_push (TV_SHORTEN_BRANCH);
-  split_all_insns (0);
+  split_all_insns_noflow ();
   timevar_pop (TV_SHORTEN_BRANCH);
 #endif
 
@@ -3802,20 +3516,7 @@ rest_of_compilation (decl)
      generated.  During that call, we *will* be routed past here.  */
 
   timevar_push (TV_SYMOUT);
-#ifdef DBX_DEBUGGING_INFO
-  if (write_symbols == DBX_DEBUG)
-    dbxout_function (decl);
-#endif
-
-#ifdef DWARF_DEBUGGING_INFO
-  if (write_symbols == DWARF_DEBUG)
-    dwarfout_file_scope_decl (decl, 0);
-#endif
-
-#ifdef DWARF2_DEBUGGING_INFO
-  if (write_symbols == DWARF2_DEBUG)
-    dwarf2out_decl (decl);
-#endif
+  (*debug_hooks->function_decl) (decl);
   timevar_pop (TV_SYMOUT);
 
  exit_rest_of_compilation:
@@ -3863,7 +3564,13 @@ rest_of_compilation (decl)
   /* We're done with this function.  Free up memory if we can.  */
   free_after_parsing (cfun);
   if (! DECL_DEFER_OUTPUT (decl))
-    free_after_compilation (cfun);
+    {
+      free_after_compilation (cfun);
+
+      /* Clear integrate.c's pointer to the cfun structure we just
+        destroyed.  */
+      DECL_SAVED_INSNS (decl) = 0;
+    }
   cfun = 0;
 
   ggc_collect ();
@@ -4069,7 +3776,7 @@ display_target_options ()
     }
 }
 \f
-/* Parse a -d... comand line switch.  */
+/* Parse a -d... command line switch.  */
 
 static void
 decode_d_option (arg)
@@ -4101,7 +3808,7 @@ decode_d_option (arg)
        rtl_dump_and_exit = 1;
        break;
       case 'y':
-       set_yydebug (1);
+       (*lang_hooks.set_yydebug) (1);
        break;
       case 'D':        /* These are handled by the preprocessor.  */
       case 'I':
@@ -4122,7 +3829,7 @@ decode_d_option (arg)
       }
 }
 
-/* Parse a -f... comand line switch.  ARG is the value after the -f.
+/* Parse a -f... command line switch.  ARG is the value after the -f.
    It is safe to access 'ARG - 2' to generate the full switch name.
    Return the number of strings consumed.  */
 
@@ -4226,7 +3933,7 @@ decode_f_option (arg)
   return 1;
 }
 
-/* Parse a -W... comand line switch.  ARG is the value after the -W.
+/* Parse a -W... command line switch.  ARG is the value after the -W.
    It is safe to access 'ARG - 2' to generate the full switch name.
    Return the number of strings consumed.  */
 
@@ -4277,7 +3984,7 @@ decode_W_option (arg)
   return 1;
 }
 
-/* Parse a -g... comand line switch.  ARG is the value after the -g.
+/* Parse a -g... command line switch.  ARG is the value after the -g.
    It is safe to access 'ARG - 2' to generate the full switch name.
    Return the number of strings consumed.  */
 
@@ -4297,7 +4004,7 @@ decode_g_option (arg)
      -gdwarf -g3 is equivalent to -gdwarf3.  */
   static int type_explicitly_set_p = 0;
   /* Indexed by enum debug_info_type.  */
-  static const char *debug_type_names[] =
+  static const char *const debug_type_names[] =
   {
     "none", "stabs", "coff", "dwarf-1", "dwarf-2", "xcoff"
   };
@@ -4315,7 +4022,7 @@ decode_g_option (arg)
          enum debug_info_type type = da->debug_type;
          const char *p = arg + da_len;
 
-         if (*p && (*p < '0' || *p > '9'))
+         if (*p && ! ISDIGIT (*p))
            continue;
 
          /* A debug flag without a level defaults to level 2.
@@ -4644,95 +4351,300 @@ independent_decode_option (argc, argv)
   return 1;
 }
 \f
-/* Entry point of cc1, cc1plus, jc1, f771, etc.
-   Decode command args, then call compile_file.
-   Exit code is FATAL_EXIT_CODE if can't open files or if there were
-   any errors, or SUCCESS_EXIT_CODE if compilation succeeded.
-
-   It is not safe to call this function more than once.  */
+/* Decode -m switches.  */
+/* Decode the switch -mNAME.  */
 
-int
-toplev_main (argc, argv)
-     int argc;
-     char **argv;
+static void
+set_target_switch (name)
+     const char *name;
 {
-  register int i;
-  char *p;
-
-  /* save in case md file wants to emit args as a comment.  */
-  save_argc = argc;
-  save_argv = argv;
-
-  p = argv[0] + strlen (argv[0]);
-  while (p != argv[0] && !IS_DIR_SEPARATOR (p[-1]))
-    --p;
-  progname = p;
-
-  xmalloc_set_program_name (progname);
+  size_t j;
+  int valid_target_option = 0;
 
-/* LC_CTYPE determines the character set used by the terminal so it has be set
-   to output messages correctly.  */
+  for (j = 0; j < ARRAY_SIZE (target_switches); j++)
+    if (!strcmp (target_switches[j].name, name))
+      {
+       if (target_switches[j].value < 0)
+         target_flags &= ~-target_switches[j].value;
+       else
+         target_flags |= target_switches[j].value;
+       valid_target_option = 1;
+      }
 
-#ifdef HAVE_LC_MESSAGES
-  setlocale (LC_CTYPE, "");
-  setlocale (LC_MESSAGES, "");
-#else
-  setlocale (LC_ALL, "");
+#ifdef TARGET_OPTIONS
+  if (!valid_target_option)
+    for (j = 0; j < ARRAY_SIZE (target_options); j++)
+      {
+       int len = strlen (target_options[j].prefix);
+       if (!strncmp (target_options[j].prefix, name, len))
+         {
+           *target_options[j].variable = name + len;
+           valid_target_option = 1;
+         }
+      }
 #endif
 
-  (void) bindtextdomain (PACKAGE, localedir);
-  (void) textdomain (PACKAGE);
-
-  /* Install handler for SIGFPE, which may be received while we do
-     compile-time floating point arithmetic.  */
-  signal (SIGFPE, float_signal);
+  if (!valid_target_option)
+    error ("Invalid option `%s'", name);
+}
+\f
+/* Print version information to FILE.
+   Each line begins with INDENT (for the case where FILE is the
+   assembler output file).  */
 
-  /* Trap fatal signals, e.g. SIGSEGV, and convert them to ICE messages.  */
-#ifdef SIGSEGV
-  signal (SIGSEGV, crash_signal);
-#endif
-#ifdef SIGILL
-  signal (SIGILL, crash_signal);
-#endif
-#ifdef SIGBUS
-  signal (SIGBUS, crash_signal);
-#endif
-#ifdef SIGABRT
-  signal (SIGABRT, crash_signal);
+static void
+print_version (file, indent)
+     FILE *file;
+     const char *indent;
+{
+#ifndef __VERSION__
+#define __VERSION__ "[?]"
 #endif
-#if defined SIGIOT && (!defined SIGABRT || SIGABRT != SIGIOT)
-  signal (SIGIOT, crash_signal);
+  fnotice (file,
+#ifdef __GNUC__
+          "%s%s%s version %s (%s)\n%s\tcompiled by GNU C version %s.\n"
+#else
+          "%s%s%s version %s (%s) compiled by CC.\n"
 #endif
+          , indent, *indent != 0 ? " " : "",
+          lang_hooks.name, version_string, TARGET_NAME,
+          indent, __VERSION__);
+}
 
-  decl_printable_name = decl_name;
-  lang_expand_expr = (lang_expand_expr_t) do_abort;
+/* Print an option value and return the adjusted position in the line.
+   ??? We don't handle error returns from fprintf (disk full); presumably
+   other code will catch a disk full though.  */
 
-  /* Initialize whether `char' is signed.  */
-  flag_signed_char = DEFAULT_SIGNED_CHAR;
-#ifdef DEFAULT_SHORT_ENUMS
-  /* Initialize how much space enums occupy, by default.  */
-  flag_short_enums = DEFAULT_SHORT_ENUMS;
-#endif
+static int
+print_single_switch (file, pos, max, indent, sep, term, type, name)
+     FILE *file;
+     int pos, max;
+     const char *indent, *sep, *term, *type, *name;
+{
+  /* The ultrix fprintf returns 0 on success, so compute the result we want
+     here since we need it for the following test.  */
+  int len = strlen (sep) + strlen (type) + strlen (name);
 
-  /* Initialize the garbage-collector.  */
-  init_ggc ();
-  init_stringpool ();
-  ggc_add_rtx_root (&stack_limit_rtx, 1);
-  ggc_add_tree_root (&current_function_decl, 1);
-  ggc_add_tree_root (&current_function_func_begin_label, 1);
+  if (pos != 0
+      && pos + len > max)
+    {
+      fprintf (file, "%s", term);
+      pos = 0;
+    }
+  if (pos == 0)
+    {
+      fprintf (file, "%s", indent);
+      pos = strlen (indent);
+    }
+  fprintf (file, "%s%s%s", sep, type, name);
+  pos += len;
+  return pos;
+}
 
-  /* Initialize the diagnostics reporting machinery.  */
-  diagnostic_initialize (global_dc);
+/* 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.  */
 
-  /* Register the language-independent parameters.  */
-  add_params (lang_independent_params, LAST_PARAM);
+static void
+print_switch_values (file, pos, max, indent, sep, term)
+     FILE *file;
+     int pos, max;
+     const char *indent, *sep, *term;
+{
+  size_t j;
+  char **p;
 
-  /* Perform language-specific options intialization.  */
-  if (lang_hooks.init_options)
-    (*lang_hooks.init_options) ();
+  /* Print the options as passed.  */
 
-  /* Scan to see what optimization level has been specified.  That will
-     determine the default value of many flags.  */
+  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 < ARRAY_SIZE (f_options); j++)
+    if (*f_options[j].variable == f_options[j].on_value)
+      pos = print_single_switch (file, pos, max, indent, sep, term,
+                                "-f", f_options[j].string);
+
+  /* Print target specific options.  */
+
+  for (j = 0; j < ARRAY_SIZE (target_switches); j++)
+    if (target_switches[j].name[0] != '\0'
+       && target_switches[j].value > 0
+       && ((target_switches[j].value & target_flags)
+           == target_switches[j].value))
+      {
+       pos = print_single_switch (file, pos, max, indent, sep, term,
+                                  "-m", target_switches[j].name);
+      }
+
+#ifdef TARGET_OPTIONS
+  for (j = 0; j < ARRAY_SIZE (target_options); 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 (file, "%s", term);
+}
+\f
+/* Open assembly code output file.  Do this even if -fsyntax-only is
+   on, because then the driver will have provided the name of a
+   temporary file or bit bucket for us.  NAME is the file specified on
+   the command line, possibly NULL.  */
+static void
+init_asm_output (name)
+     const char *name;
+{
+  if (name == NULL && asm_file_name == 0)
+    asm_out_file = stdout;
+  else
+    {
+      if (asm_file_name == 0)
+        {
+          int len = strlen (dump_base_name);
+          char *dumpname = (char *) xmalloc (len + 6);
+          memcpy (dumpname, dump_base_name, len + 1);
+          strip_off_ending (dumpname, len);
+          strcat (dumpname, ".s");
+          asm_file_name = dumpname;
+        }
+      if (!strcmp (asm_file_name, "-"))
+        asm_out_file = stdout;
+      else
+        asm_out_file = fopen (asm_file_name, "w");
+      if (asm_out_file == 0)
+       fatal_io_error ("can't open %s for writing", asm_file_name);
+    }
+
+#ifdef IO_BUFFER_SIZE
+  setvbuf (asm_out_file, (char *) xmalloc (IO_BUFFER_SIZE),
+           _IOFBF, IO_BUFFER_SIZE);
+#endif
+
+  if (!flag_syntax_only)
+    {
+#ifdef ASM_FILE_START
+      ASM_FILE_START (asm_out_file);
+#endif
+
+#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
+    }
+}
+\f
+/* Initialization of the front end environment, before command line
+   options are parsed.  Signal handlers, internationalization etc.
+   ARGV0 is main's argv[0].  */
+static void
+general_init (argv0)
+     char *argv0;
+{
+  char *p;
+
+  p = argv0 + strlen (argv0);
+  while (p != argv0 && !IS_DIR_SEPARATOR (p[-1]))
+    --p;
+  progname = p;
+
+  xmalloc_set_program_name (progname);
+
+  gcc_init_libintl ();
+
+  /* Install handler for SIGFPE, which may be received while we do
+     compile-time floating point arithmetic.  */
+  signal (SIGFPE, float_signal);
+
+  /* Trap fatal signals, e.g. SIGSEGV, and convert them to ICE messages.  */
+#ifdef SIGSEGV
+  signal (SIGSEGV, crash_signal);
+#endif
+#ifdef SIGILL
+  signal (SIGILL, crash_signal);
+#endif
+#ifdef SIGBUS
+  signal (SIGBUS, crash_signal);
+#endif
+#ifdef SIGABRT
+  signal (SIGABRT, crash_signal);
+#endif
+#if defined SIGIOT && (!defined SIGABRT || SIGABRT != SIGIOT)
+  signal (SIGIOT, crash_signal);
+#endif
+
+  /* Initialize the diagnostics reporting machinery, so option parsing
+     can give warnings and errors.  */
+  diagnostic_initialize (global_dc);
+}
+\f
+/* Parse command line options and set default flag values, called
+   after language-independent option-independent intialization.  Do
+   minimal options processing.  Outputting diagnostics is OK, but GC
+   and identifier hashtables etc. are not initialized yet.  */
+static void
+parse_options_and_default_flags (argc, argv)
+     int argc;
+     char **argv;
+{
+  int i;
+
+  /* Save in case md file wants to emit args as a comment.  */
+  save_argc = argc;
+  save_argv = argv;
+
+  /* Initialize register usage now so switches may override.  */
+  init_reg_sets ();
+
+  /* Register the language-independent parameters.  */
+  add_params (lang_independent_params, LAST_PARAM);
+
+  /* Perform language-specific options initialization.  */
+  (*lang_hooks.init_options) ();
+
+  /* Scan to see what optimization level has been specified.  That will
+     determine the default value of many flags.  */
   for (i = 1; i < argc; i++)
     {
       if (!strcmp (argv[i], "-O"))
@@ -4764,6 +4676,11 @@ toplev_main (argc, argv)
        }
     }
 
+  if (!optimize)
+    {
+      flag_merge_constants = 0;
+    }
+
   if (optimize >= 1)
     {
       flag_defer_pop = 1;
@@ -4814,6 +4731,13 @@ toplev_main (argc, argv)
       align_functions = 1;
     }
 
+  /* Initialize whether `char' is signed.  */
+  flag_signed_char = DEFAULT_SIGNED_CHAR;
+#ifdef DEFAULT_SHORT_ENUMS
+  /* Initialize how much space enums occupy, by default.  */
+  flag_short_enums = DEFAULT_SHORT_ENUMS;
+#endif
+
   /* Initialize target_flags before OPTIMIZATION_OPTIONS so the latter can
      modify it.  */
   target_flags = 0;
@@ -4830,9 +4754,6 @@ toplev_main (argc, argv)
   OPTIMIZATION_OPTIONS (optimize, optimize_size);
 #endif
 
-  /* Initialize register usage now so switches may override.  */
-  init_reg_sets ();
-
   /* Perform normal command line switch decoding.  */
   for (i = 1; i < argc;)
     {
@@ -4899,12 +4820,13 @@ toplev_main (argc, argv)
     }
 
   /* All command line options have been processed.  */
-  if (lang_hooks.post_options)
-    (*lang_hooks.post_options) ();
-
-  if (exit_after_options)
-    exit (0);
-
+  (*lang_hooks.post_options) ();
+}
+\f
+/* Process the options that have been parsed.  */
+static void
+process_options ()
+{
   /* Checker uses the frame pointer.  */
   if (flag_check_memory_usage)
     flag_omit_frame_pointer = 0;
@@ -4937,11 +4859,17 @@ toplev_main (argc, argv)
   /* Set up the align_*_log variables, defaulting them to 1 if they
      were still unset.  */
   if (align_loops <= 0) align_loops = 1;
+  if (align_loops_max_skip > align_loops || !align_loops)
+    align_loops_max_skip = align_loops - 1;
   align_loops_log = floor_log2 (align_loops * 2 - 1);
   if (align_jumps <= 0) align_jumps = 1;
+  if (align_jumps_max_skip > align_jumps || !align_jumps)
+    align_jumps_max_skip = align_jumps - 1;
   align_jumps_log = floor_log2 (align_jumps * 2 - 1);
   if (align_labels <= 0) align_labels = 1;
   align_labels_log = floor_log2 (align_labels * 2 - 1);
+  if (align_labels_max_skip > align_labels || !align_labels)
+    align_labels_max_skip = align_labels - 1;
   if (align_functions <= 0) align_functions = 1;
   align_functions_log = floor_log2 (align_functions * 2 - 1);
 
@@ -4965,6 +4893,11 @@ toplev_main (argc, argv)
       flag_rerun_cse_after_loop = 1;
     }
 
+  if (flag_non_call_exceptions)
+    flag_asynchronous_unwind_tables = 1;
+  if (flag_asynchronous_unwind_tables)
+    flag_unwind_tables = 1;
+
   /* Warn about options that are not supported on this machine.  */
 #ifndef INSN_SCHEDULING
   if (flag_schedule_insns || flag_schedule_insns_after_reload)
@@ -5009,204 +4942,276 @@ toplev_main (argc, argv)
        print_switch_values (stderr, 0, MAX_LINE, "", " ", "\n");
     }
 
-  compile_file (filename);
+  if (! quiet_flag)
+    time_report = 1;
 
-  if (errorcount)
-    return (FATAL_EXIT_CODE);
-  if (sorrycount)
-    return (FATAL_EXIT_CODE);
-  return (SUCCESS_EXIT_CODE);
+  if (flag_syntax_only)
+    {
+      write_symbols = NO_DEBUG;
+      profile_flag = 0;
+      profile_block_flag = 0;
+    }
+
+  /* Now we know write_symbols, set up the debug hooks based on it.
+     By default we do nothing for debug output.  */
+#if defined(DBX_DEBUGGING_INFO)
+  if (write_symbols == DBX_DEBUG)
+    debug_hooks = &dbx_debug_hooks;
+#endif
+#if defined(XCOFF_DEBUGGING_INFO)
+  if (write_symbols == XCOFF_DEBUG)
+    debug_hooks = &xcoff_debug_hooks;
+#endif
+#ifdef SDB_DEBUGGING_INFO
+  if (write_symbols == SDB_DEBUG)
+    debug_hooks = &sdb_debug_hooks;
+#endif
+#ifdef DWARF_DEBUGGING_INFO
+  if (write_symbols == DWARF_DEBUG)
+    debug_hooks = &dwarf_debug_hooks;
+#endif
+#ifdef DWARF2_DEBUGGING_INFO
+  if (write_symbols == DWARF2_DEBUG)
+    debug_hooks = &dwarf2_debug_hooks;
+#endif
+
+  /* If auxiliary info generation is desired, open the output file.
+     This goes in the same directory as the source file--unlike
+     all the other output files.  */
+  if (flag_gen_aux_info)
+    {
+      aux_info_file = fopen (aux_info_file_name, "w");
+      if (aux_info_file == 0)
+       fatal_io_error ("can't open %s", aux_info_file_name);
+    }
+
+  if (! targetm.have_named_sections)
+    {
+      if (flag_function_sections)
+       {
+         warning ("-ffunction-sections not supported for this target.");
+         flag_function_sections = 0;
+       }
+      if (flag_data_sections)
+       {
+         warning ("-fdata-sections not supported for this target.");
+         flag_data_sections = 0;
+       }
+    }
+
+  if (flag_function_sections
+      && (profile_flag || profile_block_flag))
+    {
+      warning ("-ffunction-sections disabled; it makes profiling impossible.");
+      flag_function_sections = 0;
+    }
+
+#ifndef OBJECT_FORMAT_ELF
+  if (flag_function_sections && write_symbols != NO_DEBUG)
+    warning ("-ffunction-sections may affect debugging on some targets.");
+#endif
 }
 \f
-/* Decode -m switches.  */
-/* Decode the switch -mNAME.  */
-
+/* Language-independent initialization, before language-dependent
+   initialization.  */
 static void
-set_target_switch (name)
+lang_independent_init ()
+{
+  decl_printable_name = decl_name;
+  lang_expand_expr = (lang_expand_expr_t) do_abort;
+
+  /* Set the language-dependent identifer size.  */
+  tree_code_length[(int) IDENTIFIER_NODE]
+    = ((lang_hooks.identifier_size - sizeof (struct tree_common))
+       / sizeof (tree));
+
+  /* Initialize the garbage-collector, and string pools.  FIXME: We
+     should do this later, in independent_init () when we know we
+     actually want to compile something, but cpplib currently wants to
+     use the hash table immediately in cpp_create_reader.  */
+  init_ggc ();
+  ggc_add_rtx_root (&stack_limit_rtx, 1);
+  ggc_add_tree_root (&current_function_decl, 1);
+  ggc_add_tree_root (&current_function_func_begin_label, 1);
+
+  init_stringpool ();
+  init_obstacks ();
+
+  init_emit_once (debug_info_level == DINFO_LEVEL_NORMAL
+                 || debug_info_level == DINFO_LEVEL_VERBOSE
+                 || flag_test_coverage
+                 || warn_notreached);
+  init_regs ();
+  init_alias_once ();
+  init_stmt ();
+  init_loop ();
+  init_reload ();
+  init_function_once ();
+  init_stor_layout_once ();
+  init_varasm_once ();
+  init_EXPR_INSN_LIST_cache ();
+
+  /* The following initialization functions need to generate rtl, so
+     provide a dummy function context for them.  */
+  init_dummy_function_start ();
+  init_expmed ();
+  init_expr_once ();
+  if (flag_caller_saves)
+    init_caller_save ();
+  expand_dummy_function_end ();
+}
+\f
+/* Language-dependent initialization.  Returns non-zero on success.  */
+static int
+lang_dependent_init (name)
      const char *name;
 {
-  register size_t j;
-  int valid_target_option = 0;
+  if (dump_base_name == 0)
+    dump_base_name = name ? name : "gccdump";
 
-  for (j = 0; j < ARRAY_SIZE (target_switches); j++)
-    if (!strcmp (target_switches[j].name, name))
-      {
-       if (target_switches[j].value < 0)
-         target_flags &= ~-target_switches[j].value;
-       else
-         target_flags |= target_switches[j].value;
-       valid_target_option = 1;
-      }
+  /* Front-end initialization.  This hook can assume that GC,
+     identifier hashes etc. are set up, but debug initialization is
+     not done yet.  This routine must return the original filename
+     (e.g. foo.i -> foo.c) so can correctly initialize debug output.  */
+  name = (*lang_hooks.init) (name);
+  if (name == NULL)
+    return 0;
 
-#ifdef TARGET_OPTIONS
-  if (!valid_target_option)
-    for (j = 0; j < ARRAY_SIZE (target_options); j++)
-      {
-       int len = strlen (target_options[j].prefix);
-       if (!strncmp (target_options[j].prefix, name, len))
-         {
-           *target_options[j].variable = name + len;
-           valid_target_option = 1;
-         }
-      }
+  /* Is this duplication necessary?  */
+  name = ggc_strdup (name);
+  main_input_filename = input_filename = name;
+  init_asm_output (name);
+
+  /* These create various _DECL nodes, so need to be called after the
+     front end is initialized.  */
+  init_eh ();
+  init_optabs ();
+
+  /* Put an entry on the input file stack for the main input file.  */
+  push_srcloc (input_filename, 0);
+
+  /* If dbx symbol table desired, initialize writing it and output the
+     predefined types.  */
+  timevar_push (TV_SYMOUT);
+
+#ifdef DWARF2_UNWIND_INFO
+  if (dwarf2out_do_frame ())
+    dwarf2out_frame_init ();
 #endif
 
-  if (!valid_target_option)
-    error ("Invalid option `%s'", name);
+  /* Now we have the correct original filename, we can initialize
+     debug output.  */
+  (*debug_hooks->init) (name);
+
+  timevar_pop (TV_SYMOUT);
+
+  return 1;
 }
 \f
-/* Print version information to FILE.
-   Each line begins with INDENT (for the case where FILE is the
-   assembler output file).  */
+/* Clean up: close opened files, etc.  */
 
 static void
-print_version (file, indent)
-     FILE *file;
-     const char *indent;
+finalize ()
 {
-#ifndef __VERSION__
-#define __VERSION__ "[?]"
-#endif
-  fnotice (file,
-#ifdef __GNUC__
-          "%s%s%s version %s (%s)\n%s\tcompiled by GNU C version %s.\n"
-#else
-          "%s%s%s version %s (%s) compiled by CC.\n"
-#endif
-          , indent, *indent != 0 ? " " : "",
-          language_string, version_string, TARGET_NAME,
-          indent, __VERSION__);
-}
-
-/* Print an option value and return the adjusted position in the line.
-   ??? We don't handle error returns from fprintf (disk full); presumably
-   other code will catch a disk full though.  */
+  /* Close the dump files.  */
+  if (flag_gen_aux_info)
+    {
+      fclose (aux_info_file);
+      if (errorcount)
+       unlink (aux_info_file_name);
+    }
 
-static int
-print_single_switch (file, pos, max, indent, sep, term, type, name)
-     FILE *file;
-     int pos, max;
-     const char *indent, *sep, *term, *type, *name;
-{
-  /* The ultrix fprintf returns 0 on success, so compute the result we want
-     here since we need it for the following test.  */
-  int len = strlen (sep) + strlen (type) + strlen (name);
+  /* Close non-debugging input and output files.  Take special care to note
+     whether fclose returns an error, since the pages might still be on the
+     buffer chain while the file is open.  */
 
-  if (pos != 0
-      && pos + len > max)
+  if (asm_out_file)
     {
-      fprintf (file, "%s", term);
-      pos = 0;
+      if (ferror (asm_out_file) != 0)
+       fatal_io_error ("error writing to %s", asm_file_name);
+      if (fclose (asm_out_file) != 0)
+       fatal_io_error ("error closing %s", asm_file_name);
     }
-  if (pos == 0)
+
+  /* Do whatever is necessary to finish printing the graphs.  */
+  if (graph_dump_format != no_graph)
     {
-      fprintf (file, "%s", indent);
-      pos = strlen (indent);
-    }
-  fprintf (file, "%s%s%s", sep, type, name);
-  pos += len;
-  return pos;
-}
+      int i;
 
-/* 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.  */
+      for (i = 0; i < (int) DFI_MAX; ++i)
+       if (dump_file[i].initialized && dump_file[i].graph_dump_p)
+         {
+           char seq[16];
+           char *suffix;
 
-static void
-print_switch_values (file, pos, max, indent, sep, term)
-     FILE *file;
-     int pos, max;
-     const char *indent, *sep, *term;
-{
-  size_t j;
-  char **p;
+           sprintf (seq, ".%02d.", i);
+           suffix = concat (seq, dump_file[i].extension, NULL);
+           finish_graph_dump_file (dump_base_name, suffix);
+           free (suffix);
+         }
+    }
 
-  /* Print the options as passed.  */
+  if (mem_report)
+    {
+      ggc_print_statistics ();
+      stringpool_statistics ();
+      dump_tree_statistics ();
+    }
 
-  pos = print_single_switch (file, pos, max, indent, *indent ? " " : "", term,
-                            _("options passed: "), "");
+  /* Free up memory for the benefit of leak detectors.  */
+  free_reg_info ();
 
-  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;
+  /* Language-specific end of compilation actions.  */
+  (*lang_hooks.finish) ();
+}
+\f
+/* Entry point of cc1, cc1plus, jc1, f771, etc.
+   Decode command args, then call compile_file.
+   Exit code is FATAL_EXIT_CODE if can't open files or if there were
+   any errors, or SUCCESS_EXIT_CODE if compilation succeeded.
 
-       pos = print_single_switch (file, pos, max, indent, sep, term, *p, "");
-      }
-  if (pos > 0)
-    fprintf (file, "%s", term);
+   It is not safe to call this function more than once.  */
 
-  /* Print the -f and -m options that have been enabled.
-     We don't handle language specific options but printing argv
-     should suffice.  */
+int
+toplev_main (argc, argv)
+     int argc;
+     char **argv;
+{
+  /* Initialization of GCC's environment, and diagnostics.  */
+  general_init (argv [0]);
 
-  pos = print_single_switch (file, 0, max, indent, *indent ? " " : "", term,
-                            _("options enabled: "), "");
+  /* Parse the options and do minimal processing; basically just
+     enough to default flags appropriately.  */
+  parse_options_and_default_flags (argc, argv);
 
-  for (j = 0; j < ARRAY_SIZE (f_options); j++)
-    if (*f_options[j].variable == f_options[j].on_value)
-      pos = print_single_switch (file, pos, max, indent, sep, term,
-                                "-f", f_options[j].string);
+  /* Exit early if we can (e.g. -help).  */
+  if (exit_after_options)
+    return (SUCCESS_EXIT_CODE);
 
-  /* Print target specific options.  */
+  /* The bulk of command line switch processing.  */
+  process_options ();
 
-  for (j = 0; j < ARRAY_SIZE (target_switches); j++)
-    if (target_switches[j].name[0] != '\0'
-       && target_switches[j].value > 0
-       && ((target_switches[j].value & target_flags)
-           == target_switches[j].value))
-      {
-       pos = print_single_switch (file, pos, max, indent, sep, term,
-                                  "-m", target_switches[j].name);
-      }
+  /* We cannot start timing until after options are processed since that
+     says if we run timers or not.  */
+  init_timevar ();
+  timevar_start (TV_TOTAL);
 
-#ifdef TARGET_OPTIONS
-  for (j = 0; j < ARRAY_SIZE (target_options); 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
+  /* Language-independent initialization.  Also sets up GC, identifier
+     hashes etc.  */
+  lang_independent_init ();
 
-  fprintf (file, "%s", term);
-}
+  /* Language-dependent initialization.  Returns true on success.  */
+  if (lang_dependent_init (filename))
+    compile_file ();
 
-/* Returns nonzero if it is appropriate not to emit any debugging
-   information for BLOCK, because it doesn't contain any instructions.
-   This may not be the case for blocks containing nested functions, since
-   we may actually call such a function even though the BLOCK information
-   is messed up.  */
+  finalize ();
 
-int
-debug_ignore_block (block)
-     tree block ATTRIBUTE_UNUSED;
-{
-  /* Never delete the BLOCK for the outermost scope
-     of the function; we can refer to names from
-     that scope even if the block notes are messed up.  */
-  if (is_body_block (block))
-    return 0;
+  /* Stop timing and print the times.  */
+  timevar_stop (TV_TOTAL);
+  timevar_print (stderr);
 
-#ifdef DWARF2_DEBUGGING_INFO
-  if (write_symbols == DWARF2_DEBUG)
-    return dwarf2out_ignore_block (block);
-#endif
+  if (errorcount || sorrycount)
+    return (FATAL_EXIT_CODE);
 
-  return 1;
+  return (SUCCESS_EXIT_CODE);
 }