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>> { + where I: Iterator, 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(&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(&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(&self, cx: C) -> (Size, Align) { + (self.size(cx), self.align(cx)) + } + + /// Returns alignment before repr alignment is applied + pub fn primitive_align(&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 { .. } | - FatPointer { .. } | - Univariant(_) | - UntaggedUnion(_) => Abi::Aggregate, + 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 + } + } - General { discr, .. } | - NullablePointer { discr, .. } => { - if fields.offset(0).bytes() == 0 && discr.size(cx) == layout.size(cx) { + 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) + } + } + + 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(&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(&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(&self, cx: C) -> (Size, Align) { - (self.size(cx), self.align(cx)) - } - - /// Returns alignment before repr alignment is applied - pub fn primitive_align(&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::>() @@ -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> 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> 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> 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> 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(&self, cx: C) -> Size { + self.abi.size(cx) + } + + pub fn align(&self, cx: C) -> Align { + self.abi.align(cx) + } + + pub fn size_and_align(&self, cx: C) -> (Size, Align) { + self.abi.size_and_align(cx) + } + + /// Returns alignment before repr alignment is applied + pub fn primitive_align(&self, cx: C) -> Align { + self.abi.primitive_align(cx) + } } impl<'gcx> HashStable> for Layout @@ -2411,12 +2444,18 @@ impl<'gcx> HashStable> 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 { 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)