]> git.proxmox.com Git - rustc.git/blame - library/stdarch/crates/intrinsic-test/src/types.rs
New upstream version 1.58.1+dfsg1
[rustc.git] / library / stdarch / crates / intrinsic-test / src / types.rs
CommitLineData
c295e0f8
XL
1use std::fmt;
2use std::str::FromStr;
3
4use crate::values::values_for_pass;
5use crate::Language;
6
7#[derive(Debug, PartialEq, Copy, Clone)]
8pub enum TypeKind {
9 BFloat,
10 Float,
11 Int,
12 UInt,
13 Poly,
14 Void,
15}
16
17impl FromStr for TypeKind {
18 type Err = String;
19
20 fn from_str(s: &str) -> Result<Self, Self::Err> {
21 match s {
22 "bfloat" => Ok(Self::BFloat),
23 "float" => Ok(Self::Float),
24 "int" => Ok(Self::Int),
25 "poly" => Ok(Self::Poly),
26 "uint" | "unsigned" => Ok(Self::UInt),
27 "void" => Ok(Self::Void),
28 _ => Err(format!("Impossible to parse argument kind {}", s)),
29 }
30 }
31}
32
33impl fmt::Display for TypeKind {
34 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
35 write!(
36 f,
37 "{}",
38 match self {
39 Self::BFloat => "bfloat",
40 Self::Float => "float",
41 Self::Int => "int",
42 Self::UInt => "uint",
43 Self::Poly => "poly",
44 Self::Void => "void",
45 }
46 )
47 }
48}
49
50impl TypeKind {
51 /// Gets the type part of a c typedef for a type that's in the form of {type}{size}_t.
52 pub fn c_prefix(&self) -> &str {
53 match self {
54 Self::Float => "float",
55 Self::Int => "int",
56 Self::UInt => "uint",
57 Self::Poly => "poly",
58 _ => unreachable!("Not used: {:#?}", self),
59 }
60 }
61
62 /// Gets the rust prefix for the type kind i.e. i, u, f.
63 pub fn rust_prefix(&self) -> &str {
64 match self {
65 Self::Float => "f",
66 Self::Int => "i",
67 Self::UInt => "u",
68 Self::Poly => "u",
69 _ => unreachable!("Unused type kind: {:#?}", self),
70 }
71 }
72}
73
74#[derive(Debug, PartialEq, Clone)]
75pub enum IntrinsicType {
76 Ptr {
77 constant: bool,
78 child: Box<IntrinsicType>,
79 },
80 Type {
81 constant: bool,
82 kind: TypeKind,
83 /// The bit length of this type (e.g. 32 for u32).
84 bit_len: Option<u32>,
85
86 /// Length of the SIMD vector (i.e. 4 for uint32x4_t), A value of `None`
87 /// means this is not a simd type. A `None` can be assumed to be 1,
88 /// although in some places a distinction is needed between `u64` and
89 /// `uint64x1_t` this signals that.
90 simd_len: Option<u32>,
91
92 /// The number of rows for SIMD matrices (i.e. 2 for uint8x8x2_t).
93 /// A value of `None` represents a type that does not contain any
94 /// rows encoded in the type (e.g. uint8x8_t).
95 /// A value of `None` can be assumed to be 1 though.
96 vec_len: Option<u32>,
97 },
98}
99
100impl IntrinsicType {
101 /// Get the TypeKind for this type, recursing into pointers.
102 pub fn kind(&self) -> TypeKind {
103 match *self {
104 IntrinsicType::Ptr { ref child, .. } => child.kind(),
105 IntrinsicType::Type { kind, .. } => kind,
106 }
107 }
108
109 /// Get the size of a single element inside this type, recursing into
110 /// pointers, i.e. a pointer to a u16 would be 16 rather than the size
111 /// of a pointer.
112 pub fn inner_size(&self) -> u32 {
113 match *self {
114 IntrinsicType::Ptr { ref child, .. } => child.inner_size(),
115 IntrinsicType::Type {
116 bit_len: Some(bl), ..
117 } => bl,
118 _ => unreachable!(""),
119 }
120 }
121
122 pub fn num_lanes(&self) -> u32 {
123 match *self {
124 IntrinsicType::Ptr { ref child, .. } => child.num_lanes(),
125 IntrinsicType::Type {
126 simd_len: Some(sl), ..
127 } => sl,
128 _ => 1,
129 }
130 }
131
3c0e092e
XL
132 pub fn num_vectors(&self) -> u32 {
133 match *self {
134 IntrinsicType::Ptr { ref child, .. } => child.num_vectors(),
135 IntrinsicType::Type {
136 vec_len: Some(vl), ..
137 } => vl,
138 _ => 1,
139 }
140 }
141
c295e0f8
XL
142 /// Determine if the type is a simd type, this will treat a type such as
143 /// `uint64x1` as simd.
144 pub fn is_simd(&self) -> bool {
145 match *self {
146 IntrinsicType::Ptr { ref child, .. } => child.is_simd(),
147 IntrinsicType::Type {
148 simd_len: None,
149 vec_len: None,
150 ..
151 } => false,
152 _ => true,
153 }
154 }
155
156 pub fn is_ptr(&self) -> bool {
157 match *self {
158 IntrinsicType::Ptr { .. } => true,
159 IntrinsicType::Type { .. } => false,
160 }
161 }
162
c295e0f8
XL
163 #[allow(unused)]
164 fn c_scalar_type(&self) -> String {
165 format!(
166 "{prefix}{bits}_t",
167 prefix = self.kind().c_prefix(),
168 bits = self.inner_size()
169 )
170 }
171
172 fn rust_scalar_type(&self) -> String {
173 format!(
174 "{prefix}{bits}",
175 prefix = self.kind().rust_prefix(),
176 bits = self.inner_size()
177 )
178 }
179
180 /// Gets a string containing the typename for this type in C format.
181 pub fn c_type(&self) -> String {
182 match self {
183 IntrinsicType::Ptr { child, .. } => child.c_type(),
184 IntrinsicType::Type {
185 constant,
186 kind,
187 bit_len: Some(bit_len),
188 simd_len: None,
189 vec_len: None,
190 ..
191 } => format!(
192 "{}{}{}_t",
193 if *constant { "const " } else { "" },
194 kind.c_prefix(),
195 bit_len
196 ),
197 IntrinsicType::Type {
198 kind,
199 bit_len: Some(bit_len),
200 simd_len: Some(simd_len),
201 vec_len: None,
202 ..
203 } => format!("{}{}x{}_t", kind.c_prefix(), bit_len, simd_len),
204 IntrinsicType::Type {
205 kind,
206 bit_len: Some(bit_len),
207 simd_len: Some(simd_len),
208 vec_len: Some(vec_len),
209 ..
210 } => format!("{}{}x{}x{}_t", kind.c_prefix(), bit_len, simd_len, vec_len),
211 _ => todo!("{:#?}", self),
212 }
213 }
214
3c0e092e
XL
215 pub fn c_single_vector_type(&self) -> String {
216 match self {
217 IntrinsicType::Ptr { child, .. } => child.c_single_vector_type(),
218 IntrinsicType::Type {
219 kind,
220 bit_len: Some(bit_len),
221 simd_len: Some(simd_len),
222 vec_len: Some(_),
223 ..
224 } => format!("{}{}x{}_t", kind.c_prefix(), bit_len, simd_len),
225 _ => unreachable!("Shouldn't be called on this type"),
226 }
227 }
228
229 pub fn rust_type(&self) -> String {
230 match self {
231 IntrinsicType::Ptr { child, .. } => child.c_type(),
232 IntrinsicType::Type {
233 kind,
234 bit_len: Some(bit_len),
235 simd_len: None,
236 vec_len: None,
237 ..
238 } => format!("{}{}", kind.rust_prefix(), bit_len),
239 IntrinsicType::Type {
240 kind,
241 bit_len: Some(bit_len),
242 simd_len: Some(simd_len),
243 vec_len: None,
244 ..
245 } => format!("{}{}x{}_t", kind.c_prefix(), bit_len, simd_len),
246 IntrinsicType::Type {
247 kind,
248 bit_len: Some(bit_len),
249 simd_len: Some(simd_len),
250 vec_len: Some(vec_len),
251 ..
252 } => format!("{}{}x{}x{}_t", kind.c_prefix(), bit_len, simd_len, vec_len),
253 _ => todo!("{:#?}", self),
254 }
255 }
256
c295e0f8
XL
257 /// Gets a cast for this type if needs promotion.
258 /// This is required for 8 bit types due to printing as the 8 bit types use
259 /// a char and when using that in `std::cout` it will print as a character,
260 /// which means value of 0 will be printed as a null byte.
261 pub fn c_promotion(&self) -> &str {
262 match *self {
263 IntrinsicType::Type {
264 kind,
265 bit_len: Some(bit_len),
266 ..
267 } if bit_len == 8 => match kind {
268 TypeKind::Int => "(int)",
269 TypeKind::UInt => "(unsigned int)",
270 TypeKind::Poly => "(unsigned int)",
271 _ => "",
272 },
273 _ => "",
274 }
275 }
276
277 /// Generates a comma list of values that can be used to initialize an
278 /// argument for the intrinsic call.
279 /// This is determistic based on the pass number.
280 ///
281 /// * `pass`: The pass index, i.e. the iteration index for the call to an intrinsic
282 ///
283 /// Returns a string such as
284 /// * `0x1, 0x7F, 0xFF` if `language` is `Language::C`
285 /// * `0x1 as _, 0x7F as _, 0xFF as _` if `language` is `Language::Rust`
286 pub fn populate_random(&self, pass: usize, language: &Language) -> String {
287 match self {
288 IntrinsicType::Ptr { child, .. } => child.populate_random(pass, language),
289 IntrinsicType::Type {
290 bit_len: Some(bit_len),
291 kind,
292 simd_len,
293 vec_len,
294 ..
295 } if kind == &TypeKind::Int || kind == &TypeKind::UInt || kind == &TypeKind::Poly => (0
296 ..(simd_len.unwrap_or(1) * vec_len.unwrap_or(1)))
297 .map(|i| {
298 format!(
299 "{}{}",
300 values_for_pass(*bit_len, i, pass),
301 match language {
302 &Language::Rust => format!(" as {ty} ", ty = self.rust_scalar_type()),
303 &Language::C => String::from(""),
304 }
305 )
306 })
307 .collect::<Vec<_>>()
308 .join(","),
309 IntrinsicType::Type {
310 kind: TypeKind::Float,
311 bit_len: Some(32),
312 simd_len,
313 vec_len,
314 ..
315 } => (0..(simd_len.unwrap_or(1) * vec_len.unwrap_or(1)))
316 .map(|i| {
317 format!(
318 "{}({})",
319 match language {
320 &Language::Rust => "f32::from_bits",
321 &Language::C => "cast<float, uint32_t>",
322 },
323 values_for_pass(32, i, pass),
324 )
325 })
326 .collect::<Vec<_>>()
327 .join(","),
328 IntrinsicType::Type {
329 kind: TypeKind::Float,
330 bit_len: Some(64),
331 simd_len,
332 vec_len,
333 ..
334 } => (0..(simd_len.unwrap_or(1) * vec_len.unwrap_or(1)))
335 .map(|i| {
336 format!(
337 "{}({}{})",
338 match language {
339 &Language::Rust => "f64::from_bits",
340 &Language::C => "cast<double, uint64_t>",
341 },
342 values_for_pass(64, i, pass),
343 match language {
344 &Language::Rust => " as u64",
345 &Language::C => "",
346 }
347 )
348 })
349 .collect::<Vec<_>>()
350 .join(","),
351 _ => unreachable!("populate random: {:#?}", self),
352 }
353 }
354
355 /// Determines the load function for this type.
356 #[allow(unused)]
357 pub fn get_load_function(&self) -> String {
358 match self {
359 IntrinsicType::Ptr { child, .. } => child.get_load_function(),
360 IntrinsicType::Type {
361 kind: k,
362 bit_len: Some(bl),
363 simd_len,
364 vec_len,
365 ..
366 } => {
367 let quad = if (simd_len.unwrap_or(1) * bl) > 64 {
368 "q"
369 } else {
370 ""
371 };
372 format!(
373 "vld{len}{quad}_{type}{size}",
374 type = match k {
375 TypeKind::UInt => "u",
376 TypeKind::Int => "s",
377 TypeKind::Float => "f",
378 TypeKind::Poly => "p",
379 x => todo!("get_load_function TypeKind: {:#?}", x),
380 },
381 size = bl,
382 quad = quad,
383 len = vec_len.unwrap_or(1),
384 )
385 }
386 _ => todo!("get_load_function IntrinsicType: {:#?}", self),
387 }
388 }
389
390 /// Determines the get lane function for this type.
391 pub fn get_lane_function(&self) -> String {
392 match self {
393 IntrinsicType::Ptr { child, .. } => child.get_lane_function(),
394 IntrinsicType::Type {
395 kind: k,
396 bit_len: Some(bl),
397 simd_len,
398 ..
399 } => {
400 let quad = if (simd_len.unwrap_or(1) * bl) > 64 {
401 "q"
402 } else {
403 ""
404 };
405 format!(
406 "vget{quad}_lane_{type}{size}",
407 type = match k {
408 TypeKind::UInt => "u",
409 TypeKind::Int => "s",
410 TypeKind::Float => "f",
411 TypeKind::Poly => "p",
412 x => todo!("get_load_function TypeKind: {:#?}", x),
413 },
414 size = bl,
415 quad = quad,
416 )
417 }
418 _ => todo!("get_lane_function IntrinsicType: {:#?}", self),
419 }
420 }
421}