]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_target/src/abi/call/sparc64.rs
New upstream version 1.65.0+dfsg1
[rustc.git] / compiler / rustc_target / src / abi / call / sparc64.rs
CommitLineData
32a655c1
SL
1// FIXME: This needs an audit for correctness and completeness.
2
a2a8927a 3use crate::abi::call::{
5e7ed085 4 ArgAbi, ArgAttribute, ArgAttributes, ArgExtension, CastTarget, FnAbi, Reg, Uniform,
a2a8927a 5};
5e7ed085
FG
6use crate::abi::{self, HasDataLayout, Scalar, Size, TyAbiInterface, TyAndLayout};
7
8#[derive(Clone, Debug)]
9pub 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}
32a655c1 16
5e7ed085 17fn arg_scalar<C>(cx: &C, scalar: &Scalar, offset: Size, mut data: Sdata) -> Sdata
dfeec247 18where
94222f64 19 C: HasDataLayout,
83c7162d 20{
5e7ed085
FG
21 let dl = cx.data_layout();
22
04454e1e 23 if !scalar.primitive().is_float() {
5e7ed085
FG
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;
32a655c1 32 }
5e7ed085
FG
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 }
32a655c1 37
5e7ed085
FG
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 }
32a655c1 45
5e7ed085
FG
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
04454e1e 59 if scalar.primitive() == abi::F32 {
5e7ed085
FG
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;
32a655c1
SL
69}
70
5e7ed085
FG
71fn arg_scalar_pair<C>(
72 cx: &C,
73 scalar1: &Scalar,
74 scalar2: &Scalar,
75 mut offset: Size,
76 mut data: Sdata,
77) -> Sdata
dfeec247 78where
94222f64 79 C: HasDataLayout,
83c7162d 80{
5e7ed085 81 data = arg_scalar(cx, &scalar1, offset, data);
04454e1e
FG
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 _ => {}
32a655c1
SL
88 }
89
04454e1e 90 if (offset.raw % 4) != 0 && scalar2.primitive().is_float() {
5e7ed085
FG
91 offset.raw += 4 - (offset.raw % 4);
92 }
93 data = arg_scalar(cx, &scalar2, offset, data);
94 return data;
95}
96
97fn parse_structure<'a, Ty, C>(
98 cx: &C,
99 layout: TyAndLayout<'a, Ty>,
100 mut data: Sdata,
101 mut offset: Size,
102) -> Sdata
103where
104 Ty: TyAbiInterface<'a, C> + Copy,
105 C: HasDataLayout,
106{
107 if let abi::FieldsShape::Union(_) = layout.fields {
108 return data;
32a655c1
SL
109 }
110
5e7ed085
FG
111 match layout.abi {
112 abi::Abi::Scalar(scalar) => {
113 data = arg_scalar(cx, &scalar, offset, data);
114 }
115 abi::Abi::Aggregate { .. } => {
04454e1e 116 for i in 0..layout.fields.count() {
5e7ed085
FG
117 if offset < layout.fields.offset(i) {
118 offset = layout.fields.offset(i);
a2a8927a 119 }
04454e1e 120 data = parse_structure(cx, layout.field(cx, i), data.clone(), offset);
a2a8927a
XL
121 }
122 }
5e7ed085
FG
123 _ => {
124 if let abi::Abi::ScalarPair(scalar1, scalar2) = &layout.abi {
125 data = arg_scalar_pair(cx, scalar1, scalar2, offset, data);
a2a8927a 126 }
a2a8927a
XL
127 }
128 }
129
5e7ed085
FG
130 return data;
131}
132
133fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>, in_registers_max: Size)
134where
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
ff7c6d11 143 let total = arg.layout.size;
a2a8927a 144 if total > in_registers_max {
2c00a5a8
XL
145 arg.make_indirect();
146 return;
147 }
148
5e7ed085
FG
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,
04454e1e 164 arg.layout,
5e7ed085
FG
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
dfeec247 208 arg.cast_to(Uniform { unit: Reg::i64(), total });
32a655c1
SL
209}
210
60c5eb7d 211pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>)
dfeec247 212where
94222f64
XL
213 Ty: TyAbiInterface<'a, C> + Copy,
214 C: HasDataLayout,
83c7162d 215{
60c5eb7d 216 if !fn_abi.ret.is_ignore() {
a2a8927a 217 classify_arg(cx, &mut fn_abi.ret, Size { raw: 32 });
32a655c1
SL
218 }
219
f2b60f7d 220 for arg in fn_abi.args.iter_mut() {
dfeec247
XL
221 if arg.is_ignore() {
222 continue;
223 }
a2a8927a 224 classify_arg(cx, arg, Size { raw: 16 });
32a655c1
SL
225 }
226}