Make return in memory explicit.
authorJason Merrill <jason@redhat.com>
Sat, 7 Aug 2004 17:40:10 +0000 (13:40 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Sat, 7 Aug 2004 17:40:10 +0000 (13:40 -0400)
        * function.c (aggregate_value_p): Check DECL_BY_REFERENCE.
        (assign_parm_find_data_types): Remove code for old front end
        invisible reference handling.
        (assign_parms): Handle DECL_BY_REFERENCE on the RESULT_DECL.
        (expand_function_end): Likewise.
        * gimplify.c (gimplify_return_expr): Handle a dereferenced
        RESULT_DECL.
        * tree-inline.c (copy_body_r): Don't bother looking for &* anymore.
        (declare_return_variable): Handle DECL_BY_REFERENCE.
        * cp/cp-gimplify.c (is_invisiref_parm): Also handle RESULT_DECL.
        (cp_genericize_r): Use convert_from_reference.
        Don't dereference a RESULT_DECL directly inside a RETURN_EXPR.
        (cp_genericize): Handle the RESULT_DECL.  Unset TREE_ADDRESSABLE.

From-SVN: r85675

gcc/ChangeLog
gcc/cp/cp-gimplify.c
gcc/function.c
gcc/gimplify.c
gcc/tree-inline.c

index 21ca11bcd68139df9d12274a2bfb7ada0c6f37c6..5cea2153d21177822114be68d5bf636f751ea9e7 100644 (file)
 
 2004-08-07  Jason Merrill  <jason@redhat.com>
 
+       Make return in memory explicit.
+       * function.c (aggregate_value_p): Check DECL_BY_REFERENCE.
+       (assign_parm_find_data_types): Remove code for old front end
+       invisible reference handling.
+       (assign_parms): Handle DECL_BY_REFERENCE on the RESULT_DECL.
+       (expand_function_end): Likewise.
+       * gimplify.c (gimplify_return_expr): Handle a dereferenced
+       RESULT_DECL.
+       * tree-inline.c (copy_body_r): Don't bother looking for &* anymore.
+       (declare_return_variable): Handle DECL_BY_REFERENCE.
+       * cp/cp-gimplify.c (is_invisiref_parm): Also handle RESULT_DECL.
+       (cp_genericize_r): Use convert_from_reference.
+       Don't dereference a RESULT_DECL directly inside a RETURN_EXPR.
+       (cp_genericize): Handle the RESULT_DECL.  Unset TREE_ADDRESSABLE.
+
        * gimplify.c (gimplify_call_expr): Make return in memory explicit.
        (gimplify_modify_expr_rhs): Likewise.
        * c-common.c (c_warn_unused_result): Check TREE_USED before
index ed0a6a19d41901f7d8de08e34f768e760b8ad4bb..5b96e39dbef2be94e9347c0a59dc4c4eeb0bf17e 100644 (file)
@@ -267,7 +267,7 @@ cp_gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p)
 static inline bool
 is_invisiref_parm (tree t)
 {
-  return (TREE_CODE (t) == PARM_DECL
+  return ((TREE_CODE (t) == PARM_DECL || TREE_CODE (t) == RESULT_DECL)
          && DECL_BY_REFERENCE (t));
 }
 
@@ -283,7 +283,7 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
 
   if (is_invisiref_parm (stmt))
     {
-      *stmt_p = build_fold_indirect_ref (stmt);
+      *stmt_p = convert_from_reference (stmt);
       *walk_subtrees = 0;
       return NULL;
     }
@@ -302,6 +302,11 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
       *stmt_p = convert (TREE_TYPE (stmt), TREE_OPERAND (stmt, 0));
       *walk_subtrees = 0;
     }
+  else if (TREE_CODE (stmt) == RETURN_EXPR
+          && TREE_OPERAND (stmt, 0)
+          && is_invisiref_parm (TREE_OPERAND (stmt, 0)))
+    /* Don't dereference an invisiref RESULT_DECL inside a RETURN_EXPR.  */
+    *walk_subtrees = 0;
   else if (DECL_P (stmt) || TYPE_P (stmt))
     *walk_subtrees = 0;
 
@@ -331,12 +336,23 @@ cp_genericize (tree fndecl)
        {
          if (DECL_ARG_TYPE (t) == TREE_TYPE (t))
            abort ();
-         DECL_BY_REFERENCE (t) = 1;
          TREE_TYPE (t) = DECL_ARG_TYPE (t);
+         DECL_BY_REFERENCE (t) = 1;
+         TREE_ADDRESSABLE (t) = 0;
          relayout_decl (t);
        }
     }
 
+  /* Do the same for the return value.  */
+  if (TREE_ADDRESSABLE (TREE_TYPE (DECL_RESULT (fndecl))))
+    {
+      t = DECL_RESULT (fndecl);
+      TREE_TYPE (t) = build_reference_type (TREE_TYPE (t));
+      DECL_BY_REFERENCE (t) = 1;
+      TREE_ADDRESSABLE (t) = 0;
+      relayout_decl (t);
+    }
+
   /* If we're a clone, the body is already GIMPLE.  */
   if (DECL_CLONED_FUNCTION_P (fndecl))
     return;
index 699a009ee039535f8b451b1e78671212cb5adace..4de748aceb8a8c659f3e01544d77896d9026b391 100644 (file)
@@ -1883,6 +1883,11 @@ aggregate_value_p (tree exp, tree fntype)
 
   if (TREE_CODE (type) == VOID_TYPE)
     return 0;
+  /* If the front end has decided that this needs to be passed by
+     reference, do so.  */
+  if ((TREE_CODE (exp) == PARM_DECL || TREE_CODE (exp) == RESULT_DECL)
+      && DECL_BY_REFERENCE (exp))
+    return 1;
   if (targetm.calls.return_in_memory (type, fntype))
     return 1;
   /* Types that are TREE_ADDRESSABLE must be constructed in memory,
@@ -2187,15 +2192,6 @@ assign_parm_find_data_types (struct assign_parm_data_all *all, tree parm,
       data->passed_pointer = true;
       passed_mode = nominal_mode = Pmode;
     }
-  /* See if the frontend wants to pass this by invisible reference.  */
-  else if (passed_type != nominal_type
-          && POINTER_TYPE_P (passed_type)
-          && TREE_TYPE (passed_type) == nominal_type)
-    {
-      nominal_type = passed_type;
-      data->passed_pointer = 1;
-      passed_mode = nominal_mode = Pmode;
-    }
 
   /* Find mode as it is passed by the ABI.  */
   promoted_mode = passed_mode;
@@ -3095,9 +3091,14 @@ assign_parms (tree fndecl)
       rtx addr = DECL_RTL (all.function_result_decl);
       rtx x;
 
-      addr = convert_memory_address (Pmode, addr);
-      x = gen_rtx_MEM (DECL_MODE (result), addr);
-      set_mem_attributes (x, result, 1);
+      if (DECL_BY_REFERENCE (result))
+       x = addr;
+      else
+       {
+         addr = convert_memory_address (Pmode, addr);
+         x = gen_rtx_MEM (DECL_MODE (result), addr);
+         set_mem_attributes (x, result, 1);
+       }
       SET_DECL_RTL (result, x);
     }
 
@@ -4385,17 +4386,22 @@ expand_function_end (void)
   if (current_function_returns_struct
       || current_function_returns_pcc_struct)
     {
-      rtx value_address
-       = XEXP (DECL_RTL (DECL_RESULT (current_function_decl)), 0);
+      rtx value_address = DECL_RTL (DECL_RESULT (current_function_decl));
       tree type = TREE_TYPE (DECL_RESULT (current_function_decl));
+      rtx outgoing;
+
+      if (DECL_BY_REFERENCE (DECL_RESULT (current_function_decl)))
+       type = TREE_TYPE (type);
+      else
+       value_address = XEXP (value_address, 0);
+
 #ifdef FUNCTION_OUTGOING_VALUE
-      rtx outgoing
-       = FUNCTION_OUTGOING_VALUE (build_pointer_type (type),
-                                  current_function_decl);
+      outgoing = FUNCTION_OUTGOING_VALUE (build_pointer_type (type),
+                                         current_function_decl);
 #else
-      rtx outgoing
-       = FUNCTION_VALUE (build_pointer_type (type), current_function_decl);
-#endif
+      outgoing = FUNCTION_VALUE (build_pointer_type (type),
+                                current_function_decl);
+#endif 
 
       /* Mark this as a function return value so integrate will delete the
         assignment and USE below when inlining this function.  */
index cd2a4a0beecc6dd346d5ee7dccbd0f904b864db5..c6478ec40f5bf2e996abcbba33adf8764ab13bcb 100644 (file)
@@ -895,6 +895,9 @@ gimplify_return_expr (tree stmt, tree *pre_p)
   else
     {
       result_decl = TREE_OPERAND (ret_expr, 0);
+      if (TREE_CODE (result_decl) == INDIRECT_REF)
+       /* See through a return by reference.  */
+       result_decl = TREE_OPERAND (result_decl, 0);
 #ifdef ENABLE_CHECKING
       if ((TREE_CODE (ret_expr) != MODIFY_EXPR
           && TREE_CODE (ret_expr) != INIT_EXPR)
index 5dacddb7152e6ffd90c08b7d1027f5bb6e7ac129..b34844d82f3945f7cb3537046c1ad9eaa32795c5 100644 (file)
@@ -573,33 +573,6 @@ copy_body_r (tree *tp, int *walk_subtrees, void *data)
                }
            }
        }
-      else if (TREE_CODE (*tp) == ADDR_EXPR
-              && (lang_hooks.tree_inlining.auto_var_in_fn_p
-                  (TREE_OPERAND (*tp, 0), fn)))
-       {
-         /* Get rid of &* from inline substitutions.  It can occur when
-            someone takes the address of a parm or return slot passed by
-            invisible reference.  */
-         tree decl = TREE_OPERAND (*tp, 0), value;
-         splay_tree_node n;
-
-         n = splay_tree_lookup (id->decl_map, (splay_tree_key) decl);
-         if (n)
-           {
-             value = (tree) n->value;
-             if (TREE_CODE (value) == INDIRECT_REF)
-               {
-                 if  (!lang_hooks.types_compatible_p
-                      (TREE_TYPE (*tp), TREE_TYPE (TREE_OPERAND (value, 0))))
-                   *tp = fold_convert (TREE_TYPE (*tp),
-                                       TREE_OPERAND (value, 0));
-                 else
-                   *tp = TREE_OPERAND (value, 0);
-
-                 return copy_body_r (tp, walk_subtrees, data);
-               }
-           }
-       }
       else if (TREE_CODE (*tp) == INDIRECT_REF)
        {
          /* Get rid of *& from inline substitutions that can happen when a
@@ -861,7 +834,7 @@ declare_return_variable (inline_data *id, tree return_slot_addr,
       return NULL_TREE;
     }
 
-  /* If there was a return slot, then the return value the the
+  /* If there was a return slot, then the return value is the
      dereferenced address of that object.  */
   if (return_slot_addr)
     {
@@ -869,7 +842,10 @@ declare_return_variable (inline_data *id, tree return_slot_addr,
         a modify expression.  */
       if (modify_dest)
        abort ();
-      var = build_fold_indirect_ref (return_slot_addr);
+      if (DECL_BY_REFERENCE (result))
+       var = return_slot_addr;
+      else
+       var = build_fold_indirect_ref (return_slot_addr);
       use = NULL;
       goto done;
     }