]> git.lizzy.rs Git - rust.git/blob - src/librustc/ty/layout.rs
571ef30b6b9096356a0f92b216088c5d6571d036
[rust.git] / src / librustc / ty / layout.rs
1 // Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 pub use self::Integer::*;
12 pub use self::Layout::*;
13 pub use self::Primitive::*;
14
15 use infer::InferCtxt;
16 use session::Session;
17 use traits;
18 use ty::{self, Ty, TyCtxt, TypeFoldable, ReprOptions};
19
20 use syntax::ast::{FloatTy, IntTy, UintTy};
21 use syntax::attr;
22 use syntax_pos::DUMMY_SP;
23
24 use std::cmp;
25 use std::fmt;
26 use std::i64;
27 use std::iter;
28
29 /// Parsed [Data layout](http://llvm.org/docs/LangRef.html#data-layout)
30 /// for a target, which contains everything needed to compute layouts.
31 pub struct TargetDataLayout {
32     pub endian: Endian,
33     pub i1_align: Align,
34     pub i8_align: Align,
35     pub i16_align: Align,
36     pub i32_align: Align,
37     pub i64_align: Align,
38     pub i128_align: Align,
39     pub f32_align: Align,
40     pub f64_align: Align,
41     pub pointer_size: Size,
42     pub pointer_align: Align,
43     pub aggregate_align: Align,
44
45     /// Alignments for vector types.
46     pub vector_align: Vec<(Size, Align)>
47 }
48
49 impl Default for TargetDataLayout {
50     /// Creates an instance of `TargetDataLayout`.
51     fn default() -> TargetDataLayout {
52         TargetDataLayout {
53             endian: Endian::Big,
54             i1_align: Align::from_bits(8, 8).unwrap(),
55             i8_align: Align::from_bits(8, 8).unwrap(),
56             i16_align: Align::from_bits(16, 16).unwrap(),
57             i32_align: Align::from_bits(32, 32).unwrap(),
58             i64_align: Align::from_bits(32, 64).unwrap(),
59             i128_align: Align::from_bits(32, 64).unwrap(),
60             f32_align: Align::from_bits(32, 32).unwrap(),
61             f64_align: Align::from_bits(64, 64).unwrap(),
62             pointer_size: Size::from_bits(64),
63             pointer_align: Align::from_bits(64, 64).unwrap(),
64             aggregate_align: Align::from_bits(0, 64).unwrap(),
65             vector_align: vec![
66                 (Size::from_bits(64), Align::from_bits(64, 64).unwrap()),
67                 (Size::from_bits(128), Align::from_bits(128, 128).unwrap())
68             ]
69         }
70     }
71 }
72
73 impl TargetDataLayout {
74     pub fn parse(sess: &Session) -> TargetDataLayout {
75         // Parse a bit count from a string.
76         let parse_bits = |s: &str, kind: &str, cause: &str| {
77             s.parse::<u64>().unwrap_or_else(|err| {
78                 sess.err(&format!("invalid {} `{}` for `{}` in \"data-layout\": {}",
79                                   kind, s, cause, err));
80                 0
81             })
82         };
83
84         // Parse a size string.
85         let size = |s: &str, cause: &str| {
86             Size::from_bits(parse_bits(s, "size", cause))
87         };
88
89         // Parse an alignment string.
90         let align = |s: &[&str], cause: &str| {
91             if s.is_empty() {
92                 sess.err(&format!("missing alignment for `{}` in \"data-layout\"", cause));
93             }
94             let abi = parse_bits(s[0], "alignment", cause);
95             let pref = s.get(1).map_or(abi, |pref| parse_bits(pref, "alignment", cause));
96             Align::from_bits(abi, pref).unwrap_or_else(|err| {
97                 sess.err(&format!("invalid alignment for `{}` in \"data-layout\": {}",
98                                   cause, err));
99                 Align::from_bits(8, 8).unwrap()
100             })
101         };
102
103         let mut dl = TargetDataLayout::default();
104         let mut i128_align_src = 64;
105         for spec in sess.target.target.data_layout.split("-") {
106             match &spec.split(":").collect::<Vec<_>>()[..] {
107                 &["e"] => dl.endian = Endian::Little,
108                 &["E"] => dl.endian = Endian::Big,
109                 &["a", ref a..] => dl.aggregate_align = align(a, "a"),
110                 &["f32", ref a..] => dl.f32_align = align(a, "f32"),
111                 &["f64", ref a..] => dl.f64_align = align(a, "f64"),
112                 &[p @ "p", s, ref a..] | &[p @ "p0", s, ref a..] => {
113                     dl.pointer_size = size(s, p);
114                     dl.pointer_align = align(a, p);
115                 }
116                 &[s, ref a..] if s.starts_with("i") => {
117                     let bits = match s[1..].parse::<u64>() {
118                         Ok(bits) => bits,
119                         Err(_) => {
120                             size(&s[1..], "i"); // For the user error.
121                             continue;
122                         }
123                     };
124                     let a = align(a, s);
125                     match bits {
126                         1 => dl.i1_align = a,
127                         8 => dl.i8_align = a,
128                         16 => dl.i16_align = a,
129                         32 => dl.i32_align = a,
130                         64 => dl.i64_align = a,
131                         _ => {}
132                     }
133                     if bits >= i128_align_src && bits <= 128 {
134                         // Default alignment for i128 is decided by taking the alignment of
135                         // largest-sized i{64...128}.
136                         i128_align_src = bits;
137                         dl.i128_align = a;
138                     }
139                 }
140                 &[s, ref a..] if s.starts_with("v") => {
141                     let v_size = size(&s[1..], "v");
142                     let a = align(a, s);
143                     if let Some(v) = dl.vector_align.iter_mut().find(|v| v.0 == v_size) {
144                         v.1 = a;
145                         continue;
146                     }
147                     // No existing entry, add a new one.
148                     dl.vector_align.push((v_size, a));
149                 }
150                 _ => {} // Ignore everything else.
151             }
152         }
153
154         // Perform consistency checks against the Target information.
155         let endian_str = match dl.endian {
156             Endian::Little => "little",
157             Endian::Big => "big"
158         };
159         if endian_str != sess.target.target.target_endian {
160             sess.err(&format!("inconsistent target specification: \"data-layout\" claims \
161                                architecture is {}-endian, while \"target-endian\" is `{}`",
162                               endian_str, sess.target.target.target_endian));
163         }
164
165         if dl.pointer_size.bits().to_string() != sess.target.target.target_pointer_width {
166             sess.err(&format!("inconsistent target specification: \"data-layout\" claims \
167                                pointers are {}-bit, while \"target-pointer-width\" is `{}`",
168                               dl.pointer_size.bits(), sess.target.target.target_pointer_width));
169         }
170
171         dl
172     }
173
174     /// Return exclusive upper bound on object size.
175     ///
176     /// The theoretical maximum object size is defined as the maximum positive `isize` value.
177     /// This ensures that the `offset` semantics remain well-defined by allowing it to correctly
178     /// index every address within an object along with one byte past the end, along with allowing
179     /// `isize` to store the difference between any two pointers into an object.
180     ///
181     /// The upper bound on 64-bit currently needs to be lower because LLVM uses a 64-bit integer
182     /// to represent object size in bits. It would need to be 1 << 61 to account for this, but is
183     /// currently conservatively bounded to 1 << 47 as that is enough to cover the current usable
184     /// address space on 64-bit ARMv8 and x86_64.
185     pub fn obj_size_bound(&self) -> u64 {
186         match self.pointer_size.bits() {
187             16 => 1 << 15,
188             32 => 1 << 31,
189             64 => 1 << 47,
190             bits => bug!("obj_size_bound: unknown pointer bit size {}", bits)
191         }
192     }
193
194     pub fn ptr_sized_integer(&self) -> Integer {
195         match self.pointer_size.bits() {
196             16 => I16,
197             32 => I32,
198             64 => I64,
199             bits => bug!("ptr_sized_integer: unknown pointer bit size {}", bits)
200         }
201     }
202 }
203
204 /// Endianness of the target, which must match cfg(target-endian).
205 #[derive(Copy, Clone)]
206 pub enum Endian {
207     Little,
208     Big
209 }
210
211 /// Size of a type in bytes.
212 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
213 pub struct Size {
214     raw: u64
215 }
216
217 impl Size {
218     pub fn from_bits(bits: u64) -> Size {
219         Size::from_bytes((bits + 7) / 8)
220     }
221
222     pub fn from_bytes(bytes: u64) -> Size {
223         if bytes >= (1 << 61) {
224             bug!("Size::from_bytes: {} bytes in bits doesn't fit in u64", bytes)
225         }
226         Size {
227             raw: bytes
228         }
229     }
230
231     pub fn bytes(self) -> u64 {
232         self.raw
233     }
234
235     pub fn bits(self) -> u64 {
236         self.bytes() * 8
237     }
238
239     pub fn abi_align(self, align: Align) -> Size {
240         let mask = align.abi() - 1;
241         Size::from_bytes((self.bytes() + mask) & !mask)
242     }
243
244     pub fn checked_add(self, offset: Size, dl: &TargetDataLayout) -> Option<Size> {
245         // Each Size is less than dl.obj_size_bound(), so the sum is
246         // also less than 1 << 62 (and therefore can't overflow).
247         let bytes = self.bytes() + offset.bytes();
248
249         if bytes < dl.obj_size_bound() {
250             Some(Size::from_bytes(bytes))
251         } else {
252             None
253         }
254     }
255
256     pub fn checked_mul(self, count: u64, dl: &TargetDataLayout) -> Option<Size> {
257         // Each Size is less than dl.obj_size_bound(), so the sum is
258         // also less than 1 << 62 (and therefore can't overflow).
259         match self.bytes().checked_mul(count) {
260             Some(bytes) if bytes < dl.obj_size_bound() => {
261                 Some(Size::from_bytes(bytes))
262             }
263             _ => None
264         }
265     }
266 }
267
268 /// Alignment of a type in bytes, both ABI-mandated and preferred.
269 /// Since alignments are always powers of 2, we can pack both in one byte,
270 /// giving each a nibble (4 bits) for a maximum alignment of 2<sup>15</sup> = 32768.
271 #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
272 pub struct Align {
273     raw: u8
274 }
275
276 impl Align {
277     pub fn from_bits(abi: u64, pref: u64) -> Result<Align, String> {
278         Align::from_bytes((abi + 7) / 8, (pref + 7) / 8)
279     }
280
281     pub fn from_bytes(abi: u64, pref: u64) -> Result<Align, String> {
282         let pack = |align: u64| {
283             // Treat an alignment of 0 bytes like 1-byte alignment.
284             if align == 0 {
285                 return Ok(0);
286             }
287
288             let mut bytes = align;
289             let mut pow: u8 = 0;
290             while (bytes & 1) == 0 {
291                 pow += 1;
292                 bytes >>= 1;
293             }
294             if bytes != 1 {
295                 Err(format!("`{}` is not a power of 2", align))
296             } else if pow > 0x0f {
297                 Err(format!("`{}` is too large", align))
298             } else {
299                 Ok(pow)
300             }
301         };
302
303         Ok(Align {
304             raw: pack(abi)? | (pack(pref)? << 4)
305         })
306     }
307
308     pub fn abi(self) -> u64 {
309         1 << (self.raw & 0xf)
310     }
311
312     pub fn pref(self) -> u64 {
313         1 << (self.raw >> 4)
314     }
315
316     pub fn min(self, other: Align) -> Align {
317         let abi = cmp::min(self.raw & 0x0f, other.raw & 0x0f);
318         let pref = cmp::min(self.raw & 0xf0, other.raw & 0xf0);
319         Align {
320             raw: abi | pref
321         }
322     }
323
324     pub fn max(self, other: Align) -> Align {
325         let abi = cmp::max(self.raw & 0x0f, other.raw & 0x0f);
326         let pref = cmp::max(self.raw & 0xf0, other.raw & 0xf0);
327         Align {
328             raw: abi | pref
329         }
330     }
331 }
332
333 /// Integers, also used for enum discriminants.
334 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
335 pub enum Integer {
336     I1,
337     I8,
338     I16,
339     I32,
340     I64,
341     I128,
342 }
343
344 impl Integer {
345     pub fn size(&self) -> Size {
346         match *self {
347             I1 => Size::from_bits(1),
348             I8 => Size::from_bytes(1),
349             I16 => Size::from_bytes(2),
350             I32 => Size::from_bytes(4),
351             I64  => Size::from_bytes(8),
352             I128  => Size::from_bytes(16),
353         }
354     }
355
356     pub fn align(&self, dl: &TargetDataLayout)-> Align {
357         match *self {
358             I1 => dl.i1_align,
359             I8 => dl.i8_align,
360             I16 => dl.i16_align,
361             I32 => dl.i32_align,
362             I64 => dl.i64_align,
363             I128 => dl.i128_align,
364         }
365     }
366
367     pub fn to_ty<'a, 'tcx>(&self, tcx: &ty::TyCtxt<'a, 'tcx, 'tcx>,
368                            signed: bool) -> Ty<'tcx> {
369         match (*self, signed) {
370             (I1, false) => tcx.types.u8,
371             (I8, false) => tcx.types.u8,
372             (I16, false) => tcx.types.u16,
373             (I32, false) => tcx.types.u32,
374             (I64, false) => tcx.types.u64,
375             (I128, false) => tcx.types.u128,
376             (I1, true) => tcx.types.i8,
377             (I8, true) => tcx.types.i8,
378             (I16, true) => tcx.types.i16,
379             (I32, true) => tcx.types.i32,
380             (I64, true) => tcx.types.i64,
381             (I128, true) => tcx.types.i128,
382         }
383     }
384
385     /// Find the smallest Integer type which can represent the signed value.
386     pub fn fit_signed(x: i64) -> Integer {
387         match x {
388             -0x0000_0000_0000_0001...0x0000_0000_0000_0000 => I1,
389             -0x0000_0000_0000_0080...0x0000_0000_0000_007f => I8,
390             -0x0000_0000_0000_8000...0x0000_0000_0000_7fff => I16,
391             -0x0000_0000_8000_0000...0x0000_0000_7fff_ffff => I32,
392             -0x8000_0000_0000_0000...0x7fff_ffff_ffff_ffff => I64,
393             _ => I128
394         }
395     }
396
397     /// Find the smallest Integer type which can represent the unsigned value.
398     pub fn fit_unsigned(x: u64) -> Integer {
399         match x {
400             0...0x0000_0000_0000_0001 => I1,
401             0...0x0000_0000_0000_00ff => I8,
402             0...0x0000_0000_0000_ffff => I16,
403             0...0x0000_0000_ffff_ffff => I32,
404             0...0xffff_ffff_ffff_ffff => I64,
405             _ => I128,
406         }
407     }
408
409     /// Find the smallest integer with the given alignment.
410     pub fn for_abi_align(dl: &TargetDataLayout, align: Align) -> Option<Integer> {
411         let wanted = align.abi();
412         for &candidate in &[I8, I16, I32, I64] {
413             let ty = Int(candidate);
414             if wanted == ty.align(dl).abi() && wanted == ty.size(dl).bytes() {
415                 return Some(candidate);
416             }
417         }
418         None
419     }
420
421     /// Get the Integer type from an attr::IntType.
422     pub fn from_attr(dl: &TargetDataLayout, ity: attr::IntType) -> Integer {
423         match ity {
424             attr::SignedInt(IntTy::I8) | attr::UnsignedInt(UintTy::U8) => I8,
425             attr::SignedInt(IntTy::I16) | attr::UnsignedInt(UintTy::U16) => I16,
426             attr::SignedInt(IntTy::I32) | attr::UnsignedInt(UintTy::U32) => I32,
427             attr::SignedInt(IntTy::I64) | attr::UnsignedInt(UintTy::U64) => I64,
428             attr::SignedInt(IntTy::I128) | attr::UnsignedInt(UintTy::U128) => I128,
429             attr::SignedInt(IntTy::Is) | attr::UnsignedInt(UintTy::Us) => {
430                 dl.ptr_sized_integer()
431             }
432         }
433     }
434
435     /// Find the appropriate Integer type and signedness for the given
436     /// signed discriminant range and #[repr] attribute.
437     /// N.B.: u64 values above i64::MAX will be treated as signed, but
438     /// that shouldn't affect anything, other than maybe debuginfo.
439     fn repr_discr(tcx: TyCtxt, ty: Ty, repr: &ReprOptions, min: i64, max: i64)
440                       -> (Integer, bool) {
441         // Theoretically, negative values could be larger in unsigned representation
442         // than the unsigned representation of the signed minimum. However, if there
443         // are any negative values, the only valid unsigned representation is u64
444         // which can fit all i64 values, so the result remains unaffected.
445         let unsigned_fit = Integer::fit_unsigned(cmp::max(min as u64, max as u64));
446         let signed_fit = cmp::max(Integer::fit_signed(min), Integer::fit_signed(max));
447
448         let mut min_from_extern = None;
449         let min_default = I8;
450
451         if let Some(ity) = repr.int {
452             let discr = Integer::from_attr(&tcx.data_layout, ity);
453             let fit = if ity.is_signed() { signed_fit } else { unsigned_fit };
454             if discr < fit {
455                 bug!("Integer::repr_discr: `#[repr]` hint too small for \
456                   discriminant range of enum `{}", ty)
457             }
458             return (discr, ity.is_signed());
459         }
460
461         if repr.c {
462             match &tcx.sess.target.target.arch[..] {
463                 // WARNING: the ARM EABI has two variants; the one corresponding
464                 // to `at_least == I32` appears to be used on Linux and NetBSD,
465                 // but some systems may use the variant corresponding to no
466                 // lower bound.  However, we don't run on those yet...?
467                 "arm" => min_from_extern = Some(I32),
468                 _ => min_from_extern = Some(I32),
469             }
470         }
471
472         let at_least = min_from_extern.unwrap_or(min_default);
473
474         // If there are no negative values, we can use the unsigned fit.
475         if min >= 0 {
476             (cmp::max(unsigned_fit, at_least), false)
477         } else {
478             (cmp::max(signed_fit, at_least), true)
479         }
480     }
481 }
482
483 /// Fundamental unit of memory access and layout.
484 #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
485 pub enum Primitive {
486     Int(Integer),
487     F32,
488     F64,
489     Pointer
490 }
491
492 impl Primitive {
493     pub fn size(self, dl: &TargetDataLayout) -> Size {
494         match self {
495             Int(I1) | Int(I8) => Size::from_bits(8),
496             Int(I16) => Size::from_bits(16),
497             Int(I32) | F32 => Size::from_bits(32),
498             Int(I64) | F64 => Size::from_bits(64),
499             Int(I128) => Size::from_bits(128),
500             Pointer => dl.pointer_size
501         }
502     }
503
504     pub fn align(self, dl: &TargetDataLayout) -> Align {
505         match self {
506             Int(I1) => dl.i1_align,
507             Int(I8) => dl.i8_align,
508             Int(I16) => dl.i16_align,
509             Int(I32) => dl.i32_align,
510             Int(I64) => dl.i64_align,
511             Int(I128) => dl.i128_align,
512             F32 => dl.f32_align,
513             F64 => dl.f64_align,
514             Pointer => dl.pointer_align
515         }
516     }
517 }
518
519 /// Path through fields of nested structures.
520 // FIXME(eddyb) use small vector optimization for the common case.
521 pub type FieldPath = Vec<u32>;
522
523 /// A structure, a product type in ADT terms.
524 #[derive(PartialEq, Eq, Hash, Debug)]
525 pub struct Struct {
526     pub align: Align,
527
528     /// If true, no alignment padding is used.
529     pub packed: bool,
530
531     /// If true, the size is exact, otherwise it's only a lower bound.
532     pub sized: bool,
533
534     /// Offsets for the first byte of each field, ordered to match the source definition order.
535     /// This vector does not go in increasing order.
536     /// FIXME(eddyb) use small vector optimization for the common case.
537     pub offsets: Vec<Size>,
538
539     /// Maps source order field indices to memory order indices, depending how fields were permuted.
540     /// FIXME (camlorn) also consider small vector  optimization here.
541     pub memory_index: Vec<u32>,
542
543     pub min_size: Size,
544 }
545
546 // Info required to optimize struct layout.
547 #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug)]
548 enum StructKind {
549     // A tuple, closure, or univariant which cannot be coerced to unsized.
550     AlwaysSizedUnivariant,
551     // A univariant, the last field of which may be coerced to unsized.
552     MaybeUnsizedUnivariant,
553     // A univariant, but part of an enum.
554     EnumVariant,
555 }
556
557 impl<'a, 'gcx, 'tcx> Struct {
558     // FIXME(camlorn): reprs need a better representation to deal with multiple reprs on one type.
559     fn new(dl: &TargetDataLayout, fields: &Vec<&'a Layout>,
560                   repr: &ReprOptions, kind: StructKind,
561                   scapegoat: Ty<'gcx>) -> Result<Struct, LayoutError<'gcx>> {
562         let packed = repr.packed;
563         let mut ret = Struct {
564             align: if packed { dl.i8_align } else { dl.aggregate_align },
565             packed: packed,
566             sized: true,
567             offsets: vec![],
568             memory_index: vec![],
569             min_size: Size::from_bytes(0),
570         };
571
572         // Anything with repr(C) or repr(packed) doesn't optimize.
573         // Neither do  1-member and 2-member structs.
574         // In addition, code in trans assume that 2-element structs can become pairs.
575         // It's easier to just short-circuit here.
576         let mut can_optimize = (fields.len() > 2 || StructKind::EnumVariant == kind)
577             && ! (repr.c || repr.packed);
578
579         // Disable field reordering until we can decide what to do.
580         // The odd pattern here avoids a warning about the value never being read.
581         if can_optimize { can_optimize = false; }
582
583         let (optimize, sort_ascending) = match kind {
584             StructKind::AlwaysSizedUnivariant => (can_optimize, false),
585             StructKind::MaybeUnsizedUnivariant => (can_optimize, false),
586             StructKind::EnumVariant => {
587                 assert!(fields.len() >= 1, "Enum variants must have discriminants.");
588                 (can_optimize && fields[0].size(dl).bytes() == 1, true)
589             }
590         };
591
592         ret.offsets = vec![Size::from_bytes(0); fields.len()];
593         let mut inverse_memory_index: Vec<u32> = (0..fields.len() as u32).collect();
594
595         if optimize {
596             let start = if let StructKind::EnumVariant = kind { 1 } else { 0 };
597             let end = if let StructKind::MaybeUnsizedUnivariant = kind {
598                 fields.len() - 1
599             } else {
600                 fields.len()
601             };
602             if end > start {
603                 let optimizing  = &mut inverse_memory_index[start..end];
604                 if sort_ascending {
605                     optimizing.sort_by_key(|&x| fields[x as usize].align(dl).abi());
606                 } else {
607                     optimizing.sort_by(| &a, &b | {
608                         let a = fields[a as usize].align(dl).abi();
609                         let b = fields[b as usize].align(dl).abi();
610                         b.cmp(&a)
611                     });
612                 }
613             }
614         }
615
616         // inverse_memory_index holds field indices by increasing memory offset.
617         // That is, if field 5 has offset 0, the first element of inverse_memory_index is 5.
618         // We now write field offsets to the corresponding offset slot;
619         // field 5 with offset 0 puts 0 in offsets[5].
620         // At the bottom of this function, we use inverse_memory_index to produce memory_index.
621
622         if let StructKind::EnumVariant = kind {
623             assert_eq!(inverse_memory_index[0], 0,
624               "Enum variant discriminants must have the lowest offset.");
625         }
626
627         let mut offset = Size::from_bytes(0);
628
629         for i in inverse_memory_index.iter() {
630             let field = fields[*i as usize];
631             if !ret.sized {
632                 bug!("Struct::new: field #{} of `{}` comes after unsized field",
633                      ret.offsets.len(), scapegoat);
634             }
635
636             if field.is_unsized() {
637                 ret.sized = false;
638             }
639
640             // Invariant: offset < dl.obj_size_bound() <= 1<<61
641             if !ret.packed {
642                 let align = field.align(dl);
643                 ret.align = ret.align.max(align);
644                 offset = offset.abi_align(align);
645             }
646
647             debug!("Struct::new offset: {:?} field: {:?} {:?}", offset, field, field.size(dl));
648             ret.offsets[*i as usize] = offset;
649
650             offset = offset.checked_add(field.size(dl), dl)
651                            .map_or(Err(LayoutError::SizeOverflow(scapegoat)), Ok)?;
652         }
653
654
655         debug!("Struct::new min_size: {:?}", offset);
656         ret.min_size = offset;
657
658         // As stated above, inverse_memory_index holds field indices by increasing offset.
659         // This makes it an already-sorted view of the offsets vec.
660         // To invert it, consider:
661         // If field 5 has offset 0, offsets[0] is 5, and memory_index[5] should be 0.
662         // Field 5 would be the first element, so memory_index is i:
663         // Note: if we didn't optimize, it's already right.
664
665         if optimize {
666             ret.memory_index = vec![0; inverse_memory_index.len()];
667
668             for i in 0..inverse_memory_index.len() {
669                 ret.memory_index[inverse_memory_index[i] as usize]  = i as u32;
670             }
671         } else {
672             ret.memory_index = inverse_memory_index;
673         }
674
675         Ok(ret)
676     }
677
678     /// Get the size with trailing alignment padding.
679     pub fn stride(&self) -> Size {
680         self.min_size.abi_align(self.align)
681     }
682
683     /// Determine whether a structure would be zero-sized, given its fields.
684     pub fn would_be_zero_sized<I>(dl: &TargetDataLayout, fields: I)
685                                   -> Result<bool, LayoutError<'gcx>>
686     where I: Iterator<Item=Result<&'a Layout, LayoutError<'gcx>>> {
687         for field in fields {
688             let field = field?;
689             if field.is_unsized() || field.size(dl).bytes() > 0 {
690                 return Ok(false);
691             }
692         }
693         Ok(true)
694     }
695
696     /// Get indices of the tys that made this struct by increasing offset.
697     #[inline]
698     pub fn field_index_by_increasing_offset<'b>(&'b self) -> impl iter::Iterator<Item=usize>+'b {
699         let mut inverse_small = [0u8; 64];
700         let mut inverse_big = vec![];
701         let use_small = self.memory_index.len() <= inverse_small.len();
702
703         // We have to write this logic twice in order to keep the array small.
704         if use_small {
705             for i in 0..self.memory_index.len() {
706                 inverse_small[self.memory_index[i] as usize] = i as u8;
707             }
708         } else {
709             inverse_big = vec![0; self.memory_index.len()];
710             for i in 0..self.memory_index.len() {
711                 inverse_big[self.memory_index[i] as usize] = i as u32;
712             }
713         }
714
715         (0..self.memory_index.len()).map(move |i| {
716             if use_small { inverse_small[i] as usize }
717             else { inverse_big[i] as usize }
718         })
719     }
720
721     /// Find the path leading to a non-zero leaf field, starting from
722     /// the given type and recursing through aggregates.
723     /// The tuple is `(path, source_path)`,
724     /// where `path` is in memory order and `source_path` in source order.
725     // FIXME(eddyb) track value ranges and traverse already optimized enums.
726     fn non_zero_field_in_type(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
727                                ty: Ty<'gcx>)
728                                -> Result<Option<(FieldPath, FieldPath)>, LayoutError<'gcx>> {
729         let tcx = infcx.tcx.global_tcx();
730         match (ty.layout(infcx)?, &ty.sty) {
731             (&Scalar { non_zero: true, .. }, _) |
732             (&CEnum { non_zero: true, .. }, _) => Ok(Some((vec![], vec![]))),
733             (&FatPointer { non_zero: true, .. }, _) => {
734                 Ok(Some((vec![FAT_PTR_ADDR as u32], vec![FAT_PTR_ADDR as u32])))
735             }
736
737             // Is this the NonZero lang item wrapping a pointer or integer type?
738             (&Univariant { non_zero: true, .. }, &ty::TyAdt(def, substs)) => {
739                 let fields = &def.struct_variant().fields;
740                 assert_eq!(fields.len(), 1);
741                 match *fields[0].ty(tcx, substs).layout(infcx)? {
742                     // FIXME(eddyb) also allow floating-point types here.
743                     Scalar { value: Int(_), non_zero: false } |
744                     Scalar { value: Pointer, non_zero: false } => {
745                         Ok(Some((vec![0], vec![0])))
746                     }
747                     FatPointer { non_zero: false, .. } => {
748                         let tmp = vec![FAT_PTR_ADDR as u32, 0];
749                         Ok(Some((tmp.clone(), tmp)))
750                     }
751                     _ => Ok(None)
752                 }
753             }
754
755             // Perhaps one of the fields of this struct is non-zero
756             // let's recurse and find out
757             (&Univariant { ref variant, .. }, &ty::TyAdt(def, substs)) if def.is_struct() => {
758                 Struct::non_zero_field_paths(infcx, def.struct_variant().fields
759                                                       .iter().map(|field| {
760                     field.ty(tcx, substs)
761                 }),
762                 Some(&variant.memory_index[..]))
763             }
764
765             // Perhaps one of the upvars of this closure is non-zero
766             (&Univariant { ref variant, .. }, &ty::TyClosure(def, substs)) => {
767                 let upvar_tys = substs.upvar_tys(def, tcx);
768                 Struct::non_zero_field_paths(infcx, upvar_tys,
769                     Some(&variant.memory_index[..]))
770             }
771             // Can we use one of the fields in this tuple?
772             (&Univariant { ref variant, .. }, &ty::TyTuple(tys, _)) => {
773                 Struct::non_zero_field_paths(infcx, tys.iter().cloned(),
774                     Some(&variant.memory_index[..]))
775             }
776
777             // Is this a fixed-size array of something non-zero
778             // with at least one element?
779             (_, &ty::TyArray(ety, d)) if d > 0 => {
780                 Struct::non_zero_field_paths(infcx, Some(ety).into_iter(), None)
781             }
782
783             (_, &ty::TyProjection(_)) | (_, &ty::TyAnon(..)) => {
784                 let normalized = normalize_associated_type(infcx, ty);
785                 if ty == normalized {
786                     return Ok(None);
787                 }
788                 return Struct::non_zero_field_in_type(infcx, normalized);
789             }
790
791             // Anything else is not a non-zero type.
792             _ => Ok(None)
793         }
794     }
795
796     /// Find the path leading to a non-zero leaf field, starting from
797     /// the given set of fields and recursing through aggregates.
798     /// Returns Some((path, source_path)) on success.
799     /// `path` is translated to memory order. `source_path` is not.
800     fn non_zero_field_paths<I>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
801                                   fields: I,
802                                   permutation: Option<&[u32]>)
803                                   -> Result<Option<(FieldPath, FieldPath)>, LayoutError<'gcx>>
804     where I: Iterator<Item=Ty<'gcx>> {
805         for (i, ty) in fields.enumerate() {
806             if let Some((mut path, mut source_path)) = Struct::non_zero_field_in_type(infcx, ty)? {
807                 source_path.push(i as u32);
808                 let index = if let Some(p) = permutation {
809                     p[i] as usize
810                 } else {
811                     i
812                 };
813                 path.push(index as u32);
814                 return Ok(Some((path, source_path)));
815             }
816         }
817         Ok(None)
818     }
819 }
820
821 /// An untagged union.
822 #[derive(PartialEq, Eq, Hash, Debug)]
823 pub struct Union {
824     pub align: Align,
825
826     pub min_size: Size,
827
828     /// If true, no alignment padding is used.
829     pub packed: bool,
830 }
831
832 impl<'a, 'gcx, 'tcx> Union {
833     pub fn new(dl: &TargetDataLayout, packed: bool) -> Union {
834         Union {
835             align: if packed { dl.i8_align } else { dl.aggregate_align },
836             min_size: Size::from_bytes(0),
837             packed: packed,
838         }
839     }
840
841     /// Extend the Struct with more fields.
842     pub fn extend<I>(&mut self, dl: &TargetDataLayout,
843                      fields: I,
844                      scapegoat: Ty<'gcx>)
845                      -> Result<(), LayoutError<'gcx>>
846     where I: Iterator<Item=Result<&'a Layout, LayoutError<'gcx>>> {
847         for (index, field) in fields.enumerate() {
848             let field = field?;
849             if field.is_unsized() {
850                 bug!("Union::extend: field #{} of `{}` is unsized",
851                      index, scapegoat);
852             }
853
854             debug!("Union::extend field: {:?} {:?}", field, field.size(dl));
855
856             if !self.packed {
857                 self.align = self.align.max(field.align(dl));
858             }
859             self.min_size = cmp::max(self.min_size, field.size(dl));
860         }
861
862         debug!("Union::extend min-size: {:?}", self.min_size);
863
864         Ok(())
865     }
866
867     /// Get the size with trailing alignment padding.
868     pub fn stride(&self) -> Size {
869         self.min_size.abi_align(self.align)
870     }
871 }
872
873 /// The first half of a fat pointer.
874 /// - For a trait object, this is the address of the box.
875 /// - For a slice, this is the base address.
876 pub const FAT_PTR_ADDR: usize = 0;
877
878 /// The second half of a fat pointer.
879 /// - For a trait object, this is the address of the vtable.
880 /// - For a slice, this is the length.
881 pub const FAT_PTR_EXTRA: usize = 1;
882
883 /// Type layout, from which size and alignment can be cheaply computed.
884 /// For ADTs, it also includes field placement and enum optimizations.
885 /// NOTE: Because Layout is interned, redundant information should be
886 /// kept to a minimum, e.g. it includes no sub-component Ty or Layout.
887 #[derive(Debug, PartialEq, Eq, Hash)]
888 pub enum Layout {
889     /// TyBool, TyChar, TyInt, TyUint, TyFloat, TyRawPtr, TyRef or TyFnPtr.
890     Scalar {
891         value: Primitive,
892         // If true, the value cannot represent a bit pattern of all zeroes.
893         non_zero: bool
894     },
895
896     /// SIMD vectors, from structs marked with #[repr(simd)].
897     Vector {
898         element: Primitive,
899         count: u64
900     },
901
902     /// TyArray, TySlice or TyStr.
903     Array {
904         /// If true, the size is exact, otherwise it's only a lower bound.
905         sized: bool,
906         align: Align,
907         size: Size
908     },
909
910     /// TyRawPtr or TyRef with a !Sized pointee.
911     FatPointer {
912         metadata: Primitive,
913         // If true, the pointer cannot be null.
914         non_zero: bool
915     },
916
917     // Remaining variants are all ADTs such as structs, enums or tuples.
918
919     /// C-like enums; basically an integer.
920     CEnum {
921         discr: Integer,
922         signed: bool,
923         non_zero: bool,
924         // Inclusive discriminant range.
925         // If min > max, it represents min...u64::MAX followed by 0...max.
926         // FIXME(eddyb) always use the shortest range, e.g. by finding
927         // the largest space between two consecutive discriminants and
928         // taking everything else as the (shortest) discriminant range.
929         min: u64,
930         max: u64
931     },
932
933     /// Single-case enums, and structs/tuples.
934     Univariant {
935         variant: Struct,
936         // If true, the structure is NonZero.
937         // FIXME(eddyb) use a newtype Layout kind for this.
938         non_zero: bool
939     },
940
941     /// Untagged unions.
942     UntaggedUnion {
943         variants: Union,
944     },
945
946     /// General-case enums: for each case there is a struct, and they
947     /// all start with a field for the discriminant.
948     General {
949         discr: Integer,
950         variants: Vec<Struct>,
951         size: Size,
952         align: Align
953     },
954
955     /// Two cases distinguished by a nullable pointer: the case with discriminant
956     /// `nndiscr` must have single field which is known to be nonnull due to its type.
957     /// The other case is known to be zero sized. Hence we represent the enum
958     /// as simply a nullable pointer: if not null it indicates the `nndiscr` variant,
959     /// otherwise it indicates the other case.
960     ///
961     /// For example, `std::option::Option` instantiated at a safe pointer type
962     /// is represented such that `None` is a null pointer and `Some` is the
963     /// identity function.
964     RawNullablePointer {
965         nndiscr: u64,
966         value: Primitive
967     },
968
969     /// Two cases distinguished by a nullable pointer: the case with discriminant
970     /// `nndiscr` is represented by the struct `nonnull`, where the `discrfield`th
971     /// field is known to be nonnull due to its type; if that field is null, then
972     /// it represents the other case, which is known to be zero sized.
973     StructWrappedNullablePointer {
974         nndiscr: u64,
975         nonnull: Struct,
976         // N.B. There is a 0 at the start, for LLVM GEP through a pointer.
977         discrfield: FieldPath,
978         // Like discrfield, but in source order. For debuginfo.
979         discrfield_source: FieldPath
980     }
981 }
982
983 #[derive(Copy, Clone, Debug)]
984 pub enum LayoutError<'tcx> {
985     Unknown(Ty<'tcx>),
986     SizeOverflow(Ty<'tcx>)
987 }
988
989 impl<'tcx> fmt::Display for LayoutError<'tcx> {
990     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
991         match *self {
992             LayoutError::Unknown(ty) => {
993                 write!(f, "the type `{:?}` has an unknown layout", ty)
994             }
995             LayoutError::SizeOverflow(ty) => {
996                 write!(f, "the type `{:?}` is too big for the current architecture", ty)
997             }
998         }
999     }
1000 }
1001
1002 /// Helper function for normalizing associated types in an inference context.
1003 fn normalize_associated_type<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
1004                                              ty: Ty<'gcx>)
1005                                              -> Ty<'gcx> {
1006     if !ty.has_projection_types() {
1007         return ty;
1008     }
1009
1010     let mut selcx = traits::SelectionContext::new(infcx);
1011     let cause = traits::ObligationCause::dummy();
1012     let traits::Normalized { value: result, obligations } =
1013         traits::normalize(&mut selcx, cause, &ty);
1014
1015     let mut fulfill_cx = traits::FulfillmentContext::new();
1016
1017     for obligation in obligations {
1018         fulfill_cx.register_predicate_obligation(infcx, obligation);
1019     }
1020
1021     infcx.drain_fulfillment_cx_or_panic(DUMMY_SP, &mut fulfill_cx, &result)
1022 }
1023
1024 impl<'a, 'gcx, 'tcx> Layout {
1025     pub fn compute_uncached(ty: Ty<'gcx>,
1026                             infcx: &InferCtxt<'a, 'gcx, 'tcx>)
1027                             -> Result<&'gcx Layout, LayoutError<'gcx>> {
1028         let tcx = infcx.tcx.global_tcx();
1029         let success = |layout| Ok(tcx.intern_layout(layout));
1030         let dl = &tcx.data_layout;
1031         assert!(!ty.has_infer_types());
1032
1033         let ptr_layout = |pointee: Ty<'gcx>| {
1034             let non_zero = !ty.is_unsafe_ptr();
1035             let pointee = normalize_associated_type(infcx, pointee);
1036             if pointee.is_sized(tcx, &infcx.parameter_environment, DUMMY_SP) {
1037                 Ok(Scalar { value: Pointer, non_zero: non_zero })
1038             } else {
1039                 let unsized_part = tcx.struct_tail(pointee);
1040                 let meta = match unsized_part.sty {
1041                     ty::TySlice(_) | ty::TyStr => {
1042                         Int(dl.ptr_sized_integer())
1043                     }
1044                     ty::TyDynamic(..) => Pointer,
1045                     _ => return Err(LayoutError::Unknown(unsized_part))
1046                 };
1047                 Ok(FatPointer { metadata: meta, non_zero: non_zero })
1048             }
1049         };
1050
1051         let layout = match ty.sty {
1052             // Basic scalars.
1053             ty::TyBool => Scalar { value: Int(I1), non_zero: false },
1054             ty::TyChar => Scalar { value: Int(I32), non_zero: false },
1055             ty::TyInt(ity) => {
1056                 Scalar {
1057                     value: Int(Integer::from_attr(dl, attr::SignedInt(ity))),
1058                     non_zero: false
1059                 }
1060             }
1061             ty::TyUint(ity) => {
1062                 Scalar {
1063                     value: Int(Integer::from_attr(dl, attr::UnsignedInt(ity))),
1064                     non_zero: false
1065                 }
1066             }
1067             ty::TyFloat(FloatTy::F32) => Scalar { value: F32, non_zero: false },
1068             ty::TyFloat(FloatTy::F64) => Scalar { value: F64, non_zero: false },
1069             ty::TyFnPtr(_) => Scalar { value: Pointer, non_zero: true },
1070
1071             // The never type.
1072             ty::TyNever => Univariant {
1073                 variant: Struct::new(dl, &vec![], &ReprOptions::default(),
1074                   StructKind::AlwaysSizedUnivariant, ty)?,
1075                 non_zero: false
1076             },
1077
1078             // Potentially-fat pointers.
1079             ty::TyRef(_, ty::TypeAndMut { ty: pointee, .. }) |
1080             ty::TyRawPtr(ty::TypeAndMut { ty: pointee, .. }) => {
1081                 ptr_layout(pointee)?
1082             }
1083             ty::TyAdt(def, _) if def.is_box() => {
1084                 ptr_layout(ty.boxed_ty())?
1085             }
1086
1087             // Arrays and slices.
1088             ty::TyArray(element, count) => {
1089                 let element = element.layout(infcx)?;
1090                 Array {
1091                     sized: true,
1092                     align: element.align(dl),
1093                     size: element.size(dl).checked_mul(count as u64, dl)
1094                                  .map_or(Err(LayoutError::SizeOverflow(ty)), Ok)?
1095                 }
1096             }
1097             ty::TySlice(element) => {
1098                 Array {
1099                     sized: false,
1100                     align: element.layout(infcx)?.align(dl),
1101                     size: Size::from_bytes(0)
1102                 }
1103             }
1104             ty::TyStr => {
1105                 Array {
1106                     sized: false,
1107                     align: dl.i8_align,
1108                     size: Size::from_bytes(0)
1109                 }
1110             }
1111
1112             // Odd unit types.
1113             ty::TyFnDef(..) => {
1114                 Univariant {
1115                     variant: Struct::new(dl, &vec![],
1116                       &ReprOptions::default(), StructKind::AlwaysSizedUnivariant, ty)?,
1117                     non_zero: false
1118                 }
1119             }
1120             ty::TyDynamic(..) => {
1121                 let mut unit = Struct::new(dl, &vec![], &ReprOptions::default(),
1122                   StructKind::AlwaysSizedUnivariant, ty)?;
1123                 unit.sized = false;
1124                 Univariant { variant: unit, non_zero: false }
1125             }
1126
1127             // Tuples and closures.
1128             ty::TyClosure(def_id, ref substs) => {
1129                 let tys = substs.upvar_tys(def_id, tcx);
1130                 let st = Struct::new(dl,
1131                     &tys.map(|ty| ty.layout(infcx))
1132                       .collect::<Result<Vec<_>, _>>()?,
1133                     &ReprOptions::default(),
1134                     StructKind::AlwaysSizedUnivariant, ty)?;
1135                 Univariant { variant: st, non_zero: false }
1136             }
1137
1138             ty::TyTuple(tys, _) => {
1139                 // FIXME(camlorn): if we ever allow unsized tuples, this needs to be checked.
1140                 // See the univariant case below to learn how.
1141                 let st = Struct::new(dl,
1142                     &tys.iter().map(|ty| ty.layout(infcx))
1143                       .collect::<Result<Vec<_>, _>>()?,
1144                     &ReprOptions::default(), StructKind::AlwaysSizedUnivariant, ty)?;
1145                 Univariant { variant: st, non_zero: false }
1146             }
1147
1148             // SIMD vector types.
1149             ty::TyAdt(def, ..) if def.repr.simd => {
1150                 let element = ty.simd_type(tcx);
1151                 match *element.layout(infcx)? {
1152                     Scalar { value, .. } => {
1153                         return success(Vector {
1154                             element: value,
1155                             count: ty.simd_size(tcx) as u64
1156                         });
1157                     }
1158                     _ => {
1159                         tcx.sess.fatal(&format!("monomorphising SIMD type `{}` with \
1160                                                 a non-machine element type `{}`",
1161                                                 ty, element));
1162                     }
1163                 }
1164             }
1165
1166             // ADTs.
1167             ty::TyAdt(def, substs) => {
1168                 if def.variants.is_empty() {
1169                     // Uninhabitable; represent as unit
1170                     // (Typechecking will reject discriminant-sizing attrs.)
1171
1172                     return success(Univariant {
1173                         variant: Struct::new(dl, &vec![],
1174                           &def.repr, StructKind::AlwaysSizedUnivariant, ty)?,
1175                         non_zero: false
1176                     });
1177                 }
1178
1179                 if def.is_enum() && def.variants.iter().all(|v| v.fields.is_empty()) {
1180                     // All bodies empty -> intlike
1181                     let (mut min, mut max, mut non_zero) = (i64::max_value(),
1182                                                             i64::min_value(),
1183                                                             true);
1184                     for discr in def.discriminants(tcx) {
1185                         let x = discr.to_u128_unchecked() as i64;
1186                         if x == 0 { non_zero = false; }
1187                         if x < min { min = x; }
1188                         if x > max { max = x; }
1189                     }
1190
1191                     // FIXME: should handle i128? signed-value based impl is weird and hard to
1192                     // grok.
1193                     let (discr, signed) = Integer::repr_discr(tcx, ty, &def.repr, min, max);
1194                     return success(CEnum {
1195                         discr: discr,
1196                         signed: signed,
1197                         non_zero: non_zero,
1198                         // FIXME: should be u128?
1199                         min: min as u64,
1200                         max: max as u64
1201                     });
1202                 }
1203
1204                 if !def.is_enum() || (def.variants.len() == 1 &&
1205                                       !def.repr.inhibit_enum_layout_opt()) {
1206                     // Struct, or union, or univariant enum equivalent to a struct.
1207                     // (Typechecking will reject discriminant-sizing attrs.)
1208
1209                     let kind = if def.is_enum() || def.variants[0].fields.len() == 0{
1210                         StructKind::AlwaysSizedUnivariant
1211                     } else {
1212                         use middle::region::ROOT_CODE_EXTENT;
1213                         let param_env = tcx.construct_parameter_environment(DUMMY_SP,
1214                           def.did, ROOT_CODE_EXTENT);
1215                         let fields = &def.variants[0].fields;
1216                         let last_field = &fields[fields.len()-1];
1217                         let always_sized = last_field.ty(tcx, param_env.free_substs)
1218                           .is_sized(tcx, &param_env, DUMMY_SP);
1219                         if !always_sized { StructKind::MaybeUnsizedUnivariant }
1220                         else { StructKind::AlwaysSizedUnivariant }
1221                     };
1222
1223                     let fields = def.variants[0].fields.iter().map(|field| {
1224                         field.ty(tcx, substs).layout(infcx)
1225                     }).collect::<Result<Vec<_>, _>>()?;
1226                     let layout = if def.is_union() {
1227                         let mut un = Union::new(dl, def.repr.packed);
1228                         un.extend(dl, fields.iter().map(|&f| Ok(f)), ty)?;
1229                         UntaggedUnion { variants: un }
1230                     } else {
1231                         let st = Struct::new(dl, &fields, &def.repr,
1232                           kind, ty)?;
1233                         let non_zero = Some(def.did) == tcx.lang_items.non_zero();
1234                         Univariant { variant: st, non_zero: non_zero }
1235                     };
1236                     return success(layout);
1237                 }
1238
1239                 // Since there's at least one
1240                 // non-empty body, explicit discriminants should have
1241                 // been rejected by a checker before this point.
1242                 for (i, v) in def.variants.iter().enumerate() {
1243                     if v.discr != ty::VariantDiscr::Relative(i) {
1244                         bug!("non-C-like enum {} with specified discriminants",
1245                             tcx.item_path_str(def.did));
1246                     }
1247                 }
1248
1249                 // Cache the substituted and normalized variant field types.
1250                 let variants = def.variants.iter().map(|v| {
1251                     v.fields.iter().map(|field| field.ty(tcx, substs)).collect::<Vec<_>>()
1252                 }).collect::<Vec<_>>();
1253
1254                 if variants.len() == 2 && !def.repr.inhibit_enum_layout_opt() {
1255                     // Nullable pointer optimization
1256                     for discr in 0..2 {
1257                         let other_fields = variants[1 - discr].iter().map(|ty| {
1258                             ty.layout(infcx)
1259                         });
1260                         if !Struct::would_be_zero_sized(dl, other_fields)? {
1261                             continue;
1262                         }
1263                         let paths = Struct::non_zero_field_paths(infcx,
1264                             variants[discr].iter().cloned(),
1265                             None)?;
1266                         let (mut path, mut path_source) = if let Some(p) = paths { p }
1267                           else { continue };
1268
1269                         // FIXME(eddyb) should take advantage of a newtype.
1270                         if path == &[0] && variants[discr].len() == 1 {
1271                             let value = match *variants[discr][0].layout(infcx)? {
1272                                 Scalar { value, .. } => value,
1273                                 CEnum { discr, .. } => Int(discr),
1274                                 _ => bug!("Layout::compute: `{}`'s non-zero \
1275                                            `{}` field not scalar?!",
1276                                            ty, variants[discr][0])
1277                             };
1278                             return success(RawNullablePointer {
1279                                 nndiscr: discr as u64,
1280                                 value: value,
1281                             });
1282                         }
1283
1284                         let st = Struct::new(dl,
1285                             &variants[discr].iter().map(|ty| ty.layout(infcx))
1286                               .collect::<Result<Vec<_>, _>>()?,
1287                             &def.repr, StructKind::AlwaysSizedUnivariant, ty)?;
1288
1289                         // We have to fix the last element of path here.
1290                         let mut i = *path.last().unwrap();
1291                         i = st.memory_index[i as usize];
1292                         *path.last_mut().unwrap() = i;
1293                         path.push(0); // For GEP through a pointer.
1294                         path.reverse();
1295                         path_source.push(0);
1296                         path_source.reverse();
1297
1298                         return success(StructWrappedNullablePointer {
1299                             nndiscr: discr as u64,
1300                             nonnull: st,
1301                             discrfield: path,
1302                             discrfield_source: path_source
1303                         });
1304                     }
1305                 }
1306
1307                 // The general case.
1308                 let discr_max = (variants.len() - 1) as i64;
1309                 assert!(discr_max >= 0);
1310                 let (min_ity, _) = Integer::repr_discr(tcx, ty, &def.repr, 0, discr_max);
1311                 let mut align = dl.aggregate_align;
1312                 let mut size = Size::from_bytes(0);
1313
1314                 // We're interested in the smallest alignment, so start large.
1315                 let mut start_align = Align::from_bytes(256, 256).unwrap();
1316
1317                 // Create the set of structs that represent each variant
1318                 // Use the minimum integer type we figured out above
1319                 let discr = Scalar { value: Int(min_ity), non_zero: false };
1320                 let mut variants = variants.into_iter().map(|fields| {
1321                     let mut fields = fields.into_iter().map(|field| {
1322                         field.layout(infcx)
1323                     }).collect::<Result<Vec<_>, _>>()?;
1324                     fields.insert(0, &discr);
1325                     let st = Struct::new(dl,
1326                         &fields,
1327                         &def.repr, StructKind::EnumVariant, ty)?;
1328                     // Find the first field we can't move later
1329                     // to make room for a larger discriminant.
1330                     // It is important to skip the first field.
1331                     for i in st.field_index_by_increasing_offset().skip(1) {
1332                         let field = fields[i];
1333                         let field_align = field.align(dl);
1334                         if field.size(dl).bytes() != 0 || field_align.abi() != 1 {
1335                             start_align = start_align.min(field_align);
1336                             break;
1337                         }
1338                     }
1339                     size = cmp::max(size, st.min_size);
1340                     align = align.max(st.align);
1341                     Ok(st)
1342                 }).collect::<Result<Vec<_>, _>>()?;
1343
1344                 // Align the maximum variant size to the largest alignment.
1345                 size = size.abi_align(align);
1346
1347                 if size.bytes() >= dl.obj_size_bound() {
1348                     return Err(LayoutError::SizeOverflow(ty));
1349                 }
1350
1351                 let typeck_ity = Integer::from_attr(dl, def.repr.discr_type());
1352                 if typeck_ity < min_ity {
1353                     // It is a bug if Layout decided on a greater discriminant size than typeck for
1354                     // some reason at this point (based on values discriminant can take on). Mostly
1355                     // because this discriminant will be loaded, and then stored into variable of
1356                     // type calculated by typeck. Consider such case (a bug): typeck decided on
1357                     // byte-sized discriminant, but layout thinks we need a 16-bit to store all
1358                     // discriminant values. That would be a bug, because then, in trans, in order
1359                     // to store this 16-bit discriminant into 8-bit sized temporary some of the
1360                     // space necessary to represent would have to be discarded (or layout is wrong
1361                     // on thinking it needs 16 bits)
1362                     bug!("layout decided on a larger discriminant type ({:?}) than typeck ({:?})",
1363                          min_ity, typeck_ity);
1364                     // However, it is fine to make discr type however large (as an optimisation)
1365                     // after this point â€“ we’ll just truncate the value we load in trans.
1366                 }
1367
1368                 // Check to see if we should use a different type for the
1369                 // discriminant. We can safely use a type with the same size
1370                 // as the alignment of the first field of each variant.
1371                 // We increase the size of the discriminant to avoid LLVM copying
1372                 // padding when it doesn't need to. This normally causes unaligned
1373                 // load/stores and excessive memcpy/memset operations. By using a
1374                 // bigger integer size, LLVM can be sure about it's contents and
1375                 // won't be so conservative.
1376
1377                 // Use the initial field alignment
1378                 let mut ity = Integer::for_abi_align(dl, start_align).unwrap_or(min_ity);
1379
1380                 // If the alignment is not larger than the chosen discriminant size,
1381                 // don't use the alignment as the final size.
1382                 if ity <= min_ity {
1383                     ity = min_ity;
1384                 } else {
1385                     // Patch up the variants' first few fields.
1386                     let old_ity_size = Int(min_ity).size(dl);
1387                     let new_ity_size = Int(ity).size(dl);
1388                     for variant in &mut variants {
1389                         for i in variant.offsets.iter_mut() {
1390                             // The first field is the discrimminant, at offset 0.
1391                             // These aren't in order, and we need to skip it.
1392                             if *i <= old_ity_size && *i > Size::from_bytes(0) {
1393                                 *i = new_ity_size;
1394                             }
1395                         }
1396                         // We might be making the struct larger.
1397                         if variant.min_size <= old_ity_size {
1398                             variant.min_size = new_ity_size;
1399                         }
1400                     }
1401                 }
1402
1403                 General {
1404                     discr: ity,
1405                     variants: variants,
1406                     size: size,
1407                     align: align
1408                 }
1409             }
1410
1411             // Types with no meaningful known layout.
1412             ty::TyProjection(_) | ty::TyAnon(..) => {
1413                 let normalized = normalize_associated_type(infcx, ty);
1414                 if ty == normalized {
1415                     return Err(LayoutError::Unknown(ty));
1416                 }
1417                 return normalized.layout(infcx);
1418             }
1419             ty::TyParam(_) => {
1420                 return Err(LayoutError::Unknown(ty));
1421             }
1422             ty::TyInfer(_) | ty::TyError => {
1423                 bug!("Layout::compute: unexpected type `{}`", ty)
1424             }
1425         };
1426
1427         success(layout)
1428     }
1429
1430     /// Returns true if the layout corresponds to an unsized type.
1431     pub fn is_unsized(&self) -> bool {
1432         match *self {
1433             Scalar {..} | Vector {..} | FatPointer {..} |
1434             CEnum {..} | UntaggedUnion {..} | General {..} |
1435             RawNullablePointer {..} |
1436             StructWrappedNullablePointer {..} => false,
1437
1438             Array { sized, .. } |
1439             Univariant { variant: Struct { sized, .. }, .. } => !sized
1440         }
1441     }
1442
1443     pub fn size(&self, dl: &TargetDataLayout) -> Size {
1444         match *self {
1445             Scalar { value, .. } | RawNullablePointer { value, .. } => {
1446                 value.size(dl)
1447             }
1448
1449             Vector { element, count } => {
1450                 let elem_size = element.size(dl);
1451                 let vec_size = match elem_size.checked_mul(count, dl) {
1452                     Some(size) => size,
1453                     None => bug!("Layout::size({:?}): {} * {} overflowed",
1454                                  self, elem_size.bytes(), count)
1455                 };
1456                 vec_size.abi_align(self.align(dl))
1457             }
1458
1459             FatPointer { metadata, .. } => {
1460                 // Effectively a (ptr, meta) tuple.
1461                 Pointer.size(dl).abi_align(metadata.align(dl))
1462                        .checked_add(metadata.size(dl), dl).unwrap()
1463                        .abi_align(self.align(dl))
1464             }
1465
1466             CEnum { discr, .. } => Int(discr).size(dl),
1467             Array { size, .. } | General { size, .. } => size,
1468             UntaggedUnion { ref variants } => variants.stride(),
1469
1470             Univariant { ref variant, .. } |
1471             StructWrappedNullablePointer { nonnull: ref variant, .. } => {
1472                 variant.stride()
1473             }
1474         }
1475     }
1476
1477     pub fn align(&self, dl: &TargetDataLayout) -> Align {
1478         match *self {
1479             Scalar { value, .. } | RawNullablePointer { value, .. } => {
1480                 value.align(dl)
1481             }
1482
1483             Vector { element, count } => {
1484                 let elem_size = element.size(dl);
1485                 let vec_size = match elem_size.checked_mul(count, dl) {
1486                     Some(size) => size,
1487                     None => bug!("Layout::align({:?}): {} * {} overflowed",
1488                                  self, elem_size.bytes(), count)
1489                 };
1490                 for &(size, align) in &dl.vector_align {
1491                     if size == vec_size {
1492                         return align;
1493                     }
1494                 }
1495                 // Default to natural alignment, which is what LLVM does.
1496                 // That is, use the size, rounded up to a power of 2.
1497                 let align = vec_size.bytes().next_power_of_two();
1498                 Align::from_bytes(align, align).unwrap()
1499             }
1500
1501             FatPointer { metadata, .. } => {
1502                 // Effectively a (ptr, meta) tuple.
1503                 Pointer.align(dl).max(metadata.align(dl))
1504             }
1505
1506             CEnum { discr, .. } => Int(discr).align(dl),
1507             Array { align, .. } | General { align, .. } => align,
1508             UntaggedUnion { ref variants } => variants.align,
1509
1510             Univariant { ref variant, .. } |
1511             StructWrappedNullablePointer { nonnull: ref variant, .. } => {
1512                 variant.align
1513             }
1514         }
1515     }
1516 }
1517
1518 /// Type size "skeleton", i.e. the only information determining a type's size.
1519 /// While this is conservative, (aside from constant sizes, only pointers,
1520 /// newtypes thereof and null pointer optimized enums are allowed), it is
1521 /// enough to statically check common usecases of transmute.
1522 #[derive(Copy, Clone, Debug)]
1523 pub enum SizeSkeleton<'tcx> {
1524     /// Any statically computable Layout.
1525     Known(Size),
1526
1527     /// A potentially-fat pointer.
1528     Pointer {
1529         // If true, this pointer is never null.
1530         non_zero: bool,
1531         // The type which determines the unsized metadata, if any,
1532         // of this pointer. Either a type parameter or a projection
1533         // depending on one, with regions erased.
1534         tail: Ty<'tcx>
1535     }
1536 }
1537
1538 impl<'a, 'gcx, 'tcx> SizeSkeleton<'gcx> {
1539     pub fn compute(ty: Ty<'gcx>, infcx: &InferCtxt<'a, 'gcx, 'tcx>)
1540                    -> Result<SizeSkeleton<'gcx>, LayoutError<'gcx>> {
1541         let tcx = infcx.tcx.global_tcx();
1542         assert!(!ty.has_infer_types());
1543
1544         // First try computing a static layout.
1545         let err = match ty.layout(infcx) {
1546             Ok(layout) => {
1547                 return Ok(SizeSkeleton::Known(layout.size(&tcx.data_layout)));
1548             }
1549             Err(err) => err
1550         };
1551
1552         let ptr_skeleton = |pointee: Ty<'gcx>| {
1553             let non_zero = !ty.is_unsafe_ptr();
1554             let tail = tcx.struct_tail(pointee);
1555             match tail.sty {
1556                 ty::TyParam(_) | ty::TyProjection(_) => {
1557                     assert!(tail.has_param_types() || tail.has_self_ty());
1558                     Ok(SizeSkeleton::Pointer {
1559                         non_zero: non_zero,
1560                         tail: tcx.erase_regions(&tail)
1561                     })
1562                 }
1563                 _ => {
1564                     bug!("SizeSkeleton::compute({}): layout errored ({}), yet \
1565                             tail `{}` is not a type parameter or a projection",
1566                             ty, err, tail)
1567                 }
1568             }
1569         };
1570
1571         match ty.sty {
1572             ty::TyRef(_, ty::TypeAndMut { ty: pointee, .. }) |
1573             ty::TyRawPtr(ty::TypeAndMut { ty: pointee, .. }) => {
1574                 ptr_skeleton(pointee)
1575             }
1576             ty::TyAdt(def, _) if def.is_box() => {
1577                 ptr_skeleton(ty.boxed_ty())
1578             }
1579
1580             ty::TyAdt(def, substs) => {
1581                 // Only newtypes and enums w/ nullable pointer optimization.
1582                 if def.is_union() || def.variants.is_empty() || def.variants.len() > 2 {
1583                     return Err(err);
1584                 }
1585
1586                 // Get a zero-sized variant or a pointer newtype.
1587                 let zero_or_ptr_variant = |i: usize| {
1588                     let fields = def.variants[i].fields.iter().map(|field| {
1589                         SizeSkeleton::compute(field.ty(tcx, substs), infcx)
1590                     });
1591                     let mut ptr = None;
1592                     for field in fields {
1593                         let field = field?;
1594                         match field {
1595                             SizeSkeleton::Known(size) => {
1596                                 if size.bytes() > 0 {
1597                                     return Err(err);
1598                                 }
1599                             }
1600                             SizeSkeleton::Pointer {..} => {
1601                                 if ptr.is_some() {
1602                                     return Err(err);
1603                                 }
1604                                 ptr = Some(field);
1605                             }
1606                         }
1607                     }
1608                     Ok(ptr)
1609                 };
1610
1611                 let v0 = zero_or_ptr_variant(0)?;
1612                 // Newtype.
1613                 if def.variants.len() == 1 {
1614                     if let Some(SizeSkeleton::Pointer { non_zero, tail }) = v0 {
1615                         return Ok(SizeSkeleton::Pointer {
1616                             non_zero: non_zero ||
1617                                 Some(def.did) == tcx.lang_items.non_zero(),
1618                             tail: tail
1619                         });
1620                     } else {
1621                         return Err(err);
1622                     }
1623                 }
1624
1625                 let v1 = zero_or_ptr_variant(1)?;
1626                 // Nullable pointer enum optimization.
1627                 match (v0, v1) {
1628                     (Some(SizeSkeleton::Pointer { non_zero: true, tail }), None) |
1629                     (None, Some(SizeSkeleton::Pointer { non_zero: true, tail })) => {
1630                         Ok(SizeSkeleton::Pointer {
1631                             non_zero: false,
1632                             tail: tail
1633                         })
1634                     }
1635                     _ => Err(err)
1636                 }
1637             }
1638
1639             ty::TyProjection(_) | ty::TyAnon(..) => {
1640                 let normalized = normalize_associated_type(infcx, ty);
1641                 if ty == normalized {
1642                     Err(err)
1643                 } else {
1644                     SizeSkeleton::compute(normalized, infcx)
1645                 }
1646             }
1647
1648             _ => Err(err)
1649         }
1650     }
1651
1652     pub fn same_size(self, other: SizeSkeleton) -> bool {
1653         match (self, other) {
1654             (SizeSkeleton::Known(a), SizeSkeleton::Known(b)) => a == b,
1655             (SizeSkeleton::Pointer { tail: a, .. },
1656              SizeSkeleton::Pointer { tail: b, .. }) => a == b,
1657             _ => false
1658         }
1659     }
1660 }