1 //! Common types for the Cranelift code generator.
2 
3 use core::default::Default;
4 use core::fmt::{self, Debug, Display, Formatter};
5 use cranelift_codegen_shared::constants;
6 use target_lexicon::{PointerWidth, Triple};
7 
8 /// The type of an SSA value.
9 ///
10 /// The `INVALID` type isn't a real type, and is used as a placeholder in the IR where a type
11 /// field is present put no type is needed, such as the controlling type variable for a
12 /// non-polymorphic instruction.
13 ///
14 /// Basic integer types: `I8`, `I16`, `I32`, `I64`, and `I128`. These types are sign-agnostic.
15 ///
16 /// Basic floating point types: `F32` and `F64`. IEEE single and double precision.
17 ///
18 /// Boolean types: `B1`, `B8`, `B16`, `B32`, `B64`, and `B128`. These all encode 'true' or 'false'. The
19 /// larger types use redundant bits.
20 ///
21 /// SIMD vector types have power-of-two lanes, up to 256. Lanes can be any int/float/bool type.
22 ///
23 #[derive(Copy, Clone, PartialEq, Eq, Hash)]
24 pub struct Type(u8);
25 
26 /// Not a valid type. Can't be loaded or stored. Can't be part of a SIMD vector.
27 pub const INVALID: Type = Type(0);
28 
29 // Include code generated by `cranelift-codegen/meta/gen_types.rs`. This file contains constant
30 // definitions for all the scalar types as well as common vector types for 64, 128, 256, and
31 // 512-bit SIMD vectors.
32 include!(concat!(env!("OUT_DIR"), "/types.rs"));
33 
34 impl Type {
35     /// Get the lane type of this SIMD vector type.
36     ///
37     /// A lane type is the same as a SIMD vector type with one lane, so it returns itself.
lane_type(self) -> Self38     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     /// The type transformation that returns the lane type of a type variable; it is just a
47     /// renaming of lane_type() to be used in context where we think in terms of type variable
48     /// transformations.
lane_of(self) -> Self49     pub fn lane_of(self) -> Self {
50         self.lane_type()
51     }
52 
53     /// Get log_2 of the number of bits in a lane.
log2_lane_bits(self) -> u854     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     /// Get the number of bits in a lane.
lane_bits(self) -> u867     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     /// Get an integer type with the requested number of bits.
int(bits: u16) -> Option<Self>80     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     /// Get a type with the same number of lanes as `self`, but using `lane` as the lane type.
replace_lanes(self, lane: Self) -> Self92     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     /// Get a type with the same number of lanes as this type, but with the lanes replaced by
98     /// booleans of the same size.
99     ///
100     /// Lane types are treated as vectors with one lane, so they are converted to the multi-bit
101     /// boolean types.
as_bool_pedantic(self) -> Self102     pub fn as_bool_pedantic(self) -> Self {
103         // Replace the low 4 bits with the boolean version, preserve the high 4 bits.
104         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     /// Get a type with the same number of lanes as this type, but with the lanes replaced by
116     /// booleans of the same size.
117     ///
118     /// Scalar types are all converted to `b1` which is usually what you want.
as_bool(self) -> Self119     pub fn as_bool(self) -> Self {
120         if !self.is_vector() {
121             B1
122         } else {
123             self.as_bool_pedantic()
124         }
125     }
126 
127     /// Get a type with the same number of lanes as this type, but with lanes that are half the
128     /// number of bits.
half_width(self) -> Option<Self>129     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     /// Get a type with the same number of lanes as this type, but with lanes that are twice the
145     /// number of bits.
double_width(self) -> Option<Self>146     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     /// Is this the INVALID type?
is_invalid(self) -> bool162     pub fn is_invalid(self) -> bool {
163         self == INVALID
164     }
165 
166     /// Is this a special type?
is_special(self) -> bool167     pub fn is_special(self) -> bool {
168         self.0 < constants::LANE_BASE
169     }
170 
171     /// Is this a lane type?
172     ///
173     /// This is a scalar type that can also appear as the lane type of a SIMD vector.
is_lane(self) -> bool174     pub fn is_lane(self) -> bool {
175         constants::LANE_BASE <= self.0 && self.0 < constants::VECTOR_BASE
176     }
177 
178     /// Is this a SIMD vector type?
179     ///
180     /// A vector type has 2 or more lanes.
is_vector(self) -> bool181     pub fn is_vector(self) -> bool {
182         self.0 >= constants::VECTOR_BASE
183     }
184 
185     /// Is this a scalar boolean type?
is_bool(self) -> bool186     pub fn is_bool(self) -> bool {
187         match self {
188             B1 | B8 | B16 | B32 | B64 | B128 => true,
189             _ => false,
190         }
191     }
192 
193     /// Is this a scalar integer type?
is_int(self) -> bool194     pub fn is_int(self) -> bool {
195         match self {
196             I8 | I16 | I32 | I64 | I128 => true,
197             _ => false,
198         }
199     }
200 
201     /// Is this a scalar floating point type?
is_float(self) -> bool202     pub fn is_float(self) -> bool {
203         match self {
204             F32 | F64 => true,
205             _ => false,
206         }
207     }
208 
209     /// Is this a CPU flags type?
is_flags(self) -> bool210     pub fn is_flags(self) -> bool {
211         match self {
212             IFLAGS | FFLAGS => true,
213             _ => false,
214         }
215     }
216 
217     /// Is this a ref type?
is_ref(self) -> bool218     pub fn is_ref(self) -> bool {
219         match self {
220             R32 | R64 => true,
221             _ => false,
222         }
223     }
224 
225     /// Get log_2 of the number of lanes in this SIMD vector type.
226     ///
227     /// All SIMD types have a lane count that is a power of two and no larger than 256, so this
228     /// will be a number in the range 0-8.
229     ///
230     /// A scalar type is the same as a SIMD vector type with one lane, so it returns 0.
log2_lane_count(self) -> u8231     pub fn log2_lane_count(self) -> u8 {
232         self.0.saturating_sub(constants::LANE_BASE) >> 4
233     }
234 
235     /// Get the number of lanes in this SIMD vector type.
236     ///
237     /// A scalar type is the same as a SIMD vector type with one lane, so it returns 1.
lane_count(self) -> u16238     pub fn lane_count(self) -> u16 {
239         1 << self.log2_lane_count()
240     }
241 
242     /// Get the total number of bits used to represent this type.
bits(self) -> u16243     pub fn bits(self) -> u16 {
244         u16::from(self.lane_bits()) * self.lane_count()
245     }
246 
247     /// Get the number of bytes used to store this type in memory.
bytes(self) -> u32248     pub fn bytes(self) -> u32 {
249         (u32::from(self.bits()) + 7) / 8
250     }
251 
252     /// Get a SIMD vector type with `n` times more lanes than this one.
253     ///
254     /// If this is a scalar type, this produces a SIMD type with this as a lane type and `n` lanes.
255     ///
256     /// If this is already a SIMD vector type, this produces a SIMD vector type with `n *
257     /// self.lane_count()` lanes.
by(self, n: u16) -> Option<Self>258     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     /// Get a SIMD vector with half the number of lanes.
272     ///
273     /// There is no `double_vector()` method. Use `t.by(2)` instead.
half_vector(self) -> Option<Self>274     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     /// Split the lane width in half and double the number of lanes to maintain the same bit-width.
283     ///
284     /// If this is a scalar type of n bits, it produces a SIMD vector type of (n/2)x2.
split_lanes(self) -> Option<Self>285     pub fn split_lanes(self) -> Option<Self> {
286         match self.half_width() {
287             Some(half_width) => half_width.by(2),
288             None => None,
289         }
290     }
291 
292     /// Index of this type, for use with hash tables etc.
index(self) -> usize293     pub fn index(self) -> usize {
294         usize::from(self.0)
295     }
296 
297     /// True iff:
298     ///
299     /// 1. `self.lane_count() == other.lane_count()` and
300     /// 2. `self.lane_bits() >= other.lane_bits()`
wider_or_equal(self, other: Self) -> bool301     pub fn wider_or_equal(self, other: Self) -> bool {
302         self.lane_count() == other.lane_count() && self.lane_bits() >= other.lane_bits()
303     }
304 
305     /// Return the pointer type for the given target triple.
triple_pointer_type(triple: &Triple) -> Self306     pub fn triple_pointer_type(triple: &Triple) -> Self {
307         match triple.pointer_width() {
308             Ok(PointerWidth::U16) => I16,
309             Ok(PointerWidth::U32) => I32,
310             Ok(PointerWidth::U64) => I64,
311             Err(()) => panic!("unable to determine architecture pointer width"),
312         }
313     }
314 }
315 
316 impl Display for Type {
fmt(&self, f: &mut Formatter) -> fmt::Result317     fn fmt(&self, f: &mut Formatter) -> fmt::Result {
318         if self.is_bool() {
319             write!(f, "b{}", self.lane_bits())
320         } else if self.is_int() {
321             write!(f, "i{}", self.lane_bits())
322         } else if self.is_float() {
323             write!(f, "f{}", self.lane_bits())
324         } else if self.is_vector() {
325             write!(f, "{}x{}", self.lane_type(), self.lane_count())
326         } else if self.is_ref() {
327             write!(f, "r{}", self.lane_bits())
328         } else {
329             f.write_str(match *self {
330                 IFLAGS => "iflags",
331                 FFLAGS => "fflags",
332                 INVALID => panic!("INVALID encountered"),
333                 _ => panic!("Unknown Type(0x{:x})", self.0),
334             })
335         }
336     }
337 }
338 
339 impl Debug for Type {
fmt(&self, f: &mut Formatter) -> fmt::Result340     fn fmt(&self, f: &mut Formatter) -> fmt::Result {
341         if self.is_bool() {
342             write!(f, "types::B{}", self.lane_bits())
343         } else if self.is_int() {
344             write!(f, "types::I{}", self.lane_bits())
345         } else if self.is_float() {
346             write!(f, "types::F{}", self.lane_bits())
347         } else if self.is_vector() {
348             write!(f, "{:?}X{}", self.lane_type(), self.lane_count())
349         } else if self.is_ref() {
350             write!(f, "types::R{}", self.lane_bits())
351         } else {
352             match *self {
353                 INVALID => write!(f, "types::INVALID"),
354                 IFLAGS => write!(f, "types::IFLAGS"),
355                 FFLAGS => write!(f, "types::FFLAGS"),
356                 _ => write!(f, "Type(0x{:x})", self.0),
357             }
358         }
359     }
360 }
361 
362 impl Default for Type {
default() -> Self363     fn default() -> Self {
364         INVALID
365     }
366 }
367 
368 #[cfg(test)]
369 mod tests {
370     use super::*;
371     use alloc::string::ToString;
372 
373     #[test]
basic_scalars()374     fn basic_scalars() {
375         assert_eq!(INVALID, INVALID.lane_type());
376         assert_eq!(0, INVALID.bits());
377         assert_eq!(IFLAGS, IFLAGS.lane_type());
378         assert_eq!(0, IFLAGS.bits());
379         assert_eq!(FFLAGS, FFLAGS.lane_type());
380         assert_eq!(0, FFLAGS.bits());
381         assert_eq!(B1, B1.lane_type());
382         assert_eq!(B8, B8.lane_type());
383         assert_eq!(B16, B16.lane_type());
384         assert_eq!(B32, B32.lane_type());
385         assert_eq!(B64, B64.lane_type());
386         assert_eq!(B128, B128.lane_type());
387         assert_eq!(I8, I8.lane_type());
388         assert_eq!(I16, I16.lane_type());
389         assert_eq!(I32, I32.lane_type());
390         assert_eq!(I64, I64.lane_type());
391         assert_eq!(I128, I128.lane_type());
392         assert_eq!(F32, F32.lane_type());
393         assert_eq!(F64, F64.lane_type());
394         assert_eq!(B1, B1.by(8).unwrap().lane_type());
395         assert_eq!(I32, I32X4.lane_type());
396         assert_eq!(F64, F64X2.lane_type());
397         assert_eq!(R32, R32.lane_type());
398         assert_eq!(R64, R64.lane_type());
399 
400         assert_eq!(INVALID.lane_bits(), 0);
401         assert_eq!(IFLAGS.lane_bits(), 0);
402         assert_eq!(FFLAGS.lane_bits(), 0);
403         assert_eq!(B1.lane_bits(), 1);
404         assert_eq!(B8.lane_bits(), 8);
405         assert_eq!(B16.lane_bits(), 16);
406         assert_eq!(B32.lane_bits(), 32);
407         assert_eq!(B64.lane_bits(), 64);
408         assert_eq!(B128.lane_bits(), 128);
409         assert_eq!(I8.lane_bits(), 8);
410         assert_eq!(I16.lane_bits(), 16);
411         assert_eq!(I32.lane_bits(), 32);
412         assert_eq!(I64.lane_bits(), 64);
413         assert_eq!(I128.lane_bits(), 128);
414         assert_eq!(F32.lane_bits(), 32);
415         assert_eq!(F64.lane_bits(), 64);
416         assert_eq!(R32.lane_bits(), 32);
417         assert_eq!(R64.lane_bits(), 64);
418     }
419 
420     #[test]
typevar_functions()421     fn typevar_functions() {
422         assert_eq!(INVALID.half_width(), None);
423         assert_eq!(INVALID.half_width(), None);
424         assert_eq!(FFLAGS.half_width(), None);
425         assert_eq!(B1.half_width(), None);
426         assert_eq!(B8.half_width(), None);
427         assert_eq!(B16.half_width(), Some(B8));
428         assert_eq!(B32.half_width(), Some(B16));
429         assert_eq!(B64.half_width(), Some(B32));
430         assert_eq!(B128.half_width(), Some(B64));
431         assert_eq!(I8.half_width(), None);
432         assert_eq!(I16.half_width(), Some(I8));
433         assert_eq!(I32.half_width(), Some(I16));
434         assert_eq!(I32X4.half_width(), Some(I16X4));
435         assert_eq!(I64.half_width(), Some(I32));
436         assert_eq!(I128.half_width(), Some(I64));
437         assert_eq!(F32.half_width(), None);
438         assert_eq!(F64.half_width(), Some(F32));
439 
440         assert_eq!(INVALID.double_width(), None);
441         assert_eq!(IFLAGS.double_width(), None);
442         assert_eq!(FFLAGS.double_width(), None);
443         assert_eq!(B1.double_width(), None);
444         assert_eq!(B8.double_width(), Some(B16));
445         assert_eq!(B16.double_width(), Some(B32));
446         assert_eq!(B32.double_width(), Some(B64));
447         assert_eq!(B64.double_width(), Some(B128));
448         assert_eq!(B128.double_width(), None);
449         assert_eq!(I8.double_width(), Some(I16));
450         assert_eq!(I16.double_width(), Some(I32));
451         assert_eq!(I32.double_width(), Some(I64));
452         assert_eq!(I32X4.double_width(), Some(I64X4));
453         assert_eq!(I64.double_width(), Some(I128));
454         assert_eq!(I128.double_width(), None);
455         assert_eq!(F32.double_width(), Some(F64));
456         assert_eq!(F64.double_width(), None);
457     }
458 
459     #[test]
vectors()460     fn vectors() {
461         let big = F64.by(256).unwrap();
462         assert_eq!(big.lane_bits(), 64);
463         assert_eq!(big.lane_count(), 256);
464         assert_eq!(big.bits(), 64 * 256);
465 
466         assert_eq!(big.half_vector().unwrap().to_string(), "f64x128");
467         assert_eq!(B1.by(2).unwrap().half_vector().unwrap().to_string(), "b1");
468         assert_eq!(I32.half_vector(), None);
469         assert_eq!(INVALID.half_vector(), None);
470 
471         // Check that the generated constants match the computed vector types.
472         assert_eq!(I32.by(4), Some(I32X4));
473         assert_eq!(F64.by(8), Some(F64X8));
474     }
475 
476     #[test]
format_scalars()477     fn format_scalars() {
478         assert_eq!(IFLAGS.to_string(), "iflags");
479         assert_eq!(FFLAGS.to_string(), "fflags");
480         assert_eq!(B1.to_string(), "b1");
481         assert_eq!(B8.to_string(), "b8");
482         assert_eq!(B16.to_string(), "b16");
483         assert_eq!(B32.to_string(), "b32");
484         assert_eq!(B64.to_string(), "b64");
485         assert_eq!(B128.to_string(), "b128");
486         assert_eq!(I8.to_string(), "i8");
487         assert_eq!(I16.to_string(), "i16");
488         assert_eq!(I32.to_string(), "i32");
489         assert_eq!(I64.to_string(), "i64");
490         assert_eq!(I128.to_string(), "i128");
491         assert_eq!(F32.to_string(), "f32");
492         assert_eq!(F64.to_string(), "f64");
493         assert_eq!(R32.to_string(), "r32");
494         assert_eq!(R64.to_string(), "r64");
495     }
496 
497     #[test]
format_vectors()498     fn format_vectors() {
499         assert_eq!(B1.by(8).unwrap().to_string(), "b1x8");
500         assert_eq!(B8.by(1).unwrap().to_string(), "b8");
501         assert_eq!(B16.by(256).unwrap().to_string(), "b16x256");
502         assert_eq!(B32.by(4).unwrap().by(2).unwrap().to_string(), "b32x8");
503         assert_eq!(B64.by(8).unwrap().to_string(), "b64x8");
504         assert_eq!(I8.by(64).unwrap().to_string(), "i8x64");
505         assert_eq!(F64.by(2).unwrap().to_string(), "f64x2");
506         assert_eq!(I8.by(3), None);
507         assert_eq!(I8.by(512), None);
508         assert_eq!(INVALID.by(4), None);
509     }
510 
511     #[test]
as_bool()512     fn as_bool() {
513         assert_eq!(I32X4.as_bool(), B32X4);
514         assert_eq!(I32.as_bool(), B1);
515         assert_eq!(I32X4.as_bool_pedantic(), B32X4);
516         assert_eq!(I32.as_bool_pedantic(), B32);
517     }
518 }
519