]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_target/src/abi/mod.rs
Rollup merge of #82403 - pnkfelix:rustbuild-emit-env-vars-on-verbose-verbose, r=Mark...
[rust.git] / compiler / rustc_target / src / abi / mod.rs
1 pub use Integer::*;
2 pub use Primitive::*;
3
4 use crate::spec::Target;
5
6 use std::convert::{TryFrom, TryInto};
7 use std::fmt;
8 use std::num::NonZeroUsize;
9 use std::ops::{Add, AddAssign, Deref, Mul, Range, RangeInclusive, Sub};
10 use std::str::FromStr;
11
12 use rustc_index::vec::{Idx, IndexVec};
13 use rustc_macros::HashStable_Generic;
14 use rustc_serialize::json::{Json, ToJson};
15 use rustc_span::Span;
16
17 pub mod call;
18
19 /// Parsed [Data layout](http://llvm.org/docs/LangRef.html#data-layout)
20 /// for a target, which contains everything needed to compute layouts.
21 pub struct TargetDataLayout {
22     pub endian: Endian,
23     pub i1_align: AbiAndPrefAlign,
24     pub i8_align: AbiAndPrefAlign,
25     pub i16_align: AbiAndPrefAlign,
26     pub i32_align: AbiAndPrefAlign,
27     pub i64_align: AbiAndPrefAlign,
28     pub i128_align: AbiAndPrefAlign,
29     pub f32_align: AbiAndPrefAlign,
30     pub f64_align: AbiAndPrefAlign,
31     pub pointer_size: Size,
32     pub pointer_align: AbiAndPrefAlign,
33     pub aggregate_align: AbiAndPrefAlign,
34
35     /// Alignments for vector types.
36     pub vector_align: Vec<(Size, AbiAndPrefAlign)>,
37
38     pub instruction_address_space: AddressSpace,
39 }
40
41 impl Default for TargetDataLayout {
42     /// Creates an instance of `TargetDataLayout`.
43     fn default() -> TargetDataLayout {
44         let align = |bits| Align::from_bits(bits).unwrap();
45         TargetDataLayout {
46             endian: Endian::Big,
47             i1_align: AbiAndPrefAlign::new(align(8)),
48             i8_align: AbiAndPrefAlign::new(align(8)),
49             i16_align: AbiAndPrefAlign::new(align(16)),
50             i32_align: AbiAndPrefAlign::new(align(32)),
51             i64_align: AbiAndPrefAlign { abi: align(32), pref: align(64) },
52             i128_align: AbiAndPrefAlign { abi: align(32), pref: align(64) },
53             f32_align: AbiAndPrefAlign::new(align(32)),
54             f64_align: AbiAndPrefAlign::new(align(64)),
55             pointer_size: Size::from_bits(64),
56             pointer_align: AbiAndPrefAlign::new(align(64)),
57             aggregate_align: AbiAndPrefAlign { abi: align(0), pref: align(64) },
58             vector_align: vec![
59                 (Size::from_bits(64), AbiAndPrefAlign::new(align(64))),
60                 (Size::from_bits(128), AbiAndPrefAlign::new(align(128))),
61             ],
62             instruction_address_space: AddressSpace::DATA,
63         }
64     }
65 }
66
67 impl TargetDataLayout {
68     pub fn parse(target: &Target) -> Result<TargetDataLayout, String> {
69         // Parse an address space index from a string.
70         let parse_address_space = |s: &str, cause: &str| {
71             s.parse::<u32>().map(AddressSpace).map_err(|err| {
72                 format!("invalid address space `{}` for `{}` in \"data-layout\": {}", s, cause, err)
73             })
74         };
75
76         // Parse a bit count from a string.
77         let parse_bits = |s: &str, kind: &str, cause: &str| {
78             s.parse::<u64>().map_err(|err| {
79                 format!("invalid {} `{}` for `{}` in \"data-layout\": {}", kind, s, cause, err)
80             })
81         };
82
83         // Parse a size string.
84         let size = |s: &str, cause: &str| parse_bits(s, "size", cause).map(Size::from_bits);
85
86         // Parse an alignment string.
87         let align = |s: &[&str], cause: &str| {
88             if s.is_empty() {
89                 return Err(format!("missing alignment for `{}` in \"data-layout\"", cause));
90             }
91             let align_from_bits = |bits| {
92                 Align::from_bits(bits).map_err(|err| {
93                     format!("invalid alignment for `{}` in \"data-layout\": {}", cause, err)
94                 })
95             };
96             let abi = parse_bits(s[0], "alignment", cause)?;
97             let pref = s.get(1).map_or(Ok(abi), |pref| parse_bits(pref, "alignment", cause))?;
98             Ok(AbiAndPrefAlign { abi: align_from_bits(abi)?, pref: align_from_bits(pref)? })
99         };
100
101         let mut dl = TargetDataLayout::default();
102         let mut i128_align_src = 64;
103         for spec in target.data_layout.split('-') {
104             let spec_parts = spec.split(':').collect::<Vec<_>>();
105
106             match &*spec_parts {
107                 ["e"] => dl.endian = Endian::Little,
108                 ["E"] => dl.endian = Endian::Big,
109                 [p] if p.starts_with('P') => {
110                     dl.instruction_address_space = parse_address_space(&p[1..], "P")?
111                 }
112                 ["a", ref a @ ..] => dl.aggregate_align = align(a, "a")?,
113                 ["f32", ref a @ ..] => dl.f32_align = align(a, "f32")?,
114                 ["f64", ref a @ ..] => dl.f64_align = align(a, "f64")?,
115                 [p @ "p", s, ref a @ ..] | [p @ "p0", s, ref a @ ..] => {
116                     dl.pointer_size = size(s, p)?;
117                     dl.pointer_align = align(a, p)?;
118                 }
119                 [s, ref a @ ..] if s.starts_with('i') => {
120                     let bits = match s[1..].parse::<u64>() {
121                         Ok(bits) => bits,
122                         Err(_) => {
123                             size(&s[1..], "i")?; // For the user error.
124                             continue;
125                         }
126                     };
127                     let a = align(a, s)?;
128                     match bits {
129                         1 => dl.i1_align = a,
130                         8 => dl.i8_align = a,
131                         16 => dl.i16_align = a,
132                         32 => dl.i32_align = a,
133                         64 => dl.i64_align = a,
134                         _ => {}
135                     }
136                     if bits >= i128_align_src && bits <= 128 {
137                         // Default alignment for i128 is decided by taking the alignment of
138                         // largest-sized i{64..=128}.
139                         i128_align_src = bits;
140                         dl.i128_align = a;
141                     }
142                 }
143                 [s, ref a @ ..] if s.starts_with('v') => {
144                     let v_size = size(&s[1..], "v")?;
145                     let a = align(a, s)?;
146                     if let Some(v) = dl.vector_align.iter_mut().find(|v| v.0 == v_size) {
147                         v.1 = a;
148                         continue;
149                     }
150                     // No existing entry, add a new one.
151                     dl.vector_align.push((v_size, a));
152                 }
153                 _ => {} // Ignore everything else.
154             }
155         }
156
157         // Perform consistency checks against the Target information.
158         if dl.endian != target.endian {
159             return Err(format!(
160                 "inconsistent target specification: \"data-layout\" claims \
161                  architecture is {}-endian, while \"target-endian\" is `{}`",
162                 dl.endian.as_str(),
163                 target.endian.as_str(),
164             ));
165         }
166
167         if dl.pointer_size.bits() != target.pointer_width.into() {
168             return Err(format!(
169                 "inconsistent target specification: \"data-layout\" claims \
170                  pointers are {}-bit, while \"target-pointer-width\" is `{}`",
171                 dl.pointer_size.bits(),
172                 target.pointer_width
173             ));
174         }
175
176         Ok(dl)
177     }
178
179     /// Returns exclusive upper bound on object size.
180     ///
181     /// The theoretical maximum object size is defined as the maximum positive `isize` value.
182     /// This ensures that the `offset` semantics remain well-defined by allowing it to correctly
183     /// index every address within an object along with one byte past the end, along with allowing
184     /// `isize` to store the difference between any two pointers into an object.
185     ///
186     /// The upper bound on 64-bit currently needs to be lower because LLVM uses a 64-bit integer
187     /// to represent object size in bits. It would need to be 1 << 61 to account for this, but is
188     /// currently conservatively bounded to 1 << 47 as that is enough to cover the current usable
189     /// address space on 64-bit ARMv8 and x86_64.
190     pub fn obj_size_bound(&self) -> u64 {
191         match self.pointer_size.bits() {
192             16 => 1 << 15,
193             32 => 1 << 31,
194             64 => 1 << 47,
195             bits => panic!("obj_size_bound: unknown pointer bit size {}", bits),
196         }
197     }
198
199     pub fn ptr_sized_integer(&self) -> Integer {
200         match self.pointer_size.bits() {
201             16 => I16,
202             32 => I32,
203             64 => I64,
204             bits => panic!("ptr_sized_integer: unknown pointer bit size {}", bits),
205         }
206     }
207
208     pub fn vector_align(&self, vec_size: Size) -> AbiAndPrefAlign {
209         for &(size, align) in &self.vector_align {
210             if size == vec_size {
211                 return align;
212             }
213         }
214         // Default to natural alignment, which is what LLVM does.
215         // That is, use the size, rounded up to a power of 2.
216         AbiAndPrefAlign::new(Align::from_bytes(vec_size.bytes().next_power_of_two()).unwrap())
217     }
218 }
219
220 pub trait HasDataLayout {
221     fn data_layout(&self) -> &TargetDataLayout;
222 }
223
224 impl HasDataLayout for TargetDataLayout {
225     fn data_layout(&self) -> &TargetDataLayout {
226         self
227     }
228 }
229
230 /// Endianness of the target, which must match cfg(target-endian).
231 #[derive(Copy, Clone, PartialEq)]
232 pub enum Endian {
233     Little,
234     Big,
235 }
236
237 impl Endian {
238     pub fn as_str(&self) -> &'static str {
239         match self {
240             Self::Little => "little",
241             Self::Big => "big",
242         }
243     }
244 }
245
246 impl fmt::Debug for Endian {
247     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
248         f.write_str(self.as_str())
249     }
250 }
251
252 impl FromStr for Endian {
253     type Err = String;
254
255     fn from_str(s: &str) -> Result<Self, Self::Err> {
256         match s {
257             "little" => Ok(Self::Little),
258             "big" => Ok(Self::Big),
259             _ => Err(format!(r#"unknown endian: "{}""#, s)),
260         }
261     }
262 }
263
264 impl ToJson for Endian {
265     fn to_json(&self) -> Json {
266         self.as_str().to_json()
267     }
268 }
269
270 /// Size of a type in bytes.
271 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Encodable, Decodable)]
272 #[derive(HashStable_Generic)]
273 pub struct Size {
274     // The top 3 bits are ALWAYS zero.
275     raw: u64,
276 }
277
278 impl Size {
279     pub const ZERO: Size = Size { raw: 0 };
280
281     /// Rounds `bits` up to the next-higher byte boundary, if `bits` is
282     /// is not aligned.
283     pub fn from_bits(bits: impl TryInto<u64>) -> Size {
284         let bits = bits.try_into().ok().unwrap();
285
286         #[cold]
287         fn overflow(bits: u64) -> ! {
288             panic!("Size::from_bits({}) has overflowed", bits);
289         }
290
291         // This is the largest value of `bits` that does not cause overflow
292         // during rounding, and guarantees that the resulting number of bytes
293         // cannot cause overflow when multiplied by 8.
294         if bits > 0xffff_ffff_ffff_fff8 {
295             overflow(bits);
296         }
297
298         // Avoid potential overflow from `bits + 7`.
299         Size { raw: bits / 8 + ((bits % 8) + 7) / 8 }
300     }
301
302     #[inline]
303     pub fn from_bytes(bytes: impl TryInto<u64>) -> Size {
304         let bytes: u64 = bytes.try_into().ok().unwrap();
305         Size { raw: bytes }
306     }
307
308     #[inline]
309     pub fn bytes(self) -> u64 {
310         self.raw
311     }
312
313     #[inline]
314     pub fn bytes_usize(self) -> usize {
315         self.bytes().try_into().unwrap()
316     }
317
318     #[inline]
319     pub fn bits(self) -> u64 {
320         self.raw << 3
321     }
322
323     #[inline]
324     pub fn bits_usize(self) -> usize {
325         self.bits().try_into().unwrap()
326     }
327
328     #[inline]
329     pub fn align_to(self, align: Align) -> Size {
330         let mask = align.bytes() - 1;
331         Size::from_bytes((self.bytes() + mask) & !mask)
332     }
333
334     #[inline]
335     pub fn is_aligned(self, align: Align) -> bool {
336         let mask = align.bytes() - 1;
337         self.bytes() & mask == 0
338     }
339
340     #[inline]
341     pub fn checked_add<C: HasDataLayout>(self, offset: Size, cx: &C) -> Option<Size> {
342         let dl = cx.data_layout();
343
344         let bytes = self.bytes().checked_add(offset.bytes())?;
345
346         if bytes < dl.obj_size_bound() { Some(Size::from_bytes(bytes)) } else { None }
347     }
348
349     #[inline]
350     pub fn checked_mul<C: HasDataLayout>(self, count: u64, cx: &C) -> Option<Size> {
351         let dl = cx.data_layout();
352
353         let bytes = self.bytes().checked_mul(count)?;
354         if bytes < dl.obj_size_bound() { Some(Size::from_bytes(bytes)) } else { None }
355     }
356
357     /// Truncates `value` to `self` bits and then sign-extends it to 128 bits
358     /// (i.e., if it is negative, fill with 1's on the left).
359     #[inline]
360     pub fn sign_extend(self, value: u128) -> u128 {
361         let size = self.bits();
362         if size == 0 {
363             // Truncated until nothing is left.
364             return 0;
365         }
366         // Sign-extend it.
367         let shift = 128 - size;
368         // Shift the unsigned value to the left, then shift back to the right as signed
369         // (essentially fills with sign bit on the left).
370         (((value << shift) as i128) >> shift) as u128
371     }
372
373     /// Truncates `value` to `self` bits.
374     #[inline]
375     pub fn truncate(self, value: u128) -> u128 {
376         let size = self.bits();
377         if size == 0 {
378             // Truncated until nothing is left.
379             return 0;
380         }
381         let shift = 128 - size;
382         // Truncate (shift left to drop out leftover values, shift right to fill with zeroes).
383         (value << shift) >> shift
384     }
385 }
386
387 // Panicking addition, subtraction and multiplication for convenience.
388 // Avoid during layout computation, return `LayoutError` instead.
389
390 impl Add for Size {
391     type Output = Size;
392     #[inline]
393     fn add(self, other: Size) -> Size {
394         Size::from_bytes(self.bytes().checked_add(other.bytes()).unwrap_or_else(|| {
395             panic!("Size::add: {} + {} doesn't fit in u64", self.bytes(), other.bytes())
396         }))
397     }
398 }
399
400 impl Sub for Size {
401     type Output = Size;
402     #[inline]
403     fn sub(self, other: Size) -> Size {
404         Size::from_bytes(self.bytes().checked_sub(other.bytes()).unwrap_or_else(|| {
405             panic!("Size::sub: {} - {} would result in negative size", self.bytes(), other.bytes())
406         }))
407     }
408 }
409
410 impl Mul<Size> for u64 {
411     type Output = Size;
412     #[inline]
413     fn mul(self, size: Size) -> Size {
414         size * self
415     }
416 }
417
418 impl Mul<u64> for Size {
419     type Output = Size;
420     #[inline]
421     fn mul(self, count: u64) -> Size {
422         match self.bytes().checked_mul(count) {
423             Some(bytes) => Size::from_bytes(bytes),
424             None => panic!("Size::mul: {} * {} doesn't fit in u64", self.bytes(), count),
425         }
426     }
427 }
428
429 impl AddAssign for Size {
430     #[inline]
431     fn add_assign(&mut self, other: Size) {
432         *self = *self + other;
433     }
434 }
435
436 /// Alignment of a type in bytes (always a power of two).
437 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Encodable, Decodable)]
438 #[derive(HashStable_Generic)]
439 pub struct Align {
440     pow2: u8,
441 }
442
443 impl Align {
444     #[inline]
445     pub fn from_bits(bits: u64) -> Result<Align, String> {
446         Align::from_bytes(Size::from_bits(bits).bytes())
447     }
448
449     #[inline]
450     pub fn from_bytes(align: u64) -> Result<Align, String> {
451         // Treat an alignment of 0 bytes like 1-byte alignment.
452         if align == 0 {
453             return Ok(Align { pow2: 0 });
454         }
455
456         #[cold]
457         fn not_power_of_2(align: u64) -> String {
458             format!("`{}` is not a power of 2", align)
459         }
460
461         #[cold]
462         fn too_large(align: u64) -> String {
463             format!("`{}` is too large", align)
464         }
465
466         let mut bytes = align;
467         let mut pow2: u8 = 0;
468         while (bytes & 1) == 0 {
469             pow2 += 1;
470             bytes >>= 1;
471         }
472         if bytes != 1 {
473             return Err(not_power_of_2(align));
474         }
475         if pow2 > 29 {
476             return Err(too_large(align));
477         }
478
479         Ok(Align { pow2 })
480     }
481
482     #[inline]
483     pub fn bytes(self) -> u64 {
484         1 << self.pow2
485     }
486
487     #[inline]
488     pub fn bits(self) -> u64 {
489         self.bytes() * 8
490     }
491
492     /// Computes the best alignment possible for the given offset
493     /// (the largest power of two that the offset is a multiple of).
494     ///
495     /// N.B., for an offset of `0`, this happens to return `2^64`.
496     #[inline]
497     pub fn max_for_offset(offset: Size) -> Align {
498         Align { pow2: offset.bytes().trailing_zeros() as u8 }
499     }
500
501     /// Lower the alignment, if necessary, such that the given offset
502     /// is aligned to it (the offset is a multiple of the alignment).
503     #[inline]
504     pub fn restrict_for_offset(self, offset: Size) -> Align {
505         self.min(Align::max_for_offset(offset))
506     }
507 }
508
509 /// A pair of alignments, ABI-mandated and preferred.
510 #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, Encodable, Decodable)]
511 #[derive(HashStable_Generic)]
512 pub struct AbiAndPrefAlign {
513     pub abi: Align,
514     pub pref: Align,
515 }
516
517 impl AbiAndPrefAlign {
518     pub fn new(align: Align) -> AbiAndPrefAlign {
519         AbiAndPrefAlign { abi: align, pref: align }
520     }
521
522     pub fn min(self, other: AbiAndPrefAlign) -> AbiAndPrefAlign {
523         AbiAndPrefAlign { abi: self.abi.min(other.abi), pref: self.pref.min(other.pref) }
524     }
525
526     pub fn max(self, other: AbiAndPrefAlign) -> AbiAndPrefAlign {
527         AbiAndPrefAlign { abi: self.abi.max(other.abi), pref: self.pref.max(other.pref) }
528     }
529 }
530
531 /// Integers, also used for enum discriminants.
532 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, HashStable_Generic)]
533 pub enum Integer {
534     I8,
535     I16,
536     I32,
537     I64,
538     I128,
539 }
540
541 impl Integer {
542     pub fn size(self) -> Size {
543         match self {
544             I8 => Size::from_bytes(1),
545             I16 => Size::from_bytes(2),
546             I32 => Size::from_bytes(4),
547             I64 => Size::from_bytes(8),
548             I128 => Size::from_bytes(16),
549         }
550     }
551
552     pub fn align<C: HasDataLayout>(self, cx: &C) -> AbiAndPrefAlign {
553         let dl = cx.data_layout();
554
555         match self {
556             I8 => dl.i8_align,
557             I16 => dl.i16_align,
558             I32 => dl.i32_align,
559             I64 => dl.i64_align,
560             I128 => dl.i128_align,
561         }
562     }
563
564     /// Finds the smallest Integer type which can represent the signed value.
565     pub fn fit_signed(x: i128) -> Integer {
566         match x {
567             -0x0000_0000_0000_0080..=0x0000_0000_0000_007f => I8,
568             -0x0000_0000_0000_8000..=0x0000_0000_0000_7fff => I16,
569             -0x0000_0000_8000_0000..=0x0000_0000_7fff_ffff => I32,
570             -0x8000_0000_0000_0000..=0x7fff_ffff_ffff_ffff => I64,
571             _ => I128,
572         }
573     }
574
575     /// Finds the smallest Integer type which can represent the unsigned value.
576     pub fn fit_unsigned(x: u128) -> Integer {
577         match x {
578             0..=0x0000_0000_0000_00ff => I8,
579             0..=0x0000_0000_0000_ffff => I16,
580             0..=0x0000_0000_ffff_ffff => I32,
581             0..=0xffff_ffff_ffff_ffff => I64,
582             _ => I128,
583         }
584     }
585
586     /// Finds the smallest integer with the given alignment.
587     pub fn for_align<C: HasDataLayout>(cx: &C, wanted: Align) -> Option<Integer> {
588         let dl = cx.data_layout();
589
590         for &candidate in &[I8, I16, I32, I64, I128] {
591             if wanted == candidate.align(dl).abi && wanted.bytes() == candidate.size().bytes() {
592                 return Some(candidate);
593             }
594         }
595         None
596     }
597
598     /// Find the largest integer with the given alignment or less.
599     pub fn approximate_align<C: HasDataLayout>(cx: &C, wanted: Align) -> Integer {
600         let dl = cx.data_layout();
601
602         // FIXME(eddyb) maybe include I128 in the future, when it works everywhere.
603         for &candidate in &[I64, I32, I16] {
604             if wanted >= candidate.align(dl).abi && wanted.bytes() >= candidate.size().bytes() {
605                 return candidate;
606             }
607         }
608         I8
609     }
610 }
611
612 /// Fundamental unit of memory access and layout.
613 #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
614 pub enum Primitive {
615     /// The `bool` is the signedness of the `Integer` type.
616     ///
617     /// One would think we would not care about such details this low down,
618     /// but some ABIs are described in terms of C types and ISAs where the
619     /// integer arithmetic is done on {sign,zero}-extended registers, e.g.
620     /// a negative integer passed by zero-extension will appear positive in
621     /// the callee, and most operations on it will produce the wrong values.
622     Int(Integer, bool),
623     F32,
624     F64,
625     Pointer,
626 }
627
628 impl Primitive {
629     pub fn size<C: HasDataLayout>(self, cx: &C) -> Size {
630         let dl = cx.data_layout();
631
632         match self {
633             Int(i, _) => i.size(),
634             F32 => Size::from_bits(32),
635             F64 => Size::from_bits(64),
636             Pointer => dl.pointer_size,
637         }
638     }
639
640     pub fn align<C: HasDataLayout>(self, cx: &C) -> AbiAndPrefAlign {
641         let dl = cx.data_layout();
642
643         match self {
644             Int(i, _) => i.align(dl),
645             F32 => dl.f32_align,
646             F64 => dl.f64_align,
647             Pointer => dl.pointer_align,
648         }
649     }
650
651     pub fn is_float(self) -> bool {
652         matches!(self, F32 | F64)
653     }
654
655     pub fn is_int(self) -> bool {
656         matches!(self, Int(..))
657     }
658 }
659
660 /// Information about one scalar component of a Rust type.
661 #[derive(Clone, PartialEq, Eq, Hash, Debug)]
662 #[derive(HashStable_Generic)]
663 pub struct Scalar {
664     pub value: Primitive,
665
666     /// Inclusive wrap-around range of valid values, that is, if
667     /// start > end, it represents `start..=MAX`,
668     /// followed by `0..=end`.
669     ///
670     /// That is, for an i8 primitive, a range of `254..=2` means following
671     /// sequence:
672     ///
673     ///    254 (-2), 255 (-1), 0, 1, 2
674     ///
675     /// This is intended specifically to mirror LLVM’s `!range` metadata,
676     /// semantics.
677     // FIXME(eddyb) always use the shortest range, e.g., by finding
678     // the largest space between two consecutive valid values and
679     // taking everything else as the (shortest) valid range.
680     pub valid_range: RangeInclusive<u128>,
681 }
682
683 impl Scalar {
684     pub fn is_bool(&self) -> bool {
685         matches!(self.value, Int(I8, false)) && self.valid_range == (0..=1)
686     }
687
688     /// Returns the valid range as a `x..y` range.
689     ///
690     /// If `x` and `y` are equal, the range is full, not empty.
691     pub fn valid_range_exclusive<C: HasDataLayout>(&self, cx: &C) -> Range<u128> {
692         // For a (max) value of -1, max will be `-1 as usize`, which overflows.
693         // However, that is fine here (it would still represent the full range),
694         // i.e., if the range is everything.
695         let bits = self.value.size(cx).bits();
696         assert!(bits <= 128);
697         let mask = !0u128 >> (128 - bits);
698         let start = *self.valid_range.start();
699         let end = *self.valid_range.end();
700         assert_eq!(start, start & mask);
701         assert_eq!(end, end & mask);
702         start..(end.wrapping_add(1) & mask)
703     }
704 }
705
706 /// Describes how the fields of a type are located in memory.
707 #[derive(PartialEq, Eq, Hash, Debug, HashStable_Generic)]
708 pub enum FieldsShape {
709     /// Scalar primitives and `!`, which never have fields.
710     Primitive,
711
712     /// All fields start at no offset. The `usize` is the field count.
713     Union(NonZeroUsize),
714
715     /// Array/vector-like placement, with all fields of identical types.
716     Array { stride: Size, count: u64 },
717
718     /// Struct-like placement, with precomputed offsets.
719     ///
720     /// Fields are guaranteed to not overlap, but note that gaps
721     /// before, between and after all the fields are NOT always
722     /// padding, and as such their contents may not be discarded.
723     /// For example, enum variants leave a gap at the start,
724     /// where the discriminant field in the enum layout goes.
725     Arbitrary {
726         /// Offsets for the first byte of each field,
727         /// ordered to match the source definition order.
728         /// This vector does not go in increasing order.
729         // FIXME(eddyb) use small vector optimization for the common case.
730         offsets: Vec<Size>,
731
732         /// Maps source order field indices to memory order indices,
733         /// depending on how the fields were reordered (if at all).
734         /// This is a permutation, with both the source order and the
735         /// memory order using the same (0..n) index ranges.
736         ///
737         /// Note that during computation of `memory_index`, sometimes
738         /// it is easier to operate on the inverse mapping (that is,
739         /// from memory order to source order), and that is usually
740         /// named `inverse_memory_index`.
741         ///
742         // FIXME(eddyb) build a better abstraction for permutations, if possible.
743         // FIXME(camlorn) also consider small vector  optimization here.
744         memory_index: Vec<u32>,
745     },
746 }
747
748 impl FieldsShape {
749     pub fn count(&self) -> usize {
750         match *self {
751             FieldsShape::Primitive => 0,
752             FieldsShape::Union(count) => count.get(),
753             FieldsShape::Array { count, .. } => {
754                 let usize_count = count as usize;
755                 assert_eq!(usize_count as u64, count);
756                 usize_count
757             }
758             FieldsShape::Arbitrary { ref offsets, .. } => offsets.len(),
759         }
760     }
761
762     pub fn offset(&self, i: usize) -> Size {
763         match *self {
764             FieldsShape::Primitive => {
765                 unreachable!("FieldsShape::offset: `Primitive`s have no fields")
766             }
767             FieldsShape::Union(count) => {
768                 assert!(
769                     i < count.get(),
770                     "tried to access field {} of union with {} fields",
771                     i,
772                     count
773                 );
774                 Size::ZERO
775             }
776             FieldsShape::Array { stride, count } => {
777                 let i = u64::try_from(i).unwrap();
778                 assert!(i < count);
779                 stride * i
780             }
781             FieldsShape::Arbitrary { ref offsets, .. } => offsets[i],
782         }
783     }
784
785     pub fn memory_index(&self, i: usize) -> usize {
786         match *self {
787             FieldsShape::Primitive => {
788                 unreachable!("FieldsShape::memory_index: `Primitive`s have no fields")
789             }
790             FieldsShape::Union(_) | FieldsShape::Array { .. } => i,
791             FieldsShape::Arbitrary { ref memory_index, .. } => {
792                 let r = memory_index[i];
793                 assert_eq!(r as usize as u32, r);
794                 r as usize
795             }
796         }
797     }
798
799     /// Gets source indices of the fields by increasing offsets.
800     #[inline]
801     pub fn index_by_increasing_offset<'a>(&'a self) -> impl Iterator<Item = usize> + 'a {
802         let mut inverse_small = [0u8; 64];
803         let mut inverse_big = vec![];
804         let use_small = self.count() <= inverse_small.len();
805
806         // We have to write this logic twice in order to keep the array small.
807         if let FieldsShape::Arbitrary { ref memory_index, .. } = *self {
808             if use_small {
809                 for i in 0..self.count() {
810                     inverse_small[memory_index[i] as usize] = i as u8;
811                 }
812             } else {
813                 inverse_big = vec![0; self.count()];
814                 for i in 0..self.count() {
815                     inverse_big[memory_index[i] as usize] = i as u32;
816                 }
817             }
818         }
819
820         (0..self.count()).map(move |i| match *self {
821             FieldsShape::Primitive | FieldsShape::Union(_) | FieldsShape::Array { .. } => i,
822             FieldsShape::Arbitrary { .. } => {
823                 if use_small {
824                     inverse_small[i] as usize
825                 } else {
826                     inverse_big[i] as usize
827                 }
828             }
829         })
830     }
831 }
832
833 /// An identifier that specifies the address space that some operation
834 /// should operate on. Special address spaces have an effect on code generation,
835 /// depending on the target and the address spaces it implements.
836 #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
837 pub struct AddressSpace(pub u32);
838
839 impl AddressSpace {
840     /// The default address space, corresponding to data space.
841     pub const DATA: Self = AddressSpace(0);
842 }
843
844 /// Describes how values of the type are passed by target ABIs,
845 /// in terms of categories of C types there are ABI rules for.
846 #[derive(Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
847 pub enum Abi {
848     Uninhabited,
849     Scalar(Scalar),
850     ScalarPair(Scalar, Scalar),
851     Vector {
852         element: Scalar,
853         count: u64,
854     },
855     Aggregate {
856         /// If true, the size is exact, otherwise it's only a lower bound.
857         sized: bool,
858     },
859 }
860
861 impl Abi {
862     /// Returns `true` if the layout corresponds to an unsized type.
863     pub fn is_unsized(&self) -> bool {
864         match *self {
865             Abi::Uninhabited | Abi::Scalar(_) | Abi::ScalarPair(..) | Abi::Vector { .. } => false,
866             Abi::Aggregate { sized } => !sized,
867         }
868     }
869
870     /// Returns `true` if this is a single signed integer scalar
871     pub fn is_signed(&self) -> bool {
872         match *self {
873             Abi::Scalar(ref scal) => match scal.value {
874                 Primitive::Int(_, signed) => signed,
875                 _ => false,
876             },
877             _ => panic!("`is_signed` on non-scalar ABI {:?}", self),
878         }
879     }
880
881     /// Returns `true` if this is an uninhabited type
882     pub fn is_uninhabited(&self) -> bool {
883         matches!(*self, Abi::Uninhabited)
884     }
885
886     /// Returns `true` is this is a scalar type
887     pub fn is_scalar(&self) -> bool {
888         matches!(*self, Abi::Scalar(_))
889     }
890 }
891
892 rustc_index::newtype_index! {
893     pub struct VariantIdx {
894         derive [HashStable_Generic]
895     }
896 }
897
898 #[derive(PartialEq, Eq, Hash, Debug, HashStable_Generic)]
899 pub enum Variants {
900     /// Single enum variants, structs/tuples, unions, and all non-ADTs.
901     Single { index: VariantIdx },
902
903     /// Enum-likes with more than one inhabited variant: each variant comes with
904     /// a *discriminant* (usually the same as the variant index but the user can
905     /// assign explicit discriminant values).  That discriminant is encoded
906     /// as a *tag* on the machine.  The layout of each variant is
907     /// a struct, and they all have space reserved for the tag.
908     /// For enums, the tag is the sole field of the layout.
909     Multiple {
910         tag: Scalar,
911         tag_encoding: TagEncoding,
912         tag_field: usize,
913         variants: IndexVec<VariantIdx, Layout>,
914     },
915 }
916
917 #[derive(PartialEq, Eq, Hash, Debug, HashStable_Generic)]
918 pub enum TagEncoding {
919     /// The tag directly stores the discriminant, but possibly with a smaller layout
920     /// (so converting the tag to the discriminant can require sign extension).
921     Direct,
922
923     /// Niche (values invalid for a type) encoding the discriminant:
924     /// Discriminant and variant index coincide.
925     /// The variant `dataful_variant` contains a niche at an arbitrary
926     /// offset (field `tag_field` of the enum), which for a variant with
927     /// discriminant `d` is set to
928     /// `(d - niche_variants.start).wrapping_add(niche_start)`.
929     ///
930     /// For example, `Option<(usize, &T)>`  is represented such that
931     /// `None` has a null pointer for the second tuple field, and
932     /// `Some` is the identity function (with a non-null reference).
933     Niche {
934         dataful_variant: VariantIdx,
935         niche_variants: RangeInclusive<VariantIdx>,
936         niche_start: u128,
937     },
938 }
939
940 #[derive(Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
941 pub struct Niche {
942     pub offset: Size,
943     pub scalar: Scalar,
944 }
945
946 impl Niche {
947     pub fn from_scalar<C: HasDataLayout>(cx: &C, offset: Size, scalar: Scalar) -> Option<Self> {
948         let niche = Niche { offset, scalar };
949         if niche.available(cx) > 0 { Some(niche) } else { None }
950     }
951
952     pub fn available<C: HasDataLayout>(&self, cx: &C) -> u128 {
953         let Scalar { value, valid_range: ref v } = self.scalar;
954         let bits = value.size(cx).bits();
955         assert!(bits <= 128);
956         let max_value = !0u128 >> (128 - bits);
957
958         // Find out how many values are outside the valid range.
959         let niche = v.end().wrapping_add(1)..*v.start();
960         niche.end.wrapping_sub(niche.start) & max_value
961     }
962
963     pub fn reserve<C: HasDataLayout>(&self, cx: &C, count: u128) -> Option<(u128, Scalar)> {
964         assert!(count > 0);
965
966         let Scalar { value, valid_range: ref v } = self.scalar;
967         let bits = value.size(cx).bits();
968         assert!(bits <= 128);
969         let max_value = !0u128 >> (128 - bits);
970
971         if count > max_value {
972             return None;
973         }
974
975         // Compute the range of invalid values being reserved.
976         let start = v.end().wrapping_add(1) & max_value;
977         let end = v.end().wrapping_add(count) & max_value;
978
979         // If the `end` of our range is inside the valid range,
980         // then we ran out of invalid values.
981         // FIXME(eddyb) abstract this with a wraparound range type.
982         let valid_range_contains = |x| {
983             if v.start() <= v.end() {
984                 *v.start() <= x && x <= *v.end()
985             } else {
986                 *v.start() <= x || x <= *v.end()
987             }
988         };
989         if valid_range_contains(end) {
990             return None;
991         }
992
993         Some((start, Scalar { value, valid_range: *v.start()..=end }))
994     }
995 }
996
997 #[derive(PartialEq, Eq, Hash, Debug, HashStable_Generic)]
998 pub struct Layout {
999     /// Says where the fields are located within the layout.
1000     pub fields: FieldsShape,
1001
1002     /// Encodes information about multi-variant layouts.
1003     /// Even with `Multiple` variants, a layout still has its own fields! Those are then
1004     /// shared between all variants. One of them will be the discriminant,
1005     /// but e.g. generators can have more.
1006     ///
1007     /// To access all fields of this layout, both `fields` and the fields of the active variant
1008     /// must be taken into account.
1009     pub variants: Variants,
1010
1011     /// The `abi` defines how this data is passed between functions, and it defines
1012     /// value restrictions via `valid_range`.
1013     ///
1014     /// Note that this is entirely orthogonal to the recursive structure defined by
1015     /// `variants` and `fields`; for example, `ManuallyDrop<Result<isize, isize>>` has
1016     /// `Abi::ScalarPair`! So, even with non-`Aggregate` `abi`, `fields` and `variants`
1017     /// have to be taken into account to find all fields of this layout.
1018     pub abi: Abi,
1019
1020     /// The leaf scalar with the largest number of invalid values
1021     /// (i.e. outside of its `valid_range`), if it exists.
1022     pub largest_niche: Option<Niche>,
1023
1024     pub align: AbiAndPrefAlign,
1025     pub size: Size,
1026 }
1027
1028 impl Layout {
1029     pub fn scalar<C: HasDataLayout>(cx: &C, scalar: Scalar) -> Self {
1030         let largest_niche = Niche::from_scalar(cx, Size::ZERO, scalar.clone());
1031         let size = scalar.value.size(cx);
1032         let align = scalar.value.align(cx);
1033         Layout {
1034             variants: Variants::Single { index: VariantIdx::new(0) },
1035             fields: FieldsShape::Primitive,
1036             abi: Abi::Scalar(scalar),
1037             largest_niche,
1038             size,
1039             align,
1040         }
1041     }
1042 }
1043
1044 /// The layout of a type, alongside the type itself.
1045 /// Provides various type traversal APIs (e.g., recursing into fields).
1046 ///
1047 /// Note that the layout is NOT guaranteed to always be identical
1048 /// to that obtained from `layout_of(ty)`, as we need to produce
1049 /// layouts for which Rust types do not exist, such as enum variants
1050 /// or synthetic fields of enums (i.e., discriminants) and fat pointers.
1051 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
1052 pub struct TyAndLayout<'a, Ty> {
1053     pub ty: Ty,
1054     pub layout: &'a Layout,
1055 }
1056
1057 impl<'a, Ty> Deref for TyAndLayout<'a, Ty> {
1058     type Target = &'a Layout;
1059     fn deref(&self) -> &&'a Layout {
1060         &self.layout
1061     }
1062 }
1063
1064 /// Trait for context types that can compute layouts of things.
1065 pub trait LayoutOf {
1066     type Ty;
1067     type TyAndLayout;
1068
1069     fn layout_of(&self, ty: Self::Ty) -> Self::TyAndLayout;
1070     fn spanned_layout_of(&self, ty: Self::Ty, _span: Span) -> Self::TyAndLayout {
1071         self.layout_of(ty)
1072     }
1073 }
1074
1075 /// The `TyAndLayout` above will always be a `MaybeResult<TyAndLayout<'_, Self>>`.
1076 /// We can't add the bound due to the lifetime, but this trait is still useful when
1077 /// writing code that's generic over the `LayoutOf` impl.
1078 pub trait MaybeResult<T> {
1079     type Error;
1080
1081     fn from(x: Result<T, Self::Error>) -> Self;
1082     fn to_result(self) -> Result<T, Self::Error>;
1083 }
1084
1085 impl<T> MaybeResult<T> for T {
1086     type Error = !;
1087
1088     fn from(Ok(x): Result<T, Self::Error>) -> Self {
1089         x
1090     }
1091     fn to_result(self) -> Result<T, Self::Error> {
1092         Ok(self)
1093     }
1094 }
1095
1096 impl<T, E> MaybeResult<T> for Result<T, E> {
1097     type Error = E;
1098
1099     fn from(x: Result<T, Self::Error>) -> Self {
1100         x
1101     }
1102     fn to_result(self) -> Result<T, Self::Error> {
1103         self
1104     }
1105 }
1106
1107 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
1108 pub enum PointerKind {
1109     /// Most general case, we know no restrictions to tell LLVM.
1110     Shared,
1111
1112     /// `&T` where `T` contains no `UnsafeCell`, is `noalias` and `readonly`.
1113     Frozen,
1114
1115     /// `&mut T`, when we know `noalias` is safe for LLVM.
1116     UniqueBorrowed,
1117
1118     /// `Box<T>`, unlike `UniqueBorrowed`, it also has `noalias` on returns.
1119     UniqueOwned,
1120 }
1121
1122 #[derive(Copy, Clone, Debug)]
1123 pub struct PointeeInfo {
1124     pub size: Size,
1125     pub align: Align,
1126     pub safe: Option<PointerKind>,
1127     pub address_space: AddressSpace,
1128 }
1129
1130 pub trait TyAndLayoutMethods<'a, C: LayoutOf<Ty = Self>>: Sized {
1131     fn for_variant(
1132         this: TyAndLayout<'a, Self>,
1133         cx: &C,
1134         variant_index: VariantIdx,
1135     ) -> TyAndLayout<'a, Self>;
1136     fn field(this: TyAndLayout<'a, Self>, cx: &C, i: usize) -> C::TyAndLayout;
1137     fn pointee_info_at(this: TyAndLayout<'a, Self>, cx: &C, offset: Size) -> Option<PointeeInfo>;
1138 }
1139
1140 impl<'a, Ty> TyAndLayout<'a, Ty> {
1141     pub fn for_variant<C>(self, cx: &C, variant_index: VariantIdx) -> Self
1142     where
1143         Ty: TyAndLayoutMethods<'a, C>,
1144         C: LayoutOf<Ty = Ty>,
1145     {
1146         Ty::for_variant(self, cx, variant_index)
1147     }
1148
1149     /// Callers might want to use `C: LayoutOf<Ty=Ty, TyAndLayout: MaybeResult<Self>>`
1150     /// to allow recursion (see `might_permit_zero_init` below for an example).
1151     pub fn field<C>(self, cx: &C, i: usize) -> C::TyAndLayout
1152     where
1153         Ty: TyAndLayoutMethods<'a, C>,
1154         C: LayoutOf<Ty = Ty>,
1155     {
1156         Ty::field(self, cx, i)
1157     }
1158
1159     pub fn pointee_info_at<C>(self, cx: &C, offset: Size) -> Option<PointeeInfo>
1160     where
1161         Ty: TyAndLayoutMethods<'a, C>,
1162         C: LayoutOf<Ty = Ty>,
1163     {
1164         Ty::pointee_info_at(self, cx, offset)
1165     }
1166 }
1167
1168 impl<'a, Ty> TyAndLayout<'a, Ty> {
1169     /// Returns `true` if the layout corresponds to an unsized type.
1170     pub fn is_unsized(&self) -> bool {
1171         self.abi.is_unsized()
1172     }
1173
1174     /// Returns `true` if the type is a ZST and not unsized.
1175     pub fn is_zst(&self) -> bool {
1176         match self.abi {
1177             Abi::Scalar(_) | Abi::ScalarPair(..) | Abi::Vector { .. } => false,
1178             Abi::Uninhabited => self.size.bytes() == 0,
1179             Abi::Aggregate { sized } => sized && self.size.bytes() == 0,
1180         }
1181     }
1182
1183     /// Determines if this type permits "raw" initialization by just transmuting some
1184     /// memory into an instance of `T`.
1185     /// `zero` indicates if the memory is zero-initialized, or alternatively
1186     /// left entirely uninitialized.
1187     /// This is conservative: in doubt, it will answer `true`.
1188     ///
1189     /// FIXME: Once we removed all the conservatism, we could alternatively
1190     /// create an all-0/all-undef constant and run the const value validator to see if
1191     /// this is a valid value for the given type.
1192     pub fn might_permit_raw_init<C, E>(self, cx: &C, zero: bool) -> Result<bool, E>
1193     where
1194         Self: Copy,
1195         Ty: TyAndLayoutMethods<'a, C>,
1196         C: LayoutOf<Ty = Ty, TyAndLayout: MaybeResult<Self, Error = E>> + HasDataLayout,
1197     {
1198         let scalar_allows_raw_init = move |s: &Scalar| -> bool {
1199             if zero {
1200                 let range = &s.valid_range;
1201                 // The range must contain 0.
1202                 range.contains(&0) || (*range.start() > *range.end()) // wrap-around allows 0
1203             } else {
1204                 // The range must include all values. `valid_range_exclusive` handles
1205                 // the wrap-around using target arithmetic; with wrap-around then the full
1206                 // range is one where `start == end`.
1207                 let range = s.valid_range_exclusive(cx);
1208                 range.start == range.end
1209             }
1210         };
1211
1212         // Check the ABI.
1213         let valid = match &self.abi {
1214             Abi::Uninhabited => false, // definitely UB
1215             Abi::Scalar(s) => scalar_allows_raw_init(s),
1216             Abi::ScalarPair(s1, s2) => scalar_allows_raw_init(s1) && scalar_allows_raw_init(s2),
1217             Abi::Vector { element: s, count } => *count == 0 || scalar_allows_raw_init(s),
1218             Abi::Aggregate { .. } => true, // Fields are checked below.
1219         };
1220         if !valid {
1221             // This is definitely not okay.
1222             return Ok(false);
1223         }
1224
1225         // If we have not found an error yet, we need to recursively descend into fields.
1226         match &self.fields {
1227             FieldsShape::Primitive | FieldsShape::Union { .. } => {}
1228             FieldsShape::Array { .. } => {
1229                 // FIXME(#66151): For now, we are conservative and do not check arrays.
1230             }
1231             FieldsShape::Arbitrary { offsets, .. } => {
1232                 for idx in 0..offsets.len() {
1233                     let field = self.field(cx, idx).to_result()?;
1234                     if !field.might_permit_raw_init(cx, zero)? {
1235                         // We found a field that is unhappy with this kind of initialization.
1236                         return Ok(false);
1237                     }
1238                 }
1239             }
1240         }
1241
1242         // FIXME(#66151): For now, we are conservative and do not check `self.variants`.
1243         Ok(true)
1244     }
1245 }