The psABI is documented here: https://github.com/riscv/riscv-elf-psabi-doc/blob/master/riscv-elf.md Structs of containing one int and one fp value are passed in int+fp registers, as described here: """ A struct containing one floating-point real and one integer, in either order, is passed in a floating-point register and an integer register, with the integer zero- or sign-extended as though it were a scalar, provided the floating-point real is no more than FLEN bits wide and the integer is no more than XLEN bits wide, and at least one floating-point argument register and at least one integer argument register is available. Otherwise, it is passed according to the integer calling convention. """ Scalar sign/zero-extension is specified as "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." As for return, the document states "Values are returned in the same manner as a first named argument of the same type would be passed." Assume a struct consisting of a uint8 and a float: struct s_u8_f { uint8_t i; float f; }; By the above rules if passed as the first argument to a function, we would expect to see i in a0 (zero-extended), and f in fa0. As specified above, we expect the same if this struct is returned by value. GCC does not sign or zero-extend as it should as demonstrated in the program below. $ cat foo.c #include <stdint.h> struct s_u8_f { uint8_t i; float f; }; struct s_i8_f { int8_t i; float f; }; struct s_u8_f should_zext_arg(int8_t i, float f) { struct s_u8_f s; s.i = i; s.f = f; return s; } struct s_i8_f should_sext_arg(uint8_t i, float f) { struct s_i8_f s; s.i = i; s.f = f; return s; } $ ./riscv32-unknown-elf-gcc -march=rv32imf -mabi=ilp32f foo.c -S -o - -O1 .file "foo.c" .option nopic .text .align 2 .globl should_zext_arg .type should_zext_arg, @function should_zext_arg: addi sp,sp,-32 addi sp,sp,32 jr ra .size should_zext_arg, .-should_zext_arg .align 2 .globl should_sext_arg .type should_sext_arg, @function should_sext_arg: addi sp,sp,-32 addi sp,sp,32 jr ra .size should_sext_arg, .-should_sext_arg .ident "GCC: (GNU) 9.0.0 20180703 (experimental)"
Changing title as this bug affects both return and argument passing. I could create a separate bug report if preferred, but the issues seem so closely related it might make most sense to keep here. No sign or zero-extension takes place in the following example, but as-per the ABI it should. I actually sought clarification on this aspect of the ABI last September, to perhaps this is a regression in GCC behaviour? https://github.com/riscv/riscv-elf-psabi-doc/issues/37 $ cat foo.c #include <stdint.h> struct s_u8_f { uint8_t i; float f; }; struct s_i8_f { int8_t i; float f; }; void must_receive_zext_arg(struct s_u8_f); void must_receive_sext_arg(struct s_i8_f); void should_zext_arg(int8_t i, float f) { struct s_u8_f s; s.i = i; s.f = f; must_receive_zext_arg(s); } void should_sext_arg(uint8_t i, float f) { struct s_i8_f s; s.i = i; s.f = f; must_receive_sext_arg(s); } ./riscv32-unknown-elf-gcc -march=rv32imf -mabi=ilp32f foo.c -S -o - -O1 .file "foo.c" .option nopic .text .align 2 .globl should_zext_arg .type should_zext_arg, @function should_zext_arg: addi sp,sp,-32 sw ra,28(sp) call must_receive_zext_arg lw ra,28(sp) addi sp,sp,32 jr ra .size should_zext_arg, .-should_zext_arg .align 2 .globl should_sext_arg .type should_sext_arg, @function should_sext_arg: addi sp,sp,-32 sw ra,28(sp) call must_receive_sext_arg lw ra,28(sp) addi sp,sp,32 jr ra .size should_sext_arg, .-should_sext_arg .ident "GCC: (GNU) 9.0.0 20180703 (experimental)"
I don't see any gcc regression. I think the psABI spec was updated without checking gcc. Unfortunately, fixing gcc would cause a non-backward compatible ABI change. Given that we fixed the ABI back in January when we upstreamed glibc, we can't change it now without causing a lot of trouble. Hence, the easy solution is to fix the paABI spec to match what gcc actually emits.
This was fixed with a psABI change in Nov 2018 and we forgot to update this bug report. https://github.com/riscv/riscv-elf-psabi-doc/pull/74