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