Commit d33606c3 by Eric Botcazou Committed by Eric Botcazou

insn-notes.def (UPDATE_SJLJ_CONTEXT): New note.

	* 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
parent 76e048a8
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> 2015-05-19 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
* calls.c: Always define STACK_GROWS_DOWNWARD as 0 or 1. * calls.c: Always define STACK_GROWS_DOWNWARD as 0 or 1.
......
...@@ -120,7 +120,6 @@ static int apply_result_size (void); ...@@ -120,7 +120,6 @@ static int apply_result_size (void);
#if defined (HAVE_untyped_call) || defined (HAVE_untyped_return) #if defined (HAVE_untyped_call) || defined (HAVE_untyped_return)
static rtx result_vector (int, rtx); static rtx result_vector (int, rtx);
#endif #endif
static void expand_builtin_update_setjmp_buf (rtx);
static void expand_builtin_prefetch (tree); static void expand_builtin_prefetch (tree);
static rtx expand_builtin_apply_args (void); static rtx expand_builtin_apply_args (void);
static rtx expand_builtin_apply_args_1 (void); static rtx expand_builtin_apply_args_1 (void);
...@@ -1213,10 +1212,10 @@ expand_builtin_nonlocal_goto (tree exp) ...@@ -1213,10 +1212,10 @@ expand_builtin_nonlocal_goto (tree exp)
/* __builtin_update_setjmp_buf is passed a pointer to an array of five words /* __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. (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 It updates the stack pointer in that block to the current value. This is
stack pointer. */ also called directly by the SJLJ exception handling code. */
static void void
expand_builtin_update_setjmp_buf (rtx buf_addr) expand_builtin_update_setjmp_buf (rtx buf_addr)
{ {
machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL); machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
...@@ -5887,10 +5886,12 @@ expand_stack_restore (tree var) ...@@ -5887,10 +5886,12 @@ expand_stack_restore (tree var)
prev = get_last_insn (); prev = get_last_insn ();
emit_stack_restore (SAVE_BLOCK, sa); emit_stack_restore (SAVE_BLOCK, sa);
record_new_stack_level ();
fixup_args_size_notes (prev, get_last_insn (), 0); fixup_args_size_notes (prev, get_last_insn (), 0);
} }
/* Emit code to save the current value of stack. */ /* Emit code to save the current value of stack. */
static rtx static rtx
...@@ -5898,7 +5899,6 @@ expand_stack_save (void) ...@@ -5898,7 +5899,6 @@ expand_stack_save (void)
{ {
rtx ret = NULL_RTX; rtx ret = NULL_RTX;
do_pending_stack_adjust ();
emit_stack_save (SAVE_BLOCK, &ret); emit_stack_save (SAVE_BLOCK, &ret);
return ret; return ret;
} }
......
...@@ -59,6 +59,7 @@ extern unsigned int get_pointer_alignment (tree); ...@@ -59,6 +59,7 @@ extern unsigned int get_pointer_alignment (tree);
extern tree c_strlen (tree, int); extern tree c_strlen (tree, int);
extern void expand_builtin_setjmp_setup (rtx, rtx); extern void expand_builtin_setjmp_setup (rtx, rtx);
extern void expand_builtin_setjmp_receiver (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 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_strncpy_read_str (void *, HOST_WIDE_INT, machine_mode);
extern rtx builtin_memset_read_str (void *, HOST_WIDE_INT, machine_mode); extern rtx builtin_memset_read_str (void *, HOST_WIDE_INT, machine_mode);
......
...@@ -3649,12 +3649,9 @@ expand_call (tree exp, rtx target, int ignore) ...@@ -3649,12 +3649,9 @@ expand_call (tree exp, rtx target, int ignore)
stack_usage_map = initial_stack_usage_map; stack_usage_map = initial_stack_usage_map;
} }
/* If this was alloca, record the new stack level for nonlocal gotos. /* If this was alloca, record the new stack level. */
Check for the handler slots since we might not have a save area if (flags & ECF_MAY_BE_ALLOCA)
for non-local gotos. */ record_new_stack_level ();
if ((flags & ECF_MAY_BE_ALLOCA) && cfun->nonlocal_goto_save_area != 0)
update_nonlocal_goto_save_area ();
/* Free up storage we no longer need. */ /* Free up storage we no longer need. */
for (i = 0; i < num_actuals; ++i) for (i = 0; i < num_actuals; ++i)
......
...@@ -4209,6 +4209,7 @@ duplicate_insn_chain (rtx_insn *from, rtx_insn *to) ...@@ -4209,6 +4209,7 @@ duplicate_insn_chain (rtx_insn *from, rtx_insn *to)
break; break;
case NOTE_INSN_EPILOGUE_BEG: case NOTE_INSN_EPILOGUE_BEG:
case NOTE_INSN_UPDATE_SJLJ_CONTEXT:
emit_note_copy (as_a <rtx_note *> (insn)); emit_note_copy (as_a <rtx_note *> (insn));
break; break;
......
...@@ -1126,6 +1126,21 @@ sjlj_mark_call_sites (void) ...@@ -1126,6 +1126,21 @@ sjlj_mark_call_sites (void)
if (LABEL_P (insn)) if (LABEL_P (insn))
last_call_site = -2; 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)) if (! INSN_P (insn))
continue; continue;
...@@ -1495,6 +1510,18 @@ sjlj_build_landing_pads (void) ...@@ -1495,6 +1510,18 @@ sjlj_build_landing_pads (void)
sjlj_lp_call_site_index.release (); 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 /* After initial rtl generation, call back to finish generating
exception support code. */ exception support code. */
......
...@@ -252,6 +252,7 @@ extern hash_map<void *, void *> *duplicate_eh_regions ...@@ -252,6 +252,7 @@ extern hash_map<void *, void *> *duplicate_eh_regions
(struct function *, eh_region, int, duplicate_eh_regions_map, void *); (struct function *, eh_region, int, duplicate_eh_regions_map, void *);
extern void sjlj_emit_function_exit_after (rtx_insn *); 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_cleanup (eh_region);
extern eh_region gen_eh_region_try (eh_region); extern eh_region gen_eh_region_try (eh_region);
......
...@@ -1096,8 +1096,8 @@ emit_stack_restore (enum save_level save_level, rtx sa) ...@@ -1096,8 +1096,8 @@ emit_stack_restore (enum save_level save_level, rtx sa)
} }
/* Invoke emit_stack_save on the nonlocal_goto_save_area for the current /* Invoke emit_stack_save on the nonlocal_goto_save_area for the current
function. This function should be called whenever we allocate or function. This should be called whenever we allocate or deallocate
deallocate dynamic stack space. */ dynamic stack space. */
void void
update_nonlocal_goto_save_area (void) update_nonlocal_goto_save_area (void)
...@@ -1117,6 +1117,21 @@ update_nonlocal_goto_save_area (void) ...@@ -1117,6 +1117,21 @@ update_nonlocal_goto_save_area (void)
emit_stack_save (SAVE_NONLOCAL, &r_save); 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 /* Return an rtx representing the address of an area of memory dynamically
pushed on the stack. pushed on the stack.
...@@ -1479,9 +1494,8 @@ allocate_dynamic_stack_space (rtx size, unsigned size_align, ...@@ -1479,9 +1494,8 @@ allocate_dynamic_stack_space (rtx size, unsigned size_align,
/* Now that we've committed to a return value, mark its alignment. */ /* Now that we've committed to a return value, mark its alignment. */
mark_reg_pointer (target, required_align); mark_reg_pointer (target, required_align);
/* Record the new stack level for nonlocal gotos. */ /* Record the new stack level. */
if (cfun->nonlocal_goto_save_area != 0) record_new_stack_level ();
update_nonlocal_goto_save_area ();
return target; return target;
} }
......
...@@ -78,6 +78,9 @@ extern void emit_stack_restore (enum save_level, rtx); ...@@ -78,6 +78,9 @@ extern void emit_stack_restore (enum save_level, rtx);
/* Invoke emit_stack_save for the nonlocal_goto_save_area. */ /* Invoke emit_stack_save for the nonlocal_goto_save_area. */
extern void update_nonlocal_goto_save_area (void); 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. */ /* Allocate some space on the stack dynamically and return its address. */
extern rtx allocate_dynamic_stack_space (rtx, unsigned, unsigned, bool); extern rtx allocate_dynamic_stack_space (rtx, unsigned, unsigned, bool);
......
...@@ -2215,6 +2215,7 @@ final_scan_insn (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED, ...@@ -2215,6 +2215,7 @@ final_scan_insn (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED,
switch (NOTE_KIND (insn)) switch (NOTE_KIND (insn))
{ {
case NOTE_INSN_DELETED: case NOTE_INSN_DELETED:
case NOTE_INSN_UPDATE_SJLJ_CONTEXT:
break; break;
case NOTE_INSN_SWITCH_TEXT_SECTIONS: case NOTE_INSN_SWITCH_TEXT_SECTIONS:
......
...@@ -87,4 +87,8 @@ INSN_NOTE (CFI) ...@@ -87,4 +87,8 @@ INSN_NOTE (CFI)
label that should be emitted. */ label that should be emitted. */
INSN_NOTE (CFI_LABEL) 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 #undef INSN_NOTE
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment