]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_abi/src/lib.rs
Rollup merge of #106946 - dtolnay:hashlinecolumn, r=m-ou-se
[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     /// Returns the largest signed value that can be represented by this Integer.
778     #[inline]
779     pub fn signed_max(self) -> i128 {
780         match self {
781             I8 => i8::MAX as i128,
782             I16 => i16::MAX as i128,
783             I32 => i32::MAX as i128,
784             I64 => i64::MAX as i128,
785             I128 => i128::MAX,
786         }
787     }
788
789     /// Finds the smallest Integer type which can represent the signed value.
790     #[inline]
791     pub fn fit_signed(x: i128) -> Integer {
792         match x {
793             -0x0000_0000_0000_0080..=0x0000_0000_0000_007f => I8,
794             -0x0000_0000_0000_8000..=0x0000_0000_0000_7fff => I16,
795             -0x0000_0000_8000_0000..=0x0000_0000_7fff_ffff => I32,
796             -0x8000_0000_0000_0000..=0x7fff_ffff_ffff_ffff => I64,
797             _ => I128,
798         }
799     }
800
801     /// Finds the smallest Integer type which can represent the unsigned value.
802     #[inline]
803     pub fn fit_unsigned(x: u128) -> Integer {
804         match x {
805             0..=0x0000_0000_0000_00ff => I8,
806             0..=0x0000_0000_0000_ffff => I16,
807             0..=0x0000_0000_ffff_ffff => I32,
808             0..=0xffff_ffff_ffff_ffff => I64,
809             _ => I128,
810         }
811     }
812
813     /// Finds the smallest integer with the given alignment.
814     pub fn for_align<C: HasDataLayout>(cx: &C, wanted: Align) -> Option<Integer> {
815         let dl = cx.data_layout();
816
817         [I8, I16, I32, I64, I128].into_iter().find(|&candidate| {
818             wanted == candidate.align(dl).abi && wanted.bytes() == candidate.size().bytes()
819         })
820     }
821
822     /// Find the largest integer with the given alignment or less.
823     pub fn approximate_align<C: HasDataLayout>(cx: &C, wanted: Align) -> Integer {
824         let dl = cx.data_layout();
825
826         // FIXME(eddyb) maybe include I128 in the future, when it works everywhere.
827         for candidate in [I64, I32, I16] {
828             if wanted >= candidate.align(dl).abi && wanted.bytes() >= candidate.size().bytes() {
829                 return candidate;
830             }
831         }
832         I8
833     }
834
835     // FIXME(eddyb) consolidate this and other methods that find the appropriate
836     // `Integer` given some requirements.
837     #[inline]
838     pub fn from_size(size: Size) -> Result<Self, String> {
839         match size.bits() {
840             8 => Ok(Integer::I8),
841             16 => Ok(Integer::I16),
842             32 => Ok(Integer::I32),
843             64 => Ok(Integer::I64),
844             128 => Ok(Integer::I128),
845             _ => Err(format!("rust does not support integers with {} bits", size.bits())),
846         }
847     }
848 }
849
850 /// Fundamental unit of memory access and layout.
851 #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
852 #[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
853 pub enum Primitive {
854     /// The `bool` is the signedness of the `Integer` type.
855     ///
856     /// One would think we would not care about such details this low down,
857     /// but some ABIs are described in terms of C types and ISAs where the
858     /// integer arithmetic is done on {sign,zero}-extended registers, e.g.
859     /// a negative integer passed by zero-extension will appear positive in
860     /// the callee, and most operations on it will produce the wrong values.
861     Int(Integer, bool),
862     F32,
863     F64,
864     Pointer,
865 }
866
867 impl Primitive {
868     pub fn size<C: HasDataLayout>(self, cx: &C) -> Size {
869         let dl = cx.data_layout();
870
871         match self {
872             Int(i, _) => i.size(),
873             F32 => Size::from_bits(32),
874             F64 => Size::from_bits(64),
875             Pointer => dl.pointer_size,
876         }
877     }
878
879     pub fn align<C: HasDataLayout>(self, cx: &C) -> AbiAndPrefAlign {
880         let dl = cx.data_layout();
881
882         match self {
883             Int(i, _) => i.align(dl),
884             F32 => dl.f32_align,
885             F64 => dl.f64_align,
886             Pointer => dl.pointer_align,
887         }
888     }
889
890     // FIXME(eddyb) remove, it's trivial thanks to `matches!`.
891     #[inline]
892     pub fn is_float(self) -> bool {
893         matches!(self, F32 | F64)
894     }
895
896     // FIXME(eddyb) remove, it's completely unused.
897     #[inline]
898     pub fn is_int(self) -> bool {
899         matches!(self, Int(..))
900     }
901
902     #[inline]
903     pub fn is_ptr(self) -> bool {
904         matches!(self, Pointer)
905     }
906 }
907
908 /// Inclusive wrap-around range of valid values, that is, if
909 /// start > end, it represents `start..=MAX`,
910 /// followed by `0..=end`.
911 ///
912 /// That is, for an i8 primitive, a range of `254..=2` means following
913 /// sequence:
914 ///
915 ///    254 (-2), 255 (-1), 0, 1, 2
916 ///
917 /// This is intended specifically to mirror LLVM’s `!range` metadata semantics.
918 #[derive(Clone, Copy, PartialEq, Eq, Hash)]
919 #[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
920 pub struct WrappingRange {
921     pub start: u128,
922     pub end: u128,
923 }
924
925 impl WrappingRange {
926     pub fn full(size: Size) -> Self {
927         Self { start: 0, end: size.unsigned_int_max() }
928     }
929
930     /// Returns `true` if `v` is contained in the range.
931     #[inline(always)]
932     pub fn contains(&self, v: u128) -> bool {
933         if self.start <= self.end {
934             self.start <= v && v <= self.end
935         } else {
936             self.start <= v || v <= self.end
937         }
938     }
939
940     /// Returns `self` with replaced `start`
941     #[inline(always)]
942     pub fn with_start(mut self, start: u128) -> Self {
943         self.start = start;
944         self
945     }
946
947     /// Returns `self` with replaced `end`
948     #[inline(always)]
949     pub fn with_end(mut self, end: u128) -> Self {
950         self.end = end;
951         self
952     }
953
954     /// Returns `true` if `size` completely fills the range.
955     #[inline]
956     pub fn is_full_for(&self, size: Size) -> bool {
957         let max_value = size.unsigned_int_max();
958         debug_assert!(self.start <= max_value && self.end <= max_value);
959         self.start == (self.end.wrapping_add(1) & max_value)
960     }
961 }
962
963 impl fmt::Debug for WrappingRange {
964     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
965         if self.start > self.end {
966             write!(fmt, "(..={}) | ({}..)", self.end, self.start)?;
967         } else {
968             write!(fmt, "{}..={}", self.start, self.end)?;
969         }
970         Ok(())
971     }
972 }
973
974 /// Information about one scalar component of a Rust type.
975 #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
976 #[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
977 pub enum Scalar {
978     Initialized {
979         value: Primitive,
980
981         // FIXME(eddyb) always use the shortest range, e.g., by finding
982         // the largest space between two consecutive valid values and
983         // taking everything else as the (shortest) valid range.
984         valid_range: WrappingRange,
985     },
986     Union {
987         /// Even for unions, we need to use the correct registers for the kind of
988         /// values inside the union, so we keep the `Primitive` type around. We
989         /// also use it to compute the size of the scalar.
990         /// However, unions never have niches and even allow undef,
991         /// so there is no `valid_range`.
992         value: Primitive,
993     },
994 }
995
996 impl Scalar {
997     #[inline]
998     pub fn is_bool(&self) -> bool {
999         matches!(
1000             self,
1001             Scalar::Initialized {
1002                 value: Int(I8, false),
1003                 valid_range: WrappingRange { start: 0, end: 1 }
1004             }
1005         )
1006     }
1007
1008     /// Get the primitive representation of this type, ignoring the valid range and whether the
1009     /// value is allowed to be undefined (due to being a union).
1010     pub fn primitive(&self) -> Primitive {
1011         match *self {
1012             Scalar::Initialized { value, .. } | Scalar::Union { value } => value,
1013         }
1014     }
1015
1016     pub fn align(self, cx: &impl HasDataLayout) -> AbiAndPrefAlign {
1017         self.primitive().align(cx)
1018     }
1019
1020     pub fn size(self, cx: &impl HasDataLayout) -> Size {
1021         self.primitive().size(cx)
1022     }
1023
1024     #[inline]
1025     pub fn to_union(&self) -> Self {
1026         Self::Union { value: self.primitive() }
1027     }
1028
1029     #[inline]
1030     pub fn valid_range(&self, cx: &impl HasDataLayout) -> WrappingRange {
1031         match *self {
1032             Scalar::Initialized { valid_range, .. } => valid_range,
1033             Scalar::Union { value } => WrappingRange::full(value.size(cx)),
1034         }
1035     }
1036
1037     #[inline]
1038     /// Allows the caller to mutate the valid range. This operation will panic if attempted on a union.
1039     pub fn valid_range_mut(&mut self) -> &mut WrappingRange {
1040         match self {
1041             Scalar::Initialized { valid_range, .. } => valid_range,
1042             Scalar::Union { .. } => panic!("cannot change the valid range of a union"),
1043         }
1044     }
1045
1046     /// Returns `true` if all possible numbers are valid, i.e `valid_range` covers the whole layout
1047     #[inline]
1048     pub fn is_always_valid<C: HasDataLayout>(&self, cx: &C) -> bool {
1049         match *self {
1050             Scalar::Initialized { valid_range, .. } => valid_range.is_full_for(self.size(cx)),
1051             Scalar::Union { .. } => true,
1052         }
1053     }
1054
1055     /// Returns `true` if this type can be left uninit.
1056     #[inline]
1057     pub fn is_uninit_valid(&self) -> bool {
1058         match *self {
1059             Scalar::Initialized { .. } => false,
1060             Scalar::Union { .. } => true,
1061         }
1062     }
1063 }
1064
1065 /// Describes how the fields of a type are located in memory.
1066 #[derive(PartialEq, Eq, Hash, Clone, Debug)]
1067 #[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
1068 pub enum FieldsShape {
1069     /// Scalar primitives and `!`, which never have fields.
1070     Primitive,
1071
1072     /// All fields start at no offset. The `usize` is the field count.
1073     Union(NonZeroUsize),
1074
1075     /// Array/vector-like placement, with all fields of identical types.
1076     Array { stride: Size, count: u64 },
1077
1078     /// Struct-like placement, with precomputed offsets.
1079     ///
1080     /// Fields are guaranteed to not overlap, but note that gaps
1081     /// before, between and after all the fields are NOT always
1082     /// padding, and as such their contents may not be discarded.
1083     /// For example, enum variants leave a gap at the start,
1084     /// where the discriminant field in the enum layout goes.
1085     Arbitrary {
1086         /// Offsets for the first byte of each field,
1087         /// ordered to match the source definition order.
1088         /// This vector does not go in increasing order.
1089         // FIXME(eddyb) use small vector optimization for the common case.
1090         offsets: Vec<Size>,
1091
1092         /// Maps source order field indices to memory order indices,
1093         /// depending on how the fields were reordered (if at all).
1094         /// This is a permutation, with both the source order and the
1095         /// memory order using the same (0..n) index ranges.
1096         ///
1097         /// Note that during computation of `memory_index`, sometimes
1098         /// it is easier to operate on the inverse mapping (that is,
1099         /// from memory order to source order), and that is usually
1100         /// named `inverse_memory_index`.
1101         ///
1102         // FIXME(eddyb) build a better abstraction for permutations, if possible.
1103         // FIXME(camlorn) also consider small vector optimization here.
1104         memory_index: Vec<u32>,
1105     },
1106 }
1107
1108 impl FieldsShape {
1109     #[inline]
1110     pub fn count(&self) -> usize {
1111         match *self {
1112             FieldsShape::Primitive => 0,
1113             FieldsShape::Union(count) => count.get(),
1114             FieldsShape::Array { count, .. } => count.try_into().unwrap(),
1115             FieldsShape::Arbitrary { ref offsets, .. } => offsets.len(),
1116         }
1117     }
1118
1119     #[inline]
1120     pub fn offset(&self, i: usize) -> Size {
1121         match *self {
1122             FieldsShape::Primitive => {
1123                 unreachable!("FieldsShape::offset: `Primitive`s have no fields")
1124             }
1125             FieldsShape::Union(count) => {
1126                 assert!(
1127                     i < count.get(),
1128                     "tried to access field {} of union with {} fields",
1129                     i,
1130                     count
1131                 );
1132                 Size::ZERO
1133             }
1134             FieldsShape::Array { stride, count } => {
1135                 let i = u64::try_from(i).unwrap();
1136                 assert!(i < count);
1137                 stride * i
1138             }
1139             FieldsShape::Arbitrary { ref offsets, .. } => offsets[i],
1140         }
1141     }
1142
1143     #[inline]
1144     pub fn memory_index(&self, i: usize) -> usize {
1145         match *self {
1146             FieldsShape::Primitive => {
1147                 unreachable!("FieldsShape::memory_index: `Primitive`s have no fields")
1148             }
1149             FieldsShape::Union(_) | FieldsShape::Array { .. } => i,
1150             FieldsShape::Arbitrary { ref memory_index, .. } => memory_index[i].try_into().unwrap(),
1151         }
1152     }
1153
1154     /// Gets source indices of the fields by increasing offsets.
1155     #[inline]
1156     pub fn index_by_increasing_offset<'a>(&'a self) -> impl Iterator<Item = usize> + 'a {
1157         let mut inverse_small = [0u8; 64];
1158         let mut inverse_big = vec![];
1159         let use_small = self.count() <= inverse_small.len();
1160
1161         // We have to write this logic twice in order to keep the array small.
1162         if let FieldsShape::Arbitrary { ref memory_index, .. } = *self {
1163             if use_small {
1164                 for i in 0..self.count() {
1165                     inverse_small[memory_index[i] as usize] = i as u8;
1166                 }
1167             } else {
1168                 inverse_big = vec![0; self.count()];
1169                 for i in 0..self.count() {
1170                     inverse_big[memory_index[i] as usize] = i as u32;
1171                 }
1172             }
1173         }
1174
1175         (0..self.count()).map(move |i| match *self {
1176             FieldsShape::Primitive | FieldsShape::Union(_) | FieldsShape::Array { .. } => i,
1177             FieldsShape::Arbitrary { .. } => {
1178                 if use_small {
1179                     inverse_small[i] as usize
1180                 } else {
1181                     inverse_big[i] as usize
1182                 }
1183             }
1184         })
1185     }
1186 }
1187
1188 /// An identifier that specifies the address space that some operation
1189 /// should operate on. Special address spaces have an effect on code generation,
1190 /// depending on the target and the address spaces it implements.
1191 #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
1192 pub struct AddressSpace(pub u32);
1193
1194 impl AddressSpace {
1195     /// The default address space, corresponding to data space.
1196     pub const DATA: Self = AddressSpace(0);
1197 }
1198
1199 /// Describes how values of the type are passed by target ABIs,
1200 /// in terms of categories of C types there are ABI rules for.
1201 #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
1202 #[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
1203
1204 pub enum Abi {
1205     Uninhabited,
1206     Scalar(Scalar),
1207     ScalarPair(Scalar, Scalar),
1208     Vector {
1209         element: Scalar,
1210         count: u64,
1211     },
1212     Aggregate {
1213         /// If true, the size is exact, otherwise it's only a lower bound.
1214         sized: bool,
1215     },
1216 }
1217
1218 impl Abi {
1219     /// Returns `true` if the layout corresponds to an unsized type.
1220     #[inline]
1221     pub fn is_unsized(&self) -> bool {
1222         match *self {
1223             Abi::Uninhabited | Abi::Scalar(_) | Abi::ScalarPair(..) | Abi::Vector { .. } => false,
1224             Abi::Aggregate { sized } => !sized,
1225         }
1226     }
1227
1228     #[inline]
1229     pub fn is_sized(&self) -> bool {
1230         !self.is_unsized()
1231     }
1232
1233     /// Returns `true` if this is a single signed integer scalar
1234     #[inline]
1235     pub fn is_signed(&self) -> bool {
1236         match self {
1237             Abi::Scalar(scal) => match scal.primitive() {
1238                 Primitive::Int(_, signed) => signed,
1239                 _ => false,
1240             },
1241             _ => panic!("`is_signed` on non-scalar ABI {:?}", self),
1242         }
1243     }
1244
1245     /// Returns `true` if this is an uninhabited type
1246     #[inline]
1247     pub fn is_uninhabited(&self) -> bool {
1248         matches!(*self, Abi::Uninhabited)
1249     }
1250
1251     /// Returns `true` is this is a scalar type
1252     #[inline]
1253     pub fn is_scalar(&self) -> bool {
1254         matches!(*self, Abi::Scalar(_))
1255     }
1256 }
1257
1258 #[derive(PartialEq, Eq, Hash, Clone, Debug)]
1259 #[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
1260 pub enum Variants<V: Idx> {
1261     /// Single enum variants, structs/tuples, unions, and all non-ADTs.
1262     Single { index: V },
1263
1264     /// Enum-likes with more than one inhabited variant: each variant comes with
1265     /// a *discriminant* (usually the same as the variant index but the user can
1266     /// assign explicit discriminant values). That discriminant is encoded
1267     /// as a *tag* on the machine. The layout of each variant is
1268     /// a struct, and they all have space reserved for the tag.
1269     /// For enums, the tag is the sole field of the layout.
1270     Multiple {
1271         tag: Scalar,
1272         tag_encoding: TagEncoding<V>,
1273         tag_field: usize,
1274         variants: IndexVec<V, LayoutS<V>>,
1275     },
1276 }
1277
1278 #[derive(PartialEq, Eq, Hash, Clone, Debug)]
1279 #[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
1280 pub enum TagEncoding<V: Idx> {
1281     /// The tag directly stores the discriminant, but possibly with a smaller layout
1282     /// (so converting the tag to the discriminant can require sign extension).
1283     Direct,
1284
1285     /// Niche (values invalid for a type) encoding the discriminant:
1286     /// Discriminant and variant index coincide.
1287     /// The variant `untagged_variant` contains a niche at an arbitrary
1288     /// offset (field `tag_field` of the enum), which for a variant with
1289     /// discriminant `d` is set to
1290     /// `(d - niche_variants.start).wrapping_add(niche_start)`.
1291     ///
1292     /// For example, `Option<(usize, &T)>`  is represented such that
1293     /// `None` has a null pointer for the second tuple field, and
1294     /// `Some` is the identity function (with a non-null reference).
1295     Niche { untagged_variant: V, niche_variants: RangeInclusive<V>, niche_start: u128 },
1296 }
1297
1298 #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
1299 #[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
1300 pub struct Niche {
1301     pub offset: Size,
1302     pub value: Primitive,
1303     pub valid_range: WrappingRange,
1304 }
1305
1306 impl Niche {
1307     pub fn from_scalar<C: HasDataLayout>(cx: &C, offset: Size, scalar: Scalar) -> Option<Self> {
1308         let Scalar::Initialized { value, valid_range } = scalar else { return None };
1309         let niche = Niche { offset, value, valid_range };
1310         if niche.available(cx) > 0 { Some(niche) } else { None }
1311     }
1312
1313     pub fn available<C: HasDataLayout>(&self, cx: &C) -> u128 {
1314         let Self { value, valid_range: v, .. } = *self;
1315         let size = value.size(cx);
1316         assert!(size.bits() <= 128);
1317         let max_value = size.unsigned_int_max();
1318
1319         // Find out how many values are outside the valid range.
1320         let niche = v.end.wrapping_add(1)..v.start;
1321         niche.end.wrapping_sub(niche.start) & max_value
1322     }
1323
1324     pub fn reserve<C: HasDataLayout>(&self, cx: &C, count: u128) -> Option<(u128, Scalar)> {
1325         assert!(count > 0);
1326
1327         let Self { value, valid_range: v, .. } = *self;
1328         let size = value.size(cx);
1329         assert!(size.bits() <= 128);
1330         let max_value = size.unsigned_int_max();
1331
1332         let niche = v.end.wrapping_add(1)..v.start;
1333         let available = niche.end.wrapping_sub(niche.start) & max_value;
1334         if count > available {
1335             return None;
1336         }
1337
1338         // Extend the range of valid values being reserved by moving either `v.start` or `v.end` bound.
1339         // Given an eventual `Option<T>`, we try to maximize the chance for `None` to occupy the niche of zero.
1340         // This is accomplished by preferring enums with 2 variants(`count==1`) and always taking the shortest path to niche zero.
1341         // Having `None` in niche zero can enable some special optimizations.
1342         //
1343         // Bound selection criteria:
1344         // 1. Select closest to zero given wrapping semantics.
1345         // 2. Avoid moving past zero if possible.
1346         //
1347         // In practice this means that enums with `count > 1` are unlikely to claim niche zero, since they have to fit perfectly.
1348         // If niche zero is already reserved, the selection of bounds are of little interest.
1349         let move_start = |v: WrappingRange| {
1350             let start = v.start.wrapping_sub(count) & max_value;
1351             Some((start, Scalar::Initialized { value, valid_range: v.with_start(start) }))
1352         };
1353         let move_end = |v: WrappingRange| {
1354             let start = v.end.wrapping_add(1) & max_value;
1355             let end = v.end.wrapping_add(count) & max_value;
1356             Some((start, Scalar::Initialized { value, valid_range: v.with_end(end) }))
1357         };
1358         let distance_end_zero = max_value - v.end;
1359         if v.start > v.end {
1360             // zero is unavailable because wrapping occurs
1361             move_end(v)
1362         } else if v.start <= distance_end_zero {
1363             if count <= v.start {
1364                 move_start(v)
1365             } else {
1366                 // moved past zero, use other bound
1367                 move_end(v)
1368             }
1369         } else {
1370             let end = v.end.wrapping_add(count) & max_value;
1371             let overshot_zero = (1..=v.end).contains(&end);
1372             if overshot_zero {
1373                 // moved past zero, use other bound
1374                 move_start(v)
1375             } else {
1376                 move_end(v)
1377             }
1378         }
1379     }
1380 }
1381
1382 #[derive(PartialEq, Eq, Hash, Clone)]
1383 #[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
1384 pub struct LayoutS<V: Idx> {
1385     /// Says where the fields are located within the layout.
1386     pub fields: FieldsShape,
1387
1388     /// Encodes information about multi-variant layouts.
1389     /// Even with `Multiple` variants, a layout still has its own fields! Those are then
1390     /// shared between all variants. One of them will be the discriminant,
1391     /// but e.g. generators can have more.
1392     ///
1393     /// To access all fields of this layout, both `fields` and the fields of the active variant
1394     /// must be taken into account.
1395     pub variants: Variants<V>,
1396
1397     /// The `abi` defines how this data is passed between functions, and it defines
1398     /// value restrictions via `valid_range`.
1399     ///
1400     /// Note that this is entirely orthogonal to the recursive structure defined by
1401     /// `variants` and `fields`; for example, `ManuallyDrop<Result<isize, isize>>` has
1402     /// `Abi::ScalarPair`! So, even with non-`Aggregate` `abi`, `fields` and `variants`
1403     /// have to be taken into account to find all fields of this layout.
1404     pub abi: Abi,
1405
1406     /// The leaf scalar with the largest number of invalid values
1407     /// (i.e. outside of its `valid_range`), if it exists.
1408     pub largest_niche: Option<Niche>,
1409
1410     pub align: AbiAndPrefAlign,
1411     pub size: Size,
1412 }
1413
1414 impl<V: Idx> LayoutS<V> {
1415     pub fn scalar<C: HasDataLayout>(cx: &C, scalar: Scalar) -> Self {
1416         let largest_niche = Niche::from_scalar(cx, Size::ZERO, scalar);
1417         let size = scalar.size(cx);
1418         let align = scalar.align(cx);
1419         LayoutS {
1420             variants: Variants::Single { index: V::new(0) },
1421             fields: FieldsShape::Primitive,
1422             abi: Abi::Scalar(scalar),
1423             largest_niche,
1424             size,
1425             align,
1426         }
1427     }
1428 }
1429
1430 impl<V: Idx> fmt::Debug for LayoutS<V> {
1431     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1432         // This is how `Layout` used to print before it become
1433         // `Interned<LayoutS>`. We print it like this to avoid having to update
1434         // expected output in a lot of tests.
1435         let LayoutS { size, align, abi, fields, largest_niche, variants } = self;
1436         f.debug_struct("Layout")
1437             .field("size", size)
1438             .field("align", align)
1439             .field("abi", abi)
1440             .field("fields", fields)
1441             .field("largest_niche", largest_niche)
1442             .field("variants", variants)
1443             .finish()
1444     }
1445 }
1446
1447 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
1448 pub enum PointerKind {
1449     /// Most general case, we know no restrictions to tell LLVM.
1450     SharedMutable,
1451
1452     /// `&T` where `T` contains no `UnsafeCell`, is `dereferenceable`, `noalias` and `readonly`.
1453     Frozen,
1454
1455     /// `&mut T` which is `dereferenceable` and `noalias` but not `readonly`.
1456     UniqueBorrowed,
1457
1458     /// `&mut !Unpin`, which is `dereferenceable` but neither `noalias` nor `readonly`.
1459     UniqueBorrowedPinned,
1460
1461     /// `Box<T>`, which is `noalias` (even on return types, unlike the above) but neither `readonly`
1462     /// nor `dereferenceable`.
1463     UniqueOwned,
1464 }
1465
1466 #[derive(Copy, Clone, Debug)]
1467 pub struct PointeeInfo {
1468     pub size: Size,
1469     pub align: Align,
1470     pub safe: Option<PointerKind>,
1471     pub address_space: AddressSpace,
1472 }
1473
1474 /// Used in `might_permit_raw_init` to indicate the kind of initialisation
1475 /// that is checked to be valid
1476 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
1477 pub enum InitKind {
1478     Zero,
1479     UninitMitigated0x01Fill,
1480 }
1481
1482 impl<V: Idx> LayoutS<V> {
1483     /// Returns `true` if the layout corresponds to an unsized type.
1484     pub fn is_unsized(&self) -> bool {
1485         self.abi.is_unsized()
1486     }
1487
1488     pub fn is_sized(&self) -> bool {
1489         self.abi.is_sized()
1490     }
1491
1492     /// Returns `true` if the type is a ZST and not unsized.
1493     pub fn is_zst(&self) -> bool {
1494         match self.abi {
1495             Abi::Scalar(_) | Abi::ScalarPair(..) | Abi::Vector { .. } => false,
1496             Abi::Uninhabited => self.size.bytes() == 0,
1497             Abi::Aggregate { sized } => sized && self.size.bytes() == 0,
1498         }
1499     }
1500 }
1501
1502 #[derive(Copy, Clone, Debug)]
1503 pub enum StructKind {
1504     /// A tuple, closure, or univariant which cannot be coerced to unsized.
1505     AlwaysSized,
1506     /// A univariant, the last field of which may be coerced to unsized.
1507     MaybeUnsized,
1508     /// A univariant, but with a prefix of an arbitrary size & alignment (e.g., enum tag).
1509     Prefixed(Size, Align),
1510 }