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