]>
Commit | Line | Data |
---|---|---|
f20569fa XL |
1 | use crate::abi::call::{ArgAbi, Conv, FnAbi, Reg, RegKind, Uniform}; |
2 | use crate::abi::{HasDataLayout, LayoutOf, TyAndLayout, TyAndLayoutMethods}; | |
3 | use crate::spec::HasTargetSpec; | |
4 | ||
5 | fn is_homogeneous_aggregate<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>) -> Option<Uniform> | |
6 | where | |
7 | Ty: TyAndLayoutMethods<'a, C> + Copy, | |
8 | C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout, | |
9 | { | |
10 | arg.layout.homogeneous_aggregate(cx).ok().and_then(|ha| ha.unit()).and_then(|unit| { | |
11 | let size = arg.layout.size; | |
12 | ||
13 | // Ensure we have at most four uniquely addressable members. | |
14 | if size > unit.size.checked_mul(4, cx).unwrap() { | |
15 | return None; | |
16 | } | |
17 | ||
18 | let valid_unit = match unit.kind { | |
19 | RegKind::Integer => false, | |
20 | RegKind::Float => true, | |
21 | RegKind::Vector => size.bits() == 64 || size.bits() == 128, | |
22 | }; | |
23 | ||
24 | valid_unit.then_some(Uniform { unit, total: size }) | |
25 | }) | |
26 | } | |
27 | ||
28 | fn classify_ret<'a, Ty, C>(cx: &C, ret: &mut ArgAbi<'a, Ty>, vfp: bool) | |
29 | where | |
30 | Ty: TyAndLayoutMethods<'a, C> + Copy, | |
31 | C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout, | |
32 | { | |
33 | if !ret.layout.is_aggregate() { | |
34 | ret.extend_integer_width_to(32); | |
35 | return; | |
36 | } | |
37 | ||
38 | if vfp { | |
39 | if let Some(uniform) = is_homogeneous_aggregate(cx, ret) { | |
40 | ret.cast_to(uniform); | |
41 | return; | |
42 | } | |
43 | } | |
44 | ||
45 | let size = ret.layout.size; | |
46 | let bits = size.bits(); | |
47 | if bits <= 32 { | |
48 | ret.cast_to(Uniform { unit: Reg::i32(), total: size }); | |
49 | return; | |
50 | } | |
51 | ret.make_indirect(); | |
52 | } | |
53 | ||
54 | fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>, vfp: bool) | |
55 | where | |
56 | Ty: TyAndLayoutMethods<'a, C> + Copy, | |
57 | C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout, | |
58 | { | |
59 | if !arg.layout.is_aggregate() { | |
60 | arg.extend_integer_width_to(32); | |
61 | return; | |
62 | } | |
63 | ||
64 | if vfp { | |
65 | if let Some(uniform) = is_homogeneous_aggregate(cx, arg) { | |
66 | arg.cast_to(uniform); | |
67 | return; | |
68 | } | |
69 | } | |
70 | ||
71 | let align = arg.layout.align.abi.bytes(); | |
72 | let total = arg.layout.size; | |
73 | arg.cast_to(Uniform { unit: if align <= 4 { Reg::i32() } else { Reg::i64() }, total }); | |
74 | } | |
75 | ||
76 | pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>) | |
77 | where | |
78 | Ty: TyAndLayoutMethods<'a, C> + Copy, | |
79 | C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout + HasTargetSpec, | |
80 | { | |
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. | |
83 | let vfp = cx.target_spec().llvm_target.ends_with("hf") | |
84 | && fn_abi.conv != Conv::ArmAapcs | |
85 | && !fn_abi.c_variadic; | |
86 | ||
87 | if !fn_abi.ret.is_ignore() { | |
88 | classify_ret(cx, &mut fn_abi.ret, vfp); | |
89 | } | |
90 | ||
91 | for arg in &mut fn_abi.args { | |
92 | if arg.is_ignore() { | |
93 | continue; | |
94 | } | |
95 | classify_arg(cx, arg, vfp); | |
96 | } | |
97 | } |