]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/lto-streamer-out.c
Merge from trunk.
[thirdparty/gcc.git] / gcc / lto-streamer-out.c
index 5649bd8443e6f386c9b974fad8708e269a894ebf..733119f6953262c1b13732b379a102df60a43c38 100644 (file)
@@ -25,15 +25,19 @@ along with GCC; see the file COPYING3.  If not see
 #include "coretypes.h"
 #include "tm.h"
 #include "tree.h"
+#include "stor-layout.h"
+#include "stringpool.h"
 #include "expr.h"
 #include "flags.h"
 #include "params.h"
 #include "input.h"
 #include "hashtab.h"
 #include "basic-block.h"
-#include "tree-flow.h"
+#include "gimple.h"
+#include "gimple-iterator.h"
+#include "gimple-ssa.h"
+#include "tree-ssanames.h"
 #include "tree-pass.h"
-#include "cgraph.h"
 #include "function.h"
 #include "ggc.h"
 #include "diagnostic-core.h"
@@ -124,8 +128,11 @@ output_type_ref (struct output_block *ob, tree node)
 static bool
 tree_is_indexable (tree t)
 {
+  /* Parameters and return values of functions of variably modified types
+     must go to global stream, because they may be used in the type
+     definition.  */
   if (TREE_CODE (t) == PARM_DECL || TREE_CODE (t) == RESULT_DECL)
-    return false;
+    return variably_modified_type_p (TREE_TYPE (DECL_CONTEXT (t)), NULL_TREE);
   else if (TREE_CODE (t) == VAR_DECL && decl_function_context (t)
           && !TREE_STATIC (t))
     return false;
@@ -364,7 +371,7 @@ lto_write_tree (struct output_block *ob, tree expr, bool ref_p)
 {
   if (!lto_is_streamable (expr))
     internal_error ("tree code %qs is not supported in LTO streams",
-                   tree_code_name[TREE_CODE (expr)]);
+                   get_tree_code_name (TREE_CODE (expr)));
 
   /* Write the header, containing everything needed to materialize
      EXPR on the reading side.  */
@@ -642,9 +649,8 @@ DFS_write_tree_body (struct output_block *ob,
       FOR_EACH_VEC_SAFE_ELT (BINFO_BASE_ACCESSES (expr), i, t)
        DFS_follow_tree_edge (t);
 
-      DFS_follow_tree_edge (BINFO_INHERITANCE_CHAIN (expr));
-      DFS_follow_tree_edge (BINFO_SUBVTT_INDEX (expr));
-      DFS_follow_tree_edge (BINFO_VPTR_INDEX (expr));
+      /* Do not walk BINFO_INHERITANCE_CHAIN, BINFO_SUBVTT_INDEX
+        and BINFO_VPTR_INDEX; these are used by C++ FE only.  */
     }
 
   if (CODE_CONTAINS_STRUCT (code, TS_CONSTRUCTOR))
@@ -708,8 +714,11 @@ hash_tree (struct streamer_tree_cache_d *cache, tree t)
 
   if (CODE_CONTAINS_STRUCT (code, TS_INT_CST))
     {
-      v = iterative_hash_host_wide_int (TREE_INT_CST_LOW (t), v);
-      v = iterative_hash_host_wide_int (TREE_INT_CST_HIGH (t), v);
+      int i; 
+      v = iterative_hash_host_wide_int (TREE_INT_CST_NUNITS (t), v);
+      v = iterative_hash_host_wide_int (TREE_INT_CST_EXT_NUNITS (t), v);
+      for (i = 0; i < TREE_INT_CST_NUNITS (t); i++)
+       v = iterative_hash_host_wide_int (TREE_INT_CST_ELT (t, i), v);
     }
 
   if (CODE_CONTAINS_STRUCT (code, TS_REAL_CST))
@@ -748,7 +757,6 @@ hash_tree (struct streamer_tree_cache_d *cache, tree t)
       v = iterative_hash_host_wide_int (DECL_ALIGN (t), v);
       if (code == LABEL_DECL)
        {
-         v = iterative_hash_host_wide_int (DECL_ERROR_ISSUED (t), v);
          v = iterative_hash_host_wide_int (EH_LANDING_PAD_NR (t), v);
          v = iterative_hash_host_wide_int (LABEL_DECL_UID (t), v);
        }
@@ -781,23 +789,27 @@ hash_tree (struct streamer_tree_cache_d *cache, tree t)
 
   if (CODE_CONTAINS_STRUCT (code, TS_DECL_WITH_VIS))
     {
-      v = iterative_hash_host_wide_int (DECL_DEFER_OUTPUT (t)
-                                       | (DECL_COMMON (t) << 1)
-                                       | (DECL_DLLIMPORT_P (t) << 2)
-                                       | (DECL_WEAK (t) << 3)
-                                       | (DECL_SEEN_IN_BIND_EXPR_P (t) << 4)
-                                       | (DECL_COMDAT (t) << 5)
+      v = iterative_hash_host_wide_int ((DECL_COMMON (t))
+                                       | (DECL_DLLIMPORT_P (t) << 1)
+                                       | (DECL_WEAK (t) << 2)
+                                       | (DECL_SEEN_IN_BIND_EXPR_P (t) << 3)
+                                       | (DECL_COMDAT (t) << 4)
                                        | (DECL_VISIBILITY_SPECIFIED (t) << 6),
                                        v);
       v = iterative_hash_host_wide_int (DECL_VISIBILITY (t), v);
       if (code == VAR_DECL)
        {
+         /* DECL_IN_TEXT_SECTION is set during final asm output only.  */
          v = iterative_hash_host_wide_int (DECL_HARD_REGISTER (t)
-                                           | (DECL_IN_TEXT_SECTION (t) << 1)
-                                           | (DECL_IN_CONSTANT_POOL (t) << 2),
+                                           | (DECL_IN_CONSTANT_POOL (t) << 1),
                                            v);
          v = iterative_hash_host_wide_int (DECL_TLS_MODEL (t), v);
        }
+      if (TREE_CODE (t) == FUNCTION_DECL)
+       v = iterative_hash_host_wide_int (DECL_FINAL_P (t)
+                                         | (DECL_CXX_CONSTRUCTOR_P (t) << 1)
+                                         | (DECL_CXX_DESTRUCTOR_P (t) << 2),
+                                         v);
       if (VAR_OR_FUNCTION_DECL_P (t))
        v = iterative_hash_host_wide_int (DECL_INIT_PRIORITY (t), v);
     }
@@ -838,7 +850,10 @@ hash_tree (struct streamer_tree_cache_d *cache, tree t)
                                        | (TYPE_USER_ALIGN (t) << 5)
                                        | (TYPE_READONLY (t) << 6), v);
       if (RECORD_OR_UNION_TYPE_P (t))
-       v = iterative_hash_host_wide_int (TYPE_TRANSPARENT_AGGR (t), v);
+       {
+         v = iterative_hash_host_wide_int (TYPE_TRANSPARENT_AGGR (t)
+                                           | (TYPE_FINAL_P (t) << 1), v);
+       }
       else if (code == ARRAY_TYPE)
        v = iterative_hash_host_wide_int (TYPE_NONALIASED_COMPONENT (t), v);
       v = iterative_hash_host_wide_int (TYPE_PRECISION (t), v);
@@ -1021,9 +1036,8 @@ hash_tree (struct streamer_tree_cache_d *cache, tree t)
       visit (BINFO_VPTR_FIELD (t));
       FOR_EACH_VEC_SAFE_ELT (BINFO_BASE_ACCESSES (t), i, b)
        visit (b);
-      visit (BINFO_INHERITANCE_CHAIN (t));
-      visit (BINFO_SUBVTT_INDEX (t));
-      visit (BINFO_VPTR_INDEX (t));
+      /* Do not walk BINFO_INHERITANCE_CHAIN, BINFO_SUBVTT_INDEX
+        and BINFO_VPTR_INDEX; these are used by C++ FE only.  */
     }
 
   if (CODE_CONTAINS_STRUCT (code, TS_CONSTRUCTOR))
@@ -1234,7 +1248,7 @@ DFS_write_tree (struct output_block *ob, sccs *from_state,
                  if (!lto_is_streamable (t))
                    internal_error ("tree code %qs is not supported "
                                    "in LTO streams",
-                                   tree_code_name[TREE_CODE (t)]);
+                                   get_tree_code_name (TREE_CODE (t)));
 
                  gcc_checking_assert (!streamer_handle_as_builtin_p (t));
 
@@ -1583,7 +1597,7 @@ output_cfg (struct output_block *ob, struct function *fn)
 
   streamer_write_hwi (ob, -1);
 
-  bb = ENTRY_BLOCK_PTR;
+  bb = ENTRY_BLOCK_PTR_FOR_FN (cfun);
   while (bb->next_bb)
     {
       streamer_write_hwi (ob, bb->next_bb->index);
@@ -1620,14 +1634,24 @@ output_cfg (struct output_block *ob, struct function *fn)
       streamer_write_hwi (ob, loop->any_upper_bound);
       if (loop->any_upper_bound)
        {
-         streamer_write_uhwi (ob, loop->nb_iterations_upper_bound.low);
-         streamer_write_hwi (ob, loop->nb_iterations_upper_bound.high);
+         int len = loop->nb_iterations_upper_bound.get_len ();
+         int i;
+
+         streamer_write_uhwi (ob, loop->nb_iterations_upper_bound.get_precision ());
+         streamer_write_uhwi (ob, len);
+         for (i = 0; i < len; i++)
+           streamer_write_hwi (ob, loop->nb_iterations_upper_bound.elt (i));
        }
       streamer_write_hwi (ob, loop->any_estimate);
       if (loop->any_estimate)
        {
-         streamer_write_uhwi (ob, loop->nb_iterations_estimate.low);
-         streamer_write_hwi (ob, loop->nb_iterations_estimate.high);
+         int len = loop->nb_iterations_estimate.get_len ();
+         int i;
+
+         streamer_write_uhwi (ob, loop->nb_iterations_estimate.get_precision ());
+         streamer_write_uhwi (ob, len);
+         for (i = 0; i < len; i++)
+           streamer_write_hwi (ob, loop->nb_iterations_estimate.elt (i));
        }
     }
 
@@ -1743,7 +1767,7 @@ output_function (struct cgraph_node *node)
   basic_block bb;
   struct output_block *ob;
 
-  function = node->symbol.decl;
+  function = node->decl;
   fn = DECL_STRUCT_FUNCTION (function);
   ob = create_output_block (LTO_section_function_body);
 
@@ -1792,12 +1816,32 @@ output_function (struct cgraph_node *node)
       FOR_ALL_BB (bb)
        {
          gimple_stmt_iterator gsi;
+         for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+           {
+             gimple stmt = gsi_stmt (gsi);
+
+             /* Virtual PHIs are not going to be streamed.  */
+             if (!virtual_operand_p (gimple_phi_result (stmt)))
+               gimple_set_uid (stmt, inc_gimple_stmt_max_uid (cfun));
+           }
          for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
            {
              gimple stmt = gsi_stmt (gsi);
              gimple_set_uid (stmt, inc_gimple_stmt_max_uid (cfun));
            }
        }
+      /* To avoid keeping duplicate gimple IDs in the statements, renumber
+        virtual phis now.  */
+      FOR_ALL_BB (bb)
+       {
+         gimple_stmt_iterator gsi;
+         for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+           {
+             gimple stmt = gsi_stmt (gsi);
+             if (virtual_operand_p (gimple_phi_result (stmt)))
+               gimple_set_uid (stmt, inc_gimple_stmt_max_uid (cfun));
+           }
+       }
 
       /* Output the code for the function.  */
       FOR_ALL_BB_FN (bb, fn)
@@ -1882,8 +1926,8 @@ lto_output_toplevel_asms (void)
 static void
 copy_function (struct cgraph_node *node)
 {
-  tree function = node->symbol.decl;
-  struct lto_file_decl_data *file_data = node->symbol.lto_file_data;
+  tree function = node->decl;
+  struct lto_file_decl_data *file_data = node->lto_file_data;
   struct lto_output_stream *output_stream = XCNEW (struct lto_output_stream);
   const char *data;
   size_t len;
@@ -1910,7 +1954,7 @@ copy_function (struct cgraph_node *node)
 
   /* Copy decls. */
   in_state =
-    lto_get_function_in_decl_state (node->symbol.lto_file_data, function);
+    lto_get_function_in_decl_state (node->lto_file_data, function);
   gcc_assert (in_state);
 
   for (i = 0; i < LTO_N_DECL_STREAMS; i++)
@@ -1937,7 +1981,7 @@ copy_function (struct cgraph_node *node)
 
 /* Main entry point from the pass manager.  */
 
-static void
+void
 lto_output (void)
 {
   struct lto_out_decl_state *decl_state;
@@ -1954,26 +1998,25 @@ lto_output (void)
   /* Process only the functions with bodies.  */
   for (i = 0; i < n_nodes; i++)
     {
-      symtab_node snode = lto_symtab_encoder_deref (encoder, i);
+      symtab_node *snode = lto_symtab_encoder_deref (encoder, i);
       cgraph_node *node = dyn_cast <cgraph_node> (snode);
       if (node
          && lto_symtab_encoder_encode_body_p (encoder, node)
-         && !node->symbol.alias
-         && !node->thunk.thunk_p)
+         && !node->alias)
        {
 #ifdef ENABLE_CHECKING
-         gcc_assert (!bitmap_bit_p (output, DECL_UID (node->symbol.decl)));
-         bitmap_set_bit (output, DECL_UID (node->symbol.decl));
+         gcc_assert (!bitmap_bit_p (output, DECL_UID (node->decl)));
+         bitmap_set_bit (output, DECL_UID (node->decl));
 #endif
          decl_state = lto_new_out_decl_state ();
          lto_push_out_decl_state (decl_state);
-         if (gimple_has_body_p (node->symbol.decl) || !flag_wpa)
+         if (gimple_has_body_p (node->decl) || !flag_wpa)
            output_function (node);
          else
            copy_function (node);
          gcc_assert (lto_get_out_decl_state () == decl_state);
          lto_pop_out_decl_state ();
-         lto_record_function_out_decl_state (node->symbol.decl, decl_state);
+         lto_record_function_out_decl_state (node->decl, decl_state);
        }
     }
 
@@ -1988,53 +2031,6 @@ lto_output (void)
 #endif
 }
 
-namespace {
-
-const pass_data pass_data_ipa_lto_gimple_out =
-{
-  IPA_PASS, /* type */
-  "lto_gimple_out", /* name */
-  OPTGROUP_NONE, /* optinfo_flags */
-  true, /* has_gate */
-  false, /* has_execute */
-  TV_IPA_LTO_GIMPLE_OUT, /* tv_id */
-  0, /* properties_required */
-  0, /* properties_provided */
-  0, /* properties_destroyed */
-  0, /* todo_flags_start */
-  0, /* todo_flags_finish */
-};
-
-class pass_ipa_lto_gimple_out : public ipa_opt_pass_d
-{
-public:
-  pass_ipa_lto_gimple_out(gcc::context *ctxt)
-    : ipa_opt_pass_d(pass_data_ipa_lto_gimple_out, ctxt,
-                    NULL, /* generate_summary */
-                    lto_output, /* write_summary */
-                    NULL, /* read_summary */
-                    lto_output, /* write_optimization_summary */
-                    NULL, /* read_optimization_summary */
-                    NULL, /* stmt_fixup */
-                    0, /* function_transform_todo_flags_start */
-                    NULL, /* function_transform */
-                    NULL) /* variable_transform */
-  {}
-
-  /* opt_pass methods: */
-  bool gate () { return gate_lto_out (); }
-
-}; // class pass_ipa_lto_gimple_out
-
-} // anon namespace
-
-ipa_opt_pass_d *
-make_pass_ipa_lto_gimple_out (gcc::context *ctxt)
-{
-  return new pass_ipa_lto_gimple_out (ctxt);
-}
-
-
 /* Write each node in encoded by ENCODER to OB, as well as those reachable
    from it and required for correct representation of its semantics.
    Each node in ENCODER must be a global declaration or a type.  A node
@@ -2205,10 +2201,10 @@ write_symbol (struct streamer_tree_cache_d *cache,
 
       /* When something is defined, it should have node attached.  */
       gcc_assert (alias || TREE_CODE (t) != VAR_DECL
-                 || varpool_get_node (t)->symbol.definition);
+                 || varpool_get_node (t)->definition);
       gcc_assert (alias || TREE_CODE (t) != FUNCTION_DECL
                  || (cgraph_get_node (t)
-                     && cgraph_get_node (t)->symbol.definition));
+                     && cgraph_get_node (t)->definition));
     }
 
   /* Imitate what default_elf_asm_output_external do.
@@ -2222,7 +2218,7 @@ write_symbol (struct streamer_tree_cache_d *cache,
       && !targetm.binds_local_p (t))
     visibility = GCCPV_DEFAULT;
   else
-    switch (DECL_VISIBILITY(t))
+    switch (DECL_VISIBILITY (t))
       {
       case VISIBILITY_DEFAULT:
        visibility = GCCPV_DEFAULT;
@@ -2263,7 +2259,7 @@ write_symbol (struct streamer_tree_cache_d *cache,
 /* Return true if NODE should appear in the plugin symbol table.  */
 
 bool
-output_symbol_p (symtab_node node)
+output_symbol_p (symtab_node *node)
 {
   struct cgraph_node *cnode;
   if (!symtab_real_symbol_p (node))
@@ -2272,7 +2268,7 @@ output_symbol_p (symtab_node node)
      and devirtualization.  We do not want to see them in symbol table as
      references unless they are really used.  */
   cnode = dyn_cast <cgraph_node> (node);
-  if (cnode && (!node->symbol.definition || DECL_EXTERNAL (cnode->symbol.decl))
+  if (cnode && (!node->definition || DECL_EXTERNAL (cnode->decl))
       && cnode->callers)
     return true;
 
@@ -2280,18 +2276,18 @@ output_symbol_p (symtab_node node)
     part of the compilation unit until they are used by folding.  Some symbols,
     like references to external construction vtables can not be referred to at all.
     We decide this at can_refer_decl_in_current_unit_p.  */
- if (!node->symbol.definition || DECL_EXTERNAL (node->symbol.decl))
+ if (!node->definition || DECL_EXTERNAL (node->decl))
     {
       int i;
       struct ipa_ref *ref;
-      for (i = 0; ipa_ref_list_referring_iterate (&node->symbol.ref_list,
+      for (i = 0; ipa_ref_list_referring_iterate (&node->ref_list,
                                                  i, ref); i++)
        {
          if (ref->use == IPA_REF_ALIAS)
            continue;
           if (is_a <cgraph_node> (ref->referring))
            return true;
-         if (!DECL_EXTERNAL (ref->referring->symbol.decl))
+         if (!DECL_EXTERNAL (ref->referring->decl))
            return true;
        }
       return false;
@@ -2325,20 +2321,20 @@ produce_symtab (struct output_block *ob)
   for (lsei = lsei_start (encoder);
        !lsei_end_p (lsei); lsei_next (&lsei))
     {
-      symtab_node node = lsei_node (lsei);
+      symtab_node *node = lsei_node (lsei);
 
-      if (!output_symbol_p (node) || DECL_EXTERNAL (node->symbol.decl))
+      if (!output_symbol_p (node) || DECL_EXTERNAL (node->decl))
        continue;
-      write_symbol (cache, &stream, node->symbol.decl, seen, false);
+      write_symbol (cache, &stream, node->decl, seen, false);
     }
   for (lsei = lsei_start (encoder);
        !lsei_end_p (lsei); lsei_next (&lsei))
     {
-      symtab_node node = lsei_node (lsei);
+      symtab_node *node = lsei_node (lsei);
 
-      if (!output_symbol_p (node) || !DECL_EXTERNAL (node->symbol.decl))
+      if (!output_symbol_p (node) || !DECL_EXTERNAL (node->decl))
        continue;
-      write_symbol (cache, &stream, node->symbol.decl, seen, false);
+      write_symbol (cache, &stream, node->decl, seen, false);
     }
 
   lto_write_stream (&stream);
@@ -2354,7 +2350,7 @@ produce_symtab (struct output_block *ob)
    this file to be written in to a section that can then be read in to
    recover these on other side.  */
 
-static void
+void
 produce_asm_for_decls (void)
 {
   struct lto_out_decl_state *out_state;
@@ -2432,7 +2428,7 @@ produce_asm_for_decls (void)
       lto_output_decl_state_refs (ob, decl_state_stream, fn_out_state);
     }
   lto_write_stream (decl_state_stream);
-  free(decl_state_stream);
+  free (decl_state_stream);
 
   lto_write_stream (ob->main_stream);
   lto_write_stream (ob->string_stream);
@@ -2458,50 +2454,3 @@ produce_asm_for_decls (void)
   lto_function_decl_states.release ();
   destroy_output_block (ob);
 }
-
-
-namespace {
-
-const pass_data pass_data_ipa_lto_finish_out =
-{
-  IPA_PASS, /* type */
-  "lto_decls_out", /* name */
-  OPTGROUP_NONE, /* optinfo_flags */
-  true, /* has_gate */
-  false, /* has_execute */
-  TV_IPA_LTO_DECL_OUT, /* tv_id */
-  0, /* properties_required */
-  0, /* properties_provided */
-  0, /* properties_destroyed */
-  0, /* todo_flags_start */
-  0, /* todo_flags_finish */
-};
-
-class pass_ipa_lto_finish_out : public ipa_opt_pass_d
-{
-public:
-  pass_ipa_lto_finish_out(gcc::context *ctxt)
-    : ipa_opt_pass_d(pass_data_ipa_lto_finish_out, ctxt,
-                    NULL, /* generate_summary */
-                    produce_asm_for_decls, /* write_summary */
-                    NULL, /* read_summary */
-                    produce_asm_for_decls, /* write_optimization_summary */
-                    NULL, /* read_optimization_summary */
-                    NULL, /* stmt_fixup */
-                    0, /* function_transform_todo_flags_start */
-                    NULL, /* function_transform */
-                    NULL) /* variable_transform */
-  {}
-
-  /* opt_pass methods: */
-  bool gate () { return gate_lto_out (); }
-
-}; // class pass_ipa_lto_finish_out
-
-} // anon namespace
-
-ipa_opt_pass_d *
-make_pass_ipa_lto_finish_out (gcc::context *ctxt)
-{
-  return new pass_ipa_lto_finish_out (ctxt);
-}