The simultaneous use of setjmp/longjmp and alloca isn't an easy matter.  The 
crux of the problem is that the stack pointer is saved into the setjmp buffer 
upon its creation.  If a dynamic stack allocation occurs afterward, changing 
the stack pointer, does the value saved in the buffer need to be updated?

The answer is, it depends.  The default implementations of SJLJ exceptions and 
of the __builtin_setjmp/__builtin_longjmp support don't update it.  This is 
correct in some situations but not in others (VLAs), see PR middle-end/19774 
and http://gcc.gnu.org/ml/gcc-patches/2007-03/msg00946.html for a patch.

In Ada, we implement our SJLJ exception scheme "manually", i.e. part in the 
front-end and the rest piggybacked on __builtin_setjmp/__builtin_longjmp.  
Since we have only VLAs (no alloca in particular), we need to update it in all 
cases and Richard K. devised a special built-in function to do so:
 http://gcc.gnu.org/ml/gcc-patches/2004-04/msg01739.html

On top of that, SPARC adds its own twist as it is the only architecture to 
define SETJMP_VIA_SAVE_AREA.  On the SPARC, we don't really use the setjmp 
buffer but instead reuse the register window save area present in all frames.
But there is a hitch: when a dynamic stack allocation occurs, we need to both 
preserve the old save area for setjmp and pre-save the important registers in 
case the stack pointer isn't updated, and pre-save the important registers 
into the new area in case the stack pointer is updated.  That's why SPARC is 
the only architecture to define the undocumented 'setjmp' pattern, which is 
only invoked by BUILT_IN_UPDATE_SETJMP_BUF and consequently only used in Ada.

It turns out that this 'setjmp' pattern works neither in 64-bit mode nor in PIC 
mode, very likely since the very beginning.  We don't test ACATS in SJLJ+PIC 
or 64-bit SJLJ mode on the SPARC at AdaCore so this has gone unnoticed.

Fixed thusly, bootstrapped/regtested on SPARC/Solaris and SPARC64/Solaris, 
applied on the mainline and 4.6/4.5/4.4 branches.


SPARC maintainers, any objection to me eliminating this SETJMP_VIA_SAVE_AREA 
kludge?  This would make it possible to have a shared implementation with the 
flat mode and remove specific support in a few locations.  Even IA-64 does 
things the canonical way here.


2011-05-21  Eric Botcazou  <ebotca...@adacore.com>

        * config/sparc/sparc.md (setjmp): Handle PIC mode and use the hard
        frame pointer.


-- 
Eric Botcazou
Index: config/sparc/sparc.md
===================================================================
--- config/sparc/sparc.md	(revision 173993)
+++ config/sparc/sparc.md	(working copy)
@@ -6507,8 +6559,8 @@ (define_insn "goto_handler_and_restore"
 		      (const_int 4)))])
 
 ;; For __builtin_setjmp we need to flush register windows iff the function
-;; calls alloca as well, because otherwise the register window might be
-;; saved after %sp adjustment and thus setjmp would crash
+;; calls alloca as well, because otherwise the current register window might
+;; be saved after the %sp adjustment and thus setjmp would crash.
 (define_expand "builtin_setjmp_setup"
   [(match_operand 0 "register_operand" "r")]
   ""
@@ -6547,19 +6599,26 @@ (define_insn "do_builtin_setjmp_setup"
                (eq_attr "pic" "true")
                  (const_int 4)] (const_int 3)))])
 
-;; Pattern for use after a setjmp to store FP and the return register
-;; into the stack area.
+;; Pattern for use after a setjmp to store registers into the save area.
 
 (define_expand "setjmp"
   [(const_int 0)]
   ""
 {
   rtx mem;
-  
+
+  if (flag_pic)
+    {
+      mem = gen_rtx_MEM (Pmode,
+			 plus_constant (stack_pointer_rtx,
+					SPARC_STACK_BIAS + 7 * UNITS_PER_WORD));
+      emit_insn (gen_rtx_SET (VOIDmode, mem, pic_offset_table_rtx));
+    }
+
   mem = gen_rtx_MEM (Pmode,
 		     plus_constant (stack_pointer_rtx,
 				    SPARC_STACK_BIAS + 14 * UNITS_PER_WORD));
-  emit_insn (gen_rtx_SET (VOIDmode, mem, frame_pointer_rtx));
+  emit_insn (gen_rtx_SET (VOIDmode, mem, hard_frame_pointer_rtx));
 
   mem = gen_rtx_MEM (Pmode,
 		     plus_constant (stack_pointer_rtx,

Reply via email to