about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEduard-Mihai Burtescu <edy.burt@gmail.com>2017-09-17 02:25:20 +0300
committerEduard-Mihai Burtescu <edy.burt@gmail.com>2017-11-19 02:14:30 +0200
commitbd86f3739e76484e410ec5e651ab3ee9049f31ba (patch)
tree9f92a22058f1ec51fa1f66fa88decaed8da2b155
parent33a205b56fbe5039d3f64743334b634be8dc4f0c (diff)
downloadrust-bd86f3739e76484e410ec5e651ab3ee9049f31ba.tar.gz
rust-bd86f3739e76484e410ec5e651ab3ee9049f31ba.zip
rustc: make Layout::NullablePointer a lot more like Layout::General.
-rw-r--r--src/librustc/ty/layout.rs109
-rw-r--r--src/librustc_trans/adt.rs51
-rw-r--r--src/librustc_trans/debuginfo/metadata.rs6
-rw-r--r--src/librustc_trans/mir/constant.rs4
-rw-r--r--src/librustc_trans/mir/lvalue.rs16
-rw-r--r--src/librustc_trans/type_of.rs9
-rw-r--r--src/test/ui/print_type_sizes/nullable.stdout3
7 files changed, 83 insertions, 115 deletions
diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs
index 5775fc957b5..bd99ae0204a 100644
--- a/src/librustc/ty/layout.rs
+++ b/src/librustc/ty/layout.rs
@@ -1128,9 +1128,12 @@ pub enum Layout {
     /// identity function.
     NullablePointer {
         nndiscr: u64,
-        nonnull: Struct,
         discr: Primitive,
         discr_offset: Size,
+        variants: Vec<Struct>,
+        size: Size,
+        align: Align,
+        primitive_align: Align,
     }
 }
 
@@ -1471,23 +1474,20 @@ impl<'a, 'tcx> Layout {
                    !def.repr.inhibit_enum_layout_opt() &&
                    no_explicit_discriminants {
                     // Nullable pointer optimization
-                    let st0 = Struct::new(dl, &variants[0],
-                        &def.repr, StructKind::AlwaysSizedUnivariant, ty)?;
-                    let st1 = Struct::new(dl, &variants[1],
-                        &def.repr, StructKind::AlwaysSizedUnivariant, ty)?;
+                    let mut st = vec![
+                        Struct::new(dl, &variants[0],
+                            &def.repr, StructKind::AlwaysSizedUnivariant, ty)?,
+                        Struct::new(dl, &variants[1],
+                            &def.repr, StructKind::AlwaysSizedUnivariant, ty)?
+                    ];
 
                     let mut choice = None;
                     for discr in 0..2 {
-                        let (st, other) = if discr == 0 {
-                            (&st0, &st1)
-                        } else {
-                            (&st1, &st0)
-                        };
-                        if other.stride().bytes() > 0 {
+                        if st[1 - discr].stride().bytes() > 0 {
                             continue;
                         }
 
-                        let field = st.non_zero_field(tcx, param_env,
+                        let field = st[discr].non_zero_field(tcx, param_env,
                             variants[discr].iter().map(|&f| Ok(f)))?;
                         if let Some((offset, primitive)) = field {
                             choice = Some((discr, offset, primitive));
@@ -1496,23 +1496,22 @@ impl<'a, 'tcx> Layout {
                     }
 
                     if let Some((discr, offset, primitive)) = choice {
-                        // HACK(eddyb) work around not being able to move
-                        // out of arrays with just the indexing operator.
-                        let mut st = if discr == 0 { st0 } else { st1 };
-
                         let mut discr_align = primitive.align(dl);
                         if offset.abi_align(discr_align) != offset {
-                            st.packed = true;
+                            st[discr].packed = true;
                             discr_align = dl.i8_align;
                         }
-                        st.align = st.align.max(discr_align);
-                        st.primitive_align = st.primitive_align.max(discr_align);
+                        let align = st[discr].align.max(discr_align);
+                        let primitive_align = st[discr].primitive_align.max(discr_align);
 
                         return success(NullablePointer {
                             nndiscr: discr as u64,
-                            nonnull: st,
                             discr: primitive,
                             discr_offset: offset,
+                            size: st[discr].stride(),
+                            align,
+                            primitive_align,
+                            variants: st,
                         });
                     }
                 }
@@ -1693,13 +1692,10 @@ impl<'a, 'tcx> Layout {
                  metadata.size(dl)).abi_align(self.align(dl))
             }
 
+            NullablePointer { size, .. } |
             General { size, .. } => size,
             UntaggedUnion(ref un) => un.stride(),
-
-            Univariant(ref variant) |
-            NullablePointer { nonnull: ref variant, .. } => {
-                variant.stride()
-            }
+            Univariant(ref variant) => variant.stride()
         }
     }
 
@@ -1726,13 +1722,11 @@ impl<'a, 'tcx> Layout {
                 Pointer.align(dl).max(metadata.align(dl))
             }
 
-            Array { align, .. } | General { align, .. } => align,
+            Array { align, .. } |
+            NullablePointer { align, .. } |
+            General { align, .. } => align,
             UntaggedUnion(ref un) => un.align,
-
-            Univariant(ref variant) |
-            NullablePointer { nonnull: ref variant, .. } => {
-                variant.align
-            }
+            Univariant(ref variant) => variant.align
         }
     }
 
@@ -1743,11 +1737,11 @@ impl<'a, 'tcx> Layout {
     /// Returns alignment before repr alignment is applied
     pub fn primitive_align<C: HasDataLayout>(&self, cx: C) -> Align {
         match *self {
-            Array { primitive_align, .. } | General { primitive_align, .. } => primitive_align,
-            Univariant(ref variant) |
-            NullablePointer { nonnull: ref variant, .. } => {
-                variant.primitive_align
-            },
+            Array { primitive_align, .. } |
+            NullablePointer { primitive_align, .. } |
+            General { primitive_align, .. } => primitive_align,
+
+            Univariant(ref variant) => variant.primitive_align,
 
             _ => self.align(cx.data_layout())
         }
@@ -1850,23 +1844,6 @@ impl<'a, 'tcx> Layout {
         };
 
         match *layout {
-            Layout::NullablePointer { nonnull: ref variant_layout,
-                                      nndiscr,
-                                      discr: _,
-                                      discr_offset: _ } => {
-                debug!("print-type-size t: `{:?}` adt nullable nndiscr {} is {:?}",
-                       ty, nndiscr, variant_layout);
-                let variant_def = &adt_def.variants[nndiscr as usize];
-                let fields: Vec<_> =
-                    variant_def.fields.iter()
-                                      .map(|field_def| (field_def.name, field_def.ty(tcx, substs)))
-                                      .collect();
-                record(adt_kind.into(),
-                       None,
-                       vec![build_variant_info(Some(variant_def.name),
-                                               &fields,
-                                               variant_layout)]);
-            }
             Layout::Univariant(ref variant_layout) => {
                 let variant_names = || {
                     adt_def.variants.iter().map(|v|format!("{}", v.name)).collect::<Vec<_>>()
@@ -1893,7 +1870,8 @@ impl<'a, 'tcx> Layout {
                 }
             }
 
-            Layout::General { ref variants, discr, .. } => {
+            Layout::NullablePointer { ref variants, .. } |
+            Layout::General { ref variants, .. } => {
                 debug!("print-type-size t: `{:?}` adt general variants def {} layouts {} {:?}",
                        ty, adt_def.variants.len(), variants.len(), variants);
                 let variant_infos: Vec<_> =
@@ -1910,7 +1888,10 @@ impl<'a, 'tcx> Layout {
                                                            variant_layout)
                                     })
                                     .collect();
-                record(adt_kind.into(), Some(discr.size(tcx)), variant_infos);
+                record(adt_kind.into(), match *layout {
+                    Layout::General { discr, .. } => Some(discr.size(tcx)),
+                    _ => None
+                }, variant_infos);
             }
 
             Layout::UntaggedUnion(ref un) => {
@@ -2215,19 +2196,13 @@ impl<'a, 'tcx> FullLayout<'tcx> {
                 }
             }
 
+            NullablePointer { ref variants, .. } |
             General { ref variants, .. } => {
                 FieldPlacement::Arbitrary {
                     offsets: &variants[variant_index].offsets
                 }
             }
 
-            NullablePointer { nndiscr, ref nonnull, .. }
-                    if nndiscr as usize == variant_index => {
-                FieldPlacement::Arbitrary {
-                    offsets: &nonnull.offsets
-                }
-            }
-
             _ => FieldPlacement::union(count)
         };
 
@@ -2390,14 +2365,20 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for Layout
             }
             NullablePointer {
                 nndiscr,
-                ref nonnull,
+                ref variants,
                 ref discr,
                 discr_offset,
+                size,
+                align,
+                primitive_align
             } => {
                 nndiscr.hash_stable(hcx, hasher);
-                nonnull.hash_stable(hcx, hasher);
+                variants.hash_stable(hcx, hasher);
                 discr.hash_stable(hcx, hasher);
                 discr_offset.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_trans/adt.rs b/src/librustc_trans/adt.rs
index e1a65f37eff..634dba3660e 100644
--- a/src/librustc_trans/adt.rs
+++ b/src/librustc_trans/adt.rs
@@ -68,28 +68,24 @@ pub fn finish_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                                 t: Ty<'tcx>, llty: &mut Type) {
     let l = cx.layout_of(t);
     debug!("finish_type_of: {} with layout {:#?}", t, l);
+    if let layout::Abi::Scalar(_) = l.abi {
+        return;
+    }
     match *l {
-        layout::General { .. } | layout::UntaggedUnion { .. } => { }
-        layout::Univariant { ..} | layout::NullablePointer { .. } => {
-            if let layout::Abi::Scalar(_) = l.abi {
-                return;
-            }
-            let (variant_layout, variant) = match *l {
-                layout::Univariant(ref variant) => {
-                    let is_enum = if let ty::TyAdt(def, _) = t.sty {
-                        def.is_enum()
-                    } else {
-                        false
-                    };
-                    if is_enum {
-                        (l.for_variant(0), variant)
-                    } else {
-                        (l, variant)
-                    }
-                }
-                layout::NullablePointer { nndiscr, ref nonnull, .. } =>
-                    (l.for_variant(nndiscr as usize), nonnull),
-                _ => unreachable!()
+        layout::NullablePointer { .. } |
+        layout::General { .. } |
+        layout::UntaggedUnion { .. } => { }
+
+        layout::Univariant(ref variant) => {
+            let is_enum = if let ty::TyAdt(def, _) = t.sty {
+                def.is_enum()
+            } else {
+                false
+            };
+            let variant_layout = if is_enum {
+                l.for_variant(0)
+            } else {
+                l
             };
             llty.set_struct_body(&struct_llfields(cx, variant_layout, variant), variant.packed)
         },
@@ -106,18 +102,6 @@ fn generic_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
         return cx.llvm_type_of(value.to_ty(cx.tcx()));
     }
     match *l {
-        layout::NullablePointer { nndiscr, ref nonnull, .. } => {
-            match name {
-                None => {
-                    Type::struct_(cx, &struct_llfields(cx, l.for_variant(nndiscr as usize),
-                                                       nonnull),
-                                  nonnull.packed)
-                }
-                Some(name) => {
-                    Type::named_struct(cx, name)
-                }
-            }
-        }
         layout::Univariant(ref variant) => {
             match name {
                 None => {
@@ -143,6 +127,7 @@ fn generic_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                 }
             }
         }
+        layout::NullablePointer { size, align, .. } |
         layout::General { size, align, .. } => {
             let fill = union_fill(cx, size, align);
             match name {
diff --git a/src/librustc_trans/debuginfo/metadata.rs b/src/librustc_trans/debuginfo/metadata.rs
index 16bca343dd0..0e74d985570 100644
--- a/src/librustc_trans/debuginfo/metadata.rs
+++ b/src/librustc_trans/debuginfo/metadata.rs
@@ -1218,11 +1218,13 @@ impl<'tcx> EnumMemberDescriptionFactory<'tcx> {
                 }
             }
             layout::NullablePointer {
-                nonnull: ref struct_def,
                 nndiscr,
                 discr,
-                discr_offset
+                discr_offset,
+                ref variants,
+                ..
             } => {
+                let struct_def = &variants[nndiscr as usize];
                 // Create a description of the non-null variant
                 let (variant_type_metadata, member_description_factory) =
                     describe_enum_variant(cx,
diff --git a/src/librustc_trans/mir/constant.rs b/src/librustc_trans/mir/constant.rs
index c8d8199a05e..4f7c91efccd 100644
--- a/src/librustc_trans/mir/constant.rs
+++ b/src/librustc_trans/mir/constant.rs
@@ -1124,9 +1124,9 @@ fn trans_const_adt<'a, 'tcx>(
         layout::Vector { .. } => {
             Const::new(C_vector(&vals.iter().map(|x| x.llval).collect::<Vec<_>>()), t)
         }
-        layout::NullablePointer { ref nonnull, nndiscr, .. } => {
+        layout::NullablePointer { ref variants, nndiscr, .. } => {
             if variant_index as u64 == nndiscr {
-                build_const_struct(ccx, l, &nonnull, vals, None)
+                build_const_struct(ccx, l, &variants[variant_index], vals, None)
             } else {
                 // Always use null even if it's not the `discrfield`th
                 // field; see #8506.
diff --git a/src/librustc_trans/mir/lvalue.rs b/src/librustc_trans/mir/lvalue.rs
index f39e3cb7812..325ccd4fde3 100644
--- a/src/librustc_trans/mir/lvalue.rs
+++ b/src/librustc_trans/mir/lvalue.rs
@@ -273,7 +273,7 @@ impl<'a, 'tcx> LvalueRef<'tcx> {
         // Check whether the variant being used is packed, if applicable.
         let is_packed = match (&*l, l.variant_index) {
             (&layout::Univariant(ref variant), _) => variant.packed,
-            (&layout::NullablePointer { ref nonnull, .. }, _) => nonnull.packed,
+            (&layout::NullablePointer { ref variants, .. }, Some(v)) |
             (&layout::General { ref variants, .. }, Some(v)) => variants[v].packed,
             _ => return simple()
         };
@@ -471,11 +471,15 @@ 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);
-            if let layout::General { ref variants, .. } = *layout {
-                let st = &variants[variant_index];
-                let variant_ty = Type::struct_(bcx.ccx,
-                    &adt::struct_llfields(bcx.ccx, layout, st), st.packed);
-                downcast.llval = bcx.pointercast(downcast.llval, variant_ty.ptr_to());
+            match *layout {
+                layout::NullablePointer { ref variants, .. } |
+                layout::General { ref variants, .. } => {
+                    let st = &variants[variant_index];
+                    let variant_ty = Type::struct_(bcx.ccx,
+                        &adt::struct_llfields(bcx.ccx, layout, st), st.packed);
+                    downcast.llval = bcx.pointercast(downcast.llval, variant_ty.ptr_to());
+                }
+                _ => {}
             }
 
             downcast
diff --git a/src/librustc_trans/type_of.rs b/src/librustc_trans/type_of.rs
index eca6057db36..eb52d58098d 100644
--- a/src/librustc_trans/type_of.rs
+++ b/src/librustc_trans/type_of.rs
@@ -259,6 +259,7 @@ impl<'tcx> LayoutLlvmExt for FullLayout<'tcx> {
                 adt::memory_index_to_gep(variant.memory_index[index] as u64)
             }
 
+            Layout::NullablePointer { ref variants, .. } |
             Layout::General { ref variants, .. } => {
                 if let Some(v) = self.variant_index {
                     adt::memory_index_to_gep(variants[v].memory_index[index] as u64)
@@ -266,14 +267,6 @@ impl<'tcx> LayoutLlvmExt for FullLayout<'tcx> {
                     bug!("FullLayout::llvm_field_index({:?}): not applicable", self)
                 }
             }
-
-            Layout::NullablePointer { nndiscr, ref nonnull, .. } => {
-                if self.variant_index == Some(nndiscr as usize) {
-                    adt::memory_index_to_gep(nonnull.memory_index[index] as u64)
-                } else {
-                    bug!("FullLayout::llvm_field_index({:?}): not applicable", self)
-                }
-            }
         }
     }
 }
diff --git a/src/test/ui/print_type_sizes/nullable.stdout b/src/test/ui/print_type_sizes/nullable.stdout
index 830678f174f..ec51adb25af 100644
--- a/src/test/ui/print_type_sizes/nullable.stdout
+++ b/src/test/ui/print_type_sizes/nullable.stdout
@@ -4,9 +4,11 @@ print-type-size     field `.post`: 2 bytes
 print-type-size     field `.pre`: 1 bytes
 print-type-size     end padding: 1 bytes
 print-type-size type: `MyOption<IndirectNonZero<u32>>`: 12 bytes, alignment: 4 bytes
+print-type-size     variant `None`: 0 bytes
 print-type-size     variant `Some`: 12 bytes
 print-type-size         field `.0`: 12 bytes
 print-type-size type: `EmbeddedDiscr`: 8 bytes, alignment: 4 bytes
+print-type-size     variant `None`: 0 bytes
 print-type-size     variant `Record`: 7 bytes
 print-type-size         field `.val`: 4 bytes
 print-type-size         field `.post`: 2 bytes
@@ -18,6 +20,7 @@ print-type-size     field `.post`: 2 bytes
 print-type-size     field `.pre`: 1 bytes
 print-type-size     end padding: 1 bytes
 print-type-size type: `MyOption<core::nonzero::NonZero<u32>>`: 4 bytes, alignment: 4 bytes
+print-type-size     variant `None`: 0 bytes
 print-type-size     variant `Some`: 4 bytes
 print-type-size         field `.0`: 4 bytes
 print-type-size type: `core::nonzero::NonZero<u32>`: 4 bytes, alignment: 4 bytes