Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 7d57c37

Browse files
committedNov 16, 2024
aarch64 softfloat target: always pass floats in int registers
1 parent 46e8d20 commit 7d57c37

File tree

3 files changed

+81
-5
lines changed

3 files changed

+81
-5
lines changed
 

‎compiler/rustc_target/src/callconv/aarch64.rs

+45-5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
1+
use std::iter;
2+
3+
use rustc_abi::{BackendRepr, Primitive};
4+
15
use crate::abi::call::{ArgAbi, FnAbi, Reg, RegKind, Uniform};
26
use crate::abi::{HasDataLayout, TyAbiInterface};
7+
use crate::spec::{HasTargetSpec, Target};
38

49
/// Indicates the variant of the AArch64 ABI we are compiling for.
510
/// Used to accommodate Apple and Microsoft's deviations from the usual AAPCS ABI.
@@ -15,7 +20,7 @@ pub(crate) enum AbiKind {
1520
fn is_homogeneous_aggregate<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>) -> Option<Uniform>
1621
where
1722
Ty: TyAbiInterface<'a, C> + Copy,
18-
C: HasDataLayout,
23+
C: HasDataLayout + HasTargetSpec,
1924
{
2025
arg.layout.homogeneous_aggregate(cx).ok().and_then(|ha| ha.unit()).and_then(|unit| {
2126
let size = arg.layout.size;
@@ -27,18 +32,40 @@ where
2732

2833
let valid_unit = match unit.kind {
2934
RegKind::Integer => false,
30-
RegKind::Float => true,
35+
RegKind::Float => cx.target_spec().abi != "softfloat",
3136
RegKind::Vector => size.bits() == 64 || size.bits() == 128,
3237
};
3338

3439
valid_unit.then_some(Uniform::consecutive(unit, size))
3540
})
3641
}
3742

43+
fn softfloat_float_abi<Ty>(target: &Target, arg: &mut ArgAbi<'_, Ty>) {
44+
if target.abi != "softfloat" {
45+
return;
46+
}
47+
if let BackendRepr::Scalar(s) = arg.layout.backend_repr
48+
&& let Primitive::Float(f) = s.primitive()
49+
{
50+
// Do *not* use the floag registers for passing arguments, as that would make
51+
// the ABI depend on whether `neon` instructions are enabled.
52+
// Apparently there is no standard ABI here [1], so we can do whatever we want.
53+
// We choose to pass floats via equal-sized integer registers.
54+
// [1]: https://github.com/rust-lang/rust/issues/131058#issuecomment-2384960972
55+
arg.cast_to(Reg { kind: RegKind::Integer, size: f.size() });
56+
} else if let BackendRepr::ScalarPair(s1, s2) = arg.layout.backend_repr
57+
&& (matches!(s1.primitive(), Primitive::Float(_))
58+
|| matches!(s2.primitive(), Primitive::Float(_)))
59+
{
60+
// For now just pass this indirectly, that definitely avoids all trouble.
61+
arg.make_indirect();
62+
}
63+
}
64+
3865
fn classify_ret<'a, Ty, C>(cx: &C, ret: &mut ArgAbi<'a, Ty>, kind: AbiKind)
3966
where
4067
Ty: TyAbiInterface<'a, C> + Copy,
41-
C: HasDataLayout,
68+
C: HasDataLayout + HasTargetSpec,
4269
{
4370
if !ret.layout.is_sized() {
4471
// Not touching this...
@@ -51,6 +78,7 @@ where
5178
// See also: <https://developer.apple.com/documentation/xcode/writing-arm64-code-for-apple-platforms#Pass-Arguments-to-Functions-Correctly>
5279
ret.extend_integer_width_to(32)
5380
}
81+
softfloat_float_abi(cx.target_spec(), ret);
5482
return;
5583
}
5684
if let Some(uniform) = is_homogeneous_aggregate(cx, ret) {
@@ -69,7 +97,7 @@ where
6997
fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>, kind: AbiKind)
7098
where
7199
Ty: TyAbiInterface<'a, C> + Copy,
72-
C: HasDataLayout,
100+
C: HasDataLayout + HasTargetSpec,
73101
{
74102
if !arg.layout.is_sized() {
75103
// Not touching this...
@@ -82,6 +110,8 @@ where
82110
// See also: <https://developer.apple.com/documentation/xcode/writing-arm64-code-for-apple-platforms#Pass-Arguments-to-Functions-Correctly>
83111
arg.extend_integer_width_to(32);
84112
}
113+
softfloat_float_abi(cx.target_spec(), arg);
114+
85115
return;
86116
}
87117
if let Some(uniform) = is_homogeneous_aggregate(cx, arg) {
@@ -112,7 +142,7 @@ where
112142
pub(crate) fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>, kind: AbiKind)
113143
where
114144
Ty: TyAbiInterface<'a, C> + Copy,
115-
C: HasDataLayout,
145+
C: HasDataLayout + HasTargetSpec,
116146
{
117147
if !fn_abi.ret.is_ignore() {
118148
classify_ret(cx, &mut fn_abi.ret, kind);
@@ -125,3 +155,13 @@ where
125155
classify_arg(cx, arg, kind);
126156
}
127157
}
158+
159+
pub(crate) fn compute_rust_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>)
160+
where
161+
Ty: TyAbiInterface<'a, C> + Copy,
162+
C: HasDataLayout + HasTargetSpec,
163+
{
164+
for arg in fn_abi.args.iter_mut().chain(iter::once(&mut fn_abi.ret)) {
165+
softfloat_float_abi(cx.target_spec(), arg);
166+
}
167+
}

‎compiler/rustc_target/src/callconv/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -738,6 +738,7 @@ impl<'a, Ty> FnAbi<'a, Ty> {
738738
"x86" => x86::compute_rust_abi_info(cx, self, abi),
739739
"riscv32" | "riscv64" => riscv::compute_rust_abi_info(cx, self, abi),
740740
"loongarch64" => loongarch::compute_rust_abi_info(cx, self, abi),
741+
"aarch64" => aarch64::compute_rust_abi_info(cx, self),
741742
_ => {}
742743
};
743744

‎tests/codegen/aarch64-softfloat.rs

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
//@ compile-flags: --target aarch64-unknown-none-softfloat
2+
//@ needs-llvm-components: aarch64
3+
#![crate_type = "lib"]
4+
#![feature(no_core, lang_items)]
5+
#![no_core]
6+
7+
#[lang = "sized"]
8+
trait Sized {}
9+
#[lang = "copy"]
10+
trait Copy {}
11+
impl Copy for f64 {}
12+
13+
// CHECK: i64 @pass_f64_C(i64 {{[^,]*}})
14+
#[no_mangle]
15+
extern "C" fn pass_f64_C(x: f64) -> f64 {
16+
x
17+
}
18+
19+
// CHECK: [2 x i64] @pass_f64_pair_C([2 x i64] {{[^,]*}})
20+
#[no_mangle]
21+
extern "C" fn pass_f64_pair_C(x: (f64, f64)) -> (f64, f64) {
22+
x
23+
}
24+
25+
// CHECK: i64 @pass_f64_Rust(i64 {{[^,]*}}, {{[^,]*}} %_dont_merge_with_other_fn)
26+
#[no_mangle]
27+
fn pass_f64_Rust(x: f64, _dont_merge_with_other_fn: bool) -> f64 {
28+
x
29+
}
30+
31+
// CHECK: void @pass_f64_pair_Rust(ptr {{[^,]*}}, ptr {{[^,]*}}, {{[^,]*}} %_dont_merge_with_other_fn)
32+
#[no_mangle]
33+
fn pass_f64_pair_Rust(x: (f64, f64), _dont_merge_with_other_fn: bool) -> (f64, f64) {
34+
x
35+
}

0 commit comments

Comments
 (0)
Failed to load comments.