aboutsummaryrefslogtreecommitdiff
path: root/gcc/gimplify.c
diff options
context:
space:
mode:
authorRichard Henderson <rth@redhat.com>2004-06-08 09:29:57 -0700
committerRichard Henderson <rth@gcc.gnu.org>2004-06-08 09:29:57 -0700
commit7187798577a9a9035d1d492d1686217ff5ca30d7 (patch)
tree916bbf6a5966ddcddcc46c35c1346ae0899e2b22 /gcc/gimplify.c
parentde101ad2f75511c715a846770e3cd446e49f882c (diff)
downloadgcc-7187798577a9a9035d1d492d1686217ff5ca30d7.zip
gcc-7187798577a9a9035d1d492d1686217ff5ca30d7.tar.gz
gcc-7187798577a9a9035d1d492d1686217ff5ca30d7.tar.bz2
gimple-low.c (struct lower_data): Replace the_return_label and one_return_stmt with return_statements.
* gimple-low.c (struct lower_data): Replace the_return_label and one_return_stmt with return_statements. (lower_function_body): Process the entire list of return_statements. (lower_return_expr): Check source value before unifying return_exprs. * gimplify.c (gimplify_return_expr): Force the use of a temporary for !aggregate_value_p. * tree-gimple.c: Update RETURN_EXPR grammer. From-SVN: r82768
Diffstat (limited to 'gcc/gimplify.c')
-rw-r--r--gcc/gimplify.c42
1 files changed, 35 insertions, 7 deletions
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 679103e..c6378aa 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -54,6 +54,7 @@ static struct gimplify_ctx
tree conditional_cleanups;
int conditions;
tree exit_label;
+ tree return_temp;
varray_type case_labels;
/* The formal temporary table. Should this be persistent? */
htab_t temp_htab;
@@ -888,7 +889,7 @@ static enum gimplify_status
gimplify_return_expr (tree stmt, tree *pre_p)
{
tree ret_expr = TREE_OPERAND (stmt, 0);
- tree result;
+ tree result_decl, result;
if (!ret_expr || TREE_CODE (ret_expr) == RESULT_DECL)
return GS_ALL_DONE;
@@ -897,24 +898,51 @@ gimplify_return_expr (tree stmt, tree *pre_p)
return GS_ERROR;
if (VOID_TYPE_P (TREE_TYPE (TREE_TYPE (current_function_decl))))
- result = NULL_TREE;
+ result_decl = NULL_TREE;
else
{
- result = TREE_OPERAND (ret_expr, 0);
+ result_decl = TREE_OPERAND (ret_expr, 0);
#ifdef ENABLE_CHECKING
if ((TREE_CODE (ret_expr) != MODIFY_EXPR
&& TREE_CODE (ret_expr) != INIT_EXPR)
- || TREE_CODE (result) != RESULT_DECL)
+ || TREE_CODE (result_decl) != RESULT_DECL)
abort ();
#endif
}
- /* We need to pass the full MODIFY_EXPR down so that special handling
- can replace it with something else. */
+ /* If aggregate_value_p is true, then we can return the bare RESULT_DECL.
+ Recall that aggregate_value_p is FALSE for any aggregate type that is
+ returned in registers. If we're returning values in registers, then
+ we don't want to extend the lifetime of the RESULT_DECL, particularly
+ across another call. In addition, for those aggregates for which
+ hard_function_value generates a PARALLEL, we'll abort during normal
+ expansion of structure assignments; there's special code in expand_return
+ to handle this case that does not exist in expand_expr. */
+ if (!result_decl
+ || aggregate_value_p (result_decl, TREE_TYPE (current_function_decl)))
+ result = result_decl;
+ else if (gimplify_ctxp->return_temp)
+ result = gimplify_ctxp->return_temp;
+ else
+ {
+ result = create_tmp_var (TREE_TYPE (result_decl), NULL);
+ gimplify_ctxp->return_temp = result;
+ }
+
+ /* Smash the lhs of the MODIFY_EXPR to the temporary we plan to use.
+ Then gimplify the whole thing. */
+ if (result != result_decl)
+ TREE_OPERAND (ret_expr, 0) = result;
gimplify_stmt (&TREE_OPERAND (stmt, 0));
append_to_statement_list (TREE_OPERAND (stmt, 0), pre_p);
- TREE_OPERAND (stmt, 0) = result;
+ /* If we didn't use a temporary, then the result is just the result_decl.
+ Otherwise we need a simple copy. This should already be gimple. */
+ if (result == result_decl)
+ ret_expr = result;
+ else
+ ret_expr = build (MODIFY_EXPR, TREE_TYPE (result), result_decl, result);
+ TREE_OPERAND (stmt, 0) = ret_expr;
return GS_ALL_DONE;
}