summaryrefslogtreecommitdiff
path: root/gcc/gimplify.c
diff options
context:
space:
mode:
authorbstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4>2011-11-14 14:34:33 +0000
committerbstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4>2011-11-14 14:34:33 +0000
commit1e87b08a4c89ee453308a0b09b5bc40a5e3bec10 (patch)
treeed7af923d74901a7a6ff5d07ef176a640a585ba7 /gcc/gimplify.c
parentcbacd2740bd9c2dfe6a0a755f74ddb45781a0665 (diff)
downloadgcc-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.c77
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;