]>
Commit | Line | Data |
---|---|---|
dfeec247 | 1 | use crate::abi::call::{ArgAbi, Conv, FnAbi, Reg, RegKind, Uniform}; |
94222f64 | 2 | use crate::abi::{HasDataLayout, TyAbiInterface}; |
9fa01778 | 3 | use crate::spec::HasTargetSpec; |
970d7e83 | 4 | |
dfeec247 XL |
5 | fn is_homogeneous_aggregate<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>) -> Option<Uniform> |
6 | where | |
94222f64 XL |
7 | Ty: TyAbiInterface<'a, C> + Copy, |
8 | C: HasDataLayout, | |
83c7162d | 9 | { |
74b04a01 | 10 | arg.layout.homogeneous_aggregate(cx).ok().and_then(|ha| ha.unit()).and_then(|unit| { |
ff7c6d11 | 11 | let size = arg.layout.size; |
3b2f2976 XL |
12 | |
13 | // Ensure we have at most four uniquely addressable members. | |
2c00a5a8 | 14 | if size > unit.size.checked_mul(4, cx).unwrap() { |
3b2f2976 XL |
15 | return None; |
16 | } | |
17 | ||
18 | let valid_unit = match unit.kind { | |
19 | RegKind::Integer => false, | |
20 | RegKind::Float => true, | |
dfeec247 | 21 | RegKind::Vector => size.bits() == 64 || size.bits() == 128, |
3b2f2976 XL |
22 | }; |
23 | ||
60c5eb7d | 24 | valid_unit.then_some(Uniform { unit, total: size }) |
3b2f2976 XL |
25 | }) |
26 | } | |
27 | ||
60c5eb7d | 28 | fn classify_ret<'a, Ty, C>(cx: &C, ret: &mut ArgAbi<'a, Ty>, vfp: bool) |
dfeec247 | 29 | where |
94222f64 XL |
30 | Ty: TyAbiInterface<'a, C> + Copy, |
31 | C: HasDataLayout, | |
83c7162d | 32 | { |
cc61c64b | 33 | if !ret.layout.is_aggregate() { |
54a0048b SL |
34 | ret.extend_integer_width_to(32); |
35 | return; | |
223e47cc | 36 | } |
3b2f2976 XL |
37 | |
38 | if vfp { | |
2c00a5a8 | 39 | if let Some(uniform) = is_homogeneous_aggregate(cx, ret) { |
ff7c6d11 | 40 | ret.cast_to(uniform); |
3b2f2976 XL |
41 | return; |
42 | } | |
43 | } | |
44 | ||
ff7c6d11 | 45 | let size = ret.layout.size; |
cc61c64b XL |
46 | let bits = size.bits(); |
47 | if bits <= 32 { | |
5869c6ff | 48 | ret.cast_to(Uniform { unit: Reg::i32(), total: size }); |
54a0048b | 49 | return; |
223e47cc | 50 | } |
ff7c6d11 | 51 | ret.make_indirect(); |
223e47cc LB |
52 | } |
53 | ||
60c5eb7d | 54 | fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>, vfp: bool) |
dfeec247 | 55 | where |
94222f64 XL |
56 | Ty: TyAbiInterface<'a, C> + Copy, |
57 | C: HasDataLayout, | |
83c7162d | 58 | { |
cc61c64b | 59 | if !arg.layout.is_aggregate() { |
54a0048b SL |
60 | arg.extend_integer_width_to(32); |
61 | return; | |
223e47cc | 62 | } |
3b2f2976 XL |
63 | |
64 | if vfp { | |
2c00a5a8 | 65 | if let Some(uniform) = is_homogeneous_aggregate(cx, arg) { |
ff7c6d11 | 66 | arg.cast_to(uniform); |
3b2f2976 XL |
67 | return; |
68 | } | |
69 | } | |
70 | ||
a1dfa0c6 | 71 | let align = arg.layout.align.abi.bytes(); |
ff7c6d11 | 72 | let total = arg.layout.size; |
dfeec247 | 73 | arg.cast_to(Uniform { unit: if align <= 4 { Reg::i32() } else { Reg::i64() }, total }); |
223e47cc LB |
74 | } |
75 | ||
60c5eb7d | 76 | pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>) |
dfeec247 | 77 | where |
94222f64 XL |
78 | Ty: TyAbiInterface<'a, C> + Copy, |
79 | C: HasDataLayout + HasTargetSpec, | |
83c7162d | 80 | { |
3b2f2976 XL |
81 | // If this is a target with a hard-float ABI, and the function is not explicitly |
82 | // `extern "aapcs"`, then we must use the VFP registers for homogeneous aggregates. | |
83c7162d | 83 | let vfp = cx.target_spec().llvm_target.ends_with("hf") |
60c5eb7d XL |
84 | && fn_abi.conv != Conv::ArmAapcs |
85 | && !fn_abi.c_variadic; | |
3b2f2976 | 86 | |
60c5eb7d XL |
87 | if !fn_abi.ret.is_ignore() { |
88 | classify_ret(cx, &mut fn_abi.ret, vfp); | |
223e47cc | 89 | } |
223e47cc | 90 | |
f2b60f7d | 91 | for arg in fn_abi.args.iter_mut() { |
dfeec247 XL |
92 | if arg.is_ignore() { |
93 | continue; | |
94 | } | |
60c5eb7d | 95 | classify_arg(cx, arg, vfp); |
54a0048b | 96 | } |
223e47cc | 97 | } |