https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87690
Bug ID: 87690
Summary: [RISCV][ABI] GCC fails to sign-extend floats passed in
the lp64 ABI
Product: gcc
Version: 9.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: target
Assignee: unassigned at gcc dot gnu.org
Reporter: asb at lowrisc dot org
Target Milestone: ---
The RISC-V PSABI documentation specifies the following for the base/integer
calling convention:
1) When passed in registers, scalars narrower than XLEN bits are widened
according to the sign of their type up to 32 bits, then sign-extended to XLEN
bits.
2) Floating-point reals are passed the same way as integers of the same size
3) For aggregates, bits unused due to padding, and bits past the end of an
aggregate whose size in bits is not divisible by XLEN, are undefined.
i.e. when XLEN=64, floats should be sign-extended when passed in GPRs.
In the following example, the top 54 bits in the GPR for char_struct and the
top 32 bits in the GPR for float_struct are undefined. Therefore, the compiler
should insert an explicit sign extension in both cases.
$ cat foo.c
struct float_struct { float v; };
struct char_struct { char v; };
struct float_struct callee(float, char);
struct float_struct caller(struct float_struct fs, struct char_struct cs) {
return callee(fs.v, cs.v);
}
It does for the char, but not for the float. This is not compliant with the
specified ABI:
./riscv32-unknown-elf-gcc -march=rv64i -mabi=lp64 -S -o - foo.c -O2
.file "foo.c"
.option nopic
.text
.align 2
.globl caller
.type caller, @function
caller:
andi a1,a1,0xff
tail callee
.size caller, .-caller
.ident "GCC: (GNU) 9.0.0 20180922 (experimental)"
Note: this is a compiler build from one month ago. I can't see any commits
since then that fix this, and unfortunately I seem unable to build
gas+newlib+gcc in a combined tree currently which I usually do for a rapid
build in order to verify a bug (Error: non-constant .uleb128 is not supported).