IA MCU psABI support: changes to libraries
[gcc.git] / gcc / toplev.c
index 98ea05880135f993f79b5ca335ca428b7ac00089..573b144a138735fc9684612222be58915ad6a554 100644 (file)
@@ -1,5 +1,5 @@
 /* Top level of GCC compilers (cc1, cc1plus, etc.)
-   Copyright (C) 1987-2014 Free Software Foundation, Inc.
+   Copyright (C) 1987-2015 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -26,9 +26,10 @@ along with GCC; see the file COPYING3.  If not see
 #include "system.h"
 #include "coretypes.h"
 #include "tm.h"
-#include "line-map.h"
-#include "input.h"
+#include "alias.h"
+#include "symtab.h"
 #include "tree.h"
+#include "fold-const.h"
 #include "varasm.h"
 #include "tree-inline.h"
 #include "realmpfr.h"  /* For GMP/MPFR/MPC versions, in print_version.  */
@@ -45,6 +46,12 @@ along with GCC; see the file COPYING3.  If not see
 #include "except.h"
 #include "function.h"
 #include "toplev.h"
+#include "expmed.h"
+#include "dojump.h"
+#include "explow.h"
+#include "calls.h"
+#include "emit-rtl.h"
+#include "stmt.h"
 #include "expr.h"
 #include "intl.h"
 #include "regs.h"
@@ -55,6 +62,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "params.h"
 #include "reload.h"
 #include "ira.h"
+#include "lra.h"
 #include "dwarf2asm.h"
 #include "debug.h"
 #include "target.h"
@@ -62,6 +70,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "langhooks.h"
 #include "cfgloop.h" /* for init_set_costs */
 #include "hosthooks.h"
+#include "predict.h"
+#include "basic-block.h"
 #include "cgraph.h"
 #include "opts.h"
 #include "opts-diagnostic.h"
@@ -75,10 +85,19 @@ along with GCC; see the file COPYING3.  If not see
 #include "gimple-expr.h"
 #include "gimple.h"
 #include "plugin.h"
-#include "diagnostic-color.h"
 #include "context.h"
 #include "pass_manager.h"
+#include "auto-profile.h"
+#include "dwarf2out.h"
+#include "bitmap.h"
+#include "ipa-reference.h"
+#include "symbol-summary.h"
+#include "ipa-prop.h"
+#include "gcse.h"
+#include "insn-codes.h"
 #include "optabs.h"
+#include "tree-chkp.h"
+#include "omp-low.h"
 
 #if defined(DBX_DEBUGGING_INFO) || defined(XCOFF_DEBUGGING_INFO)
 #include "dbxout.h"
@@ -93,8 +112,14 @@ along with GCC; see the file COPYING3.  If not see
                                   declarations for e.g. AIX 4.x.  */
 #endif
 
-static void general_init (const char *);
-static void do_compile (void);
+#ifndef HAVE_prologue
+#define HAVE_prologue 0
+#endif
+
+#include <new>
+
+static void general_init (const char *, bool);
+static void do_compile ();
 static void process_options (void);
 static void backend_init (void);
 static int lang_dependent_init (const char *);
@@ -251,7 +276,9 @@ init_local_tick (void)
       int fd = open ("/dev/urandom", O_RDONLY);
       if (fd >= 0)
         {
-          read (fd, &random_seed, sizeof (random_seed));
+          if (read (fd, &random_seed, sizeof (random_seed))
+              != sizeof (random_seed))
+            random_seed = 0;
           close (fd);
         }
 
@@ -401,7 +428,7 @@ wrapup_global_declaration_2 (tree decl)
        needed = false;
       else if (node && node->alias)
        needed = false;
-      else if (!cgraph_global_info_ready
+      else if (!symtab->global_info_ready
               && (TREE_USED (decl)
                   || TREE_USED (DECL_ASSEMBLER_NAME (decl))))
        /* needed */;
@@ -454,15 +481,15 @@ wrapup_global_declarations (tree *vec, int len)
   return output_something;
 }
 
-/* A subroutine of check_global_declarations.  Issue appropriate warnings
-   for the global declaration DECL.  */
+/* Issue appropriate warnings for the global declaration DECL.  */
 
 void
-check_global_declaration_1 (tree decl)
+check_global_declaration (tree decl)
 {
   /* Warn about any function declared static but not defined.  We don't
      warn about variables, because many programs have static variables
      that exist only to get some text into the object file.  */
+  symtab_node *snode = symtab_node::get (decl);
   if (TREE_CODE (decl) == FUNCTION_DECL
       && DECL_INITIAL (decl) == 0
       && DECL_EXTERNAL (decl)
@@ -470,9 +497,9 @@ check_global_declaration_1 (tree decl)
       && ! TREE_NO_WARNING (decl)
       && ! TREE_PUBLIC (decl)
       && (warn_unused_function
-         || TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))))
+         || snode->referred_to_p (/*include_self=*/false)))
     {
-      if (TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)))
+      if (snode->referred_to_p (/*include_self=*/false))
        pedwarn (input_location, 0, "%q+F used but never defined", decl);
       else
        warning (OPT_Wunused_function, "%q+F declared %<static%> but never defined", decl);
@@ -487,16 +514,26 @@ check_global_declaration_1 (tree decl)
        || (warn_unused_variable
           && TREE_CODE (decl) == VAR_DECL && ! TREE_READONLY (decl)))
       && ! DECL_IN_SYSTEM_HEADER (decl)
+      && ! snode->referred_to_p (/*include_self=*/false)
+      /* This TREE_USED check is needed in addition to referred_to_p
+        above, because the `__unused__' attribute is not being
+        considered for referred_to_p.  */
       && ! TREE_USED (decl)
       /* The TREE_USED bit for file-scope decls is kept in the identifier,
         to handle multiple external decls in different scopes.  */
       && ! (DECL_NAME (decl) && TREE_USED (DECL_NAME (decl)))
       && ! DECL_EXTERNAL (decl)
+      && ! DECL_ARTIFICIAL (decl)
+      && ! DECL_ABSTRACT_ORIGIN (decl)
       && ! TREE_PUBLIC (decl)
       /* A volatile variable might be used in some non-obvious way.  */
       && ! TREE_THIS_VOLATILE (decl)
       /* Global register variables must be declared to reserve them.  */
       && ! (TREE_CODE (decl) == VAR_DECL && DECL_REGISTER (decl))
+      /* Global ctors and dtors are called by the runtime.  */
+      && (TREE_CODE (decl) != FUNCTION_DECL
+         || (!DECL_STATIC_CONSTRUCTOR (decl)
+             && !DECL_STATIC_DESTRUCTOR (decl)))
       /* Otherwise, ask the language.  */
       && lang_hooks.decls.warn_unused_global (decl))
     warning ((TREE_CODE (decl) == FUNCTION_DECL)
@@ -505,35 +542,6 @@ check_global_declaration_1 (tree decl)
             "%q+D defined but not used", decl);
 }
 
-/* Issue appropriate warnings for the global declarations in V (of
-   which there are LEN).  */
-
-void
-check_global_declarations (tree *v, int len)
-{
-  int i;
-
-  for (i = 0; i < len; i++)
-    check_global_declaration_1 (v[i]);
-}
-
-/* Emit debugging information for all global declarations in VEC.  */
-
-void
-emit_debug_global_declarations (tree *vec, int len)
-{
-  int i;
-
-  /* Avoid confusing the debug information machinery when there are errors.  */
-  if (seen_error ())
-    return;
-
-  timevar_push (TV_SYMOUT);
-  for (i = 0; i < len; i++)
-    debug_hooks->global_decl (vec[i]);
-  timevar_pop (TV_SYMOUT);
-}
-
 /* Compile an entire translation unit.  Write a file of assembly
    output and various debugging dumps.  */
 
@@ -543,13 +551,15 @@ compile_file (void)
   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).  */
+  /* Parse entire file and generate initial debug information.  */
   lang_hooks.parse_file ();
 
   timevar_pop (TV_PARSE_GLOBAL);
   timevar_stop (TV_PHASE_PARSING);
 
+  if (flag_dump_locations)
+    dump_location_info (stderr);
+
   /* Compilation is now finished except for writing
      what's left of the symbol table output.  */
 
@@ -558,12 +568,33 @@ compile_file (void)
 
   ggc_protect_identifiers = false;
 
-  /* This must also call finalize_compilation_unit.  */
-  lang_hooks.decls.final_write_globals ();
+  /* Run the actual compilation process.  */
+  if (!in_lto_p)
+    {
+      timevar_start (TV_PHASE_OPT_GEN);
+      symtab->finalize_compilation_unit ();
+      timevar_stop (TV_PHASE_OPT_GEN);
+    }
+
+  /* Perform any post compilation-proper parser cleanups and
+     processing.  This is currently only needed for the C++ parser,
+     which can be hopefully cleaned up so this hook is no longer
+     necessary.  */
+  if (lang_hooks.decls.post_compilation_parsing_cleanups)
+    lang_hooks.decls.post_compilation_parsing_cleanups ();
 
   if (seen_error ())
     return;
 
+  /* After the parser has generated debugging information, augment
+     this information with any new location/etc information that may
+     have become available after the compilation proper.  */
+  timevar_start (TV_PHASE_DBGINFO);
+  symtab_node *node;
+  FOR_EACH_DEFINED_SYMBOL (node)
+    debug_hooks->late_global_decl (node->decl);
+  timevar_stop (TV_PHASE_DBGINFO);
+
   timevar_start (TV_PHASE_LATE_ASM);
 
   /* Compilation unit is finalized.  When producing non-fat LTO object, we are
@@ -577,6 +608,11 @@ compile_file (void)
       if (flag_sanitize & SANITIZE_THREAD)
        tsan_finish_file ();
 
+      if (flag_check_pointer_bounds)
+       chkp_finish_file ();
+
+      omp_finish_file ();
+
       output_shared_constant_pool ();
       output_object_blocks ();
       finish_tm_clone_pairs ();
@@ -612,7 +648,7 @@ compile_file (void)
      We used to emit an undefined reference here, but this produces
      link errors if an object file with IL is stored into a shared
      library without invoking lto1.  */
-  if (flag_generate_lto)
+  if (flag_generate_lto || flag_generate_offload)
     {
 #if defined ASM_OUTPUT_ALIGNED_DECL_COMMON
       ASM_OUTPUT_ALIGNED_DECL_COMMON (asm_out_file, NULL_TREE,
@@ -626,23 +662,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)
-        {
+    }
+
+  /* Let linker plugin know that this is a slim object and must be LTOed
+     even when user did not ask for it.  */
+  if (flag_generate_lto && !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);
+      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);
+      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);
+      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
@@ -660,6 +696,10 @@ compile_file (void)
       targetm.asm_out.output_ident (ident_str);
     }
 
+  /* Auto profile finalization. */
+  if (flag_auto_profile)
+    end_auto_profile ();
+
   /* Invoke registered plugin callbacks.  */
   invoke_plugin_callbacks (PLUGIN_FINISH_UNIT, NULL);
 
@@ -673,10 +713,19 @@ compile_file (void)
 
 /* Print version information to FILE.
    Each line begins with INDENT (for the case where FILE is the
-   assembler output file).  */
+   assembler output file).
+
+   If SHOW_GLOBAL_STATE is true (for cc1 etc), we are within the compiler
+   proper and can print pertinent state (e.g. params and plugins).
+
+   If SHOW_GLOBAL_STATE is false (for use by libgccjit), we are outside the
+   compiler, and we don't hold the mutex on the compiler's global state:
+   we can't print params and plugins, since they might not be initialized,
+   or might be being manipulated by a compile running in another
+   thread.  */
 
 void
-print_version (FILE *file, const char *indent)
+print_version (FILE *file, const char *indent, bool show_global_state)
 {
   static const char fmt1[] =
 #ifdef __GNUC__
@@ -736,12 +785,16 @@ print_version (FILE *file, const char *indent)
             file == stderr ? _(fmt3) : fmt3,
             indent, *indent != 0 ? " " : "",
             "MPC", MPC_VERSION_STRING, mpc_get_version ());
-  fprintf (file,
-          file == stderr ? _(fmt4) : fmt4,
-          indent, *indent != 0 ? " " : "",
-          PARAM_VALUE (GGC_MIN_EXPAND), PARAM_VALUE (GGC_MIN_HEAPSIZE));
 
-  print_plugins_versions (file, indent);
+  if (show_global_state)
+    {
+      fprintf (file,
+              file == stderr ? _(fmt4) : fmt4,
+              indent, *indent != 0 ? " " : "",
+              PARAM_VALUE (GGC_MIN_EXPAND), PARAM_VALUE (GGC_MIN_HEAPSIZE));
+
+      print_plugins_versions (file, indent);
+    }
 }
 
 static int
@@ -914,10 +967,18 @@ init_asm_output (const char *name)
        }
       if (!strcmp (asm_file_name, "-"))
        asm_out_file = stdout;
-      else
+      else if (!canonical_filename_eq (asm_file_name, name)
+              || !strcmp (asm_file_name, HOST_BIT_BUCKET))
        asm_out_file = fopen (asm_file_name, "w");
+      else
+       /* Use UNKOWN_LOCATION to prevent gcc from printing the first
+          line in the current file. */
+       fatal_error (UNKNOWN_LOCATION,
+                    "input file %qs is the same as output file",
+                    asm_file_name);
       if (asm_out_file == 0)
-       fatal_error ("can%'t open %s for writing: %m", asm_file_name);
+       fatal_error (UNKNOWN_LOCATION,
+                    "can%'t open %qs for writing: %m", asm_file_name);
     }
 
   if (!flag_syntax_only)
@@ -945,7 +1006,7 @@ init_asm_output (const char *name)
        {
          /* Print the list of switches in effect
             into the assembler file as comments.  */
-         print_version (asm_out_file, ASM_COMMENT_START);
+         print_version (asm_out_file, ASM_COMMENT_START, true);
          print_switch_values (print_to_asm_out_file);
          putc ('\n', asm_out_file);
        }
@@ -1041,7 +1102,7 @@ output_stack_usage (void)
        }
 
       fprintf (stack_usage_file,
-              "%s:%d:%d:%s\t"HOST_WIDE_INT_PRINT_DEC"\t%s\n",
+              "%s:%d:%d:%s\t" HOST_WIDE_INT_PRINT_DEC"\t%s\n",
               lbasename (loc.file),
               loc.line,
               loc.column,
@@ -1079,7 +1140,7 @@ open_auxiliary_file (const char *ext)
   filename = concat (aux_base_name, ".", ext, NULL);
   file = fopen (filename, "w");
   if (!file)
-    fatal_error ("can%'t open %s for writing: %m", filename);
+    fatal_error (input_location, "can%'t open %s for writing: %m", filename);
   free (filename);
   return file;
 }
@@ -1088,7 +1149,7 @@ open_auxiliary_file (const char *ext)
    options are parsed.  Signal handlers, internationalization etc.
    ARGV0 is main's argv[0].  */
 static void
-general_init (const char *argv0)
+general_init (const char *argv0, bool init_signals)
 {
   const char *p;
 
@@ -1115,11 +1176,6 @@ general_init (const char *argv0)
   /* Set a default printer.  Language specific initializations will
      override it later.  */
   tree_diagnostics_defaults (global_dc);
-  /* FIXME: This should probably be moved to C-family
-     language-specific initializations.  */
-  /* By default print macro expansion contexts in the diagnostic
-     finalizer -- for tokens resulting from macro expansion.  */
-  diagnostic_finalizer (global_dc) = virt_loc_aware_diagnostic_finalizer;
 
   global_dc->show_caret
     = global_options_init.x_flag_diagnostics_show_caret;
@@ -1132,33 +1188,37 @@ general_init (const char *argv0)
   global_dc->option_state = &global_options;
   global_dc->option_name = option_name;
 
-  /* Trap fatal signals, e.g. SIGSEGV, and convert them to ICE messages.  */
+  if (init_signals)
+    {
+      /* Trap fatal signals, e.g. SIGSEGV, and convert them to ICE messages.  */
 #ifdef SIGSEGV
-  signal (SIGSEGV, crash_signal);
+      signal (SIGSEGV, crash_signal);
 #endif
 #ifdef SIGILL
-  signal (SIGILL, crash_signal);
+      signal (SIGILL, crash_signal);
 #endif
 #ifdef SIGBUS
-  signal (SIGBUS, crash_signal);
+      signal (SIGBUS, crash_signal);
 #endif
 #ifdef SIGABRT
-  signal (SIGABRT, crash_signal);
+      signal (SIGABRT, crash_signal);
 #endif
 #if defined SIGIOT && (!defined SIGABRT || SIGABRT != SIGIOT)
-  signal (SIGIOT, crash_signal);
+      signal (SIGIOT, crash_signal);
 #endif
 #ifdef SIGFPE
-  signal (SIGFPE, crash_signal);
+      signal (SIGFPE, crash_signal);
 #endif
 
-  /* Other host-specific signal setup.  */
-  (*host_hooks.extra_signals)();
+      /* Other host-specific signal setup.  */
+      (*host_hooks.extra_signals)();
+  }
 
   /* Initialize the garbage-collector, string pools and tree type hash
      table.  */
   init_ggc ();
   init_stringpool ();
+  input_location = UNKNOWN_LOCATION;
   line_table = ggc_alloc<line_maps> ();
   linemap_init (line_table, BUILTINS_LOCATION);
   line_table->reallocator = realloc_for_line_map;
@@ -1178,6 +1238,7 @@ general_init (const char *argv0)
   /* Create the singleton holder for global state.
      Doing so also creates the pass manager and with it the passes.  */
   g = new gcc::context ();
+  symtab = new (ggc_cleared_alloc <symbol_table> ()) symbol_table ();
 
   statistics_early_init ();
   finish_params ();
@@ -1232,19 +1293,26 @@ process_options (void)
 
   maximum_field_alignment = initial_max_fld_align * BITS_PER_UNIT;
 
-  /* Default to -fdiagnostics-color=auto if GCC_COLORS is in the environment,
-     otherwise default to -fdiagnostics-color=never.  */
-  if (!global_options_set.x_flag_diagnostics_show_color
-      && getenv ("GCC_COLORS"))
-    pp_show_color (global_dc->printer)
-      = colorize_init (DIAGNOSTICS_COLOR_AUTO);
-
   /* 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)
      so we can correctly initialize debug output.  */
   no_backend = lang_hooks.post_options (&main_input_filename);
 
+  /* Set default values for parameters relation to the Scalar Reduction
+     of Aggregates passes (SRA and IP-SRA).  We must do this here, rather
+     than in opts.c:default_options_optimization as historically these
+     tuning heuristics have been based on MOVE_RATIO, which on some
+     targets requires other symbols from the backend.  */
+  maybe_set_param_value
+    (PARAM_SRA_MAX_SCALARIZATION_SIZE_SPEED,
+     get_move_ratio (true) * UNITS_PER_WORD,
+     global_options.x_param_values, global_options_set.x_param_values);
+  maybe_set_param_value
+    (PARAM_SRA_MAX_SCALARIZATION_SIZE_SIZE,
+     get_move_ratio (false) * UNITS_PER_WORD,
+     global_options.x_param_values, global_options_set.x_param_values);
+
   /* Some machines may reject certain combinations of options.  */
   targetm.target_option.override ();
 
@@ -1275,19 +1343,36 @@ process_options (void)
   else
     aux_base_name = "gccaux";
 
-#ifndef HAVE_cloog
+#ifndef HAVE_isl
   if (flag_graphite
       || flag_graphite_identity
       || flag_loop_block
       || flag_loop_interchange
       || flag_loop_strip_mine
-      || flag_loop_parallelize_all)
-    sorry ("Graphite loop optimizations cannot be used (-fgraphite, "
-          "-fgraphite-identity, -floop-block, "
+      || flag_loop_parallelize_all
+      || flag_loop_unroll_jam)
+    sorry ("Graphite loop optimizations cannot be used (ISL is not available)" 
+          "(-fgraphite, -fgraphite-identity, -floop-block, "
           "-floop-interchange, -floop-strip-mine, -floop-parallelize-all, "
-          "and -ftree-loop-linear)");
+          "-floop-unroll-and-jam, and -ftree-loop-linear)");
 #endif
 
+  if (flag_check_pointer_bounds)
+    {
+      if (targetm.chkp_bound_mode () == VOIDmode)
+       {
+         error ("-fcheck-pointer-bounds is not supported for this target");
+         flag_check_pointer_bounds = 0;
+       }
+
+      if (flag_sanitize & SANITIZE_ADDRESS)
+       {
+         error ("-fcheck-pointer-bounds is not supported with "
+                "Address Sanitizer");
+         flag_check_pointer_bounds = 0;
+       }
+    }
+
   /* One region RA really helps to decrease the code size.  */
   if (flag_ira_region == IRA_REGION_AUTODETECT)
     flag_ira_region
@@ -1349,7 +1434,7 @@ process_options (void)
      option flags in use.  */
   if (version_flag)
     {
-      print_version (stderr, "");
+      print_version (stderr, "", true);
       if (! quiet_flag)
        print_switch_values (print_to_stderr);
     }
@@ -1418,7 +1503,7 @@ process_options (void)
     debug_hooks = &vmsdbg_debug_hooks;
 #endif
   else
-    error ("target system does not support the \"%s\" debug format",
+    error ("target system does not support the %qs debug format",
           debug_type_names[write_symbols]);
 
   /* We know which debug output will be used so we can set flag_var_tracking
@@ -1473,11 +1558,12 @@ process_options (void)
     warning (0, "var-tracking-assignments changes selective scheduling");
 
   if (flag_tree_cselim == AUTODETECT_VALUE)
-#ifdef HAVE_conditional_move
-    flag_tree_cselim = 1;
-#else
-    flag_tree_cselim = 0;
-#endif
+    {
+      if (HAVE_conditional_move)
+       flag_tree_cselim = 1;
+      else
+       flag_tree_cselim = 0;
+    }
 
   /* If auxiliary info generation is desired, open the output file.
      This goes in the same directory as the source file--unlike
@@ -1486,7 +1572,7 @@ process_options (void)
     {
       aux_info_file = fopen (aux_info_file_name, "w");
       if (aux_info_file == 0)
-       fatal_error ("can%'t open %s: %m", aux_info_file_name);
+       fatal_error (input_location, "can%'t open %s: %m", aux_info_file_name);
     }
 
   if (!targetm_common.have_named_sections)
@@ -1555,14 +1641,28 @@ process_options (void)
     warn_stack_protect = 0;
 
   /* Address Sanitizer needs porting to each target architecture.  */
+
   if ((flag_sanitize & SANITIZE_ADDRESS)
-      && (targetm.asan_shadow_offset == NULL
-         || !FRAME_GROWS_DOWNWARD))
+      && !FRAME_GROWS_DOWNWARD)
+    {
+      warning (0,
+              "-fsanitize=address and -fsanitize=kernel-address "
+              "are not supported for this target");
+      flag_sanitize &= ~SANITIZE_ADDRESS;
+    }
+
+  if ((flag_sanitize & SANITIZE_USER_ADDRESS)
+      && targetm.asan_shadow_offset == NULL)
     {
       warning (0, "-fsanitize=address not supported for this target");
       flag_sanitize &= ~SANITIZE_ADDRESS;
     }
 
+ /* Do not use IPA optimizations for register allocation if profiler is active
+    or port does not emit prologue and epilogue as RTL.  */
+  if (profile_flag || !HAVE_prologue || !HAVE_epilogue)
+    flag_ipa_ra = 0;
+
   /* Enable -Werror=coverage-mismatch when -Werror and -Wno-error
      have not been set.  */
   if (!global_options_set.x_warnings_are_errors
@@ -1575,6 +1675,9 @@ process_options (void)
   /* Save the current optimization options.  */
   optimization_default_node = build_optimization_node (&global_options);
   optimization_current_node = optimization_default_node;
+
+  /* Please don't change global_options after this point, those changes won't
+     be reflected in optimization_{default,current}_node.  */
 }
 
 /* This function can be called multiple times to reinitialize the compiler
@@ -1696,16 +1799,18 @@ lang_dependent_init_target (void)
 /* Perform initializations that are lang-dependent or target-dependent.
    but matters only for late optimizations and RTL generation.  */
 
+static int rtl_initialized;
+
 void
 initialize_rtl (void)
 {
-  static int initialized_once;
+  auto_timevar tv (TV_INITIALIZE_RTL);
 
   /* Initialization done just once per compilation, but delayed
      till code generation.  */
-  if (!initialized_once)
+  if (!rtl_initialized)
     ira_init_once ();
-  initialized_once = true;
+  rtl_initialized = true;
 
   /* Target specific RTL backend initialization.  */
   if (!this_target_rtl->target_specific_initialized)
@@ -1840,6 +1945,7 @@ dump_memory_report (bool final)
   dump_rtx_statistics ();
   dump_alloc_pool_statistics ();
   dump_bitmap_statistics ();
+  dump_hash_table_loc_statistics ();
   dump_vec_loc_statistics ();
   dump_ggc_loc_statistics (final);
   dump_alias_stats (stderr);
@@ -1866,9 +1972,9 @@ finalize (bool no_backend)
   if (asm_out_file)
     {
       if (ferror (asm_out_file) != 0)
-       fatal_error ("error writing to %s: %m", asm_file_name);
+       fatal_error (input_location, "error writing to %s: %m", asm_file_name);
       if (fclose (asm_out_file) != 0)
-       fatal_error ("error closing %s: %m", asm_file_name);
+       fatal_error (input_location, "error closing %s: %m", asm_file_name);
     }
 
   if (stack_usage_file)
@@ -1880,7 +1986,7 @@ finalize (bool no_backend)
 
       g->get_passes ()->finish_optimization_passes ();
 
-      ira_finish_once ();
+      lra_finish_once ();
     }
 
   if (mem_report)
@@ -1893,21 +1999,32 @@ finalize (bool no_backend)
   lang_hooks.finish ();
 }
 
+static bool
+standard_type_bitsize (int bitsize)
+{
+  /* As a special exception, we always want __int128 enabled if possible.  */
+  if (bitsize == 128)
+    return false;
+  if (bitsize == CHAR_TYPE_SIZE
+      || bitsize == SHORT_TYPE_SIZE
+      || bitsize == INT_TYPE_SIZE
+      || bitsize == LONG_TYPE_SIZE
+      || bitsize == LONG_LONG_TYPE_SIZE)
+    return true;
+  return false;
+}
+
 /* Initialize the compiler, and compile the input file.  */
 static void
-do_compile (void)
+do_compile ()
 {
-  /* Initialize timing first.  The C front ends read the main file in
-     the post_options hook, and C++ does file timings.  */
-  if (time_report || !quiet_flag  || flag_detailed_statistics)
-    timevar_init ();
-  timevar_start (TV_TOTAL);
-
   process_options ();
 
   /* Don't do any more if an error has already occurred.  */
   if (!seen_error ())
     {
+      int i;
+
       timevar_start (TV_PHASE_SETUP);
 
       /* This must be run always, because it is needed to compute the FP
@@ -1916,6 +2033,16 @@ do_compile (void)
       init_adjust_machine_modes ();
       init_derived_machine_modes ();
 
+      /* This must happen after the backend has a chance to process
+        command line options, but before the parsers are
+        initialized.  */
+      for (i = 0; i < NUM_INT_N_ENTS; i ++)
+       if (targetm.scalar_mode_supported_p (int_n_data[i].m)
+           && ! standard_type_bitsize (int_n_data[i].bitsize))
+         int_n_enabled_p[i] = true;
+       else
+         int_n_enabled_p[i] = false;
+
       /* Set up the back-end if requested.  */
       if (!no_backend)
        backend_init ();
@@ -1927,7 +2054,7 @@ do_compile (void)
 
           ggc_protect_identifiers = true;
 
-          init_cgraph ();
+         symtab->initialize ();
           init_final (main_input_filename);
           coverage_init (aux_base_name);
           statistics_init ();
@@ -1948,10 +2075,32 @@ do_compile (void)
 
       timevar_stop (TV_PHASE_FINALIZE);
     }
+}
+
+toplev::toplev (bool use_TV_TOTAL, bool init_signals)
+  : m_use_TV_TOTAL (use_TV_TOTAL),
+    m_init_signals (init_signals)
+{
+  if (!m_use_TV_TOTAL)
+    start_timevars ();
+}
+
+toplev::~toplev ()
+{
+  if (g_timer)
+    {
+      g_timer->stop (TV_TOTAL);
+      g_timer->print (stderr);
+    }
+}
+
+void
+toplev::start_timevars ()
+{
+  if (time_report || !quiet_flag  || flag_detailed_statistics)
+    timevar_init ();
 
-  /* Stop timing and print the times.  */
-  timevar_stop (TV_TOTAL);
-  timevar_print (stderr);
+  timevar_start (TV_TOTAL);
 }
 
 /* Entry point of cc1, cc1plus, jc1, f771, etc.
@@ -1961,7 +2110,7 @@ do_compile (void)
    It is not safe to call this function more than once.  */
 
 int
-toplev_main (int argc, char **argv)
+toplev::main (int argc, char **argv)
 {
   /* Parsing and gimplification sometimes need quite large stack.
      Increase stack size limits if possible.  */
@@ -1970,7 +2119,7 @@ toplev_main (int argc, char **argv)
   expandargv (&argc, &argv);
 
   /* Initialization of GCC's environment, and diagnostics.  */
-  general_init (argv[0]);
+  general_init (argv[0], m_init_signals);
 
   /* One-off initialization of options that does not need to be
      repeated when options are added for particular functions.  */
@@ -2004,14 +2153,18 @@ toplev_main (int argc, char **argv)
   initialize_plugins ();
 
   if (version_flag)
-    print_version (stderr, "");
+    print_version (stderr, "", true);
 
   if (help_flag)
     print_plugins_help (stderr, "");
 
   /* Exit early if we can (e.g. -help).  */
   if (!exit_after_options)
-    do_compile ();
+    {
+      if (m_use_TV_TOTAL)
+       start_timevars ();
+      do_compile ();
+    }
 
   if (warningcount || errorcount || werrorcount)
     print_ignored_options ();
@@ -2029,3 +2182,34 @@ toplev_main (int argc, char **argv)
 
   return (SUCCESS_EXIT_CODE);
 }
+
+/* For those that want to, this function aims to clean up enough state that
+   you can call toplev::main again. */
+void
+toplev::finalize (void)
+{
+  rtl_initialized = false;
+  this_target_rtl->target_specific_initialized = false;
+
+  /* Needs to be called before cgraph_c_finalize since it uses symtab.  */
+  ipa_reference_c_finalize ();
+
+  cgraph_c_finalize ();
+  cgraphunit_c_finalize ();
+  dwarf2out_c_finalize ();
+  gcse_c_finalize ();
+  ipa_cp_c_finalize ();
+  ira_costs_c_finalize ();
+  params_c_finalize ();
+
+  finalize_options_struct (&global_options);
+  finalize_options_struct (&global_options_set);
+
+  XDELETEVEC (save_decoded_options);
+
+  /* Clean up the context (and pass_manager etc). */
+  delete g;
+  g = NULL;
+
+  obstack_free (&opts_obstack, NULL);
+}