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