This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Applied: PATCH to use REFERENCE_TYPE for return by invisiblereference
- From: Jason Merrill <jason at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Sat, 07 Aug 2004 13:39:15 -0400
- Subject: Applied: PATCH to use REFERENCE_TYPE for return by invisiblereference
- References: <xyp4qngui22.fsf@miranda.boston.redhat.com>
Here's the version I'm applying to the trunk; the only change is to the
copy_body_r chunk, where I remove the now-unnecessary code rather than
adding an abort. Bootstrap was no faster this testrun.
2004-08-06 Jason Merrill <jason@redhat.com>
* 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.
*** ./cp/cp-gimplify.c.~1~ 2004-07-22 15:02:50.000000000 -0400
--- ./cp/cp-gimplify.c 2004-07-22 17:26:39.000000000 -0400
*************** cp_gimplify_expr (tree *expr_p, tree *pr
*** 267,273 ****
static inline bool
is_invisiref_parm (tree t)
{
! return (TREE_CODE (t) == PARM_DECL
&& DECL_BY_REFERENCE (t));
}
--- 267,273 ----
static inline bool
is_invisiref_parm (tree t)
{
! return ((TREE_CODE (t) == PARM_DECL || TREE_CODE (t) == RESULT_DECL)
&& DECL_BY_REFERENCE (t));
}
*************** cp_genericize_r (tree *stmt_p, int *walk
*** 283,289 ****
if (is_invisiref_parm (stmt))
{
! *stmt_p = build_fold_indirect_ref (stmt);
*walk_subtrees = 0;
return NULL;
}
--- 283,289 ----
if (is_invisiref_parm (stmt))
{
! *stmt_p = convert_from_reference (stmt);
*walk_subtrees = 0;
return NULL;
}
*************** cp_genericize_r (tree *stmt_p, int *walk
*** 302,307 ****
--- 302,312 ----
*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;
*************** cp_genericize (tree fndecl)
*** 331,342 ****
{
if (DECL_ARG_TYPE (t) == TREE_TYPE (t))
abort ();
- DECL_BY_REFERENCE (t) = 1;
TREE_TYPE (t) = DECL_ARG_TYPE (t);
relayout_decl (t);
}
}
/* If we're a clone, the body is already GIMPLE. */
if (DECL_CLONED_FUNCTION_P (fndecl))
return;
--- 336,358 ----
{
if (DECL_ARG_TYPE (t) == TREE_TYPE (t))
abort ();
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;
*** ./function.c.~1~ 2004-07-22 15:02:50.000000000 -0400
--- ./function.c 2004-07-22 16:59:10.000000000 -0400
*************** aggregate_value_p (tree exp, tree fntype
*** 1961,1966 ****
--- 1961,1971 ----
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,
*************** assign_parm_find_data_types (struct assi
*** 2265,2279 ****
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;
--- 2270,2275 ----
*************** assign_parms (tree fndecl)
*** 3173,3181 ****
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);
SET_DECL_RTL (result, x);
}
--- 3169,3182 ----
rtx addr = DECL_RTL (all.function_result_decl);
rtx x;
! 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);
}
*************** expand_function_end (void)
*** 4501,4517 ****
if (current_function_returns_struct
|| current_function_returns_pcc_struct)
{
! rtx value_address
! = XEXP (DECL_RTL (DECL_RESULT (current_function_decl)), 0);
tree type = TREE_TYPE (DECL_RESULT (current_function_decl));
#ifdef FUNCTION_OUTGOING_VALUE
! rtx outgoing
! = FUNCTION_OUTGOING_VALUE (build_pointer_type (type),
! current_function_decl);
#else
! rtx 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. */
--- 4502,4523 ----
if (current_function_returns_struct
|| current_function_returns_pcc_struct)
{
! 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
! outgoing = FUNCTION_OUTGOING_VALUE (build_pointer_type (type),
! current_function_decl);
#else
! 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. */
*** ./gimplify.c.~1~ 2004-07-22 15:02:50.000000000 -0400
--- ./gimplify.c 2004-07-22 16:30:55.000000000 -0400
*************** gimplify_return_expr (tree stmt, tree *p
*** 895,900 ****
--- 895,903 ----
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)
*** tree-inline.c.~1~ 2004-08-02 16:09:13.000000000 -0400
--- tree-inline.c 2004-08-06 16:17:25.000000000 -0400
*************** copy_body_r (tree *tp, int *walk_subtree
*** 573,605 ****
}
}
}
- 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
--- 573,578 ----
*************** declare_return_variable (inline_data *id
*** 861,867 ****
return NULL_TREE;
}
! /* If there was a return slot, then the return value the the
dereferenced address of that object. */
if (return_slot_addr)
{
--- 834,840 ----
return NULL_TREE;
}
! /* If there was a return slot, then the return value is the
dereferenced address of that object. */
if (return_slot_addr)
{
*************** declare_return_variable (inline_data *id
*** 869,875 ****
a modify expression. */
if (modify_dest)
abort ();
! var = build_fold_indirect_ref (return_slot_addr);
use = NULL;
goto done;
}
--- 842,851 ----
a modify expression. */
if (modify_dest)
abort ();
! if (DECL_BY_REFERENCE (result))
! var = return_slot_addr;
! else
! var = build_fold_indirect_ref (return_slot_addr);
use = NULL;
goto done;
}