OSDN Git Service

PR target/33135
[pf3gnuchains/gcc-fork.git] / gcc / lto-streamer-out.c
index d107b91..054bb85 100644 (file)
@@ -129,6 +129,16 @@ tree_is_indexable (tree t)
   else if (TREE_CODE (t) == VAR_DECL && decl_function_context (t)
           && !TREE_STATIC (t))
     return false;
+  /* Variably modified types need to be streamed alongside function
+     bodies because they can refer to local entities.  Together with
+     them we have to localize their members as well.
+     ???  In theory that includes non-FIELD_DECLs as well.  */
+  else if (TYPE_P (t)
+          && variably_modified_type_p (t, NULL_TREE))
+    return false;
+  else if (TREE_CODE (t) == FIELD_DECL
+          && variably_modified_type_p (DECL_CONTEXT (t), NULL_TREE))
+    return false;
   else
     return (TYPE_P (t) || DECL_P (t) || TREE_CODE (t) == SSA_NAME);
 }
@@ -172,15 +182,21 @@ lto_output_location_bitpack (struct bitpack_d *bp,
 
 
 /* Emit location LOC to output block OB.
-   When bitpack is handy, it is more space effecient to call
+   If the output_location streamer hook exists, call it.
+   Otherwise, when bitpack is handy, it is more space efficient to call
    lto_output_location_bitpack with existing bitpack.  */
 
 void
 lto_output_location (struct output_block *ob, location_t loc)
 {
-  struct bitpack_d bp = bitpack_create (ob->main_stream);
-  lto_output_location_bitpack (&bp, ob, loc);
-  streamer_write_bitpack (&bp);
+  if (streamer_hooks.output_location)
+    streamer_hooks.output_location (ob, loc);
+  else
+    {
+      struct bitpack_d bp = bitpack_create (ob->main_stream);
+      lto_output_location_bitpack (&bp, ob, loc);
+      streamer_write_bitpack (&bp);
+    }
 }
 
 
@@ -288,7 +304,6 @@ lto_is_streamable (tree expr)
         && code != WITH_CLEANUP_EXPR
         && code != STATEMENT_LIST
         && code != OMP_CLAUSE
-        && code != OPTIMIZATION_NODE
         && (code == CASE_LABEL_EXPR
             || code == DECL_EXPR
             || TREE_CODE_CLASS (code) != tcc_statement);
@@ -354,11 +369,12 @@ lto_write_tree (struct output_block *ob, tree expr, bool ref_p)
 
 
 /* Emit the physical representation of tree node EXPR to output block
-   OB.  If REF_P is true, the leaves of EXPR are emitted as references
-   via lto_output_tree_ref.  */
+   OB.  If THIS_REF_P is true, the leaves of EXPR are emitted as references
+   via lto_output_tree_ref.  REF_P is used for streaming siblings of EXPR.  */
 
 void
-lto_output_tree (struct output_block *ob, tree expr, bool ref_p)
+lto_output_tree (struct output_block *ob, tree expr,
+                bool ref_p, bool this_ref_p)
 {
   unsigned ix;
   bool existed_p;
@@ -369,7 +385,7 @@ lto_output_tree (struct output_block *ob, tree expr, bool ref_p)
       return;
     }
 
-  if (ref_p && tree_is_indexable (expr))
+  if (this_ref_p && tree_is_indexable (expr))
     {
       lto_output_tree_ref (ob, expr);
       return;
@@ -713,36 +729,30 @@ produce_asm (struct output_block *ob, tree fn)
 }
 
 
-/* Output the body of function NODE->DECL.  */
+/* Output the base body of struct function FN using output block OB.  */
 
 static void
-output_function (struct cgraph_node *node)
+output_struct_function_base (struct output_block *ob, struct function *fn)
 {
   struct bitpack_d bp;
-  tree function;
-  struct function *fn;
-  basic_block bb;
-  struct output_block *ob;
   unsigned i;
   tree t;
 
-  function = node->decl;
-  fn = DECL_STRUCT_FUNCTION (function);
-  ob = create_output_block (LTO_section_function_body);
-
-  clear_line_info (ob);
-  ob->cgraph_node = node;
-
-  gcc_assert (current_function_decl == NULL_TREE && cfun == NULL);
+  /* Output the static chain and non-local goto save area.  */
+  stream_write_tree (ob, fn->static_chain_decl, true);
+  stream_write_tree (ob, fn->nonlocal_goto_save_area, true);
 
-  /* Set current_function_decl and cfun.  */
-  current_function_decl = function;
-  push_cfun (fn);
+  /* Output all the local variables in the function.  */
+  streamer_write_hwi (ob, VEC_length (tree, fn->local_decls));
+  FOR_EACH_VEC_ELT (tree, fn->local_decls, i, t)
+    stream_write_tree (ob, t, true);
 
-  /* Make string 0 be a NULL string.  */
-  streamer_write_char_stream (ob->string_stream, 0);
+  /* Output the function start and end loci.  */
+  lto_output_location (ob, fn->function_start_locus);
+  lto_output_location (ob, fn->function_end_locus);
 
-  streamer_write_record_start (ob, LTO_function);
+  /* Output current IL state of the function.  */
+  streamer_write_uhwi (ob, fn->curr_properties);
 
   /* Write all the attributes for FN.  */
   bp = bitpack_create (ob->main_stream);
@@ -761,22 +771,38 @@ output_function (struct cgraph_node *node)
   bp_pack_value (&bp, fn->va_list_fpr_size, 8);
   bp_pack_value (&bp, fn->va_list_gpr_size, 8);
   streamer_write_bitpack (&bp);
+}
 
-  /* Output the function start and end loci.  */
-  lto_output_location (ob, fn->function_start_locus);
-  lto_output_location (ob, fn->function_end_locus);
 
-  /* Output current IL state of the function.  */
-  streamer_write_uhwi (ob, fn->curr_properties);
+/* Output the body of function NODE->DECL.  */
 
-  /* Output the static chain and non-local goto save area.  */
-  stream_write_tree (ob, fn->static_chain_decl, true);
-  stream_write_tree (ob, fn->nonlocal_goto_save_area, true);
+static void
+output_function (struct cgraph_node *node)
+{
+  tree function;
+  struct function *fn;
+  basic_block bb;
+  struct output_block *ob;
 
-  /* Output all the local variables in the function.  */
-  streamer_write_hwi (ob, VEC_length (tree, fn->local_decls));
-  FOR_EACH_VEC_ELT (tree, fn->local_decls, i, t)
-    stream_write_tree (ob, t, true);
+  function = node->decl;
+  fn = DECL_STRUCT_FUNCTION (function);
+  ob = create_output_block (LTO_section_function_body);
+
+  clear_line_info (ob);
+  ob->cgraph_node = node;
+
+  gcc_assert (current_function_decl == NULL_TREE && cfun == NULL);
+
+  /* Set current_function_decl and cfun.  */
+  current_function_decl = function;
+  push_cfun (fn);
+
+  /* Make string 0 be a NULL string.  */
+  streamer_write_char_stream (ob->string_stream, 0);
+
+  streamer_write_record_start (ob, LTO_function);
+
+  output_struct_function_base (ob, fn);
 
   /* Output the head of the arguments list.  */
   stream_write_tree (ob, DECL_ARGUMENTS (function), true);
@@ -954,7 +980,10 @@ lto_output_toplevel_asms (void)
   streamer_write_char_stream (ob->string_stream, 0);
 
   for (can = cgraph_asm_nodes; can; can = can->next)
-    streamer_write_string_cst (ob, ob->main_stream, can->asm_str);
+    {
+      streamer_write_string_cst (ob, ob->main_stream, can->asm_str);
+      streamer_write_hwi (ob, can->order);
+    }
 
   streamer_write_string_cst (ob, ob->main_stream, NULL_TREE);
 
@@ -1251,7 +1280,7 @@ write_symbol (struct streamer_tree_cache_d *cache,
   enum gcc_plugin_symbol_kind kind;
   enum gcc_plugin_symbol_visibility visibility;
   unsigned slot_num;
-  uint64_t size;
+  unsigned HOST_WIDEST_INT size;
   const char *comdat;
   unsigned char c;
 
@@ -1309,7 +1338,7 @@ write_symbol (struct streamer_tree_cache_d *cache,
      when symbol has attribute (visibility("hidden")) specified.
      targetm.binds_local_p check DECL_VISIBILITY_SPECIFIED and gets this
      right. */
-     
+
   if (DECL_EXTERNAL (t)
       && !targetm.binds_local_p (t))
     visibility = GCCPV_DEFAULT;
@@ -1331,14 +1360,9 @@ write_symbol (struct streamer_tree_cache_d *cache,
       }
 
   if (kind == GCCPK_COMMON
-      && DECL_SIZE (t)
-      && TREE_CODE (DECL_SIZE (t)) == INTEGER_CST)
-    {
-      size = (HOST_BITS_PER_WIDE_INT >= 64)
-       ? (uint64_t) int_size_in_bytes (TREE_TYPE (t))
-       : (((uint64_t) TREE_INT_CST_HIGH (DECL_SIZE_UNIT (t))) << 32)
-               | TREE_INT_CST_LOW (DECL_SIZE_UNIT (t));
-    }
+      && DECL_SIZE_UNIT (t)
+      && TREE_CODE (DECL_SIZE_UNIT (t)) == INTEGER_CST)
+    size = TREE_INT_CST_LOW (DECL_SIZE_UNIT (t));
   else
     size = 0;
 
@@ -1411,11 +1435,7 @@ produce_symtab (struct output_block *ob,
         them indirectly or via vtables.  Do not output them to symbol
         table: they end up being undefined and just consume space.  */
       if (!node->address_taken && !node->callers)
-       {
-         gcc_assert (node->analyzed);
-         gcc_assert (DECL_DECLARED_INLINE_P (node->decl));
-         continue;
-       }
+       continue;
       if (DECL_COMDAT (node->decl)
          && cgraph_comdat_can_be_unshared_p (node))
        continue;