1 #![cfg_attr(feature = "nightly", feature(step_trait, rustc_attrs, min_specialization))] 2 3 use std::fmt; 4 #[cfg(feature = "nightly")] 5 use std::iter::Step; 6 use std::num::{NonZeroUsize, ParseIntError}; 7 use std::ops::{Add, AddAssign, Mul, RangeInclusive, Sub}; 8 use std::str::FromStr; 9 10 use bitflags::bitflags; 11 use rustc_data_structures::intern::Interned; 12 use rustc_data_structures::stable_hasher::Hash64; 13 #[cfg(feature = "nightly")] 14 use rustc_data_structures::stable_hasher::StableOrd; 15 use rustc_index::{IndexSlice, IndexVec}; 16 #[cfg(feature = "nightly")] 17 use rustc_macros::HashStable_Generic; 18 #[cfg(feature = "nightly")] 19 use rustc_macros::{Decodable, Encodable}; 20 21 mod layout; 22 23 pub use layout::LayoutCalculator; 24 25 /// Requirements for a `StableHashingContext` to be used in this crate. 26 /// This is a hack to allow using the `HashStable_Generic` derive macro 27 /// instead of implementing everything in `rustc_middle`. 28 pub trait HashStableContext {} 29 30 use Integer::*; 31 use Primitive::*; 32 33 bitflags! { 34 #[derive(Default)] 35 #[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_Generic))] 36 pub struct ReprFlags: u8 { 37 const IS_C = 1 << 0; 38 const IS_SIMD = 1 << 1; 39 const IS_TRANSPARENT = 1 << 2; 40 // Internal only for now. If true, don't reorder fields. 41 const IS_LINEAR = 1 << 3; 42 // If true, the type's layout can be randomized using 43 // the seed stored in `ReprOptions.layout_seed` 44 const RANDOMIZE_LAYOUT = 1 << 4; 45 // Any of these flags being set prevent field reordering optimisation. 46 const IS_UNOPTIMISABLE = ReprFlags::IS_C.bits 47 | ReprFlags::IS_SIMD.bits 48 | ReprFlags::IS_LINEAR.bits; 49 } 50 } 51 52 #[derive(Copy, Clone, Debug, Eq, PartialEq)] 53 #[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_Generic))] 54 pub enum IntegerType { 55 /// Pointer sized integer type, i.e. isize and usize. The field shows signedness, that 56 /// is, `Pointer(true)` is isize. 57 Pointer(bool), 58 /// Fix sized integer type, e.g. i8, u32, i128 The bool field shows signedness, `Fixed(I8, false)` means `u8` 59 Fixed(Integer, bool), 60 } 61 62 impl IntegerType { is_signed(&self) -> bool63 pub fn is_signed(&self) -> bool { 64 match self { 65 IntegerType::Pointer(b) => *b, 66 IntegerType::Fixed(_, b) => *b, 67 } 68 } 69 } 70 71 /// Represents the repr options provided by the user, 72 #[derive(Copy, Clone, Debug, Eq, PartialEq, Default)] 73 #[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_Generic))] 74 pub struct ReprOptions { 75 pub int: Option<IntegerType>, 76 pub align: Option<Align>, 77 pub pack: Option<Align>, 78 pub flags: ReprFlags, 79 /// The seed to be used for randomizing a type's layout 80 /// 81 /// Note: This could technically be a `Hash128` which would 82 /// be the "most accurate" hash as it'd encompass the item and crate 83 /// hash without loss, but it does pay the price of being larger. 84 /// Everything's a tradeoff, a 64-bit seed should be sufficient for our 85 /// purposes (primarily `-Z randomize-layout`) 86 pub field_shuffle_seed: Hash64, 87 } 88 89 impl ReprOptions { 90 #[inline] simd(&self) -> bool91 pub fn simd(&self) -> bool { 92 self.flags.contains(ReprFlags::IS_SIMD) 93 } 94 95 #[inline] c(&self) -> bool96 pub fn c(&self) -> bool { 97 self.flags.contains(ReprFlags::IS_C) 98 } 99 100 #[inline] packed(&self) -> bool101 pub fn packed(&self) -> bool { 102 self.pack.is_some() 103 } 104 105 #[inline] transparent(&self) -> bool106 pub fn transparent(&self) -> bool { 107 self.flags.contains(ReprFlags::IS_TRANSPARENT) 108 } 109 110 #[inline] linear(&self) -> bool111 pub fn linear(&self) -> bool { 112 self.flags.contains(ReprFlags::IS_LINEAR) 113 } 114 115 /// Returns the discriminant type, given these `repr` options. 116 /// This must only be called on enums! discr_type(&self) -> IntegerType117 pub fn discr_type(&self) -> IntegerType { 118 self.int.unwrap_or(IntegerType::Pointer(true)) 119 } 120 121 /// Returns `true` if this `#[repr()]` should inhabit "smart enum 122 /// layout" optimizations, such as representing `Foo<&T>` as a 123 /// single pointer. inhibit_enum_layout_opt(&self) -> bool124 pub fn inhibit_enum_layout_opt(&self) -> bool { 125 self.c() || self.int.is_some() 126 } 127 128 /// Returns `true` if this `#[repr()]` should inhibit struct field reordering 129 /// optimizations, such as with `repr(C)`, `repr(packed(1))`, or `repr(<int>)`. inhibit_struct_field_reordering_opt(&self) -> bool130 pub fn inhibit_struct_field_reordering_opt(&self) -> bool { 131 if let Some(pack) = self.pack { 132 if pack.bytes() == 1 { 133 return true; 134 } 135 } 136 137 self.flags.intersects(ReprFlags::IS_UNOPTIMISABLE) || self.int.is_some() 138 } 139 140 /// Returns `true` if this type is valid for reordering and `-Z randomize-layout` 141 /// was enabled for its declaration crate can_randomize_type_layout(&self) -> bool142 pub fn can_randomize_type_layout(&self) -> bool { 143 !self.inhibit_struct_field_reordering_opt() 144 && self.flags.contains(ReprFlags::RANDOMIZE_LAYOUT) 145 } 146 147 /// Returns `true` if this `#[repr()]` should inhibit union ABI optimisations. inhibit_union_abi_opt(&self) -> bool148 pub fn inhibit_union_abi_opt(&self) -> bool { 149 self.c() 150 } 151 } 152 153 /// Parsed [Data layout](https://llvm.org/docs/LangRef.html#data-layout) 154 /// for a target, which contains everything needed to compute layouts. 155 #[derive(Debug, PartialEq, Eq)] 156 pub struct TargetDataLayout { 157 pub endian: Endian, 158 pub i1_align: AbiAndPrefAlign, 159 pub i8_align: AbiAndPrefAlign, 160 pub i16_align: AbiAndPrefAlign, 161 pub i32_align: AbiAndPrefAlign, 162 pub i64_align: AbiAndPrefAlign, 163 pub i128_align: AbiAndPrefAlign, 164 pub f32_align: AbiAndPrefAlign, 165 pub f64_align: AbiAndPrefAlign, 166 pub pointer_size: Size, 167 pub pointer_align: AbiAndPrefAlign, 168 pub aggregate_align: AbiAndPrefAlign, 169 170 /// Alignments for vector types. 171 pub vector_align: Vec<(Size, AbiAndPrefAlign)>, 172 173 pub instruction_address_space: AddressSpace, 174 175 /// Minimum size of #[repr(C)] enums (default c_int::BITS, usually 32) 176 /// Note: This isn't in LLVM's data layout string, it is `short_enum` 177 /// so the only valid spec for LLVM is c_int::BITS or 8 178 pub c_enum_min_size: Integer, 179 } 180 181 impl Default for TargetDataLayout { 182 /// Creates an instance of `TargetDataLayout`. default() -> TargetDataLayout183 fn default() -> TargetDataLayout { 184 let align = |bits| Align::from_bits(bits).unwrap(); 185 TargetDataLayout { 186 endian: Endian::Big, 187 i1_align: AbiAndPrefAlign::new(align(8)), 188 i8_align: AbiAndPrefAlign::new(align(8)), 189 i16_align: AbiAndPrefAlign::new(align(16)), 190 i32_align: AbiAndPrefAlign::new(align(32)), 191 i64_align: AbiAndPrefAlign { abi: align(32), pref: align(64) }, 192 i128_align: AbiAndPrefAlign { abi: align(32), pref: align(64) }, 193 f32_align: AbiAndPrefAlign::new(align(32)), 194 f64_align: AbiAndPrefAlign::new(align(64)), 195 pointer_size: Size::from_bits(64), 196 pointer_align: AbiAndPrefAlign::new(align(64)), 197 aggregate_align: AbiAndPrefAlign { abi: align(0), pref: align(64) }, 198 vector_align: vec![ 199 (Size::from_bits(64), AbiAndPrefAlign::new(align(64))), 200 (Size::from_bits(128), AbiAndPrefAlign::new(align(128))), 201 ], 202 instruction_address_space: AddressSpace::DATA, 203 c_enum_min_size: Integer::I32, 204 } 205 } 206 } 207 208 pub enum TargetDataLayoutErrors<'a> { 209 InvalidAddressSpace { addr_space: &'a str, cause: &'a str, err: ParseIntError }, 210 InvalidBits { kind: &'a str, bit: &'a str, cause: &'a str, err: ParseIntError }, 211 MissingAlignment { cause: &'a str }, 212 InvalidAlignment { cause: &'a str, err: AlignFromBytesError }, 213 InconsistentTargetArchitecture { dl: &'a str, target: &'a str }, 214 InconsistentTargetPointerWidth { pointer_size: u64, target: u32 }, 215 InvalidBitsSize { err: String }, 216 } 217 218 impl TargetDataLayout { 219 /// Parse data layout from an [llvm data layout string](https://llvm.org/docs/LangRef.html#data-layout) 220 /// 221 /// This function doesn't fill `c_enum_min_size` and it will always be `I32` since it can not be 222 /// determined from llvm string. parse_from_llvm_datalayout_string<'a>( input: &'a str, ) -> Result<TargetDataLayout, TargetDataLayoutErrors<'a>>223 pub fn parse_from_llvm_datalayout_string<'a>( 224 input: &'a str, 225 ) -> Result<TargetDataLayout, TargetDataLayoutErrors<'a>> { 226 // Parse an address space index from a string. 227 let parse_address_space = |s: &'a str, cause: &'a str| { 228 s.parse::<u32>().map(AddressSpace).map_err(|err| { 229 TargetDataLayoutErrors::InvalidAddressSpace { addr_space: s, cause, err } 230 }) 231 }; 232 233 // Parse a bit count from a string. 234 let parse_bits = |s: &'a str, kind: &'a str, cause: &'a str| { 235 s.parse::<u64>().map_err(|err| TargetDataLayoutErrors::InvalidBits { 236 kind, 237 bit: s, 238 cause, 239 err, 240 }) 241 }; 242 243 // Parse a size string. 244 let size = |s: &'a str, cause: &'a str| parse_bits(s, "size", cause).map(Size::from_bits); 245 246 // Parse an alignment string. 247 let align = |s: &[&'a str], cause: &'a str| { 248 if s.is_empty() { 249 return Err(TargetDataLayoutErrors::MissingAlignment { cause }); 250 } 251 let align_from_bits = |bits| { 252 Align::from_bits(bits) 253 .map_err(|err| TargetDataLayoutErrors::InvalidAlignment { cause, err }) 254 }; 255 let abi = parse_bits(s[0], "alignment", cause)?; 256 let pref = s.get(1).map_or(Ok(abi), |pref| parse_bits(pref, "alignment", cause))?; 257 Ok(AbiAndPrefAlign { abi: align_from_bits(abi)?, pref: align_from_bits(pref)? }) 258 }; 259 260 let mut dl = TargetDataLayout::default(); 261 let mut i128_align_src = 64; 262 for spec in input.split('-') { 263 let spec_parts = spec.split(':').collect::<Vec<_>>(); 264 265 match &*spec_parts { 266 ["e"] => dl.endian = Endian::Little, 267 ["E"] => dl.endian = Endian::Big, 268 [p] if p.starts_with('P') => { 269 dl.instruction_address_space = parse_address_space(&p[1..], "P")? 270 } 271 ["a", ref a @ ..] => dl.aggregate_align = align(a, "a")?, 272 ["f32", ref a @ ..] => dl.f32_align = align(a, "f32")?, 273 ["f64", ref a @ ..] => dl.f64_align = align(a, "f64")?, 274 // FIXME(erikdesjardins): we should be parsing nonzero address spaces 275 // this will require replacing TargetDataLayout::{pointer_size,pointer_align} 276 // with e.g. `fn pointer_size_in(AddressSpace)` 277 [p @ "p", s, ref a @ ..] | [p @ "p0", s, ref a @ ..] => { 278 dl.pointer_size = size(s, p)?; 279 dl.pointer_align = align(a, p)?; 280 } 281 [s, ref a @ ..] if s.starts_with('i') => { 282 let Ok(bits) = s[1..].parse::<u64>() else { 283 size(&s[1..], "i")?; // For the user error. 284 continue; 285 }; 286 let a = align(a, s)?; 287 match bits { 288 1 => dl.i1_align = a, 289 8 => dl.i8_align = a, 290 16 => dl.i16_align = a, 291 32 => dl.i32_align = a, 292 64 => dl.i64_align = a, 293 _ => {} 294 } 295 if bits >= i128_align_src && bits <= 128 { 296 // Default alignment for i128 is decided by taking the alignment of 297 // largest-sized i{64..=128}. 298 i128_align_src = bits; 299 dl.i128_align = a; 300 } 301 } 302 [s, ref a @ ..] if s.starts_with('v') => { 303 let v_size = size(&s[1..], "v")?; 304 let a = align(a, s)?; 305 if let Some(v) = dl.vector_align.iter_mut().find(|v| v.0 == v_size) { 306 v.1 = a; 307 continue; 308 } 309 // No existing entry, add a new one. 310 dl.vector_align.push((v_size, a)); 311 } 312 _ => {} // Ignore everything else. 313 } 314 } 315 Ok(dl) 316 } 317 318 /// Returns exclusive upper bound on object size. 319 /// 320 /// The theoretical maximum object size is defined as the maximum positive `isize` value. 321 /// This ensures that the `offset` semantics remain well-defined by allowing it to correctly 322 /// index every address within an object along with one byte past the end, along with allowing 323 /// `isize` to store the difference between any two pointers into an object. 324 /// 325 /// The upper bound on 64-bit currently needs to be lower because LLVM uses a 64-bit integer 326 /// to represent object size in bits. It would need to be 1 << 61 to account for this, but is 327 /// currently conservatively bounded to 1 << 47 as that is enough to cover the current usable 328 /// address space on 64-bit ARMv8 and x86_64. 329 #[inline] obj_size_bound(&self) -> u64330 pub fn obj_size_bound(&self) -> u64 { 331 match self.pointer_size.bits() { 332 16 => 1 << 15, 333 32 => 1 << 31, 334 64 => 1 << 47, 335 bits => panic!("obj_size_bound: unknown pointer bit size {}", bits), 336 } 337 } 338 339 #[inline] ptr_sized_integer(&self) -> Integer340 pub fn ptr_sized_integer(&self) -> Integer { 341 match self.pointer_size.bits() { 342 16 => I16, 343 32 => I32, 344 64 => I64, 345 bits => panic!("ptr_sized_integer: unknown pointer bit size {}", bits), 346 } 347 } 348 349 #[inline] vector_align(&self, vec_size: Size) -> AbiAndPrefAlign350 pub fn vector_align(&self, vec_size: Size) -> AbiAndPrefAlign { 351 for &(size, align) in &self.vector_align { 352 if size == vec_size { 353 return align; 354 } 355 } 356 // Default to natural alignment, which is what LLVM does. 357 // That is, use the size, rounded up to a power of 2. 358 AbiAndPrefAlign::new(Align::from_bytes(vec_size.bytes().next_power_of_two()).unwrap()) 359 } 360 } 361 362 pub trait HasDataLayout { data_layout(&self) -> &TargetDataLayout363 fn data_layout(&self) -> &TargetDataLayout; 364 } 365 366 impl HasDataLayout for TargetDataLayout { 367 #[inline] data_layout(&self) -> &TargetDataLayout368 fn data_layout(&self) -> &TargetDataLayout { 369 self 370 } 371 } 372 373 /// Endianness of the target, which must match cfg(target-endian). 374 #[derive(Copy, Clone, PartialEq, Eq)] 375 pub enum Endian { 376 Little, 377 Big, 378 } 379 380 impl Endian { as_str(&self) -> &'static str381 pub fn as_str(&self) -> &'static str { 382 match self { 383 Self::Little => "little", 384 Self::Big => "big", 385 } 386 } 387 } 388 389 impl fmt::Debug for Endian { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result390 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 391 f.write_str(self.as_str()) 392 } 393 } 394 395 impl FromStr for Endian { 396 type Err = String; 397 from_str(s: &str) -> Result<Self, Self::Err>398 fn from_str(s: &str) -> Result<Self, Self::Err> { 399 match s { 400 "little" => Ok(Self::Little), 401 "big" => Ok(Self::Big), 402 _ => Err(format!(r#"unknown endian: "{}""#, s)), 403 } 404 } 405 } 406 407 /// Size of a type in bytes. 408 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] 409 #[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_Generic))] 410 pub struct Size { 411 raw: u64, 412 } 413 414 // Safety: Ord is implement as just comparing numerical values and numerical values 415 // are not changed by (de-)serialization. 416 #[cfg(feature = "nightly")] 417 unsafe impl StableOrd for Size { 418 const CAN_USE_UNSTABLE_SORT: bool = true; 419 } 420 421 // This is debug-printed a lot in larger structs, don't waste too much space there 422 impl fmt::Debug for Size { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result423 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 424 write!(f, "Size({} bytes)", self.bytes()) 425 } 426 } 427 428 impl Size { 429 pub const ZERO: Size = Size { raw: 0 }; 430 431 /// Rounds `bits` up to the next-higher byte boundary, if `bits` is 432 /// not a multiple of 8. from_bits(bits: impl TryInto<u64>) -> Size433 pub fn from_bits(bits: impl TryInto<u64>) -> Size { 434 let bits = bits.try_into().ok().unwrap(); 435 // Avoid potential overflow from `bits + 7`. 436 Size { raw: bits / 8 + ((bits % 8) + 7) / 8 } 437 } 438 439 #[inline] from_bytes(bytes: impl TryInto<u64>) -> Size440 pub fn from_bytes(bytes: impl TryInto<u64>) -> Size { 441 let bytes: u64 = bytes.try_into().ok().unwrap(); 442 Size { raw: bytes } 443 } 444 445 #[inline] bytes(self) -> u64446 pub fn bytes(self) -> u64 { 447 self.raw 448 } 449 450 #[inline] bytes_usize(self) -> usize451 pub fn bytes_usize(self) -> usize { 452 self.bytes().try_into().unwrap() 453 } 454 455 #[inline] bits(self) -> u64456 pub fn bits(self) -> u64 { 457 #[cold] 458 fn overflow(bytes: u64) -> ! { 459 panic!("Size::bits: {} bytes in bits doesn't fit in u64", bytes) 460 } 461 462 self.bytes().checked_mul(8).unwrap_or_else(|| overflow(self.bytes())) 463 } 464 465 #[inline] bits_usize(self) -> usize466 pub fn bits_usize(self) -> usize { 467 self.bits().try_into().unwrap() 468 } 469 470 #[inline] align_to(self, align: Align) -> Size471 pub fn align_to(self, align: Align) -> Size { 472 let mask = align.bytes() - 1; 473 Size::from_bytes((self.bytes() + mask) & !mask) 474 } 475 476 #[inline] is_aligned(self, align: Align) -> bool477 pub fn is_aligned(self, align: Align) -> bool { 478 let mask = align.bytes() - 1; 479 self.bytes() & mask == 0 480 } 481 482 #[inline] checked_add<C: HasDataLayout>(self, offset: Size, cx: &C) -> Option<Size>483 pub fn checked_add<C: HasDataLayout>(self, offset: Size, cx: &C) -> Option<Size> { 484 let dl = cx.data_layout(); 485 486 let bytes = self.bytes().checked_add(offset.bytes())?; 487 488 if bytes < dl.obj_size_bound() { Some(Size::from_bytes(bytes)) } else { None } 489 } 490 491 #[inline] checked_mul<C: HasDataLayout>(self, count: u64, cx: &C) -> Option<Size>492 pub fn checked_mul<C: HasDataLayout>(self, count: u64, cx: &C) -> Option<Size> { 493 let dl = cx.data_layout(); 494 495 let bytes = self.bytes().checked_mul(count)?; 496 if bytes < dl.obj_size_bound() { Some(Size::from_bytes(bytes)) } else { None } 497 } 498 499 /// Truncates `value` to `self` bits and then sign-extends it to 128 bits 500 /// (i.e., if it is negative, fill with 1's on the left). 501 #[inline] sign_extend(self, value: u128) -> u128502 pub fn sign_extend(self, value: u128) -> u128 { 503 let size = self.bits(); 504 if size == 0 { 505 // Truncated until nothing is left. 506 return 0; 507 } 508 // Sign-extend it. 509 let shift = 128 - size; 510 // Shift the unsigned value to the left, then shift back to the right as signed 511 // (essentially fills with sign bit on the left). 512 (((value << shift) as i128) >> shift) as u128 513 } 514 515 /// Truncates `value` to `self` bits. 516 #[inline] truncate(self, value: u128) -> u128517 pub fn truncate(self, value: u128) -> u128 { 518 let size = self.bits(); 519 if size == 0 { 520 // Truncated until nothing is left. 521 return 0; 522 } 523 let shift = 128 - size; 524 // Truncate (shift left to drop out leftover values, shift right to fill with zeroes). 525 (value << shift) >> shift 526 } 527 528 #[inline] signed_int_min(&self) -> i128529 pub fn signed_int_min(&self) -> i128 { 530 self.sign_extend(1_u128 << (self.bits() - 1)) as i128 531 } 532 533 #[inline] signed_int_max(&self) -> i128534 pub fn signed_int_max(&self) -> i128 { 535 i128::MAX >> (128 - self.bits()) 536 } 537 538 #[inline] unsigned_int_max(&self) -> u128539 pub fn unsigned_int_max(&self) -> u128 { 540 u128::MAX >> (128 - self.bits()) 541 } 542 } 543 544 // Panicking addition, subtraction and multiplication for convenience. 545 // Avoid during layout computation, return `LayoutError` instead. 546 547 impl Add for Size { 548 type Output = Size; 549 #[inline] add(self, other: Size) -> Size550 fn add(self, other: Size) -> Size { 551 Size::from_bytes(self.bytes().checked_add(other.bytes()).unwrap_or_else(|| { 552 panic!("Size::add: {} + {} doesn't fit in u64", self.bytes(), other.bytes()) 553 })) 554 } 555 } 556 557 impl Sub for Size { 558 type Output = Size; 559 #[inline] sub(self, other: Size) -> Size560 fn sub(self, other: Size) -> Size { 561 Size::from_bytes(self.bytes().checked_sub(other.bytes()).unwrap_or_else(|| { 562 panic!("Size::sub: {} - {} would result in negative size", self.bytes(), other.bytes()) 563 })) 564 } 565 } 566 567 impl Mul<Size> for u64 { 568 type Output = Size; 569 #[inline] mul(self, size: Size) -> Size570 fn mul(self, size: Size) -> Size { 571 size * self 572 } 573 } 574 575 impl Mul<u64> for Size { 576 type Output = Size; 577 #[inline] mul(self, count: u64) -> Size578 fn mul(self, count: u64) -> Size { 579 match self.bytes().checked_mul(count) { 580 Some(bytes) => Size::from_bytes(bytes), 581 None => panic!("Size::mul: {} * {} doesn't fit in u64", self.bytes(), count), 582 } 583 } 584 } 585 586 impl AddAssign for Size { 587 #[inline] add_assign(&mut self, other: Size)588 fn add_assign(&mut self, other: Size) { 589 *self = *self + other; 590 } 591 } 592 593 #[cfg(feature = "nightly")] 594 impl Step for Size { 595 #[inline] steps_between(start: &Self, end: &Self) -> Option<usize>596 fn steps_between(start: &Self, end: &Self) -> Option<usize> { 597 u64::steps_between(&start.bytes(), &end.bytes()) 598 } 599 600 #[inline] forward_checked(start: Self, count: usize) -> Option<Self>601 fn forward_checked(start: Self, count: usize) -> Option<Self> { 602 u64::forward_checked(start.bytes(), count).map(Self::from_bytes) 603 } 604 605 #[inline] forward(start: Self, count: usize) -> Self606 fn forward(start: Self, count: usize) -> Self { 607 Self::from_bytes(u64::forward(start.bytes(), count)) 608 } 609 610 #[inline] forward_unchecked(start: Self, count: usize) -> Self611 unsafe fn forward_unchecked(start: Self, count: usize) -> Self { 612 Self::from_bytes(u64::forward_unchecked(start.bytes(), count)) 613 } 614 615 #[inline] backward_checked(start: Self, count: usize) -> Option<Self>616 fn backward_checked(start: Self, count: usize) -> Option<Self> { 617 u64::backward_checked(start.bytes(), count).map(Self::from_bytes) 618 } 619 620 #[inline] backward(start: Self, count: usize) -> Self621 fn backward(start: Self, count: usize) -> Self { 622 Self::from_bytes(u64::backward(start.bytes(), count)) 623 } 624 625 #[inline] backward_unchecked(start: Self, count: usize) -> Self626 unsafe fn backward_unchecked(start: Self, count: usize) -> Self { 627 Self::from_bytes(u64::backward_unchecked(start.bytes(), count)) 628 } 629 } 630 631 /// Alignment of a type in bytes (always a power of two). 632 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] 633 #[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_Generic))] 634 pub struct Align { 635 pow2: u8, 636 } 637 638 // This is debug-printed a lot in larger structs, don't waste too much space there 639 impl fmt::Debug for Align { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result640 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 641 write!(f, "Align({} bytes)", self.bytes()) 642 } 643 } 644 645 #[derive(Clone, Copy)] 646 pub enum AlignFromBytesError { 647 NotPowerOfTwo(u64), 648 TooLarge(u64), 649 } 650 651 impl AlignFromBytesError { diag_ident(self) -> &'static str652 pub fn diag_ident(self) -> &'static str { 653 match self { 654 Self::NotPowerOfTwo(_) => "not_power_of_two", 655 Self::TooLarge(_) => "too_large", 656 } 657 } 658 align(self) -> u64659 pub fn align(self) -> u64 { 660 let (Self::NotPowerOfTwo(align) | Self::TooLarge(align)) = self; 661 align 662 } 663 } 664 665 impl fmt::Debug for AlignFromBytesError { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result666 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 667 fmt::Display::fmt(self, f) 668 } 669 } 670 671 impl fmt::Display for AlignFromBytesError { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result672 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 673 match self { 674 AlignFromBytesError::NotPowerOfTwo(align) => write!(f, "`{align}` is not a power of 2"), 675 AlignFromBytesError::TooLarge(align) => write!(f, "`{align}` is too large"), 676 } 677 } 678 } 679 680 impl Align { 681 pub const ONE: Align = Align { pow2: 0 }; 682 pub const MAX: Align = Align { pow2: 29 }; 683 684 #[inline] from_bits(bits: u64) -> Result<Align, AlignFromBytesError>685 pub fn from_bits(bits: u64) -> Result<Align, AlignFromBytesError> { 686 Align::from_bytes(Size::from_bits(bits).bytes()) 687 } 688 689 #[inline] from_bytes(align: u64) -> Result<Align, AlignFromBytesError>690 pub fn from_bytes(align: u64) -> Result<Align, AlignFromBytesError> { 691 // Treat an alignment of 0 bytes like 1-byte alignment. 692 if align == 0 { 693 return Ok(Align::ONE); 694 } 695 696 #[cold] 697 fn not_power_of_2(align: u64) -> AlignFromBytesError { 698 AlignFromBytesError::NotPowerOfTwo(align) 699 } 700 701 #[cold] 702 fn too_large(align: u64) -> AlignFromBytesError { 703 AlignFromBytesError::TooLarge(align) 704 } 705 706 let tz = align.trailing_zeros(); 707 if align != (1 << tz) { 708 return Err(not_power_of_2(align)); 709 } 710 711 let pow2 = tz as u8; 712 if pow2 > Self::MAX.pow2 { 713 return Err(too_large(align)); 714 } 715 716 Ok(Align { pow2 }) 717 } 718 719 #[inline] bytes(self) -> u64720 pub fn bytes(self) -> u64 { 721 1 << self.pow2 722 } 723 724 #[inline] bits(self) -> u64725 pub fn bits(self) -> u64 { 726 self.bytes() * 8 727 } 728 729 /// Computes the best alignment possible for the given offset 730 /// (the largest power of two that the offset is a multiple of). 731 /// 732 /// N.B., for an offset of `0`, this happens to return `2^64`. 733 #[inline] max_for_offset(offset: Size) -> Align734 pub fn max_for_offset(offset: Size) -> Align { 735 Align { pow2: offset.bytes().trailing_zeros() as u8 } 736 } 737 738 /// Lower the alignment, if necessary, such that the given offset 739 /// is aligned to it (the offset is a multiple of the alignment). 740 #[inline] restrict_for_offset(self, offset: Size) -> Align741 pub fn restrict_for_offset(self, offset: Size) -> Align { 742 self.min(Align::max_for_offset(offset)) 743 } 744 } 745 746 /// A pair of alignments, ABI-mandated and preferred. 747 #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] 748 #[cfg_attr(feature = "nightly", derive(HashStable_Generic))] 749 750 pub struct AbiAndPrefAlign { 751 pub abi: Align, 752 pub pref: Align, 753 } 754 755 impl AbiAndPrefAlign { 756 #[inline] new(align: Align) -> AbiAndPrefAlign757 pub fn new(align: Align) -> AbiAndPrefAlign { 758 AbiAndPrefAlign { abi: align, pref: align } 759 } 760 761 #[inline] min(self, other: AbiAndPrefAlign) -> AbiAndPrefAlign762 pub fn min(self, other: AbiAndPrefAlign) -> AbiAndPrefAlign { 763 AbiAndPrefAlign { abi: self.abi.min(other.abi), pref: self.pref.min(other.pref) } 764 } 765 766 #[inline] max(self, other: AbiAndPrefAlign) -> AbiAndPrefAlign767 pub fn max(self, other: AbiAndPrefAlign) -> AbiAndPrefAlign { 768 AbiAndPrefAlign { abi: self.abi.max(other.abi), pref: self.pref.max(other.pref) } 769 } 770 } 771 772 /// Integers, also used for enum discriminants. 773 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] 774 #[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_Generic))] 775 776 pub enum Integer { 777 I8, 778 I16, 779 I32, 780 I64, 781 I128, 782 } 783 784 impl Integer { 785 #[inline] size(self) -> Size786 pub fn size(self) -> Size { 787 match self { 788 I8 => Size::from_bytes(1), 789 I16 => Size::from_bytes(2), 790 I32 => Size::from_bytes(4), 791 I64 => Size::from_bytes(8), 792 I128 => Size::from_bytes(16), 793 } 794 } 795 796 /// Gets the Integer type from an IntegerType. from_attr<C: HasDataLayout>(cx: &C, ity: IntegerType) -> Integer797 pub fn from_attr<C: HasDataLayout>(cx: &C, ity: IntegerType) -> Integer { 798 let dl = cx.data_layout(); 799 800 match ity { 801 IntegerType::Pointer(_) => dl.ptr_sized_integer(), 802 IntegerType::Fixed(x, _) => x, 803 } 804 } 805 align<C: HasDataLayout>(self, cx: &C) -> AbiAndPrefAlign806 pub fn align<C: HasDataLayout>(self, cx: &C) -> AbiAndPrefAlign { 807 let dl = cx.data_layout(); 808 809 match self { 810 I8 => dl.i8_align, 811 I16 => dl.i16_align, 812 I32 => dl.i32_align, 813 I64 => dl.i64_align, 814 I128 => dl.i128_align, 815 } 816 } 817 818 /// Returns the largest signed value that can be represented by this Integer. 819 #[inline] signed_max(self) -> i128820 pub fn signed_max(self) -> i128 { 821 match self { 822 I8 => i8::MAX as i128, 823 I16 => i16::MAX as i128, 824 I32 => i32::MAX as i128, 825 I64 => i64::MAX as i128, 826 I128 => i128::MAX, 827 } 828 } 829 830 /// Finds the smallest Integer type which can represent the signed value. 831 #[inline] fit_signed(x: i128) -> Integer832 pub fn fit_signed(x: i128) -> Integer { 833 match x { 834 -0x0000_0000_0000_0080..=0x0000_0000_0000_007f => I8, 835 -0x0000_0000_0000_8000..=0x0000_0000_0000_7fff => I16, 836 -0x0000_0000_8000_0000..=0x0000_0000_7fff_ffff => I32, 837 -0x8000_0000_0000_0000..=0x7fff_ffff_ffff_ffff => I64, 838 _ => I128, 839 } 840 } 841 842 /// Finds the smallest Integer type which can represent the unsigned value. 843 #[inline] fit_unsigned(x: u128) -> Integer844 pub fn fit_unsigned(x: u128) -> Integer { 845 match x { 846 0..=0x0000_0000_0000_00ff => I8, 847 0..=0x0000_0000_0000_ffff => I16, 848 0..=0x0000_0000_ffff_ffff => I32, 849 0..=0xffff_ffff_ffff_ffff => I64, 850 _ => I128, 851 } 852 } 853 854 /// Finds the smallest integer with the given alignment. for_align<C: HasDataLayout>(cx: &C, wanted: Align) -> Option<Integer>855 pub fn for_align<C: HasDataLayout>(cx: &C, wanted: Align) -> Option<Integer> { 856 let dl = cx.data_layout(); 857 858 [I8, I16, I32, I64, I128].into_iter().find(|&candidate| { 859 wanted == candidate.align(dl).abi && wanted.bytes() == candidate.size().bytes() 860 }) 861 } 862 863 /// Find the largest integer with the given alignment or less. approximate_align<C: HasDataLayout>(cx: &C, wanted: Align) -> Integer864 pub fn approximate_align<C: HasDataLayout>(cx: &C, wanted: Align) -> Integer { 865 let dl = cx.data_layout(); 866 867 // FIXME(eddyb) maybe include I128 in the future, when it works everywhere. 868 for candidate in [I64, I32, I16] { 869 if wanted >= candidate.align(dl).abi && wanted.bytes() >= candidate.size().bytes() { 870 return candidate; 871 } 872 } 873 I8 874 } 875 876 // FIXME(eddyb) consolidate this and other methods that find the appropriate 877 // `Integer` given some requirements. 878 #[inline] from_size(size: Size) -> Result<Self, String>879 pub fn from_size(size: Size) -> Result<Self, String> { 880 match size.bits() { 881 8 => Ok(Integer::I8), 882 16 => Ok(Integer::I16), 883 32 => Ok(Integer::I32), 884 64 => Ok(Integer::I64), 885 128 => Ok(Integer::I128), 886 _ => Err(format!("rust does not support integers with {} bits", size.bits())), 887 } 888 } 889 } 890 891 /// Fundamental unit of memory access and layout. 892 #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] 893 #[cfg_attr(feature = "nightly", derive(HashStable_Generic))] 894 pub enum Primitive { 895 /// The `bool` is the signedness of the `Integer` type. 896 /// 897 /// One would think we would not care about such details this low down, 898 /// but some ABIs are described in terms of C types and ISAs where the 899 /// integer arithmetic is done on {sign,zero}-extended registers, e.g. 900 /// a negative integer passed by zero-extension will appear positive in 901 /// the callee, and most operations on it will produce the wrong values. 902 Int(Integer, bool), 903 F32, 904 F64, 905 Pointer(AddressSpace), 906 } 907 908 impl Primitive { size<C: HasDataLayout>(self, cx: &C) -> Size909 pub fn size<C: HasDataLayout>(self, cx: &C) -> Size { 910 let dl = cx.data_layout(); 911 912 match self { 913 Int(i, _) => i.size(), 914 F32 => Size::from_bits(32), 915 F64 => Size::from_bits(64), 916 // FIXME(erikdesjardins): ignoring address space is technically wrong, pointers in 917 // different address spaces can have different sizes 918 // (but TargetDataLayout doesn't currently parse that part of the DL string) 919 Pointer(_) => dl.pointer_size, 920 } 921 } 922 align<C: HasDataLayout>(self, cx: &C) -> AbiAndPrefAlign923 pub fn align<C: HasDataLayout>(self, cx: &C) -> AbiAndPrefAlign { 924 let dl = cx.data_layout(); 925 926 match self { 927 Int(i, _) => i.align(dl), 928 F32 => dl.f32_align, 929 F64 => dl.f64_align, 930 // FIXME(erikdesjardins): ignoring address space is technically wrong, pointers in 931 // different address spaces can have different alignments 932 // (but TargetDataLayout doesn't currently parse that part of the DL string) 933 Pointer(_) => dl.pointer_align, 934 } 935 } 936 } 937 938 /// Inclusive wrap-around range of valid values, that is, if 939 /// start > end, it represents `start..=MAX`, 940 /// followed by `0..=end`. 941 /// 942 /// That is, for an i8 primitive, a range of `254..=2` means following 943 /// sequence: 944 /// 945 /// 254 (-2), 255 (-1), 0, 1, 2 946 /// 947 /// This is intended specifically to mirror LLVM’s `!range` metadata semantics. 948 #[derive(Clone, Copy, PartialEq, Eq, Hash)] 949 #[cfg_attr(feature = "nightly", derive(HashStable_Generic))] 950 pub struct WrappingRange { 951 pub start: u128, 952 pub end: u128, 953 } 954 955 impl WrappingRange { full(size: Size) -> Self956 pub fn full(size: Size) -> Self { 957 Self { start: 0, end: size.unsigned_int_max() } 958 } 959 960 /// Returns `true` if `v` is contained in the range. 961 #[inline(always)] contains(&self, v: u128) -> bool962 pub fn contains(&self, v: u128) -> bool { 963 if self.start <= self.end { 964 self.start <= v && v <= self.end 965 } else { 966 self.start <= v || v <= self.end 967 } 968 } 969 970 /// Returns `self` with replaced `start` 971 #[inline(always)] with_start(mut self, start: u128) -> Self972 pub fn with_start(mut self, start: u128) -> Self { 973 self.start = start; 974 self 975 } 976 977 /// Returns `self` with replaced `end` 978 #[inline(always)] with_end(mut self, end: u128) -> Self979 pub fn with_end(mut self, end: u128) -> Self { 980 self.end = end; 981 self 982 } 983 984 /// Returns `true` if `size` completely fills the range. 985 #[inline] is_full_for(&self, size: Size) -> bool986 pub fn is_full_for(&self, size: Size) -> bool { 987 let max_value = size.unsigned_int_max(); 988 debug_assert!(self.start <= max_value && self.end <= max_value); 989 self.start == (self.end.wrapping_add(1) & max_value) 990 } 991 } 992 993 impl fmt::Debug for WrappingRange { fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result994 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { 995 if self.start > self.end { 996 write!(fmt, "(..={}) | ({}..)", self.end, self.start)?; 997 } else { 998 write!(fmt, "{}..={}", self.start, self.end)?; 999 } 1000 Ok(()) 1001 } 1002 } 1003 1004 /// Information about one scalar component of a Rust type. 1005 #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] 1006 #[cfg_attr(feature = "nightly", derive(HashStable_Generic))] 1007 pub enum Scalar { 1008 Initialized { 1009 value: Primitive, 1010 1011 // FIXME(eddyb) always use the shortest range, e.g., by finding 1012 // the largest space between two consecutive valid values and 1013 // taking everything else as the (shortest) valid range. 1014 valid_range: WrappingRange, 1015 }, 1016 Union { 1017 /// Even for unions, we need to use the correct registers for the kind of 1018 /// values inside the union, so we keep the `Primitive` type around. We 1019 /// also use it to compute the size of the scalar. 1020 /// However, unions never have niches and even allow undef, 1021 /// so there is no `valid_range`. 1022 value: Primitive, 1023 }, 1024 } 1025 1026 impl Scalar { 1027 #[inline] is_bool(&self) -> bool1028 pub fn is_bool(&self) -> bool { 1029 matches!( 1030 self, 1031 Scalar::Initialized { 1032 value: Int(I8, false), 1033 valid_range: WrappingRange { start: 0, end: 1 } 1034 } 1035 ) 1036 } 1037 1038 /// Get the primitive representation of this type, ignoring the valid range and whether the 1039 /// value is allowed to be undefined (due to being a union). primitive(&self) -> Primitive1040 pub fn primitive(&self) -> Primitive { 1041 match *self { 1042 Scalar::Initialized { value, .. } | Scalar::Union { value } => value, 1043 } 1044 } 1045 align(self, cx: &impl HasDataLayout) -> AbiAndPrefAlign1046 pub fn align(self, cx: &impl HasDataLayout) -> AbiAndPrefAlign { 1047 self.primitive().align(cx) 1048 } 1049 size(self, cx: &impl HasDataLayout) -> Size1050 pub fn size(self, cx: &impl HasDataLayout) -> Size { 1051 self.primitive().size(cx) 1052 } 1053 1054 #[inline] to_union(&self) -> Self1055 pub fn to_union(&self) -> Self { 1056 Self::Union { value: self.primitive() } 1057 } 1058 1059 #[inline] valid_range(&self, cx: &impl HasDataLayout) -> WrappingRange1060 pub fn valid_range(&self, cx: &impl HasDataLayout) -> WrappingRange { 1061 match *self { 1062 Scalar::Initialized { valid_range, .. } => valid_range, 1063 Scalar::Union { value } => WrappingRange::full(value.size(cx)), 1064 } 1065 } 1066 1067 #[inline] 1068 /// Allows the caller to mutate the valid range. This operation will panic if attempted on a union. valid_range_mut(&mut self) -> &mut WrappingRange1069 pub fn valid_range_mut(&mut self) -> &mut WrappingRange { 1070 match self { 1071 Scalar::Initialized { valid_range, .. } => valid_range, 1072 Scalar::Union { .. } => panic!("cannot change the valid range of a union"), 1073 } 1074 } 1075 1076 /// Returns `true` if all possible numbers are valid, i.e `valid_range` covers the whole layout 1077 #[inline] is_always_valid<C: HasDataLayout>(&self, cx: &C) -> bool1078 pub fn is_always_valid<C: HasDataLayout>(&self, cx: &C) -> bool { 1079 match *self { 1080 Scalar::Initialized { valid_range, .. } => valid_range.is_full_for(self.size(cx)), 1081 Scalar::Union { .. } => true, 1082 } 1083 } 1084 1085 /// Returns `true` if this type can be left uninit. 1086 #[inline] is_uninit_valid(&self) -> bool1087 pub fn is_uninit_valid(&self) -> bool { 1088 match *self { 1089 Scalar::Initialized { .. } => false, 1090 Scalar::Union { .. } => true, 1091 } 1092 } 1093 } 1094 1095 rustc_index::newtype_index! { 1096 /// The *source-order* index of a field in a variant. 1097 /// 1098 /// This is how most code after type checking refers to fields, rather than 1099 /// using names (as names have hygiene complications and more complex lookup). 1100 /// 1101 /// Particularly for `repr(Rust)` types, this may not be the same as *layout* order. 1102 /// (It is for `repr(C)` `struct`s, however.) 1103 /// 1104 /// For example, in the following types, 1105 /// ```rust 1106 /// # enum Never {} 1107 /// # #[repr(u16)] 1108 /// enum Demo1 { 1109 /// Variant0 { a: Never, b: i32 } = 100, 1110 /// Variant1 { c: u8, d: u64 } = 10, 1111 /// } 1112 /// struct Demo2 { e: u8, f: u16, g: u8 } 1113 /// ``` 1114 /// `b` is `FieldIdx(1)` in `VariantIdx(0)`, 1115 /// `d` is `FieldIdx(1)` in `VariantIdx(1)`, and 1116 /// `f` is `FieldIdx(1)` in `VariantIdx(0)`. 1117 #[derive(HashStable_Generic)] 1118 pub struct FieldIdx {} 1119 } 1120 1121 /// Describes how the fields of a type are located in memory. 1122 #[derive(PartialEq, Eq, Hash, Clone, Debug)] 1123 #[cfg_attr(feature = "nightly", derive(HashStable_Generic))] 1124 pub enum FieldsShape { 1125 /// Scalar primitives and `!`, which never have fields. 1126 Primitive, 1127 1128 /// All fields start at no offset. The `usize` is the field count. 1129 Union(NonZeroUsize), 1130 1131 /// Array/vector-like placement, with all fields of identical types. 1132 Array { stride: Size, count: u64 }, 1133 1134 /// Struct-like placement, with precomputed offsets. 1135 /// 1136 /// Fields are guaranteed to not overlap, but note that gaps 1137 /// before, between and after all the fields are NOT always 1138 /// padding, and as such their contents may not be discarded. 1139 /// For example, enum variants leave a gap at the start, 1140 /// where the discriminant field in the enum layout goes. 1141 Arbitrary { 1142 /// Offsets for the first byte of each field, 1143 /// ordered to match the source definition order. 1144 /// This vector does not go in increasing order. 1145 // FIXME(eddyb) use small vector optimization for the common case. 1146 offsets: IndexVec<FieldIdx, Size>, 1147 1148 /// Maps source order field indices to memory order indices, 1149 /// depending on how the fields were reordered (if at all). 1150 /// This is a permutation, with both the source order and the 1151 /// memory order using the same (0..n) index ranges. 1152 /// 1153 /// Note that during computation of `memory_index`, sometimes 1154 /// it is easier to operate on the inverse mapping (that is, 1155 /// from memory order to source order), and that is usually 1156 /// named `inverse_memory_index`. 1157 /// 1158 // FIXME(eddyb) build a better abstraction for permutations, if possible. 1159 // FIXME(camlorn) also consider small vector optimization here. 1160 memory_index: IndexVec<FieldIdx, u32>, 1161 }, 1162 } 1163 1164 impl FieldsShape { 1165 #[inline] count(&self) -> usize1166 pub fn count(&self) -> usize { 1167 match *self { 1168 FieldsShape::Primitive => 0, 1169 FieldsShape::Union(count) => count.get(), 1170 FieldsShape::Array { count, .. } => count.try_into().unwrap(), 1171 FieldsShape::Arbitrary { ref offsets, .. } => offsets.len(), 1172 } 1173 } 1174 1175 #[inline] offset(&self, i: usize) -> Size1176 pub fn offset(&self, i: usize) -> Size { 1177 match *self { 1178 FieldsShape::Primitive => { 1179 unreachable!("FieldsShape::offset: `Primitive`s have no fields") 1180 } 1181 FieldsShape::Union(count) => { 1182 assert!( 1183 i < count.get(), 1184 "tried to access field {} of union with {} fields", 1185 i, 1186 count 1187 ); 1188 Size::ZERO 1189 } 1190 FieldsShape::Array { stride, count } => { 1191 let i = u64::try_from(i).unwrap(); 1192 assert!(i < count); 1193 stride * i 1194 } 1195 FieldsShape::Arbitrary { ref offsets, .. } => offsets[FieldIdx::from_usize(i)], 1196 } 1197 } 1198 1199 #[inline] memory_index(&self, i: usize) -> usize1200 pub fn memory_index(&self, i: usize) -> usize { 1201 match *self { 1202 FieldsShape::Primitive => { 1203 unreachable!("FieldsShape::memory_index: `Primitive`s have no fields") 1204 } 1205 FieldsShape::Union(_) | FieldsShape::Array { .. } => i, 1206 FieldsShape::Arbitrary { ref memory_index, .. } => { 1207 memory_index[FieldIdx::from_usize(i)].try_into().unwrap() 1208 } 1209 } 1210 } 1211 1212 /// Gets source indices of the fields by increasing offsets. 1213 #[inline] index_by_increasing_offset(&self) -> impl Iterator<Item = usize> + '_1214 pub fn index_by_increasing_offset(&self) -> impl Iterator<Item = usize> + '_ { 1215 let mut inverse_small = [0u8; 64]; 1216 let mut inverse_big = IndexVec::new(); 1217 let use_small = self.count() <= inverse_small.len(); 1218 1219 // We have to write this logic twice in order to keep the array small. 1220 if let FieldsShape::Arbitrary { ref memory_index, .. } = *self { 1221 if use_small { 1222 for (field_idx, &mem_idx) in memory_index.iter_enumerated() { 1223 inverse_small[mem_idx as usize] = field_idx.as_u32() as u8; 1224 } 1225 } else { 1226 inverse_big = memory_index.invert_bijective_mapping(); 1227 } 1228 } 1229 1230 (0..self.count()).map(move |i| match *self { 1231 FieldsShape::Primitive | FieldsShape::Union(_) | FieldsShape::Array { .. } => i, 1232 FieldsShape::Arbitrary { .. } => { 1233 if use_small { 1234 inverse_small[i] as usize 1235 } else { 1236 inverse_big[i as u32].as_usize() 1237 } 1238 } 1239 }) 1240 } 1241 } 1242 1243 /// An identifier that specifies the address space that some operation 1244 /// should operate on. Special address spaces have an effect on code generation, 1245 /// depending on the target and the address spaces it implements. 1246 #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] 1247 #[cfg_attr(feature = "nightly", derive(HashStable_Generic))] 1248 pub struct AddressSpace(pub u32); 1249 1250 impl AddressSpace { 1251 /// The default address space, corresponding to data space. 1252 pub const DATA: Self = AddressSpace(0); 1253 } 1254 1255 /// Describes how values of the type are passed by target ABIs, 1256 /// in terms of categories of C types there are ABI rules for. 1257 #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] 1258 #[cfg_attr(feature = "nightly", derive(HashStable_Generic))] 1259 1260 pub enum Abi { 1261 Uninhabited, 1262 Scalar(Scalar), 1263 ScalarPair(Scalar, Scalar), 1264 Vector { 1265 element: Scalar, 1266 count: u64, 1267 }, 1268 Aggregate { 1269 /// If true, the size is exact, otherwise it's only a lower bound. 1270 sized: bool, 1271 }, 1272 } 1273 1274 impl Abi { 1275 /// Returns `true` if the layout corresponds to an unsized type. 1276 #[inline] is_unsized(&self) -> bool1277 pub fn is_unsized(&self) -> bool { 1278 match *self { 1279 Abi::Uninhabited | Abi::Scalar(_) | Abi::ScalarPair(..) | Abi::Vector { .. } => false, 1280 Abi::Aggregate { sized } => !sized, 1281 } 1282 } 1283 1284 #[inline] is_sized(&self) -> bool1285 pub fn is_sized(&self) -> bool { 1286 !self.is_unsized() 1287 } 1288 1289 /// Returns `true` if this is a single signed integer scalar 1290 #[inline] is_signed(&self) -> bool1291 pub fn is_signed(&self) -> bool { 1292 match self { 1293 Abi::Scalar(scal) => match scal.primitive() { 1294 Primitive::Int(_, signed) => signed, 1295 _ => false, 1296 }, 1297 _ => panic!("`is_signed` on non-scalar ABI {:?}", self), 1298 } 1299 } 1300 1301 /// Returns `true` if this is an uninhabited type 1302 #[inline] is_uninhabited(&self) -> bool1303 pub fn is_uninhabited(&self) -> bool { 1304 matches!(*self, Abi::Uninhabited) 1305 } 1306 1307 /// Returns `true` is this is a scalar type 1308 #[inline] is_scalar(&self) -> bool1309 pub fn is_scalar(&self) -> bool { 1310 matches!(*self, Abi::Scalar(_)) 1311 } 1312 1313 /// Returns the fixed alignment of this ABI, if any is mandated. inherent_align<C: HasDataLayout>(&self, cx: &C) -> Option<AbiAndPrefAlign>1314 pub fn inherent_align<C: HasDataLayout>(&self, cx: &C) -> Option<AbiAndPrefAlign> { 1315 Some(match *self { 1316 Abi::Scalar(s) => s.align(cx), 1317 Abi::ScalarPair(s1, s2) => s1.align(cx).max(s2.align(cx)), 1318 Abi::Vector { element, count } => { 1319 cx.data_layout().vector_align(element.size(cx) * count) 1320 } 1321 Abi::Uninhabited | Abi::Aggregate { .. } => return None, 1322 }) 1323 } 1324 1325 /// Returns the fixed size of this ABI, if any is mandated. inherent_size<C: HasDataLayout>(&self, cx: &C) -> Option<Size>1326 pub fn inherent_size<C: HasDataLayout>(&self, cx: &C) -> Option<Size> { 1327 Some(match *self { 1328 Abi::Scalar(s) => { 1329 // No padding in scalars. 1330 s.size(cx) 1331 } 1332 Abi::ScalarPair(s1, s2) => { 1333 // May have some padding between the pair. 1334 let field2_offset = s1.size(cx).align_to(s2.align(cx).abi); 1335 (field2_offset + s2.size(cx)).align_to(self.inherent_align(cx)?.abi) 1336 } 1337 Abi::Vector { element, count } => { 1338 // No padding in vectors, except possibly for trailing padding 1339 // to make the size a multiple of align (e.g. for vectors of size 3). 1340 (element.size(cx) * count).align_to(self.inherent_align(cx)?.abi) 1341 } 1342 Abi::Uninhabited | Abi::Aggregate { .. } => return None, 1343 }) 1344 } 1345 1346 /// Discard validity range information and allow undef. to_union(&self) -> Self1347 pub fn to_union(&self) -> Self { 1348 assert!(self.is_sized()); 1349 match *self { 1350 Abi::Scalar(s) => Abi::Scalar(s.to_union()), 1351 Abi::ScalarPair(s1, s2) => Abi::ScalarPair(s1.to_union(), s2.to_union()), 1352 Abi::Vector { element, count } => Abi::Vector { element: element.to_union(), count }, 1353 Abi::Uninhabited | Abi::Aggregate { .. } => Abi::Aggregate { sized: true }, 1354 } 1355 } 1356 } 1357 1358 #[derive(PartialEq, Eq, Hash, Clone, Debug)] 1359 #[cfg_attr(feature = "nightly", derive(HashStable_Generic))] 1360 pub enum Variants { 1361 /// Single enum variants, structs/tuples, unions, and all non-ADTs. 1362 Single { index: VariantIdx }, 1363 1364 /// Enum-likes with more than one inhabited variant: each variant comes with 1365 /// a *discriminant* (usually the same as the variant index but the user can 1366 /// assign explicit discriminant values). That discriminant is encoded 1367 /// as a *tag* on the machine. The layout of each variant is 1368 /// a struct, and they all have space reserved for the tag. 1369 /// For enums, the tag is the sole field of the layout. 1370 Multiple { 1371 tag: Scalar, 1372 tag_encoding: TagEncoding, 1373 tag_field: usize, 1374 variants: IndexVec<VariantIdx, LayoutS>, 1375 }, 1376 } 1377 1378 #[derive(PartialEq, Eq, Hash, Clone, Debug)] 1379 #[cfg_attr(feature = "nightly", derive(HashStable_Generic))] 1380 pub enum TagEncoding { 1381 /// The tag directly stores the discriminant, but possibly with a smaller layout 1382 /// (so converting the tag to the discriminant can require sign extension). 1383 Direct, 1384 1385 /// Niche (values invalid for a type) encoding the discriminant: 1386 /// Discriminant and variant index coincide. 1387 /// The variant `untagged_variant` contains a niche at an arbitrary 1388 /// offset (field `tag_field` of the enum), which for a variant with 1389 /// discriminant `d` is set to 1390 /// `(d - niche_variants.start).wrapping_add(niche_start)`. 1391 /// 1392 /// For example, `Option<(usize, &T)>` is represented such that 1393 /// `None` has a null pointer for the second tuple field, and 1394 /// `Some` is the identity function (with a non-null reference). 1395 Niche { 1396 untagged_variant: VariantIdx, 1397 niche_variants: RangeInclusive<VariantIdx>, 1398 niche_start: u128, 1399 }, 1400 } 1401 1402 #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] 1403 #[cfg_attr(feature = "nightly", derive(HashStable_Generic))] 1404 pub struct Niche { 1405 pub offset: Size, 1406 pub value: Primitive, 1407 pub valid_range: WrappingRange, 1408 } 1409 1410 impl Niche { from_scalar<C: HasDataLayout>(cx: &C, offset: Size, scalar: Scalar) -> Option<Self>1411 pub fn from_scalar<C: HasDataLayout>(cx: &C, offset: Size, scalar: Scalar) -> Option<Self> { 1412 let Scalar::Initialized { value, valid_range } = scalar else { return None }; 1413 let niche = Niche { offset, value, valid_range }; 1414 if niche.available(cx) > 0 { Some(niche) } else { None } 1415 } 1416 available<C: HasDataLayout>(&self, cx: &C) -> u1281417 pub fn available<C: HasDataLayout>(&self, cx: &C) -> u128 { 1418 let Self { value, valid_range: v, .. } = *self; 1419 let size = value.size(cx); 1420 assert!(size.bits() <= 128); 1421 let max_value = size.unsigned_int_max(); 1422 1423 // Find out how many values are outside the valid range. 1424 let niche = v.end.wrapping_add(1)..v.start; 1425 niche.end.wrapping_sub(niche.start) & max_value 1426 } 1427 reserve<C: HasDataLayout>(&self, cx: &C, count: u128) -> Option<(u128, Scalar)>1428 pub fn reserve<C: HasDataLayout>(&self, cx: &C, count: u128) -> Option<(u128, Scalar)> { 1429 assert!(count > 0); 1430 1431 let Self { value, valid_range: v, .. } = *self; 1432 let size = value.size(cx); 1433 assert!(size.bits() <= 128); 1434 let max_value = size.unsigned_int_max(); 1435 1436 let niche = v.end.wrapping_add(1)..v.start; 1437 let available = niche.end.wrapping_sub(niche.start) & max_value; 1438 if count > available { 1439 return None; 1440 } 1441 1442 // Extend the range of valid values being reserved by moving either `v.start` or `v.end` bound. 1443 // Given an eventual `Option<T>`, we try to maximize the chance for `None` to occupy the niche of zero. 1444 // This is accomplished by preferring enums with 2 variants(`count==1`) and always taking the shortest path to niche zero. 1445 // Having `None` in niche zero can enable some special optimizations. 1446 // 1447 // Bound selection criteria: 1448 // 1. Select closest to zero given wrapping semantics. 1449 // 2. Avoid moving past zero if possible. 1450 // 1451 // In practice this means that enums with `count > 1` are unlikely to claim niche zero, since they have to fit perfectly. 1452 // If niche zero is already reserved, the selection of bounds are of little interest. 1453 let move_start = |v: WrappingRange| { 1454 let start = v.start.wrapping_sub(count) & max_value; 1455 Some((start, Scalar::Initialized { value, valid_range: v.with_start(start) })) 1456 }; 1457 let move_end = |v: WrappingRange| { 1458 let start = v.end.wrapping_add(1) & max_value; 1459 let end = v.end.wrapping_add(count) & max_value; 1460 Some((start, Scalar::Initialized { value, valid_range: v.with_end(end) })) 1461 }; 1462 let distance_end_zero = max_value - v.end; 1463 if v.start > v.end { 1464 // zero is unavailable because wrapping occurs 1465 move_end(v) 1466 } else if v.start <= distance_end_zero { 1467 if count <= v.start { 1468 move_start(v) 1469 } else { 1470 // moved past zero, use other bound 1471 move_end(v) 1472 } 1473 } else { 1474 let end = v.end.wrapping_add(count) & max_value; 1475 let overshot_zero = (1..=v.end).contains(&end); 1476 if overshot_zero { 1477 // moved past zero, use other bound 1478 move_start(v) 1479 } else { 1480 move_end(v) 1481 } 1482 } 1483 } 1484 } 1485 1486 rustc_index::newtype_index! { 1487 /// The *source-order* index of a variant in a type. 1488 /// 1489 /// For enums, these are always `0..variant_count`, regardless of any 1490 /// custom discriminants that may have been defined, and including any 1491 /// variants that may end up uninhabited due to field types. (Some of the 1492 /// variants may not be present in a monomorphized ABI [`Variants`], but 1493 /// those skipped variants are always counted when determining the *index*.) 1494 /// 1495 /// `struct`s, `tuples`, and `unions`s are considered to have a single variant 1496 /// with variant index zero, aka [`FIRST_VARIANT`]. 1497 #[derive(HashStable_Generic)] 1498 pub struct VariantIdx { 1499 /// Equivalent to `VariantIdx(0)`. 1500 const FIRST_VARIANT = 0; 1501 } 1502 } 1503 1504 #[derive(PartialEq, Eq, Hash, Clone)] 1505 #[cfg_attr(feature = "nightly", derive(HashStable_Generic))] 1506 pub struct LayoutS { 1507 /// Says where the fields are located within the layout. 1508 pub fields: FieldsShape, 1509 1510 /// Encodes information about multi-variant layouts. 1511 /// Even with `Multiple` variants, a layout still has its own fields! Those are then 1512 /// shared between all variants. One of them will be the discriminant, 1513 /// but e.g. generators can have more. 1514 /// 1515 /// To access all fields of this layout, both `fields` and the fields of the active variant 1516 /// must be taken into account. 1517 pub variants: Variants, 1518 1519 /// The `abi` defines how this data is passed between functions, and it defines 1520 /// value restrictions via `valid_range`. 1521 /// 1522 /// Note that this is entirely orthogonal to the recursive structure defined by 1523 /// `variants` and `fields`; for example, `ManuallyDrop<Result<isize, isize>>` has 1524 /// `Abi::ScalarPair`! So, even with non-`Aggregate` `abi`, `fields` and `variants` 1525 /// have to be taken into account to find all fields of this layout. 1526 pub abi: Abi, 1527 1528 /// The leaf scalar with the largest number of invalid values 1529 /// (i.e. outside of its `valid_range`), if it exists. 1530 pub largest_niche: Option<Niche>, 1531 1532 pub align: AbiAndPrefAlign, 1533 pub size: Size, 1534 } 1535 1536 impl LayoutS { scalar<C: HasDataLayout>(cx: &C, scalar: Scalar) -> Self1537 pub fn scalar<C: HasDataLayout>(cx: &C, scalar: Scalar) -> Self { 1538 let largest_niche = Niche::from_scalar(cx, Size::ZERO, scalar); 1539 let size = scalar.size(cx); 1540 let align = scalar.align(cx); 1541 LayoutS { 1542 variants: Variants::Single { index: FIRST_VARIANT }, 1543 fields: FieldsShape::Primitive, 1544 abi: Abi::Scalar(scalar), 1545 largest_niche, 1546 size, 1547 align, 1548 } 1549 } 1550 } 1551 1552 impl fmt::Debug for LayoutS { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result1553 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 1554 // This is how `Layout` used to print before it become 1555 // `Interned<LayoutS>`. We print it like this to avoid having to update 1556 // expected output in a lot of tests. 1557 let LayoutS { size, align, abi, fields, largest_niche, variants } = self; 1558 f.debug_struct("Layout") 1559 .field("size", size) 1560 .field("align", align) 1561 .field("abi", abi) 1562 .field("fields", fields) 1563 .field("largest_niche", largest_niche) 1564 .field("variants", variants) 1565 .finish() 1566 } 1567 } 1568 1569 #[derive(Copy, Clone, PartialEq, Eq, Hash, HashStable_Generic)] 1570 #[rustc_pass_by_value] 1571 pub struct Layout<'a>(pub Interned<'a, LayoutS>); 1572 1573 impl<'a> fmt::Debug for Layout<'a> { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result1574 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 1575 // See comment on `<LayoutS as Debug>::fmt` above. 1576 self.0.0.fmt(f) 1577 } 1578 } 1579 1580 impl<'a> Layout<'a> { fields(self) -> &'a FieldsShape1581 pub fn fields(self) -> &'a FieldsShape { 1582 &self.0.0.fields 1583 } 1584 variants(self) -> &'a Variants1585 pub fn variants(self) -> &'a Variants { 1586 &self.0.0.variants 1587 } 1588 abi(self) -> Abi1589 pub fn abi(self) -> Abi { 1590 self.0.0.abi 1591 } 1592 largest_niche(self) -> Option<Niche>1593 pub fn largest_niche(self) -> Option<Niche> { 1594 self.0.0.largest_niche 1595 } 1596 align(self) -> AbiAndPrefAlign1597 pub fn align(self) -> AbiAndPrefAlign { 1598 self.0.0.align 1599 } 1600 size(self) -> Size1601 pub fn size(self) -> Size { 1602 self.0.0.size 1603 } 1604 1605 /// Whether the layout is from a type that implements [`std::marker::PointerLike`]. 1606 /// 1607 /// Currently, that means that the type is pointer-sized, pointer-aligned, 1608 /// and has a scalar ABI. is_pointer_like(self, data_layout: &TargetDataLayout) -> bool1609 pub fn is_pointer_like(self, data_layout: &TargetDataLayout) -> bool { 1610 self.size() == data_layout.pointer_size 1611 && self.align().abi == data_layout.pointer_align.abi 1612 && matches!(self.abi(), Abi::Scalar(..)) 1613 } 1614 } 1615 1616 #[derive(Copy, Clone, PartialEq, Eq, Debug)] 1617 pub enum PointerKind { 1618 /// Shared reference. `frozen` indicates the absence of any `UnsafeCell`. 1619 SharedRef { frozen: bool }, 1620 /// Mutable reference. `unpin` indicates the absence of any pinned data. 1621 MutableRef { unpin: bool }, 1622 /// Box. `unpin` indicates the absence of any pinned data. 1623 Box { unpin: bool }, 1624 } 1625 1626 /// Note that this information is advisory only, and backends are free to ignore it. 1627 /// It can only be used to encode potential optimizations, but no critical information. 1628 #[derive(Copy, Clone, Debug)] 1629 pub struct PointeeInfo { 1630 pub size: Size, 1631 pub align: Align, 1632 pub safe: Option<PointerKind>, 1633 } 1634 1635 impl LayoutS { 1636 /// Returns `true` if the layout corresponds to an unsized type. is_unsized(&self) -> bool1637 pub fn is_unsized(&self) -> bool { 1638 self.abi.is_unsized() 1639 } 1640 is_sized(&self) -> bool1641 pub fn is_sized(&self) -> bool { 1642 self.abi.is_sized() 1643 } 1644 1645 /// Returns `true` if the type is a ZST and not unsized. is_zst(&self) -> bool1646 pub fn is_zst(&self) -> bool { 1647 match self.abi { 1648 Abi::Scalar(_) | Abi::ScalarPair(..) | Abi::Vector { .. } => false, 1649 Abi::Uninhabited => self.size.bytes() == 0, 1650 Abi::Aggregate { sized } => sized && self.size.bytes() == 0, 1651 } 1652 } 1653 } 1654 1655 #[derive(Copy, Clone, Debug)] 1656 pub enum StructKind { 1657 /// A tuple, closure, or univariant which cannot be coerced to unsized. 1658 AlwaysSized, 1659 /// A univariant, the last field of which may be coerced to unsized. 1660 MaybeUnsized, 1661 /// A univariant, but with a prefix of an arbitrary size & alignment (e.g., enum tag). 1662 Prefixed(Size, Align), 1663 } 1664