1use core::default::Default;
4use core::fmt::{self, Debug, Display, Formatter};
5use cranelift_codegen_shared::constants;
6use target_lexicon::{PointerWidth, Triple};
7
8#[derive(Copy, Clone, PartialEq, Eq, Hash)]
24pub struct Type(u8);
25
26pub const INVALID: Type = Type(0);
28
29include!(concat!(env!("OUT_DIR"), "/types.rs"));
33
34impl Type {
35 pub fn lane_type(self) -> Self {
39 if self.0 < constants::VECTOR_BASE {
40 self
41 } else {
42 Self(constants::LANE_BASE | (self.0 & 0x0f))
43 }
44 }
45
46 pub fn lane_of(self) -> Self {
50 self.lane_type()
51 }
52
53 pub fn log2_lane_bits(self) -> u8 {
55 match self.lane_type() {
56 B1 => 0,
57 B8 | I8 => 3,
58 B16 | I16 => 4,
59 B32 | I32 | F32 | R32 => 5,
60 B64 | I64 | F64 | R64 => 6,
61 B128 | I128 => 7,
62 _ => 0,
63 }
64 }
65
66 pub fn lane_bits(self) -> u8 {
68 match self.lane_type() {
69 B1 => 1,
70 B8 | I8 => 8,
71 B16 | I16 => 16,
72 B32 | I32 | F32 | R32 => 32,
73 B64 | I64 | F64 | R64 => 64,
74 B128 | I128 => 128,
75 _ => 0,
76 }
77 }
78
79 pub fn int(bits: u16) -> Option<Self> {
81 match bits {
82 8 => Some(I8),
83 16 => Some(I16),
84 32 => Some(I32),
85 64 => Some(I64),
86 128 => Some(I128),
87 _ => None,
88 }
89 }
90
91 fn replace_lanes(self, lane: Self) -> Self {
93 debug_assert!(lane.is_lane() && !self.is_special());
94 Self((lane.0 & 0x0f) | (self.0 & 0xf0))
95 }
96
97 pub fn as_bool_pedantic(self) -> Self {
103 self.replace_lanes(match self.lane_type() {
105 B8 | I8 => B8,
106 B16 | I16 => B16,
107 B32 | I32 | F32 => B32,
108 B64 | I64 | F64 => B64,
109 R32 | R64 => panic!("Reference types should not convert to bool"),
110 B128 | I128 => B128,
111 _ => B1,
112 })
113 }
114
115 pub fn as_bool(self) -> Self {
120 if !self.is_vector() {
121 B1
122 } else {
123 self.as_bool_pedantic()
124 }
125 }
126
127 pub fn half_width(self) -> Option<Self> {
130 Some(self.replace_lanes(match self.lane_type() {
131 I16 => I8,
132 I32 => I16,
133 I64 => I32,
134 I128 => I64,
135 F64 => F32,
136 B16 => B8,
137 B32 => B16,
138 B64 => B32,
139 B128 => B64,
140 _ => return None,
141 }))
142 }
143
144 pub fn double_width(self) -> Option<Self> {
147 Some(self.replace_lanes(match self.lane_type() {
148 I8 => I16,
149 I16 => I32,
150 I32 => I64,
151 I64 => I128,
152 F32 => F64,
153 B8 => B16,
154 B16 => B32,
155 B32 => B64,
156 B64 => B128,
157 _ => return None,
158 }))
159 }
160
161 pub fn is_invalid(self) -> bool {
163 self == INVALID
164 }
165
166 pub fn is_special(self) -> bool {
168 self.0 < constants::LANE_BASE
169 }
170
171 pub fn is_lane(self) -> bool {
175 constants::LANE_BASE <= self.0 && self.0 < constants::VECTOR_BASE
176 }
177
178 pub fn is_vector(self) -> bool {
182 self.0 >= constants::VECTOR_BASE
183 }
184
185 pub fn is_bool(self) -> bool {
187 match self {
188 B1 | B8 | B16 | B32 | B64 | B128 => true,
189 _ => false,
190 }
191 }
192
193 pub fn is_int(self) -> bool {
195 match self {
196 I8 | I16 | I32 | I64 | I128 => true,
197 _ => false,
198 }
199 }
200
201 pub fn is_float(self) -> bool {
203 match self {
204 F32 | F64 => true,
205 _ => false,
206 }
207 }
208
209 pub fn is_flags(self) -> bool {
211 match self {
212 IFLAGS | FFLAGS => true,
213 _ => false,
214 }
215 }
216
217 pub fn is_ref(self) -> bool {
219 match self {
220 R32 | R64 => true,
221 _ => false,
222 }
223 }
224
225 pub fn log2_lane_count(self) -> u8 {
232 self.0.saturating_sub(constants::LANE_BASE) >> 4
233 }
234
235 pub fn lane_count(self) -> u16 {
239 1 << self.log2_lane_count()
240 }
241
242 pub fn bits(self) -> u16 {
244 u16::from(self.lane_bits()) * self.lane_count()
245 }
246
247 pub fn bytes(self) -> u32 {
249 (u32::from(self.bits()) + 7) / 8
250 }
251
252 pub fn by(self, n: u16) -> Option<Self> {
259 if self.lane_bits() == 0 || !n.is_power_of_two() {
260 return None;
261 }
262 let log2_lanes: u32 = n.trailing_zeros();
263 let new_type = u32::from(self.0) + (log2_lanes << 4);
264 if new_type < 0x100 {
265 Some(Self(new_type as u8))
266 } else {
267 None
268 }
269 }
270
271 pub fn half_vector(self) -> Option<Self> {
275 if self.is_vector() {
276 Some(Self(self.0 - 0x10))
277 } else {
278 None
279 }
280 }
281
282 pub fn index(self) -> usize {
284 usize::from(self.0)
285 }
286
287 pub fn wider_or_equal(self, other: Self) -> bool {
292 self.lane_count() == other.lane_count() && self.lane_bits() >= other.lane_bits()
293 }
294
295 pub fn triple_pointer_type(triple: &Triple) -> Self {
297 match triple.pointer_width() {
298 Ok(PointerWidth::U16) => I16,
299 Ok(PointerWidth::U32) => I32,
300 Ok(PointerWidth::U64) => I64,
301 Err(()) => panic!("unable to determine architecture pointer width"),
302 }
303 }
304}
305
306impl Display for Type {
307 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
308 if self.is_bool() {
309 write!(f, "b{}", self.lane_bits())
310 } else if self.is_int() {
311 write!(f, "i{}", self.lane_bits())
312 } else if self.is_float() {
313 write!(f, "f{}", self.lane_bits())
314 } else if self.is_vector() {
315 write!(f, "{}x{}", self.lane_type(), self.lane_count())
316 } else if self.is_ref() {
317 write!(f, "r{}", self.lane_bits())
318 } else {
319 f.write_str(match *self {
320 IFLAGS => "iflags",
321 FFLAGS => "fflags",
322 INVALID => panic!("INVALID encountered"),
323 _ => panic!("Unknown Type(0x{:x})", self.0),
324 })
325 }
326 }
327}
328
329impl Debug for Type {
330 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
331 if self.is_bool() {
332 write!(f, "types::B{}", self.lane_bits())
333 } else if self.is_int() {
334 write!(f, "types::I{}", self.lane_bits())
335 } else if self.is_float() {
336 write!(f, "types::F{}", self.lane_bits())
337 } else if self.is_vector() {
338 write!(f, "{:?}X{}", self.lane_type(), self.lane_count())
339 } else if self.is_ref() {
340 write!(f, "types::R{}", self.lane_bits())
341 } else {
342 match *self {
343 INVALID => write!(f, "types::INVALID"),
344 IFLAGS => write!(f, "types::IFLAGS"),
345 FFLAGS => write!(f, "types::FFLAGS"),
346 _ => write!(f, "Type(0x{:x})", self.0),
347 }
348 }
349 }
350}
351
352impl Default for Type {
353 fn default() -> Self {
354 INVALID
355 }
356}
357
358#[cfg(test)]
359mod tests {
360 use super::*;
361 use alloc::string::ToString;
362
363 #[test]
364 fn basic_scalars() {
365 assert_eq!(INVALID, INVALID.lane_type());
366 assert_eq!(0, INVALID.bits());
367 assert_eq!(IFLAGS, IFLAGS.lane_type());
368 assert_eq!(0, IFLAGS.bits());
369 assert_eq!(FFLAGS, FFLAGS.lane_type());
370 assert_eq!(0, FFLAGS.bits());
371 assert_eq!(B1, B1.lane_type());
372 assert_eq!(B8, B8.lane_type());
373 assert_eq!(B16, B16.lane_type());
374 assert_eq!(B32, B32.lane_type());
375 assert_eq!(B64, B64.lane_type());
376 assert_eq!(B128, B128.lane_type());
377 assert_eq!(I8, I8.lane_type());
378 assert_eq!(I16, I16.lane_type());
379 assert_eq!(I32, I32.lane_type());
380 assert_eq!(I64, I64.lane_type());
381 assert_eq!(I128, I128.lane_type());
382 assert_eq!(F32, F32.lane_type());
383 assert_eq!(F64, F64.lane_type());
384 assert_eq!(B1, B1.by(8).unwrap().lane_type());
385 assert_eq!(I32, I32X4.lane_type());
386 assert_eq!(F64, F64X2.lane_type());
387 assert_eq!(R32, R32.lane_type());
388 assert_eq!(R64, R64.lane_type());
389
390 assert_eq!(INVALID.lane_bits(), 0);
391 assert_eq!(IFLAGS.lane_bits(), 0);
392 assert_eq!(FFLAGS.lane_bits(), 0);
393 assert_eq!(B1.lane_bits(), 1);
394 assert_eq!(B8.lane_bits(), 8);
395 assert_eq!(B16.lane_bits(), 16);
396 assert_eq!(B32.lane_bits(), 32);
397 assert_eq!(B64.lane_bits(), 64);
398 assert_eq!(B128.lane_bits(), 128);
399 assert_eq!(I8.lane_bits(), 8);
400 assert_eq!(I16.lane_bits(), 16);
401 assert_eq!(I32.lane_bits(), 32);
402 assert_eq!(I64.lane_bits(), 64);
403 assert_eq!(I128.lane_bits(), 128);
404 assert_eq!(F32.lane_bits(), 32);
405 assert_eq!(F64.lane_bits(), 64);
406 assert_eq!(R32.lane_bits(), 32);
407 assert_eq!(R64.lane_bits(), 64);
408 }
409
410 #[test]
411 fn typevar_functions() {
412 assert_eq!(INVALID.half_width(), None);
413 assert_eq!(INVALID.half_width(), None);
414 assert_eq!(FFLAGS.half_width(), None);
415 assert_eq!(B1.half_width(), None);
416 assert_eq!(B8.half_width(), None);
417 assert_eq!(B16.half_width(), Some(B8));
418 assert_eq!(B32.half_width(), Some(B16));
419 assert_eq!(B64.half_width(), Some(B32));
420 assert_eq!(B128.half_width(), Some(B64));
421 assert_eq!(I8.half_width(), None);
422 assert_eq!(I16.half_width(), Some(I8));
423 assert_eq!(I32.half_width(), Some(I16));
424 assert_eq!(I32X4.half_width(), Some(I16X4));
425 assert_eq!(I64.half_width(), Some(I32));
426 assert_eq!(I128.half_width(), Some(I64));
427 assert_eq!(F32.half_width(), None);
428 assert_eq!(F64.half_width(), Some(F32));
429
430 assert_eq!(INVALID.double_width(), None);
431 assert_eq!(IFLAGS.double_width(), None);
432 assert_eq!(FFLAGS.double_width(), None);
433 assert_eq!(B1.double_width(), None);
434 assert_eq!(B8.double_width(), Some(B16));
435 assert_eq!(B16.double_width(), Some(B32));
436 assert_eq!(B32.double_width(), Some(B64));
437 assert_eq!(B64.double_width(), Some(B128));
438 assert_eq!(B128.double_width(), None);
439 assert_eq!(I8.double_width(), Some(I16));
440 assert_eq!(I16.double_width(), Some(I32));
441 assert_eq!(I32.double_width(), Some(I64));
442 assert_eq!(I32X4.double_width(), Some(I64X4));
443 assert_eq!(I64.double_width(), Some(I128));
444 assert_eq!(I128.double_width(), None);
445 assert_eq!(F32.double_width(), Some(F64));
446 assert_eq!(F64.double_width(), None);
447 }
448
449 #[test]
450 fn vectors() {
451 let big = F64.by(256).unwrap();
452 assert_eq!(big.lane_bits(), 64);
453 assert_eq!(big.lane_count(), 256);
454 assert_eq!(big.bits(), 64 * 256);
455
456 assert_eq!(big.half_vector().unwrap().to_string(), "f64x128");
457 assert_eq!(B1.by(2).unwrap().half_vector().unwrap().to_string(), "b1");
458 assert_eq!(I32.half_vector(), None);
459 assert_eq!(INVALID.half_vector(), None);
460
461 assert_eq!(I32.by(4), Some(I32X4));
463 assert_eq!(F64.by(8), Some(F64X8));
464 }
465
466 #[test]
467 fn format_scalars() {
468 assert_eq!(IFLAGS.to_string(), "iflags");
469 assert_eq!(FFLAGS.to_string(), "fflags");
470 assert_eq!(B1.to_string(), "b1");
471 assert_eq!(B8.to_string(), "b8");
472 assert_eq!(B16.to_string(), "b16");
473 assert_eq!(B32.to_string(), "b32");
474 assert_eq!(B64.to_string(), "b64");
475 assert_eq!(B128.to_string(), "b128");
476 assert_eq!(I8.to_string(), "i8");
477 assert_eq!(I16.to_string(), "i16");
478 assert_eq!(I32.to_string(), "i32");
479 assert_eq!(I64.to_string(), "i64");
480 assert_eq!(I128.to_string(), "i128");
481 assert_eq!(F32.to_string(), "f32");
482 assert_eq!(F64.to_string(), "f64");
483 assert_eq!(R32.to_string(), "r32");
484 assert_eq!(R64.to_string(), "r64");
485 }
486
487 #[test]
488 fn format_vectors() {
489 assert_eq!(B1.by(8).unwrap().to_string(), "b1x8");
490 assert_eq!(B8.by(1).unwrap().to_string(), "b8");
491 assert_eq!(B16.by(256).unwrap().to_string(), "b16x256");
492 assert_eq!(B32.by(4).unwrap().by(2).unwrap().to_string(), "b32x8");
493 assert_eq!(B64.by(8).unwrap().to_string(), "b64x8");
494 assert_eq!(I8.by(64).unwrap().to_string(), "i8x64");
495 assert_eq!(F64.by(2).unwrap().to_string(), "f64x2");
496 assert_eq!(I8.by(3), None);
497 assert_eq!(I8.by(512), None);
498 assert_eq!(INVALID.by(4), None);
499 }
500
501 #[test]
502 fn as_bool() {
503 assert_eq!(I32X4.as_bool(), B32X4);
504 assert_eq!(I32.as_bool(), B1);
505 assert_eq!(I32X4.as_bool_pedantic(), B32X4);
506 assert_eq!(I32.as_bool_pedantic(), B32);
507 }
508}