Skip to content

Commit 42a09c0

Browse files
committed
Auto merge of #43518 - cuviper:aapcs_vfp, r=eddyb
Support homogeneous aggregates for hard-float ARM Hard-float ARM targets use the AAPCS-VFP ABI, which passes and returns homogeneous float/vector aggregates in the VFP registers. Fixes #43329. r? @eddyb
2 parents 126321e + efc6764 commit 42a09c0

File tree

1 file changed

+55
-5
lines changed

1 file changed

+55
-5
lines changed

src/librustc_trans/cabi_arm.rs

+55-5
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,50 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
use abi::{FnType, ArgType, LayoutExt, Reg, Uniform};
11+
use abi::{FnType, ArgType, LayoutExt, Reg, RegKind, Uniform};
1212
use context::CrateContext;
13+
use llvm::CallConv;
1314

14-
fn classify_ret_ty<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ret: &mut ArgType<'tcx>) {
15+
fn is_homogeneous_aggregate<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, arg: &mut ArgType<'tcx>)
16+
-> Option<Uniform> {
17+
arg.layout.homogeneous_aggregate(ccx).and_then(|unit| {
18+
let size = arg.layout.size(ccx);
19+
20+
// Ensure we have at most four uniquely addressable members.
21+
if size > unit.size.checked_mul(4, ccx).unwrap() {
22+
return None;
23+
}
24+
25+
let valid_unit = match unit.kind {
26+
RegKind::Integer => false,
27+
RegKind::Float => true,
28+
RegKind::Vector => size.bits() == 64 || size.bits() == 128
29+
};
30+
31+
if valid_unit {
32+
Some(Uniform {
33+
unit,
34+
total: size
35+
})
36+
} else {
37+
None
38+
}
39+
})
40+
}
41+
42+
fn classify_ret_ty<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ret: &mut ArgType<'tcx>, vfp: bool) {
1543
if !ret.layout.is_aggregate() {
1644
ret.extend_integer_width_to(32);
1745
return;
1846
}
47+
48+
if vfp {
49+
if let Some(uniform) = is_homogeneous_aggregate(ccx, ret) {
50+
ret.cast_to(ccx, uniform);
51+
return;
52+
}
53+
}
54+
1955
let size = ret.layout.size(ccx);
2056
let bits = size.bits();
2157
if bits <= 32 {
@@ -35,11 +71,19 @@ fn classify_ret_ty<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ret: &mut ArgType<'tc
3571
ret.make_indirect(ccx);
3672
}
3773

38-
fn classify_arg_ty<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, arg: &mut ArgType<'tcx>) {
74+
fn classify_arg_ty<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, arg: &mut ArgType<'tcx>, vfp: bool) {
3975
if !arg.layout.is_aggregate() {
4076
arg.extend_integer_width_to(32);
4177
return;
4278
}
79+
80+
if vfp {
81+
if let Some(uniform) = is_homogeneous_aggregate(ccx, arg) {
82+
arg.cast_to(ccx, uniform);
83+
return;
84+
}
85+
}
86+
4387
let align = arg.layout.align(ccx).abi();
4488
let total = arg.layout.size(ccx);
4589
arg.cast_to(ccx, Uniform {
@@ -49,12 +93,18 @@ fn classify_arg_ty<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, arg: &mut ArgType<'tc
4993
}
5094

5195
pub fn compute_abi_info<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fty: &mut FnType<'tcx>) {
96+
// If this is a target with a hard-float ABI, and the function is not explicitly
97+
// `extern "aapcs"`, then we must use the VFP registers for homogeneous aggregates.
98+
let vfp = ccx.sess().target.target.llvm_target.ends_with("hf")
99+
&& fty.cconv != CallConv::ArmAapcsCallConv
100+
&& !fty.variadic;
101+
52102
if !fty.ret.is_ignore() {
53-
classify_ret_ty(ccx, &mut fty.ret);
103+
classify_ret_ty(ccx, &mut fty.ret, vfp);
54104
}
55105

56106
for arg in &mut fty.args {
57107
if arg.is_ignore() { continue; }
58-
classify_arg_ty(ccx, arg);
108+
classify_arg_ty(ccx, arg, vfp);
59109
}
60110
}

0 commit comments

Comments
 (0)