From: Jason Merrill Date: Sat, 7 Aug 2004 17:40:10 +0000 (-0400) Subject: Make return in memory explicit. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=cc77ae108d3b8cf9aa8bbbeada6c0c1fbcf8920f;p=gcc.git 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. From-SVN: r85675 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 21ca11bcd68..5cea2153d21 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -14,6 +14,21 @@ 2004-08-07 Jason Merrill + 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 diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c index ed0a6a19d41..5b96e39dbef 100644 --- a/gcc/cp/cp-gimplify.c +++ b/gcc/cp/cp-gimplify.c @@ -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; diff --git a/gcc/function.c b/gcc/function.c index 699a009ee03..4de748aceb8 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -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. */ diff --git a/gcc/gimplify.c b/gcc/gimplify.c index cd2a4a0beec..c6478ec40f5 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -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) diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c index 5dacddb7152..b34844d82f3 100644 --- a/gcc/tree-inline.c +++ b/gcc/tree-inline.c @@ -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; }