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

Peter Bergner <bergner at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|UNCONFIRMED                 |RESOLVED
         Resolution|---                         |INVALID

--- Comment #16 from Peter Bergner <bergner at gcc dot gnu.org> ---
Ok, this is an application problem.  From the last gdb session, we see that the
jmpbuf has an address non 16-byte aligned address, which the setjmp/longjmp
code requires.

(gdb) i reg r3
r3             0x2086db8    34106808

This leads to the code that saves the Altivec registers to clobber the jmpbuf
field where f31 is stored, since the stvx store instruction implicitly
truncates the bottom nibble of its address, giving it the same address as f31's
field.

Speaking with Camm offline, he doesn't use the jmpbuf type included from
setjmp.h, but rather uses:

struct frame {
   char     frs_jmpbuf[SIZEOF_JMP_BUF];
   object  *frs_lex;
   bds_ptr  frs_bds_top;
   object   frs_val;
   ihs_ptr  frs_ihs;
   char     frs_class;
   char     frs_in_signal_handler;
   char     frs_pad[6]; /*Keep frs_jumpbuf 8 byte aligned*/
};

...which will only enforce an 8 byte alignment.  If you look at the jmpbuf
declaration included from setjmp.h, you'll see it defined as:

typedef long int __jmp_buf[64 + (12 * 4)] __attribute__ ((__aligned__ (16)));

The save/restore code within setjmp/longjmp requires the 16-byte alignment.
I'm guessing the working "optimized" code was only getting lucky with the
address of your jmpbuf.  I'll note that the same jmpbuf layout and
setjmp/longjmp code is used for both ELFv1 and ELFv2, so you'll need to do this
for both of them.  The __powerpc64__ macro is defined for both ELFv1 and ELFv2,
so you can use that to increase your jumpbuf's alignment when compiling for
ELFv1 and ELFv2.

Reply via email to