1#![cfg_attr(feature = "nightly", allow(internal_features))]
3#![cfg_attr(feature = "nightly", doc(rust_logo))]
4#![cfg_attr(feature = "nightly", feature(assert_matches))]
5#![cfg_attr(feature = "nightly", feature(rustc_attrs))]
6#![cfg_attr(feature = "nightly", feature(rustdoc_internals))]
7#![cfg_attr(feature = "nightly", feature(step_trait))]
8use std::fmt;
43#[cfg(feature = "nightly")]
44use std::iter::Step;
45use std::num::{NonZeroUsize, ParseIntError};
46use std::ops::{Add, AddAssign, Deref, Mul, RangeInclusive, Sub};
47use std::str::FromStr;
48
49use bitflags::bitflags;
50#[cfg(feature = "nightly")]
51use rustc_data_structures::stable_hasher::StableOrd;
52use rustc_hashes::Hash64;
53use rustc_index::{Idx, IndexSlice, IndexVec};
54#[cfg(feature = "nightly")]
55use rustc_macros::{Decodable_NoContext, Encodable_NoContext, HashStable_Generic};
56
57mod callconv;
58mod canon_abi;
59mod extern_abi;
60mod layout;
61#[cfg(test)]
62mod tests;
63
64pub use callconv::{Heterogeneous, HomogeneousAggregate, Reg, RegKind};
65pub use canon_abi::{ArmCall, CanonAbi, InterruptKind, X86Call};
66pub use extern_abi::{ExternAbi, all_names};
67#[cfg(feature = "nightly")]
68pub use layout::{FIRST_VARIANT, FieldIdx, Layout, TyAbiInterface, TyAndLayout, VariantIdx};
69pub use layout::{LayoutCalculator, LayoutCalculatorError};
70
71#[cfg(feature = "nightly")]
75pub trait HashStableContext {}
76
77#[derive(Clone, Copy, PartialEq, Eq, Default)]
78#[cfg_attr(
79 feature = "nightly",
80 derive(Encodable_NoContext, Decodable_NoContext, HashStable_Generic)
81)]
82pub struct ReprFlags(u8);
83
84bitflags! {
85 impl ReprFlags: u8 {
86 const IS_C = 1 << 0;
87 const IS_SIMD = 1 << 1;
88 const IS_TRANSPARENT = 1 << 2;
89 const IS_LINEAR = 1 << 3;
92 const RANDOMIZE_LAYOUT = 1 << 4;
96 const FIELD_ORDER_UNOPTIMIZABLE = ReprFlags::IS_C.bits()
98 | ReprFlags::IS_SIMD.bits()
99 | ReprFlags::IS_LINEAR.bits();
100 const ABI_UNOPTIMIZABLE = ReprFlags::IS_C.bits() | ReprFlags::IS_SIMD.bits();
101 }
102}
103
104impl std::fmt::Debug for ReprFlags {
107 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
108 bitflags::parser::to_writer(self, f)
109 }
110}
111
112#[derive(Copy, Clone, Debug, Eq, PartialEq)]
113#[cfg_attr(
114 feature = "nightly",
115 derive(Encodable_NoContext, Decodable_NoContext, HashStable_Generic)
116)]
117pub enum IntegerType {
118 Pointer(bool),
121 Fixed(Integer, bool),
124}
125
126impl IntegerType {
127 pub fn is_signed(&self) -> bool {
128 match self {
129 IntegerType::Pointer(b) => *b,
130 IntegerType::Fixed(_, b) => *b,
131 }
132 }
133}
134
135#[derive(Copy, Clone, Debug, Eq, PartialEq, Default)]
137#[cfg_attr(
138 feature = "nightly",
139 derive(Encodable_NoContext, Decodable_NoContext, HashStable_Generic)
140)]
141pub struct ReprOptions {
142 pub int: Option<IntegerType>,
143 pub align: Option<Align>,
144 pub pack: Option<Align>,
145 pub flags: ReprFlags,
146 pub field_shuffle_seed: Hash64,
154}
155
156impl ReprOptions {
157 #[inline]
158 pub fn simd(&self) -> bool {
159 self.flags.contains(ReprFlags::IS_SIMD)
160 }
161
162 #[inline]
163 pub fn c(&self) -> bool {
164 self.flags.contains(ReprFlags::IS_C)
165 }
166
167 #[inline]
168 pub fn packed(&self) -> bool {
169 self.pack.is_some()
170 }
171
172 #[inline]
173 pub fn transparent(&self) -> bool {
174 self.flags.contains(ReprFlags::IS_TRANSPARENT)
175 }
176
177 #[inline]
178 pub fn linear(&self) -> bool {
179 self.flags.contains(ReprFlags::IS_LINEAR)
180 }
181
182 pub fn discr_type(&self) -> IntegerType {
185 self.int.unwrap_or(IntegerType::Pointer(true))
186 }
187
188 pub fn inhibit_enum_layout_opt(&self) -> bool {
192 self.c() || self.int.is_some()
193 }
194
195 pub fn inhibit_newtype_abi_optimization(&self) -> bool {
196 self.flags.intersects(ReprFlags::ABI_UNOPTIMIZABLE)
197 }
198
199 pub fn inhibit_struct_field_reordering(&self) -> bool {
202 self.flags.intersects(ReprFlags::FIELD_ORDER_UNOPTIMIZABLE) || self.int.is_some()
203 }
204
205 pub fn can_randomize_type_layout(&self) -> bool {
208 !self.inhibit_struct_field_reordering() && self.flags.contains(ReprFlags::RANDOMIZE_LAYOUT)
209 }
210
211 pub fn inhibits_union_abi_opt(&self) -> bool {
213 self.c()
214 }
215}
216
217pub const MAX_SIMD_LANES: u64 = 1 << 0xF;
223
224#[derive(Debug, PartialEq, Eq)]
227pub struct TargetDataLayout {
228 pub endian: Endian,
229 pub i1_align: AbiAlign,
230 pub i8_align: AbiAlign,
231 pub i16_align: AbiAlign,
232 pub i32_align: AbiAlign,
233 pub i64_align: AbiAlign,
234 pub i128_align: AbiAlign,
235 pub f16_align: AbiAlign,
236 pub f32_align: AbiAlign,
237 pub f64_align: AbiAlign,
238 pub f128_align: AbiAlign,
239 pub pointer_size: Size,
240 pub pointer_align: AbiAlign,
241 pub aggregate_align: AbiAlign,
242
243 pub vector_align: Vec<(Size, AbiAlign)>,
245
246 pub instruction_address_space: AddressSpace,
247
248 pub c_enum_min_size: Integer,
252}
253
254impl Default for TargetDataLayout {
255 fn default() -> TargetDataLayout {
257 let align = |bits| Align::from_bits(bits).unwrap();
258 TargetDataLayout {
259 endian: Endian::Big,
260 i1_align: AbiAlign::new(align(8)),
261 i8_align: AbiAlign::new(align(8)),
262 i16_align: AbiAlign::new(align(16)),
263 i32_align: AbiAlign::new(align(32)),
264 i64_align: AbiAlign::new(align(32)),
265 i128_align: AbiAlign::new(align(32)),
266 f16_align: AbiAlign::new(align(16)),
267 f32_align: AbiAlign::new(align(32)),
268 f64_align: AbiAlign::new(align(64)),
269 f128_align: AbiAlign::new(align(128)),
270 pointer_size: Size::from_bits(64),
271 pointer_align: AbiAlign::new(align(64)),
272 aggregate_align: AbiAlign { abi: align(8) },
273 vector_align: vec![
274 (Size::from_bits(64), AbiAlign::new(align(64))),
275 (Size::from_bits(128), AbiAlign::new(align(128))),
276 ],
277 instruction_address_space: AddressSpace::DATA,
278 c_enum_min_size: Integer::I32,
279 }
280 }
281}
282
283pub enum TargetDataLayoutErrors<'a> {
284 InvalidAddressSpace { addr_space: &'a str, cause: &'a str, err: ParseIntError },
285 InvalidBits { kind: &'a str, bit: &'a str, cause: &'a str, err: ParseIntError },
286 MissingAlignment { cause: &'a str },
287 InvalidAlignment { cause: &'a str, err: AlignFromBytesError },
288 InconsistentTargetArchitecture { dl: &'a str, target: &'a str },
289 InconsistentTargetPointerWidth { pointer_size: u64, target: u32 },
290 InvalidBitsSize { err: String },
291}
292
293impl TargetDataLayout {
294 pub fn parse_from_llvm_datalayout_string<'a>(
300 input: &'a str,
301 ) -> Result<TargetDataLayout, TargetDataLayoutErrors<'a>> {
302 let parse_address_space = |s: &'a str, cause: &'a str| {
304 s.parse::<u32>().map(AddressSpace).map_err(|err| {
305 TargetDataLayoutErrors::InvalidAddressSpace { addr_space: s, cause, err }
306 })
307 };
308
309 let parse_bits = |s: &'a str, kind: &'a str, cause: &'a str| {
311 s.parse::<u64>().map_err(|err| TargetDataLayoutErrors::InvalidBits {
312 kind,
313 bit: s,
314 cause,
315 err,
316 })
317 };
318
319 let parse_size =
321 |s: &'a str, cause: &'a str| parse_bits(s, "size", cause).map(Size::from_bits);
322
323 let parse_align = |s: &[&'a str], cause: &'a str| {
325 if s.is_empty() {
326 return Err(TargetDataLayoutErrors::MissingAlignment { cause });
327 }
328 let align_from_bits = |bits| {
329 Align::from_bits(bits)
330 .map_err(|err| TargetDataLayoutErrors::InvalidAlignment { cause, err })
331 };
332 let abi = parse_bits(s[0], "alignment", cause)?;
333 Ok(AbiAlign::new(align_from_bits(abi)?))
334 };
335
336 let mut dl = TargetDataLayout::default();
337 let mut i128_align_src = 64;
338 for spec in input.split('-') {
339 let spec_parts = spec.split(':').collect::<Vec<_>>();
340
341 match &*spec_parts {
342 ["e"] => dl.endian = Endian::Little,
343 ["E"] => dl.endian = Endian::Big,
344 [p] if p.starts_with('P') => {
345 dl.instruction_address_space = parse_address_space(&p[1..], "P")?
346 }
347 ["a", a @ ..] => dl.aggregate_align = parse_align(a, "a")?,
348 ["f16", a @ ..] => dl.f16_align = parse_align(a, "f16")?,
349 ["f32", a @ ..] => dl.f32_align = parse_align(a, "f32")?,
350 ["f64", a @ ..] => dl.f64_align = parse_align(a, "f64")?,
351 ["f128", a @ ..] => dl.f128_align = parse_align(a, "f128")?,
352 [p @ "p", s, a @ ..] | [p @ "p0", s, a @ ..] => {
356 dl.pointer_size = parse_size(s, p)?;
357 dl.pointer_align = parse_align(a, p)?;
358 }
359 [s, a @ ..] if s.starts_with('i') => {
360 let Ok(bits) = s[1..].parse::<u64>() else {
361 parse_size(&s[1..], "i")?; continue;
363 };
364 let a = parse_align(a, s)?;
365 match bits {
366 1 => dl.i1_align = a,
367 8 => dl.i8_align = a,
368 16 => dl.i16_align = a,
369 32 => dl.i32_align = a,
370 64 => dl.i64_align = a,
371 _ => {}
372 }
373 if bits >= i128_align_src && bits <= 128 {
374 i128_align_src = bits;
377 dl.i128_align = a;
378 }
379 }
380 [s, a @ ..] if s.starts_with('v') => {
381 let v_size = parse_size(&s[1..], "v")?;
382 let a = parse_align(a, s)?;
383 if let Some(v) = dl.vector_align.iter_mut().find(|v| v.0 == v_size) {
384 v.1 = a;
385 continue;
386 }
387 dl.vector_align.push((v_size, a));
389 }
390 _ => {} }
392 }
393 Ok(dl)
394 }
395
396 #[inline]
406 pub fn obj_size_bound(&self) -> u64 {
407 match self.pointer_size.bits() {
408 16 => 1 << 15,
409 32 => 1 << 31,
410 64 => 1 << 61,
411 bits => panic!("obj_size_bound: unknown pointer bit size {bits}"),
412 }
413 }
414
415 #[inline]
416 pub fn ptr_sized_integer(&self) -> Integer {
417 use Integer::*;
418 match self.pointer_size.bits() {
419 16 => I16,
420 32 => I32,
421 64 => I64,
422 bits => panic!("ptr_sized_integer: unknown pointer bit size {bits}"),
423 }
424 }
425
426 #[inline]
428 fn cabi_vector_align(&self, vec_size: Size) -> Option<AbiAlign> {
429 self.vector_align
430 .iter()
431 .find(|(size, _align)| *size == vec_size)
432 .map(|(_size, align)| *align)
433 }
434
435 #[inline]
437 pub fn llvmlike_vector_align(&self, vec_size: Size) -> AbiAlign {
438 self.cabi_vector_align(vec_size).unwrap_or(AbiAlign::new(
439 Align::from_bytes(vec_size.bytes().next_power_of_two()).unwrap(),
440 ))
441 }
442}
443
444pub trait HasDataLayout {
445 fn data_layout(&self) -> &TargetDataLayout;
446}
447
448impl HasDataLayout for TargetDataLayout {
449 #[inline]
450 fn data_layout(&self) -> &TargetDataLayout {
451 self
452 }
453}
454
455impl HasDataLayout for &TargetDataLayout {
457 #[inline]
458 fn data_layout(&self) -> &TargetDataLayout {
459 (**self).data_layout()
460 }
461}
462
463#[derive(Copy, Clone, PartialEq, Eq)]
465pub enum Endian {
466 Little,
467 Big,
468}
469
470impl Endian {
471 pub fn as_str(&self) -> &'static str {
472 match self {
473 Self::Little => "little",
474 Self::Big => "big",
475 }
476 }
477}
478
479impl fmt::Debug for Endian {
480 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
481 f.write_str(self.as_str())
482 }
483}
484
485impl FromStr for Endian {
486 type Err = String;
487
488 fn from_str(s: &str) -> Result<Self, Self::Err> {
489 match s {
490 "little" => Ok(Self::Little),
491 "big" => Ok(Self::Big),
492 _ => Err(format!(r#"unknown endian: "{s}""#)),
493 }
494 }
495}
496
497#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
499#[cfg_attr(
500 feature = "nightly",
501 derive(Encodable_NoContext, Decodable_NoContext, HashStable_Generic)
502)]
503pub struct Size {
504 raw: u64,
505}
506
507#[cfg(feature = "nightly")]
508impl StableOrd for Size {
509 const CAN_USE_UNSTABLE_SORT: bool = true;
510
511 const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
514}
515
516impl fmt::Debug for Size {
518 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
519 write!(f, "Size({} bytes)", self.bytes())
520 }
521}
522
523impl Size {
524 pub const ZERO: Size = Size { raw: 0 };
525
526 pub fn from_bits(bits: impl TryInto<u64>) -> Size {
529 let bits = bits.try_into().ok().unwrap();
530 Size { raw: bits / 8 + ((bits % 8) + 7) / 8 }
532 }
533
534 #[inline]
535 pub fn from_bytes(bytes: impl TryInto<u64>) -> Size {
536 let bytes: u64 = bytes.try_into().ok().unwrap();
537 Size { raw: bytes }
538 }
539
540 #[inline]
541 pub fn bytes(self) -> u64 {
542 self.raw
543 }
544
545 #[inline]
546 pub fn bytes_usize(self) -> usize {
547 self.bytes().try_into().unwrap()
548 }
549
550 #[inline]
551 pub fn bits(self) -> u64 {
552 #[cold]
553 fn overflow(bytes: u64) -> ! {
554 panic!("Size::bits: {bytes} bytes in bits doesn't fit in u64")
555 }
556
557 self.bytes().checked_mul(8).unwrap_or_else(|| overflow(self.bytes()))
558 }
559
560 #[inline]
561 pub fn bits_usize(self) -> usize {
562 self.bits().try_into().unwrap()
563 }
564
565 #[inline]
566 pub fn align_to(self, align: Align) -> Size {
567 let mask = align.bytes() - 1;
568 Size::from_bytes((self.bytes() + mask) & !mask)
569 }
570
571 #[inline]
572 pub fn is_aligned(self, align: Align) -> bool {
573 let mask = align.bytes() - 1;
574 self.bytes() & mask == 0
575 }
576
577 #[inline]
578 pub fn checked_add<C: HasDataLayout>(self, offset: Size, cx: &C) -> Option<Size> {
579 let dl = cx.data_layout();
580
581 let bytes = self.bytes().checked_add(offset.bytes())?;
582
583 if bytes < dl.obj_size_bound() { Some(Size::from_bytes(bytes)) } else { None }
584 }
585
586 #[inline]
587 pub fn checked_mul<C: HasDataLayout>(self, count: u64, cx: &C) -> Option<Size> {
588 let dl = cx.data_layout();
589
590 let bytes = self.bytes().checked_mul(count)?;
591 if bytes < dl.obj_size_bound() { Some(Size::from_bytes(bytes)) } else { None }
592 }
593
594 #[inline]
597 pub fn sign_extend(self, value: u128) -> i128 {
598 let size = self.bits();
599 if size == 0 {
600 return 0;
602 }
603 let shift = 128 - size;
605 ((value << shift) as i128) >> shift
608 }
609
610 #[inline]
612 pub fn truncate(self, value: u128) -> u128 {
613 let size = self.bits();
614 if size == 0 {
615 return 0;
617 }
618 let shift = 128 - size;
619 (value << shift) >> shift
621 }
622
623 #[inline]
624 pub fn signed_int_min(&self) -> i128 {
625 self.sign_extend(1_u128 << (self.bits() - 1))
626 }
627
628 #[inline]
629 pub fn signed_int_max(&self) -> i128 {
630 i128::MAX >> (128 - self.bits())
631 }
632
633 #[inline]
634 pub fn unsigned_int_max(&self) -> u128 {
635 u128::MAX >> (128 - self.bits())
636 }
637}
638
639impl Add for Size {
643 type Output = Size;
644 #[inline]
645 fn add(self, other: Size) -> Size {
646 Size::from_bytes(self.bytes().checked_add(other.bytes()).unwrap_or_else(|| {
647 panic!("Size::add: {} + {} doesn't fit in u64", self.bytes(), other.bytes())
648 }))
649 }
650}
651
652impl Sub for Size {
653 type Output = Size;
654 #[inline]
655 fn sub(self, other: Size) -> Size {
656 Size::from_bytes(self.bytes().checked_sub(other.bytes()).unwrap_or_else(|| {
657 panic!("Size::sub: {} - {} would result in negative size", self.bytes(), other.bytes())
658 }))
659 }
660}
661
662impl Mul<Size> for u64 {
663 type Output = Size;
664 #[inline]
665 fn mul(self, size: Size) -> Size {
666 size * self
667 }
668}
669
670impl Mul<u64> for Size {
671 type Output = Size;
672 #[inline]
673 fn mul(self, count: u64) -> Size {
674 match self.bytes().checked_mul(count) {
675 Some(bytes) => Size::from_bytes(bytes),
676 None => panic!("Size::mul: {} * {} doesn't fit in u64", self.bytes(), count),
677 }
678 }
679}
680
681impl AddAssign for Size {
682 #[inline]
683 fn add_assign(&mut self, other: Size) {
684 *self = *self + other;
685 }
686}
687
688#[cfg(feature = "nightly")]
689impl Step for Size {
690 #[inline]
691 fn steps_between(start: &Self, end: &Self) -> (usize, Option<usize>) {
692 u64::steps_between(&start.bytes(), &end.bytes())
693 }
694
695 #[inline]
696 fn forward_checked(start: Self, count: usize) -> Option<Self> {
697 u64::forward_checked(start.bytes(), count).map(Self::from_bytes)
698 }
699
700 #[inline]
701 fn forward(start: Self, count: usize) -> Self {
702 Self::from_bytes(u64::forward(start.bytes(), count))
703 }
704
705 #[inline]
706 unsafe fn forward_unchecked(start: Self, count: usize) -> Self {
707 Self::from_bytes(unsafe { u64::forward_unchecked(start.bytes(), count) })
708 }
709
710 #[inline]
711 fn backward_checked(start: Self, count: usize) -> Option<Self> {
712 u64::backward_checked(start.bytes(), count).map(Self::from_bytes)
713 }
714
715 #[inline]
716 fn backward(start: Self, count: usize) -> Self {
717 Self::from_bytes(u64::backward(start.bytes(), count))
718 }
719
720 #[inline]
721 unsafe fn backward_unchecked(start: Self, count: usize) -> Self {
722 Self::from_bytes(unsafe { u64::backward_unchecked(start.bytes(), count) })
723 }
724}
725
726#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
728#[cfg_attr(
729 feature = "nightly",
730 derive(Encodable_NoContext, Decodable_NoContext, HashStable_Generic)
731)]
732pub struct Align {
733 pow2: u8,
734}
735
736impl fmt::Debug for Align {
738 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
739 write!(f, "Align({} bytes)", self.bytes())
740 }
741}
742
743#[derive(Clone, Copy)]
744pub enum AlignFromBytesError {
745 NotPowerOfTwo(u64),
746 TooLarge(u64),
747}
748
749impl AlignFromBytesError {
750 pub fn diag_ident(self) -> &'static str {
751 match self {
752 Self::NotPowerOfTwo(_) => "not_power_of_two",
753 Self::TooLarge(_) => "too_large",
754 }
755 }
756
757 pub fn align(self) -> u64 {
758 let (Self::NotPowerOfTwo(align) | Self::TooLarge(align)) = self;
759 align
760 }
761}
762
763impl fmt::Debug for AlignFromBytesError {
764 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
765 fmt::Display::fmt(self, f)
766 }
767}
768
769impl fmt::Display for AlignFromBytesError {
770 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
771 match self {
772 AlignFromBytesError::NotPowerOfTwo(align) => write!(f, "`{align}` is not a power of 2"),
773 AlignFromBytesError::TooLarge(align) => write!(f, "`{align}` is too large"),
774 }
775 }
776}
777
778impl Align {
779 pub const ONE: Align = Align { pow2: 0 };
780 pub const EIGHT: Align = Align { pow2: 3 };
781 pub const MAX: Align = Align { pow2: 29 };
783
784 #[inline]
785 pub fn from_bits(bits: u64) -> Result<Align, AlignFromBytesError> {
786 Align::from_bytes(Size::from_bits(bits).bytes())
787 }
788
789 #[inline]
790 pub const fn from_bytes(align: u64) -> Result<Align, AlignFromBytesError> {
791 if align == 0 {
793 return Ok(Align::ONE);
794 }
795
796 #[cold]
797 const fn not_power_of_2(align: u64) -> AlignFromBytesError {
798 AlignFromBytesError::NotPowerOfTwo(align)
799 }
800
801 #[cold]
802 const fn too_large(align: u64) -> AlignFromBytesError {
803 AlignFromBytesError::TooLarge(align)
804 }
805
806 let tz = align.trailing_zeros();
807 if align != (1 << tz) {
808 return Err(not_power_of_2(align));
809 }
810
811 let pow2 = tz as u8;
812 if pow2 > Self::MAX.pow2 {
813 return Err(too_large(align));
814 }
815
816 Ok(Align { pow2 })
817 }
818
819 #[inline]
820 pub const fn bytes(self) -> u64 {
821 1 << self.pow2
822 }
823
824 #[inline]
825 pub fn bytes_usize(self) -> usize {
826 self.bytes().try_into().unwrap()
827 }
828
829 #[inline]
830 pub const fn bits(self) -> u64 {
831 self.bytes() * 8
832 }
833
834 #[inline]
835 pub fn bits_usize(self) -> usize {
836 self.bits().try_into().unwrap()
837 }
838
839 #[inline]
844 pub fn max_aligned_factor(size: Size) -> Align {
845 Align { pow2: size.bytes().trailing_zeros() as u8 }
846 }
847
848 #[inline]
850 pub fn restrict_for_offset(self, size: Size) -> Align {
851 self.min(Align::max_aligned_factor(size))
852 }
853}
854
855#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
865#[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
866pub struct AbiAlign {
867 pub abi: Align,
868}
869
870impl AbiAlign {
871 #[inline]
872 pub fn new(align: Align) -> AbiAlign {
873 AbiAlign { abi: align }
874 }
875
876 #[inline]
877 pub fn min(self, other: AbiAlign) -> AbiAlign {
878 AbiAlign { abi: self.abi.min(other.abi) }
879 }
880
881 #[inline]
882 pub fn max(self, other: AbiAlign) -> AbiAlign {
883 AbiAlign { abi: self.abi.max(other.abi) }
884 }
885}
886
887impl Deref for AbiAlign {
888 type Target = Align;
889
890 fn deref(&self) -> &Self::Target {
891 &self.abi
892 }
893}
894
895#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
897#[cfg_attr(
898 feature = "nightly",
899 derive(Encodable_NoContext, Decodable_NoContext, HashStable_Generic)
900)]
901pub enum Integer {
902 I8,
903 I16,
904 I32,
905 I64,
906 I128,
907}
908
909impl Integer {
910 pub fn int_ty_str(self) -> &'static str {
911 use Integer::*;
912 match self {
913 I8 => "i8",
914 I16 => "i16",
915 I32 => "i32",
916 I64 => "i64",
917 I128 => "i128",
918 }
919 }
920
921 pub fn uint_ty_str(self) -> &'static str {
922 use Integer::*;
923 match self {
924 I8 => "u8",
925 I16 => "u16",
926 I32 => "u32",
927 I64 => "u64",
928 I128 => "u128",
929 }
930 }
931
932 #[inline]
933 pub fn size(self) -> Size {
934 use Integer::*;
935 match self {
936 I8 => Size::from_bytes(1),
937 I16 => Size::from_bytes(2),
938 I32 => Size::from_bytes(4),
939 I64 => Size::from_bytes(8),
940 I128 => Size::from_bytes(16),
941 }
942 }
943
944 pub fn from_attr<C: HasDataLayout>(cx: &C, ity: IntegerType) -> Integer {
946 let dl = cx.data_layout();
947
948 match ity {
949 IntegerType::Pointer(_) => dl.ptr_sized_integer(),
950 IntegerType::Fixed(x, _) => x,
951 }
952 }
953
954 pub fn align<C: HasDataLayout>(self, cx: &C) -> AbiAlign {
955 use Integer::*;
956 let dl = cx.data_layout();
957
958 match self {
959 I8 => dl.i8_align,
960 I16 => dl.i16_align,
961 I32 => dl.i32_align,
962 I64 => dl.i64_align,
963 I128 => dl.i128_align,
964 }
965 }
966
967 #[inline]
969 pub fn signed_max(self) -> i128 {
970 use Integer::*;
971 match self {
972 I8 => i8::MAX as i128,
973 I16 => i16::MAX as i128,
974 I32 => i32::MAX as i128,
975 I64 => i64::MAX as i128,
976 I128 => i128::MAX,
977 }
978 }
979
980 #[inline]
982 pub fn fit_signed(x: i128) -> Integer {
983 use Integer::*;
984 match x {
985 -0x0000_0000_0000_0080..=0x0000_0000_0000_007f => I8,
986 -0x0000_0000_0000_8000..=0x0000_0000_0000_7fff => I16,
987 -0x0000_0000_8000_0000..=0x0000_0000_7fff_ffff => I32,
988 -0x8000_0000_0000_0000..=0x7fff_ffff_ffff_ffff => I64,
989 _ => I128,
990 }
991 }
992
993 #[inline]
995 pub fn fit_unsigned(x: u128) -> Integer {
996 use Integer::*;
997 match x {
998 0..=0x0000_0000_0000_00ff => I8,
999 0..=0x0000_0000_0000_ffff => I16,
1000 0..=0x0000_0000_ffff_ffff => I32,
1001 0..=0xffff_ffff_ffff_ffff => I64,
1002 _ => I128,
1003 }
1004 }
1005
1006 pub fn for_align<C: HasDataLayout>(cx: &C, wanted: Align) -> Option<Integer> {
1008 use Integer::*;
1009 let dl = cx.data_layout();
1010
1011 [I8, I16, I32, I64, I128].into_iter().find(|&candidate| {
1012 wanted == candidate.align(dl).abi && wanted.bytes() == candidate.size().bytes()
1013 })
1014 }
1015
1016 pub fn approximate_align<C: HasDataLayout>(cx: &C, wanted: Align) -> Integer {
1018 use Integer::*;
1019 let dl = cx.data_layout();
1020
1021 for candidate in [I64, I32, I16] {
1023 if wanted >= candidate.align(dl).abi && wanted.bytes() >= candidate.size().bytes() {
1024 return candidate;
1025 }
1026 }
1027 I8
1028 }
1029
1030 #[inline]
1033 pub fn from_size(size: Size) -> Result<Self, String> {
1034 match size.bits() {
1035 8 => Ok(Integer::I8),
1036 16 => Ok(Integer::I16),
1037 32 => Ok(Integer::I32),
1038 64 => Ok(Integer::I64),
1039 128 => Ok(Integer::I128),
1040 _ => Err(format!("rust does not support integers with {} bits", size.bits())),
1041 }
1042 }
1043}
1044
1045#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
1047#[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
1048pub enum Float {
1049 F16,
1050 F32,
1051 F64,
1052 F128,
1053}
1054
1055impl Float {
1056 pub fn size(self) -> Size {
1057 use Float::*;
1058
1059 match self {
1060 F16 => Size::from_bits(16),
1061 F32 => Size::from_bits(32),
1062 F64 => Size::from_bits(64),
1063 F128 => Size::from_bits(128),
1064 }
1065 }
1066
1067 pub fn align<C: HasDataLayout>(self, cx: &C) -> AbiAlign {
1068 use Float::*;
1069 let dl = cx.data_layout();
1070
1071 match self {
1072 F16 => dl.f16_align,
1073 F32 => dl.f32_align,
1074 F64 => dl.f64_align,
1075 F128 => dl.f128_align,
1076 }
1077 }
1078}
1079
1080#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
1082#[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
1083pub enum Primitive {
1084 Int(Integer, bool),
1092 Float(Float),
1093 Pointer(AddressSpace),
1094}
1095
1096impl Primitive {
1097 pub fn size<C: HasDataLayout>(self, cx: &C) -> Size {
1098 use Primitive::*;
1099 let dl = cx.data_layout();
1100
1101 match self {
1102 Int(i, _) => i.size(),
1103 Float(f) => f.size(),
1104 Pointer(_) => dl.pointer_size,
1108 }
1109 }
1110
1111 pub fn align<C: HasDataLayout>(self, cx: &C) -> AbiAlign {
1112 use Primitive::*;
1113 let dl = cx.data_layout();
1114
1115 match self {
1116 Int(i, _) => i.align(dl),
1117 Float(f) => f.align(dl),
1118 Pointer(_) => dl.pointer_align,
1122 }
1123 }
1124}
1125
1126#[derive(Clone, Copy, PartialEq, Eq, Hash)]
1136#[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
1137pub struct WrappingRange {
1138 pub start: u128,
1139 pub end: u128,
1140}
1141
1142impl WrappingRange {
1143 pub fn full(size: Size) -> Self {
1144 Self { start: 0, end: size.unsigned_int_max() }
1145 }
1146
1147 #[inline(always)]
1149 pub fn contains(&self, v: u128) -> bool {
1150 if self.start <= self.end {
1151 self.start <= v && v <= self.end
1152 } else {
1153 self.start <= v || v <= self.end
1154 }
1155 }
1156
1157 #[inline(always)]
1159 fn with_start(mut self, start: u128) -> Self {
1160 self.start = start;
1161 self
1162 }
1163
1164 #[inline(always)]
1166 fn with_end(mut self, end: u128) -> Self {
1167 self.end = end;
1168 self
1169 }
1170
1171 #[inline]
1173 fn is_full_for(&self, size: Size) -> bool {
1174 let max_value = size.unsigned_int_max();
1175 debug_assert!(self.start <= max_value && self.end <= max_value);
1176 self.start == (self.end.wrapping_add(1) & max_value)
1177 }
1178}
1179
1180impl fmt::Debug for WrappingRange {
1181 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
1182 if self.start > self.end {
1183 write!(fmt, "(..={}) | ({}..)", self.end, self.start)?;
1184 } else {
1185 write!(fmt, "{}..={}", self.start, self.end)?;
1186 }
1187 Ok(())
1188 }
1189}
1190
1191#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
1193#[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
1194pub enum Scalar {
1195 Initialized {
1196 value: Primitive,
1197
1198 valid_range: WrappingRange,
1202 },
1203 Union {
1204 value: Primitive,
1210 },
1211}
1212
1213impl Scalar {
1214 #[inline]
1215 pub fn is_bool(&self) -> bool {
1216 use Integer::*;
1217 matches!(
1218 self,
1219 Scalar::Initialized {
1220 value: Primitive::Int(I8, false),
1221 valid_range: WrappingRange { start: 0, end: 1 }
1222 }
1223 )
1224 }
1225
1226 pub fn primitive(&self) -> Primitive {
1229 match *self {
1230 Scalar::Initialized { value, .. } | Scalar::Union { value } => value,
1231 }
1232 }
1233
1234 pub fn align(self, cx: &impl HasDataLayout) -> AbiAlign {
1235 self.primitive().align(cx)
1236 }
1237
1238 pub fn size(self, cx: &impl HasDataLayout) -> Size {
1239 self.primitive().size(cx)
1240 }
1241
1242 #[inline]
1243 pub fn to_union(&self) -> Self {
1244 Self::Union { value: self.primitive() }
1245 }
1246
1247 #[inline]
1248 pub fn valid_range(&self, cx: &impl HasDataLayout) -> WrappingRange {
1249 match *self {
1250 Scalar::Initialized { valid_range, .. } => valid_range,
1251 Scalar::Union { value } => WrappingRange::full(value.size(cx)),
1252 }
1253 }
1254
1255 #[inline]
1256 pub fn valid_range_mut(&mut self) -> &mut WrappingRange {
1259 match self {
1260 Scalar::Initialized { valid_range, .. } => valid_range,
1261 Scalar::Union { .. } => panic!("cannot change the valid range of a union"),
1262 }
1263 }
1264
1265 #[inline]
1268 pub fn is_always_valid<C: HasDataLayout>(&self, cx: &C) -> bool {
1269 match *self {
1270 Scalar::Initialized { valid_range, .. } => valid_range.is_full_for(self.size(cx)),
1271 Scalar::Union { .. } => true,
1272 }
1273 }
1274
1275 #[inline]
1277 pub fn is_uninit_valid(&self) -> bool {
1278 match *self {
1279 Scalar::Initialized { .. } => false,
1280 Scalar::Union { .. } => true,
1281 }
1282 }
1283
1284 #[inline]
1286 pub fn is_signed(&self) -> bool {
1287 match self.primitive() {
1288 Primitive::Int(_, signed) => signed,
1289 _ => false,
1290 }
1291 }
1292}
1293
1294#[derive(PartialEq, Eq, Hash, Clone, Debug)]
1297#[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
1298pub enum FieldsShape<FieldIdx: Idx> {
1299 Primitive,
1301
1302 Union(NonZeroUsize),
1304
1305 Array { stride: Size, count: u64 },
1307
1308 Arbitrary {
1316 offsets: IndexVec<FieldIdx, Size>,
1321
1322 memory_index: IndexVec<FieldIdx, u32>,
1335 },
1336}
1337
1338impl<FieldIdx: Idx> FieldsShape<FieldIdx> {
1339 #[inline]
1340 pub fn count(&self) -> usize {
1341 match *self {
1342 FieldsShape::Primitive => 0,
1343 FieldsShape::Union(count) => count.get(),
1344 FieldsShape::Array { count, .. } => count.try_into().unwrap(),
1345 FieldsShape::Arbitrary { ref offsets, .. } => offsets.len(),
1346 }
1347 }
1348
1349 #[inline]
1350 pub fn offset(&self, i: usize) -> Size {
1351 match *self {
1352 FieldsShape::Primitive => {
1353 unreachable!("FieldsShape::offset: `Primitive`s have no fields")
1354 }
1355 FieldsShape::Union(count) => {
1356 assert!(i < count.get(), "tried to access field {i} of union with {count} fields");
1357 Size::ZERO
1358 }
1359 FieldsShape::Array { stride, count } => {
1360 let i = u64::try_from(i).unwrap();
1361 assert!(i < count, "tried to access field {i} of array with {count} fields");
1362 stride * i
1363 }
1364 FieldsShape::Arbitrary { ref offsets, .. } => offsets[FieldIdx::new(i)],
1365 }
1366 }
1367
1368 #[inline]
1369 pub fn memory_index(&self, i: usize) -> usize {
1370 match *self {
1371 FieldsShape::Primitive => {
1372 unreachable!("FieldsShape::memory_index: `Primitive`s have no fields")
1373 }
1374 FieldsShape::Union(_) | FieldsShape::Array { .. } => i,
1375 FieldsShape::Arbitrary { ref memory_index, .. } => {
1376 memory_index[FieldIdx::new(i)].try_into().unwrap()
1377 }
1378 }
1379 }
1380
1381 #[inline]
1383 pub fn index_by_increasing_offset(&self) -> impl ExactSizeIterator<Item = usize> {
1384 let mut inverse_small = [0u8; 64];
1385 let mut inverse_big = IndexVec::new();
1386 let use_small = self.count() <= inverse_small.len();
1387
1388 if let FieldsShape::Arbitrary { ref memory_index, .. } = *self {
1390 if use_small {
1391 for (field_idx, &mem_idx) in memory_index.iter_enumerated() {
1392 inverse_small[mem_idx as usize] = field_idx.index() as u8;
1393 }
1394 } else {
1395 inverse_big = memory_index.invert_bijective_mapping();
1396 }
1397 }
1398
1399 let pseudofield_count = if let FieldsShape::Primitive = self { 1 } else { self.count() };
1403
1404 (0..pseudofield_count).map(move |i| match *self {
1405 FieldsShape::Primitive | FieldsShape::Union(_) | FieldsShape::Array { .. } => i,
1406 FieldsShape::Arbitrary { .. } => {
1407 if use_small {
1408 inverse_small[i] as usize
1409 } else {
1410 inverse_big[i as u32].index()
1411 }
1412 }
1413 })
1414 }
1415}
1416
1417#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
1421#[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
1422pub struct AddressSpace(pub u32);
1423
1424impl AddressSpace {
1425 pub const DATA: Self = AddressSpace(0);
1427}
1428
1429#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
1440#[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
1441pub enum BackendRepr {
1442 Scalar(Scalar),
1443 ScalarPair(Scalar, Scalar),
1444 SimdVector {
1445 element: Scalar,
1446 count: u64,
1447 },
1448 Memory {
1450 sized: bool,
1452 },
1453}
1454
1455impl BackendRepr {
1456 #[inline]
1458 pub fn is_unsized(&self) -> bool {
1459 match *self {
1460 BackendRepr::Scalar(_)
1461 | BackendRepr::ScalarPair(..)
1462 | BackendRepr::SimdVector { .. } => false,
1463 BackendRepr::Memory { sized } => !sized,
1464 }
1465 }
1466
1467 #[inline]
1468 pub fn is_sized(&self) -> bool {
1469 !self.is_unsized()
1470 }
1471
1472 #[inline]
1475 pub fn is_signed(&self) -> bool {
1476 match self {
1477 BackendRepr::Scalar(scal) => scal.is_signed(),
1478 _ => panic!("`is_signed` on non-scalar ABI {self:?}"),
1479 }
1480 }
1481
1482 #[inline]
1484 pub fn is_scalar(&self) -> bool {
1485 matches!(*self, BackendRepr::Scalar(_))
1486 }
1487
1488 #[inline]
1490 pub fn is_bool(&self) -> bool {
1491 matches!(*self, BackendRepr::Scalar(s) if s.is_bool())
1492 }
1493
1494 pub fn scalar_align<C: HasDataLayout>(&self, cx: &C) -> Option<Align> {
1498 match *self {
1499 BackendRepr::Scalar(s) => Some(s.align(cx).abi),
1500 BackendRepr::ScalarPair(s1, s2) => Some(s1.align(cx).max(s2.align(cx)).abi),
1501 BackendRepr::SimdVector { .. } | BackendRepr::Memory { .. } => None,
1503 }
1504 }
1505
1506 pub fn scalar_size<C: HasDataLayout>(&self, cx: &C) -> Option<Size> {
1510 match *self {
1511 BackendRepr::Scalar(s) => Some(s.size(cx)),
1513 BackendRepr::ScalarPair(s1, s2) => {
1515 let field2_offset = s1.size(cx).align_to(s2.align(cx).abi);
1516 let size = (field2_offset + s2.size(cx)).align_to(
1517 self.scalar_align(cx)
1518 .unwrap(),
1520 );
1521 Some(size)
1522 }
1523 BackendRepr::SimdVector { .. } | BackendRepr::Memory { .. } => None,
1525 }
1526 }
1527
1528 pub fn to_union(&self) -> Self {
1530 match *self {
1531 BackendRepr::Scalar(s) => BackendRepr::Scalar(s.to_union()),
1532 BackendRepr::ScalarPair(s1, s2) => {
1533 BackendRepr::ScalarPair(s1.to_union(), s2.to_union())
1534 }
1535 BackendRepr::SimdVector { element, count } => {
1536 BackendRepr::SimdVector { element: element.to_union(), count }
1537 }
1538 BackendRepr::Memory { .. } => BackendRepr::Memory { sized: true },
1539 }
1540 }
1541
1542 pub fn eq_up_to_validity(&self, other: &Self) -> bool {
1543 match (self, other) {
1544 (BackendRepr::Scalar(l), BackendRepr::Scalar(r)) => l.primitive() == r.primitive(),
1547 (
1548 BackendRepr::SimdVector { element: element_l, count: count_l },
1549 BackendRepr::SimdVector { element: element_r, count: count_r },
1550 ) => element_l.primitive() == element_r.primitive() && count_l == count_r,
1551 (BackendRepr::ScalarPair(l1, l2), BackendRepr::ScalarPair(r1, r2)) => {
1552 l1.primitive() == r1.primitive() && l2.primitive() == r2.primitive()
1553 }
1554 _ => self == other,
1556 }
1557 }
1558}
1559
1560#[derive(PartialEq, Eq, Hash, Clone, Debug)]
1562#[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
1563pub enum Variants<FieldIdx: Idx, VariantIdx: Idx> {
1564 Empty,
1566
1567 Single {
1569 index: VariantIdx,
1571 },
1572
1573 Multiple {
1580 tag: Scalar,
1581 tag_encoding: TagEncoding<VariantIdx>,
1582 tag_field: FieldIdx,
1583 variants: IndexVec<VariantIdx, LayoutData<FieldIdx, VariantIdx>>,
1584 },
1585}
1586
1587#[derive(PartialEq, Eq, Hash, Clone, Debug)]
1589#[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
1590pub enum TagEncoding<VariantIdx: Idx> {
1591 Direct,
1594
1595 Niche {
1610 untagged_variant: VariantIdx,
1611 niche_variants: RangeInclusive<VariantIdx>,
1614 niche_start: u128,
1617 },
1618}
1619
1620#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
1621#[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
1622pub struct Niche {
1623 pub offset: Size,
1624 pub value: Primitive,
1625 pub valid_range: WrappingRange,
1626}
1627
1628impl Niche {
1629 pub fn from_scalar<C: HasDataLayout>(cx: &C, offset: Size, scalar: Scalar) -> Option<Self> {
1630 let Scalar::Initialized { value, valid_range } = scalar else { return None };
1631 let niche = Niche { offset, value, valid_range };
1632 if niche.available(cx) > 0 { Some(niche) } else { None }
1633 }
1634
1635 pub fn available<C: HasDataLayout>(&self, cx: &C) -> u128 {
1636 let Self { value, valid_range: v, .. } = *self;
1637 let size = value.size(cx);
1638 assert!(size.bits() <= 128);
1639 let max_value = size.unsigned_int_max();
1640
1641 let niche = v.end.wrapping_add(1)..v.start;
1643 niche.end.wrapping_sub(niche.start) & max_value
1644 }
1645
1646 pub fn reserve<C: HasDataLayout>(&self, cx: &C, count: u128) -> Option<(u128, Scalar)> {
1647 assert!(count > 0);
1648
1649 let Self { value, valid_range: v, .. } = *self;
1650 let size = value.size(cx);
1651 assert!(size.bits() <= 128);
1652 let max_value = size.unsigned_int_max();
1653
1654 let niche = v.end.wrapping_add(1)..v.start;
1655 let available = niche.end.wrapping_sub(niche.start) & max_value;
1656 if count > available {
1657 return None;
1658 }
1659
1660 let move_start = |v: WrappingRange| {
1674 let start = v.start.wrapping_sub(count) & max_value;
1675 Some((start, Scalar::Initialized { value, valid_range: v.with_start(start) }))
1676 };
1677 let move_end = |v: WrappingRange| {
1678 let start = v.end.wrapping_add(1) & max_value;
1679 let end = v.end.wrapping_add(count) & max_value;
1680 Some((start, Scalar::Initialized { value, valid_range: v.with_end(end) }))
1681 };
1682 let distance_end_zero = max_value - v.end;
1683 if v.start > v.end {
1684 move_end(v)
1686 } else if v.start <= distance_end_zero {
1687 if count <= v.start {
1688 move_start(v)
1689 } else {
1690 move_end(v)
1692 }
1693 } else {
1694 let end = v.end.wrapping_add(count) & max_value;
1695 let overshot_zero = (1..=v.end).contains(&end);
1696 if overshot_zero {
1697 move_start(v)
1699 } else {
1700 move_end(v)
1701 }
1702 }
1703 }
1704}
1705
1706#[derive(PartialEq, Eq, Hash, Clone)]
1708#[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
1709pub struct LayoutData<FieldIdx: Idx, VariantIdx: Idx> {
1710 pub fields: FieldsShape<FieldIdx>,
1712
1713 pub variants: Variants<FieldIdx, VariantIdx>,
1721
1722 pub backend_repr: BackendRepr,
1730
1731 pub largest_niche: Option<Niche>,
1734 pub uninhabited: bool,
1739
1740 pub align: AbiAlign,
1741 pub size: Size,
1742
1743 pub max_repr_align: Option<Align>,
1747
1748 pub unadjusted_abi_align: Align,
1752
1753 pub randomization_seed: Hash64,
1764}
1765
1766impl<FieldIdx: Idx, VariantIdx: Idx> LayoutData<FieldIdx, VariantIdx> {
1767 pub fn is_aggregate(&self) -> bool {
1769 match self.backend_repr {
1770 BackendRepr::Scalar(_) | BackendRepr::SimdVector { .. } => false,
1771 BackendRepr::ScalarPair(..) | BackendRepr::Memory { .. } => true,
1772 }
1773 }
1774
1775 pub fn is_uninhabited(&self) -> bool {
1777 self.uninhabited
1778 }
1779}
1780
1781impl<FieldIdx: Idx, VariantIdx: Idx> fmt::Debug for LayoutData<FieldIdx, VariantIdx>
1782where
1783 FieldsShape<FieldIdx>: fmt::Debug,
1784 Variants<FieldIdx, VariantIdx>: fmt::Debug,
1785{
1786 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1787 let LayoutData {
1791 size,
1792 align,
1793 backend_repr,
1794 fields,
1795 largest_niche,
1796 uninhabited,
1797 variants,
1798 max_repr_align,
1799 unadjusted_abi_align,
1800 randomization_seed,
1801 } = self;
1802 f.debug_struct("Layout")
1803 .field("size", size)
1804 .field("align", align)
1805 .field("backend_repr", backend_repr)
1806 .field("fields", fields)
1807 .field("largest_niche", largest_niche)
1808 .field("uninhabited", uninhabited)
1809 .field("variants", variants)
1810 .field("max_repr_align", max_repr_align)
1811 .field("unadjusted_abi_align", unadjusted_abi_align)
1812 .field("randomization_seed", randomization_seed)
1813 .finish()
1814 }
1815}
1816
1817#[derive(Copy, Clone, PartialEq, Eq, Debug)]
1818pub enum PointerKind {
1819 SharedRef { frozen: bool },
1821 MutableRef { unpin: bool },
1823 Box { unpin: bool, global: bool },
1826}
1827
1828#[derive(Copy, Clone, Debug)]
1833pub struct PointeeInfo {
1834 pub safe: Option<PointerKind>,
1837 pub size: Size,
1843 pub align: Align,
1845}
1846
1847impl<FieldIdx: Idx, VariantIdx: Idx> LayoutData<FieldIdx, VariantIdx> {
1848 #[inline]
1850 pub fn is_unsized(&self) -> bool {
1851 self.backend_repr.is_unsized()
1852 }
1853
1854 #[inline]
1855 pub fn is_sized(&self) -> bool {
1856 self.backend_repr.is_sized()
1857 }
1858
1859 pub fn is_1zst(&self) -> bool {
1861 self.is_sized() && self.size.bytes() == 0 && self.align.abi.bytes() == 1
1862 }
1863
1864 pub fn is_zst(&self) -> bool {
1869 match self.backend_repr {
1870 BackendRepr::Scalar(_)
1871 | BackendRepr::ScalarPair(..)
1872 | BackendRepr::SimdVector { .. } => false,
1873 BackendRepr::Memory { sized } => sized && self.size.bytes() == 0,
1874 }
1875 }
1876
1877 pub fn eq_abi(&self, other: &Self) -> bool {
1883 self.size == other.size
1887 && self.is_sized() == other.is_sized()
1888 && self.backend_repr.eq_up_to_validity(&other.backend_repr)
1889 && self.backend_repr.is_bool() == other.backend_repr.is_bool()
1890 && self.align.abi == other.align.abi
1891 && self.max_repr_align == other.max_repr_align
1892 && self.unadjusted_abi_align == other.unadjusted_abi_align
1893 }
1894}
1895
1896#[derive(Copy, Clone, Debug)]
1897pub enum StructKind {
1898 AlwaysSized,
1900 MaybeUnsized,
1902 Prefixed(Size, Align),
1904}
1905
1906#[derive(Clone, Debug)]
1907pub enum AbiFromStrErr {
1908 Unknown,
1910 NoExplicitUnwind,
1912}