rustc_target/callconv/
mips64.rs1use arrayvec::ArrayVec;
2use rustc_abi::{
3 BackendRepr, FieldsShape, Float, HasDataLayout, Primitive, Reg, Size, TyAbiInterface,
4};
5
6use crate::callconv::{ArgAbi, ArgAttribute, ArgExtension, CastTarget, FnAbi, PassMode, Uniform};
7
8fn extend_integer_width_mips<Ty>(arg: &mut ArgAbi<'_, Ty>, bits: u64) {
9 if let BackendRepr::Scalar(scalar) = arg.layout.backend_repr
11 && let Primitive::Int(i, signed) = scalar.primitive()
12 && !signed
13 && i.size().bits() == 32
14 && let PassMode::Direct(ref mut attrs) = arg.mode
15 {
16 attrs.ext(ArgExtension::Sext);
17 return;
18 }
19
20 arg.extend_integer_width_to(bits);
21}
22
23fn float_reg<'a, Ty, C>(cx: &C, ret: &ArgAbi<'a, Ty>, i: usize) -> Option<Reg>
24where
25 Ty: TyAbiInterface<'a, C> + Copy,
26 C: HasDataLayout,
27{
28 match ret.layout.field(cx, i).backend_repr {
29 BackendRepr::Scalar(scalar) => match scalar.primitive() {
30 Primitive::Float(float) => {
31 match float {
32 Float::F16 => None,
34 Float::F32 => Some(Reg::f32()),
35 Float::F64 => Some(Reg::f64()),
36 Float::F128 => Some(Reg::f128()),
37 }
38 }
39 _ => None,
40 },
41 _ => None,
42 }
43}
44
45fn classify_ret<'a, Ty, C>(cx: &C, ret: &mut ArgAbi<'a, Ty>, offset: &mut Size)
46where
47 Ty: TyAbiInterface<'a, C> + Copy,
48 C: HasDataLayout,
49{
50 if !ret.layout.is_aggregate() {
51 extend_integer_width_mips(ret, 64);
52 return;
53 }
54
55 let size = ret.layout.size;
56 let bits = size.bits();
57 if bits <= 128 {
58 if let FieldsShape::Arbitrary { .. } = ret.layout.fields {
63 if ret.layout.fields.count() == 1 {
64 if let Some(reg) = float_reg(cx, ret, 0) {
65 ret.cast_to_with_attrs(reg, ArgAttribute::InReg.into());
69 return;
70 }
71 } else if ret.layout.fields.count() == 2
72 && let Some(reg0) = float_reg(cx, ret, 0)
73 && let Some(reg1) = float_reg(cx, ret, 1)
74 {
75 ret.cast_to_with_attrs(CastTarget::pair(reg0, reg1), ArgAttribute::InReg.into());
76 return;
77 }
78 }
79
80 ret.cast_to(Uniform::new(Reg::i64(), size));
82 } else {
83 ret.make_indirect();
84 *offset += cx.data_layout().pointer_size();
85 }
86}
87
88fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>, offset: &mut Size)
89where
90 Ty: TyAbiInterface<'a, C> + Copy,
91 C: HasDataLayout,
92{
93 let dl = cx.data_layout();
94 let size = arg.layout.size;
95 let mut prefix = ArrayVec::new();
96
97 let align = Ord::clamp(arg.layout.align.abi, dl.i64_align, dl.i128_align);
99 let pad_i32 = !offset.is_aligned(align);
100
101 if !arg.layout.is_aggregate() {
102 extend_integer_width_mips(arg, 64);
103 } else if arg.layout.pass_indirectly_in_non_rustic_abis(cx) {
104 arg.make_indirect();
105 } else {
106 match arg.layout.fields {
107 FieldsShape::Primitive => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
108 FieldsShape::Array { .. } => {
109 arg.make_indirect();
111 }
112 FieldsShape::Union(_) => {
113 }
115 FieldsShape::Arbitrary { .. } => {
116 let mut last_offset = Size::ZERO;
119
120 'outer: for i in 0..arg.layout.fields.count() {
121 let field = arg.layout.field(cx, i);
122 let offset = arg.layout.fields.offset(i);
123
124 if let BackendRepr::Scalar(scalar) = field.backend_repr {
126 if scalar.primitive() == Primitive::Float(Float::F64) {
127 if offset.is_aligned(dl.f64_align) {
128 if !last_offset.is_aligned(dl.f64_align) {
::core::panicking::panic("assertion failed: last_offset.is_aligned(dl.f64_align)")
};assert!(last_offset.is_aligned(dl.f64_align));
130 for _ in 0..((offset - last_offset).bits() / 64) {
131 if prefix.try_push(Reg::i64()).is_err() {
132 break 'outer;
133 }
134 }
135
136 if prefix.try_push(Reg::f64()).is_err() {
137 break;
138 }
139 last_offset = offset + Reg::f64().size;
140 }
141 }
142 }
143 }
144 }
145 };
146
147 let rest_size = size - Size::from_bytes(8) * prefix.len() as u64;
149 arg.cast_to_and_pad_i32(
150 CastTarget::prefixed(prefix, Uniform::new(Reg::i64(), rest_size)),
151 pad_i32,
152 );
153 }
154 *offset = offset.align_to(align) + size.align_to(align);
155}
156
157pub(crate) fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>)
158where
159 Ty: TyAbiInterface<'a, C> + Copy,
160 C: HasDataLayout,
161{
162 let mut offset = Size::ZERO;
165
166 if !fn_abi.ret.is_ignore() && fn_abi.ret.layout.is_sized() {
167 classify_ret(cx, &mut fn_abi.ret, &mut offset);
168 }
169
170 for arg in fn_abi.args.iter_mut() {
171 if arg.is_ignore() || !arg.layout.is_sized() {
172 continue;
173 }
174 classify_arg(cx, arg, &mut offset);
175 }
176}