]>
Commit | Line | Data |
---|---|---|
32a655c1 SL |
1 | // FIXME: This needs an audit for correctness and completeness. |
2 | ||
dfeec247 | 3 | use crate::abi::call::{ArgAbi, FnAbi, Reg, RegKind, Uniform}; |
ba9703b0 | 4 | use crate::abi::{HasDataLayout, LayoutOf, TyAndLayout, TyAndLayoutMethods}; |
32a655c1 | 5 | |
dfeec247 XL |
6 | fn is_homogeneous_aggregate<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>) -> Option<Uniform> |
7 | where | |
ba9703b0 XL |
8 | Ty: TyAndLayoutMethods<'a, C> + Copy, |
9 | C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout, | |
83c7162d | 10 | { |
74b04a01 | 11 | arg.layout.homogeneous_aggregate(cx).ok().and_then(|ha| ha.unit()).and_then(|unit| { |
cc61c64b | 12 | // Ensure we have at most eight uniquely addressable members. |
2c00a5a8 | 13 | if arg.layout.size > unit.size.checked_mul(8, cx).unwrap() { |
cc61c64b | 14 | return None; |
32a655c1 SL |
15 | } |
16 | ||
cc61c64b XL |
17 | let valid_unit = match unit.kind { |
18 | RegKind::Integer => false, | |
19 | RegKind::Float => true, | |
dfeec247 | 20 | RegKind::Vector => arg.layout.size.bits() == 128, |
cc61c64b | 21 | }; |
32a655c1 | 22 | |
60c5eb7d | 23 | valid_unit.then_some(Uniform { unit, total: arg.layout.size }) |
32a655c1 SL |
24 | }) |
25 | } | |
26 | ||
60c5eb7d | 27 | fn classify_ret<'a, Ty, C>(cx: &C, ret: &mut ArgAbi<'a, Ty>) |
dfeec247 | 28 | where |
ba9703b0 XL |
29 | Ty: TyAndLayoutMethods<'a, C> + Copy, |
30 | C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout, | |
83c7162d | 31 | { |
cc61c64b | 32 | if !ret.layout.is_aggregate() { |
32a655c1 SL |
33 | ret.extend_integer_width_to(64); |
34 | return; | |
35 | } | |
36 | ||
2c00a5a8 | 37 | if let Some(uniform) = is_homogeneous_aggregate(cx, ret) { |
ff7c6d11 | 38 | ret.cast_to(uniform); |
32a655c1 SL |
39 | return; |
40 | } | |
ff7c6d11 | 41 | let size = ret.layout.size; |
cc61c64b | 42 | let bits = size.bits(); |
2c00a5a8 | 43 | if bits <= 256 { |
8faf50e0 | 44 | let unit = Reg::i64(); |
dfeec247 | 45 | ret.cast_to(Uniform { unit, total: size }); |
32a655c1 SL |
46 | return; |
47 | } | |
cc61c64b XL |
48 | |
49 | // don't return aggregates in registers | |
ff7c6d11 | 50 | ret.make_indirect(); |
32a655c1 SL |
51 | } |
52 | ||
60c5eb7d | 53 | fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>) |
dfeec247 | 54 | where |
ba9703b0 XL |
55 | Ty: TyAndLayoutMethods<'a, C> + Copy, |
56 | C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout, | |
83c7162d | 57 | { |
cc61c64b | 58 | if !arg.layout.is_aggregate() { |
32a655c1 SL |
59 | arg.extend_integer_width_to(64); |
60 | return; | |
61 | } | |
62 | ||
2c00a5a8 | 63 | if let Some(uniform) = is_homogeneous_aggregate(cx, arg) { |
ff7c6d11 | 64 | arg.cast_to(uniform); |
32a655c1 SL |
65 | return; |
66 | } | |
67 | ||
ff7c6d11 | 68 | let total = arg.layout.size; |
2c00a5a8 XL |
69 | if total.bits() > 128 { |
70 | arg.make_indirect(); | |
71 | return; | |
72 | } | |
73 | ||
dfeec247 | 74 | arg.cast_to(Uniform { unit: Reg::i64(), total }); |
32a655c1 SL |
75 | } |
76 | ||
60c5eb7d | 77 | pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>) |
dfeec247 | 78 | where |
ba9703b0 XL |
79 | Ty: TyAndLayoutMethods<'a, C> + Copy, |
80 | C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout, | |
83c7162d | 81 | { |
60c5eb7d XL |
82 | if !fn_abi.ret.is_ignore() { |
83 | classify_ret(cx, &mut fn_abi.ret); | |
32a655c1 SL |
84 | } |
85 | ||
60c5eb7d | 86 | for arg in &mut fn_abi.args { |
dfeec247 XL |
87 | if arg.is_ignore() { |
88 | continue; | |
89 | } | |
60c5eb7d | 90 | classify_arg(cx, arg); |
32a655c1 SL |
91 | } |
92 | } |