about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc/ty/layout.rs95
-rw-r--r--src/librustc_trans/abi.rs13
-rw-r--r--src/librustc_trans/cabi_s390x.rs12
-rw-r--r--src/librustc_trans/cabi_x86.rs12
4 files changed, 51 insertions, 81 deletions
diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs
index aebe0c852b3..d798982f3c8 100644
--- a/src/librustc/ty/layout.rs
+++ b/src/librustc/ty/layout.rs
@@ -838,14 +838,18 @@ impl<'a, 'tcx> Struct {
                               -> Result<Option<(Size, Primitive)>, LayoutError<'tcx>> {
         let cx = (tcx, param_env);
         match (layout.layout, &layout.ty.sty) {
-            (&Scalar { non_zero: true, value, .. }, _) => {
-                Ok(Some((Size::from_bytes(0), value)))
+            (&Scalar(Pointer), _) if !layout.ty.is_unsafe_ptr() => {
+                Ok(Some((Size::from_bytes(0), Pointer)))
             }
-            (&CEnum { non_zero: true, discr, .. }, _) => {
-                Ok(Some((Size::from_bytes(0), Int(discr))))
+            (&CEnum { discr, .. }, &ty::TyAdt(def, _)) => {
+                if def.discriminants(tcx).all(|d| d.to_u128_unchecked() != 0) {
+                    Ok(Some((Size::from_bytes(0), Int(discr))))
+                } else {
+                    Ok(None)
+                }
             }
 
-            (&FatPointer { non_zero: true, .. }, _) => {
+            (&FatPointer(_), _) if !layout.ty.is_unsafe_ptr() => {
                 Ok(Some((layout.fields.offset(FAT_PTR_ADDR), Pointer)))
             }
 
@@ -853,12 +857,10 @@ impl<'a, 'tcx> Struct {
             (_, &ty::TyAdt(def, _)) if Some(def.did) == tcx.lang_items().non_zero() => {
                 let field = layout.field(cx, 0)?;
                 match *field {
-                    // FIXME(eddyb) also allow floating-point types here.
-                    Scalar { value: value @ Int(_), non_zero: false } |
-                    Scalar { value: value @ Pointer, non_zero: false } => {
+                    Scalar(value) => {
                         Ok(Some((layout.fields.offset(0), value)))
                     }
-                    FatPointer { non_zero: false, .. } => {
+                    FatPointer(_) => {
                         Ok(Some((layout.fields.offset(0) +
                                  field.fields.offset(FAT_PTR_ADDR),
                                  Pointer)))
@@ -1070,11 +1072,7 @@ pub enum Abi {
 #[derive(Debug, PartialEq, Eq, Hash)]
 pub enum Layout {
     /// TyBool, TyChar, TyInt, TyUint, TyFloat, TyRawPtr, TyRef or TyFnPtr.
-    Scalar {
-        value: Primitive,
-        // If true, the value cannot represent a bit pattern of all zeroes.
-        non_zero: bool
-    },
+    Scalar(Primitive),
 
     /// SIMD vectors, from structs marked with #[repr(simd)].
     Vector {
@@ -1092,12 +1090,8 @@ pub enum Layout {
         count: u64
     },
 
-    /// TyRawPtr or TyRef with a !Sized pointee.
-    FatPointer {
-        metadata: Primitive,
-        /// If true, the pointer cannot be null.
-        non_zero: bool
-    },
+    /// TyRawPtr or TyRef with a !Sized pointee. The primitive is the metadata.
+    FatPointer(Primitive),
 
     // Remaining variants are all ADTs such as structs, enums or tuples.
 
@@ -1105,7 +1099,6 @@ pub enum Layout {
     CEnum {
         discr: Integer,
         signed: bool,
-        non_zero: bool,
         /// Inclusive discriminant range.
         /// If min > max, it represents min...u64::MAX followed by 0...max.
         // FIXME(eddyb) always use the shortest range, e.g. by finding
@@ -1211,7 +1204,7 @@ impl<'a, 'tcx> Layout {
         let success = |layout| {
             let layout = tcx.intern_layout(layout);
             let fields = match *layout {
-                Scalar { .. } |
+                Scalar(_) |
                 CEnum { .. } => {
                     FieldPlacement::union(0)
                 }
@@ -1258,7 +1251,7 @@ impl<'a, 'tcx> Layout {
                 }
             };
             let abi = match *layout {
-                Scalar { value, .. } => Abi::Scalar(value),
+                Scalar(value) => Abi::Scalar(value),
                 CEnum { discr, .. } => Abi::Scalar(Int(discr)),
 
                 Vector { .. } => Abi::Vector,
@@ -1286,43 +1279,36 @@ impl<'a, 'tcx> Layout {
         assert!(!ty.has_infer_types());
 
         let ptr_layout = |pointee: Ty<'tcx>| {
-            let non_zero = !ty.is_unsafe_ptr();
             let pointee = tcx.normalize_associated_type_in_env(&pointee, param_env);
             if pointee.is_sized(tcx, param_env, DUMMY_SP) {
-                Ok(Scalar { value: Pointer, non_zero })
+                Ok(Scalar(Pointer))
             } else {
                 let unsized_part = tcx.struct_tail(pointee);
                 let metadata = match unsized_part.sty {
-                    ty::TyForeign(..) => return Ok(Scalar { value: Pointer, non_zero }),
+                    ty::TyForeign(..) => return Ok(Scalar(Pointer)),
                     ty::TySlice(_) | ty::TyStr => {
                         Int(dl.ptr_sized_integer())
                     }
                     ty::TyDynamic(..) => Pointer,
                     _ => return Err(LayoutError::Unknown(unsized_part))
                 };
-                Ok(FatPointer { metadata, non_zero })
+                Ok(FatPointer(metadata))
             }
         };
 
         let layout = match ty.sty {
             // Basic scalars.
-            ty::TyBool => Scalar { value: Int(I1), non_zero: false },
-            ty::TyChar => Scalar { value: Int(I32), non_zero: false },
+            ty::TyBool => Scalar(Int(I1)),
+            ty::TyChar => Scalar(Int(I32)),
             ty::TyInt(ity) => {
-                Scalar {
-                    value: Int(Integer::from_attr(dl, attr::SignedInt(ity))),
-                    non_zero: false
-                }
+                Scalar(Int(Integer::from_attr(dl, attr::SignedInt(ity))))
             }
             ty::TyUint(ity) => {
-                Scalar {
-                    value: Int(Integer::from_attr(dl, attr::UnsignedInt(ity))),
-                    non_zero: false
-                }
+                Scalar(Int(Integer::from_attr(dl, attr::UnsignedInt(ity))))
             }
-            ty::TyFloat(FloatTy::F32) => Scalar { value: F32, non_zero: false },
-            ty::TyFloat(FloatTy::F64) => Scalar { value: F64, non_zero: false },
-            ty::TyFnPtr(_) => Scalar { value: Pointer, non_zero: true },
+            ty::TyFloat(FloatTy::F32) => Scalar(F32),
+            ty::TyFloat(FloatTy::F64) => Scalar(F64),
+            ty::TyFnPtr(_) => Scalar(Pointer),
 
             // The never type.
             ty::TyNever => {
@@ -1430,7 +1416,7 @@ impl<'a, 'tcx> Layout {
             ty::TyAdt(def, ..) if def.repr.simd() => {
                 let element = ty.simd_type(tcx);
                 match *cx.layout_of(element)? {
-                    Scalar { value, .. } => {
+                    Scalar(value) => {
                         return success(Vector {
                             element: value,
                             count: ty.simd_size(tcx) as u64
@@ -1456,12 +1442,9 @@ impl<'a, 'tcx> Layout {
 
                 if def.is_enum() && def.variants.iter().all(|v| v.fields.is_empty()) {
                     // All bodies empty -> intlike
-                    let (mut min, mut max, mut non_zero) = (i64::max_value(),
-                                                            i64::min_value(),
-                                                            true);
+                    let (mut min, mut max) = (i64::max_value(), i64::min_value());
                     for discr in def.discriminants(tcx) {
                         let x = discr.to_u128_unchecked() as i64;
-                        if x == 0 { non_zero = false; }
                         if x < min { min = x; }
                         if x > max { max = x; }
                     }
@@ -1472,7 +1455,6 @@ impl<'a, 'tcx> Layout {
                     return success(CEnum {
                         discr,
                         signed,
-                        non_zero,
                         // FIXME: should be u128?
                         min: min as u64,
                         max: max as u64
@@ -1699,7 +1681,7 @@ impl<'a, 'tcx> Layout {
     /// Returns true if the layout corresponds to an unsized type.
     pub fn is_unsized(&self) -> bool {
         match *self {
-            Scalar {..} | Vector {..} | FatPointer {..} |
+            Scalar(_) | Vector {..} | FatPointer {..} |
             CEnum {..} | UntaggedUnion {..} | General {..} |
             NullablePointer {..} => false,
 
@@ -1712,7 +1694,7 @@ impl<'a, 'tcx> Layout {
         let dl = cx.data_layout();
 
         match *self {
-            Scalar { value, .. } => {
+            Scalar(value) => {
                 value.size(dl)
             }
 
@@ -1734,7 +1716,7 @@ impl<'a, 'tcx> Layout {
                 }
             }
 
-            FatPointer { metadata, .. } => {
+            FatPointer(metadata) => {
                 // Effectively a (ptr, meta) tuple.
                 (Pointer.size(dl).abi_align(metadata.align(dl)) +
                  metadata.size(dl)).abi_align(self.align(dl))
@@ -1755,7 +1737,7 @@ impl<'a, 'tcx> Layout {
         let dl = cx.data_layout();
 
         match *self {
-            Scalar { value, .. } => {
+            Scalar(value) => {
                 value.align(dl)
             }
 
@@ -1769,7 +1751,7 @@ impl<'a, 'tcx> Layout {
                 dl.vector_align(vec_size)
             }
 
-            FatPointer { metadata, .. } => {
+            FatPointer(metadata) => {
                 // Effectively a (ptr, meta) tuple.
                 Pointer.align(dl).max(metadata.align(dl))
             }
@@ -1993,7 +1975,7 @@ impl<'a, 'tcx> Layout {
 
             // other cases provide little interesting (i.e. adjustable
             // via representation tweaks) size info beyond total size.
-            Layout::Scalar { .. } |
+            Layout::Scalar(_) |
             Layout::Vector { .. } |
             Layout::Array { .. } |
             Layout::FatPointer { .. } => {
@@ -2421,9 +2403,8 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for Layout
         mem::discriminant(self).hash_stable(hcx, hasher);
 
         match *self {
-            Scalar { value, non_zero } => {
+            Scalar(ref value) => {
                 value.hash_stable(hcx, hasher);
-                non_zero.hash_stable(hcx, hasher);
             }
             Vector { element, count } => {
                 element.hash_stable(hcx, hasher);
@@ -2436,14 +2417,12 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for Layout
                 element_size.hash_stable(hcx, hasher);
                 count.hash_stable(hcx, hasher);
             }
-            FatPointer { ref metadata, non_zero } => {
+            FatPointer(ref metadata) => {
                 metadata.hash_stable(hcx, hasher);
-                non_zero.hash_stable(hcx, hasher);
             }
-            CEnum { discr, signed, non_zero, min, max } => {
+            CEnum { discr, signed, min, max } => {
                 discr.hash_stable(hcx, hasher);
                 signed.hash_stable(hcx, hasher);
-                non_zero.hash_stable(hcx, hasher);
                 min.hash_stable(hcx, hasher);
                 max.hash_stable(hcx, hasher);
             }
diff --git a/src/librustc_trans/abi.rs b/src/librustc_trans/abi.rs
index 8be2cb2a1d3..c3b6c1cce67 100644
--- a/src/librustc_trans/abi.rs
+++ b/src/librustc_trans/abi.rs
@@ -468,17 +468,8 @@ impl<'a, 'tcx> ArgType<'tcx> {
     pub fn extend_integer_width_to(&mut self, bits: u64) {
         // Only integers have signedness
         let (i, signed) = match *self.layout {
-            Layout::Scalar { value, .. } => {
-                match value {
-                    layout::Int(i) => {
-                        if self.layout.ty.is_integral() {
-                            (i, self.layout.ty.is_signed())
-                        } else {
-                            return;
-                        }
-                    }
-                    _ => return
-                }
+            Layout::Scalar(layout::Int(i)) if self.layout.ty.is_integral() => {
+                (i, self.layout.ty.is_signed())
             }
 
             // Rust enum types that map onto C enums also need to follow
diff --git a/src/librustc_trans/cabi_s390x.rs b/src/librustc_trans/cabi_s390x.rs
index 4db33b9204a..a45fe662bd6 100644
--- a/src/librustc_trans/cabi_s390x.rs
+++ b/src/librustc_trans/cabi_s390x.rs
@@ -14,7 +14,7 @@
 use abi::{FnType, ArgType, LayoutExt, Reg};
 use context::CrateContext;
 
-use rustc::ty::layout::{self, Layout, FullLayout};
+use rustc::ty::layout::{self, FullLayout};
 
 fn classify_ret_ty<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ret: &mut ArgType<'tcx>) {
     if !ret.layout.is_aggregate() && ret.layout.size(ccx).bits() <= 64 {
@@ -26,11 +26,11 @@ fn classify_ret_ty<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ret: &mut ArgType<'tc
 
 fn is_single_fp_element<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                                   layout: FullLayout<'tcx>) -> bool {
-    match *layout {
-        Layout::Scalar { value: layout::F32, .. } |
-        Layout::Scalar { value: layout::F64, .. } => true,
-        Layout::Univariant { .. } => {
-            if layout.fields.count() == 1 {
+    match layout.abi {
+        layout::Abi::Scalar(layout::F32) |
+        layout::Abi::Scalar(layout::F64) => true,
+        layout::Abi::Aggregate => {
+            if layout.fields.count() == 1 && layout.fields.offset(0).bytes() == 0 {
                 is_single_fp_element(ccx, layout.field(ccx, 0))
             } else {
                 false
diff --git a/src/librustc_trans/cabi_x86.rs b/src/librustc_trans/cabi_x86.rs
index 362ceb60601..bc7c9a3ed05 100644
--- a/src/librustc_trans/cabi_x86.rs
+++ b/src/librustc_trans/cabi_x86.rs
@@ -11,7 +11,7 @@
 use abi::{ArgAttribute, FnType, LayoutExt, Reg, RegKind};
 use common::CrateContext;
 
-use rustc::ty::layout::{self, Layout, FullLayout};
+use rustc::ty::layout::{self, FullLayout};
 
 #[derive(PartialEq)]
 pub enum Flavor {
@@ -21,11 +21,11 @@ pub enum Flavor {
 
 fn is_single_fp_element<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                                   layout: FullLayout<'tcx>) -> bool {
-    match *layout {
-        Layout::Scalar { value: layout::F32, .. } |
-        Layout::Scalar { value: layout::F64, .. } => true,
-        Layout::Univariant { .. } => {
-            if layout.fields.count() == 1 {
+    match layout.abi {
+        layout::Abi::Scalar(layout::F32) |
+        layout::Abi::Scalar(layout::F64) => true,
+        layout::Abi::Aggregate => {
+            if layout.fields.count() == 1 && layout.fields.offset(0).bytes() == 0 {
                 is_single_fp_element(ccx, layout.field(ccx, 0))
             } else {
                 false