* insn-notes.def (UPDATE_SJLJ_CONTEXT): New note.
* builtins.c (expand_builtin_update_setjmp_buf): Make global.
(expand_stack_restore): Call record_new_stack_level.
(expand_stack_save): Do not call do_pending_stack_adjust.
* builtins.h (expand_builtin_update_setjmp_buf): Declare.
* calls.c (expand_call): Call record_new_stack_level for alloca.
* except.c (sjlj_mark_call_sites): Expand builtin_update_setjmp_buf
wherever a NOTE_INSN_UPDATE_SJLJ_CONTEXT note is present.
(update_sjlj_context): New global function.
* except.h (update_sjlj_context): Declare.
* explow.c (record_new_stack_level): New global function.
(allocate_dynamic_stack_space): Call record_new_stack_level.
* explow.h (record_new_stack_level): Declare.
* final.c (final_scan_insn): Deal with NOTE_INSN_UPDATE_SJLJ_CONTEXT.
* cfgrtl.c (duplicate_insn_chain): Likewise.
Co-Authored-By: Tristan Gingold <gingold@adacore.com>
From-SVN: r223348
+2015-05-19 Eric Botcazou <ebotcazou@adacore.com>
+ Tristan Gingold <gingold@adacore.com>
+
+ * insn-notes.def (UPDATE_SJLJ_CONTEXT): New note.
+ * builtins.c (expand_builtin_update_setjmp_buf): Make global.
+ (expand_stack_restore): Call record_new_stack_level.
+ (expand_stack_save): Do not call do_pending_stack_adjust.
+ * builtins.h (expand_builtin_update_setjmp_buf): Declare.
+ * calls.c (expand_call): Call record_new_stack_level for alloca.
+ * except.c (sjlj_mark_call_sites): Expand builtin_update_setjmp_buf
+ wherever a NOTE_INSN_UPDATE_SJLJ_CONTEXT note is present.
+ (update_sjlj_context): New global function.
+ * except.h (update_sjlj_context): Declare.
+ * explow.c (record_new_stack_level): New global function.
+ (allocate_dynamic_stack_space): Call record_new_stack_level.
+ * explow.h (record_new_stack_level): Declare.
+ * final.c (final_scan_insn): Deal with NOTE_INSN_UPDATE_SJLJ_CONTEXT.
+ * cfgrtl.c (duplicate_insn_chain): Likewise.
+
2015-05-19 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
* calls.c: Always define STACK_GROWS_DOWNWARD as 0 or 1.
#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);
/* __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);
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
{
rtx ret = NULL_RTX;
- do_pending_stack_adjust ();
emit_stack_save (SAVE_BLOCK, &ret);
return ret;
}
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);
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)
break;
case NOTE_INSN_EPILOGUE_BEG:
+ case NOTE_INSN_UPDATE_SJLJ_CONTEXT:
emit_note_copy (as_a <rtx_note *> (insn));
break;
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;
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. */
(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);
}
/* 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)
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 ();
+}
\f
/* Return an rtx representing the address of an area of memory dynamically
pushed on the stack.
/* 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;
}
/* 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);
switch (NOTE_KIND (insn))
{
case NOTE_INSN_DELETED:
+ case NOTE_INSN_UPDATE_SJLJ_CONTEXT:
break;
case NOTE_INSN_SWITCH_TEXT_SECTIONS:
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