Description
librustc_target/abi/call/sparc64.rs
passes structures as Uniform
, which get allocated to stack or "promoted" to integer registers by LLVM. According to the SPARC v9 64 Bit ABI definition in the SPARC Compliance Definition, floating point members should be promoted into floating point registers instead of integer registers, see page 47 in SCD 2.4.1. This also affects returning of structures, and makes run-pass/structs-enums/struct-return.rs
fail. gcc returns the members of struct Floats
in %d0
, %o1
and %d4
, whereas Rust expects the members to be in %o0
, %o1
and %o2
.
I guess we need to create a CastTarget
that contains a mixture of Int and Float registers in the prefix with an empty tail. As structures with at most 256 bits (8 * 32 bits) can be returned in registers, the eight class items in the prefix are enough. I expect that the structures needs to be flattened, so a structure containing a structure containing a float also has the float value passed in a floating point register.
Unaligned Floats and Doubles (with __attribute__((packed))
) end up being put in integer registers by gcc
and clang
, whereas "accidently" aligned floating point members get passed in integer registers by gcc
and floating point registers by clang
:
// Structure without "packed" declaration
struct str1 {
float f; // passed in %f0
int i; // passed in least-significant half of %o0
};
// Structure that gets misalignment due to packed declaration
struct str2 {
short s; // passed in bits 48..63 of %o0
float f; // passed in bits 16..47 of %o0 (due to misalignment)
} __attribute__((packed));
// Layout exactly as str1, but has alignof() 1. Different behaviour between gcc 8.2 and clang 7.0
struct str3 {
float f; // passed in most-significant half of %o0 (gcc) or in %f0 (clang)
int i; // passed in least-significant half of %o0
} __attribute__((packed));