OSDN Git Service

Daily bump.
[pf3gnuchains/gcc-fork.git] / gcc / toplev.c
index 2cef957..6bf1736 100644 (file)
@@ -1,7 +1,7 @@
 /* Top level of GCC compilers (cc1, cc1plus, etc.)
    Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
-   Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
+   2011 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -62,6 +62,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "integrate.h"
 #include "debug.h"
 #include "target.h"
+#include "common/common-target.h"
 #include "langhooks.h"
 #include "cfglayout.h"
 #include "cfgloop.h"
@@ -124,13 +125,6 @@ unsigned int save_decoded_options_count;
 
 const struct gcc_debug_hooks *debug_hooks;
 
-/* True if this is the lto front end.  This is used to disable
-   gimple generation and lowering passes that are normally run on the
-   output of a front end.  These passes must be bypassed for lto since
-   they have already been done before the gimple was written.  */
-
-bool in_lto_p = false;
-
 /* The FUNCTION_DECL for the function currently being compiled,
    or 0 if between functions.  */
 tree current_function_decl;
@@ -147,15 +141,10 @@ static const char *flag_random_seed;
    user has specified a particular random seed.  */
 unsigned local_tick;
 
-/* -f flags.  */
-
-/* Generate code for GNU or NeXT Objective-C runtime environment.  */
+/* Random number for this compilation */
+HOST_WIDE_INT random_seed;
 
-#ifdef NEXT_OBJC_RUNTIME
-int flag_next_runtime = 1;
-#else
-int flag_next_runtime = 0;
-#endif
+/* -f flags.  */
 
 /* Nonzero means make permerror produce warnings instead of errors.  */
 
@@ -170,9 +159,6 @@ int flag_permissive = 0;
    the support provided depends on the backend.  */
 rtx stack_limit_rtx;
 
-/* Type of stack check.  */
-enum stack_check_type flag_stack_check = NO_STACK_CHECK;
-
 /* True if the user has tagged the function with the 'section'
    attribute.  */
 
@@ -185,25 +171,9 @@ struct target_flag_state *this_target_flag_state = &default_target_flag_state;
 #define this_target_flag_state (&default_target_flag_state)
 #endif
 
-typedef struct
-{
-  const char *const string;
-  int *const variable;
-  const int on_value;
-}
-lang_independent_options;
-
 /* The user symbol prefix after having resolved same.  */
 const char *user_label_prefix;
 
-static const param_info lang_independent_params[] = {
-#define DEFPARAM(ENUM, OPTION, HELP, DEFAULT, MIN, MAX) \
-  { OPTION, DEFAULT, MIN, MAX, HELP },
-#include "params.def"
-#undef DEFPARAM
-  { NULL, 0, 0, 0, NULL }
-};
-
 /* Output files for assembler code (real compiler output)
    and debugging dumps.  */
 
@@ -276,7 +246,7 @@ announce_function (tree decl)
     }
 }
 
-/* Initialize local_tick with the time of day, or -1 if
+/* Initialize local_tick with a random number or -1 if
    flag_random_seed is set.  */
 
 static void
@@ -284,7 +254,17 @@ init_local_tick (void)
 {
   if (!flag_random_seed)
     {
-      /* Get some more or less random data.  */
+      /* Try urandom first. Time of day is too likely to collide. 
+        In case of any error we just use the local tick. */
+
+      int fd = open ("/dev/urandom", O_RDONLY);
+      if (fd >= 0)
+        {
+          read (fd, &random_seed, sizeof (random_seed));
+          close (fd);
+        }
+
+      /* Now get the tick anyways  */
 #ifdef HAVE_GETTIMEOFDAY
       {
        struct timeval tv;
@@ -311,24 +291,28 @@ init_local_tick (void)
 static void
 init_random_seed (void)
 {
-  unsigned HOST_WIDE_INT value;
-  static char random_seed[HOST_BITS_PER_WIDE_INT / 4 + 3];
-
-  value = local_tick ^ getpid ();
+  if (flag_random_seed)
+    {
+      char *endp;
 
-  sprintf (random_seed, HOST_WIDE_INT_PRINT_HEX, value);
-  flag_random_seed = random_seed;
+      /* When the driver passed in a hex number don't crc it again */
+      random_seed = strtoul (flag_random_seed, &endp, 0);
+      if (!(endp > flag_random_seed && *endp == 0))
+        random_seed = crc32_string (0, flag_random_seed);
+    }
+  else if (!random_seed)
+    random_seed = local_tick ^ getpid ();  /* Old racey fallback method */
 }
 
-/* Obtain the random_seed string.  Unless NOINIT, initialize it if
+/* Obtain the random_seed.  Unless NOINIT, initialize it if
    it's not provided in the command line.  */
 
-const char *
+HOST_WIDE_INT
 get_random_seed (bool noinit)
 {
   if (!flag_random_seed && !noinit)
     init_random_seed ();
-  return flag_random_seed;
+  return random_seed;
 }
 
 /* Modify the random_seed string to VAL.  Return its previous
@@ -565,71 +549,75 @@ emit_debug_global_declarations (tree *vec, int len)
 static void
 compile_file (void)
 {
-  /* Initialize yet another pass.  */
-
-  ggc_protect_identifiers = true;
-
-  init_cgraph ();
-  init_final (main_input_filename);
-  coverage_init (aux_base_name);
-  statistics_init ();
-  invoke_plugin_callbacks (PLUGIN_START_UNIT, NULL);
-
-  timevar_push (TV_PARSE);
+  timevar_start (TV_PHASE_PARSING);
+  timevar_push (TV_PARSE_GLOBAL);
 
   /* Call the parser, which parses the entire file (calling
      rest_of_compilation for each function).  */
   lang_hooks.parse_file ();
 
+  timevar_pop (TV_PARSE_GLOBAL);
+  timevar_stop (TV_PHASE_PARSING);
+
   /* Compilation is now finished except for writing
      what's left of the symbol table output.  */
-  timevar_pop (TV_PARSE);
 
   if (flag_syntax_only || flag_wpa)
     return;
 
+  timevar_start (TV_PHASE_GENERATE);
+
   ggc_protect_identifiers = false;
 
   /* This must also call cgraph_finalize_compilation_unit.  */
   lang_hooks.decls.final_write_globals ();
 
   if (seen_error ())
-    return;
+    {
+      timevar_stop (TV_PHASE_GENERATE);
+      return;
+    }
 
-  varpool_assemble_pending_decls ();
-  finish_aliases_2 ();
+  /* Compilation unit is finalized.  When producing non-fat LTO object, we are
+     basically finished.  */
+  if (in_lto_p || !flag_lto || flag_fat_lto_objects)
+    {
+      varpool_assemble_pending_decls ();
+      finish_aliases_2 ();
 
-  /* Likewise for mudflap static object registrations.  */
-  if (flag_mudflap)
-    mudflap_finish_file ();
+      /* Likewise for mudflap static object registrations.  */
+      if (flag_mudflap)
+       mudflap_finish_file ();
 
-  output_shared_constant_pool ();
-  output_object_blocks ();
+      output_shared_constant_pool ();
+      output_object_blocks ();
+  finish_tm_clone_pairs ();
 
-  /* Write out any pending weak symbol declarations.  */
-  weak_finish ();
+      /* Write out any pending weak symbol declarations.  */
+      weak_finish ();
 
-  /* This must be at the end before unwind and debug info.
-     Some target ports emit PIC setup thunks here.  */
-  targetm.asm_out.code_end ();
+      /* This must be at the end before unwind and debug info.
+        Some target ports emit PIC setup thunks here.  */
+      targetm.asm_out.code_end ();
 
-  /* Do dbx symbols.  */
-  timevar_push (TV_SYMOUT);
+      /* Do dbx symbols.  */
+      timevar_push (TV_SYMOUT);
 
-#if defined DWARF2_DEBUGGING_INFO || defined DWARF2_UNWIND_INFO
-  if (dwarf2out_do_frame ())
-    dwarf2out_frame_finish ();
-#endif
+    #if defined DWARF2_DEBUGGING_INFO || defined DWARF2_UNWIND_INFO
+      if (dwarf2out_do_frame ())
+       dwarf2out_frame_finish ();
+    #endif
 
-  (*debug_hooks->finish) (main_input_filename);
-  timevar_pop (TV_SYMOUT);
+      (*debug_hooks->finish) (main_input_filename);
+      timevar_pop (TV_SYMOUT);
 
-  /* Output some stuff at end of file if nec.  */
+      /* Output some stuff at end of file if nec.  */
 
-  dw2_output_indirect_constants ();
+      dw2_output_indirect_constants ();
 
-  /* Flush any pending external directives.  */
-  process_pending_assemble_externals ();
+      /* Flush any pending external directives.  */
+      process_pending_assemble_externals ();
+   }
 
   /* Emit LTO marker if LTO info has been previously emitted.  This is
      used by collect2 to determine whether an object file contains IL.
@@ -650,6 +638,23 @@ compile_file (void)
                         (unsigned HOST_WIDE_INT) 1,
                         (unsigned HOST_WIDE_INT) 1);
 #endif
+      /* Let linker plugin know that this is a slim object and must be LTOed
+         even when user did not ask for it.  */
+      if (!flag_fat_lto_objects)
+        {
+#if defined ASM_OUTPUT_ALIGNED_DECL_COMMON
+         ASM_OUTPUT_ALIGNED_DECL_COMMON (asm_out_file, NULL_TREE,
+                                         "__gnu_lto_slim",
+                                         (unsigned HOST_WIDE_INT) 1, 8);
+#elif defined ASM_OUTPUT_ALIGNED_COMMON
+         ASM_OUTPUT_ALIGNED_COMMON (asm_out_file, "__gnu_lto_slim",
+                                    (unsigned HOST_WIDE_INT) 1, 8);
+#else
+         ASM_OUTPUT_COMMON (asm_out_file, "__gnu_lto_slim",
+                            (unsigned HOST_WIDE_INT) 1,
+                            (unsigned HOST_WIDE_INT) 1);
+#endif
+        }
     }
 
   /* Attach a special .ident directive to the end of the file to identify
@@ -674,13 +679,9 @@ compile_file (void)
      into the assembly file here, and hence we can not output anything to the
      assembly file after this point.  */
   targetm.asm_out.file_end ();
-}
 
-/* Indexed by enum debug_info_type.  */
-const char *const debug_type_names[] =
-{
-  "none", "stabs", "coff", "dwarf-2", "xcoff", "vms"
-};
+  timevar_stop (TV_PHASE_GENERATE);
+}
 
 /* Print version information to FILE.
    Each line begins with INDENT (for the case where FILE is the
@@ -753,7 +754,6 @@ print_version (FILE *file, const char *indent)
   print_plugins_versions (file, indent);
 }
 
-#ifdef ASM_COMMENT_START
 static int
 print_to_asm_out_file (print_switch_type type, const char * text)
 {
@@ -786,7 +786,6 @@ print_to_asm_out_file (print_switch_type type, const char * text)
       return -1;
     }
 }
-#endif
 
 static int
 print_to_stderr (print_switch_type type, const char * text)
@@ -894,7 +893,7 @@ print_switch_values (print_switch_fn_type print_fn)
                             SWITCH_TYPE_DESCRIPTIVE, _("options enabled: "));
 
   for (j = 0; j < cl_options_count; j++)
-    if ((cl_options[j].flags & CL_REPORT)
+    if (cl_options[j].cl_report
        && option_enabled (j, &global_options) > 0)
       pos = print_single_switch (print_fn, pos,
                                 SWITCH_TYPE_ENABLED, cl_options[j].opt_text);
@@ -952,7 +951,6 @@ init_asm_output (const char *name)
            inform (input_location, "-frecord-gcc-switches is not supported by the current target");
        }
 
-#ifdef ASM_COMMENT_START
       if (flag_verbose_asm)
        {
          /* Print the list of switches in effect
@@ -961,7 +959,6 @@ init_asm_output (const char *name)
          print_switch_values (print_to_asm_out_file);
          putc ('\n', asm_out_file);
        }
-#endif
     }
 }
 
@@ -1051,14 +1048,12 @@ output_stack_usage (void)
   };
   HOST_WIDE_INT stack_usage = current_function_static_stack_size;
   enum stack_usage_kind_type stack_usage_kind;
-  expanded_location loc;
-  const char *raw_id, *id;
 
   if (stack_usage < 0)
     {
       if (!warning_issued)
        {
-         warning (0, "-fstack-usage not supported for this target");
+         warning (0, "stack usage computation not supported for this target");
          warning_issued = true;
        }
       return;
@@ -1085,24 +1080,44 @@ output_stack_usage (void)
       stack_usage += current_function_dynamic_stack_size;
     }
 
-  loc = expand_location (DECL_SOURCE_LOCATION (current_function_decl));
+  if (flag_stack_usage)
+    {
+      expanded_location loc
+       = expand_location (DECL_SOURCE_LOCATION (current_function_decl));
+      const char *raw_id, *id;
+
+      /* Strip the scope prefix if any.  */
+      raw_id = lang_hooks.decl_printable_name (current_function_decl, 2);
+      id = strrchr (raw_id, '.');
+      if (id)
+       id++;
+      else
+       id = raw_id;
+
+      fprintf (stack_usage_file,
+              "%s:%d:%d:%s\t"HOST_WIDE_INT_PRINT_DEC"\t%s\n",
+              lbasename (loc.file),
+              loc.line,
+              loc.column,
+              id,
+              stack_usage,
+              stack_usage_kind_str[stack_usage_kind]);
+    }
 
-  /* Strip the scope prefix if any.  */
-  raw_id = lang_hooks.decl_printable_name (current_function_decl, 2);
-  id = strrchr (raw_id, '.');
-  if (id)
-    id++;
-  else
-    id = raw_id;
-
-  fprintf (stack_usage_file,
-          "%s:%d:%d:%s\t"HOST_WIDE_INT_PRINT_DEC"\t%s\n",
-          lbasename (loc.file),
-          loc.line,
-          loc.column,
-          id,
-          stack_usage,
-          stack_usage_kind_str[stack_usage_kind]);
+  if (warn_stack_usage >= 0)
+    {
+      if (stack_usage_kind == DYNAMIC)
+       warning (OPT_Wstack_usage_, "stack usage might be unbounded");
+      else if (stack_usage > warn_stack_usage)
+       {
+         if (stack_usage_kind == DYNAMIC_BOUNDED)
+           warning (OPT_Wstack_usage_, "stack usage might be %wd bytes",
+                    stack_usage);
+         else
+           warning (OPT_Wstack_usage_, "stack usage is %wd bytes",
+                    stack_usage);
+       }
+    }
 }
 
 /* Open an auxiliary output file.  */
@@ -1149,6 +1164,9 @@ general_init (const char *argv0)
      can give warnings and errors.  */
   diagnostic_initialize (global_dc, N_OPTS);
   diagnostic_starter (global_dc) = default_tree_diagnostic_starter;
+  /* By default print macro expansion contexts in the diagnostic
+     finalizer -- for tokens resulting from macro macro expansion.  */
+  diagnostic_finalizer (global_dc) = virt_loc_aware_diagnostic_finalizer;
   /* Set a default printer.  Language specific initializations will
      override it later.  */
   pp_format_decoder (global_dc->printer) = &default_tree_printer;
@@ -1191,16 +1209,17 @@ general_init (const char *argv0)
   line_table = ggc_alloc_line_maps ();
   linemap_init (line_table);
   line_table->reallocator = realloc_for_line_map;
+  line_table->round_alloc_size = ggc_round_alloc_size;
   init_ttree ();
 
   /* Initialize register usage now so switches may override.  */
   init_reg_sets ();
 
   /* Register the language-independent parameters.  */
-  add_params (lang_independent_params, LAST_PARAM);
-  targetm.target_option.default_params ();
+  global_init_params ();
 
-  /* This must be done after add_params but before argument processing.  */
+  /* This must be done after global_init_params but before argument
+     processing.  */
   init_ggc_heuristics();
   init_optimization_passes ();
   statistics_early_init ();
@@ -1256,29 +1275,6 @@ process_options (void)
 
   maximum_field_alignment = initial_max_fld_align * BITS_PER_UNIT;
 
-  /* This replaces set_Wunused.  */
-  if (warn_unused_function == -1)
-    warn_unused_function = warn_unused;
-  if (warn_unused_label == -1)
-    warn_unused_label = warn_unused;
-  /* Wunused-parameter is enabled if both -Wunused -Wextra are enabled.  */
-  if (warn_unused_parameter == -1)
-    warn_unused_parameter = (warn_unused && extra_warnings);
-  if (warn_unused_variable == -1)
-    warn_unused_variable = warn_unused;
-  /* Wunused-but-set-parameter is enabled if both -Wunused -Wextra are
-     enabled.  */
-  if (warn_unused_but_set_parameter == -1)
-    warn_unused_but_set_parameter = (warn_unused && extra_warnings);
-  if (warn_unused_but_set_variable == -1)
-    warn_unused_but_set_variable = warn_unused;
-  if (warn_unused_value == -1)
-    warn_unused_value = warn_unused;
-
-  /* This replaces set_Wextra.  */
-  if (warn_uninitialized == -1)
-    warn_uninitialized = extra_warnings;
-
   /* Allow the front end to perform consistency checks and do further
      initialization based on the command line options.  This hook also
      sets the original filename if appropriate (e.g. foo.i -> foo.c)
@@ -1317,14 +1313,33 @@ process_options (void)
 
 #ifndef HAVE_cloog
   if (flag_graphite
+      || flag_graphite_identity
       || flag_loop_block
+      || flag_loop_flatten
       || flag_loop_interchange
       || flag_loop_strip_mine
-      || flag_graphite_identity
       || flag_loop_parallelize_all)
-    sorry ("Graphite loop optimizations cannot be used");
+    sorry ("Graphite loop optimizations cannot be used (-fgraphite, "
+          "-fgraphite-identity, -floop-block, -floop-flatten, "
+          "-floop-interchange, -floop-strip-mine, -floop-parallelize-all, "
+          "and -ftree-loop-linear)");
 #endif
 
+  if (flag_mudflap && flag_lto)
+    sorry ("mudflap cannot be used together with link-time optimization");
+
+  /* One region RA really helps to decrease the code size.  */
+  if (flag_ira_region == IRA_REGION_AUTODETECT)
+    flag_ira_region
+      = optimize_size || !optimize ? IRA_REGION_ONE : IRA_REGION_MIXED;
+
+  if (flag_strict_volatile_bitfields > 0 && !abi_version_at_least (2))
+    {
+      warning (0, "-fstrict-volatile-bitfields disabled; "
+              "it is incompatible with ABI versions < 2");
+      flag_strict_volatile_bitfields = 0;
+    }
+
   /* Unrolling all loops implies that standard loop unrolling must also
      be done.  */
   if (flag_unroll_all_loops)
@@ -1479,12 +1494,15 @@ process_options (void)
   /* If the user specifically requested variable tracking with tagging
      uninitialized variables, we need to turn on variable tracking.
      (We already determined above that variable tracking is feasible.)  */
-  if (flag_var_tracking_uninit)
+  if (flag_var_tracking_uninit == 1)
     flag_var_tracking = 1;
 
   if (flag_var_tracking == AUTODETECT_VALUE)
     flag_var_tracking = optimize >= 1;
 
+  if (flag_var_tracking_uninit == AUTODETECT_VALUE)
+    flag_var_tracking_uninit = flag_var_tracking;
+
   if (flag_var_tracking_assignments == AUTODETECT_VALUE)
     flag_var_tracking_assignments = flag_var_tracking
       && !(flag_selective_scheduling || flag_selective_scheduling2);
@@ -1516,7 +1534,7 @@ process_options (void)
        fatal_error ("can%'t open %s: %m", aux_info_file_name);
     }
 
-  if (! targetm.have_named_sections)
+  if (!targetm_common.have_named_sections)
     {
       if (flag_function_sections)
        {
@@ -1587,17 +1605,14 @@ process_options (void)
   if (!flag_stack_protect)
     warn_stack_protect = 0;
 
-  /* ??? Unwind info is not correct around the CFG unless either a frame
-     pointer is present or A_O_A is set.  Fixing this requires rewriting
-     unwind info generation to be aware of the CFG and propagating states
-     around edges.  */
-  if (flag_unwind_tables && !ACCUMULATE_OUTGOING_ARGS
-      && flag_omit_frame_pointer)
-    {
-      warning (0, "unwind tables currently require a frame pointer "
-              "for correctness");
-      flag_omit_frame_pointer = 0;
-    }
+  /* Enable -Werror=coverage-mismatch when -Werror and -Wno-error
+     have not been set.  */
+  if (!global_options_set.x_warnings_are_errors
+      && warn_coverage_mismatch
+      && (global_dc->classify_diagnostic[OPT_Wcoverage_mismatch] ==
+          DK_UNSPECIFIED))
+    diagnostic_classify_diagnostic (global_dc, OPT_Wcoverage_mismatch,
+                                    DK_ERROR, UNKNOWN_LOCATION);
 
   /* Save the current optimization options.  */
   optimization_default_node = build_optimization_node ();
@@ -1742,11 +1757,14 @@ lang_dependent_init (const char *name)
     return 0;
   input_location = save_loc;
 
-  init_asm_output (name);
+  if (!flag_wpa)
+    {
+      init_asm_output (name);
 
-  /* If stack usage information is desired, open the output file.  */
-  if (flag_stack_usage)
-    stack_usage_file = open_auxiliary_file ("su");
+      /* If stack usage information is desired, open the output file.  */
+      if (flag_stack_usage)
+       stack_usage_file = open_auxiliary_file ("su");
+    }
 
   /* This creates various _DECL nodes, so needs to be called after the
      front end is initialized.  */
@@ -1755,20 +1773,18 @@ lang_dependent_init (const char *name)
   /* Do the target-specific parts of the initialization.  */
   lang_dependent_init_target ();
 
-  /* If dbx symbol table desired, initialize writing it and output the
-     predefined types.  */
-  timevar_push (TV_SYMOUT);
-
-#if defined DWARF2_DEBUGGING_INFO || defined DWARF2_UNWIND_INFO
-  if (dwarf2out_do_frame ())
-    dwarf2out_frame_init ();
-#endif
+  if (!flag_wpa)
+    {
+      /* If dbx symbol table desired, initialize writing it and output the
+        predefined types.  */
+      timevar_push (TV_SYMOUT);
 
-  /* Now we have the correct original filename, we can initialize
-     debug output.  */
-  (*debug_hooks->init) (name);
+      /* Now we have the correct original filename, we can initialize
+        debug output.  */
+      (*debug_hooks->init) (name);
 
-  timevar_pop (TV_SYMOUT);
+      timevar_pop (TV_SYMOUT);
+    }
 
   return 1;
 }
@@ -1779,16 +1795,39 @@ lang_dependent_init (const char *name)
 void
 target_reinit (void)
 {
+  struct rtl_data saved_x_rtl;
+  rtx *saved_regno_reg_rtx;
+
+  /* Save *crtl and regno_reg_rtx around the reinitialization
+     to allow target_reinit being called even after prepare_function_start.  */
+  saved_regno_reg_rtx = regno_reg_rtx;
+  if (saved_regno_reg_rtx)
+    {  
+      saved_x_rtl = *crtl;
+      memset (crtl, '\0', sizeof (*crtl));
+      regno_reg_rtx = NULL;
+    }
+
   /* Reinitialize RTL backend.  */
   backend_init_target ();
 
   /* Reinitialize lang-dependent parts.  */
   lang_dependent_init_target ();
+
+  /* And restore it at the end, as free_after_compilation from
+     expand_dummy_function_end clears it.  */
+  if (saved_regno_reg_rtx)
+    {
+      *crtl = saved_x_rtl;
+      regno_reg_rtx = saved_regno_reg_rtx;
+      saved_regno_reg_rtx = NULL;
+    }
 }
 
 void
 dump_memory_report (bool final)
 {
+  dump_line_table_statistics ();
   ggc_print_statistics ();
   stringpool_statistics ();
   dump_tree_statistics ();
@@ -1825,8 +1864,6 @@ finalize (bool no_backend)
        fatal_error ("error writing to %s: %m", asm_file_name);
       if (fclose (asm_out_file) != 0)
        fatal_error ("error closing %s: %m", asm_file_name);
-      if (flag_wpa)
-       unlink_if_ordinary (asm_file_name);
     }
 
   if (stack_usage_file)
@@ -1863,6 +1900,8 @@ do_compile (void)
   /* Don't do any more if an error has already occurred.  */
   if (!seen_error ())
     {
+      timevar_start (TV_PHASE_SETUP);
+
       /* This must be run always, because it is needed to compute the FP
         predefined macros, such as __LDBL_MAX__, for targets using non
         default FP formats.  */
@@ -1874,9 +1913,31 @@ do_compile (void)
 
       /* Language-dependent initialization.  Returns true on success.  */
       if (lang_dependent_init (main_input_filename))
-       compile_file ();
+        {
+          /* Initialize yet another pass.  */
+
+          ggc_protect_identifiers = true;
+
+          init_cgraph ();
+          init_final (main_input_filename);
+          coverage_init (aux_base_name);
+          statistics_init ();
+          invoke_plugin_callbacks (PLUGIN_START_UNIT, NULL);
+
+          timevar_stop (TV_PHASE_SETUP);
+
+          compile_file ();
+        }
+      else
+        {
+          timevar_stop (TV_PHASE_SETUP);
+        }
+
+      timevar_start (TV_PHASE_FINALIZE);
 
       finalize (no_backend);
+
+      timevar_stop (TV_PHASE_FINALIZE);
     }
 
   /* Stop timing and print the times.  */
@@ -1893,6 +1954,10 @@ do_compile (void)
 int
 toplev_main (int argc, char **argv)
 {
+  /* Parsing and gimplification sometimes need quite large stack.
+     Increase stack size limits if possible.  */
+  stack_limit_increase (64 * 1024 * 1024);
+
   expandargv (&argc, &argv);
 
   /* Initialization of GCC's environment, and diagnostics.  */