re PR target/34879 (__builtin_setjmp / __builtin_longjmp fails stack frame address...
authorAndy Hutchinson <hutchinsonandy@aim.com>
Mon, 2 Jun 2008 22:08:25 +0000 (22:08 +0000)
committerAndy Hutchinson <hutchinsonandy@gcc.gnu.org>
Mon, 2 Jun 2008 22:08:25 +0000 (22:08 +0000)
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
gcc/config/avr/avr.c
gcc/config/avr/avr.md

index 8db8a5552534300e33b1bda77ecc97bbe64a993a..56b6ddbb7aac2756e03908dc956cb4561f1f7a27 100644 (file)
@@ -1,3 +1,11 @@
+2008-06-02  Andy Hutchinson  <hutchinsonandy@aim.com> 
+
+       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  <rdsandiford@googlemail.com>
 
        * config/mips/mips.c (mips_emit_loadgp): Return early if
index 7135c79610a4a5e62c8eebef412c1d126f475a43..405f42f76328b497ca3ab53d492b7ca5b14c91b5 100644 (file)
@@ -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;
 \f
 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
index a4914c4aa6185729a517d35a7bf07ce47f378bff..0fd371282cc928212aebe86ca8fc73ef69d7b1b0 100644 (file)
@@ -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")
                       (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"))]