Index: builtins.c =================================================================== --- builtins.c (revision 222673) +++ builtins.c (working copy) @@ -120,7 +120,6 @@ static int apply_result_size (void); #if defined (HAVE_untyped_call) || defined (HAVE_untyped_return) static rtx result_vector (int, rtx); #endif -static void expand_builtin_update_setjmp_buf (rtx); static void expand_builtin_prefetch (tree); static rtx expand_builtin_apply_args (void); static rtx expand_builtin_apply_args_1 (void); @@ -1213,10 +1212,10 @@ expand_builtin_nonlocal_goto (tree exp) /* __builtin_update_setjmp_buf is passed a pointer to an array of five words (not all will be used on all machines) that was passed to __builtin_setjmp. - It updates the stack pointer in that block to correspond to the current - stack pointer. */ + It updates the stack pointer in that block to the current value. This is + also called directly by the SJLJ exception handling code. */ -static void +void expand_builtin_update_setjmp_buf (rtx buf_addr) { machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL); @@ -5891,10 +5890,12 @@ expand_stack_restore (tree var) prev = get_last_insn (); emit_stack_restore (SAVE_BLOCK, sa); + + record_new_stack_level (); + fixup_args_size_notes (prev, get_last_insn (), 0); } - /* Emit code to save the current value of stack. */ static rtx @@ -5902,7 +5903,6 @@ expand_stack_save (void) { rtx ret = NULL_RTX; - do_pending_stack_adjust (); emit_stack_save (SAVE_BLOCK, &ret); return ret; } Index: final.c =================================================================== --- final.c (revision 222673) +++ final.c (working copy) @@ -2215,6 +2215,7 @@ final_scan_insn (rtx_insn *insn, FILE *f switch (NOTE_KIND (insn)) { case NOTE_INSN_DELETED: + case NOTE_INSN_UPDATE_SJLJ_CONTEXT: break; case NOTE_INSN_SWITCH_TEXT_SECTIONS: Index: builtins.h =================================================================== --- builtins.h (revision 222673) +++ builtins.h (working copy) @@ -59,6 +59,7 @@ extern unsigned int get_pointer_alignmen extern tree c_strlen (tree, int); extern void expand_builtin_setjmp_setup (rtx, rtx); extern void expand_builtin_setjmp_receiver (rtx); +extern void expand_builtin_update_setjmp_buf (rtx); extern tree mathfn_built_in (tree, enum built_in_function fn); extern rtx builtin_strncpy_read_str (void *, HOST_WIDE_INT, machine_mode); extern rtx builtin_memset_read_str (void *, HOST_WIDE_INT, machine_mode); Index: insn-notes.def =================================================================== --- insn-notes.def (revision 222673) +++ insn-notes.def (working copy) @@ -87,4 +87,8 @@ INSN_NOTE (CFI) label that should be emitted. */ INSN_NOTE (CFI_LABEL) +/* This note indicates that the function context must be updated if + the Setjmp/Longjmp exception mechanism is used. */ +INSN_NOTE (UPDATE_SJLJ_CONTEXT) + #undef INSN_NOTE Index: calls.c =================================================================== --- calls.c (revision 222673) +++ calls.c (working copy) @@ -3632,12 +3632,9 @@ expand_call (tree exp, rtx target, int i stack_usage_map = initial_stack_usage_map; } - /* If this was alloca, record the new stack level for nonlocal gotos. - Check for the handler slots since we might not have a save area - for non-local gotos. */ - - if ((flags & ECF_MAY_BE_ALLOCA) && cfun->nonlocal_goto_save_area != 0) - update_nonlocal_goto_save_area (); + /* If this was alloca, record the new stack level. */ + if (flags & ECF_MAY_BE_ALLOCA) + record_new_stack_level (); /* Free up storage we no longer need. */ for (i = 0; i < num_actuals; ++i) Index: except.c =================================================================== --- except.c (revision 222673) +++ except.c (working copy) @@ -1126,6 +1126,21 @@ sjlj_mark_call_sites (void) if (LABEL_P (insn)) last_call_site = -2; + /* If the function allocates dynamic stack space, the context must + be updated after every allocation/deallocation accordingly. */ + if (NOTE_P (insn) && NOTE_KIND (insn) == NOTE_INSN_UPDATE_SJLJ_CONTEXT) + { + rtx buf_addr; + + start_sequence (); + buf_addr = plus_constant (Pmode, XEXP (crtl->eh.sjlj_fc, 0), + sjlj_fc_jbuf_ofs); + expand_builtin_update_setjmp_buf (buf_addr); + p = get_insns (); + end_sequence (); + emit_insn_before (p, insn); + } + if (! INSN_P (insn)) continue; @@ -1495,6 +1510,18 @@ sjlj_build_landing_pads (void) sjlj_lp_call_site_index.release (); } +/* Update the sjlj function context. This function should be called + whenever we allocate or deallocate dynamic stack space. */ + +void +update_sjlj_context (void) +{ + if (!flag_exceptions) + return; + + emit_note (NOTE_INSN_UPDATE_SJLJ_CONTEXT); +} + /* After initial rtl generation, call back to finish generating exception support code. */ Index: except.h =================================================================== --- except.h (revision 222673) +++ except.h (working copy) @@ -252,6 +252,7 @@ extern hash_map *duplica (struct function *, eh_region, int, duplicate_eh_regions_map, void *); extern void sjlj_emit_function_exit_after (rtx_insn *); +extern void update_sjlj_context (void); extern eh_region gen_eh_region_cleanup (eh_region); extern eh_region gen_eh_region_try (eh_region); Index: explow.c =================================================================== --- explow.c (revision 222673) +++ explow.c (working copy) @@ -1096,8 +1096,8 @@ emit_stack_restore (enum save_level save } /* Invoke emit_stack_save on the nonlocal_goto_save_area for the current - function. This function should be called whenever we allocate or - deallocate dynamic stack space. */ + function. This should be called whenever we allocate or deallocate + dynamic stack space. */ void update_nonlocal_goto_save_area (void) @@ -1117,6 +1117,21 @@ update_nonlocal_goto_save_area (void) emit_stack_save (SAVE_NONLOCAL, &r_save); } + +/* Record a new stack level for the current function. This should be called + whenever we allocate or deallocate dynamic stack space. */ + +void +record_new_stack_level (void) +{ + /* Record the new stack level for nonlocal gotos. */ + if (cfun->nonlocal_goto_save_area) + update_nonlocal_goto_save_area (); + + /* Record the new stack level for SJLJ exceptions. */ + if (targetm_common.except_unwind_info (&global_options) == UI_SJLJ) + update_sjlj_context (); +} /* Return an rtx representing the address of an area of memory dynamically pushed on the stack. @@ -1479,9 +1494,8 @@ allocate_dynamic_stack_space (rtx size, /* Now that we've committed to a return value, mark its alignment. */ mark_reg_pointer (target, required_align); - /* Record the new stack level for nonlocal gotos. */ - if (cfun->nonlocal_goto_save_area != 0) - update_nonlocal_goto_save_area (); + /* Record the new stack level. */ + record_new_stack_level (); return target; } Index: explow.h =================================================================== --- explow.h (revision 222673) +++ explow.h (working copy) @@ -78,6 +78,9 @@ extern void emit_stack_restore (enum sav /* Invoke emit_stack_save for the nonlocal_goto_save_area. */ extern void update_nonlocal_goto_save_area (void); +/* Record a new stack level. */ +extern void record_new_stack_level (void); + /* Allocate some space on the stack dynamically and return its address. */ extern rtx allocate_dynamic_stack_space (rtx, unsigned, unsigned, bool); Index: cfgrtl.c =================================================================== --- cfgrtl.c (revision 222673) +++ cfgrtl.c (working copy) @@ -4209,6 +4209,7 @@ duplicate_insn_chain (rtx_insn *from, rt break; case NOTE_INSN_EPILOGUE_BEG: + case NOTE_INSN_UPDATE_SJLJ_CONTEXT: emit_note_copy (as_a (insn)); break;