re PR driver/36312 (should refuse to overwrite input file with output file)
[platform/upstream/gcc.git] / gcc / toplev.c
index 9e747e5..d3bd35c 100644 (file)
@@ -43,6 +43,10 @@ along with GCC; see the file COPYING3.  If not see
 #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"
@@ -55,6 +59,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 +67,12 @@ 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 "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"
@@ -78,7 +89,15 @@ along with GCC; see the file COPYING3.  If not see
 #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 "ipa-prop.h"
+#include "gcse.h"
+#include "insn-codes.h"
 #include "optabs.h"
+#include "tree-chkp.h"
 
 #if defined(DBX_DEBUGGING_INFO) || defined(XCOFF_DEBUGGING_INFO)
 #include "dbxout.h"
@@ -93,8 +112,10 @@ along with GCC; see the file COPYING3.  If not see
                                   declarations for e.g. AIX 4.x.  */
 #endif
 
+#include <new>
+
 static void general_init (const char *);
-static void do_compile (void);
+static void do_compile ();
 static void process_options (void);
 static void backend_init (void);
 static int lang_dependent_init (const char *);
@@ -282,16 +303,7 @@ init_local_tick (void)
 static void
 init_random_seed (void)
 {
-  if (flag_random_seed)
-    {
-      char *endp;
-
-      /* 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)
+  if (!random_seed)
     random_seed = local_tick ^ getpid ();  /* Old racey fallback method */
 }
 
@@ -314,6 +326,15 @@ set_random_seed (const char *val)
 {
   const char *old = flag_random_seed;
   flag_random_seed = val;
+  if (flag_random_seed)
+    {
+      char *endp;
+
+      /* 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);
+    }
   return old;
 }
 
@@ -393,7 +414,7 @@ wrapup_global_declaration_2 (tree decl)
     {
       varpool_node *node;
       bool needed = true;
-      node = varpool_get_node (decl);
+      node = varpool_node::get (decl);
 
       if (!node && flag_ltrans)
        needed = false;
@@ -401,7 +422,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 */;
@@ -577,6 +598,9 @@ compile_file (void)
       if (flag_sanitize & SANITIZE_THREAD)
        tsan_finish_file ();
 
+      if (flag_check_pointer_bounds)
+       chkp_finish_file ();
+
       output_shared_constant_pool ();
       output_object_blocks ();
       finish_tm_clone_pairs ();
@@ -660,6 +684,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);
 
@@ -914,10 +942,17 @@ 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))
        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. */
+       fatal_error (UNKNOWN_LOCATION,
+                    "output file %s is the same as input 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 %s for writing: %m", asm_file_name);
     }
 
   if (!flag_syntax_only)
@@ -1052,16 +1087,19 @@ output_stack_usage (void)
 
   if (warn_stack_usage >= 0)
     {
+      const location_t loc = DECL_SOURCE_LOCATION (current_function_decl);
+
       if (stack_usage_kind == DYNAMIC)
-       warning (OPT_Wstack_usage_, "stack usage might be unbounded");
+       warning_at (loc, 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);
+           warning_at (loc,
+                       OPT_Wstack_usage_, "stack usage might be %wd bytes",
+                       stack_usage);
          else
-           warning (OPT_Wstack_usage_, "stack usage is %wd bytes",
-                    stack_usage);
+           warning_at (loc, OPT_Wstack_usage_, "stack usage is %wd bytes",
+                       stack_usage);
        }
     }
 }
@@ -1112,11 +1150,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;
@@ -1156,6 +1189,7 @@ general_init (const char *argv0)
      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;
@@ -1175,6 +1209,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> ();
 
   statistics_early_init ();
   finish_params ();
@@ -1272,19 +1307,25 @@ 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, "
+    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)");
 #endif
 
+  if (flag_check_pointer_bounds)
+    {
+      if (targetm.chkp_bound_mode () == VOIDmode)
+       error ("-fcheck-pointer-bounds is not supported for this target");
+    }
+
   /* One region RA really helps to decrease the code size.  */
   if (flag_ira_region == IRA_REGION_AUTODETECT)
     flag_ira_region
@@ -1552,9 +1593,18 @@ 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;
@@ -1604,6 +1654,10 @@ backend_init_target (void)
      on a mode change.  */
   init_expmed ();
   init_lower_subreg ();
+  init_set_costs ();
+
+  init_expr_target ();
+  ira_init ();
 
   /* We may need to recompute regno_save_code[] and regno_restore_code[]
      after a mode change as well.  */
@@ -1682,45 +1736,30 @@ lang_dependent_init_target (void)
      front end is initialized.  It also depends on the HAVE_xxx macros
      generated from the target machine description.  */
   init_optabs ();
-  this_target_rtl->lang_dependent_initialized = false;
+
+  gcc_assert (!this_target_rtl->target_specific_initialized);
 }
 
 /* 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;
-
   /* 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)
-    backend_init_target ();
-  this_target_rtl->target_specific_initialized = true;
-
-  if (this_target_rtl->lang_dependent_initialized)
-    return;
-  this_target_rtl->lang_dependent_initialized = true;
-
-  /* The following initialization functions need to generate rtl, so
-     provide a dummy function context for them.  */
-  init_dummy_function_start ();
-
-  /* Do the target-specific parts of expr initialization.  */
-  init_expr_target ();
-
-  /* Although the actions of these functions are language-independent,
-     they use optabs, so we cannot call them from backend_init.  */
-  init_set_costs ();
-  ira_init ();
-
-  expand_dummy_function_end ();
+    {
+      backend_init_target ();
+      this_target_rtl->target_specific_initialized = true;
+    }
 }
 
 /* Language-dependent initialization.  Returns nonzero on success.  */
@@ -1888,7 +1927,7 @@ finalize (bool no_backend)
 
       g->get_passes ()->finish_optimization_passes ();
 
-      ira_finish_once ();
+      lra_finish_once ();
     }
 
   if (mem_report)
@@ -1901,21 +1940,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
@@ -1924,6 +1974,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 ();
@@ -1935,7 +1995,7 @@ do_compile (void)
 
           ggc_protect_identifiers = true;
 
-          init_cgraph ();
+         symtab->initialize ();
           init_final (main_input_filename);
           coverage_init (aux_base_name);
           statistics_init ();
@@ -1956,12 +2016,30 @@ do_compile (void)
 
       timevar_stop (TV_PHASE_FINALIZE);
     }
+}
+
+toplev::toplev (bool use_TV_TOTAL)
+  : m_use_TV_TOTAL (use_TV_TOTAL)
+{
+  if (!m_use_TV_TOTAL)
+    start_timevars ();
+}
 
-  /* Stop timing and print the times.  */
+toplev::~toplev ()
+{
   timevar_stop (TV_TOTAL);
   timevar_print (stderr);
 }
 
+void
+toplev::start_timevars ()
+{
+  if (time_report || !quiet_flag  || flag_detailed_statistics)
+    timevar_init ();
+
+  timevar_start (TV_TOTAL);
+}
+
 /* 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.
@@ -1969,7 +2047,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.  */
@@ -2019,7 +2097,11 @@ toplev_main (int argc, char **argv)
 
   /* 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 ();
@@ -2037,3 +2119,20 @@ 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;
+
+  cgraph_c_finalize ();
+  cgraphunit_c_finalize ();
+  dwarf2out_c_finalize ();
+  gcse_c_finalize ();
+  ipa_cp_c_finalize ();
+  ipa_reference_c_finalize ();
+  params_c_finalize ();
+}