diff options
author | bstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4> | 2011-11-14 14:34:33 +0000 |
---|---|---|
committer | bstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4> | 2011-11-14 14:34:33 +0000 |
commit | 1e87b08a4c89ee453308a0b09b5bc40a5e3bec10 (patch) | |
tree | ed7af923d74901a7a6ff5d07ef176a640a585ba7 /gcc/gimplify.c | |
parent | cbacd2740bd9c2dfe6a0a755f74ddb45781a0665 (diff) | |
download | gcc-1e87b08a4c89ee453308a0b09b5bc40a5e3bec10.tar.gz |
2011-11-14 Basile Starynkevitch <basile@starynkevitch.net>
MELT branch merged with trunk rev 181350 using svnmerge
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/melt-branch@181351 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/gimplify.c')
-rw-r--r-- | gcc/gimplify.c | 77 |
1 files changed, 70 insertions, 7 deletions
diff --git a/gcc/gimplify.c b/gcc/gimplify.c index 99e0d0dad90..cfe6696f590 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -1135,7 +1135,8 @@ gimplify_bind_expr (tree *expr_p, gimple_seq *pre_p) bool old_save_stack = gimplify_ctxp->save_stack; tree t; gimple gimple_bind; - gimple_seq body; + gimple_seq body, cleanup; + gimple stack_save; tree temp = voidify_wrapper_expr (bind_expr, NULL); @@ -1181,22 +1182,50 @@ gimplify_bind_expr (tree *expr_p, gimple_seq *pre_p) gimplify_stmt (&BIND_EXPR_BODY (bind_expr), &body); gimple_bind_set_body (gimple_bind, body); + cleanup = NULL; + stack_save = NULL; if (gimplify_ctxp->save_stack) { - gimple stack_save, stack_restore, gs; - gimple_seq cleanup, new_body; + gimple stack_restore; /* Save stack on entry and restore it on exit. Add a try_finally block to achieve this. Note that mudflap depends on the format of the emitted code: see mx_register_decls(). */ build_stack_save_restore (&stack_save, &stack_restore); - cleanup = new_body = NULL; gimplify_seq_add_stmt (&cleanup, stack_restore); + } + + /* Add clobbers for all variables that go out of scope. */ + for (t = BIND_EXPR_VARS (bind_expr); t ; t = DECL_CHAIN (t)) + { + if (TREE_CODE (t) == VAR_DECL + && !is_global_var (t) + && DECL_CONTEXT (t) == current_function_decl + && !DECL_HARD_REGISTER (t) + && !TREE_THIS_VOLATILE (t) + && !DECL_HAS_VALUE_EXPR_P (t) + /* Only care for variables that have to be in memory. Others + will be rewritten into SSA names, hence moved to the top-level. */ + && needs_to_live_in_memory (t)) + { + tree clobber = build_constructor (TREE_TYPE (t), NULL); + TREE_THIS_VOLATILE (clobber) = 1; + gimplify_seq_add_stmt (&cleanup, gimple_build_assign (t, clobber)); + } + } + + if (cleanup) + { + gimple gs; + gimple_seq new_body; + + new_body = NULL; gs = gimple_build_try (gimple_bind_body (gimple_bind), cleanup, GIMPLE_TRY_FINALLY); - gimplify_seq_add_stmt (&new_body, stack_save); + if (stack_save) + gimplify_seq_add_stmt (&new_body, stack_save); gimplify_seq_add_stmt (&new_body, gs); gimple_bind_set_body (gimple_bind, new_body); } @@ -4525,6 +4554,16 @@ gimplify_modify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, gcc_assert (TREE_CODE (*expr_p) == MODIFY_EXPR || TREE_CODE (*expr_p) == INIT_EXPR); + /* Trying to simplify a clobber using normal logic doesn't work, + so handle it here. */ + if (TREE_CLOBBER_P (*from_p)) + { + gcc_assert (!want_value && TREE_CODE (*to_p) == VAR_DECL); + gimplify_seq_add_stmt (pre_p, gimple_build_assign (*to_p, *from_p)); + *expr_p = NULL; + return GS_ALL_DONE; + } + /* Insert pointer conversions required by the middle-end that are not required by the frontend. This fixes middle-end type checking for for example gcc.dg/redecl-6.c. */ @@ -5306,6 +5345,8 @@ gimplify_target_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p) if (init) { + tree cleanup = NULL_TREE; + /* TARGET_EXPR temps aren't part of the enclosing block, so add it to the temps list. Handle also variable length TARGET_EXPRs. */ if (TREE_CODE (DECL_SIZE (temp)) != INTEGER_CST) @@ -5340,8 +5381,30 @@ gimplify_target_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p) /* If needed, push the cleanup for the temp. */ if (TARGET_EXPR_CLEANUP (targ)) - gimple_push_cleanup (temp, TARGET_EXPR_CLEANUP (targ), - CLEANUP_EH_ONLY (targ), pre_p); + { + if (CLEANUP_EH_ONLY (targ)) + gimple_push_cleanup (temp, TARGET_EXPR_CLEANUP (targ), + CLEANUP_EH_ONLY (targ), pre_p); + else + cleanup = TARGET_EXPR_CLEANUP (targ); + } + + /* Add a clobber for the temporary going out of scope, like + gimplify_bind_expr. */ + if (needs_to_live_in_memory (temp)) + { + tree clobber = build_constructor (TREE_TYPE (temp), NULL); + TREE_THIS_VOLATILE (clobber) = true; + clobber = build2 (MODIFY_EXPR, TREE_TYPE (temp), temp, clobber); + if (cleanup) + cleanup = build2 (COMPOUND_EXPR, void_type_node, cleanup, + clobber); + else + cleanup = clobber; + } + + if (cleanup) + gimple_push_cleanup (temp, cleanup, false, pre_p); /* Only expand this once. */ TREE_OPERAND (targ, 3) = init; |