OSDN Git Service

dwarf2cfi: Reset args_size properly across abnormal edges.
[pf3gnuchains/gcc-fork.git] / gcc / lto-streamer-out.c
index 3d42483..6345d83 100644 (file)
@@ -340,7 +340,10 @@ pack_ts_base_value_fields (struct bitpack_d *bp, tree expr)
     bp_pack_value (bp, 0, 1);
   /* We write debug info two times, do not confuse the second one.  */
   bp_pack_value (bp, TYPE_P (expr) ? 0 : TREE_ASM_WRITTEN (expr), 1);
-  bp_pack_value (bp, TREE_NO_WARNING (expr), 1);
+  if (TYPE_P (expr))
+    bp_pack_value (bp, TYPE_ARTIFICIAL (expr), 1);
+  else
+    bp_pack_value (bp, TREE_NO_WARNING (expr), 1);
   bp_pack_value (bp, TREE_USED (expr), 1);
   bp_pack_value (bp, TREE_NOTHROW (expr), 1);
   bp_pack_value (bp, TREE_STATIC (expr), 1);
@@ -589,26 +592,11 @@ pack_value_fields (struct bitpack_d *bp, tree expr)
   if (CODE_CONTAINS_STRUCT (code, TS_BLOCK))
     pack_ts_block_value_fields (bp, expr);
 
-  if (CODE_CONTAINS_STRUCT (code, TS_SSA_NAME))
-    {
-      /* We only stream the version number of SSA names.  */
-      gcc_unreachable ();
-    }
-
-  if (CODE_CONTAINS_STRUCT (code, TS_STATEMENT_LIST))
-    {
-      /* This is only used by GENERIC.  */
-      gcc_unreachable ();
-    }
-
-  if (CODE_CONTAINS_STRUCT (code, TS_OMP_CLAUSE))
-    {
-      /* This is only used by High GIMPLE.  */
-      gcc_unreachable ();
-    }
-
   if (CODE_CONTAINS_STRUCT (code, TS_TRANSLATION_UNIT_DECL))
     pack_ts_translation_unit_decl_value_fields (bp, expr);
+
+  if (streamer_hooks.pack_value_fields)
+    streamer_hooks.pack_value_fields (bp, expr);
 }
 
 
@@ -772,9 +760,22 @@ lto_output_tree_ref (struct output_block *ob, tree expr)
       break;
 
     default:
-      /* No other node is indexable, so it should have been handled
-        by lto_output_tree.  */
-      gcc_unreachable ();
+      {
+       /* See if the streamer allows this node to be indexable
+          like other global declarations.  */
+       if (streamer_hooks.indexable_with_decls_p
+           && streamer_hooks.indexable_with_decls_p (expr))
+         {
+           output_record_start (ob, LTO_global_decl_ref);
+           lto_output_var_decl_index (ob->decl_state, ob->main_stream, expr);
+         }
+       else
+         {
+           /* No other node is indexable, so it should have been
+             handled by lto_output_tree.  */
+           gcc_unreachable ();
+         }
+      }
     }
 }
 
@@ -883,27 +884,11 @@ lto_output_ts_decl_common_tree_pointers (struct output_block *ob, tree expr,
   lto_output_tree_or_ref (ob, DECL_SIZE (expr), ref_p);
   lto_output_tree_or_ref (ob, DECL_SIZE_UNIT (expr), ref_p);
 
-  if (TREE_CODE (expr) != FUNCTION_DECL
-      && TREE_CODE (expr) != TRANSLATION_UNIT_DECL)
-    {
-      tree initial = DECL_INITIAL (expr);
-      if (TREE_CODE (expr) == VAR_DECL
-         && (TREE_STATIC (expr) || DECL_EXTERNAL (expr))
-         && initial)
-       {
-         lto_varpool_encoder_t varpool_encoder = ob->decl_state->varpool_node_encoder;
-         struct varpool_node *vnode = varpool_get_node (expr);
-         if (!vnode)
-           initial = error_mark_node;
-         else if (!lto_varpool_encoder_encode_initializer_p (varpool_encoder,
-                                                             vnode))
-           initial = NULL;
-       }
-    
-      lto_output_tree_or_ref (ob, initial, ref_p);
-    }
+  /* Note, DECL_INITIAL is not handled here.  Since DECL_INITIAL needs
+     special handling in LTO, it must be handled by streamer hooks.  */
 
   lto_output_tree_or_ref (ob, DECL_ATTRIBUTES (expr), ref_p);
+
   /* Do not stream DECL_ABSTRACT_ORIGIN.  We cannot handle debug information
      for early inlining so drop it on the floor instead of ICEing in
      dwarf2out.c.  */
@@ -1135,7 +1120,11 @@ lto_output_ts_binfo_tree_pointers (struct output_block *ob, tree expr,
 
   lto_output_tree_or_ref (ob, BINFO_OFFSET (expr), ref_p);
   lto_output_tree_or_ref (ob, BINFO_VTABLE (expr), ref_p);
-  lto_output_tree_or_ref (ob, BINFO_VIRTUALS (expr), ref_p);
+  /* BINFO_VIRTUALS is used to drive type based devirtualizatoin.  It often links
+     together large portions of programs making it harder to partition.  Becuase
+     devirtualization is interesting before inlining, only, there is no real
+     need to ship it into ltrans partition.  */
+  lto_output_tree_or_ref (ob, flag_wpa ? NULL : BINFO_VIRTUALS (expr), ref_p);
   lto_output_tree_or_ref (ob, BINFO_VPTR_FIELD (expr), ref_p);
 
   output_uleb128 (ob, VEC_length (tree, BINFO_BASE_ACCESSES (expr)));
@@ -1251,12 +1240,6 @@ lto_output_tree_pointers (struct output_block *ob, tree expr, bool ref_p)
   if (CODE_CONTAINS_STRUCT (code, TS_EXP))
     lto_output_ts_exp_tree_pointers (ob, expr, ref_p);
 
-  if (CODE_CONTAINS_STRUCT (code, TS_SSA_NAME))
-    {
-      /* We only stream the version number of SSA names.  */
-      gcc_unreachable ();
-    }
-
   if (CODE_CONTAINS_STRUCT (code, TS_BLOCK))
     lto_output_ts_block_tree_pointers (ob, expr, ref_p);
 
@@ -1266,21 +1249,6 @@ lto_output_tree_pointers (struct output_block *ob, tree expr, bool ref_p)
   if (CODE_CONTAINS_STRUCT (code, TS_CONSTRUCTOR))
     lto_output_ts_constructor_tree_pointers (ob, expr, ref_p);
 
-  if (CODE_CONTAINS_STRUCT (code, TS_STATEMENT_LIST))
-    {
-      /* This should only appear in GENERIC.  */
-      gcc_unreachable ();
-    }
-
-  if (CODE_CONTAINS_STRUCT (code, TS_OMP_CLAUSE))
-    {
-      /* This should only appear in High GIMPLE.  */
-      gcc_unreachable ();
-    }
-
-  if (CODE_CONTAINS_STRUCT (code, TS_OPTIMIZATION))
-    sorry ("gimple bytecode streams do not support the optimization attribute");
-
   if (CODE_CONTAINS_STRUCT (code, TS_TARGET_OPTION))
     lto_output_ts_target_option (ob, expr);
 
@@ -1300,11 +1268,11 @@ lto_output_tree_header (struct output_block *ob, tree expr)
   enum LTO_tags tag;
   enum tree_code code;
 
-  /* We should not see any non-GIMPLE tree nodes here.  */
+  /* We should not see any tree nodes not handled by the streamer.  */
   code = TREE_CODE (expr);
-  if (!lto_is_streamable (expr))
-    internal_error ("tree code %qs is not supported in gimple streams",
-                   tree_code_name[code]);
+  if (!streamer_hooks.is_streamable (expr))
+    internal_error ("tree code %qs is not supported in %s streams",
+                   tree_code_name[code], streamer_hooks.name);
 
   /* The header of a tree node consists of its tag, the size of
      the node, and any other information needed to instantiate
@@ -1333,6 +1301,11 @@ lto_output_tree_header (struct output_block *ob, tree expr)
     output_sleb128 (ob, TREE_VEC_LENGTH (expr));
   else if (CODE_CONTAINS_STRUCT (code, TS_BINFO))
     output_uleb128 (ob, BINFO_N_BASE_BINFOS (expr));
+
+  /* Allow the streamer to write any streamer-specific information
+     needed to instantiate the node when reading.  */
+  if (streamer_hooks.output_tree_header)
+    streamer_hooks.output_tree_header (ob, expr);
 }
 
 
@@ -1394,11 +1367,49 @@ lto_write_tree (struct output_block *ob, tree expr, bool ref_p)
   /* Write all the pointer fields in EXPR.  */
   lto_output_tree_pointers (ob, expr, ref_p);
 
+  /* Call back into the streaming module to see if it needs to write
+     anything that was not written by the common streamer.  */
+  if (streamer_hooks.write_tree)
+    streamer_hooks.write_tree (ob, expr, ref_p);
+
   /* Mark the end of EXPR.  */
   output_zero (ob);
 }
 
 
+/* GIMPLE hook for writing GIMPLE-specific parts of trees.  OB, EXPR
+   and REF_P are as in lto_write_tree.  */
+
+void
+lto_streamer_write_tree (struct output_block *ob, tree expr, bool ref_p)
+{
+  if (DECL_P (expr)
+      && TREE_CODE (expr) != FUNCTION_DECL
+      && TREE_CODE (expr) != TRANSLATION_UNIT_DECL)
+    {
+      /* Handle DECL_INITIAL for symbols.  */
+      tree initial = DECL_INITIAL (expr);
+      if (TREE_CODE (expr) == VAR_DECL
+         && (TREE_STATIC (expr) || DECL_EXTERNAL (expr))
+         && initial)
+       {
+         lto_varpool_encoder_t varpool_encoder;
+         struct varpool_node *vnode;
+
+         varpool_encoder = ob->decl_state->varpool_node_encoder;
+         vnode = varpool_get_node (expr);
+         if (!vnode)
+           initial = error_mark_node;
+         else if (!lto_varpool_encoder_encode_initializer_p (varpool_encoder,
+                                                             vnode))
+           initial = NULL;
+       }
+
+      lto_output_tree_or_ref (ob, initial, ref_p);
+    }
+}
+
+
 /* Emit the integer constant CST to output block OB.  If REF_P is true,
    CST's type will be emitted as a reference.  */
 
@@ -2227,15 +2238,6 @@ copy_function (struct cgraph_node *node)
 }
 
 
-/* Initialize the LTO writer.  */
-
-static void
-lto_writer_init (void)
-{
-  lto_streamer_init ();
-}
-
-
 /* Main entry point from the pass manager.  */
 
 static void
@@ -2249,7 +2251,8 @@ lto_output (cgraph_node_set set, varpool_node_set vset)
   int i, n_nodes;
   lto_cgraph_encoder_t encoder = lto_get_out_decl_state ()->cgraph_node_encoder;
 
-  lto_writer_init ();
+  /* Initialize the streamer.  */
+  lto_streamer_init ();
 
   n_nodes = lto_cgraph_encoder_size (encoder);
   /* Process only the functions with bodies.  */
@@ -2257,6 +2260,7 @@ lto_output (cgraph_node_set set, varpool_node_set vset)
     {
       node = lto_cgraph_encoder_deref (encoder, i);
       if (lto_cgraph_encoder_encode_body_p (encoder, node)
+         && !node->alias
          && !node->thunk.thunk_p)
        {
 #ifdef ENABLE_CHECKING
@@ -2301,7 +2305,7 @@ struct ipa_opt_pass_d pass_ipa_lto_gimple_out =
   0,                                   /* properties_provided */
   0,                                   /* properties_destroyed */
   0,                                   /* todo_flags_start */
-  TODO_dump_func                        /* todo_flags_finish */
+  0                                     /* todo_flags_finish */
  },
  NULL,                                 /* generate_summary */
  lto_output,                                   /* write_summary */
@@ -2555,8 +2559,8 @@ produce_symtab (struct output_block *ob,
   struct lto_streamer_cache_d *cache = ob->writer_cache;
   char *section_name = lto_get_section_name (LTO_section_symtab, NULL, NULL);
   struct pointer_set_t *seen;
-  struct cgraph_node *node, *alias;
-  struct varpool_node *vnode, *valias;
+  struct cgraph_node *node;
+  struct varpool_node *vnode;
   struct lto_output_stream stream;
   lto_varpool_encoder_t varpool_encoder = ob->decl_state->varpool_node_encoder;
   lto_cgraph_encoder_t encoder = ob->decl_state->cgraph_node_encoder;
@@ -2585,11 +2589,9 @@ produce_symtab (struct output_block *ob,
       if (DECL_COMDAT (node->decl)
          && cgraph_comdat_can_be_unshared_p (node))
        continue;
-      if (node->alias || node->global.inlined_to)
+      if ((node->alias && !node->thunk.alias) || node->global.inlined_to)
        continue;
       write_symbol (cache, &stream, node->decl, seen, false);
-      for (alias = node->same_body; alias; alias = alias->next)
-        write_symbol (cache, &stream, alias->decl, seen, true);
     }
   for (i = 0; i < lto_cgraph_encoder_size (encoder); i++)
     {
@@ -2599,11 +2601,9 @@ produce_symtab (struct output_block *ob,
       if (DECL_COMDAT (node->decl)
          && cgraph_comdat_can_be_unshared_p (node))
        continue;
-      if (node->alias || node->global.inlined_to)
+      if ((node->alias && !node->thunk.alias) || node->global.inlined_to)
        continue;
       write_symbol (cache, &stream, node->decl, seen, false);
-      for (alias = node->same_body; alias; alias = alias->next)
-        write_symbol (cache, &stream, alias->decl, seen, true);
     }
 
   /* Write all variables.  */
@@ -2620,11 +2620,9 @@ produce_symtab (struct output_block *ob,
          && vnode->finalized 
          && DECL_VIRTUAL_P (vnode->decl))
        continue;
-      if (vnode->alias)
+      if (vnode->alias && !vnode->alias_of)
        continue;
       write_symbol (cache, &stream, vnode->decl, seen, false);
-      for (valias = vnode->extra_name; valias; valias = valias->next)
-        write_symbol (cache, &stream, valias->decl, seen, true);
     }
   for (i = 0; i < lto_varpool_encoder_size (varpool_encoder); i++)
     {
@@ -2636,11 +2634,9 @@ produce_symtab (struct output_block *ob,
          && vnode->finalized 
          && DECL_VIRTUAL_P (vnode->decl))
        continue;
-      if (vnode->alias)
+      if (vnode->alias && !vnode->alias_of)
        continue;
       write_symbol (cache, &stream, vnode->decl, seen, false);
-      for (valias = vnode->extra_name; valias; valias = valias->next)
-        write_symbol (cache, &stream, valias->decl, seen, true);
     }
 
   /* Write all aliases.  */