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.