]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_abi/src/lib.rs
Rollup merge of #104675 - SarthakSingh31:issue-101666, r=jyn514
[rust.git] / compiler / rustc_abi / src / lib.rs
1 #![cfg_attr(feature = "nightly", feature(step_trait, rustc_attrs, min_specialization))]
2
3 use std::convert::{TryFrom, TryInto};
4 use std::fmt;
5 #[cfg(feature = "nightly")]
6 use std::iter::Step;
7 use std::num::{NonZeroUsize, ParseIntError};
8 use std::ops::{Add, AddAssign, Mul, RangeInclusive, Sub};
9 use std::str::FromStr;
10
11 use bitflags::bitflags;
12 use rustc_index::vec::{Idx, IndexVec};
13 #[cfg(feature = "nightly")]
14 use rustc_macros::HashStable_Generic;
15 #[cfg(feature = "nightly")]
16 use rustc_macros::{Decodable, Encodable};
17
18 mod layout;
19
20 pub use layout::LayoutCalculator;
21
22 /// Requirements for a `StableHashingContext` to be used in this crate.
23 /// This is a hack to allow using the `HashStable_Generic` derive macro
24 /// instead of implementing everything in `rustc_middle`.
25 pub trait HashStableContext {}
26
27 use Integer::*;
28 use Primitive::*;
29
30 bitflags! {
31     #[derive(Default)]
32     #[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_Generic))]
33     pub struct ReprFlags: u8 {
34         const IS_C               = 1 << 0;
35         const IS_SIMD            = 1 << 1;
36         const IS_TRANSPARENT     = 1 << 2;
37         // Internal only for now. If true, don't reorder fields.
38         const IS_LINEAR          = 1 << 3;
39         // If true, the type's layout can be randomized using
40         // the seed stored in `ReprOptions.layout_seed`
41         const RANDOMIZE_LAYOUT   = 1 << 4;
42         // Any of these flags being set prevent field reordering optimisation.
43         const IS_UNOPTIMISABLE   = ReprFlags::IS_C.bits
44                                  | ReprFlags::IS_SIMD.bits
45                                  | ReprFlags::IS_LINEAR.bits;
46     }
47 }
48
49 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
50 #[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_Generic))]
51 pub enum IntegerType {
52     /// Pointer sized integer type, i.e. isize and usize. The field shows signedness, that
53     /// is, `Pointer(true)` is isize.
54     Pointer(bool),
55     /// Fix sized integer type, e.g. i8, u32, i128 The bool field shows signedness, `Fixed(I8, false)` means `u8`
56     Fixed(Integer, bool),
57 }
58
59 impl IntegerType {
60     pub fn is_signed(&self) -> bool {
61         match self {
62             IntegerType::Pointer(b) => *b,
63             IntegerType::Fixed(_, b) => *b,
64         }
65     }
66 }
67
68 /// Represents the repr options provided by the user,
69 #[derive(Copy, Clone, Debug, Eq, PartialEq, Default)]
70 #[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_Generic))]
71 pub struct ReprOptions {
72     pub int: Option<IntegerType>,
73     pub align: Option<Align>,
74     pub pack: Option<Align>,
75     pub flags: ReprFlags,
76     /// The seed to be used for randomizing a type's layout
77     ///
78     /// Note: This could technically be a `[u8; 16]` (a `u128`) which would
79     /// be the "most accurate" hash as it'd encompass the item and crate
80     /// hash without loss, but it does pay the price of being larger.
81     /// Everything's a tradeoff, a `u64` seed should be sufficient for our
82     /// purposes (primarily `-Z randomize-layout`)
83     pub field_shuffle_seed: u64,
84 }
85
86 impl ReprOptions {
87     #[inline]
88     pub fn simd(&self) -> bool {
89         self.flags.contains(ReprFlags::IS_SIMD)
90     }
91
92     #[inline]
93     pub fn c(&self) -> bool {
94         self.flags.contains(ReprFlags::IS_C)
95     }
96
97     #[inline]
98     pub fn packed(&self) -> bool {
99         self.pack.is_some()
100     }
101
102     #[inline]
103     pub fn transparent(&self) -> bool {
104         self.flags.contains(ReprFlags::IS_TRANSPARENT)
105     }
106
107     #[inline]
108     pub fn linear(&self) -> bool {
109         self.flags.contains(ReprFlags::IS_LINEAR)
110     }
111
112     /// Returns the discriminant type, given these `repr` options.
113     /// This must only be called on enums!
114     pub fn discr_type(&self) -> IntegerType {
115         self.int.unwrap_or(IntegerType::Pointer(true))
116     }
117
118     /// Returns `true` if this `#[repr()]` should inhabit "smart enum
119     /// layout" optimizations, such as representing `Foo<&T>` as a
120     /// single pointer.
121     pub fn inhibit_enum_layout_opt(&self) -> bool {
122         self.c() || self.int.is_some()
123     }
124
125     /// Returns `true` if this `#[repr()]` should inhibit struct field reordering
126     /// optimizations, such as with `repr(C)`, `repr(packed(1))`, or `repr(<int>)`.
127     pub fn inhibit_struct_field_reordering_opt(&self) -> bool {
128         if let Some(pack) = self.pack {
129             if pack.bytes() == 1 {
130                 return true;
131             }
132         }
133
134         self.flags.intersects(ReprFlags::IS_UNOPTIMISABLE) || self.int.is_some()
135     }
136
137     /// Returns `true` if this type is valid for reordering and `-Z randomize-layout`
138     /// was enabled for its declaration crate
139     pub fn can_randomize_type_layout(&self) -> bool {
140         !self.inhibit_struct_field_reordering_opt()
141             && self.flags.contains(ReprFlags::RANDOMIZE_LAYOUT)
142     }
143
144     /// Returns `true` if this `#[repr()]` should inhibit union ABI optimisations.
145     pub fn inhibit_union_abi_opt(&self) -> bool {
146         self.c()
147     }
148 }
149
150 /// Parsed [Data layout](https://llvm.org/docs/LangRef.html#data-layout)
151 /// for a target, which contains everything needed to compute layouts.
152 #[derive(Debug, PartialEq, Eq)]
153 pub struct TargetDataLayout {
154     pub endian: Endian,
155     pub i1_align: AbiAndPrefAlign,
156     pub i8_align: AbiAndPrefAlign,
157     pub i16_align: AbiAndPrefAlign,
158     pub i32_align: AbiAndPrefAlign,
159     pub i64_align: AbiAndPrefAlign,
160     pub i128_align: AbiAndPrefAlign,
161     pub f32_align: AbiAndPrefAlign,
162     pub f64_align: AbiAndPrefAlign,
163     pub pointer_size: Size,
164     pub pointer_align: AbiAndPrefAlign,
165     pub aggregate_align: AbiAndPrefAlign,
166
167     /// Alignments for vector types.
168     pub vector_align: Vec<(Size, AbiAndPrefAlign)>,
169
170     pub instruction_address_space: AddressSpace,
171
172     /// Minimum size of #[repr(C)] enums (default I32 bits)
173     pub c_enum_min_size: Integer,
174 }
175
176 impl Default for TargetDataLayout {
177     /// Creates an instance of `TargetDataLayout`.
178     fn default() -> TargetDataLayout {
179         let align = |bits| Align::from_bits(bits).unwrap();
180         TargetDataLayout {
181             endian: Endian::Big,
182             i1_align: AbiAndPrefAlign::new(align(8)),
183             i8_align: AbiAndPrefAlign::new(align(8)),
184             i16_align: AbiAndPrefAlign::new(align(16)),
185             i32_align: AbiAndPrefAlign::new(align(32)),
186             i64_align: AbiAndPrefAlign { abi: align(32), pref: align(64) },
187             i128_align: AbiAndPrefAlign { abi: align(32), pref: align(64) },
188             f32_align: AbiAndPrefAlign::new(align(32)),
189             f64_align: AbiAndPrefAlign::new(align(64)),
190             pointer_size: Size::from_bits(64),
191             pointer_align: AbiAndPrefAlign::new(align(64)),
192             aggregate_align: AbiAndPrefAlign { abi: align(0), pref: align(64) },
193             vector_align: vec![
194                 (Size::from_bits(64), AbiAndPrefAlign::new(align(64))),
195                 (Size::from_bits(128), AbiAndPrefAlign::new(align(128))),
196             ],
197             instruction_address_space: AddressSpace::DATA,
198             c_enum_min_size: Integer::I32,
199         }
200     }
201 }
202
203 pub enum TargetDataLayoutErrors<'a> {
204     InvalidAddressSpace { addr_space: &'a str, cause: &'a str, err: ParseIntError },
205     InvalidBits { kind: &'a str, bit: &'a str, cause: &'a str, err: ParseIntError },
206     MissingAlignment { cause: &'a str },
207     InvalidAlignment { cause: &'a str, err: String },
208     InconsistentTargetArchitecture { dl: &'a str, target: &'a str },
209     InconsistentTargetPointerWidth { pointer_size: u64, target: u32 },
210     InvalidBitsSize { err: String },
211 }
212
213 impl TargetDataLayout {
214     /// Returns exclusive upper bound on object size.
215     ///
216     /// The theoretical maximum object size is defined as the maximum positive `isize` value.
217     /// This ensures that the `offset` semantics remain well-defined by allowing it to correctly
218     /// index every address within an object along with one byte past the end, along with allowing
219     /// `isize` to store the difference between any two pointers into an object.
220     ///
221     /// The upper bound on 64-bit currently needs to be lower because LLVM uses a 64-bit integer
222     /// to represent object size in bits. It would need to be 1 << 61 to account for this, but is
223     /// currently conservatively bounded to 1 << 47 as that is enough to cover the current usable
224     /// address space on 64-bit ARMv8 and x86_64.
225     #[inline]
226     pub fn obj_size_bound(&self) -> u64 {
227         match self.pointer_size.bits() {
228             16 => 1 << 15,
229             32 => 1 << 31,
230             64 => 1 << 47,
231             bits => panic!("obj_size_bound: unknown pointer bit size {}", bits),
232         }
233     }
234
235     #[inline]
236     pub fn ptr_sized_integer(&self) -> Integer {
237         match self.pointer_size.bits() {
238             16 => I16,
239             32 => I32,
240             64 => I64,
241             bits => panic!("ptr_sized_integer: unknown pointer bit size {}", bits),
242         }
243     }
244
245     #[inline]
246     pub fn vector_align(&self, vec_size: Size) -> AbiAndPrefAlign {
247         for &(size, align) in &self.vector_align {
248             if size == vec_size {
249                 return align;
250             }
251         }
252         // Default to natural alignment, which is what LLVM does.
253         // That is, use the size, rounded up to a power of 2.
254         AbiAndPrefAlign::new(Align::from_bytes(vec_size.bytes().next_power_of_two()).unwrap())
255     }
256 }
257
258 pub trait HasDataLayout {
259     fn data_layout(&self) -> &TargetDataLayout;
260 }
261
262 impl HasDataLayout for TargetDataLayout {
263     #[inline]
264     fn data_layout(&self) -> &TargetDataLayout {
265         self
266     }
267 }
268
269 /// Endianness of the target, which must match cfg(target-endian).
270 #[derive(Copy, Clone, PartialEq, Eq)]
271 pub enum Endian {
272     Little,
273     Big,
274 }
275
276 impl Endian {
277     pub fn as_str(&self) -> &'static str {
278         match self {
279             Self::Little => "little",
280             Self::Big => "big",
281         }
282     }
283 }
284
285 impl fmt::Debug for Endian {
286     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
287         f.write_str(self.as_str())
288     }
289 }
290
291 impl FromStr for Endian {
292     type Err = String;
293
294     fn from_str(s: &str) -> Result<Self, Self::Err> {
295         match s {
296             "little" => Ok(Self::Little),
297             "big" => Ok(Self::Big),
298             _ => Err(format!(r#"unknown endian: "{}""#, s)),
299         }
300     }
301 }
302
303 /// Size of a type in bytes.
304 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
305 #[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_Generic))]
306 pub struct Size {
307     raw: u64,
308 }
309
310 // This is debug-printed a lot in larger structs, don't waste too much space there
311 impl fmt::Debug for Size {
312     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
313         write!(f, "Size({} bytes)", self.bytes())
314     }
315 }
316
317 impl Size {
318     pub const ZERO: Size = Size { raw: 0 };
319
320     /// Rounds `bits` up to the next-higher byte boundary, if `bits` is
321     /// not a multiple of 8.
322     pub fn from_bits(bits: impl TryInto<u64>) -> Size {
323         let bits = bits.try_into().ok().unwrap();
324         // Avoid potential overflow from `bits + 7`.
325         Size { raw: bits / 8 + ((bits % 8) + 7) / 8 }
326     }
327
328     #[inline]
329     pub fn from_bytes(bytes: impl TryInto<u64>) -> Size {
330         let bytes: u64 = bytes.try_into().ok().unwrap();
331         Size { raw: bytes }
332     }
333
334     #[inline]
335     pub fn bytes(self) -> u64 {
336         self.raw
337     }
338
339     #[inline]
340     pub fn bytes_usize(self) -> usize {
341         self.bytes().try_into().unwrap()
342     }
343
344     #[inline]
345     pub fn bits(self) -> u64 {
346         #[cold]
347         fn overflow(bytes: u64) -> ! {
348             panic!("Size::bits: {} bytes in bits doesn't fit in u64", bytes)
349         }
350
351         self.bytes().checked_mul(8).unwrap_or_else(|| overflow(self.bytes()))
352     }
353
354     #[inline]
355     pub fn bits_usize(self) -> usize {
356         self.bits().try_into().unwrap()
357     }
358
359     #[inline]
360     pub fn align_to(self, align: Align) -> Size {
361         let mask = align.bytes() - 1;
362         Size::from_bytes((self.bytes() + mask) & !mask)
363     }
364
365     #[inline]
366     pub fn is_aligned(self, align: Align) -> bool {
367         let mask = align.bytes() - 1;
368         self.bytes() & mask == 0
369     }
370
371     #[inline]
372     pub fn checked_add<C: HasDataLayout>(self, offset: Size, cx: &C) -> Option<Size> {
373         let dl = cx.data_layout();
374
375         let bytes = self.bytes().checked_add(offset.bytes())?;
376
377         if bytes < dl.obj_size_bound() { Some(Size::from_bytes(bytes)) } else { None }
378     }
379
380     #[inline]
381     pub fn checked_mul<C: HasDataLayout>(self, count: u64, cx: &C) -> Option<Size> {
382         let dl = cx.data_layout();
383
384         let bytes = self.bytes().checked_mul(count)?;
385         if bytes < dl.obj_size_bound() { Some(Size::from_bytes(bytes)) } else { None }
386     }
387
388     /// Truncates `value` to `self` bits and then sign-extends it to 128 bits
389     /// (i.e., if it is negative, fill with 1's on the left).
390     #[inline]
391     pub fn sign_extend(self, value: u128) -> u128 {
392         let size = self.bits();
393         if size == 0 {
394             // Truncated until nothing is left.
395             return 0;
396         }
397         // Sign-extend it.
398         let shift = 128 - size;
399         // Shift the unsigned value to the left, then shift back to the right as signed
400         // (essentially fills with sign bit on the left).
401         (((value << shift) as i128) >> shift) as u128
402     }
403
404     /// Truncates `value` to `self` bits.
405     #[inline]
406     pub fn truncate(self, value: u128) -> u128 {
407         let size = self.bits();
408         if size == 0 {
409             // Truncated until nothing is left.
410             return 0;
411         }
412         let shift = 128 - size;
413         // Truncate (shift left to drop out leftover values, shift right to fill with zeroes).
414         (value << shift) >> shift
415     }
416
417     #[inline]
418     pub fn signed_int_min(&self) -> i128 {
419         self.sign_extend(1_u128 << (self.bits() - 1)) as i128
420     }
421
422     #[inline]
423     pub fn signed_int_max(&self) -> i128 {
424         i128::MAX >> (128 - self.bits())
425     }
426
427     #[inline]
428     pub fn unsigned_int_max(&self) -> u128 {
429         u128::MAX >> (128 - self.bits())
430     }
431 }
432
433 // Panicking addition, subtraction and multiplication for convenience.
434 // Avoid during layout computation, return `LayoutError` instead.
435
436 impl Add for Size {
437     type Output = Size;
438     #[inline]
439     fn add(self, other: Size) -> Size {
440         Size::from_bytes(self.bytes().checked_add(other.bytes()).unwrap_or_else(|| {
441             panic!("Size::add: {} + {} doesn't fit in u64", self.bytes(), other.bytes())
442         }))
443     }
444 }
445
446 impl Sub for Size {
447     type Output = Size;
448     #[inline]
449     fn sub(self, other: Size) -> Size {
450         Size::from_bytes(self.bytes().checked_sub(other.bytes()).unwrap_or_else(|| {
451             panic!("Size::sub: {} - {} would result in negative size", self.bytes(), other.bytes())
452         }))
453     }
454 }
455
456 impl Mul<Size> for u64 {
457     type Output = Size;
458     #[inline]
459     fn mul(self, size: Size) -> Size {
460         size * self
461     }
462 }
463
464 impl Mul<u64> for Size {
465     type Output = Size;
466     #[inline]
467     fn mul(self, count: u64) -> Size {
468         match self.bytes().checked_mul(count) {
469             Some(bytes) => Size::from_bytes(bytes),
470             None => panic!("Size::mul: {} * {} doesn't fit in u64", self.bytes(), count),
471         }
472     }
473 }
474
475 impl AddAssign for Size {
476     #[inline]
477     fn add_assign(&mut self, other: Size) {
478         *self = *self + other;
479     }
480 }
481
482 #[cfg(feature = "nightly")]
483 impl Step for Size {
484     #[inline]
485     fn steps_between(start: &Self, end: &Self) -> Option<usize> {
486         u64::steps_between(&start.bytes(), &end.bytes())
487     }
488
489     #[inline]
490     fn forward_checked(start: Self, count: usize) -> Option<Self> {
491         u64::forward_checked(start.bytes(), count).map(Self::from_bytes)
492     }
493
494     #[inline]
495     fn forward(start: Self, count: usize) -> Self {
496         Self::from_bytes(u64::forward(start.bytes(), count))
497     }
498
499     #[inline]
500     unsafe fn forward_unchecked(start: Self, count: usize) -> Self {
501         Self::from_bytes(u64::forward_unchecked(start.bytes(), count))
502     }
503
504     #[inline]
505     fn backward_checked(start: Self, count: usize) -> Option<Self> {
506         u64::backward_checked(start.bytes(), count).map(Self::from_bytes)
507     }
508
509     #[inline]
510     fn backward(start: Self, count: usize) -> Self {
511         Self::from_bytes(u64::backward(start.bytes(), count))
512     }
513
514     #[inline]
515     unsafe fn backward_unchecked(start: Self, count: usize) -> Self {
516         Self::from_bytes(u64::backward_unchecked(start.bytes(), count))
517     }
518 }
519
520 /// Alignment of a type in bytes (always a power of two).
521 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
522 #[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_Generic))]
523 pub struct Align {
524     pow2: u8,
525 }
526
527 // This is debug-printed a lot in larger structs, don't waste too much space there
528 impl fmt::Debug for Align {
529     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
530         write!(f, "Align({} bytes)", self.bytes())
531     }
532 }
533
534 impl Align {
535     pub const ONE: Align = Align { pow2: 0 };
536     pub const MAX: Align = Align { pow2: 29 };
537
538     #[inline]
539     pub fn from_bits(bits: u64) -> Result<Align, String> {
540         Align::from_bytes(Size::from_bits(bits).bytes())
541     }
542
543     #[inline]
544     pub fn from_bytes(align: u64) -> Result<Align, String> {
545         // Treat an alignment of 0 bytes like 1-byte alignment.
546         if align == 0 {
547             return Ok(Align::ONE);
548         }
549
550         #[cold]
551         fn not_power_of_2(align: u64) -> String {
552             format!("`{}` is not a power of 2", align)
553         }
554
555         #[cold]
556         fn too_large(align: u64) -> String {
557             format!("`{}` is too large", align)
558         }
559
560         let mut bytes = align;
561         let mut pow2: u8 = 0;
562         while (bytes & 1) == 0 {
563             pow2 += 1;
564             bytes >>= 1;
565         }
566         if bytes != 1 {
567             return Err(not_power_of_2(align));
568         }
569         if pow2 > Self::MAX.pow2 {
570             return Err(too_large(align));
571         }
572
573         Ok(Align { pow2 })
574     }
575
576     #[inline]
577     pub fn bytes(self) -> u64 {
578         1 << self.pow2
579     }
580
581     #[inline]
582     pub fn bits(self) -> u64 {
583         self.bytes() * 8
584     }
585
586     /// Computes the best alignment possible for the given offset
587     /// (the largest power of two that the offset is a multiple of).
588     ///
589     /// N.B., for an offset of `0`, this happens to return `2^64`.
590     #[inline]
591     pub fn max_for_offset(offset: Size) -> Align {
592         Align { pow2: offset.bytes().trailing_zeros() as u8 }
593     }
594
595     /// Lower the alignment, if necessary, such that the given offset
596     /// is aligned to it (the offset is a multiple of the alignment).
597     #[inline]
598     pub fn restrict_for_offset(self, offset: Size) -> Align {
599         self.min(Align::max_for_offset(offset))
600     }
601 }
602
603 /// A pair of alignments, ABI-mandated and preferred.
604 #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
605 #[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
606
607 pub struct AbiAndPrefAlign {
608     pub abi: Align,
609     pub pref: Align,
610 }
611
612 impl AbiAndPrefAlign {
613     #[inline]
614     pub fn new(align: Align) -> AbiAndPrefAlign {
615         AbiAndPrefAlign { abi: align, pref: align }
616     }
617
618     #[inline]
619     pub fn min(self, other: AbiAndPrefAlign) -> AbiAndPrefAlign {
620         AbiAndPrefAlign { abi: self.abi.min(other.abi), pref: self.pref.min(other.pref) }
621     }
622
623     #[inline]
624     pub fn max(self, other: AbiAndPrefAlign) -> AbiAndPrefAlign {
625         AbiAndPrefAlign { abi: self.abi.max(other.abi), pref: self.pref.max(other.pref) }
626     }
627 }
628
629 /// Integers, also used for enum discriminants.
630 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
631 #[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_Generic))]
632
633 pub enum Integer {
634     I8,
635     I16,
636     I32,
637     I64,
638     I128,
639 }
640
641 impl Integer {
642     #[inline]
643     pub fn size(self) -> Size {
644         match self {
645             I8 => Size::from_bytes(1),
646             I16 => Size::from_bytes(2),
647             I32 => Size::from_bytes(4),
648             I64 => Size::from_bytes(8),
649             I128 => Size::from_bytes(16),
650         }
651     }
652
653     /// Gets the Integer type from an IntegerType.
654     pub fn from_attr<C: HasDataLayout>(cx: &C, ity: IntegerType) -> Integer {
655         let dl = cx.data_layout();
656
657         match ity {
658             IntegerType::Pointer(_) => dl.ptr_sized_integer(),
659             IntegerType::Fixed(x, _) => x,
660         }
661     }
662
663     pub fn align<C: HasDataLayout>(self, cx: &C) -> AbiAndPrefAlign {
664         let dl = cx.data_layout();
665
666         match self {
667             I8 => dl.i8_align,
668             I16 => dl.i16_align,
669             I32 => dl.i32_align,
670             I64 => dl.i64_align,
671             I128 => dl.i128_align,
672         }
673     }
674
675     /// Finds the smallest Integer type which can represent the signed value.
676     #[inline]
677     pub fn fit_signed(x: i128) -> Integer {
678         match x {
679             -0x0000_0000_0000_0080..=0x0000_0000_0000_007f => I8,
680             -0x0000_0000_0000_8000..=0x0000_0000_0000_7fff => I16,
681             -0x0000_0000_8000_0000..=0x0000_0000_7fff_ffff => I32,
682             -0x8000_0000_0000_0000..=0x7fff_ffff_ffff_ffff => I64,
683             _ => I128,
684         }
685     }
686
687     /// Finds the smallest Integer type which can represent the unsigned value.
688     #[inline]
689     pub fn fit_unsigned(x: u128) -> Integer {
690         match x {
691             0..=0x0000_0000_0000_00ff => I8,
692             0..=0x0000_0000_0000_ffff => I16,
693             0..=0x0000_0000_ffff_ffff => I32,
694             0..=0xffff_ffff_ffff_ffff => I64,
695             _ => I128,
696         }
697     }
698
699     /// Finds the smallest integer with the given alignment.
700     pub fn for_align<C: HasDataLayout>(cx: &C, wanted: Align) -> Option<Integer> {
701         let dl = cx.data_layout();
702
703         for candidate in [I8, I16, I32, I64, I128] {
704             if wanted == candidate.align(dl).abi && wanted.bytes() == candidate.size().bytes() {
705                 return Some(candidate);
706             }
707         }
708         None
709     }
710
711     /// Find the largest integer with the given alignment or less.
712     pub fn approximate_align<C: HasDataLayout>(cx: &C, wanted: Align) -> Integer {
713         let dl = cx.data_layout();
714
715         // FIXME(eddyb) maybe include I128 in the future, when it works everywhere.
716         for candidate in [I64, I32, I16] {
717             if wanted >= candidate.align(dl).abi && wanted.bytes() >= candidate.size().bytes() {
718                 return candidate;
719             }
720         }
721         I8
722     }
723
724     // FIXME(eddyb) consolidate this and other methods that find the appropriate
725     // `Integer` given some requirements.
726     #[inline]
727     pub fn from_size(size: Size) -> Result<Self, String> {
728         match size.bits() {
729             8 => Ok(Integer::I8),
730             16 => Ok(Integer::I16),
731             32 => Ok(Integer::I32),
732             64 => Ok(Integer::I64),
733             128 => Ok(Integer::I128),
734             _ => Err(format!("rust does not support integers with {} bits", size.bits())),
735         }
736     }
737 }
738
739 /// Fundamental unit of memory access and layout.
740 #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
741 #[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
742 pub enum Primitive {
743     /// The `bool` is the signedness of the `Integer` type.
744     ///
745     /// One would think we would not care about such details this low down,
746     /// but some ABIs are described in terms of C types and ISAs where the
747     /// integer arithmetic is done on {sign,zero}-extended registers, e.g.
748     /// a negative integer passed by zero-extension will appear positive in
749     /// the callee, and most operations on it will produce the wrong values.
750     Int(Integer, bool),
751     F32,
752     F64,
753     Pointer,
754 }
755
756 impl Primitive {
757     pub fn size<C: HasDataLayout>(self, cx: &C) -> Size {
758         let dl = cx.data_layout();
759
760         match self {
761             Int(i, _) => i.size(),
762             F32 => Size::from_bits(32),
763             F64 => Size::from_bits(64),
764             Pointer => dl.pointer_size,
765         }
766     }
767
768     pub fn align<C: HasDataLayout>(self, cx: &C) -> AbiAndPrefAlign {
769         let dl = cx.data_layout();
770
771         match self {
772             Int(i, _) => i.align(dl),
773             F32 => dl.f32_align,
774             F64 => dl.f64_align,
775             Pointer => dl.pointer_align,
776         }
777     }
778
779     // FIXME(eddyb) remove, it's trivial thanks to `matches!`.
780     #[inline]
781     pub fn is_float(self) -> bool {
782         matches!(self, F32 | F64)
783     }
784
785     // FIXME(eddyb) remove, it's completely unused.
786     #[inline]
787     pub fn is_int(self) -> bool {
788         matches!(self, Int(..))
789     }
790
791     #[inline]
792     pub fn is_ptr(self) -> bool {
793         matches!(self, Pointer)
794     }
795 }
796
797 /// Inclusive wrap-around range of valid values, that is, if
798 /// start > end, it represents `start..=MAX`,
799 /// followed by `0..=end`.
800 ///
801 /// That is, for an i8 primitive, a range of `254..=2` means following
802 /// sequence:
803 ///
804 ///    254 (-2), 255 (-1), 0, 1, 2
805 ///
806 /// This is intended specifically to mirror LLVM’s `!range` metadata semantics.
807 #[derive(Clone, Copy, PartialEq, Eq, Hash)]
808 #[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
809 pub struct WrappingRange {
810     pub start: u128,
811     pub end: u128,
812 }
813
814 impl WrappingRange {
815     pub fn full(size: Size) -> Self {
816         Self { start: 0, end: size.unsigned_int_max() }
817     }
818
819     /// Returns `true` if `v` is contained in the range.
820     #[inline(always)]
821     pub fn contains(&self, v: u128) -> bool {
822         if self.start <= self.end {
823             self.start <= v && v <= self.end
824         } else {
825             self.start <= v || v <= self.end
826         }
827     }
828
829     /// Returns `self` with replaced `start`
830     #[inline(always)]
831     pub fn with_start(mut self, start: u128) -> Self {
832         self.start = start;
833         self
834     }
835
836     /// Returns `self` with replaced `end`
837     #[inline(always)]
838     pub fn with_end(mut self, end: u128) -> Self {
839         self.end = end;
840         self
841     }
842
843     /// Returns `true` if `size` completely fills the range.
844     #[inline]
845     pub fn is_full_for(&self, size: Size) -> bool {
846         let max_value = size.unsigned_int_max();
847         debug_assert!(self.start <= max_value && self.end <= max_value);
848         self.start == (self.end.wrapping_add(1) & max_value)
849     }
850 }
851
852 impl fmt::Debug for WrappingRange {
853     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
854         if self.start > self.end {
855             write!(fmt, "(..={}) | ({}..)", self.end, self.start)?;
856         } else {
857             write!(fmt, "{}..={}", self.start, self.end)?;
858         }
859         Ok(())
860     }
861 }
862
863 /// Information about one scalar component of a Rust type.
864 #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
865 #[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
866 pub enum Scalar {
867     Initialized {
868         value: Primitive,
869
870         // FIXME(eddyb) always use the shortest range, e.g., by finding
871         // the largest space between two consecutive valid values and
872         // taking everything else as the (shortest) valid range.
873         valid_range: WrappingRange,
874     },
875     Union {
876         /// Even for unions, we need to use the correct registers for the kind of
877         /// values inside the union, so we keep the `Primitive` type around. We
878         /// also use it to compute the size of the scalar.
879         /// However, unions never have niches and even allow undef,
880         /// so there is no `valid_range`.
881         value: Primitive,
882     },
883 }
884
885 impl Scalar {
886     #[inline]
887     pub fn is_bool(&self) -> bool {
888         matches!(
889             self,
890             Scalar::Initialized {
891                 value: Int(I8, false),
892                 valid_range: WrappingRange { start: 0, end: 1 }
893             }
894         )
895     }
896
897     /// Get the primitive representation of this type, ignoring the valid range and whether the
898     /// value is allowed to be undefined (due to being a union).
899     pub fn primitive(&self) -> Primitive {
900         match *self {
901             Scalar::Initialized { value, .. } | Scalar::Union { value } => value,
902         }
903     }
904
905     pub fn align(self, cx: &impl HasDataLayout) -> AbiAndPrefAlign {
906         self.primitive().align(cx)
907     }
908
909     pub fn size(self, cx: &impl HasDataLayout) -> Size {
910         self.primitive().size(cx)
911     }
912
913     #[inline]
914     pub fn to_union(&self) -> Self {
915         Self::Union { value: self.primitive() }
916     }
917
918     #[inline]
919     pub fn valid_range(&self, cx: &impl HasDataLayout) -> WrappingRange {
920         match *self {
921             Scalar::Initialized { valid_range, .. } => valid_range,
922             Scalar::Union { value } => WrappingRange::full(value.size(cx)),
923         }
924     }
925
926     #[inline]
927     /// Allows the caller to mutate the valid range. This operation will panic if attempted on a union.
928     pub fn valid_range_mut(&mut self) -> &mut WrappingRange {
929         match self {
930             Scalar::Initialized { valid_range, .. } => valid_range,
931             Scalar::Union { .. } => panic!("cannot change the valid range of a union"),
932         }
933     }
934
935     /// Returns `true` if all possible numbers are valid, i.e `valid_range` covers the whole layout
936     #[inline]
937     pub fn is_always_valid<C: HasDataLayout>(&self, cx: &C) -> bool {
938         match *self {
939             Scalar::Initialized { valid_range, .. } => valid_range.is_full_for(self.size(cx)),
940             Scalar::Union { .. } => true,
941         }
942     }
943
944     /// Returns `true` if this type can be left uninit.
945     #[inline]
946     pub fn is_uninit_valid(&self) -> bool {
947         match *self {
948             Scalar::Initialized { .. } => false,
949             Scalar::Union { .. } => true,
950         }
951     }
952 }
953
954 /// Describes how the fields of a type are located in memory.
955 #[derive(PartialEq, Eq, Hash, Clone, Debug)]
956 #[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
957 pub enum FieldsShape {
958     /// Scalar primitives and `!`, which never have fields.
959     Primitive,
960
961     /// All fields start at no offset. The `usize` is the field count.
962     Union(NonZeroUsize),
963
964     /// Array/vector-like placement, with all fields of identical types.
965     Array { stride: Size, count: u64 },
966
967     /// Struct-like placement, with precomputed offsets.
968     ///
969     /// Fields are guaranteed to not overlap, but note that gaps
970     /// before, between and after all the fields are NOT always
971     /// padding, and as such their contents may not be discarded.
972     /// For example, enum variants leave a gap at the start,
973     /// where the discriminant field in the enum layout goes.
974     Arbitrary {
975         /// Offsets for the first byte of each field,
976         /// ordered to match the source definition order.
977         /// This vector does not go in increasing order.
978         // FIXME(eddyb) use small vector optimization for the common case.
979         offsets: Vec<Size>,
980
981         /// Maps source order field indices to memory order indices,
982         /// depending on how the fields were reordered (if at all).
983         /// This is a permutation, with both the source order and the
984         /// memory order using the same (0..n) index ranges.
985         ///
986         /// Note that during computation of `memory_index`, sometimes
987         /// it is easier to operate on the inverse mapping (that is,
988         /// from memory order to source order), and that is usually
989         /// named `inverse_memory_index`.
990         ///
991         // FIXME(eddyb) build a better abstraction for permutations, if possible.
992         // FIXME(camlorn) also consider small vector  optimization here.
993         memory_index: Vec<u32>,
994     },
995 }
996
997 impl FieldsShape {
998     #[inline]
999     pub fn count(&self) -> usize {
1000         match *self {
1001             FieldsShape::Primitive => 0,
1002             FieldsShape::Union(count) => count.get(),
1003             FieldsShape::Array { count, .. } => count.try_into().unwrap(),
1004             FieldsShape::Arbitrary { ref offsets, .. } => offsets.len(),
1005         }
1006     }
1007
1008     #[inline]
1009     pub fn offset(&self, i: usize) -> Size {
1010         match *self {
1011             FieldsShape::Primitive => {
1012                 unreachable!("FieldsShape::offset: `Primitive`s have no fields")
1013             }
1014             FieldsShape::Union(count) => {
1015                 assert!(
1016                     i < count.get(),
1017                     "tried to access field {} of union with {} fields",
1018                     i,
1019                     count
1020                 );
1021                 Size::ZERO
1022             }
1023             FieldsShape::Array { stride, count } => {
1024                 let i = u64::try_from(i).unwrap();
1025                 assert!(i < count);
1026                 stride * i
1027             }
1028             FieldsShape::Arbitrary { ref offsets, .. } => offsets[i],
1029         }
1030     }
1031
1032     #[inline]
1033     pub fn memory_index(&self, i: usize) -> usize {
1034         match *self {
1035             FieldsShape::Primitive => {
1036                 unreachable!("FieldsShape::memory_index: `Primitive`s have no fields")
1037             }
1038             FieldsShape::Union(_) | FieldsShape::Array { .. } => i,
1039             FieldsShape::Arbitrary { ref memory_index, .. } => memory_index[i].try_into().unwrap(),
1040         }
1041     }
1042
1043     /// Gets source indices of the fields by increasing offsets.
1044     #[inline]
1045     pub fn index_by_increasing_offset<'a>(&'a self) -> impl Iterator<Item = usize> + 'a {
1046         let mut inverse_small = [0u8; 64];
1047         let mut inverse_big = vec![];
1048         let use_small = self.count() <= inverse_small.len();
1049
1050         // We have to write this logic twice in order to keep the array small.
1051         if let FieldsShape::Arbitrary { ref memory_index, .. } = *self {
1052             if use_small {
1053                 for i in 0..self.count() {
1054                     inverse_small[memory_index[i] as usize] = i as u8;
1055                 }
1056             } else {
1057                 inverse_big = vec![0; self.count()];
1058                 for i in 0..self.count() {
1059                     inverse_big[memory_index[i] as usize] = i as u32;
1060                 }
1061             }
1062         }
1063
1064         (0..self.count()).map(move |i| match *self {
1065             FieldsShape::Primitive | FieldsShape::Union(_) | FieldsShape::Array { .. } => i,
1066             FieldsShape::Arbitrary { .. } => {
1067                 if use_small {
1068                     inverse_small[i] as usize
1069                 } else {
1070                     inverse_big[i] as usize
1071                 }
1072             }
1073         })
1074     }
1075 }
1076
1077 /// An identifier that specifies the address space that some operation
1078 /// should operate on. Special address spaces have an effect on code generation,
1079 /// depending on the target and the address spaces it implements.
1080 #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
1081 pub struct AddressSpace(pub u32);
1082
1083 impl AddressSpace {
1084     /// The default address space, corresponding to data space.
1085     pub const DATA: Self = AddressSpace(0);
1086 }
1087
1088 /// Describes how values of the type are passed by target ABIs,
1089 /// in terms of categories of C types there are ABI rules for.
1090 #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
1091 #[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
1092
1093 pub enum Abi {
1094     Uninhabited,
1095     Scalar(Scalar),
1096     ScalarPair(Scalar, Scalar),
1097     Vector {
1098         element: Scalar,
1099         count: u64,
1100     },
1101     Aggregate {
1102         /// If true, the size is exact, otherwise it's only a lower bound.
1103         sized: bool,
1104     },
1105 }
1106
1107 impl Abi {
1108     /// Returns `true` if the layout corresponds to an unsized type.
1109     #[inline]
1110     pub fn is_unsized(&self) -> bool {
1111         match *self {
1112             Abi::Uninhabited | Abi::Scalar(_) | Abi::ScalarPair(..) | Abi::Vector { .. } => false,
1113             Abi::Aggregate { sized } => !sized,
1114         }
1115     }
1116
1117     #[inline]
1118     pub fn is_sized(&self) -> bool {
1119         !self.is_unsized()
1120     }
1121
1122     /// Returns `true` if this is a single signed integer scalar
1123     #[inline]
1124     pub fn is_signed(&self) -> bool {
1125         match self {
1126             Abi::Scalar(scal) => match scal.primitive() {
1127                 Primitive::Int(_, signed) => signed,
1128                 _ => false,
1129             },
1130             _ => panic!("`is_signed` on non-scalar ABI {:?}", self),
1131         }
1132     }
1133
1134     /// Returns `true` if this is an uninhabited type
1135     #[inline]
1136     pub fn is_uninhabited(&self) -> bool {
1137         matches!(*self, Abi::Uninhabited)
1138     }
1139
1140     /// Returns `true` is this is a scalar type
1141     #[inline]
1142     pub fn is_scalar(&self) -> bool {
1143         matches!(*self, Abi::Scalar(_))
1144     }
1145 }
1146
1147 #[derive(PartialEq, Eq, Hash, Clone, Debug)]
1148 #[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
1149 pub enum Variants<V: Idx> {
1150     /// Single enum variants, structs/tuples, unions, and all non-ADTs.
1151     Single { index: V },
1152
1153     /// Enum-likes with more than one inhabited variant: each variant comes with
1154     /// a *discriminant* (usually the same as the variant index but the user can
1155     /// assign explicit discriminant values).  That discriminant is encoded
1156     /// as a *tag* on the machine.  The layout of each variant is
1157     /// a struct, and they all have space reserved for the tag.
1158     /// For enums, the tag is the sole field of the layout.
1159     Multiple {
1160         tag: Scalar,
1161         tag_encoding: TagEncoding<V>,
1162         tag_field: usize,
1163         variants: IndexVec<V, LayoutS<V>>,
1164     },
1165 }
1166
1167 #[derive(PartialEq, Eq, Hash, Clone, Debug)]
1168 #[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
1169 pub enum TagEncoding<V: Idx> {
1170     /// The tag directly stores the discriminant, but possibly with a smaller layout
1171     /// (so converting the tag to the discriminant can require sign extension).
1172     Direct,
1173
1174     /// Niche (values invalid for a type) encoding the discriminant:
1175     /// Discriminant and variant index coincide.
1176     /// The variant `untagged_variant` contains a niche at an arbitrary
1177     /// offset (field `tag_field` of the enum), which for a variant with
1178     /// discriminant `d` is set to
1179     /// `(d - niche_variants.start).wrapping_add(niche_start)`.
1180     ///
1181     /// For example, `Option<(usize, &T)>`  is represented such that
1182     /// `None` has a null pointer for the second tuple field, and
1183     /// `Some` is the identity function (with a non-null reference).
1184     Niche { untagged_variant: V, niche_variants: RangeInclusive<V>, niche_start: u128 },
1185 }
1186
1187 #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
1188 #[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
1189 pub struct Niche {
1190     pub offset: Size,
1191     pub value: Primitive,
1192     pub valid_range: WrappingRange,
1193 }
1194
1195 impl Niche {
1196     pub fn from_scalar<C: HasDataLayout>(cx: &C, offset: Size, scalar: Scalar) -> Option<Self> {
1197         let Scalar::Initialized { value, valid_range } = scalar else { return None };
1198         let niche = Niche { offset, value, valid_range };
1199         if niche.available(cx) > 0 { Some(niche) } else { None }
1200     }
1201
1202     pub fn available<C: HasDataLayout>(&self, cx: &C) -> u128 {
1203         let Self { value, valid_range: v, .. } = *self;
1204         let size = value.size(cx);
1205         assert!(size.bits() <= 128);
1206         let max_value = size.unsigned_int_max();
1207
1208         // Find out how many values are outside the valid range.
1209         let niche = v.end.wrapping_add(1)..v.start;
1210         niche.end.wrapping_sub(niche.start) & max_value
1211     }
1212
1213     pub fn reserve<C: HasDataLayout>(&self, cx: &C, count: u128) -> Option<(u128, Scalar)> {
1214         assert!(count > 0);
1215
1216         let Self { value, valid_range: v, .. } = *self;
1217         let size = value.size(cx);
1218         assert!(size.bits() <= 128);
1219         let max_value = size.unsigned_int_max();
1220
1221         let niche = v.end.wrapping_add(1)..v.start;
1222         let available = niche.end.wrapping_sub(niche.start) & max_value;
1223         if count > available {
1224             return None;
1225         }
1226
1227         // Extend the range of valid values being reserved by moving either `v.start` or `v.end` bound.
1228         // Given an eventual `Option<T>`, we try to maximize the chance for `None` to occupy the niche of zero.
1229         // This is accomplished by preferring enums with 2 variants(`count==1`) and always taking the shortest path to niche zero.
1230         // Having `None` in niche zero can enable some special optimizations.
1231         //
1232         // Bound selection criteria:
1233         // 1. Select closest to zero given wrapping semantics.
1234         // 2. Avoid moving past zero if possible.
1235         //
1236         // In practice this means that enums with `count > 1` are unlikely to claim niche zero, since they have to fit perfectly.
1237         // If niche zero is already reserved, the selection of bounds are of little interest.
1238         let move_start = |v: WrappingRange| {
1239             let start = v.start.wrapping_sub(count) & max_value;
1240             Some((start, Scalar::Initialized { value, valid_range: v.with_start(start) }))
1241         };
1242         let move_end = |v: WrappingRange| {
1243             let start = v.end.wrapping_add(1) & max_value;
1244             let end = v.end.wrapping_add(count) & max_value;
1245             Some((start, Scalar::Initialized { value, valid_range: v.with_end(end) }))
1246         };
1247         let distance_end_zero = max_value - v.end;
1248         if v.start > v.end {
1249             // zero is unavailable because wrapping occurs
1250             move_end(v)
1251         } else if v.start <= distance_end_zero {
1252             if count <= v.start {
1253                 move_start(v)
1254             } else {
1255                 // moved past zero, use other bound
1256                 move_end(v)
1257             }
1258         } else {
1259             let end = v.end.wrapping_add(count) & max_value;
1260             let overshot_zero = (1..=v.end).contains(&end);
1261             if overshot_zero {
1262                 // moved past zero, use other bound
1263                 move_start(v)
1264             } else {
1265                 move_end(v)
1266             }
1267         }
1268     }
1269 }
1270
1271 #[derive(PartialEq, Eq, Hash, Clone)]
1272 #[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
1273 pub struct LayoutS<V: Idx> {
1274     /// Says where the fields are located within the layout.
1275     pub fields: FieldsShape,
1276
1277     /// Encodes information about multi-variant layouts.
1278     /// Even with `Multiple` variants, a layout still has its own fields! Those are then
1279     /// shared between all variants. One of them will be the discriminant,
1280     /// but e.g. generators can have more.
1281     ///
1282     /// To access all fields of this layout, both `fields` and the fields of the active variant
1283     /// must be taken into account.
1284     pub variants: Variants<V>,
1285
1286     /// The `abi` defines how this data is passed between functions, and it defines
1287     /// value restrictions via `valid_range`.
1288     ///
1289     /// Note that this is entirely orthogonal to the recursive structure defined by
1290     /// `variants` and `fields`; for example, `ManuallyDrop<Result<isize, isize>>` has
1291     /// `Abi::ScalarPair`! So, even with non-`Aggregate` `abi`, `fields` and `variants`
1292     /// have to be taken into account to find all fields of this layout.
1293     pub abi: Abi,
1294
1295     /// The leaf scalar with the largest number of invalid values
1296     /// (i.e. outside of its `valid_range`), if it exists.
1297     pub largest_niche: Option<Niche>,
1298
1299     pub align: AbiAndPrefAlign,
1300     pub size: Size,
1301 }
1302
1303 impl<V: Idx> LayoutS<V> {
1304     pub fn scalar<C: HasDataLayout>(cx: &C, scalar: Scalar) -> Self {
1305         let largest_niche = Niche::from_scalar(cx, Size::ZERO, scalar);
1306         let size = scalar.size(cx);
1307         let align = scalar.align(cx);
1308         LayoutS {
1309             variants: Variants::Single { index: V::new(0) },
1310             fields: FieldsShape::Primitive,
1311             abi: Abi::Scalar(scalar),
1312             largest_niche,
1313             size,
1314             align,
1315         }
1316     }
1317 }
1318
1319 impl<V: Idx> fmt::Debug for LayoutS<V> {
1320     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1321         // This is how `Layout` used to print before it become
1322         // `Interned<LayoutS>`. We print it like this to avoid having to update
1323         // expected output in a lot of tests.
1324         let LayoutS { size, align, abi, fields, largest_niche, variants } = self;
1325         f.debug_struct("Layout")
1326             .field("size", size)
1327             .field("align", align)
1328             .field("abi", abi)
1329             .field("fields", fields)
1330             .field("largest_niche", largest_niche)
1331             .field("variants", variants)
1332             .finish()
1333     }
1334 }
1335
1336 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
1337 pub enum PointerKind {
1338     /// Most general case, we know no restrictions to tell LLVM.
1339     SharedMutable,
1340
1341     /// `&T` where `T` contains no `UnsafeCell`, is `dereferenceable`, `noalias` and `readonly`.
1342     Frozen,
1343
1344     /// `&mut T` which is `dereferenceable` and `noalias` but not `readonly`.
1345     UniqueBorrowed,
1346
1347     /// `&mut !Unpin`, which is `dereferenceable` but neither `noalias` nor `readonly`.
1348     UniqueBorrowedPinned,
1349
1350     /// `Box<T>`, which is `noalias` (even on return types, unlike the above) but neither `readonly`
1351     /// nor `dereferenceable`.
1352     UniqueOwned,
1353 }
1354
1355 #[derive(Copy, Clone, Debug)]
1356 pub struct PointeeInfo {
1357     pub size: Size,
1358     pub align: Align,
1359     pub safe: Option<PointerKind>,
1360     pub address_space: AddressSpace,
1361 }
1362
1363 /// Used in `might_permit_raw_init` to indicate the kind of initialisation
1364 /// that is checked to be valid
1365 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
1366 pub enum InitKind {
1367     Zero,
1368     UninitMitigated0x01Fill,
1369 }
1370
1371 impl<V: Idx> LayoutS<V> {
1372     /// Returns `true` if the layout corresponds to an unsized type.
1373     pub fn is_unsized(&self) -> bool {
1374         self.abi.is_unsized()
1375     }
1376
1377     pub fn is_sized(&self) -> bool {
1378         self.abi.is_sized()
1379     }
1380
1381     /// Returns `true` if the type is a ZST and not unsized.
1382     pub fn is_zst(&self) -> bool {
1383         match self.abi {
1384             Abi::Scalar(_) | Abi::ScalarPair(..) | Abi::Vector { .. } => false,
1385             Abi::Uninhabited => self.size.bytes() == 0,
1386             Abi::Aggregate { sized } => sized && self.size.bytes() == 0,
1387         }
1388     }
1389 }
1390
1391 #[derive(Copy, Clone, Debug)]
1392 pub enum StructKind {
1393     /// A tuple, closure, or univariant which cannot be coerced to unsized.
1394     AlwaysSized,
1395     /// A univariant, the last field of which may be coerced to unsized.
1396     MaybeUnsized,
1397     /// A univariant, but with a prefix of an arbitrary size & alignment (e.g., enum tag).
1398     Prefixed(Size, Align),
1399 }