rustc_target/callconv/
arm.rs
1use rustc_abi::{HasDataLayout, TyAbiInterface};
2
3use crate::callconv::{ArgAbi, Conv, FnAbi, Reg, RegKind, Uniform};
4use crate::spec::HasTargetSpec;
5
6fn is_homogeneous_aggregate<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>) -> Option<Uniform>
7where
8 Ty: TyAbiInterface<'a, C> + Copy,
9 C: HasDataLayout,
10{
11 arg.layout.homogeneous_aggregate(cx).ok().and_then(|ha| ha.unit()).and_then(|unit| {
12 let size = arg.layout.size;
13
14 if size > unit.size.checked_mul(4, cx).unwrap() {
16 return None;
17 }
18
19 let valid_unit = match unit.kind {
20 RegKind::Integer => false,
21 RegKind::Float => true,
22 RegKind::Vector => size.bits() == 64 || size.bits() == 128,
23 };
24
25 valid_unit.then_some(Uniform::consecutive(unit, size))
26 })
27}
28
29fn classify_ret<'a, Ty, C>(cx: &C, ret: &mut ArgAbi<'a, Ty>, vfp: bool)
30where
31 Ty: TyAbiInterface<'a, C> + Copy,
32 C: HasDataLayout,
33{
34 if !ret.layout.is_sized() {
35 return;
37 }
38 if !ret.layout.is_aggregate() {
39 ret.extend_integer_width_to(32);
40 return;
41 }
42
43 if vfp {
44 if let Some(uniform) = is_homogeneous_aggregate(cx, ret) {
45 ret.cast_to(uniform);
46 return;
47 }
48 }
49
50 let size = ret.layout.size;
51 let bits = size.bits();
52 if bits <= 32 {
53 ret.cast_to(Uniform::new(Reg::i32(), size));
54 return;
55 }
56 ret.make_indirect();
57}
58
59fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>, vfp: bool)
60where
61 Ty: TyAbiInterface<'a, C> + Copy,
62 C: HasDataLayout,
63{
64 if !arg.layout.is_sized() {
65 return;
67 }
68 if !arg.layout.is_aggregate() {
69 arg.extend_integer_width_to(32);
70 return;
71 }
72
73 if vfp {
74 if let Some(uniform) = is_homogeneous_aggregate(cx, arg) {
75 arg.cast_to(uniform);
76 return;
77 }
78 }
79
80 let align = arg.layout.align.abi.bytes();
81 let total = arg.layout.size;
82 arg.cast_to(Uniform::consecutive(if align <= 4 { Reg::i32() } else { Reg::i64() }, total));
83}
84
85pub(crate) fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>)
86where
87 Ty: TyAbiInterface<'a, C> + Copy,
88 C: HasDataLayout + HasTargetSpec,
89{
90 let vfp = cx.target_spec().llvm_target.ends_with("hf")
93 && fn_abi.conv != Conv::ArmAapcs
94 && !fn_abi.c_variadic;
95
96 if !fn_abi.ret.is_ignore() {
97 classify_ret(cx, &mut fn_abi.ret, vfp);
98 }
99
100 for arg in fn_abi.args.iter_mut() {
101 if arg.is_ignore() {
102 continue;
103 }
104 classify_arg(cx, arg, vfp);
105 }
106}