rustc_target/callconv/
s390x.rs1use rustc_abi::{BackendRepr, FieldsShape, HasDataLayout, Primitive, TyAbiInterface, TyAndLayout};
5
6use crate::callconv::{ArgAbi, FnAbi, Reg};
7use crate::spec::{Env, HasTargetSpec, Os};
8
9fn is_single_fp_element<'a, Ty, C>(mut layout: TyAndLayout<'a, Ty>, cx: &C) -> bool
11where
12 Ty: TyAbiInterface<'a, C> + Copy,
13 C: HasDataLayout,
14{
15 loop {
18 layout = layout.peel_transparent_wrappers(cx);
19
20 return match layout.backend_repr {
21 BackendRepr::Scalar(scalar) => match scalar.primitive() {
22 Primitive::Float(_) => true,
23 Primitive::Int(_, _) | Primitive::Pointer(_) => false,
24 },
25 BackendRepr::Memory { .. } => {
26 if let FieldsShape::Arbitrary { .. } = layout.fields
28 && layout.fields.count() == 1
29 && layout.fields.offset(0).bytes() == 0
30 {
31 layout = layout.field(cx, 0);
32 continue;
33 } else {
34 false
35 }
36 }
37 _ => false,
38 };
39 }
40}
41
42fn classify_ret<Ty>(ret: &mut ArgAbi<'_, Ty>) {
43 let size = ret.layout.size;
44 if size.bits() <= 128 && #[allow(non_exhaustive_omitted_patterns)] match ret.layout.backend_repr {
BackendRepr::SimdVector { .. } => true,
_ => false,
}matches!(ret.layout.backend_repr, BackendRepr::SimdVector { .. }) {
45 return;
46 }
47 if !ret.layout.is_aggregate() && size.bits() <= 64 {
48 ret.extend_integer_width_to(64);
49 } else {
50 ret.make_indirect();
51 }
52}
53
54fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>)
55where
56 Ty: TyAbiInterface<'a, C> + Copy,
57 C: HasDataLayout + HasTargetSpec,
58{
59 if !arg.layout.is_sized() {
60 return;
62 }
63 if arg.is_ignore() {
64 if cx.target_spec().os == Os::Linux
66 && #[allow(non_exhaustive_omitted_patterns)] match cx.target_spec().env {
Env::Gnu | Env::Musl | Env::Uclibc => true,
_ => false,
}matches!(cx.target_spec().env, Env::Gnu | Env::Musl | Env::Uclibc)
67 && arg.layout.is_zst()
68 {
69 arg.make_indirect_from_ignore();
70 }
71 return;
72 }
73 if arg.layout.pass_indirectly_in_non_rustic_abis(cx) {
74 arg.make_indirect();
75 return;
76 }
77
78 if arg.layout.is_complex_number(cx) {
79 arg.make_indirect();
80 return;
81 }
82
83 let size = arg.layout.size;
84 if size.bits() <= 128 {
85 if let BackendRepr::SimdVector { .. } = arg.layout.backend_repr {
86 return;
88 }
89
90 if arg.layout.is_single_vector_element(cx, size) {
91 arg.cast_to(Reg::opaque_vector(size));
93 return;
94 }
95 }
96 if !arg.layout.is_aggregate() && size.bits() <= 64 {
97 arg.extend_integer_width_to(64);
98 return;
99 }
100
101 if is_single_fp_element(arg.layout, cx) {
102 match size.bytes() {
113 2 => arg.cast_to(Reg::f16()),
114 4 => arg.cast_to(Reg::f32()),
115 8 => arg.cast_to(Reg::f64()),
116 _ => arg.make_indirect(),
117 }
118 } else {
119 match size.bytes() {
120 1 => arg.cast_to(Reg::i8()),
121 2 => arg.cast_to(Reg::i16()),
122 4 => arg.cast_to(Reg::i32()),
123 8 => arg.cast_to(Reg::i64()),
124 _ => arg.make_indirect(),
125 }
126 }
127}
128
129pub(crate) fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>)
130where
131 Ty: TyAbiInterface<'a, C> + Copy,
132 C: HasDataLayout + HasTargetSpec,
133{
134 if !fn_abi.ret.is_ignore() {
135 classify_ret(&mut fn_abi.ret);
136 }
137
138 for arg in fn_abi.args.iter_mut() {
139 classify_arg(cx, arg);
140 }
141}