1
Fork 0

Ensure floats are returned losslessly by the Rust ABI on 32-bit x86

This commit is contained in:
beetrees 2024-04-02 05:08:56 +01:00
parent dcc9a8f283
commit 952becc0bd
No known key found for this signature in database
GPG key ID: 8791BD754191EBD6
3 changed files with 414 additions and 0 deletions

View file

@ -744,6 +744,40 @@ fn fn_abi_adjust_for_abi<'tcx>(
return;
}
// Avoid returning floats in x87 registers on x86 as loading and storing from x87
// registers will quiet signalling NaNs.
if cx.tcx.sess.target.arch == "x86"
&& arg_idx.is_none()
// Intrinsics themselves are not actual "real" functions, so theres no need to
// change their ABIs.
&& abi != SpecAbi::RustIntrinsic
{
match arg.layout.abi {
// Handle similar to the way arguments with an `Abi::Aggregate` abi are handled
// below, by returning arguments up to the size of a pointer (32 bits on x86)
// cast to an appropriately sized integer.
Abi::Scalar(s) if s.primitive() == Float(F32) => {
// Same size as a pointer, return in a register.
arg.cast_to(Reg::i32());
return;
}
Abi::Scalar(s) if s.primitive() == Float(F64) => {
// Larger than a pointer, return indirectly.
arg.make_indirect();
return;
}
Abi::ScalarPair(s1, s2)
if matches!(s1.primitive(), Float(F32 | F64))
|| matches!(s2.primitive(), Float(F32 | F64)) =>
{
// Larger than a pointer, return indirectly.
arg.make_indirect();
return;
}
_ => {}
};
}
match arg.layout.abi {
Abi::Aggregate { .. } => {}