Fix RISC-V C function ABI when passing/returning structs containing floats by beetrees · Pull Request #139340 · rust-lang/rust (original) (raw)
RISC-V passes structs containing only one or two floats (or a float and integer pair) in registers, as long as the individual floats/integers fit in a single corresponding register (see the ABI specification for details). Before this PR, Rust would not check what offset the second float/integer was at, instead assuming that it was at the standard offset for its default alignment. However, as the offset can be affected by #[repr(align(N))]
and #[repr(packed)]
, this caused miscompilations (see #115609). To fix this, this PR introduces a rest_offset
field to CastTarget
that can be used to explicitly specify at what offset the rest
part of the cast is located at.
While fixing this, I discovered another bug: the size of the cast target was being used as the size of the MIR return place (when the function was using a PassMode::Cast
return type). However, the cast target is allowed to be smaller than the size of the actual type, causing a miscompilation. This PR fixes this issue by using the largest of the size of the type and the size of the cast target as the size of the MIR return place, ensuring all reads/writes will be inbounds.
Fixes the RISC-V part of #115609.
cc target maintainers of riscv64gc-unknown-linux-gnu
: @kito-cheng @michaelmaitland @robin-randhawa-sifive @topperc