aboutsummaryrefslogtreecommitdiff
path: root/gcc/stmt.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/stmt.c')
-rw-r--r--gcc/stmt.c42
1 files changed, 32 insertions, 10 deletions
diff --git a/gcc/stmt.c b/gcc/stmt.c
index 38572ca..6ecfcd2 100644
--- a/gcc/stmt.c
+++ b/gcc/stmt.c
@@ -903,7 +903,15 @@ expand_goto_internal (body, label, last_insn)
deleted as dead by flow. */
clear_pending_stack_adjust ();
do_pending_stack_adjust ();
- emit_stack_restore (SAVE_BLOCK, stack_level, NULL_RTX);
+
+ /* Don't do this adjust if it's to the end label and this function
+ is to return with a depressed stack pointer. */
+ if (label == return_label
+ && (TYPE_RETURNS_STACK_DEPRESSED
+ (TREE_TYPE (current_function_decl))))
+ ;
+ else
+ emit_stack_restore (SAVE_BLOCK, stack_level, NULL_RTX);
}
if (body != 0 && DECL_TOO_LATE (body))
@@ -1182,7 +1190,10 @@ fixup_gotos (thisblock, stack_level, cleanup_list, first_insn, dont_jump_in)
/* Restore stack level for the biggest contour that this
jump jumps out of. */
- if (f->stack_level)
+ if (f->stack_level
+ && ! (f->target_rtl == return_label
+ && (TYPE_RETURNS_STACK_DEPRESSED
+ (TREE_TYPE (current_function_decl)))))
emit_stack_restore (SAVE_BLOCK, f->stack_level, f->before_jump);
/* Finish up the sequence containing the insns which implement the
@@ -3667,6 +3678,23 @@ expand_end_bindings (vars, mark_ends, dont_jump_in)
pop_temp_slots ();
}
+/* Generate code to save the stack pointer at the start of the current block
+ and set up to restore it on exit. */
+
+void
+save_stack_pointer ()
+{
+ struct nesting *thisblock = block_stack;
+
+ if (thisblock->data.block.stack_level == 0)
+ {
+ emit_stack_save (thisblock->next ? SAVE_BLOCK : SAVE_FUNCTION,
+ &thisblock->data.block.stack_level,
+ thisblock->data.block.first_insn);
+ stack_block_stack = thisblock;
+ }
+}
+
/* Generate RTL for the automatic variable declaration DECL.
(Other kinds of declarations are simply ignored if seen here.) */
@@ -3777,14 +3805,8 @@ expand_decl (decl)
/* Record the stack pointer on entry to block, if have
not already done so. */
- if (thisblock->data.block.stack_level == 0)
- {
- do_pending_stack_adjust ();
- emit_stack_save (thisblock->next ? SAVE_BLOCK : SAVE_FUNCTION,
- &thisblock->data.block.stack_level,
- thisblock->data.block.first_insn);
- stack_block_stack = thisblock;
- }
+ do_pending_stack_adjust ();
+ save_stack_pointer ();
/* In function-at-a-time mode, variable_size doesn't expand this,
so do it now. */