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 #[cfg(feature = "enable-serde")]
7 use serde::{Deserialize, Serialize};
8 use target_lexicon::{PointerWidth, Triple};
9 
10 /// The type of an SSA value.
11 ///
12 /// The `INVALID` type isn't a real type, and is used as a placeholder in the IR where a type
13 /// field is present put no type is needed, such as the controlling type variable for a
14 /// non-polymorphic instruction.
15 ///
16 /// Basic integer types: `I8`, `I16`, `I32`, `I64`, and `I128`. These types are sign-agnostic.
17 ///
18 /// Basic floating point types: `F32` and `F64`. IEEE single and double precision.
19 ///
20 /// Boolean types: `B1`, `B8`, `B16`, `B32`, `B64`, and `B128`. These all encode 'true' or 'false'. The
21 /// larger types use redundant bits.
22 ///
23 /// SIMD vector types have power-of-two lanes, up to 256. Lanes can be any int/float/bool type.
24 ///
25 #[derive(Copy, Clone, PartialEq, Eq, Hash)]
26 #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
27 pub struct Type(u8);
28 
29 /// Not a valid type. Can't be loaded or stored. Can't be part of a SIMD vector.
30 pub const INVALID: Type = Type(0);
31 
32 // Include code generated by `cranelift-codegen/meta/gen_types.rs`. This file contains constant
33 // definitions for all the scalar types as well as common vector types for 64, 128, 256, and
34 // 512-bit SIMD vectors.
35 include!(concat!(env!("OUT_DIR"), "/types.rs"));
36 
37 impl Type {
38     /// Get the lane type of this SIMD vector type.
39     ///
40     /// A lane type is the same as a SIMD vector type with one lane, so it returns itself.
lane_type(self) -> Self41     pub fn lane_type(self) -> Self {
42         if self.0 < constants::VECTOR_BASE {
43             self
44         } else {
45             Self(constants::LANE_BASE | (self.0 & 0x0f))
46         }
47     }
48 
49     /// The type transformation that returns the lane type of a type variable; it is just a
50     /// renaming of lane_type() to be used in context where we think in terms of type variable
51     /// transformations.
lane_of(self) -> Self52     pub fn lane_of(self) -> Self {
53         self.lane_type()
54     }
55 
56     /// Get log_2 of the number of bits in a lane.
log2_lane_bits(self) -> u857     pub fn log2_lane_bits(self) -> u8 {
58         match self.lane_type() {
59             B1 => 0,
60             B8 | I8 => 3,
61             B16 | I16 => 4,
62             B32 | I32 | F32 | R32 => 5,
63             B64 | I64 | F64 | R64 => 6,
64             B128 | I128 => 7,
65             _ => 0,
66         }
67     }
68 
69     /// Get the number of bits in a lane.
lane_bits(self) -> u870     pub fn lane_bits(self) -> u8 {
71         match self.lane_type() {
72             B1 => 1,
73             B8 | I8 => 8,
74             B16 | I16 => 16,
75             B32 | I32 | F32 | R32 => 32,
76             B64 | I64 | F64 | R64 => 64,
77             B128 | I128 => 128,
78             _ => 0,
79         }
80     }
81 
82     /// Get an integer type with the requested number of bits.
int(bits: u16) -> Option<Self>83     pub fn int(bits: u16) -> Option<Self> {
84         match bits {
85             8 => Some(I8),
86             16 => Some(I16),
87             32 => Some(I32),
88             64 => Some(I64),
89             128 => Some(I128),
90             _ => None,
91         }
92     }
93 
94     /// Get a type with the same number of lanes as `self`, but using `lane` as the lane type.
replace_lanes(self, lane: Self) -> Self95     fn replace_lanes(self, lane: Self) -> Self {
96         debug_assert!(lane.is_lane() && !self.is_special());
97         Self((lane.0 & 0x0f) | (self.0 & 0xf0))
98     }
99 
100     /// Get a type with the same number of lanes as this type, but with the lanes replaced by
101     /// booleans of the same size.
102     ///
103     /// Lane types are treated as vectors with one lane, so they are converted to the multi-bit
104     /// boolean types.
as_bool_pedantic(self) -> Self105     pub fn as_bool_pedantic(self) -> Self {
106         // Replace the low 4 bits with the boolean version, preserve the high 4 bits.
107         self.replace_lanes(match self.lane_type() {
108             B8 | I8 => B8,
109             B16 | I16 => B16,
110             B32 | I32 | F32 => B32,
111             B64 | I64 | F64 => B64,
112             R32 | R64 => panic!("Reference types should not convert to bool"),
113             B128 | I128 => B128,
114             _ => B1,
115         })
116     }
117 
118     /// Get a type with the same number of lanes as this type, but with the lanes replaced by
119     /// booleans of the same size.
120     ///
121     /// Scalar types are all converted to `b1` which is usually what you want.
as_bool(self) -> Self122     pub fn as_bool(self) -> Self {
123         if !self.is_vector() {
124             B1
125         } else {
126             self.as_bool_pedantic()
127         }
128     }
129 
130     /// Get a type with the same number of lanes as this type, but with lanes that are half the
131     /// number of bits.
half_width(self) -> Option<Self>132     pub fn half_width(self) -> Option<Self> {
133         Some(self.replace_lanes(match self.lane_type() {
134             I16 => I8,
135             I32 => I16,
136             I64 => I32,
137             I128 => I64,
138             F64 => F32,
139             B16 => B8,
140             B32 => B16,
141             B64 => B32,
142             B128 => B64,
143             _ => return None,
144         }))
145     }
146 
147     /// Get a type with the same number of lanes as this type, but with lanes that are twice the
148     /// number of bits.
double_width(self) -> Option<Self>149     pub fn double_width(self) -> Option<Self> {
150         Some(self.replace_lanes(match self.lane_type() {
151             I8 => I16,
152             I16 => I32,
153             I32 => I64,
154             I64 => I128,
155             F32 => F64,
156             B8 => B16,
157             B16 => B32,
158             B32 => B64,
159             B64 => B128,
160             _ => return None,
161         }))
162     }
163 
164     /// Is this the INVALID type?
is_invalid(self) -> bool165     pub fn is_invalid(self) -> bool {
166         self == INVALID
167     }
168 
169     /// Is this a special type?
is_special(self) -> bool170     pub fn is_special(self) -> bool {
171         self.0 < constants::LANE_BASE
172     }
173 
174     /// Is this a lane type?
175     ///
176     /// This is a scalar type that can also appear as the lane type of a SIMD vector.
is_lane(self) -> bool177     pub fn is_lane(self) -> bool {
178         constants::LANE_BASE <= self.0 && self.0 < constants::VECTOR_BASE
179     }
180 
181     /// Is this a SIMD vector type?
182     ///
183     /// A vector type has 2 or more lanes.
is_vector(self) -> bool184     pub fn is_vector(self) -> bool {
185         self.0 >= constants::VECTOR_BASE
186     }
187 
188     /// Is this a scalar boolean type?
is_bool(self) -> bool189     pub fn is_bool(self) -> bool {
190         match self {
191             B1 | B8 | B16 | B32 | B64 | B128 => true,
192             _ => false,
193         }
194     }
195 
196     /// Is this a scalar integer type?
is_int(self) -> bool197     pub fn is_int(self) -> bool {
198         match self {
199             I8 | I16 | I32 | I64 | I128 => true,
200             _ => false,
201         }
202     }
203 
204     /// Is this a scalar floating point type?
is_float(self) -> bool205     pub fn is_float(self) -> bool {
206         match self {
207             F32 | F64 => true,
208             _ => false,
209         }
210     }
211 
212     /// Is this a CPU flags type?
is_flags(self) -> bool213     pub fn is_flags(self) -> bool {
214         match self {
215             IFLAGS | FFLAGS => true,
216             _ => false,
217         }
218     }
219 
220     /// Is this a ref type?
is_ref(self) -> bool221     pub fn is_ref(self) -> bool {
222         match self {
223             R32 | R64 => true,
224             _ => false,
225         }
226     }
227 
228     /// Get log_2 of the number of lanes in this SIMD vector type.
229     ///
230     /// All SIMD types have a lane count that is a power of two and no larger than 256, so this
231     /// will be a number in the range 0-8.
232     ///
233     /// A scalar type is the same as a SIMD vector type with one lane, so it returns 0.
log2_lane_count(self) -> u8234     pub fn log2_lane_count(self) -> u8 {
235         self.0.saturating_sub(constants::LANE_BASE) >> 4
236     }
237 
238     /// Get the number of lanes in this SIMD vector type.
239     ///
240     /// A scalar type is the same as a SIMD vector type with one lane, so it returns 1.
lane_count(self) -> u16241     pub fn lane_count(self) -> u16 {
242         1 << self.log2_lane_count()
243     }
244 
245     /// Get the total number of bits used to represent this type.
bits(self) -> u16246     pub fn bits(self) -> u16 {
247         u16::from(self.lane_bits()) * self.lane_count()
248     }
249 
250     /// Get the number of bytes used to store this type in memory.
bytes(self) -> u32251     pub fn bytes(self) -> u32 {
252         (u32::from(self.bits()) + 7) / 8
253     }
254 
255     /// Get a SIMD vector type with `n` times more lanes than this one.
256     ///
257     /// If this is a scalar type, this produces a SIMD type with this as a lane type and `n` lanes.
258     ///
259     /// If this is already a SIMD vector type, this produces a SIMD vector type with `n *
260     /// self.lane_count()` lanes.
by(self, n: u16) -> Option<Self>261     pub fn by(self, n: u16) -> Option<Self> {
262         if self.lane_bits() == 0 || !n.is_power_of_two() {
263             return None;
264         }
265         let log2_lanes: u32 = n.trailing_zeros();
266         let new_type = u32::from(self.0) + (log2_lanes << 4);
267         if new_type < 0x100 {
268             Some(Self(new_type as u8))
269         } else {
270             None
271         }
272     }
273 
274     /// Get a SIMD vector with half the number of lanes.
275     ///
276     /// There is no `double_vector()` method. Use `t.by(2)` instead.
half_vector(self) -> Option<Self>277     pub fn half_vector(self) -> Option<Self> {
278         if self.is_vector() {
279             Some(Self(self.0 - 0x10))
280         } else {
281             None
282         }
283     }
284 
285     /// Split the lane width in half and double the number of lanes to maintain the same bit-width.
286     ///
287     /// If this is a scalar type of `n` bits, it produces a SIMD vector type of `(n/2)x2`.
split_lanes(self) -> Option<Self>288     pub fn split_lanes(self) -> Option<Self> {
289         match self.half_width() {
290             Some(half_width) => half_width.by(2),
291             None => None,
292         }
293     }
294 
295     /// Merge lanes to half the number of lanes and double the lane width to maintain the same
296     /// bit-width.
297     ///
298     /// If this is a scalar type, it will return `None`.
merge_lanes(self) -> Option<Self>299     pub fn merge_lanes(self) -> Option<Self> {
300         match self.double_width() {
301             Some(double_width) => double_width.half_vector(),
302             None => None,
303         }
304     }
305 
306     /// Index of this type, for use with hash tables etc.
index(self) -> usize307     pub fn index(self) -> usize {
308         usize::from(self.0)
309     }
310 
311     /// True iff:
312     ///
313     /// 1. `self.lane_count() == other.lane_count()` and
314     /// 2. `self.lane_bits() >= other.lane_bits()`
wider_or_equal(self, other: Self) -> bool315     pub fn wider_or_equal(self, other: Self) -> bool {
316         self.lane_count() == other.lane_count() && self.lane_bits() >= other.lane_bits()
317     }
318 
319     /// Return the pointer type for the given target triple.
triple_pointer_type(triple: &Triple) -> Self320     pub fn triple_pointer_type(triple: &Triple) -> Self {
321         match triple.pointer_width() {
322             Ok(PointerWidth::U16) => I16,
323             Ok(PointerWidth::U32) => I32,
324             Ok(PointerWidth::U64) => I64,
325             Err(()) => panic!("unable to determine architecture pointer width"),
326         }
327     }
328 }
329 
330 impl Display for Type {
fmt(&self, f: &mut Formatter) -> fmt::Result331     fn fmt(&self, f: &mut Formatter) -> fmt::Result {
332         if self.is_bool() {
333             write!(f, "b{}", self.lane_bits())
334         } else if self.is_int() {
335             write!(f, "i{}", self.lane_bits())
336         } else if self.is_float() {
337             write!(f, "f{}", self.lane_bits())
338         } else if self.is_vector() {
339             write!(f, "{}x{}", self.lane_type(), self.lane_count())
340         } else if self.is_ref() {
341             write!(f, "r{}", self.lane_bits())
342         } else {
343             f.write_str(match *self {
344                 IFLAGS => "iflags",
345                 FFLAGS => "fflags",
346                 SARG_T => "sarg_t",
347                 INVALID => panic!("INVALID encountered"),
348                 _ => panic!("Unknown Type(0x{:x})", self.0),
349             })
350         }
351     }
352 }
353 
354 impl Debug for Type {
fmt(&self, f: &mut Formatter) -> fmt::Result355     fn fmt(&self, f: &mut Formatter) -> fmt::Result {
356         if self.is_bool() {
357             write!(f, "types::B{}", self.lane_bits())
358         } else if self.is_int() {
359             write!(f, "types::I{}", self.lane_bits())
360         } else if self.is_float() {
361             write!(f, "types::F{}", self.lane_bits())
362         } else if self.is_vector() {
363             write!(f, "{:?}X{}", self.lane_type(), self.lane_count())
364         } else if self.is_ref() {
365             write!(f, "types::R{}", self.lane_bits())
366         } else {
367             match *self {
368                 INVALID => write!(f, "types::INVALID"),
369                 IFLAGS => write!(f, "types::IFLAGS"),
370                 FFLAGS => write!(f, "types::FFLAGS"),
371                 _ => write!(f, "Type(0x{:x})", self.0),
372             }
373         }
374     }
375 }
376 
377 impl Default for Type {
default() -> Self378     fn default() -> Self {
379         INVALID
380     }
381 }
382 
383 #[cfg(test)]
384 mod tests {
385     use super::*;
386     use alloc::string::ToString;
387 
388     #[test]
basic_scalars()389     fn basic_scalars() {
390         assert_eq!(INVALID, INVALID.lane_type());
391         assert_eq!(0, INVALID.bits());
392         assert_eq!(IFLAGS, IFLAGS.lane_type());
393         assert_eq!(0, IFLAGS.bits());
394         assert_eq!(FFLAGS, FFLAGS.lane_type());
395         assert_eq!(0, FFLAGS.bits());
396         assert_eq!(B1, B1.lane_type());
397         assert_eq!(B8, B8.lane_type());
398         assert_eq!(B16, B16.lane_type());
399         assert_eq!(B32, B32.lane_type());
400         assert_eq!(B64, B64.lane_type());
401         assert_eq!(B128, B128.lane_type());
402         assert_eq!(I8, I8.lane_type());
403         assert_eq!(I16, I16.lane_type());
404         assert_eq!(I32, I32.lane_type());
405         assert_eq!(I64, I64.lane_type());
406         assert_eq!(I128, I128.lane_type());
407         assert_eq!(F32, F32.lane_type());
408         assert_eq!(F64, F64.lane_type());
409         assert_eq!(B1, B1.by(8).unwrap().lane_type());
410         assert_eq!(I32, I32X4.lane_type());
411         assert_eq!(F64, F64X2.lane_type());
412         assert_eq!(R32, R32.lane_type());
413         assert_eq!(R64, R64.lane_type());
414 
415         assert_eq!(INVALID.lane_bits(), 0);
416         assert_eq!(IFLAGS.lane_bits(), 0);
417         assert_eq!(FFLAGS.lane_bits(), 0);
418         assert_eq!(B1.lane_bits(), 1);
419         assert_eq!(B8.lane_bits(), 8);
420         assert_eq!(B16.lane_bits(), 16);
421         assert_eq!(B32.lane_bits(), 32);
422         assert_eq!(B64.lane_bits(), 64);
423         assert_eq!(B128.lane_bits(), 128);
424         assert_eq!(I8.lane_bits(), 8);
425         assert_eq!(I16.lane_bits(), 16);
426         assert_eq!(I32.lane_bits(), 32);
427         assert_eq!(I64.lane_bits(), 64);
428         assert_eq!(I128.lane_bits(), 128);
429         assert_eq!(F32.lane_bits(), 32);
430         assert_eq!(F64.lane_bits(), 64);
431         assert_eq!(R32.lane_bits(), 32);
432         assert_eq!(R64.lane_bits(), 64);
433     }
434 
435     #[test]
typevar_functions()436     fn typevar_functions() {
437         assert_eq!(INVALID.half_width(), None);
438         assert_eq!(INVALID.half_width(), None);
439         assert_eq!(FFLAGS.half_width(), None);
440         assert_eq!(B1.half_width(), None);
441         assert_eq!(B8.half_width(), None);
442         assert_eq!(B16.half_width(), Some(B8));
443         assert_eq!(B32.half_width(), Some(B16));
444         assert_eq!(B64.half_width(), Some(B32));
445         assert_eq!(B128.half_width(), Some(B64));
446         assert_eq!(I8.half_width(), None);
447         assert_eq!(I16.half_width(), Some(I8));
448         assert_eq!(I32.half_width(), Some(I16));
449         assert_eq!(I32X4.half_width(), Some(I16X4));
450         assert_eq!(I64.half_width(), Some(I32));
451         assert_eq!(I128.half_width(), Some(I64));
452         assert_eq!(F32.half_width(), None);
453         assert_eq!(F64.half_width(), Some(F32));
454 
455         assert_eq!(INVALID.double_width(), None);
456         assert_eq!(IFLAGS.double_width(), None);
457         assert_eq!(FFLAGS.double_width(), None);
458         assert_eq!(B1.double_width(), None);
459         assert_eq!(B8.double_width(), Some(B16));
460         assert_eq!(B16.double_width(), Some(B32));
461         assert_eq!(B32.double_width(), Some(B64));
462         assert_eq!(B64.double_width(), Some(B128));
463         assert_eq!(B128.double_width(), None);
464         assert_eq!(I8.double_width(), Some(I16));
465         assert_eq!(I16.double_width(), Some(I32));
466         assert_eq!(I32.double_width(), Some(I64));
467         assert_eq!(I32X4.double_width(), Some(I64X4));
468         assert_eq!(I64.double_width(), Some(I128));
469         assert_eq!(I128.double_width(), None);
470         assert_eq!(F32.double_width(), Some(F64));
471         assert_eq!(F64.double_width(), None);
472     }
473 
474     #[test]
vectors()475     fn vectors() {
476         let big = F64.by(256).unwrap();
477         assert_eq!(big.lane_bits(), 64);
478         assert_eq!(big.lane_count(), 256);
479         assert_eq!(big.bits(), 64 * 256);
480 
481         assert_eq!(big.half_vector().unwrap().to_string(), "f64x128");
482         assert_eq!(B1.by(2).unwrap().half_vector().unwrap().to_string(), "b1");
483         assert_eq!(I32.half_vector(), None);
484         assert_eq!(INVALID.half_vector(), None);
485 
486         // Check that the generated constants match the computed vector types.
487         assert_eq!(I32.by(4), Some(I32X4));
488         assert_eq!(F64.by(8), Some(F64X8));
489     }
490 
491     #[test]
format_scalars()492     fn format_scalars() {
493         assert_eq!(IFLAGS.to_string(), "iflags");
494         assert_eq!(FFLAGS.to_string(), "fflags");
495         assert_eq!(B1.to_string(), "b1");
496         assert_eq!(B8.to_string(), "b8");
497         assert_eq!(B16.to_string(), "b16");
498         assert_eq!(B32.to_string(), "b32");
499         assert_eq!(B64.to_string(), "b64");
500         assert_eq!(B128.to_string(), "b128");
501         assert_eq!(I8.to_string(), "i8");
502         assert_eq!(I16.to_string(), "i16");
503         assert_eq!(I32.to_string(), "i32");
504         assert_eq!(I64.to_string(), "i64");
505         assert_eq!(I128.to_string(), "i128");
506         assert_eq!(F32.to_string(), "f32");
507         assert_eq!(F64.to_string(), "f64");
508         assert_eq!(R32.to_string(), "r32");
509         assert_eq!(R64.to_string(), "r64");
510     }
511 
512     #[test]
format_vectors()513     fn format_vectors() {
514         assert_eq!(B1.by(8).unwrap().to_string(), "b1x8");
515         assert_eq!(B8.by(1).unwrap().to_string(), "b8");
516         assert_eq!(B16.by(256).unwrap().to_string(), "b16x256");
517         assert_eq!(B32.by(4).unwrap().by(2).unwrap().to_string(), "b32x8");
518         assert_eq!(B64.by(8).unwrap().to_string(), "b64x8");
519         assert_eq!(I8.by(64).unwrap().to_string(), "i8x64");
520         assert_eq!(F64.by(2).unwrap().to_string(), "f64x2");
521         assert_eq!(I8.by(3), None);
522         assert_eq!(I8.by(512), None);
523         assert_eq!(INVALID.by(4), None);
524     }
525 
526     #[test]
as_bool()527     fn as_bool() {
528         assert_eq!(I32X4.as_bool(), B32X4);
529         assert_eq!(I32.as_bool(), B1);
530         assert_eq!(I32X4.as_bool_pedantic(), B32X4);
531         assert_eq!(I32.as_bool_pedantic(), B32);
532     }
533 }
534