From 1bf296437b0a3361c2b005c03204c16b3f0de234 Mon Sep 17 00:00:00 2001 From: Andy Hutchinson Date: Mon, 2 Jun 2008 22:08:25 +0000 Subject: [PATCH] re PR target/34879 (__builtin_setjmp / __builtin_longjmp fails stack frame address with O2, O3 and Os) PR target/34879 * config/avr/avr.c (TARGET_BUILTIN_SETJMP_FRAME_VALUE): Redefine. (avr_builtin_setjmp_frame_value): New function. * config/avr/avr.md (nonlocal_goto_receiver): Define. (nonlocal_goto): Define. From-SVN: r136297 --- gcc/ChangeLog | 8 ++++++ gcc/config/avr/avr.c | 16 ++++++++++++ gcc/config/avr/avr.md | 60 ++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 83 insertions(+), 1 deletion(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 8db8a555253..56b6ddbb7aa 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2008-06-02 Andy Hutchinson + + PR target/34879 + * config/avr/avr.c (TARGET_BUILTIN_SETJMP_FRAME_VALUE): Redefine. + (avr_builtin_setjmp_frame_value): New function. + * config/avr/avr.md (nonlocal_goto_receiver): Define. + (nonlocal_goto): Define. + 2008-06-02 Richard Sandiford * config/mips/mips.c (mips_emit_loadgp): Return early if diff --git a/gcc/config/avr/avr.c b/gcc/config/avr/avr.c index 7135c79610a..405f42f7632 100644 --- a/gcc/config/avr/avr.c +++ b/gcc/config/avr/avr.c @@ -83,6 +83,8 @@ static bool avr_rtx_costs (rtx, int, int, int *); static int avr_address_cost (rtx); static bool avr_return_in_memory (const_tree, const_tree); static struct machine_function * avr_init_machine_status (void); +static rtx avr_builtin_setjmp_frame_value (void); + /* Allocate registers from r25 to r8 for parameters for function calls. */ #define FIRST_CUM_REG 26 @@ -323,6 +325,9 @@ int avr_case_values_threshold = 30000; #undef TARGET_STRICT_ARGUMENT_NAMING #define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true +#undef TARGET_BUILTIN_SETJMP_FRAME_VALUE +#define TARGET_BUILTIN_SETJMP_FRAME_VALUE avr_builtin_setjmp_frame_value + struct gcc_target targetm = TARGET_INITIALIZER; void @@ -523,6 +528,17 @@ initial_elimination_offset (int from, int to) } } +/* Actual start of frame is virtual_stack_vars_rtx this is offset from + frame pointer by +STARTING_FRAME_OFFSET. + Using saved frame = virtual_stack_vars_rtx - STARTING_FRAME_OFFSET + avoids creating add/sub of offset in nonlocal goto and setjmp. */ + +rtx avr_builtin_setjmp_frame_value (void) +{ + return gen_rtx_MINUS (Pmode, virtual_stack_vars_rtx, + gen_int_mode (STARTING_FRAME_OFFSET, Pmode)); +} + /* Return 1 if the function epilogue is just a single "ret". */ int diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md index a4914c4aa61..0fd371282cc 100644 --- a/gcc/config/avr/avr.md +++ b/gcc/config/avr/avr.md @@ -58,7 +58,8 @@ (UNSPECV_PROLOGUE_SAVES 0) (UNSPECV_EPILOGUE_RESTORES 1) (UNSPECV_WRITE_SP_IRQ_ON 2) - (UNSPECV_WRITE_SP_IRQ_OFF 3)]) + (UNSPECV_WRITE_SP_IRQ_OFF 3) + (UNSPECV_GOTO_RECEIVER 4)]) (include "predicates.md") (include "constraints.md") @@ -115,6 +116,63 @@ (const_int 2))] (const_int 2))) +;;======================================================================== +;; The following is used by nonlocal_goto and setjmp. +;; The receiver pattern will create no instructions since internally +;; virtual_stack_vars = hard_frame_pointer + 1 so the RTL become R28=R28 +;; This avoids creating add/sub offsets in frame_pointer save/resore. +;; The 'null' receiver also avoids problems with optimisation +;; not recognising incoming jmp and removing code that resets frame_pointer. +;; The code derived from builtins.c. + +(define_expand "nonlocal_goto_receiver" + [(set (reg:HI REG_Y) + (unspec_volatile:HI [(const_int 0)] UNSPECV_GOTO_RECEIVER))] + "" + { + emit_move_insn (virtual_stack_vars_rtx, + gen_rtx_PLUS (Pmode, hard_frame_pointer_rtx, + gen_int_mode (STARTING_FRAME_OFFSET, + Pmode))); + /* This might change the hard frame pointer in ways that aren't + apparent to early optimization passes, so force a clobber. */ + emit_clobber (hard_frame_pointer_rtx); + DONE; + }) + + +;; Defining nonlocal_goto_receiver means we must also define this. +;; even though its function is identical to that in builtins.c + +(define_expand "nonlocal_goto" + [ + (use (match_operand 0 "general_operand")) + (use (match_operand 1 "general_operand")) + (use (match_operand 2 "general_operand")) + (use (match_operand 3 "general_operand")) + ] + "" +{ + rtx r_label = copy_to_reg (operands[1]); + rtx r_fp = operands[3]; + rtx r_sp = operands[2]; + + emit_clobber (gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (VOIDmode))); + + emit_clobber (gen_rtx_MEM (BLKmode, hard_frame_pointer_rtx)); + + emit_move_insn (hard_frame_pointer_rtx, r_fp); + emit_stack_restore (SAVE_NONLOCAL, r_sp, NULL_RTX); + + emit_use (hard_frame_pointer_rtx); + emit_use (stack_pointer_rtx); + + emit_indirect_jump (r_label); + + DONE; +}) + + (define_insn "*pushqi" [(set (mem:QI (post_dec (reg:HI REG_SP))) (match_operand:QI 0 "reg_or_0_operand" "r,L"))] -- 2.30.2