Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit f484507

Browse filesBrowse files
committed
aarch64 softfloat target: always pass floats in int registers
1 parent 46e8d20 commit f484507
Copy full SHA for f484507

File tree

Expand file treeCollapse file tree

3 files changed

+104
-5
lines changed
Filter options
Expand file treeCollapse file tree

3 files changed

+104
-5
lines changed

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

Copy file name to clipboardExpand all lines: compiler/rustc_target/src/callconv/aarch64.rs
+55-5Lines changed: 55 additions & 5 deletions
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,50 @@ where
2732

2833
let valid_unit = match unit.kind {
2934
RegKind::Integer => false,
30-
RegKind::Float => true,
35+
// The softfloat ABI treats floats like integers, so they
36+
// do not get homogeneous aggregate treatment.
37+
RegKind::Float => cx.target_spec().abi != "softfloat",
3138
RegKind::Vector => size.bits() == 64 || size.bits() == 128,
3239
};
3340

3441
valid_unit.then_some(Uniform::consecutive(unit, size))
3542
})
3643
}
3744

45+
fn softfloat_float_abi<Ty>(target: &Target, arg: &mut ArgAbi<'_, Ty>) {
46+
if target.abi != "softfloat" {
47+
return;
48+
}
49+
// Do *not* use the float registers for passing arguments, as that would make
50+
// the ABI depend on whether `neon` instructions are enabled.
51+
// Instead, we follow the "softfloat" ABI, which specifies that floats should be passed as
52+
// equivalently sized integers.
53+
if let BackendRepr::Scalar(s) = arg.layout.backend_repr
54+
&& let Primitive::Float(f) = s.primitive()
55+
{
56+
arg.cast_to(Reg { kind: RegKind::Integer, size: f.size() });
57+
} else if let BackendRepr::ScalarPair(s1, s2) = arg.layout.backend_repr
58+
&& (matches!(s1.primitive(), Primitive::Float(_))
59+
|| matches!(s2.primitive(), Primitive::Float(_)))
60+
{
61+
// This case can only be reached for the Rust ABI, so we can do whatever we want here as
62+
// long as it does not depend on target features (i.e., as long as we do not use float
63+
// registers). So we pass small things in integer registers and large things via pointer
64+
// indirection. This means we lose the nice "pass it as two arguments" optimization, but we
65+
// currently just have to way to combine a `PassMode::Cast` with that optimization (and we
66+
// need a cast since we want to pass the float as an int).
67+
if arg.layout.size.bits() <= target.pointer_width.into() {
68+
arg.cast_to(Reg { kind: RegKind::Integer, size: arg.layout.size });
69+
} else {
70+
arg.make_indirect();
71+
}
72+
}
73+
}
74+
3875
fn classify_ret<'a, Ty, C>(cx: &C, ret: &mut ArgAbi<'a, Ty>, kind: AbiKind)
3976
where
4077
Ty: TyAbiInterface<'a, C> + Copy,
41-
C: HasDataLayout,
78+
C: HasDataLayout + HasTargetSpec,
4279
{
4380
if !ret.layout.is_sized() {
4481
// Not touching this...
@@ -51,6 +88,7 @@ where
5188
// See also: <https://developer.apple.com/documentation/xcode/writing-arm64-code-for-apple-platforms#Pass-Arguments-to-Functions-Correctly>
5289
ret.extend_integer_width_to(32)
5390
}
91+
softfloat_float_abi(cx.target_spec(), ret);
5492
return;
5593
}
5694
if let Some(uniform) = is_homogeneous_aggregate(cx, ret) {
@@ -69,7 +107,7 @@ where
69107
fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>, kind: AbiKind)
70108
where
71109
Ty: TyAbiInterface<'a, C> + Copy,
72-
C: HasDataLayout,
110+
C: HasDataLayout + HasTargetSpec,
73111
{
74112
if !arg.layout.is_sized() {
75113
// Not touching this...
@@ -82,6 +120,8 @@ where
82120
// See also: <https://developer.apple.com/documentation/xcode/writing-arm64-code-for-apple-platforms#Pass-Arguments-to-Functions-Correctly>
83121
arg.extend_integer_width_to(32);
84122
}
123+
softfloat_float_abi(cx.target_spec(), arg);
124+
85125
return;
86126
}
87127
if let Some(uniform) = is_homogeneous_aggregate(cx, arg) {
@@ -112,7 +152,7 @@ where
112152
pub(crate) fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>, kind: AbiKind)
113153
where
114154
Ty: TyAbiInterface<'a, C> + Copy,
115-
C: HasDataLayout,
155+
C: HasDataLayout + HasTargetSpec,
116156
{
117157
if !fn_abi.ret.is_ignore() {
118158
classify_ret(cx, &mut fn_abi.ret, kind);
@@ -125,3 +165,13 @@ where
125165
classify_arg(cx, arg, kind);
126166
}
127167
}
168+
169+
pub(crate) fn compute_rust_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>)
170+
where
171+
Ty: TyAbiInterface<'a, C> + Copy,
172+
C: HasDataLayout + HasTargetSpec,
173+
{
174+
for arg in fn_abi.args.iter_mut().chain(iter::once(&mut fn_abi.ret)) {
175+
softfloat_float_abi(cx.target_spec(), arg);
176+
}
177+
}

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

Copy file name to clipboardExpand all lines: compiler/rustc_target/src/callconv/mod.rs
+1Lines changed: 1 addition & 0 deletions
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

Copy file name to clipboard
+48Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
//@ compile-flags: --target aarch64-unknown-none-softfloat -Zmerge-functions=disabled
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 f32 {}
12+
impl Copy for f64 {}
13+
14+
// CHECK: i64 @pass_f64_C(i64 {{[^,]*}})
15+
#[no_mangle]
16+
extern "C" fn pass_f64_C(x: f64) -> f64 {
17+
x
18+
}
19+
20+
// CHECK: i64 @pass_f32_pair_C(i64 {{[^,]*}})
21+
#[no_mangle]
22+
extern "C" fn pass_f32_pair_C(x: (f32, f32)) -> (f32, f32) {
23+
x
24+
}
25+
26+
// CHECK: [2 x i64] @pass_f64_pair_C([2 x i64] {{[^,]*}})
27+
#[no_mangle]
28+
extern "C" fn pass_f64_pair_C(x: (f64, f64)) -> (f64, f64) {
29+
x
30+
}
31+
32+
// CHECK: i64 @pass_f64_Rust(i64 {{[^,]*}})
33+
#[no_mangle]
34+
fn pass_f64_Rust(x: f64) -> f64 {
35+
x
36+
}
37+
38+
// CHECK: i64 @pass_f32_pair_Rust(i64 {{[^,]*}})
39+
#[no_mangle]
40+
fn pass_f32_pair_Rust(x: (f32, f32)) -> (f32, f32) {
41+
x
42+
}
43+
44+
// CHECK: void @pass_f64_pair_Rust(ptr {{[^,]*}}, ptr {{[^,]*}})
45+
#[no_mangle]
46+
fn pass_f64_pair_Rust(x: (f64, f64)) -> (f64, f64) {
47+
x
48+
}

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.