about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEduard-Mihai Burtescu <edy.burt@gmail.com>2017-09-17 04:42:22 +0300
committerEduard-Mihai Burtescu <edy.burt@gmail.com>2017-11-19 02:14:31 +0200
commitbd51a2bc192f323d0da2ea7716860b1699d315d8 (patch)
tree67183938e89ad580214c020de42451531341bdc1
parentbd86f3739e76484e410ec5e651ab3ee9049f31ba (diff)
downloadrust-bd51a2bc192f323d0da2ea7716860b1699d315d8.tar.gz
rust-bd51a2bc192f323d0da2ea7716860b1699d315d8.zip
rustc: move size/alignment from Layout into layout::Abi.
-rw-r--r--src/librustc/ty/layout.rs359
-rw-r--r--src/librustc_lint/types.rs2
-rw-r--r--src/librustc_trans/abi.rs12
-rw-r--r--src/librustc_trans/adt.rs4
-rw-r--r--src/librustc_trans/cabi_s390x.rs2
-rw-r--r--src/librustc_trans/cabi_x86.rs2
-rw-r--r--src/librustc_trans/cabi_x86_64.rs10
-rw-r--r--src/librustc_trans/cabi_x86_win64.rs36
-rw-r--r--src/librustc_trans/common.rs8
-rw-r--r--src/librustc_trans/debuginfo/metadata.rs8
-rw-r--r--src/librustc_trans/glue.rs2
-rw-r--r--src/librustc_trans/mir/constant.rs2
-rw-r--r--src/librustc_trans/mir/lvalue.rs18
-rw-r--r--src/librustc_trans/mir/mod.rs2
-rw-r--r--src/librustc_trans/mir/rvalue.rs2
-rw-r--r--src/librustc_trans/type_of.rs2
16 files changed, 257 insertions, 214 deletions
diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs
index bd99ae0204a..eb22b6f2ce9 100644
--- a/src/librustc/ty/layout.rs
+++ b/src/librustc/ty/layout.rs
@@ -25,7 +25,7 @@ use std::fmt;
 use std::i64;
 use std::iter;
 use std::mem;
-use std::ops::{Deref, Add, Sub, Mul, AddAssign, RangeInclusive};
+use std::ops::{Add, Sub, Mul, AddAssign, RangeInclusive};
 
 use ich::StableHashingContext;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
@@ -856,7 +856,7 @@ impl<'a, 'tcx> Struct {
             // Is this the NonZero lang item wrapping a pointer or integer type?
             (_, &ty::TyAdt(def, _)) if Some(def.did) == tcx.lang_items().non_zero() => {
                 let field = layout.field(cx, 0)?;
-                match *field {
+                match *field.layout {
                     Scalar(value) => {
                         Ok(Some((layout.fields.offset(0), value)))
                     }
@@ -965,7 +965,7 @@ impl<'a, 'tcx> Union {
                  fields: I,
                  scapegoat: Ty<'tcx>)
                  -> Result<(), LayoutError<'tcx>>
-    where I: Iterator<Item=Result<&'a Layout, LayoutError<'tcx>>> {
+    where I: Iterator<Item=Result<FullLayout<'a>, LayoutError<'tcx>>> {
         for (index, field) in fields.enumerate() {
             let field = field?;
             if field.is_unsized() {
@@ -1061,8 +1061,80 @@ impl<'a> FieldPlacement<'a> {
 #[derive(Copy, Clone, Debug)]
 pub enum Abi {
     Scalar(Primitive),
-    Vector,
-    Aggregate
+    Vector {
+        element: Primitive,
+        count: u64
+    },
+    Aggregate {
+        /// If true, the size is exact, otherwise it's only a lower bound.
+        sized: bool,
+        align: Align,
+        primitive_align: Align,
+        size: Size
+    }
+}
+
+impl Abi {
+    /// Returns true if the layout corresponds to an unsized type.
+    pub fn is_unsized(&self) -> bool {
+        match *self {
+            Abi::Scalar(_) | Abi::Vector {..} => false,
+            Abi::Aggregate { sized, .. } => !sized
+        }
+    }
+
+    pub fn size<C: HasDataLayout>(&self, cx: C) -> Size {
+        let dl = cx.data_layout();
+
+        match *self {
+            Abi::Scalar(value) => value.size(dl),
+
+            Abi::Vector { element, count } => {
+                let element_size = element.size(dl);
+                let vec_size = match element_size.checked_mul(count, dl) {
+                    Some(size) => size,
+                    None => bug!("Layout::size({:?}): {} * {} overflowed",
+                                 self, element_size.bytes(), count)
+                };
+                vec_size.abi_align(self.align(dl))
+            }
+
+            Abi::Aggregate { size, .. } => size
+        }
+    }
+
+    pub fn align<C: HasDataLayout>(&self, cx: C) -> Align {
+        let dl = cx.data_layout();
+
+        match *self {
+            Abi::Scalar(value) => value.align(dl),
+
+            Abi::Vector { element, count } => {
+                let elem_size = element.size(dl);
+                let vec_size = match elem_size.checked_mul(count, dl) {
+                    Some(size) => size,
+                    None => bug!("Layout::align({:?}): {} * {} overflowed",
+                                 self, elem_size.bytes(), count)
+                };
+                dl.vector_align(vec_size)
+            }
+
+            Abi::Aggregate { align, .. } => align
+        }
+    }
+
+    pub fn size_and_align<C: HasDataLayout>(&self, cx: C) -> (Size, Align) {
+        (self.size(cx), self.align(cx))
+    }
+
+    /// Returns alignment before repr alignment is applied
+    pub fn primitive_align<C: HasDataLayout>(&self, cx: C) -> Align {
+        match *self {
+            Abi::Aggregate { primitive_align, .. } => primitive_align,
+
+            _ => self.align(cx.data_layout())
+        }
+    }
 }
 
 /// Type layout, from which size and alignment can be cheaply computed.
@@ -1247,19 +1319,63 @@ impl<'a, 'tcx> Layout {
             };
             let abi = match *layout {
                 Scalar(value) => Abi::Scalar(value),
-                Vector { .. } => Abi::Vector,
+                Vector { element, count } => Abi::Vector { element, count },
+
+                Array { sized, align, primitive_align, element_size, count, .. } => {
+                    let size = match element_size.checked_mul(count, dl) {
+                        Some(size) => size,
+                        None => return Err(LayoutError::SizeOverflow(ty))
+                    };
+                    Abi::Aggregate {
+                        sized,
+                        align,
+                        primitive_align,
+                        size
+                    }
+                }
 
-                Array { .. } |
-                FatPointer { .. } |
-                Univariant(_) |
-                UntaggedUnion(_) => Abi::Aggregate,
+                FatPointer(metadata) => {
+                    // Effectively a (ptr, meta) tuple.
+                    let align = Pointer.align(dl).max(metadata.align(dl));
+                    Abi::Aggregate {
+                        sized: true,
+                        align,
+                        primitive_align: align,
+                        size: (Pointer.size(dl).abi_align(metadata.align(dl)) +
+                               metadata.size(dl))
+                            .abi_align(align)
+                    }
+                }
 
-                General { discr, .. } |
-                NullablePointer { discr, .. } => {
-                    if fields.offset(0).bytes() == 0 && discr.size(cx) == layout.size(cx) {
+                Univariant(ref st) => {
+                    Abi::Aggregate {
+                        sized: st.sized,
+                        align: st.align,
+                        primitive_align: st.primitive_align,
+                        size: st.stride()
+                    }
+                }
+
+                UntaggedUnion(ref un ) => {
+                    Abi::Aggregate {
+                        sized: true,
+                        align: un.align,
+                        primitive_align: un.primitive_align,
+                        size: un.stride()
+                    }
+                }
+
+                General { discr, align, primitive_align, size, .. } |
+                NullablePointer { discr, align, primitive_align, size, .. } => {
+                    if fields.offset(0).bytes() == 0 && discr.size(cx) == size {
                         Abi::Scalar(discr)
                     } else {
-                        Abi::Aggregate
+                        Abi::Aggregate {
+                            sized: true,
+                            align,
+                            primitive_align,
+                            size
+                        }
                     }
                 }
             };
@@ -1330,9 +1446,6 @@ impl<'a, 'tcx> Layout {
                 let element = cx.layout_of(element)?;
                 let element_size = element.size(dl);
                 let count = count.val.to_const_int().unwrap().to_u64().unwrap();
-                if element_size.checked_mul(count, dl).is_none() {
-                    return Err(LayoutError::SizeOverflow(ty));
-                }
                 Array {
                     sized: true,
                     align: element.align(dl),
@@ -1408,8 +1521,8 @@ impl<'a, 'tcx> Layout {
             // SIMD vector types.
             ty::TyAdt(def, ..) if def.repr.simd() => {
                 let element = ty.simd_type(tcx);
-                match *cx.layout_of(element)? {
-                    Scalar(value) => {
+                match cx.layout_of(element)?.abi {
+                    Abi::Scalar(value) => {
                         return success(Vector {
                             element: value,
                             count: ty.simd_size(tcx) as u64
@@ -1459,7 +1572,7 @@ impl<'a, 'tcx> Layout {
 
                     let layout = if def.is_union() {
                         let mut un = Union::new(dl, &def.repr);
-                        un.extend(dl, variants[0].iter().map(|&f| Ok(f.layout)), ty)?;
+                        un.extend(dl, variants[0].iter().map(|&f| Ok(f)), ty)?;
                         UntaggedUnion(un)
                     } else {
                         Univariant(Struct::new(dl, &variants[0], &def.repr, kind, ty)?)
@@ -1648,112 +1761,13 @@ impl<'a, 'tcx> Layout {
         success(layout)
     }
 
-    /// Returns true if the layout corresponds to an unsized type.
-    pub fn is_unsized(&self) -> bool {
-        match *self {
-            Scalar(_) | Vector {..} | FatPointer {..} |
-            UntaggedUnion {..} | General {..} |
-            NullablePointer {..} => false,
-
-            Array { sized, .. } |
-            Univariant(Struct { sized, .. }) => !sized
-        }
-    }
-
-    pub fn size<C: HasDataLayout>(&self, cx: C) -> Size {
-        let dl = cx.data_layout();
-
-        match *self {
-            Scalar(value) => {
-                value.size(dl)
-            }
-
-            Vector { element, count } => {
-                let element_size = element.size(dl);
-                let vec_size = match element_size.checked_mul(count, dl) {
-                    Some(size) => size,
-                    None => bug!("Layout::size({:?}): {} * {} overflowed",
-                                 self, element_size.bytes(), count)
-                };
-                vec_size.abi_align(self.align(dl))
-            }
-
-            Array { element_size, count, .. } => {
-                match element_size.checked_mul(count, dl) {
-                    Some(size) => size,
-                    None => bug!("Layout::size({:?}): {} * {} overflowed",
-                                 self, element_size.bytes(), count)
-                }
-            }
-
-            FatPointer(metadata) => {
-                // Effectively a (ptr, meta) tuple.
-                (Pointer.size(dl).abi_align(metadata.align(dl)) +
-                 metadata.size(dl)).abi_align(self.align(dl))
-            }
-
-            NullablePointer { size, .. } |
-            General { size, .. } => size,
-            UntaggedUnion(ref un) => un.stride(),
-            Univariant(ref variant) => variant.stride()
-        }
-    }
-
-    pub fn align<C: HasDataLayout>(&self, cx: C) -> Align {
-        let dl = cx.data_layout();
-
-        match *self {
-            Scalar(value) => {
-                value.align(dl)
-            }
-
-            Vector { element, count } => {
-                let elem_size = element.size(dl);
-                let vec_size = match elem_size.checked_mul(count, dl) {
-                    Some(size) => size,
-                    None => bug!("Layout::align({:?}): {} * {} overflowed",
-                                 self, elem_size.bytes(), count)
-                };
-                dl.vector_align(vec_size)
-            }
-
-            FatPointer(metadata) => {
-                // Effectively a (ptr, meta) tuple.
-                Pointer.align(dl).max(metadata.align(dl))
-            }
-
-            Array { align, .. } |
-            NullablePointer { align, .. } |
-            General { align, .. } => align,
-            UntaggedUnion(ref un) => un.align,
-            Univariant(ref variant) => variant.align
-        }
-    }
-
-    pub fn size_and_align<C: HasDataLayout>(&self, cx: C) -> (Size, Align) {
-        (self.size(cx), self.align(cx))
-    }
-
-    /// Returns alignment before repr alignment is applied
-    pub fn primitive_align<C: HasDataLayout>(&self, cx: C) -> Align {
-        match *self {
-            Array { primitive_align, .. } |
-            NullablePointer { primitive_align, .. } |
-            General { primitive_align, .. } => primitive_align,
-
-            Univariant(ref variant) => variant.primitive_align,
-
-            _ => self.align(cx.data_layout())
-        }
-    }
-
     /// This is invoked by the `layout_raw` query to record the final
     /// layout of each type.
     #[inline]
     fn record_layout_for_printing(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                   ty: Ty<'tcx>,
                                   param_env: ty::ParamEnv<'tcx>,
-                                  layout: &Layout) {
+                                  layout: FullLayout) {
         // If we are running with `-Zprint-type-sizes`, record layouts for
         // dumping later. Ignore layouts that are done with non-empty
         // environments or non-monomorphic layouts, as the user only wants
@@ -1773,7 +1787,7 @@ impl<'a, 'tcx> Layout {
     fn record_layout_for_printing_outlined(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                            ty: Ty<'tcx>,
                                            param_env: ty::ParamEnv<'tcx>,
-                                           layout: &Layout) {
+                                           layout: FullLayout) {
         // (delay format until we actually need it)
         let record = |kind, opt_discr_size, variants| {
             let type_desc = format!("{:?}", ty);
@@ -1843,7 +1857,7 @@ impl<'a, 'tcx> Layout {
             }
         };
 
-        match *layout {
+        match *layout.layout {
             Layout::Univariant(ref variant_layout) => {
                 let variant_names = || {
                     adt_def.variants.iter().map(|v|format!("{}", v.name)).collect::<Vec<_>>()
@@ -1888,7 +1902,7 @@ impl<'a, 'tcx> Layout {
                                                            variant_layout)
                                     })
                                     .collect();
-                record(adt_kind.into(), match *layout {
+                record(adt_kind.into(), match *layout.layout {
                     Layout::General { discr, .. } => Some(discr.size(tcx)),
                     _ => None
                 }, variant_infos);
@@ -2075,13 +2089,6 @@ pub struct FullLayout<'tcx> {
     pub abi: Abi,
 }
 
-impl<'tcx> Deref for FullLayout<'tcx> {
-    type Target = Layout;
-    fn deref(&self) -> &Layout {
-        self.layout
-    }
-}
-
 pub trait HasTyCtxt<'tcx>: HasDataLayout {
     fn tcx<'a>(&'a self) -> TyCtxt<'a, 'tcx, 'tcx>;
 }
@@ -2127,6 +2134,13 @@ impl<'a, 'tcx> LayoutOf<Ty<'tcx>> for (TyCtxt<'a, 'tcx, 'tcx>, ty::ParamEnv<'tcx
 
         let ty = tcx.normalize_associated_type_in_env(&ty, param_env.reveal_all());
         let cached = tcx.layout_raw(param_env.reveal_all().and(ty))?;
+        let layout = FullLayout {
+            ty,
+            variant_index: None,
+            layout: cached.layout,
+            fields: cached.fields,
+            abi: cached.abi
+        };
 
         // NB: This recording is normally disabled; when enabled, it
         // can however trigger recursive invocations of `layout_of`.
@@ -2134,15 +2148,9 @@ impl<'a, 'tcx> LayoutOf<Ty<'tcx>> for (TyCtxt<'a, 'tcx, 'tcx>, ty::ParamEnv<'tcx
         // completed, to avoid problems around recursive structures
         // and the like. (Admitedly, I wasn't able to reproduce a problem
         // here, but it seems like the right thing to do. -nmatsakis)
-        Layout::record_layout_for_printing(tcx, ty, param_env, cached.layout);
+        Layout::record_layout_for_printing(tcx, ty, param_env, layout);
 
-        Ok(FullLayout {
-            ty,
-            variant_index: None,
-            layout: cached.layout,
-            fields: cached.fields,
-            abi: cached.abi
-        })
+        Ok(layout)
     }
 }
 
@@ -2158,6 +2166,13 @@ impl<'a, 'tcx> LayoutOf<Ty<'tcx>> for (ty::maps::TyCtxtAt<'a, 'tcx, 'tcx>,
 
         let ty = tcx_at.tcx.normalize_associated_type_in_env(&ty, param_env.reveal_all());
         let cached = tcx_at.layout_raw(param_env.reveal_all().and(ty))?;
+        let layout = FullLayout {
+            ty,
+            variant_index: None,
+            layout: cached.layout,
+            fields: cached.fields,
+            abi: cached.abi
+        };
 
         // NB: This recording is normally disabled; when enabled, it
         // can however trigger recursive invocations of `layout_of`.
@@ -2165,15 +2180,9 @@ impl<'a, 'tcx> LayoutOf<Ty<'tcx>> for (ty::maps::TyCtxtAt<'a, 'tcx, 'tcx>,
         // completed, to avoid problems around recursive structures
         // and the like. (Admitedly, I wasn't able to reproduce a problem
         // here, but it seems like the right thing to do. -nmatsakis)
-        Layout::record_layout_for_printing(tcx_at.tcx, ty, param_env, cached.layout);
+        Layout::record_layout_for_printing(tcx_at.tcx, ty, param_env, layout);
 
-        Ok(FullLayout {
-            ty,
-            variant_index: None,
-            layout: cached.layout,
-            fields: cached.fields,
-            abi: cached.abi
-        })
+        Ok(layout)
     }
 }
 
@@ -2189,27 +2198,29 @@ impl<'a, 'tcx> FullLayout<'tcx> {
             variants[variant_index].fields.len()
         };
 
-        let fields = match *self.layout {
-            Univariant(ref variant) => {
-                FieldPlacement::Arbitrary {
-                    offsets: &variant.offsets
-                }
-            }
+        let (fields, abi) = match *self.layout {
+            Univariant(_) => (self.fields, self.abi),
 
             NullablePointer { ref variants, .. } |
             General { ref variants, .. } => {
-                FieldPlacement::Arbitrary {
-                    offsets: &variants[variant_index].offsets
-                }
+                let variant = &variants[variant_index];
+                (FieldPlacement::Arbitrary {
+                    offsets: &variant.offsets
+                }, Abi::Aggregate {
+                    sized: true,
+                    align: variant.align,
+                    primitive_align: variant.primitive_align,
+                    size: variant.stride(),
+                })
             }
 
-            _ => FieldPlacement::union(count)
+            _ => (FieldPlacement::union(count), self.abi)
         };
 
         FullLayout {
             variant_index: Some(variant_index),
             fields,
-            abi: Abi::Aggregate,
+            abi,
             ..*self
         }
     }
@@ -2313,6 +2324,28 @@ impl<'a, 'tcx> FullLayout<'tcx> {
                                                           -> C::FullLayout {
         cx.layout_of(self.field_type_unnormalized(cx.tcx(), i))
     }
+
+    /// Returns true if the layout corresponds to an unsized type.
+    pub fn is_unsized(&self) -> bool {
+        self.abi.is_unsized()
+    }
+
+    pub fn size<C: HasDataLayout>(&self, cx: C) -> Size {
+        self.abi.size(cx)
+    }
+
+    pub fn align<C: HasDataLayout>(&self, cx: C) -> Align {
+        self.abi.align(cx)
+    }
+
+    pub fn size_and_align<C: HasDataLayout>(&self, cx: C) -> (Size, Align) {
+        self.abi.size_and_align(cx)
+    }
+
+    /// Returns alignment before repr alignment is applied
+    pub fn primitive_align<C: HasDataLayout>(&self, cx: C) -> Align {
+        self.abi.primitive_align(cx)
+    }
 }
 
 impl<'gcx> HashStable<StableHashingContext<'gcx>> for Layout
@@ -2411,12 +2444,18 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for Abi {
         mem::discriminant(self).hash_stable(hcx, hasher);
 
         match *self {
-            Scalar(value) => {
+            Scalar(ref value) => {
                 value.hash_stable(hcx, hasher);
             }
-            Vector => {
+            Vector { ref element, count } => {
+                element.hash_stable(hcx, hasher);
+                count.hash_stable(hcx, hasher);
             }
-            Aggregate => {
+            Aggregate { sized, size, align, primitive_align } => {
+                sized.hash_stable(hcx, hasher);
+                size.hash_stable(hcx, hasher);
+                align.hash_stable(hcx, hasher);
+                primitive_align.hash_stable(hcx, hasher);
             }
         }
     }
diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs
index 879d2e326d8..b993b161877 100644
--- a/src/librustc_lint/types.rs
+++ b/src/librustc_lint/types.rs
@@ -753,7 +753,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for VariantSizeDifferences {
                     bug!("failed to get layout for `{}`: {}", t, e)
                 });
 
-                if let Layout::General { ref variants, ref size, discr, .. } = *layout {
+                if let Layout::General { ref variants, size, discr, .. } = *layout.layout {
                     let discr_size = discr.size(cx.tcx).bytes();
 
                     debug!("enum `{}` is {} bytes large with layout:\n{:#?}",
diff --git a/src/librustc_trans/abi.rs b/src/librustc_trans/abi.rs
index 93cfd967643..712108bf437 100644
--- a/src/librustc_trans/abi.rs
+++ b/src/librustc_trans/abi.rs
@@ -278,8 +278,8 @@ impl<'tcx> LayoutExt<'tcx> for FullLayout<'tcx> {
     fn is_aggregate(&self) -> bool {
         match self.abi {
             layout::Abi::Scalar(_) |
-            layout::Abi::Vector => false,
-            layout::Abi::Aggregate => true
+            layout::Abi::Vector { .. } => false,
+            layout::Abi::Aggregate { .. } => true
         }
     }
 
@@ -299,14 +299,14 @@ impl<'tcx> LayoutExt<'tcx> for FullLayout<'tcx> {
                 })
             }
 
-            layout::Abi::Vector => {
+            layout::Abi::Vector { .. } => {
                 Some(Reg {
                     kind: RegKind::Vector,
                     size: self.size(ccx)
                 })
             }
 
-            layout::Abi::Aggregate => {
+            layout::Abi::Aggregate { .. } => {
                 if let Layout::Array { count, .. } = *self.layout {
                     if count > 0 {
                         return self.field(ccx, 0).homogeneous_aggregate(ccx);
@@ -767,7 +767,7 @@ impl<'a, 'tcx> FnType<'tcx> {
         for ty in inputs.iter().chain(extra_args.iter()) {
             let mut arg = arg_of(ty, false);
 
-            if let ty::layout::FatPointer { .. } = *arg.layout {
+            if let ty::layout::FatPointer { .. } = *arg.layout.layout {
                 let mut data = ArgType::new(arg.layout.field(ccx, 0));
                 let mut info = ArgType::new(arg.layout.field(ccx, 1));
 
@@ -809,7 +809,7 @@ impl<'a, 'tcx> FnType<'tcx> {
            abi == Abi::RustIntrinsic || abi == Abi::PlatformIntrinsic {
             let fixup = |arg: &mut ArgType<'tcx>| {
                 match arg.layout.abi {
-                    layout::Abi::Aggregate => {}
+                    layout::Abi::Aggregate { .. } => {}
                     _ => return
                 }
 
diff --git a/src/librustc_trans/adt.rs b/src/librustc_trans/adt.rs
index 634dba3660e..314d929fe8c 100644
--- a/src/librustc_trans/adt.rs
+++ b/src/librustc_trans/adt.rs
@@ -71,7 +71,7 @@ pub fn finish_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
     if let layout::Abi::Scalar(_) = l.abi {
         return;
     }
-    match *l {
+    match *l.layout {
         layout::NullablePointer { .. } |
         layout::General { .. } |
         layout::UntaggedUnion { .. } => { }
@@ -101,7 +101,7 @@ fn generic_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
     if let layout::Abi::Scalar(value) = l.abi {
         return cx.llvm_type_of(value.to_ty(cx.tcx()));
     }
-    match *l {
+    match *l.layout {
         layout::Univariant(ref variant) => {
             match name {
                 None => {
diff --git a/src/librustc_trans/cabi_s390x.rs b/src/librustc_trans/cabi_s390x.rs
index a45fe662bd6..2766edb59c1 100644
--- a/src/librustc_trans/cabi_s390x.rs
+++ b/src/librustc_trans/cabi_s390x.rs
@@ -29,7 +29,7 @@ fn is_single_fp_element<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
     match layout.abi {
         layout::Abi::Scalar(layout::F32) |
         layout::Abi::Scalar(layout::F64) => true,
-        layout::Abi::Aggregate => {
+        layout::Abi::Aggregate { .. } => {
             if layout.fields.count() == 1 && layout.fields.offset(0).bytes() == 0 {
                 is_single_fp_element(ccx, layout.field(ccx, 0))
             } else {
diff --git a/src/librustc_trans/cabi_x86.rs b/src/librustc_trans/cabi_x86.rs
index bc7c9a3ed05..7d3621d53e0 100644
--- a/src/librustc_trans/cabi_x86.rs
+++ b/src/librustc_trans/cabi_x86.rs
@@ -24,7 +24,7 @@ fn is_single_fp_element<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
     match layout.abi {
         layout::Abi::Scalar(layout::F32) |
         layout::Abi::Scalar(layout::F64) => true,
-        layout::Abi::Aggregate => {
+        layout::Abi::Aggregate { .. } => {
             if layout.fields.count() == 1 && layout.fields.offset(0).bytes() == 0 {
                 is_single_fp_element(ccx, layout.field(ccx, 0))
             } else {
diff --git a/src/librustc_trans/cabi_x86_64.rs b/src/librustc_trans/cabi_x86_64.rs
index f2208e4909e..d6d46307a4f 100644
--- a/src/librustc_trans/cabi_x86_64.rs
+++ b/src/librustc_trans/cabi_x86_64.rs
@@ -75,22 +75,22 @@ fn classify_arg<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, arg: &ArgType<'tcx>)
                 unify(cls, off, reg);
             }
 
-            layout::Abi::Vector => {
+            layout::Abi::Vector { element, count } => {
                 unify(cls, off, Class::Sse);
 
                 // everything after the first one is the upper
                 // half of a register.
-                let eltsz = layout.field(ccx, 0).size(ccx);
-                for i in 1..layout.fields.count() {
+                let eltsz = element.size(ccx);
+                for i in 1..count {
                     unify(cls, off + eltsz * (i as u64), Class::SseUp);
                 }
             }
 
-            layout::Abi::Aggregate => {
+            layout::Abi::Aggregate { .. } => {
                 // FIXME(eddyb) have to work around Rust enums for now.
                 // Fix is either guarantee no data where there is no field,
                 // by putting variants in fields, or be more clever.
-                match *layout {
+                match *layout.layout {
                     Layout::General { .. } |
                     Layout::NullablePointer { .. } => return Err(Memory),
                     _ => {}
diff --git a/src/librustc_trans/cabi_x86_win64.rs b/src/librustc_trans/cabi_x86_win64.rs
index 1d391da5993..b27ccc98861 100644
--- a/src/librustc_trans/cabi_x86_win64.rs
+++ b/src/librustc_trans/cabi_x86_win64.rs
@@ -8,32 +8,36 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use abi::{ArgType, FnType, LayoutExt, Reg};
+use abi::{ArgType, FnType, Reg};
 use common::CrateContext;
 
-use rustc::ty::layout::Layout;
+use rustc::ty::layout;
 
 // Win64 ABI: http://msdn.microsoft.com/en-us/library/zthk2dkh.aspx
 
 pub fn compute_abi_info<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fty: &mut FnType<'tcx>) {
     let fixup = |a: &mut ArgType<'tcx>| {
         let size = a.layout.size(ccx);
-        if a.layout.is_aggregate() {
-            match size.bits() {
-                8 => a.cast_to(Reg::i8()),
-                16 => a.cast_to(Reg::i16()),
-                32 => a.cast_to(Reg::i32()),
-                64 => a.cast_to(Reg::i64()),
-                _ => a.make_indirect(ccx)
-            };
-        } else {
-            if let Layout::Vector { .. } = *a.layout {
+        match a.layout.abi {
+            layout::Abi::Aggregate { .. } => {
+                match size.bits() {
+                    8 => a.cast_to(Reg::i8()),
+                    16 => a.cast_to(Reg::i16()),
+                    32 => a.cast_to(Reg::i32()),
+                    64 => a.cast_to(Reg::i64()),
+                    _ => a.make_indirect(ccx)
+                }
+            }
+            layout::Abi::Vector { .. } => {
                 // FIXME(eddyb) there should be a size cap here
                 // (probably what clang calls "illegal vectors").
-            } else if size.bytes() > 8 {
-                a.make_indirect(ccx);
-            } else {
-                a.extend_integer_width_to(32);
+            }
+            layout::Abi::Scalar(_) => {
+                if size.bytes() > 8 {
+                    a.make_indirect(ccx);
+                } else {
+                    a.extend_integer_width_to(32);
+                }
             }
         }
     };
diff --git a/src/librustc_trans/common.rs b/src/librustc_trans/common.rs
index b80fded638d..bc6ddef0e72 100644
--- a/src/librustc_trans/common.rs
+++ b/src/librustc_trans/common.rs
@@ -41,7 +41,7 @@ use syntax_pos::{Span, DUMMY_SP};
 pub use context::{CrateContext, SharedCrateContext};
 
 pub fn type_is_fat_ptr<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) -> bool {
-    if let Layout::FatPointer { .. } = *ccx.layout_of(ty) {
+    if let Layout::FatPointer { .. } = *ccx.layout_of(ty).layout {
         true
     } else {
         false
@@ -51,9 +51,9 @@ pub fn type_is_fat_ptr<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) ->
 pub fn type_is_immediate<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) -> bool {
     let layout = ccx.layout_of(ty);
     match layout.abi {
-        layout::Abi::Scalar(_) | layout::Abi::Vector => true,
+        layout::Abi::Scalar(_) | layout::Abi::Vector { .. } => true,
 
-        layout::Abi::Aggregate => {
+        layout::Abi::Aggregate { .. } => {
             !layout.is_unsized() && layout.size(ccx).bytes() == 0
         }
     }
@@ -63,7 +63,7 @@ pub fn type_is_immediate<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) -
 pub fn type_is_imm_pair<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>)
                                   -> bool {
     let layout = ccx.layout_of(ty);
-    match *layout {
+    match *layout.layout {
         Layout::FatPointer { .. } => true,
         Layout::Univariant(ref variant) => {
             // There must be only 2 fields.
diff --git a/src/librustc_trans/debuginfo/metadata.rs b/src/librustc_trans/debuginfo/metadata.rs
index 0e74d985570..6ab89f5c3eb 100644
--- a/src/librustc_trans/debuginfo/metadata.rs
+++ b/src/librustc_trans/debuginfo/metadata.rs
@@ -941,7 +941,7 @@ impl<'tcx> StructMemberDescriptionFactory<'tcx> {
         let layout = cx.layout_of(self.ty);
 
         let tmp;
-        let offsets = match *layout {
+        let offsets = match *layout.layout {
             layout::Univariant(ref variant) => &variant.offsets,
             layout::Vector { element, count } => {
                 let element_size = element.size(cx).bytes();
@@ -1022,7 +1022,7 @@ impl<'tcx> TupleMemberDescriptionFactory<'tcx> {
     fn create_member_descriptions<'a>(&self, cx: &CrateContext<'a, 'tcx>)
                                       -> Vec<MemberDescription> {
         let layout = cx.layout_of(self.ty);
-        let offsets = if let layout::Univariant(ref variant) = *layout {
+        let offsets = if let layout::Univariant(ref variant) = *layout.layout {
             &variant.offsets
         } else {
             bug!("{} is not a tuple", self.ty);
@@ -1339,7 +1339,7 @@ fn describe_enum_variant<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                                    span: Span)
                                    -> (DICompositeType, MemberDescriptionFactory<'tcx>) {
     let layout = cx.layout_of(enum_type);
-    let maybe_discr = match *layout {
+    let maybe_discr = match *layout.layout {
         layout::General { .. } => Some(layout.field(cx, 0).ty),
         _ => None,
     };
@@ -1491,7 +1491,7 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
 
     let type_rep = cx.layout_of(enum_type);
 
-    let discriminant_type_metadata = match *type_rep {
+    let discriminant_type_metadata = match *type_rep.layout {
         layout::NullablePointer { .. } | layout::Univariant { .. } => None,
         layout::General { discr, .. } => Some(discriminant_type_metadata(discr)),
         ref l @ _ => bug!("Not an enum layout: {:#?}", l)
diff --git a/src/librustc_trans/glue.rs b/src/librustc_trans/glue.rs
index 61c0820539d..209083a8e25 100644
--- a/src/librustc_trans/glue.rs
+++ b/src/librustc_trans/glue.rs
@@ -58,7 +58,7 @@ pub fn size_and_align_of_dst<'a, 'tcx>(bcx: &Builder<'a, 'tcx>, t: Ty<'tcx>, inf
             let layout = ccx.layout_of(t);
             debug!("DST {} layout: {:?}", t, layout);
 
-            let (sized_size, sized_align) = match *layout {
+            let (sized_size, sized_align) = match *layout.layout {
                 ty::layout::Layout::Univariant(ref variant) => {
                     (variant.offsets.last().map_or(0, |o| o.bytes()), variant.align.abi())
                 }
diff --git a/src/librustc_trans/mir/constant.rs b/src/librustc_trans/mir/constant.rs
index 4f7c91efccd..c64333fc044 100644
--- a/src/librustc_trans/mir/constant.rs
+++ b/src/librustc_trans/mir/constant.rs
@@ -1090,7 +1090,7 @@ fn trans_const_adt<'a, 'tcx>(
         mir::AggregateKind::Adt(_, index, _, _) => index,
         _ => 0,
     };
-    match *l {
+    match *l.layout {
         layout::General { ref variants, .. } => {
             let discr = match *kind {
                 mir::AggregateKind::Adt(adt_def, _, _, _) => {
diff --git a/src/librustc_trans/mir/lvalue.rs b/src/librustc_trans/mir/lvalue.rs
index 325ccd4fde3..00c76bee1a8 100644
--- a/src/librustc_trans/mir/lvalue.rs
+++ b/src/librustc_trans/mir/lvalue.rs
@@ -208,10 +208,10 @@ impl<'a, 'tcx> LvalueRef<'tcx> {
         let field = l.field(ccx, ix);
         let offset = l.fields.offset(ix).bytes();
 
-        let alignment = self.alignment | Alignment::from(&*l);
+        let alignment = self.alignment | Alignment::from(l.layout);
 
         // Unions and newtypes only use an offset of 0.
-        match *l {
+        match *l.layout {
             // FIXME(eddyb) The fields of a fat pointer aren't correct, especially
             // to unsized structs, we can't represent their pointee types in `Ty`.
             Layout::FatPointer { .. } => {}
@@ -234,7 +234,7 @@ impl<'a, 'tcx> LvalueRef<'tcx> {
         }
 
         // Discriminant field of enums.
-        match *l {
+        match *l.layout {
             layout::NullablePointer { .. } if l.variant_index.is_none() => {
                 let ty = ccx.llvm_type_of(field.ty);
                 let size = field.size(ccx).bytes();
@@ -271,7 +271,7 @@ impl<'a, 'tcx> LvalueRef<'tcx> {
         };
 
         // Check whether the variant being used is packed, if applicable.
-        let is_packed = match (&*l, l.variant_index) {
+        let is_packed = match (l.layout, l.variant_index) {
             (&layout::Univariant(ref variant), _) => variant.packed,
             (&layout::NullablePointer { ref variants, .. }, Some(v)) |
             (&layout::General { ref variants, .. }, Some(v)) => variants[v].packed,
@@ -354,7 +354,7 @@ impl<'a, 'tcx> LvalueRef<'tcx> {
         let l = bcx.ccx.layout_of(self.ty.to_ty(bcx.tcx()));
 
         let cast_to = bcx.ccx.immediate_llvm_type_of(cast_to);
-        match *l {
+        match *l.layout {
             layout::Univariant { .. } |
             layout::UntaggedUnion { .. } => return C_uint(cast_to, 0),
             _ => {}
@@ -366,7 +366,7 @@ impl<'a, 'tcx> LvalueRef<'tcx> {
             layout::Abi::Scalar(discr) => discr,
             _ => bug!("discriminant not scalar: {:#?}", discr_layout)
         };
-        let (min, max) = match *l {
+        let (min, max) = match *l.layout {
             layout::General { ref discr_range, .. } => (discr_range.start, discr_range.end),
             _ => (0, u64::max_value()),
         };
@@ -392,7 +392,7 @@ impl<'a, 'tcx> LvalueRef<'tcx> {
                 bcx.load(discr.llval, discr.alignment.non_abi())
             }
         };
-        match *l {
+        match *l.layout {
             layout::General { .. } => {
                 let signed = match discr_scalar {
                     layout::Int(_, signed) => signed,
@@ -416,7 +416,7 @@ impl<'a, 'tcx> LvalueRef<'tcx> {
         let to = l.ty.ty_adt_def().unwrap()
             .discriminant_for_variant(bcx.tcx(), variant_index)
             .to_u128_unchecked() as u64;
-        match *l {
+        match *l.layout {
             layout::General { .. } => {
                 let ptr = self.project_field(bcx, 0);
                 bcx.store(C_int(bcx.ccx.llvm_type_of(ptr.ty.to_ty(bcx.tcx())), to as i64),
@@ -471,7 +471,7 @@ impl<'a, 'tcx> LvalueRef<'tcx> {
 
             // If this is an enum, cast to the appropriate variant struct type.
             let layout = bcx.ccx.layout_of(ty).for_variant(variant_index);
-            match *layout {
+            match *layout.layout {
                 layout::NullablePointer { ref variants, .. } |
                 layout::General { ref variants, .. } => {
                     let st = &variants[variant_index];
diff --git a/src/librustc_trans/mir/mod.rs b/src/librustc_trans/mir/mod.rs
index b1a9be881f7..a71bcf47838 100644
--- a/src/librustc_trans/mir/mod.rs
+++ b/src/librustc_trans/mir/mod.rs
@@ -576,7 +576,7 @@ fn arg_local_refs<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
             };
 
             let layout = bcx.ccx.layout_of(closure_ty);
-            let offsets = match *layout {
+            let offsets = match *layout.layout {
                 layout::Univariant(ref variant) => &variant.offsets[..],
                 _ => bug!("Closures are only supposed to be Univariant")
             };
diff --git a/src/librustc_trans/mir/rvalue.rs b/src/librustc_trans/mir/rvalue.rs
index b7143f23691..518f36a77b5 100644
--- a/src/librustc_trans/mir/rvalue.rs
+++ b/src/librustc_trans/mir/rvalue.rs
@@ -277,7 +277,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
                         let llval = operand.immediate();
                         let l = bcx.ccx.layout_of(operand.ty);
 
-                        if let Layout::General { ref discr_range, .. } = *l {
+                        if let Layout::General { ref discr_range, .. } = *l.layout {
                             if discr_range.end > discr_range.start {
                                 // We want `table[e as usize]` to not
                                 // have bound checks, and this is the most
diff --git a/src/librustc_trans/type_of.rs b/src/librustc_trans/type_of.rs
index eb52d58098d..b829d33600c 100644
--- a/src/librustc_trans/type_of.rs
+++ b/src/librustc_trans/type_of.rs
@@ -240,7 +240,7 @@ impl<'tcx> LayoutLlvmExt for FullLayout<'tcx> {
         if let layout::Abi::Scalar(_) = self.abi {
             bug!("FullLayout::llvm_field_index({:?}): not applicable", self);
         }
-        match **self {
+        match *self.layout {
             Layout::Scalar { .. } |
             Layout::UntaggedUnion { .. } => {
                 bug!("FullLayout::llvm_field_index({:?}): not applicable", self)