https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84521

--- Comment #19 from Wilco <wilco at gcc dot gnu.org> ---
(In reply to sudi from comment #17)
> I looked up what other targets were doing and one thing found to be
> interesting was that a lot of them are defining the target hook
> TARGET_BUILTIN_SETJMP_FRAME_VALUE. In AArch64 case I am suggesting to define
> it to return the hard frame pointer. That seems to solve the issue with both
> the attached test case and the test that Wilco mentioned.
> 
> Does this look like it solves "mid-end versus back-end : who fixes this
> issue" problem?
> 
> I am still pretty new to knowing how the stack should actually look. So
> calling for some help!

This is not about stack layout but ensuring we don't corrupt the frame pointer
or the stack pointer. Any changes to SP/FP are inherently extremely risky and
need to be done exactly right or lots of things will fail.

There are too many issues to make a full list, but here are a few obvious ones:

1. The TARGET_BUILTIN_SETJMP_FRAME_VALUE only fixes the store of the frame
pointer, however it does not fix the landing pad, I see code like this:

        str     x29, [x3, #:lo12:.LANCHOR0]
        mov     x0, sp
        stp     x1, x0, [x2, 8]
        bl      baz
        .p2align 2
.L7:
        sub     x29, x29, #176
        ldr     w0, [x29, 172]
        mov     sp, x29

So now the store is correct, but when returning at L2 we corrupt the frame
pointer badly (and then the stack pointer as well)... This is basically the
same as pr60003.c but with an alloca added.

2. We still need to force the frame pointer to be saved,
TARGET_BUILTIN_SETJMP_FRAME_VALUE doesn't fix that.

3. __builtin_longjmp is still incorrect, like I showed in PR64242, it also
fails on AArch64:

#include <setjmp.h>
#include <string.h>
void bug (jmp_buf buf)
{
  jmp_buf buf2;
  memcpy (buf2, buf, sizeof (jmp_buf));
  __builtin_longjmp (buf2, 1);
}

bug:
        stp     x29, x30, [sp, -336]!
        mov     x1, x0
        mov     x2, 312
        mov     x29, sp
        add     x0, x29, 24
        bl      memcpy
        ldr     x0, [x29, 32]
        ldr     x29, [x29, 24]  // oops
        ldr     x1, [x29, 40]
        mov     sp, x1
        br      x0

4. Trying to use setjmp and longjmp in the same function often gives this ICE:

during RTL pass: cse1
setjmp.c: In function ‘bug1’:
setjmp.c:86:1: internal compiler error: in mark_jump_label_1, at jump.c:1151
 }
 ^
0xa598f7 mark_jump_label_1
        /home/wdijkstr/gcc/gcc/jump.c:1151
0xa59a6b mark_jump_label_1
        /home/wdijkstr/gcc/gcc/jump.c:1211
0xa59a6b mark_jump_label_1
        /home/wdijkstr/gcc/gcc/jump.c:1211
0xa59e17 mark_all_labels
        /home/wdijkstr/gcc/gcc/jump.c:305
0xa59e17 rebuild_jump_labels_1
        /home/wdijkstr/gcc/gcc/jump.c:74
0x128ce23 rest_of_handle_cse
        /home/wdijkstr/gcc/gcc/cse.c:7628
0x128ce23 execute
        /home/wdijkstr/gcc/gcc/cse.c:7662

5. Things get really interesting on ARM and Thumb-2 where there are multiple
frame pointer registers. This shows again why it is wrong to change the sp/fp
in the longjmp - for it to work correctly it must be done in the landing pad in
the function that has the setjmp.

Reply via email to