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