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