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