1 //! Cranelift ValueType hierarchy
2 
3 use std::fmt;
4 
5 use crate::shared::types as shared_types;
6 use cranelift_codegen_shared::constants;
7 
8 // Rust name prefix used for the `rust_name` method.
9 static _RUST_NAME_PREFIX: &str = "ir::types::";
10 
11 // ValueType variants (i8, i32, ...) are provided in `shared::types.rs`.
12 
13 /// A concrete SSA value type.
14 ///
15 /// All SSA values have a type that is described by an instance of `ValueType`
16 /// or one of its subclasses.
17 #[derive(Clone, Debug, PartialEq, Eq, Hash)]
18 pub(crate) enum ValueType {
19     Lane(LaneType),
20     Reference(ReferenceType),
21     Special(SpecialType),
22     Vector(VectorType),
23 }
24 
25 impl ValueType {
26     /// Iterate through all of the lane types.
all_lane_types() -> LaneTypeIterator27     pub fn all_lane_types() -> LaneTypeIterator {
28         LaneTypeIterator::new()
29     }
30 
31     /// Iterate through all of the special types (neither lanes nor vectors).
all_special_types() -> SpecialTypeIterator32     pub fn all_special_types() -> SpecialTypeIterator {
33         SpecialTypeIterator::new()
34     }
35 
all_reference_types() -> ReferenceTypeIterator36     pub fn all_reference_types() -> ReferenceTypeIterator {
37         ReferenceTypeIterator::new()
38     }
39 
40     /// Return a string containing the documentation comment for this type.
doc(&self) -> String41     pub fn doc(&self) -> String {
42         match *self {
43             ValueType::Lane(l) => l.doc(),
44             ValueType::Reference(r) => r.doc(),
45             ValueType::Special(s) => s.doc(),
46             ValueType::Vector(ref v) => v.doc(),
47         }
48     }
49 
50     /// Return the number of bits in a lane.
lane_bits(&self) -> u6451     pub fn lane_bits(&self) -> u64 {
52         match *self {
53             ValueType::Lane(l) => l.lane_bits(),
54             ValueType::Reference(r) => r.lane_bits(),
55             ValueType::Special(s) => s.lane_bits(),
56             ValueType::Vector(ref v) => v.lane_bits(),
57         }
58     }
59 
60     /// Return the number of lanes.
lane_count(&self) -> u6461     pub fn lane_count(&self) -> u64 {
62         match *self {
63             ValueType::Vector(ref v) => v.lane_count(),
64             _ => 1,
65         }
66     }
67 
68     /// Find the number of bytes that this type occupies in memory.
membytes(&self) -> u6469     pub fn membytes(&self) -> u64 {
70         self.width() / 8
71     }
72 
73     /// Find the unique number associated with this type.
number(&self) -> Option<u8>74     pub fn number(&self) -> Option<u8> {
75         match *self {
76             ValueType::Lane(l) => Some(l.number()),
77             ValueType::Reference(r) => Some(r.number()),
78             ValueType::Special(s) => Some(s.number()),
79             ValueType::Vector(ref v) => Some(v.number()),
80         }
81     }
82 
83     /// Return the name of this type for generated Rust source files.
rust_name(&self) -> String84     pub fn rust_name(&self) -> String {
85         format!("{}{}", _RUST_NAME_PREFIX, self.to_string().to_uppercase())
86     }
87 
88     /// Return true iff:
89     ///     1. self and other have equal number of lanes
90     ///     2. each lane in self has at least as many bits as a lane in other
_wider_or_equal(&self, rhs: &ValueType) -> bool91     pub fn _wider_or_equal(&self, rhs: &ValueType) -> bool {
92         (self.lane_count() == rhs.lane_count()) && (self.lane_bits() >= rhs.lane_bits())
93     }
94 
95     /// Return the total number of bits of an instance of this type.
width(&self) -> u6496     pub fn width(&self) -> u64 {
97         self.lane_count() * self.lane_bits()
98     }
99 }
100 
101 impl fmt::Display for ValueType {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result102     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
103         match *self {
104             ValueType::Lane(l) => l.fmt(f),
105             ValueType::Reference(r) => r.fmt(f),
106             ValueType::Special(s) => s.fmt(f),
107             ValueType::Vector(ref v) => v.fmt(f),
108         }
109     }
110 }
111 
112 /// Create a ValueType from a given lane type.
113 impl From<LaneType> for ValueType {
from(lane: LaneType) -> Self114     fn from(lane: LaneType) -> Self {
115         ValueType::Lane(lane)
116     }
117 }
118 
119 /// Create a ValueType from a given reference type.
120 impl From<ReferenceType> for ValueType {
from(reference: ReferenceType) -> Self121     fn from(reference: ReferenceType) -> Self {
122         ValueType::Reference(reference)
123     }
124 }
125 
126 /// Create a ValueType from a given special type.
127 impl From<SpecialType> for ValueType {
from(spec: SpecialType) -> Self128     fn from(spec: SpecialType) -> Self {
129         ValueType::Special(spec)
130     }
131 }
132 
133 /// Create a ValueType from a given vector type.
134 impl From<VectorType> for ValueType {
from(vector: VectorType) -> Self135     fn from(vector: VectorType) -> Self {
136         ValueType::Vector(vector)
137     }
138 }
139 
140 /// A concrete scalar type that can appear as a vector lane too.
141 #[derive(Clone, Copy, PartialEq, Eq, Hash)]
142 pub(crate) enum LaneType {
143     Bool(shared_types::Bool),
144     Float(shared_types::Float),
145     Int(shared_types::Int),
146 }
147 
148 impl LaneType {
149     /// Return a string containing the documentation comment for this lane type.
doc(self) -> String150     pub fn doc(self) -> String {
151         match self {
152             LaneType::Bool(_) => format!("A boolean type with {} bits.", self.lane_bits()),
153             LaneType::Float(shared_types::Float::F32) => String::from(
154                 "A 32-bit floating point type represented in the IEEE 754-2008
155                 *binary32* interchange format. This corresponds to the :c:type:`float`
156                 type in most C implementations.",
157             ),
158             LaneType::Float(shared_types::Float::F64) => String::from(
159                 "A 64-bit floating point type represented in the IEEE 754-2008
160                 *binary64* interchange format. This corresponds to the :c:type:`double`
161                 type in most C implementations.",
162             ),
163             LaneType::Int(_) if self.lane_bits() < 32 => format!(
164                 "An integer type with {} bits.
165                 WARNING: arithmetic on {}bit integers is incomplete",
166                 self.lane_bits(),
167                 self.lane_bits()
168             ),
169             LaneType::Int(_) => format!("An integer type with {} bits.", self.lane_bits()),
170         }
171     }
172 
173     /// Return the number of bits in a lane.
lane_bits(self) -> u64174     pub fn lane_bits(self) -> u64 {
175         match self {
176             LaneType::Bool(ref b) => *b as u64,
177             LaneType::Float(ref f) => *f as u64,
178             LaneType::Int(ref i) => *i as u64,
179         }
180     }
181 
182     /// Find the unique number associated with this lane type.
number(self) -> u8183     pub fn number(self) -> u8 {
184         constants::LANE_BASE
185             + match self {
186                 LaneType::Bool(shared_types::Bool::B1) => 0,
187                 LaneType::Bool(shared_types::Bool::B8) => 1,
188                 LaneType::Bool(shared_types::Bool::B16) => 2,
189                 LaneType::Bool(shared_types::Bool::B32) => 3,
190                 LaneType::Bool(shared_types::Bool::B64) => 4,
191                 LaneType::Bool(shared_types::Bool::B128) => 5,
192                 LaneType::Int(shared_types::Int::I8) => 6,
193                 LaneType::Int(shared_types::Int::I16) => 7,
194                 LaneType::Int(shared_types::Int::I32) => 8,
195                 LaneType::Int(shared_types::Int::I64) => 9,
196                 LaneType::Int(shared_types::Int::I128) => 10,
197                 LaneType::Float(shared_types::Float::F32) => 11,
198                 LaneType::Float(shared_types::Float::F64) => 12,
199             }
200     }
201 
bool_from_bits(num_bits: u16) -> LaneType202     pub fn bool_from_bits(num_bits: u16) -> LaneType {
203         LaneType::Bool(match num_bits {
204             1 => shared_types::Bool::B1,
205             8 => shared_types::Bool::B8,
206             16 => shared_types::Bool::B16,
207             32 => shared_types::Bool::B32,
208             64 => shared_types::Bool::B64,
209             128 => shared_types::Bool::B128,
210             _ => unreachable!("unxpected num bits for bool"),
211         })
212     }
213 
int_from_bits(num_bits: u16) -> LaneType214     pub fn int_from_bits(num_bits: u16) -> LaneType {
215         LaneType::Int(match num_bits {
216             8 => shared_types::Int::I8,
217             16 => shared_types::Int::I16,
218             32 => shared_types::Int::I32,
219             64 => shared_types::Int::I64,
220             128 => shared_types::Int::I128,
221             _ => unreachable!("unxpected num bits for int"),
222         })
223     }
224 
float_from_bits(num_bits: u16) -> LaneType225     pub fn float_from_bits(num_bits: u16) -> LaneType {
226         LaneType::Float(match num_bits {
227             32 => shared_types::Float::F32,
228             64 => shared_types::Float::F64,
229             _ => unreachable!("unxpected num bits for float"),
230         })
231     }
232 
by(self, lanes: u16) -> ValueType233     pub fn by(self, lanes: u16) -> ValueType {
234         if lanes == 1 {
235             self.into()
236         } else {
237             ValueType::Vector(VectorType::new(self, lanes.into()))
238         }
239     }
240 
is_float(self) -> bool241     pub fn is_float(self) -> bool {
242         match self {
243             LaneType::Float(_) => true,
244             _ => false,
245         }
246     }
247 
is_int(self) -> bool248     pub fn is_int(self) -> bool {
249         match self {
250             LaneType::Int(_) => true,
251             _ => false,
252         }
253     }
254 }
255 
256 impl fmt::Display for LaneType {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result257     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
258         match *self {
259             LaneType::Bool(_) => write!(f, "b{}", self.lane_bits()),
260             LaneType::Float(_) => write!(f, "f{}", self.lane_bits()),
261             LaneType::Int(_) => write!(f, "i{}", self.lane_bits()),
262         }
263     }
264 }
265 
266 impl fmt::Debug for LaneType {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result267     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
268         let inner_msg = format!("bits={}", self.lane_bits());
269         write!(
270             f,
271             "{}",
272             match *self {
273                 LaneType::Bool(_) => format!("BoolType({})", inner_msg),
274                 LaneType::Float(_) => format!("FloatType({})", inner_msg),
275                 LaneType::Int(_) => format!("IntType({})", inner_msg),
276             }
277         )
278     }
279 }
280 
281 /// Create a LaneType from a given bool variant.
282 impl From<shared_types::Bool> for LaneType {
from(b: shared_types::Bool) -> Self283     fn from(b: shared_types::Bool) -> Self {
284         LaneType::Bool(b)
285     }
286 }
287 
288 /// Create a LaneType from a given float variant.
289 impl From<shared_types::Float> for LaneType {
from(f: shared_types::Float) -> Self290     fn from(f: shared_types::Float) -> Self {
291         LaneType::Float(f)
292     }
293 }
294 
295 /// Create a LaneType from a given int variant.
296 impl From<shared_types::Int> for LaneType {
from(i: shared_types::Int) -> Self297     fn from(i: shared_types::Int) -> Self {
298         LaneType::Int(i)
299     }
300 }
301 
302 /// An iterator for different lane types.
303 pub(crate) struct LaneTypeIterator {
304     bool_iter: shared_types::BoolIterator,
305     int_iter: shared_types::IntIterator,
306     float_iter: shared_types::FloatIterator,
307 }
308 
309 impl LaneTypeIterator {
310     /// Create a new lane type iterator.
new() -> Self311     fn new() -> Self {
312         Self {
313             bool_iter: shared_types::BoolIterator::new(),
314             int_iter: shared_types::IntIterator::new(),
315             float_iter: shared_types::FloatIterator::new(),
316         }
317     }
318 }
319 
320 impl Iterator for LaneTypeIterator {
321     type Item = LaneType;
next(&mut self) -> Option<Self::Item>322     fn next(&mut self) -> Option<Self::Item> {
323         if let Some(b) = self.bool_iter.next() {
324             Some(LaneType::from(b))
325         } else if let Some(i) = self.int_iter.next() {
326             Some(LaneType::from(i))
327         } else if let Some(f) = self.float_iter.next() {
328             Some(LaneType::from(f))
329         } else {
330             None
331         }
332     }
333 }
334 
335 /// A concrete SIMD vector type.
336 ///
337 /// A vector type has a lane type which is an instance of `LaneType`,
338 /// and a positive number of lanes.
339 #[derive(Clone, PartialEq, Eq, Hash)]
340 pub(crate) struct VectorType {
341     base: LaneType,
342     lanes: u64,
343 }
344 
345 impl VectorType {
346     /// Initialize a new integer type with `n` bits.
new(base: LaneType, lanes: u64) -> Self347     pub fn new(base: LaneType, lanes: u64) -> Self {
348         Self { base, lanes }
349     }
350 
351     /// Return a string containing the documentation comment for this vector type.
doc(&self) -> String352     pub fn doc(&self) -> String {
353         format!(
354             "A SIMD vector with {} lanes containing a `{}` each.",
355             self.lane_count(),
356             self.base
357         )
358     }
359 
360     /// Return the number of bits in a lane.
lane_bits(&self) -> u64361     pub fn lane_bits(&self) -> u64 {
362         self.base.lane_bits()
363     }
364 
365     /// Return the number of lanes.
lane_count(&self) -> u64366     pub fn lane_count(&self) -> u64 {
367         self.lanes
368     }
369 
370     /// Return the lane type.
lane_type(&self) -> LaneType371     pub fn lane_type(&self) -> LaneType {
372         self.base
373     }
374 
375     /// Find the unique number associated with this vector type.
376     ///
377     /// Vector types are encoded with the lane type in the low 4 bits and
378     /// log2(lanes) in the high 4 bits, giving a range of 2-256 lanes.
number(&self) -> u8379     pub fn number(&self) -> u8 {
380         let lanes_log_2: u32 = 63 - self.lane_count().leading_zeros();
381         let base_num = u32::from(self.base.number());
382         let num = (lanes_log_2 << 4) + base_num;
383         num as u8
384     }
385 }
386 
387 impl fmt::Display for VectorType {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result388     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
389         write!(f, "{}x{}", self.base, self.lane_count())
390     }
391 }
392 
393 impl fmt::Debug for VectorType {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result394     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
395         write!(
396             f,
397             "VectorType(base={}, lanes={})",
398             self.base,
399             self.lane_count()
400         )
401     }
402 }
403 
404 /// A concrete scalar type that is neither a vector nor a lane type.
405 ///
406 /// Special types cannot be used to form vectors.
407 #[derive(Clone, Copy, PartialEq, Eq, Hash)]
408 pub(crate) enum SpecialType {
409     Flag(shared_types::Flag),
410     // FIXME remove once the old style backends are removed.
411     StructArgument,
412 }
413 
414 impl SpecialType {
415     /// Return a string containing the documentation comment for this special type.
doc(self) -> String416     pub fn doc(self) -> String {
417         match self {
418             SpecialType::Flag(shared_types::Flag::IFlags) => String::from(
419                 "CPU flags representing the result of an integer comparison. These flags
420                 can be tested with an :type:`intcc` condition code.",
421             ),
422             SpecialType::Flag(shared_types::Flag::FFlags) => String::from(
423                 "CPU flags representing the result of a floating point comparison. These
424                 flags can be tested with a :type:`floatcc` condition code.",
425             ),
426             SpecialType::StructArgument => {
427                 String::from("After legalization sarg_t arguments will get this type.")
428             }
429         }
430     }
431 
432     /// Return the number of bits in a lane.
lane_bits(self) -> u64433     pub fn lane_bits(self) -> u64 {
434         match self {
435             SpecialType::Flag(_) => 0,
436             SpecialType::StructArgument => 0,
437         }
438     }
439 
440     /// Find the unique number associated with this special type.
number(self) -> u8441     pub fn number(self) -> u8 {
442         match self {
443             SpecialType::Flag(shared_types::Flag::IFlags) => 1,
444             SpecialType::Flag(shared_types::Flag::FFlags) => 2,
445             SpecialType::StructArgument => 3,
446         }
447     }
448 }
449 
450 impl fmt::Display for SpecialType {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result451     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
452         match *self {
453             SpecialType::Flag(shared_types::Flag::IFlags) => write!(f, "iflags"),
454             SpecialType::Flag(shared_types::Flag::FFlags) => write!(f, "fflags"),
455             SpecialType::StructArgument => write!(f, "sarg_t"),
456         }
457     }
458 }
459 
460 impl fmt::Debug for SpecialType {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result461     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
462         write!(
463             f,
464             "{}",
465             match *self {
466                 SpecialType::Flag(_) => format!("FlagsType({})", self),
467                 SpecialType::StructArgument => format!("StructArgument"),
468             }
469         )
470     }
471 }
472 
473 impl From<shared_types::Flag> for SpecialType {
from(f: shared_types::Flag) -> Self474     fn from(f: shared_types::Flag) -> Self {
475         SpecialType::Flag(f)
476     }
477 }
478 
479 pub(crate) struct SpecialTypeIterator {
480     flag_iter: shared_types::FlagIterator,
481     done: bool,
482 }
483 
484 impl SpecialTypeIterator {
new() -> Self485     fn new() -> Self {
486         Self {
487             flag_iter: shared_types::FlagIterator::new(),
488             done: false,
489         }
490     }
491 }
492 
493 impl Iterator for SpecialTypeIterator {
494     type Item = SpecialType;
next(&mut self) -> Option<Self::Item>495     fn next(&mut self) -> Option<Self::Item> {
496         if let Some(f) = self.flag_iter.next() {
497             Some(SpecialType::from(f))
498         } else {
499             if !self.done {
500                 self.done = true;
501                 Some(SpecialType::StructArgument)
502             } else {
503                 None
504             }
505         }
506     }
507 }
508 
509 /// Reference type is scalar type, but not lane type.
510 #[derive(Clone, Copy, PartialEq, Eq, Hash)]
511 pub(crate) struct ReferenceType(pub shared_types::Reference);
512 
513 impl ReferenceType {
514     /// Return a string containing the documentation comment for this reference type.
doc(self) -> String515     pub fn doc(self) -> String {
516         format!("An opaque reference type with {} bits.", self.lane_bits())
517     }
518 
519     /// Return the number of bits in a lane.
lane_bits(self) -> u64520     pub fn lane_bits(self) -> u64 {
521         match self.0 {
522             shared_types::Reference::R32 => 32,
523             shared_types::Reference::R64 => 64,
524         }
525     }
526 
527     /// Find the unique number associated with this reference type.
number(self) -> u8528     pub fn number(self) -> u8 {
529         constants::REFERENCE_BASE
530             + match self {
531                 ReferenceType(shared_types::Reference::R32) => 0,
532                 ReferenceType(shared_types::Reference::R64) => 1,
533             }
534     }
535 
ref_from_bits(num_bits: u16) -> ReferenceType536     pub fn ref_from_bits(num_bits: u16) -> ReferenceType {
537         ReferenceType(match num_bits {
538             32 => shared_types::Reference::R32,
539             64 => shared_types::Reference::R64,
540             _ => unreachable!("unexpected number of bits for a reference type"),
541         })
542     }
543 }
544 
545 impl fmt::Display for ReferenceType {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result546     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
547         write!(f, "r{}", self.lane_bits())
548     }
549 }
550 
551 impl fmt::Debug for ReferenceType {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result552     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
553         write!(f, "ReferenceType(bits={})", self.lane_bits())
554     }
555 }
556 
557 /// Create a ReferenceType from a given reference variant.
558 impl From<shared_types::Reference> for ReferenceType {
from(r: shared_types::Reference) -> Self559     fn from(r: shared_types::Reference) -> Self {
560         ReferenceType(r)
561     }
562 }
563 
564 /// An iterator for different reference types.
565 pub(crate) struct ReferenceTypeIterator {
566     reference_iter: shared_types::ReferenceIterator,
567 }
568 
569 impl ReferenceTypeIterator {
570     /// Create a new reference type iterator.
new() -> Self571     fn new() -> Self {
572         Self {
573             reference_iter: shared_types::ReferenceIterator::new(),
574         }
575     }
576 }
577 
578 impl Iterator for ReferenceTypeIterator {
579     type Item = ReferenceType;
next(&mut self) -> Option<Self::Item>580     fn next(&mut self) -> Option<Self::Item> {
581         if let Some(r) = self.reference_iter.next() {
582             Some(ReferenceType::from(r))
583         } else {
584             None
585         }
586     }
587 }
588