]> git.proxmox.com Git - rustc.git/blob - compiler/rustc_target/src/abi/call/sparc64.rs
1b74959ad17c2e577efc76d7cf759f4976ff7645
[rustc.git] / compiler / rustc_target / src / abi / call / sparc64.rs
1 // FIXME: This needs an audit for correctness and completeness.
2
3 use crate::abi::call::{
4 ArgAbi, ArgAttribute, ArgAttributes, ArgExtension, CastTarget, FnAbi, Reg, Uniform,
5 };
6 use crate::abi::{self, HasDataLayout, Scalar, Size, TyAbiInterface, TyAndLayout};
7
8 #[derive(Clone, Debug)]
9 pub struct Sdata {
10 pub prefix: [Option<Reg>; 8],
11 pub prefix_index: usize,
12 pub last_offset: Size,
13 pub has_float: bool,
14 pub arg_attribute: ArgAttribute,
15 }
16
17 fn arg_scalar<C>(cx: &C, scalar: &Scalar, offset: Size, mut data: Sdata) -> Sdata
18 where
19 C: HasDataLayout,
20 {
21 let dl = cx.data_layout();
22
23 if !scalar.primitive().is_float() {
24 return data;
25 }
26
27 data.has_float = true;
28
29 if !data.last_offset.is_aligned(dl.f64_align.abi) && data.last_offset < offset {
30 if data.prefix_index == data.prefix.len() {
31 return data;
32 }
33 data.prefix[data.prefix_index] = Some(Reg::i32());
34 data.prefix_index += 1;
35 data.last_offset = data.last_offset + Reg::i32().size;
36 }
37
38 for _ in 0..((offset - data.last_offset).bits() / 64)
39 .min((data.prefix.len() - data.prefix_index) as u64)
40 {
41 data.prefix[data.prefix_index] = Some(Reg::i64());
42 data.prefix_index += 1;
43 data.last_offset = data.last_offset + Reg::i64().size;
44 }
45
46 if data.last_offset < offset {
47 if data.prefix_index == data.prefix.len() {
48 return data;
49 }
50 data.prefix[data.prefix_index] = Some(Reg::i32());
51 data.prefix_index += 1;
52 data.last_offset = data.last_offset + Reg::i32().size;
53 }
54
55 if data.prefix_index == data.prefix.len() {
56 return data;
57 }
58
59 if scalar.primitive() == abi::F32 {
60 data.arg_attribute = ArgAttribute::InReg;
61 data.prefix[data.prefix_index] = Some(Reg::f32());
62 data.last_offset = offset + Reg::f32().size;
63 } else {
64 data.prefix[data.prefix_index] = Some(Reg::f64());
65 data.last_offset = offset + Reg::f64().size;
66 }
67 data.prefix_index += 1;
68 return data;
69 }
70
71 fn arg_scalar_pair<C>(
72 cx: &C,
73 scalar1: &Scalar,
74 scalar2: &Scalar,
75 mut offset: Size,
76 mut data: Sdata,
77 ) -> Sdata
78 where
79 C: HasDataLayout,
80 {
81 data = arg_scalar(cx, &scalar1, offset, data);
82 match (scalar1.primitive(), scalar2.primitive()) {
83 (abi::F32, _) => offset += Reg::f32().size,
84 (_, abi::F64) => offset += Reg::f64().size,
85 (abi::Int(i, _signed), _) => offset += i.size(),
86 (abi::Pointer, _) => offset += Reg::i64().size,
87 _ => {}
88 }
89
90 if (offset.raw % 4) != 0 && scalar2.primitive().is_float() {
91 offset.raw += 4 - (offset.raw % 4);
92 }
93 data = arg_scalar(cx, &scalar2, offset, data);
94 return data;
95 }
96
97 fn parse_structure<'a, Ty, C>(
98 cx: &C,
99 layout: TyAndLayout<'a, Ty>,
100 mut data: Sdata,
101 mut offset: Size,
102 ) -> Sdata
103 where
104 Ty: TyAbiInterface<'a, C> + Copy,
105 C: HasDataLayout,
106 {
107 if let abi::FieldsShape::Union(_) = layout.fields {
108 return data;
109 }
110
111 match layout.abi {
112 abi::Abi::Scalar(scalar) => {
113 data = arg_scalar(cx, &scalar, offset, data);
114 }
115 abi::Abi::Aggregate { .. } => {
116 for i in 0..layout.fields.count() {
117 if offset < layout.fields.offset(i) {
118 offset = layout.fields.offset(i);
119 }
120 data = parse_structure(cx, layout.field(cx, i), data.clone(), offset);
121 }
122 }
123 _ => {
124 if let abi::Abi::ScalarPair(scalar1, scalar2) = &layout.abi {
125 data = arg_scalar_pair(cx, scalar1, scalar2, offset, data);
126 }
127 }
128 }
129
130 return data;
131 }
132
133 fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>, in_registers_max: Size)
134 where
135 Ty: TyAbiInterface<'a, C> + Copy,
136 C: HasDataLayout,
137 {
138 if !arg.layout.is_aggregate() {
139 arg.extend_integer_width_to(64);
140 return;
141 }
142
143 let total = arg.layout.size;
144 if total > in_registers_max {
145 arg.make_indirect();
146 return;
147 }
148
149 match arg.layout.fields {
150 abi::FieldsShape::Primitive => unreachable!(),
151 abi::FieldsShape::Array { .. } => {
152 // Arrays are passed indirectly
153 arg.make_indirect();
154 return;
155 }
156 abi::FieldsShape::Union(_) => {
157 // Unions and are always treated as a series of 64-bit integer chunks
158 }
159 abi::FieldsShape::Arbitrary { .. } => {
160 // Structures with floating point numbers need special care.
161
162 let mut data = parse_structure(
163 cx,
164 arg.layout,
165 Sdata {
166 prefix: [None; 8],
167 prefix_index: 0,
168 last_offset: Size::ZERO,
169 has_float: false,
170 arg_attribute: ArgAttribute::default(),
171 },
172 Size { raw: 0 },
173 );
174
175 if data.has_float {
176 // Structure { float, int, int } doesn't like to be handled like
177 // { float, long int }. Other way around it doesn't mind.
178 if data.last_offset < arg.layout.size
179 && (data.last_offset.raw % 8) != 0
180 && data.prefix_index < data.prefix.len()
181 {
182 data.prefix[data.prefix_index] = Some(Reg::i32());
183 data.prefix_index += 1;
184 data.last_offset += Reg::i32().size;
185 }
186
187 let mut rest_size = arg.layout.size - data.last_offset;
188 if (rest_size.raw % 8) != 0 && data.prefix_index < data.prefix.len() {
189 data.prefix[data.prefix_index] = Some(Reg::i32());
190 rest_size = rest_size - Reg::i32().size;
191 }
192
193 arg.cast_to(CastTarget {
194 prefix: data.prefix,
195 rest: Uniform { unit: Reg::i64(), total: rest_size },
196 attrs: ArgAttributes {
197 regular: data.arg_attribute,
198 arg_ext: ArgExtension::None,
199 pointee_size: Size::ZERO,
200 pointee_align: None,
201 },
202 });
203 return;
204 }
205 }
206 }
207
208 arg.cast_to(Uniform { unit: Reg::i64(), total });
209 }
210
211 pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>)
212 where
213 Ty: TyAbiInterface<'a, C> + Copy,
214 C: HasDataLayout,
215 {
216 if !fn_abi.ret.is_ignore() {
217 classify_arg(cx, &mut fn_abi.ret, Size { raw: 32 });
218 }
219
220 for arg in fn_abi.args.iter_mut() {
221 if arg.is_ignore() {
222 continue;
223 }
224 classify_arg(cx, arg, Size { raw: 16 });
225 }
226 }