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