]> git.proxmox.com Git - rustc.git/blob - compiler/rustc_target/src/abi/call/aarch64.rs
New upstream version 1.51.0+dfsg1
[rustc.git] / compiler / rustc_target / src / abi / call / aarch64.rs
1 use crate::abi::call::{ArgAbi, FnAbi, Reg, RegKind, Uniform};
2 use crate::abi::{HasDataLayout, LayoutOf, TyAndLayout, TyAndLayoutMethods};
3
4 fn is_homogeneous_aggregate<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>) -> Option<Uniform>
5 where
6 Ty: TyAndLayoutMethods<'a, C> + Copy,
7 C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
8 {
9 arg.layout.homogeneous_aggregate(cx).ok().and_then(|ha| ha.unit()).and_then(|unit| {
10 let size = arg.layout.size;
11
12 // Ensure we have at most four uniquely addressable members.
13 if size > unit.size.checked_mul(4, 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 => size.bits() == 64 || size.bits() == 128,
21 };
22
23 valid_unit.then_some(Uniform { unit, total: size })
24 })
25 }
26
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(32);
34 return;
35 }
36 if let Some(uniform) = is_homogeneous_aggregate(cx, ret) {
37 ret.cast_to(uniform);
38 return;
39 }
40 let size = ret.layout.size;
41 let bits = size.bits();
42 if bits <= 128 {
43 ret.cast_to(Uniform { unit: Reg::i64(), total: size });
44 return;
45 }
46 ret.make_indirect();
47 }
48
49 fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>)
50 where
51 Ty: TyAndLayoutMethods<'a, C> + Copy,
52 C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
53 {
54 if !arg.layout.is_aggregate() {
55 arg.extend_integer_width_to(32);
56 return;
57 }
58 if let Some(uniform) = is_homogeneous_aggregate(cx, arg) {
59 arg.cast_to(uniform);
60 return;
61 }
62 let size = arg.layout.size;
63 let bits = size.bits();
64 if bits <= 128 {
65 arg.cast_to(Uniform { unit: Reg::i64(), total: size });
66 return;
67 }
68 arg.make_indirect();
69 }
70
71 pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>)
72 where
73 Ty: TyAndLayoutMethods<'a, C> + Copy,
74 C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
75 {
76 if !fn_abi.ret.is_ignore() {
77 classify_ret(cx, &mut fn_abi.ret);
78 }
79
80 for arg in &mut fn_abi.args {
81 if arg.is_ignore() {
82 continue;
83 }
84 classify_arg(cx, arg);
85 }
86 }