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