aboutsummaryrefslogtreecommitdiff
path: root/gcc/gimplify.c
diff options
context:
space:
mode:
authorEric Botcazou <ebotcazou@adacore.com>2015-12-04 11:57:15 +0000
committerEric Botcazou <ebotcazou@gcc.gnu.org>2015-12-04 11:57:15 +0000
commit03c00798828246afcfd998988c9fee8321b9313c (patch)
treed944ebe798474d59975ae0092d6818956e8aeba8 /gcc/gimplify.c
parenta3eb8a52b5c1e1f3af616d88bf6a057dd4f81eb3 (diff)
downloadgcc-03c00798828246afcfd998988c9fee8321b9313c.zip
gcc-03c00798828246afcfd998988c9fee8321b9313c.tar.gz
gcc-03c00798828246afcfd998988c9fee8321b9313c.tar.bz2
re PR middle-end/65958 (-fstack-check breaks alloca on architectures using generic stack checking)
PR middle-end/65958 * gimplify.c (struct gimplify_ctx): Turn boolean fields into 1-bit fields, add keep_stack and reorder them. (gimplify_bind_expr): Save gimplify_ctxp->keep_stack on entry then set it to false. Do not insert a stack save/restore pair if it has been set to true by the gimplification of the statements. Restore it to the saved value on exit if it is still false. (gimplify_vla_decl): Do not set gimplify_ctxp->save_stack here. (gimplify_call_expr) <BUILT_IN_ALLOCA[_WITH_ALIGN]>: New case. Set either save_stack or keep_stack depending on CALL_ALLOCA_FOR_VAR_P. * doc/extend.texi (Variable Length): Document new behavior. * doc/generic.texi (Blocks): Document new handling of VLAs. From-SVN: r231260
Diffstat (limited to 'gcc/gimplify.c')
-rw-r--r--gcc/gimplify.c38
1 files changed, 28 insertions, 10 deletions
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 7146a01..80c6bf2 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -155,10 +155,11 @@ struct gimplify_ctx
hash_table<gimplify_hasher> *temp_htab;
int conditions;
- bool save_stack;
- bool into_ssa;
- bool allow_rhs_cond_expr;
- bool in_cleanup_point_expr;
+ unsigned into_ssa : 1;
+ unsigned allow_rhs_cond_expr : 1;
+ unsigned in_cleanup_point_expr : 1;
+ unsigned keep_stack : 1;
+ unsigned save_stack : 1;
};
struct gimplify_omp_ctx
@@ -1080,6 +1081,7 @@ static enum gimplify_status
gimplify_bind_expr (tree *expr_p, gimple_seq *pre_p)
{
tree bind_expr = *expr_p;
+ bool old_keep_stack = gimplify_ctxp->keep_stack;
bool old_save_stack = gimplify_ctxp->save_stack;
tree t;
gbind *bind_stmt;
@@ -1129,9 +1131,10 @@ gimplify_bind_expr (tree *expr_p, gimple_seq *pre_p)
}
bind_stmt = gimple_build_bind (BIND_EXPR_VARS (bind_expr), NULL,
- BIND_EXPR_BLOCK (bind_expr));
+ BIND_EXPR_BLOCK (bind_expr));
gimple_push_bind_expr (bind_stmt);
+ gimplify_ctxp->keep_stack = false;
gimplify_ctxp->save_stack = false;
/* Gimplify the body into the GIMPLE_BIND tuple's body. */
@@ -1154,7 +1157,10 @@ gimplify_bind_expr (tree *expr_p, gimple_seq *pre_p)
cleanup = NULL;
stack_save = NULL;
- if (gimplify_ctxp->save_stack)
+
+ /* If the code both contains VLAs and calls alloca, then we cannot reclaim
+ the stack space allocated to the VLAs. */
+ if (gimplify_ctxp->save_stack && !gimplify_ctxp->keep_stack)
{
gcall *stack_restore;
@@ -1236,7 +1242,11 @@ gimplify_bind_expr (tree *expr_p, gimple_seq *pre_p)
gimple_bind_set_body (bind_stmt, new_body);
}
+ /* keep_stack propagates all the way up to the outermost BIND_EXPR. */
+ if (!gimplify_ctxp->keep_stack)
+ gimplify_ctxp->keep_stack = old_keep_stack;
gimplify_ctxp->save_stack = old_save_stack;
+
gimple_pop_bind_expr ();
gimplify_seq_add_stmt (pre_p, bind_stmt);
@@ -1393,10 +1403,6 @@ gimplify_vla_decl (tree decl, gimple_seq *seq_p)
t = build2 (MODIFY_EXPR, TREE_TYPE (addr), addr, t);
gimplify_and_add (t, seq_p);
-
- /* Indicate that we need to restore the stack level when the
- enclosing BIND_EXPR is exited. */
- gimplify_ctxp->save_stack = true;
}
/* A helper function to be called via walk_tree. Mark all labels under *TP
@@ -2377,6 +2383,18 @@ gimplify_call_expr (tree *expr_p, gimple_seq *pre_p, bool want_value)
&& DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
switch (DECL_FUNCTION_CODE (fndecl))
{
+ case BUILT_IN_ALLOCA:
+ case BUILT_IN_ALLOCA_WITH_ALIGN:
+ /* If the call has been built for a variable-sized object, then we
+ want to restore the stack level when the enclosing BIND_EXPR is
+ exited to reclaim the allocated space; otherwise, we precisely
+ need to do the opposite and preserve the latest stack level. */
+ if (CALL_ALLOCA_FOR_VAR_P (*expr_p))
+ gimplify_ctxp->save_stack = true;
+ else
+ gimplify_ctxp->keep_stack = true;
+ break;
+
case BUILT_IN_VA_START:
{
builtin_va_start_p = TRUE;