OSDN Git Service

cp:
[pf3gnuchains/gcc-fork.git] / gcc / toplev.c
index ad23683..7460582 100644 (file)
@@ -1,6 +1,6 @@
 /* Top level of GNU C compiler
    Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001 Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -46,6 +46,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "flags.h"
 #include "insn-attr.h"
 #include "insn-config.h"
+#include "insn-flags.h"
 #include "hard-reg-set.h"
 #include "recog.h"
 #include "output.h"
@@ -68,6 +69,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "integrate.h"
 #include "debug.h"
 #include "target.h"
+#include "langhooks.h"
 
 #if defined (DWARF2_UNWIND_INFO) || defined (DWARF2_DEBUGGING_INFO)
 #include "dwarf2out.h"
@@ -113,60 +115,28 @@ vms_fopen (fname, type)
 #define fopen vms_fopen
 #endif /* VMS  */
 
-#ifndef DEFAULT_GDB_EXTENSIONS
-#define DEFAULT_GDB_EXTENSIONS 1
-#endif
-
-/* If more than one debugging type is supported, you must define
-   PREFERRED_DEBUGGING_TYPE to choose a format in a system-dependent way.
-
-   This is one long line cause VAXC can't handle a \-newline.  */
-#if 1 < (defined (DBX_DEBUGGING_INFO) + defined (SDB_DEBUGGING_INFO) + defined (DWARF_DEBUGGING_INFO) + defined (DWARF2_DEBUGGING_INFO) + defined (XCOFF_DEBUGGING_INFO))
-#ifndef PREFERRED_DEBUGGING_TYPE
-You Lose!  You must define PREFERRED_DEBUGGING_TYPE!
-#endif /* no PREFERRED_DEBUGGING_TYPE */
-#else /* Only one debugging format supported.  Define PREFERRED_DEBUGGING_TYPE
-        so the following code needn't care.  */
-#ifdef DBX_DEBUGGING_INFO
-#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG
-#endif
-#ifdef SDB_DEBUGGING_INFO
-#define PREFERRED_DEBUGGING_TYPE SDB_DEBUG
-#endif
-#ifdef DWARF_DEBUGGING_INFO
-#define PREFERRED_DEBUGGING_TYPE DWARF_DEBUG
-#endif
-#ifdef DWARF2_DEBUGGING_INFO
-#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
-#endif
-#ifdef XCOFF_DEBUGGING_INFO
-#define PREFERRED_DEBUGGING_TYPE XCOFF_DEBUG
-#endif
-#endif /* More than one debugger format enabled.  */
-
-/* If still not defined, must have been because no debugging formats
-   are supported.  */
-#ifndef PREFERRED_DEBUGGING_TYPE
-#define PREFERRED_DEBUGGING_TYPE NO_DEBUG
-#endif
-
-#if defined (HAVE_DECL_ENVIRON) && !HAVE_DECL_ENVIRON
-extern char **environ;
-#endif
-
 /* Carry information from ASM_DECLARE_OBJECT_NAME
    to ASM_FINISH_DECLARE_OBJECT.  */
 
 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 do_compile PARAMS ((void));
+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 set_float_handler PARAMS ((jmp_buf));
-static void compile_file PARAMS ((const char *));
+static void compile_file PARAMS ((void));
 static void display_help PARAMS ((void));
 static void display_target_options PARAMS ((void));
 
@@ -223,6 +193,11 @@ int input_file_stack_tick;
 
 const char *dump_base_name;
 
+/* Format to use to print dumpfile index value */
+#ifndef DUMPFILE_FORMAT
+#define DUMPFILE_FORMAT ".%02d."
+#endif
+
 /* Bit flags that specify the machine subtype we are compiling for.
    Bits are tested using macros TARGET_... defined in the tm.h file
    and set by `-m...' switches.  Must be defined in rtlanal.c.  */
@@ -231,7 +206,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.  */
 
@@ -265,13 +240,14 @@ enum dump_file_index
   DFI_ssa_ccp,
   DFI_ssa_dce,
   DFI_ussa,
+  DFI_null,
   DFI_cse,
   DFI_addressof,
   DFI_gcse,
   DFI_loop,
-  DFI_cse2,
   DFI_cfg,
   DFI_bp,
+  DFI_cse2,
   DFI_life,
   DFI_combine,
   DFI_ce,
@@ -297,11 +273,11 @@ enum dump_file_index
 
    Remaining -d letters:
 
-       "              o q   u     "
+       "              o q         "
        "       H JK   OPQ  TUV  YZ"
 */
 
-struct dump_file_info dump_file[DFI_MAX] =
+static struct dump_file_info dump_file[DFI_MAX] =
 {
   { "rtl",     'r', 0, 0, 0 },
   { "sibling",  'i', 0, 0, 0 },
@@ -311,13 +287,14 @@ struct dump_file_info dump_file[DFI_MAX] =
   { "ssaccp",  'W', 1, 0, 0 },
   { "ssadce",  'X', 1, 0, 0 },
   { "ussa",    'e', 1, 0, 0 }, /* Yes, duplicate enable switch.  */
+  { "null",    'u', 0, 0, 0 },
   { "cse",     's', 0, 0, 0 },
   { "addressof", 'F', 0, 0, 0 },
   { "gcse",    'G', 1, 0, 0 },
   { "loop",    'L', 1, 0, 0 },
-  { "cse2",    't', 1, 0, 0 },
   { "cfg",     'f', 1, 0, 0 },
   { "bp",      'b', 1, 0, 0 },
+  { "cse2",    't', 1, 0, 0 },
   { "life",    'f', 1, 0, 0 }, /* Yes, duplicate enable switch.  */
   { "combine", 'c', 1, 0, 0 },
   { "ce",      'C', 1, 0, 0 },
@@ -417,8 +394,6 @@ typedef rtx (*lang_expand_expr_t)
 
 lang_expand_expr_t lang_expand_expr = 0;
 
-tree (*lang_expand_constant) PARAMS ((tree)) = 0;
-
 /* Pointer to function to finish handling an incomplete decl at the
    end of compilation.  */
 
@@ -432,10 +407,6 @@ int flag_eliminate_dwarf2_dups = 0;
 
 int profile_flag = 0;
 
-/* Nonzero if generating code to do profiling on a line-by-line basis.  */
-
-int profile_block_flag;
-
 /* Nonzero if generating code to profile program flow graph arcs.  */
 
 int profile_arc_flag = 0;
@@ -455,6 +426,7 @@ int flag_reorder_blocks = 0;
 /* Nonzero if registers should be renamed.  */
 
 int flag_rename_registers = 0;
+int flag_cprop_registers = 0;
 
 /* Nonzero for -pedantic switch: warn about anything
    that standard spec forbids.  */
@@ -571,6 +543,10 @@ int flag_unroll_loops;
 
 int flag_unroll_all_loops;
 
+/* Nonzero enables prefetch optimizations for arrays in loops.  */
+
+int flag_prefetch_loop_arrays;
+
 /* Nonzero forces all invariant computations in loops to be moved
    outside the loop.  */
 
@@ -827,6 +803,9 @@ int flag_gnu_linker = 0;
 int flag_gnu_linker = 1;
 #endif
 
+/* Nonzero means put zero initialized data in the bss section.  */
+int flag_zero_initialized_in_bss = 1;
+
 /* Enable SSA.  */
 int flag_ssa = 0;
 
@@ -852,16 +831,6 @@ int flag_stack_check;
    the support provided depends on the backend.  */
 rtx stack_limit_rtx;
 
-/* -fcheck-memory-usage causes extra code to be generated in order to check
-   memory accesses.  This is used by a detector of bad memory accesses such
-   as Checker.  */
-int flag_check_memory_usage = 0;
-
-/* -fprefix-function-name causes function name to be prefixed.  This
-   can be used with -fcheck-memory-usage to isolate code compiled with
-   -fcheck-memory-usage.  */
-int flag_prefix_function_name = 0;
-
 /* 0 if pointer arguments may alias each other.  True in C.
    1 if pointer arguments may not alias each other but may alias
    global variables.
@@ -923,10 +892,13 @@ 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;
 
@@ -969,10 +941,10 @@ debug_args[] =
 
 typedef struct
 {
-  const char *string;
-  int *variable;
-  int on_value;
-  const char *description;
+  const char *const string;
+  int *const variable;
+  const int on_value;
+  const char *const description;
 }
 lang_independent_options;
 
@@ -1003,7 +975,7 @@ static const param_info lang_independent_params[] = {
     if `-fSTRING' is seen as an option.
    (If `-fno-STRING' is seen as an option, the opposite value is stored.)  */
 
-lang_independent_options f_options[] =
+static const lang_independent_options f_options[] =
 {
   {"eliminate-dwarf2-dups", &flag_eliminate_dwarf2_dups, 1,
    N_("Perform DWARF2 duplicate elimination") },
@@ -1026,15 +998,17 @@ lang_independent_options f_options[] =
   {"cse-skip-blocks", &flag_cse_skip_blocks, 1,
    N_("When running CSE, follow conditional jumps") },
   {"expensive-optimizations", &flag_expensive_optimizations, 1,
-   N_("Perform a number of minor, expensive optimisations") },
+   N_("Perform a number of minor, expensive optimizations") },
   {"thread-jumps", &flag_thread_jumps, 1,
-   N_("Perform jump threading optimisations") },
+   N_("Perform jump threading optimizations") },
   {"strength-reduce", &flag_strength_reduce, 1,
-   N_("Perform strength reduction optimisations") },
+   N_("Perform strength reduction optimizations") },
   {"unroll-loops", &flag_unroll_loops, 1,
    N_("Perform loop unrolling when iteration count is known") },
   {"unroll-all-loops", &flag_unroll_all_loops, 1,
    N_("Perform loop unrolling for all loops") },
+  {"prefetch-loop-arrays", &flag_prefetch_loop_arrays, 1,
+   N_("Generate prefetch instructions, if available, for arrays in loops") },
   {"move-all-movables", &flag_move_all_movables, 1,
    N_("Force all loop invariant computations out of loops") },
   {"reduce-all-givs", &flag_reduce_all_givs, 1,
@@ -1042,7 +1016,7 @@ lang_independent_options f_options[] =
   {"writable-strings", &flag_writable_strings, 1,
    N_("Store strings in writable data section") },
   {"peephole", &flag_no_peephole, 0,
-   N_("Enable machine specific peephole optimisations") },
+   N_("Enable machine specific peephole optimizations") },
   {"force-mem", &flag_force_mem, 1,
    N_("Copy memory operands into registers before using") },
   {"force-addr", &flag_force_addr, 1,
@@ -1076,9 +1050,9 @@ lang_independent_options f_options[] =
   {"gcse-sm", &flag_gcse_sm, 1,
    N_("Perform store motion after global subexpression elimination") },
   {"rerun-cse-after-loop", &flag_rerun_cse_after_loop, 1,
-   N_("Run CSE pass after loop optimisations") },
+   N_("Run CSE pass after loop optimizations") },
   {"rerun-loop-opt", &flag_rerun_loop_opt, 1,
-   N_("Run the loop optimiser twice") },
+   N_("Run the loop optimizer twice") },
   {"delete-null-pointer-checks", &flag_delete_null_pointer_checks, 1,
    N_("Delete useless null pointer checks") },
   {"pretend-float", &flag_pretend_float, 1,
@@ -1118,6 +1092,8 @@ lang_independent_options f_options[] =
    N_("Reorder basic blocks to improve code placement") },
   {"rename-registers", &flag_rename_registers, 1,
    N_("Do the register renaming optimization pass") },
+  {"cprop-registers", &flag_cprop_registers, 1,
+   N_("Do the register copy-propagation optimization pass") },
   {"common", &flag_no_common, 0,
    N_("Do not put uninitialized globals in the common section") },
   {"inhibit-size-directive", &flag_inhibit_size_directive, 1,
@@ -1129,9 +1105,9 @@ lang_independent_options f_options[] =
   {"verbose-asm", &flag_verbose_asm, 1,
    N_("Add extra commentry to assembler output") },
   {"gnu-linker", &flag_gnu_linker, 1,
-   N_("Output GNU ld formatted global initialisers") },
+   N_("Output GNU ld formatted global initializers") },
   {"regmove", &flag_regmove, 1,
-   N_("Enables a register move optimisation") },
+   N_("Enables a register move optimization") },
   {"optimize-register-move", &flag_regmove, 1,
    N_("Do the full regmove optimization pass") },
   {"pack-struct", &flag_pack_struct, 1,
@@ -1158,18 +1134,16 @@ lang_independent_options f_options[] =
    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,
-   N_("Add a prefix to all function names") },
   {"dump-unnumbered", &flag_dump_unnumbered, 1,
    N_("Suppress output of instruction numbers and line number notes in debugging dumps") },
   {"instrument-functions", &flag_instrument_function_entry_exit, 1,
    N_("Instrument function entry/exit with profiling calls") },
+  {"zero-initialized-in-bss", &flag_zero_initialized_in_bss, 1,
+   N_("Put zero initialized data in the bss section") },
   {"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,
@@ -1197,7 +1171,7 @@ lang_independent_options f_options[] =
   {"mem-report", &mem_report, 1,
    N_("Report on permanent memory allocation at end of run") },
   { "trapv", &flag_trapv, 1,
-   N_("Trap for signed overflow in addition / subtraction / multiplication.") },
+   N_("Trap for signed overflow in addition / subtraction / multiplication") },
 };
 
 /* Table of language-specific options.  */
@@ -1215,14 +1189,12 @@ documented_lang_options[] =
 
   { "-ansi", 
     N_("Compile just for ISO C89") },
-  { "-fallow-single-precision",
-    N_("Do not promote floats to double if using -traditional") },
   { "-std= ", 
     N_("Determine language standard") },
 
   { "-fsigned-bitfields", "" },
   { "-funsigned-bitfields",
-    N_("Make bitfields by unsigned by default") },
+    N_("Make bit-fields by unsigned by default") },
   { "-fno-signed-bitfields", "" },
   { "-fno-unsigned-bitfields","" },
   { "-fsigned-char", 
@@ -1232,18 +1204,12 @@ documented_lang_options[] =
   { "-fno-signed-char", "" },
   { "-fno-unsigned-char", "" },
 
-  { "-ftraditional", "" },
-  { "-traditional", 
-    N_("Attempt to support traditional K&R style C") },
-  { "-fnotraditional", "" },
-  { "-fno-traditional", "" },
-
   { "-fasm", "" },
   { "-fno-asm", 
-    N_("Do not recognise the 'asm' keyword") },
+    N_("Do not recognize the 'asm' keyword") },
   { "-fbuiltin", "" },
   { "-fno-builtin", 
-    N_("Do not recognise any built in functions") },
+    N_("Do not recognize any built in functions") },
   { "-fhosted", 
     N_("Assume normal C execution environment") },
   { "-fno-hosted", "" },
@@ -1326,7 +1292,7 @@ documented_lang_options[] =
     N_("Warn about suspicious declarations of main") },
   { "-Wno-main", "" },
   { "-Wmissing-braces",
-    N_("Warn about possibly missing braces around initialisers") },
+    N_("Warn about possibly missing braces around initializers") },
   { "-Wno-missing-braces", "" },
   { "-Wmissing-declarations",
     N_("Warn about global funcs without previous declarations") },
@@ -1365,7 +1331,7 @@ documented_lang_options[] =
     N_("Warn about non-prototyped function decls") },
   { "-Wno-strict-prototypes", "" },
   { "-Wtraditional", 
-    N_("Warn about constructs whose meaning change in ISO C") },
+    N_("Warn about constructs whose meanings change in ISO C") },
   { "-Wno-traditional", "" },
   { "-Wtrigraphs", 
     N_("Warn when trigraphs are encountered") },
@@ -1434,23 +1400,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;
@@ -1510,9 +1459,14 @@ int warn_disabled_optimization;
 
 int warn_missing_noreturn;
 
+/* Nonzero means warn about uses of __attribute__((deprecated)) 
+   declarations.  */
+
+int warn_deprecated_decl = 1;
+
 /* Likewise for -W.  */
 
-lang_independent_options W_options[] =
+static const lang_independent_options W_options[] =
 {
   {"unused-function", &warn_unused_function, 1,
    N_("Warn when a function is unused") },
@@ -1548,10 +1502,29 @@ lang_independent_options W_options[] =
    N_("Warn when padding is required to align struct members") },
   {"disabled-optimization", &warn_disabled_optimization, 1,
    N_("Warn when an optimization pass is disabled") },
+  {"deprecated-declarations", &warn_deprecated_decl, 1,
+   N_("Warn about uses of __attribute__((deprecated)) declarations") },
   {"missing-noreturn", &warn_missing_noreturn, 1,
    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.  */
 
@@ -1603,7 +1576,7 @@ read_integral_parameter (p, pname, defval)
   if (*endp != 0)
     {
       if (pname != 0)
-       error ("Invalid option `%s'", pname);
+       error ("invalid option `%s'", pname);
       return defval;
     }
 
@@ -1723,8 +1696,8 @@ set_float_handler (handler)
 
 int
 do_float_handler (fn, data)
-  void (*fn) PARAMS ((PTR));
-  PTR data;
+     void (*fn) PARAMS ((PTR));
+     PTR data;
 {
   jmp_buf buf;
 
@@ -1749,7 +1722,7 @@ static void
 crash_signal (signo)
      int signo;
 {
-  internal_error ("Internal error: %s", strsignal (signo));
+  internal_error ("internal error: %s", strsignal (signo));
 }
 
 /* Strip off a legitimate source ending from the input string NAME of
@@ -1788,9 +1761,14 @@ output_quoted_string (asm_file, string)
   putc ('\"', asm_file);
   while ((c = *string++) != 0)
     {
-      if (c == '\"' || c == '\\')
-       putc ('\\', asm_file);
-      putc (c, asm_file);
+      if (ISPRINT (c))
+       {
+         if (c == '\"' || c == '\\')
+           putc ('\\', asm_file);
+         putc (c, asm_file);
+       }
+      else
+       fprintf (asm_file, "\\%03o", c);
     }
   putc ('\"', asm_file);
 #endif
@@ -1845,7 +1823,7 @@ open_dump_file (index, decl)
   if (rtl_dump_file != NULL)
     fclose (rtl_dump_file);
 
-  sprintf (seq, ".%02d.", index);
+  sprintf (seq, DUMPFILE_FORMAT, index);
 
   if (! dump_file[index].initialized)
     {
@@ -1899,7 +1877,7 @@ close_dump_file (index, func, insns)
       char seq[16];
       char *suffix;
 
-      sprintf (seq, ".%02d.", index);
+      sprintf (seq, DUMPFILE_FORMAT, index);
       suffix = concat (seq, dump_file[index].extension, NULL);
       print_rtl_graph_with_bb (dump_base_name, suffix, insns);
       free (suffix);
@@ -2128,203 +2106,14 @@ pop_srcloc ()
   lineno = input_file_stack->line;
 }
 
-/* Compile an entire translation unit, whose primary source file is
-   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 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.  */
-
-  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.  */
-  (*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
-
-  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
-
-  /* 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);
@@ -2346,7 +2135,7 @@ compile_file (name)
   timevar_pop (TV_PARSE);
 
   if (flag_syntax_only)
-    goto finish_syntax;
+    return;
 
   globals = getdecls ();
 
@@ -2428,19 +2217,6 @@ compile_file (name)
             IDENT_ASM_OP, version_string);
 #endif
 
-  /* Language-specific end of compilation actions.  */
- finish_syntax:
-  (*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);
@@ -2448,66 +2224,20 @@ 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);
-
-  /* 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 ();
-      dump_tree_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.  */
+   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)
@@ -2601,7 +2331,9 @@ rest_of_type_compilation (type, toplev)
     sdbout_symbol (TYPE_STUB_DECL (type), !toplev);
 #endif
 #ifdef DWARF2_DEBUGGING_INFO
-  if (write_symbols == DWARF2_DEBUG && toplev)
+  if ((write_symbols == DWARF2_DEBUG
+       || write_symbols == VMS_AND_DWARF2_DEBUG)
+      && toplev)
     dwarf2out_decl (TYPE_STUB_DECL (type));
 #endif
   timevar_pop (TV_SYMOUT);
@@ -2638,11 +2370,6 @@ rest_of_compilation (decl)
   if (!cfun->x_whole_function_mode_p)
     identify_blocks ();
 
-  /* Then remove any notes we don't need.  That will make iterating
-     over the instruction sequence faster, and allow the garbage
-     collector to reclaim the memory used by the notes.  */
-  remove_unnecessary_notes ();
-
   /* In function-at-a-time mode, we do not attempt to keep the BLOCK
      tree in sensible shape.  So, we just recalculate it here.  */
   if (cfun->x_whole_function_mode_p)
@@ -2780,6 +2507,29 @@ rest_of_compilation (decl)
        goto exit_rest_of_compilation;
     }
 
+  /* If we're emitting a nested function, make sure its parent gets
+     emitted as well.  Doing otherwise confuses debug info.  */
+  {
+    tree parent;
+    for (parent = DECL_CONTEXT (current_function_decl);
+        parent != NULL_TREE;
+        parent = get_containing_scope (parent))
+      if (TREE_CODE (parent) == FUNCTION_DECL)
+       TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (parent)) = 1;
+  }
+
+  /* We are now committed to emitting code for this function.  Do any
+     preparation, such as emitting abstract debug info for the inline
+     before it gets mangled by optimization.  */
+  if (DECL_INLINE (decl))
+    (*debug_hooks->outlining_inline_function) (decl);
+
+  /* Remove any notes we don't need.  That will make iterating
+     over the instruction sequence faster, and allow the garbage
+     collector to reclaim the memory used by the notes.  */
+  remove_unnecessary_notes ();
+  reorder_blocks ();
+
   ggc_collect ();
 
   /* Initialize some variables used by the optimizers.  */
@@ -2865,6 +2615,8 @@ rest_of_compilation (decl)
   reg_scan (insns, max_reg_num (), 0);
   rebuild_jump_labels (insns);
   find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
+  if (rtl_dump_file)
+    dump_flow_info (rtl_dump_file);
   cleanup_cfg ((optimize ? CLEANUP_EXPENSIVE : 0) | CLEANUP_PRE_LOOP);
 
   /* CFG is no longer maintained up-to-date.  */
@@ -2873,11 +2625,11 @@ rest_of_compilation (decl)
   purge_line_number_notes (insns);
 
   timevar_pop (TV_JUMP);
+  close_dump_file (DFI_jump, print_rtl, insns);
 
   /* Now is when we stop if -fsyntax-only and -Wreturn-type.  */
   if (rtl_dump_and_exit || flag_syntax_only || DECL_DEFER_OUTPUT (decl))
     {
-      close_dump_file (DFI_jump, print_rtl, insns);
       goto exit_rest_of_compilation;
     }
 
@@ -2954,22 +2706,22 @@ rest_of_compilation (decl)
 
   if (optimize > 0)
     {
+      open_dump_file (DFI_null, decl);
       find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
-      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
-        be changed -- no since converting if's that are going to
-        be deleted.  */
-      timevar_push (TV_IFCVT);
-      if_convert (0);
-      timevar_pop (TV_IFCVT);
+      if (rtl_dump_file)
+       dump_flow_info (rtl_dump_file);
+      cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP
+                  | (flag_thread_jumps ? CLEANUP_THREADING : 0));
 
-      /* 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);
+
+      timevar_push (TV_IFCVT);
+      if_convert (0);
+      timevar_pop (TV_IFCVT);
+      cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP);
+      close_dump_file (DFI_null, print_rtl_with_bb, insns);
     }
 
   /* Jump optimization, and the removal of NULL pointer checks, may
@@ -2978,9 +2730,11 @@ rest_of_compilation (decl)
      maximum instruction UID, so if we can reduce the maximum UID
      we'll save big on memory.  */
   renumber_insns (rtl_dump_file);
+  if (optimize)
+    compute_bb_for_insn (get_max_uid ());
   timevar_pop (TV_JUMP);
 
-  close_dump_file (DFI_jump, print_rtl, insns);
+  close_dump_file (DFI_jump, print_rtl_with_bb, insns);
 
   ggc_collect ();
 
@@ -2992,63 +2746,56 @@ rest_of_compilation (decl)
   if (optimize > 0)
     {
       open_dump_file (DFI_cse, decl);
+      if (rtl_dump_file)
+       dump_flow_info (rtl_dump_file);
       timevar_push (TV_CSE);
 
       reg_scan (insns, max_reg_num (), 1);
 
-      if (flag_thread_jumps)
-       {
-         timevar_push (TV_JUMP);
-         thread_jumps (insns, max_reg_num (), 1);
-         timevar_pop (TV_JUMP);
-       }
-
       tem = cse_main (insns, max_reg_num (), 0, rtl_dump_file);
+      if (tem)
+       rebuild_jump_labels (insns);
+      purge_all_dead_edges (0);
 
       /* If we are not running more CSE passes, then we are no longer
         expecting CSE to be run.  But always rerun it in a cheap mode.  */
       cse_not_expected = !flag_rerun_cse_after_loop && !flag_gcse;
 
       if (tem || optimize > 1)
-       {
-         timevar_push (TV_JUMP);
-         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 ();
-       }
+       cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP);
 
       /* Run this after jump optmizations remove all the unreachable code
         so that unreachable code will not keep values live.  */
-      delete_trivially_dead_insns (insns, max_reg_num (), 0);
+      delete_trivially_dead_insns (insns, max_reg_num (), 1);
 
       /* Try to identify useless null pointer tests and delete them.  */
-      if (flag_delete_null_pointer_checks)
+      if (flag_delete_null_pointer_checks || flag_thread_jumps)
        {
          timevar_push (TV_JUMP);
-         find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
 
-         cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP);
+         cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP
+                      | (flag_thread_jumps ? CLEANUP_THREADING : 0));
 
-         delete_null_pointer_checks (insns);
+         if (flag_delete_null_pointer_checks)
+           delete_null_pointer_checks (insns);
          /* CFG is no longer maintained up-to-date.  */
-         free_bb_for_insn ();
          timevar_pop (TV_JUMP);
        }
 
       /* The second pass of jump optimization is likely to have
          removed a bunch more instructions.  */
       renumber_insns (rtl_dump_file);
+      compute_bb_for_insn (get_max_uid ());
 
       timevar_pop (TV_CSE);
-      close_dump_file (DFI_cse, print_rtl, insns);
+      close_dump_file (DFI_cse, print_rtl_with_bb, insns);
     }
 
   open_dump_file (DFI_addressof, decl);
 
   purge_addressof (insns);
+  if (optimize)
+    purge_all_dead_edges (0);
   reg_scan (insns, max_reg_num (), 1);
 
   close_dump_file (DFI_addressof, print_rtl, insns);
@@ -3065,16 +2812,14 @@ rest_of_compilation (decl)
       timevar_push (TV_GCSE);
       open_dump_file (DFI_gcse, decl);
 
-      find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
       cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP);
       tem = gcse_main (insns, rtl_dump_file);
+      rebuild_jump_labels (insns);
 
       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)
@@ -3082,6 +2827,7 @@ rest_of_compilation (decl)
          timevar_push (TV_CSE);
          reg_scan (insns, max_reg_num (), 1);
          tem2 = cse_main (insns, max_reg_num (), 0, rtl_dump_file);
+         purge_all_dead_edges (0);
          timevar_pop (TV_CSE);
          cse_not_expected = !flag_rerun_cse_after_loop;
        }
@@ -3093,11 +2839,8 @@ rest_of_compilation (decl)
          tem = tem2 = 0;
          timevar_push (TV_JUMP);
          rebuild_jump_labels (insns);
-         delete_trivially_dead_insns (insns, max_reg_num (), 0);
-         find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
+         delete_trivially_dead_insns (insns, max_reg_num (), 1);
          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)
@@ -3105,24 +2848,30 @@ rest_of_compilation (decl)
              timevar_push (TV_CSE);
              reg_scan (insns, max_reg_num (), 1);
              tem2 = cse_main (insns, max_reg_num (), 0, rtl_dump_file);
+             purge_all_dead_edges (0);
              timevar_pop (TV_CSE);
            }
        }
 
-      close_dump_file (DFI_gcse, print_rtl, insns);
+      close_dump_file (DFI_gcse, print_rtl_with_bb, insns);
       timevar_pop (TV_GCSE);
 
       ggc_collect ();
       flag_cse_skip_blocks = save_csb;
       flag_cse_follow_jumps = save_cfj;
-     }
+#ifdef ENABLE_CHECKING
+      verify_flow_info ();
+#endif
+    }
 
   /* Move constant computations out of loops.  */
 
   if (optimize > 0)
     {
       timevar_push (TV_LOOP);
+      delete_dead_jumptables ();
       open_dump_file (DFI_loop, decl);
+      /* CFG is no longer maintained up-to-date.  */
       free_bb_for_insn ();
 
       if (flag_rerun_loop_opt)
@@ -3145,74 +2894,101 @@ rest_of_compilation (decl)
        }
       cleanup_barriers ();
       loop_optimize (insns, rtl_dump_file,
-                    (flag_unroll_loops ? LOOP_UNROLL : 0) | LOOP_BCT);
+                    (flag_unroll_loops ? LOOP_UNROLL : 0) | LOOP_BCT
+                    | (flag_prefetch_loop_arrays ? LOOP_PREFETCH : 0));
 
+      /* Loop can create trivially dead instructions.  */
+      delete_trivially_dead_insns (insns, max_reg_num (), 0);
       close_dump_file (DFI_loop, print_rtl, insns);
       timevar_pop (TV_LOOP);
 
       ggc_collect ();
     }
 
+  /* Do control and data flow analysis; wrote some of the results to
+     the dump file.  */
+
+  timevar_push (TV_FLOW);
+  open_dump_file (DFI_cfg, decl);
+
+  find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
+  if (rtl_dump_file)
+    dump_flow_info (rtl_dump_file);
+  cleanup_cfg ((optimize ? CLEANUP_EXPENSIVE : 0)
+              | (flag_thread_jumps ? CLEANUP_THREADING : 0));
+
+  /* It may make more sense to mark constant functions after dead code is
+     eliminated by life_analyzis, but we need to do it early, as -fprofile-arcs
+     may insert code making function non-constant, but we still must consider
+     it as constant, otherwise -fbranch-probabilities will not read data back.
+
+     life_analyzis rarely eliminates modification of external memory.
+   */
+  mark_constant_function ();
+
+  close_dump_file (DFI_cfg, print_rtl_with_bb, insns);
+
+  /* Do branch profiling and static profile estimation passes.  */
+  if (optimize > 0 || profile_arc_flag || flag_test_coverage
+      || flag_branch_probabilities)
+    {
+      struct loops loops;
+
+      timevar_push (TV_BRANCH_PROB);
+      open_dump_file (DFI_bp, decl);
+      if (profile_arc_flag || flag_test_coverage || flag_branch_probabilities)
+       branch_prob ();
+
+      /* Discover and record the loop depth at the head of each basic
+        block.  The loop infrastructure does the real job for us.  */
+      flow_loops_find (&loops, LOOP_TREE);
+
+      /* Estimate using heuristics if no profiling info is available.  */
+      if (flag_guess_branch_prob)
+       estimate_probability (&loops);
+
+      if (rtl_dump_file)
+       flow_loops_dump (&loops, rtl_dump_file, NULL, 0);
+
+      flow_loops_free (&loops);
+      close_dump_file (DFI_bp, print_rtl_with_bb, insns);
+      timevar_pop (TV_BRANCH_PROB);
+    }
+
   if (optimize > 0)
     {
       timevar_push (TV_CSE2);
       open_dump_file (DFI_cse2, decl);
+      if (rtl_dump_file)
+       dump_flow_info (rtl_dump_file);
 
       if (flag_rerun_cse_after_loop)
        {
-         /* Running another jump optimization pass before the second
-            cse pass sometimes simplifies the RTL enough to allow
-            the second CSE pass to do a better job.  Jump_optimize can change
-            max_reg_num so we must rerun reg_scan afterwards.
-            ??? Rework to not call reg_scan so often.  */
          timevar_push (TV_JUMP);
 
-         /* The previous call to loop_optimize makes some instructions
-            trivially dead.  We delete those instructions now in the
-            hope that doing so will make the heuristics in jump work
-            better and possibly speed up compilation.  */
-         delete_trivially_dead_insns (insns, max_reg_num (), 0);
-
          reg_scan (insns, max_reg_num (), 0);
 
          timevar_push (TV_IFCVT);
-
-         find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
          cleanup_cfg (CLEANUP_EXPENSIVE);
          if_convert (0);
-
          timevar_pop(TV_IFCVT);
 
          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);
+         purge_all_dead_edges (0);
 
          if (tem)
            {
              timevar_push (TV_JUMP);
              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);
            }
        }
 
-      if (flag_thread_jumps)
-       {
-         /* This pass of jump threading straightens out code
-            that was kinked by loop optimization.  */
-         timevar_push (TV_JUMP);
-         reg_scan (insns, max_reg_num (), 0);
-         thread_jumps (insns, max_reg_num (), 0);
-         timevar_pop (TV_JUMP);
-       }
-
-      close_dump_file (DFI_cse2, print_rtl, insns);
+      close_dump_file (DFI_cse2, print_rtl_with_bb, insns);
       timevar_pop (TV_CSE2);
 
       ggc_collect ();
@@ -3220,59 +2996,17 @@ rest_of_compilation (decl)
 
   cse_not_expected = 1;
 
+  close_dump_file (DFI_life, print_rtl_with_bb, insns);
   regclass_init ();
 
-  /* Do control and data flow analysis; wrote some of the results to
-     the dump file.  */
-
-  timevar_push (TV_FLOW);
-  open_dump_file (DFI_cfg, decl);
-
-  find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
-  cleanup_cfg (optimize ? CLEANUP_EXPENSIVE : 0);
   check_function_return_warnings ();
 
-  /* It may make more sense to mark constant functions after dead code is
-     eliminated by life_analyzis, but we need to do it early, as -fprofile-arcs
-     may insert code making function non-constant, but we still must consider
-     it as constant, otherwise -fbranch-probabilities will not read data back.
-
-     life_analyzis rarely eliminates modification of external memory.
-   */
-  mark_constant_function ();
-
-  close_dump_file (DFI_cfg, print_rtl_with_bb, insns);
-
-  if (profile_arc_flag || flag_test_coverage || flag_branch_probabilities)
-    {
-      timevar_push (TV_BRANCH_PROB);
-      open_dump_file (DFI_bp, decl);
-
-      branch_prob ();
-
-      close_dump_file (DFI_bp, print_rtl_with_bb, insns);
-      timevar_pop (TV_BRANCH_PROB);
-    }
-
-  open_dump_file (DFI_life, decl);
-  if (optimize)
-    {
-      struct loops loops;
-
-      /* Discover and record the loop depth at the head of each basic
-        block.  The loop infrastructure does the real job for us.  */
-      flow_loops_find (&loops, LOOP_TREE);
-
-      /* Estimate using heuristics if no profiling info is available.  */
-      if (flag_guess_branch_prob)
-       estimate_probability (&loops);
-
-      if (rtl_dump_file)
-       flow_loops_dump (&loops, rtl_dump_file, NULL, 0);
-
-      flow_loops_free (&loops);
-    }
+#ifdef ENABLE_CHECKING
+  verify_flow_info ();
+#endif
   life_analysis (insns, rtl_dump_file, PROP_FINAL);
+  if (optimize)
+    cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_UPDATE_LIFE);
   timevar_pop (TV_FLOW);
 
   no_new_pseudos = 1;
@@ -3284,6 +3018,19 @@ rest_of_compilation (decl)
        setjmp_args_warning ();
     }
 
+  if (optimize)
+    {
+      clear_bb_flags ();
+      if (initialize_uninitialized_subregs ())
+       {
+         /* Insns were inserted, so things might look a bit different.  */
+         insns = get_insns ();
+         update_life_info_in_dirty_blocks (UPDATE_LIFE_GLOBAL_RM_NOTES,
+                                           PROP_LOG_LINKS | PROP_REG_INFO
+                                           | PROP_DEATH_NOTES);
+       }
+    }
+
   close_dump_file (DFI_life, print_rtl_with_bb, insns);
 
   ggc_collect ();
@@ -3346,6 +3093,7 @@ rest_of_compilation (decl)
 
       regmove_optimize (insns, max_reg_num (), rtl_dump_file);
 
+      cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_UPDATE_LIFE);
       close_dump_file (DFI_regmove, print_rtl_with_bb, insns);
       timevar_pop (TV_REGMOVE);
 
@@ -3364,13 +3112,7 @@ rest_of_compilation (decl)
   timevar_push (TV_MODE_SWITCH);
 
   no_new_pseudos = 0;
-  if (optimize_mode_switching (NULL))
-    {
-      /* We did work, and so had to regenerate global life information.
-        Take advantage of this and don't re-recompute register life
-        information below.  */
-      register_life_up_to_date = 1;
-    }
+  optimize_mode_switching (NULL);
   no_new_pseudos = 1;
 
   timevar_pop (TV_MODE_SWITCH);
@@ -3554,12 +3296,15 @@ rest_of_compilation (decl)
     }
 #endif
 
-  if (optimize > 0 && flag_rename_registers)
+  if (flag_rename_registers || flag_cprop_registers)
     {
       timevar_push (TV_RENAME_REGISTERS);
       open_dump_file (DFI_rnreg, decl);
 
-      regrename_optimize ();
+      if (flag_rename_registers)
+        regrename_optimize ();
+      if (flag_cprop_registers)
+        copyprop_hardreg_forward ();
 
       close_dump_file (DFI_rnreg, print_rtl_with_bb, insns);
       timevar_pop (TV_RENAME_REGISTERS);
@@ -3783,6 +3528,7 @@ rest_of_compilation (decl)
   init_temp_slots ();
 
   free_basic_block_vars (0);
+  free_bb_for_insn ();
 
   timevar_pop (TV_FINAL);
 
@@ -3837,8 +3583,8 @@ display_help ()
                f_options[i].string, _(description));
     }
 
-  printf (_("  -O[number]              Set optimisation level to [number]\n"));
-  printf (_("  -Os                     Optimise for space rather than speed\n"));
+  printf (_("  -O[number]              Set optimization level to [number]\n"));
+  printf (_("  -Os                     Optimize for space rather than speed\n"));
   for (i = LAST_PARAM; i--;)
     {
       const char *description = compiler_params[i].help;
@@ -3951,7 +3697,13 @@ display_help ()
 static void
 display_target_options ()
 {
-  int undoc,i;
+  int undoc, i;
+  static bool displayed = false;
+
+  /* Avoid double printing for --help --target-help.  */
+  if (displayed)
+    return;
+  displayed = true;
 
   if (ARRAY_SIZE (target_switches) > 1
 #ifdef TARGET_OPTIONS
@@ -4044,7 +3796,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':
@@ -4094,9 +3846,9 @@ decode_f_option (arg)
     }
 
   if (!strcmp (arg, "fast-math"))
-    set_fast_math_flags();
+    set_fast_math_flags ();
   else if (!strcmp (arg, "no-fast-math"))
-    set_no_fast_math_flags();
+    set_no_fast_math_flags ();
   else if ((option_value = skip_leading_substring (arg, "inline-limit-"))
           || (option_value = skip_leading_substring (arg, "inline-limit=")))
     {
@@ -4155,7 +3907,7 @@ decode_f_option (arg)
         diagnostic_prefixing_rule (global_dc)
           = DIAGNOSTICS_SHOW_PREFIX_EVERY_LINE;
       else
-       error ("Unrecognized option `%s'", arg - 2);
+       error ("unrecognized option `%s'", arg - 2);
     }
   else if (!strcmp (arg, "no-stack-limit"))
     stack_limit_rtx = NULL_RTX;
@@ -4242,7 +3994,7 @@ decode_g_option (arg)
   /* Indexed by enum debug_info_type.  */
   static const char *const debug_type_names[] =
   {
-    "none", "stabs", "coff", "dwarf-1", "dwarf-2", "xcoff"
+    "none", "stabs", "coff", "dwarf-1", "dwarf-2", "xcoff", "vms"
   };
 
   /* The maximum admissible debug level value.  */
@@ -4502,24 +4254,7 @@ independent_decode_option (argc, argv)
       break;
 
     case 'a':
-      if (arg[1] == 0)
-       {
-#if !defined (BLOCK_PROFILER) || !defined (FUNCTION_BLOCK_PROFILER)
-         warning ("`-a' option (basic block profile) not supported");
-#else
-         profile_block_flag = (profile_block_flag < 2) ? 1 : 3;
-#endif
-       }
-      else if (!strcmp (arg, "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 (!strncmp (arg, "aux-info", 8))
+      if (!strncmp (arg, "aux-info", 8))
        {
          if (arg[8] == '\0')
            {
@@ -4587,28 +4322,242 @@ 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;
 {
-  int i;
-  char *p;
-
-  /* save in case md file wants to emit args as a comment.  */
-  save_argc = argc;
-  save_argv = argv;
+  size_t j;
+  int valid_target_option = 0;
 
-  p = argv[0] + strlen (argv[0]);
-  while (p != argv[0] && !IS_DIR_SEPARATOR (p[-1]))
-    --p;
+  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 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
+
+  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).  */
+
+static void
+print_version (file, indent)
+     FILE *file;
+     const char *indent;
+{
+#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 ? " " : "",
+          lang_hooks.name, 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.  */
+
+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);
+
+  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;
+}
+
+/* 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 (file, pos, max, indent, sep, term)
+     FILE *file;
+     int pos, max;
+     const char *indent, *sep, *term;
+{
+  size_t j;
+  char **p;
+
+  /* Print the options as passed.  */
+
+  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);
@@ -4636,30 +4585,33 @@ toplev_main (argc, argv)
   signal (SIGIOT, crash_signal);
 #endif
 
-  decl_printable_name = decl_name;
-  lang_expand_expr = (lang_expand_expr_t) do_abort;
-
-  /* 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 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 initialization.  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;
 
-  /* 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);
+  /* Save in case md file wants to emit args as a comment.  */
+  save_argc = argc;
+  save_argv = argv;
 
-  /* Initialize the diagnostics reporting machinery.  */
-  diagnostic_initialize (global_dc);
+  /* 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 intialization.  */
+  /* Perform language-specific options initialization.  */
   (*lang_hooks.init_options) ();
 
   /* Scan to see what optimization level has been specified.  That will
@@ -4711,6 +4663,7 @@ toplev_main (argc, argv)
       flag_omit_frame_pointer = 1;
 #endif
       flag_guess_branch_prob = 1;
+      flag_cprop_registers = 1;
     }
 
   if (optimize >= 2)
@@ -4750,6 +4703,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;
@@ -4766,9 +4726,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;)
     {
@@ -4818,32 +4775,27 @@ toplev_main (argc, argv)
            {
              if (extra_warnings)
                {
-                 warning ("Ignoring command line option '%s'", argv[i]);
+                 warning ("ignoring command line option '%s'", argv[i]);
                  if (lang)
                    warning
-                     ("(It is valid for %s but not the selected language)",
+                     ("(it is valid for %s but not the selected language)",
                       lang);
                }
            }
          else if (argv[i][0] == '-' && argv[i][1] == 'g')
            warning ("`%s': unknown or unsupported -g option", &argv[i][2]);
          else
-           error ("Unrecognized option `%s'", argv[i]);
+           error ("unrecognized option `%s'", argv[i]);
 
          i++;
        }
     }
 
-  /* All command line options have been processed.  */
-  (*lang_hooks.post_options) ();
-
-  if (exit_after_options)
-    exit (0);
-
-  /* Checker uses the frame pointer.  */
-  if (flag_check_memory_usage)
-    flag_omit_frame_pointer = 0;
-
+  /* Set flag_no_inline before the post_options () hook.  The C front
+     ends use it to determine tree inlining defaults.  FIXME: such
+     code should be lang-independent when all front ends use tree
+     inlining, in which case it, and this condition, should be moved
+     to the top of process_options() instead.  */
   if (optimize == 0)
     {
       /* Inlining does not work if not optimizing,
@@ -4858,34 +4810,37 @@ toplev_main (argc, argv)
        warning ("-Wuninitialized is not supported without -O");
     }
 
-  /* We do not currently support sibling-call optimization in the
-     presence of exceptions.  See PR2975 for a test-case that will
-     fail if we try to combine both of these features.  */
-  if (flag_exceptions)
-    flag_optimize_sibling_calls = 0;
-
-#ifdef OVERRIDE_OPTIONS
-  /* Some machines may reject certain combinations of options.  */
-  OVERRIDE_OPTIONS;
-#endif
+  /* All command line options have been parsed; allow the front end to
+     perform consistency checks, etc.  */
+  (*lang_hooks.post_options) ();
+}
+\f
+/* Process the options that have been parsed.  */
+static void
+process_options ()
+{
+#ifdef OVERRIDE_OPTIONS
+  /* Some machines may reject certain combinations of options.  */
+  OVERRIDE_OPTIONS;
+#endif
 
   /* 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);
 
-  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)
@@ -4949,180 +4904,308 @@ 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;
+    }
+
+  /* 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
+#ifdef VMS_DEBUGGING_INFO
+  if (write_symbols == VMS_DEBUG || write_symbols == VMS_AND_DWARF2_DEBUG)
+    debug_hooks = &vmsdbg_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)
+    {
+      warning ("-ffunction-sections disabled; it makes profiling impossible");
+      flag_function_sections = 0;
+    }
+
+#ifndef HAVE_prefetch
+  if (flag_prefetch_loop_arrays)
+    {
+      warning ("-fprefetch-loop-arrays not supported for this target");
+      flag_prefetch_loop_arrays = 0;
+    }
+#else
+  if (flag_prefetch_loop_arrays && !HAVE_prefetch)
+    {
+      warning ("-fprefetch-loop-arrays not supported for this target (try -march switches)");
+      flag_prefetch_loop_arrays = 0;
+    }
+#endif
+
+  /* This combination of options isn't handled for i386 targets and doesn't
+     make much sense anyway, so don't allow it.  */
+  if (flag_prefetch_loop_arrays && optimize_size)
+    {
+      warning ("-fprefetch-loop-arrays is not supported with -Os");
+      flag_prefetch_loop_arrays = 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 identifier size.  */
+  tree_code_length[(int) IDENTIFIER_NODE]
+    = ((lang_hooks.identifier_size - sizeof (struct tree_common)
+       + sizeof (tree) - 1) / sizeof (tree));
+
+  /* Initialize the garbage-collector, and string pools.  */
+  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
+#ifdef VMS_DEBUGGING_INFO
+                   /* Enable line number info for traceback */
+                   || debug_info_level > DINFO_LEVEL_NONE
+#endif
+                   || 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;
 {
-  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__);
-}
+  /* Close the dump files.  */
+  if (flag_gen_aux_info)
+    {
+      fclose (aux_info_file);
+      if (errorcount)
+       unlink (aux_info_file_name);
+    }
 
-/* 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 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.  */
 
-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);
+  if (asm_out_file)
+    {
+      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
-      && pos + len > max)
+  /* Do whatever is necessary to finish printing the graphs.  */
+  if (graph_dump_format != no_graph)
     {
-      fprintf (file, "%s", term);
-      pos = 0;
+      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, DUMPFILE_FORMAT, i);
+           suffix = concat (seq, dump_file[i].extension, NULL);
+           finish_graph_dump_file (dump_base_name, suffix);
+           free (suffix);
+         }
     }
-  if (pos == 0)
+
+  if (mem_report)
     {
-      fprintf (file, "%s", indent);
-      pos = strlen (indent);
+      ggc_print_statistics ();
+      stringpool_statistics ();
+      dump_tree_statistics ();
     }
-  fprintf (file, "%s%s%s", sep, type, name);
-  pos += len;
-  return pos;
-}
 
-/* 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.  */
+  /* Free up memory for the benefit of leak detectors.  */
+  free_reg_info ();
 
+  /* Language-specific end of compilation actions.  */
+  (*lang_hooks.finish) ();
+}
+\f
+/* Initialize the compiler, and compile the input file.  */
 static void
-print_switch_values (file, pos, max, indent, sep, term)
-     FILE *file;
-     int pos, max;
-     const char *indent, *sep, *term;
+do_compile ()
 {
-  size_t j;
-  char **p;
+  /* The bulk of command line switch processing.  */
+  process_options ();
 
-  /* Print the options as passed.  */
+  /* We cannot start timing until after options are processed since that
+     says if we run timers or not.  */
+  init_timevar ();
+  timevar_start (TV_TOTAL);
 
-  pos = print_single_switch (file, pos, max, indent, *indent ? " " : "", term,
-                            _("options passed: "), "");
+  /* Language-independent initialization.  Also sets up GC, identifier
+     hashes etc.  */
+  lang_independent_init ();
 
-  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-dependent initialization.  Returns true on success.  */
+  if (lang_dependent_init (filename))
+    compile_file ();
 
-       pos = print_single_switch (file, pos, max, indent, sep, term, *p, "");
-      }
-  if (pos > 0)
-    fprintf (file, "%s", term);
+  finalize ();
 
-  /* Print the -f and -m options that have been enabled.
-     We don't handle language specific options but printing argv
-     should suffice.  */
+  /* Stop timing and print the times.  */
+  timevar_stop (TV_TOTAL);
+  timevar_print (stderr);
+}
+\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, 0, max, indent, *indent ? " " : "", term,
-                            _("options enabled: "), "");
+   It is not safe to call this function more than once.  */
 
-  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);
+int
+toplev_main (argc, argv)
+     int argc;
+     char **argv;
+{
+  hex_init ();
 
-  /* Print target specific options.  */
+  /* Initialization of GCC's environment, and diagnostics.  */
+  general_init (argv [0]);
 
-  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);
-      }
+  /* Parse the options and do minimal processing; basically just
+     enough to default flags appropriately.  */
+  parse_options_and_default_flags (argc, argv);
 
-#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
+  /* Exit early if we can (e.g. -help).  */
+  if (!exit_after_options)
+    do_compile ();
 
-  fprintf (file, "%s", term);
+  if (errorcount || sorrycount)
+    return (FATAL_EXIT_CODE);
+
+  return (SUCCESS_EXIT_CODE);
 }