OSDN Git Service

Daily bump.
[pf3gnuchains/gcc-fork.git] / gcc / tree-inline.c
index afec40d..d326525 100644 (file)
@@ -257,26 +257,10 @@ remap_decl (tree decl, inline_data *id)
 }
 
 static tree
-remap_type (tree type, inline_data *id)
+remap_type_1 (tree type, inline_data *id)
 {
-  splay_tree_node node;
   tree new, t;
 
-  if (type == NULL)
-    return type;
-
-  /* See if we have remapped this type.  */
-  node = splay_tree_lookup (id->decl_map, (splay_tree_key) type);
-  if (node)
-    return (tree) node->value;
-
-  /* The type only needs remapping if it's variably modified.  */
-  if (! variably_modified_type_p (type, id->callee))
-    {
-      insert_decl_map (id, type, type);
-      return type;
-    }
-
   /* We do need a copy.  build and register it now.  If this is a pointer or
      reference type, remap the designated type and make a new pointer or
      reference type.  */
@@ -353,7 +337,18 @@ remap_type (tree type, inline_data *id)
     case RECORD_TYPE:
     case UNION_TYPE:
     case QUAL_UNION_TYPE:
-      walk_tree (&TYPE_FIELDS (new), copy_body_r, id, NULL);
+      {
+       tree f, nf = NULL;
+
+       for (f = TYPE_FIELDS (new); f ; f = TREE_CHAIN (f))
+         {
+           t = remap_decl (f, id);
+           DECL_CONTEXT (t) = new;
+           TREE_CHAIN (t) = nf;
+           nf = t;
+         }
+       TYPE_FIELDS (new) = nreverse (nf);
+      }
       break;
 
     case OFFSET_TYPE:
@@ -369,6 +364,29 @@ remap_type (tree type, inline_data *id)
 }
 
 static tree
+remap_type (tree type, inline_data *id)
+{
+  splay_tree_node node;
+
+  if (type == NULL)
+    return type;
+
+  /* See if we have remapped this type.  */
+  node = splay_tree_lookup (id->decl_map, (splay_tree_key) type);
+  if (node)
+    return (tree) node->value;
+
+  /* The type only needs remapping if it's variably modified.  */
+  if (! variably_modified_type_p (type, id->callee))
+    {
+      insert_decl_map (id, type, type);
+      return type;
+    }
+
+  return remap_type_1 (type, id);
+}
+
+static tree
 remap_decls (tree decls, inline_data *id)
 {
   tree old_var;
@@ -526,7 +544,7 @@ copy_body_r (tree *tp, int *walk_subtrees, void *data)
       else /* Else the RETURN_EXPR returns no value.  */
        {
          *tp = NULL;
-         return (void *)1;
+         return (tree) (void *)1;
        }
     }
 
@@ -621,6 +639,7 @@ copy_body_r (tree *tp, int *walk_subtrees, void *data)
          n = splay_tree_lookup (id->decl_map, (splay_tree_key) decl);
          if (n)
            {
+             tree new;
              /* If we happen to get an ADDR_EXPR in n->value, strip
                 it manually here as we'll eventually get ADDR_EXPRs
                 which lie about their types pointed to.  In this case
@@ -628,13 +647,14 @@ copy_body_r (tree *tp, int *walk_subtrees, void *data)
                 but we absolutely rely on that.  As fold_indirect_ref
                 does other useful transformations, try that first, though.  */
              tree type = TREE_TYPE (TREE_TYPE ((tree)n->value));
-             *tp = fold_indirect_ref_1 (type, (tree)n->value);
+             new = unshare_expr ((tree)n->value);
+             *tp = fold_indirect_ref_1 (type, new);
              if (! *tp)
                {
-                 if (TREE_CODE ((tree)n->value) == ADDR_EXPR)
-                   *tp = TREE_OPERAND ((tree)n->value, 0);
+                 if (TREE_CODE (new) == ADDR_EXPR)
+                   *tp = TREE_OPERAND (new, 0);
                  else
-                   *tp = build1 (INDIRECT_REF, type, (tree)n->value);
+                   *tp = build1 (INDIRECT_REF, type, new);
                }
              *walk_subtrees = 0;
              return NULL;
@@ -684,7 +704,7 @@ copy_body_r (tree *tp, int *walk_subtrees, void *data)
       else if (TREE_CODE (*tp) == ADDR_EXPR)
        {
          walk_tree (&TREE_OPERAND (*tp, 0), copy_body_r, id, NULL);
-         recompute_tree_invarant_for_addr_expr (*tp);
+         recompute_tree_invariant_for_addr_expr (*tp);
          *walk_subtrees = 0;
        }
     }
@@ -704,7 +724,8 @@ copy_bb (inline_data *id, basic_block bb, int frequency_scale, int count_scale)
 
   /* create_basic_block() will append every new block to
      basic_block_info automatically.  */
-  copy_basic_block = create_basic_block (NULL, (void *) 0, bb->prev_bb->aux);
+  copy_basic_block = create_basic_block (NULL, (void *) 0,
+                                         (basic_block) bb->prev_bb->aux);
   copy_basic_block->count = bb->count * count_scale / REG_BR_PROB_BASE;
   copy_basic_block->frequency = (bb->frequency
                                     * frequency_scale / REG_BR_PROB_BASE);
@@ -807,7 +828,7 @@ copy_bb (inline_data *id, basic_block bb, int frequency_scale, int count_scale)
 static void
 copy_edges_for_bb (basic_block bb, int count_scale)
 {
-  basic_block new_bb = bb->aux;
+  basic_block new_bb = (basic_block) bb->aux;
   edge_iterator ei;
   edge old_edge;
   block_stmt_iterator bsi;
@@ -826,7 +847,7 @@ copy_edges_for_bb (basic_block bb, int count_scale)
        if (old_edge->dest->index == EXIT_BLOCK && !old_edge->flags
            && old_edge->dest->aux != EXIT_BLOCK_PTR)
          flags |= EDGE_FALLTHRU;
-       new = make_edge (new_bb, old_edge->dest->aux, flags);
+       new = make_edge (new_bb, (basic_block) old_edge->dest->aux, flags);
        new->count = old_edge->count * count_scale / REG_BR_PROB_BASE;
        new->probability = old_edge->probability;
       }
@@ -875,7 +896,7 @@ copy_edges_for_bb (basic_block bb, int count_scale)
 static tree
 remap_decl_1 (tree decl, void *data)
 {
-  return remap_decl (decl, data);
+  return remap_decl (decl, (inline_data *) data);
 }
 
 /* Make a copy of the body of FN so that it can be inserted inline in
@@ -1128,7 +1149,7 @@ setup_one_parameter (inline_data *id, tree p, tree value, tree fn,
 
       /* We want to use MODIFY_EXPR, not INIT_EXPR here so that we
         keep our trees in gimple form.  */
-      init_stmt = build (MODIFY_EXPR, TREE_TYPE (var), var, rhs);
+      init_stmt = build2 (MODIFY_EXPR, TREE_TYPE (var), var, rhs);
 
       /* If we did not create a gimple value and we did not create a gimple
         cast of a gimple value, then we will need to gimplify INIT_STMTS
@@ -1139,7 +1160,11 @@ setup_one_parameter (inline_data *id, tree p, tree value, tree fn,
          && (!is_gimple_cast (rhs)
              || !is_gimple_val (TREE_OPERAND (rhs, 0))))
        gimplify_stmt (&init_stmt);
-      bsi_insert_after (&bsi, init_stmt, BSI_NEW_STMT);
+
+      /* If VAR represents a zero-sized variable, it's possible that the
+        assignment statment may result in no gimple statements.  */
+      if (init_stmt)
+        bsi_insert_after (&bsi, init_stmt, BSI_NEW_STMT);
     }
 }
 
@@ -1260,10 +1285,21 @@ declare_return_variable (inline_data *id, tree return_slot_addr,
       /* If the callee cannot possibly modify MODIFY_DEST, then we can
         reuse it as the result of the call directly.  Don't do this if
         it would promote MODIFY_DEST to addressable.  */
-      else if (!TREE_STATIC (modify_dest)
-              && !TREE_ADDRESSABLE (modify_dest)
-              && !TREE_ADDRESSABLE (result))
-       use_it = true;
+      else if (TREE_ADDRESSABLE (result))
+       use_it = false;
+      else
+       {
+         tree base_m = get_base_address (modify_dest);
+
+         /* If the base isn't a decl, then it's a pointer, and we don't
+            know where that's going to go.  */
+         if (!DECL_P (base_m))
+           use_it = false;
+         else if (is_global_var (base_m))
+           use_it = false;
+         else if (!TREE_ADDRESSABLE (base_m))
+           use_it = true;
+       }
 
       if (use_it)
        {
@@ -1579,7 +1615,7 @@ estimate_move_cost (tree type)
 static tree
 estimate_num_insns_1 (tree *tp, int *walk_subtrees, void *data)
 {
-  int *count = data;
+  int *count = (int *) data;
   tree x = *tp;
 
   if (IS_TYPE_OR_DECL_P (x))
@@ -2948,3 +2984,23 @@ inlining_p (inline_data * id)
 {
   return (!id->saving_p && !id->cloning_p && !id->versioning_p);
 }
+
+/* Duplicate a type, fields and all.  */
+
+tree
+build_duplicate_type (tree type)
+{
+  inline_data id;
+
+  memset (&id, 0, sizeof (id));
+  id.callee = current_function_decl;
+  id.caller = current_function_decl;
+  id.callee_cfun = cfun;
+  id.decl_map = splay_tree_new (splay_tree_compare_pointers, NULL, NULL);
+
+  type = remap_type_1 (type, &id);
+
+  splay_tree_delete (id.decl_map);
+
+  return type;
+}