diff --git a/compiler/rustc_target/src/callconv/aarch64.rs b/compiler/rustc_target/src/callconv/aarch64.rs index 55b65fb1caaaf..6521104309644 100644 --- a/compiler/rustc_target/src/callconv/aarch64.rs +++ b/compiler/rustc_target/src/callconv/aarch64.rs @@ -1,5 +1,10 @@ +use std::iter; + +use rustc_abi::{BackendRepr, Primitive}; + use crate::abi::call::{ArgAbi, FnAbi, Reg, RegKind, Uniform}; use crate::abi::{HasDataLayout, TyAbiInterface}; +use crate::spec::{HasTargetSpec, Target}; /// Indicates the variant of the AArch64 ABI we are compiling for. /// Used to accommodate Apple and Microsoft's deviations from the usual AAPCS ABI. @@ -35,10 +40,25 @@ where }) } +fn softfloat_float_abi(target: &Target, arg: &mut ArgAbi<'_, Ty>) { + if let BackendRepr::Scalar(s) = arg.layout.backend_repr + && let Primitive::Float(f) = s.primitive() + { + if target.abi == "softfloat" { + // Do *not* use the floag registers for passing arguments, as that would make + // the ABI depend on whether `neon` instructions are enabled. + // Apparently there is no standard ABI here [1], so we can do whatever we want. + // We choose to pass floats via equal-sized integer registers. + // [1]: https://github.com/rust-lang/rust/issues/131058#issuecomment-2384960972 + arg.cast_to(Reg { kind: RegKind::Integer, size: f.size() }); + } + } +} + fn classify_ret<'a, Ty, C>(cx: &C, ret: &mut ArgAbi<'a, Ty>, kind: AbiKind) where Ty: TyAbiInterface<'a, C> + Copy, - C: HasDataLayout, + C: HasDataLayout + HasTargetSpec, { if !ret.layout.is_sized() { // Not touching this... @@ -51,6 +71,7 @@ where // See also: ret.extend_integer_width_to(32) } + softfloat_float_abi(cx.target_spec(), ret); return; } if let Some(uniform) = is_homogeneous_aggregate(cx, ret) { @@ -69,7 +90,7 @@ where fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>, kind: AbiKind) where Ty: TyAbiInterface<'a, C> + Copy, - C: HasDataLayout, + C: HasDataLayout + HasTargetSpec, { if !arg.layout.is_sized() { // Not touching this... @@ -82,6 +103,8 @@ where // See also: arg.extend_integer_width_to(32); } + softfloat_float_abi(cx.target_spec(), arg); + return; } if let Some(uniform) = is_homogeneous_aggregate(cx, arg) { @@ -112,7 +135,7 @@ where pub(crate) fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>, kind: AbiKind) where Ty: TyAbiInterface<'a, C> + Copy, - C: HasDataLayout, + C: HasDataLayout + HasTargetSpec, { if !fn_abi.ret.is_ignore() { classify_ret(cx, &mut fn_abi.ret, kind); @@ -125,3 +148,13 @@ where classify_arg(cx, arg, kind); } } + +pub(crate) fn compute_rust_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>) +where + Ty: TyAbiInterface<'a, C> + Copy, + C: HasDataLayout + HasTargetSpec, +{ + for arg in fn_abi.args.iter_mut().chain(iter::once(&mut fn_abi.ret)) { + softfloat_float_abi(cx.target_spec(), arg); + } +} diff --git a/compiler/rustc_target/src/callconv/mod.rs b/compiler/rustc_target/src/callconv/mod.rs index aa639f1624f42..fb0fe4029348e 100644 --- a/compiler/rustc_target/src/callconv/mod.rs +++ b/compiler/rustc_target/src/callconv/mod.rs @@ -738,6 +738,7 @@ impl<'a, Ty> FnAbi<'a, Ty> { "x86" => x86::compute_rust_abi_info(cx, self, abi), "riscv32" | "riscv64" => riscv::compute_rust_abi_info(cx, self, abi), "loongarch64" => loongarch::compute_rust_abi_info(cx, self, abi), + "aarch64" => aarch64::compute_rust_abi_info(cx, self), _ => {} }; diff --git a/tests/codegen/aarch64-softfloat.rs b/tests/codegen/aarch64-softfloat.rs new file mode 100644 index 0000000000000..a8a8e5434aadd --- /dev/null +++ b/tests/codegen/aarch64-softfloat.rs @@ -0,0 +1,23 @@ +//@ compile-flags: --target aarch64-unknown-none-softfloat +//@ needs-llvm-components: aarch64 +#![crate_type = "lib"] +#![feature(no_core, lang_items)] +#![no_core] + +#[lang = "sized"] +trait Sized {} +#[lang = "copy"] +trait Copy {} +impl Copy for f64 {} + +// CHECK: i64 @pass_f64_C(i64 +#[no_mangle] +extern "C" fn pass_f64_C(x: f64) -> f64 { + x +} + +// CHECK: i64 @pass_f64_Rust(i64 +#[no_mangle] +fn pass_f64_Rust(x: f64, _y: f64) -> f64 { + x +} diff --git a/tests/ui/abi/aarch64-softfloat.rs b/tests/ui/abi/aarch64-softfloat.rs new file mode 100644 index 0000000000000..14f54d6ea7ca0 --- /dev/null +++ b/tests/ui/abi/aarch64-softfloat.rs @@ -0,0 +1,5 @@ +//@ compile-flags: --target aarch64-unknown-linux-gnu +//@ needs-llvm-components: aarch64 +#![feature(no_core, lang_items)] +#![no_core] +