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

            Bug ID: 125493
           Summary: powerpc64: 14th float argument in wrong location on
                    stack
           Product: gcc
           Version: 13.3.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: target
          Assignee: unassigned at gcc dot gnu.org
          Reporter: kadler at us dot ibm.com
  Target Milestone: ---

This was found on AIX, but appears to affect Linux ppc64 as well (but not
ppc64le)

Compiler explorer link: https://gcc.godbolt.org/z/sWdT6bjnx

test case:

float func(float f1, float f2, float f3, float f4,
            float f5, float f6, float f7, float f8,
            float f9, float f10, float f11, float f12,
            float f13, float f14) {

            return f14;
}

gcc-13 -maix64 -c -O2 test.c
objdump -d test.o

0000000000000000 <.func>:
   0:   c0 21 00 9c     lfs     f1,156(r1)
   4:   4e 80 00 20     blr
   8:   00 00 00 00     .long 0x0
   c:   00 00 20 40     .long 0x2040
  10:   00 00 00 1a     .long 0x1a
  14:   aa aa aa 80     lha     r21,-21888(r10)
  18:   00 00 00 08     .long 0x8
  1c:   00 08 66 75     .long 0x86675
  20:   6e 63 5b 44     xoris   r3,r19,23364
  24:   53 5d 00 00     rlwimi  r29,r26,0,0,0

The AIX ABI specifies that the first 13 floating point arguments are passed in
registers f1-f13. After that, arguments are passed via the stack. These
arguments are stored in the parameter save area which starts at sp+48 and each
take a double word. The offset to the 14th float should be at offset 152 (48 +
13x8), however GCC calculates this as 156, adding an extra 4 bytes into the
offset. Further float arguments are at the expected 8 byte offsets from this,
however (164, 172, ...) so it's just going from 13 -> 14 that has a problem.

Both classic XLC and Clang calculate this correctly:

/opt/IBM/xlC/16.1.0/bin/xlc -q64 -c test.c -O2
objdump -d test.o

0000000000000000 <.func>:
   0:   c0 21 00 98     lfs     f1,152(r1)
   4:   4e 80 00 20     blr
   8:   00 00 00 00     .long 0x0
   c:   00 00 22 00     attn
  10:   00 00 00 00     .long 0x0
  14:   00 00 00 08     .long 0x8

$ /opt/IBM/openxlC/17.1.4/bin/ibm-clang -c -m64 test.c -O2
$ objdump -d test.o

0000000000000000 <.func>:
   0:   c0 21 00 98     lfs     f1,152(r1)
   4:   4e 80 00 20     blr
   8:   00 00 00 00     .long 0x0
   c:   00 09 22 40     .long 0x92240
  10:   00 00 00 1b     .long 0x1b
  14:   aa aa aa 80     lha     r21,-21888(r10)
  18:   00 00 00 08     .long 0x8
  1c:   00 04 66 75     .long 0x46675
  20:   6e 63 00 00     xoris   r3,r19,0


When calling the function, GCC *is* at least consistent with itself in where
these parameters are stored on the stack. However if you were to mix/match code
across compilers or use libffi, (where this bug was found while running its
tests) results would be garbage. This also does not occur with doubles, only
single precision floats.

Reply via email to