diff options
author | Richard Henderson <rth@redhat.com> | 2004-06-08 09:29:57 -0700 |
---|---|---|
committer | Richard Henderson <rth@gcc.gnu.org> | 2004-06-08 09:29:57 -0700 |
commit | 7187798577a9a9035d1d492d1686217ff5ca30d7 (patch) | |
tree | 916bbf6a5966ddcddcc46c35c1346ae0899e2b22 /gcc/gimplify.c | |
parent | de101ad2f75511c715a846770e3cd446e49f882c (diff) | |
download | gcc-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.c | 42 |
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; } |