2017-01-22 Matthias Klose <doko@ubuntu.com>
[platform/upstream/gcc.git] / gcc / toplev.c
index 2f547bf..2335ad7 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-2017 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -25,97 +25,74 @@ along with GCC; see the file COPYING3.  If not see
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
-#include "tm.h"
-#include "line-map.h"
-#include "input.h"
+#include "backend.h"
+#include "target.h"
+#include "rtl.h"
 #include "tree.h"
+#include "gimple.h"
+#include "alloc-pool.h"
+#include "timevar.h"
+#include "memmodel.h"
+#include "tm_p.h"
+#include "optabs-libfuncs.h"
+#include "insn-config.h"
+#include "ira.h"
+#include "recog.h"
+#include "cgraph.h"
+#include "coverage.h"
+#include "diagnostic.h"
 #include "varasm.h"
 #include "tree-inline.h"
 #include "realmpfr.h"  /* For GMP/MPFR/MPC versions, in print_version.  */
 #include "version.h"
-#include "rtl.h"
-#include "tm_p.h"
 #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"
-#include "except.h"
-#include "hashtab.h"
-#include "hash-set.h"
-#include "vec.h"
-#include "machmode.h"
-#include "function.h"
 #include "toplev.h"
 #include "expr.h"
 #include "intl.h"
-#include "regs.h"
-#include "timevar.h"
-#include "diagnostic.h"
 #include "tree-diagnostic.h"
-#include "tree-pretty-print.h"
 #include "params.h"
 #include "reload.h"
-#include "ira.h"
 #include "lra.h"
 #include "dwarf2asm.h"
 #include "debug.h"
-#include "target.h"
 #include "common/common-target.h"
 #include "langhooks.h"
 #include "cfgloop.h" /* for init_set_costs */
 #include "hosthooks.h"
-#include "predict.h"
-#include "basic-block.h"
-#include "hash-map.h"
-#include "is-a.h"
-#include "plugin-api.h"
-#include "ipa-ref.h"
-#include "cgraph.h"
 #include "opts.h"
 #include "opts-diagnostic.h"
-#include "coverage.h"
-#include "value-prof.h"
-#include "alloc-pool.h"
 #include "asan.h"
 #include "tsan.h"
-#include "tree-ssa-alias.h"
-#include "internal-fn.h"
-#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 "tree-vrp.h"
 #include "ipa-prop.h"
 #include "gcse.h"
-#include "insn-codes.h"
-#include "optabs.h"
 #include "tree-chkp.h"
-#include "omp-low.h"
+#include "omp-offload.h"
+#include "hsa-common.h"
+#include "edit-context.h"
 
 #if defined(DBX_DEBUGGING_INFO) || defined(XCOFF_DEBUGGING_INFO)
 #include "dbxout.h"
 #endif
 
-#ifdef SDB_DEBUGGING_INFO
 #include "sdbout.h"
-#endif
 
 #ifdef XCOFF_DEBUGGING_INFO
-#include "xcoffout.h"          /* Needed for external data
-                                  declarations for e.g. AIX 4.x.  */
+#include "xcoffout.h"          /* Needed for external data declarations. */
 #endif
 
-#include <new>
+#include "selftest.h"
 
-static void general_init (const char *);
+static void general_init (const char *, bool);
 static void do_compile ();
 static void process_options (void);
 static void backend_init (void);
@@ -174,11 +151,6 @@ HOST_WIDE_INT random_seed;
    the support provided depends on the backend.  */
 rtx stack_limit_rtx;
 
-/* True if the user has tagged the function with the 'section'
-   attribute.  */
-
-bool user_defined_section_attribute = false;
-
 struct target_flag_state default_target_flag_state;
 #if SWITCHABLE_TARGET
 struct target_flag_state *this_target_flag_state = &default_target_flag_state;
@@ -273,7 +245,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);
         }
 
@@ -372,7 +346,7 @@ wrapup_global_declaration_1 (tree decl)
       && DECL_DEFER_OUTPUT (decl) != 0)
     DECL_DEFER_OUTPUT (decl) = 0;
 
-  if (TREE_CODE (decl) == VAR_DECL && DECL_SIZE (decl) == 0)
+  if (VAR_P (decl) && DECL_SIZE (decl) == 0)
     lang_hooks.finish_incomplete_decl (decl);
 }
 
@@ -383,7 +357,7 @@ bool
 wrapup_global_declaration_2 (tree decl)
 {
   if (TREE_ASM_WRITTEN (decl) || DECL_EXTERNAL (decl)
-      || (TREE_CODE (decl) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (decl)))
+      || (VAR_P (decl) && DECL_HAS_VALUE_EXPR_P (decl)))
     return false;
 
   /* Don't write out static consts, unless we still need them.
@@ -411,7 +385,7 @@ wrapup_global_declaration_2 (tree decl)
      to force a constant to be written if and only if it is
      defined in a main file, as opposed to an include file.  */
 
-  if (TREE_CODE (decl) == VAR_DECL && TREE_STATIC (decl))
+  if (VAR_P (decl) && TREE_STATIC (decl))
     {
       varpool_node *node;
       bool needed = true;
@@ -476,86 +450,6 @@ wrapup_global_declarations (tree *vec, int len)
   return output_something;
 }
 
-/* A subroutine of check_global_declarations.  Issue appropriate warnings
-   for the global declaration DECL.  */
-
-void
-check_global_declaration_1 (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.  */
-  if (TREE_CODE (decl) == FUNCTION_DECL
-      && DECL_INITIAL (decl) == 0
-      && DECL_EXTERNAL (decl)
-      && ! DECL_ARTIFICIAL (decl)
-      && ! TREE_NO_WARNING (decl)
-      && ! TREE_PUBLIC (decl)
-      && (warn_unused_function
-         || TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))))
-    {
-      if (TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)))
-       pedwarn (input_location, 0, "%q+F used but never defined", decl);
-      else
-       warning (OPT_Wunused_function, "%q+F declared %<static%> but never defined", decl);
-      /* This symbol is effectively an "extern" declaration now.  */
-      TREE_PUBLIC (decl) = 1;
-    }
-
-  /* Warn about static fns or vars defined but not used.  */
-  if (((warn_unused_function && TREE_CODE (decl) == FUNCTION_DECL)
-       /* We don't warn about "static const" variables because the
-         "rcs_id" idiom uses that construction.  */
-       || (warn_unused_variable
-          && TREE_CODE (decl) == VAR_DECL && ! TREE_READONLY (decl)))
-      && ! DECL_IN_SYSTEM_HEADER (decl)
-      && ! 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)
-      && ! 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))
-      /* Otherwise, ask the language.  */
-      && lang_hooks.decls.warn_unused_global (decl))
-    warning ((TREE_CODE (decl) == FUNCTION_DECL)
-            ? OPT_Wunused_function
-             : OPT_Wunused_variable,
-            "%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.  */
 
@@ -565,23 +459,42 @@ 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.  */
 
   if (flag_syntax_only || flag_wpa)
     return;
+  /* Reset maximum_field_alignment, it can be adjusted by #pragma pack
+     and this shouldn't influence any types built by the middle-end
+     from now on (like gcov_info_type).  */
+  maximum_field_alignment = initial_max_fld_align * BITS_PER_UNIT;
 
   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;
@@ -604,6 +517,8 @@ compile_file (void)
 
       omp_finish_file ();
 
+      hsa_output_brig ();
+
       output_shared_constant_pool ();
       output_object_blocks ();
       finish_tm_clone_pairs ();
@@ -644,14 +559,14 @@ compile_file (void)
 #if defined ASM_OUTPUT_ALIGNED_DECL_COMMON
       ASM_OUTPUT_ALIGNED_DECL_COMMON (asm_out_file, NULL_TREE,
                                      "__gnu_lto_v1",
-                                     (unsigned HOST_WIDE_INT) 1, 8);
+                                     HOST_WIDE_INT_1U, 8);
 #elif defined ASM_OUTPUT_ALIGNED_COMMON
       ASM_OUTPUT_ALIGNED_COMMON (asm_out_file, "__gnu_lto_v1",
-                                (unsigned HOST_WIDE_INT) 1, 8);
+                                HOST_WIDE_INT_1U, 8);
 #else
       ASM_OUTPUT_COMMON (asm_out_file, "__gnu_lto_v1",
-                        (unsigned HOST_WIDE_INT) 1,
-                        (unsigned HOST_WIDE_INT) 1);
+                        HOST_WIDE_INT_1U,
+                        HOST_WIDE_INT_1U);
 #endif
     }
 
@@ -661,14 +576,14 @@ compile_file (void)
     {
 #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);
+                                     HOST_WIDE_INT_1U, 8);
 #elif defined ASM_OUTPUT_ALIGNED_COMMON
       ASM_OUTPUT_ALIGNED_COMMON (asm_out_file, "__gnu_lto_slim",
-                                (unsigned HOST_WIDE_INT) 1, 8);
+                                HOST_WIDE_INT_1U, 8);
 #else
       ASM_OUTPUT_COMMON (asm_out_file, "__gnu_lto_slim",
-                        (unsigned HOST_WIDE_INT) 1,
-                        (unsigned HOST_WIDE_INT) 1);
+                        HOST_WIDE_INT_1U,
+                        HOST_WIDE_INT_1U);
 #endif
     }
 
@@ -704,10 +619,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__
@@ -717,7 +641,7 @@ print_version (FILE *file, const char *indent)
 #endif
     ;
   static const char fmt2[] =
-    N_("GMP version %s, MPFR version %s, MPC version %s\n");
+    N_("GMP version %s, MPFR version %s, MPC version %s, isl version %s\n");
   static const char fmt3[] =
     N_("%s%swarning: %s header version %s differs from library version %s.\n");
   static const char fmt4[] =
@@ -751,7 +675,15 @@ print_version (FILE *file, const char *indent)
 #endif
   fprintf (file,
           file == stderr ? _(fmt2) : fmt2,
-          GCC_GMP_STRINGIFY_VERSION, MPFR_VERSION_STRING, MPC_VERSION_STRING);
+          GCC_GMP_STRINGIFY_VERSION, MPFR_VERSION_STRING, MPC_VERSION_STRING,
+#ifndef HAVE_isl
+          "none"
+#elif HAVE_ISL_OPTIONS_SET_SCHEDULE_SERIALIZE_SCCS
+          "0.15"
+#else
+          "0.14 or 0.13"
+#endif
+          );
   if (strcmp (GCC_GMP_STRINGIFY_VERSION, gmp_version))
     fprintf (file,
             file == stderr ? _(fmt3) : fmt3,
@@ -767,12 +699,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
@@ -793,7 +729,7 @@ print_to_asm_out_file (print_switch_type type, const char * text)
     case SWITCH_TYPE_DESCRIPTIVE:
       if (ASM_COMMENT_START[0] == 0)
        prepend_sep = false;
-      /* Drop through.  */
+      /* FALLTHRU */
     case SWITCH_TYPE_PASSED:
     case SWITCH_TYPE_ENABLED:
       if (prepend_sep)
@@ -823,7 +759,7 @@ print_to_stderr (print_switch_type type, const char * text)
     case SWITCH_TYPE_PASSED:
     case SWITCH_TYPE_ENABLED:
       fputc (' ', stderr);
-      /* Drop through.  */
+      /* FALLTHRU */
 
     case SWITCH_TYPE_DESCRIPTIVE:
       fputs (text, stderr);
@@ -949,8 +885,8 @@ init_asm_output (const char *name)
               || !strcmp (asm_file_name, HOST_BIT_BUCKET))
        asm_out_file = fopen (asm_file_name, "w");
       else
-       /* Use fatal_error (UNKOWN_LOCATION) instead of just fatal_error to
-          prevent gcc from printing the first line in the current file. */
+       /* 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);
@@ -977,14 +913,16 @@ init_asm_output (const char *name)
                                                   NULL);
            }
          else
-           inform (input_location, "-frecord-gcc-switches is not supported by the current target");
+           inform (UNKNOWN_LOCATION,
+                   "-frecord-gcc-switches is not supported by "
+                   "the current target");
        }
 
       if (flag_verbose_asm)
        {
          /* 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);
        }
@@ -1080,7 +1018,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,
@@ -1118,7 +1056,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;
 }
@@ -1127,7 +1065,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;
 
@@ -1166,28 +1104,31 @@ 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.  */
@@ -1198,6 +1139,7 @@ general_init (const char *argv0)
   linemap_init (line_table, BUILTINS_LOCATION);
   line_table->reallocator = realloc_for_line_map;
   line_table->round_alloc_size = ggc_round_alloc_size;
+  line_table->default_range_bits = 5;
   init_ttree ();
 
   /* Initialize register usage now so switches may override.  */
@@ -1213,7 +1155,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 = ggc_cleared_alloc <symbol_table> ();
+  symtab = new (ggc_cleared_alloc <symbol_table> ()) symbol_table ();
 
   statistics_early_init ();
   finish_params ();
@@ -1268,51 +1210,20 @@ process_options (void)
 
   maximum_field_alignment = initial_max_fld_align * BITS_PER_UNIT;
 
-  /* If DIAGNOSTICS_COLOR_DEFAULT is -1, default to -fdiagnostics-color=auto
-     if GCC_COLORS is in the environment, otherwise default to
-     -fdiagnostics-color=never, for other values default to that
-     -fdiagnostics-color={never,auto,always}.  */
-  if (!global_options_set.x_flag_diagnostics_show_color)
-    switch ((int) DIAGNOSTICS_COLOR_DEFAULT)
-      {
-      case -1:
-       if (!getenv ("GCC_COLORS"))
-         break;
-       /* FALLTHRU */
-      case DIAGNOSTICS_COLOR_AUTO:
-       pp_show_color (global_dc->printer)
-         = colorize_init (DIAGNOSTICS_COLOR_AUTO);
-       break;
-      case DIAGNOSTICS_COLOR_YES:
-       pp_show_color (global_dc->printer)
-         = colorize_init (DIAGNOSTICS_COLOR_YES);
-       break;
-      default:
-       break;
-      }
-
   /* 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.  */
+  location_t saved_location = input_location;
+  input_location = UNKNOWN_LOCATION;
   targetm.target_option.override ();
+  input_location = saved_location;
+
+  if (flag_diagnostics_generate_patch)
+      global_dc->edit_context_ptr = new edit_context ();
 
   /* Avoid any informative notes in the second run of -fcompare-debug.  */
   if (flag_compare_debug) 
@@ -1320,8 +1231,9 @@ process_options (void)
 
   if (flag_section_anchors && !target_supports_section_anchors_p ())
     {
-      warning (OPT_fsection_anchors,
-              "this target does not support %qs", "-fsection-anchors");
+      warning_at (UNKNOWN_LOCATION, OPT_fsection_anchors,
+                 "this target does not support %qs",
+                 "-fsection-anchors");
       flag_section_anchors = 0;
     }
 
@@ -1343,13 +1255,10 @@ process_options (void)
 
 #ifndef HAVE_isl
   if (flag_graphite
+      || flag_loop_nest_optimize
       || flag_graphite_identity
-      || flag_loop_block
-      || flag_loop_interchange
-      || flag_loop_strip_mine
-      || flag_loop_parallelize_all
-      || flag_loop_unroll_jam)
-    sorry ("Graphite loop optimizations cannot be used (ISL is not available)" 
+      || flag_loop_parallelize_all)
+    sorry ("Graphite loop optimizations cannot be used (isl is not available)"
           "(-fgraphite, -fgraphite-identity, -floop-block, "
           "-floop-interchange, -floop-strip-mine, -floop-parallelize-all, "
           "-floop-unroll-and-jam, and -ftree-loop-linear)");
@@ -1358,7 +1267,28 @@ process_options (void)
   if (flag_check_pointer_bounds)
     {
       if (targetm.chkp_bound_mode () == VOIDmode)
-       error ("-fcheck-pointer-bounds is not supported for this target");
+       {
+         error_at (UNKNOWN_LOCATION,
+                   "-fcheck-pointer-bounds is not supported for this target");
+         flag_check_pointer_bounds = 0;
+       }
+
+      if (flag_sanitize & SANITIZE_ADDRESS)
+       {
+         error_at (UNKNOWN_LOCATION,
+                   "-fcheck-pointer-bounds is not supported with "
+                   "Address Sanitizer");
+         flag_check_pointer_bounds = 0;
+       }
+
+      if (flag_sanitize & SANITIZE_BOUNDS)
+       {
+         error_at (UNKNOWN_LOCATION,
+                   "-fcheck-pointer-bounds is not supported with "
+                   "-fsanitize=bounds");
+         flag_check_pointer_bounds = 0;
+       }
+
     }
 
   /* One region RA really helps to decrease the code size.  */
@@ -1369,7 +1299,8 @@ process_options (void)
   if (!abi_version_at_least (2))
     {
       /* -fabi-version=1 support was removed after GCC 4.9.  */
-      error ("%<-fabi-version=1%> is no longer supported");
+      error_at (UNKNOWN_LOCATION,
+               "%<-fabi-version=1%> is no longer supported");
       flag_abi_version = 2;
     }
 
@@ -1380,10 +1311,10 @@ process_options (void)
 
   /* web and rename-registers help when run after loop unrolling.  */
   if (flag_web == AUTODETECT_VALUE)
-    flag_web = flag_unroll_loops || flag_peel_loops;
+    flag_web = flag_unroll_loops;
 
   if (flag_rename_registers == AUTODETECT_VALUE)
-    flag_rename_registers = flag_unroll_loops || flag_peel_loops;
+    flag_rename_registers = flag_unroll_loops;
 
   if (flag_non_call_exceptions)
     flag_asynchronous_unwind_tables = 1;
@@ -1396,12 +1327,12 @@ process_options (void)
   /* Warn about options that are not supported on this machine.  */
 #ifndef INSN_SCHEDULING
   if (flag_schedule_insns || flag_schedule_insns_after_reload)
-    warning (0, "instruction scheduling not supported on this target machine");
-#endif
-#ifndef DELAY_SLOTS
-  if (flag_delayed_branch)
-    warning (0, "this target machine does not have delayed branches");
+    warning_at (UNKNOWN_LOCATION, 0,
+               "instruction scheduling not supported on this target machine");
 #endif
+  if (!DELAY_SLOTS && flag_delayed_branch)
+    warning_at (UNKNOWN_LOCATION, 0,
+               "this target machine does not have delayed branches");
 
   user_label_prefix = USER_LABEL_PREFIX;
   if (flag_leading_underscore != -1)
@@ -1414,15 +1345,16 @@ process_options (void)
          user_label_prefix = flag_leading_underscore ? "_" : "";
        }
       else
-       warning (0, "-f%sleading-underscore not supported on this target machine",
-                flag_leading_underscore ? "" : "no-");
+       warning_at (UNKNOWN_LOCATION, 0,
+                   "-f%sleading-underscore not supported on this "
+                   "target machine", flag_leading_underscore ? "" : "no-");
     }
 
   /* If we are in verbose mode, write out the version and maybe all the
      option flags in use.  */
   if (version_flag)
     {
-      print_version (stderr, "");
+      print_version (stderr, "", true);
       if (! quiet_flag)
        print_switch_values (print_to_stderr);
     }
@@ -1451,14 +1383,16 @@ process_options (void)
       FILE *final_output = fopen (flag_dump_final_insns, "w");
       if (!final_output)
        {
-         error ("could not open final insn dump file %qs: %m",
-                flag_dump_final_insns);
+         error_at (UNKNOWN_LOCATION,
+                   "could not open final insn dump file %qs: %m",
+                   flag_dump_final_insns);
          flag_dump_final_insns = NULL;
        }
       else if (fclose (final_output))
        {
-         error ("could not close zeroed insn dump file %qs: %m",
-                flag_dump_final_insns);
+         error_at (UNKNOWN_LOCATION,
+                   "could not close zeroed insn dump file %qs: %m",
+                   flag_dump_final_insns);
          flag_dump_final_insns = NULL;
        }
     }
@@ -1478,10 +1412,8 @@ process_options (void)
   else if (write_symbols == XCOFF_DEBUG)
     debug_hooks = &xcoff_debug_hooks;
 #endif
-#ifdef SDB_DEBUGGING_INFO
-  else if (write_symbols == SDB_DEBUG)
+  else if (SDB_DEBUGGING_INFO && write_symbols == SDB_DEBUG)
     debug_hooks = &sdb_debug_hooks;
-#endif
 #ifdef DWARF2_DEBUGGING_INFO
   else if (write_symbols == DWARF2_DEBUG)
     debug_hooks = &dwarf2_debug_hooks;
@@ -1490,9 +1422,14 @@ process_options (void)
   else if (write_symbols == VMS_DEBUG || write_symbols == VMS_AND_DWARF2_DEBUG)
     debug_hooks = &vmsdbg_debug_hooks;
 #endif
+#ifdef DWARF2_LINENO_DEBUGGING_INFO
+  else if (write_symbols == DWARF2_DEBUG)
+    debug_hooks = &dwarf2_lineno_debug_hooks;
+#endif
   else
-    error ("target system does not support the %qs debug format",
-          debug_type_names[write_symbols]);
+    error_at (UNKNOWN_LOCATION,
+             "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
      and flag_var_tracking_uninit if the user has not specified them.  */
@@ -1503,11 +1440,13 @@ process_options (void)
          || flag_var_tracking_uninit == 1)
         {
          if (debug_info_level < DINFO_LEVEL_NORMAL)
-           warning (0, "variable tracking requested, but useless unless "
-                    "producing debug info");
+           warning_at (UNKNOWN_LOCATION, 0,
+                       "variable tracking requested, but useless unless "
+                       "producing debug info");
          else
-           warning (0, "variable tracking requested, but not supported "
-                    "by this debug format");
+           warning_at (UNKNOWN_LOCATION, 0,
+                       "variable tracking requested, but not supported "
+                       "by this debug format");
        }
       flag_var_tracking = 0;
       flag_var_tracking_uninit = 0;
@@ -1543,14 +1482,16 @@ process_options (void)
 
   if (flag_var_tracking_assignments
       && (flag_selective_scheduling || flag_selective_scheduling2))
-    warning (0, "var-tracking-assignments changes selective scheduling");
+    warning_at (UNKNOWN_LOCATION, 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
@@ -1559,42 +1500,46 @@ 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 (UNKNOWN_LOCATION,
+                    "can%'t open %s: %m", aux_info_file_name);
     }
 
   if (!targetm_common.have_named_sections)
     {
       if (flag_function_sections)
        {
-         warning (0, "-ffunction-sections not supported for this target");
+         warning_at (UNKNOWN_LOCATION, 0,
+                     "-ffunction-sections not supported for this target");
          flag_function_sections = 0;
        }
       if (flag_data_sections)
        {
-         warning (0, "-fdata-sections not supported for this target");
+         warning_at (UNKNOWN_LOCATION, 0,
+                     "-fdata-sections not supported for this target");
          flag_data_sections = 0;
        }
     }
 
-#ifndef HAVE_prefetch
-  if (flag_prefetch_loop_arrays > 0)
+  if (flag_prefetch_loop_arrays > 0 && !targetm.code_for_prefetch)
     {
-      warning (0, "-fprefetch-loop-arrays not supported for this target");
+      warning_at (UNKNOWN_LOCATION, 0,
+                 "-fprefetch-loop-arrays not supported for this target");
       flag_prefetch_loop_arrays = 0;
     }
-#else
-  if (flag_prefetch_loop_arrays > 0 && !HAVE_prefetch)
+  else if (flag_prefetch_loop_arrays > 0 && !targetm.have_prefetch ())
     {
-      warning (0, "-fprefetch-loop-arrays not supported for this target (try -march switches)");
+      warning_at (UNKNOWN_LOCATION, 0,
+                 "-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 > 0 && optimize_size)
     {
-      warning (0, "-fprefetch-loop-arrays is not supported with -Os");
+      warning_at (UNKNOWN_LOCATION, 0,
+                 "-fprefetch-loop-arrays is not supported with -Os");
       flag_prefetch_loop_arrays = 0;
     }
 
@@ -1605,7 +1550,9 @@ process_options (void)
   /* We cannot reassociate if we want traps or signed zeros.  */
   if (flag_associative_math && (flag_trapping_math || flag_signed_zeros))
     {
-      warning (0, "-fassociative-math disabled; other options take precedence");
+      warning_at (UNKNOWN_LOCATION, 0,
+                 "-fassociative-math disabled; other options take "
+                 "precedence");
       flag_associative_math = 0;
     }
 
@@ -1621,7 +1568,8 @@ process_options (void)
      target already uses a soft frame pointer, the transition is trivial.  */
   if (!FRAME_GROWS_DOWNWARD && flag_stack_protect)
     {
-      warning (0, "-fstack-protector not supported for this target");
+      warning_at (UNKNOWN_LOCATION, 0,
+                 "-fstack-protector not supported for this target");
       flag_stack_protect = 0;
     }
   if (!flag_stack_protect)
@@ -1632,19 +1580,25 @@ process_options (void)
   if ((flag_sanitize & SANITIZE_ADDRESS)
       && !FRAME_GROWS_DOWNWARD)
     {
-      warning (0,
-              "-fsanitize=address and -fsanitize=kernel-address "
-              "are not supported for this target");
+      warning_at (UNKNOWN_LOCATION, 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");
+      warning_at (UNKNOWN_LOCATION, 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 || !targetm.have_prologue () || !targetm.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
@@ -1657,6 +1611,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
@@ -1676,7 +1633,8 @@ backend_init_target (void)
   init_alias_target ();
 
   /* Depends on HARD_FRAME_POINTER_REGNUM.  */
-  init_reload ();
+  if (!ira_use_lra_p)
+    init_reload ();
 
   /* Depends on the enabled attribute.  */
   recog_init ();
@@ -1722,41 +1680,17 @@ backend_init (void)
   init_regs ();
 }
 
-/* Initialize excess precision settings.  */
+/* Initialize excess precision settings.
+
+   We have no need to modify anything here, just keep track of what the
+   user requested.  We'll figure out any appropriate relaxations
+   later.  */
+
 static void
 init_excess_precision (void)
 {
-  /* Adjust excess precision handling based on the target options.  If
-     the front end cannot handle it, flag_excess_precision_cmdline
-     will already have been set accordingly in the post_options
-     hook.  */
   gcc_assert (flag_excess_precision_cmdline != EXCESS_PRECISION_DEFAULT);
   flag_excess_precision = flag_excess_precision_cmdline;
-  if (flag_unsafe_math_optimizations)
-    flag_excess_precision = EXCESS_PRECISION_FAST;
-  if (flag_excess_precision == EXCESS_PRECISION_STANDARD)
-    {
-      int flt_eval_method = TARGET_FLT_EVAL_METHOD;
-      switch (flt_eval_method)
-       {
-       case -1:
-       case 0:
-         /* Either the target acts unpredictably (-1) or has all the
-            operations required not to have excess precision (0).  */
-         flag_excess_precision = EXCESS_PRECISION_FAST;
-         break;
-       case 1:
-       case 2:
-         /* In these cases, predictable excess precision makes
-            sense.  */
-         break;
-       default:
-         /* Any other implementation-defined FLT_EVAL_METHOD values
-            require the compiler to handle the associated excess
-            precision rules in excess_precision_type.  */
-         gcc_unreachable ();
-       }
-    }
 }
 
 /* Initialize things that are both lang-dependent and target-dependent.
@@ -1783,6 +1717,8 @@ static int rtl_initialized;
 void
 initialize_rtl (void)
 {
+  auto_timevar tv (g_timer, TV_INITIALIZE_RTL);
+
   /* Initialization done just once per compilation, but delayed
      till code generation.  */
   if (!rtl_initialized)
@@ -1922,6 +1858,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);
@@ -1937,6 +1874,7 @@ finalize (bool no_backend)
   if (flag_gen_aux_info)
     {
       fclose (aux_info_file);
+      aux_info_file = NULL;
       if (seen_error ())
        unlink (aux_info_file_name);
     }
@@ -1948,13 +1886,17 @@ 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);
+      asm_out_file = NULL;
     }
 
   if (stack_usage_file)
-    fclose (stack_usage_file);
+    {
+      fclose (stack_usage_file);
+      stack_usage_file = NULL;
+    }
 
   if (!no_backend)
     {
@@ -2053,19 +1995,29 @@ do_compile ()
     }
 }
 
-toplev::toplev (bool use_TV_TOTAL)
-  : m_use_TV_TOTAL (use_TV_TOTAL)
+toplev::toplev (timer *external_timer,
+               bool init_signals)
+  : m_use_TV_TOTAL (external_timer == NULL),
+    m_init_signals (init_signals)
 {
-  if (!m_use_TV_TOTAL)
-    start_timevars ();
+  if (external_timer)
+    g_timer = external_timer;
 }
 
 toplev::~toplev ()
 {
-  timevar_stop (TV_TOTAL);
-  timevar_print (stderr);
+  if (g_timer && m_use_TV_TOTAL)
+    {
+      g_timer->stop (TV_TOTAL);
+      g_timer->print (stderr);
+      delete g_timer;
+      g_timer = NULL;
+    }
 }
 
+/* Potentially call timevar_init (which will create g_timevars if it
+   doesn't already exist).  */
+
 void
 toplev::start_timevars ()
 {
@@ -2075,6 +2027,32 @@ toplev::start_timevars ()
   timevar_start (TV_TOTAL);
 }
 
+/* Handle -fself-test.   */
+
+void
+toplev::run_self_tests ()
+{
+  if (no_backend)
+    {
+      error_at (UNKNOWN_LOCATION, "self-tests incompatible with -E");
+      return;
+    }
+#if CHECKING_P
+  /* Reset some state.  */
+  input_location = UNKNOWN_LOCATION;
+  bitmap_obstack_initialize (NULL);
+
+  /* Run the tests; any failures will lead to an abort of the process.
+     Use "make selftests-gdb" to run under the debugger.  */
+  ::selftest::run_tests ();
+
+  /* Cleanup.  */
+  bitmap_obstack_release (NULL);
+#else
+  inform (UNKNOWN_LOCATION, "self-tests are not enabled in this build");
+#endif /* #if CHECKING_P */
+}
+
 /* Entry point of cc1, cc1plus, jc1, f771, etc.
    Exit code is FATAL_EXIT_CODE if can't open files or if there were
    any errors, or SUCCESS_EXIT_CODE if compilation succeeded.
@@ -2091,11 +2069,12 @@ 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.  */
   init_options_once ();
+  init_opts_obstack ();
 
   /* Initialize global options structures; this must be repeated for
      each structure used for parsing options.  */
@@ -2125,7 +2104,7 @@ 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, "");
@@ -2141,14 +2120,29 @@ toplev::main (int argc, char **argv)
   if (warningcount || errorcount || werrorcount)
     print_ignored_options ();
 
+  if (flag_self_test)
+    run_self_tests ();
+
   /* Invoke registered plugin callbacks if any.  Some plugins could
      emit some diagnostics here.  */
   invoke_plugin_callbacks (PLUGIN_FINISH, NULL);
 
+  if (flag_diagnostics_generate_patch)
+    {
+      gcc_assert (global_dc->edit_context_ptr);
+
+      pretty_printer (pp);
+      pp_show_color (&pp) = pp_show_color (global_dc->printer);
+      global_dc->edit_context_ptr->print_diff (&pp, true);
+      pp_flush (&pp);
+    }
+
   diagnostic_finish (global_dc);
 
   finalize_plugins ();
-  location_adhoc_data_fini (line_table);
+
+  after_memory_report = true;
+
   if (seen_error () || werrorcount)
     return (FATAL_EXIT_CODE);
 
@@ -2163,23 +2157,29 @@ 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 ();
-  ipa_reference_c_finalize ();
   ira_costs_c_finalize ();
   params_c_finalize ();
 
   finalize_options_struct (&global_options);
   finalize_options_struct (&global_options_set);
 
+  /* save_decoded_options uses opts_obstack, so these must
+     be cleaned up together.  */
+  obstack_free (&opts_obstack, NULL);
   XDELETEVEC (save_decoded_options);
+  save_decoded_options = NULL;
+  save_decoded_options_count = 0;
 
   /* Clean up the context (and pass_manager etc). */
   delete g;
   g = NULL;
 
-  obstack_free (&opts_obstack, NULL);
 }