diff options
| author | Eduard-Mihai Burtescu <edy.burt@gmail.com> | 2017-09-23 01:54:45 +0300 |
|---|---|---|
| committer | Eduard-Mihai Burtescu <edy.burt@gmail.com> | 2017-11-19 02:14:32 +0200 |
| commit | 018323ffc2c38669f594b8f7025a3440ae529d2a (patch) | |
| tree | 0852579792f5b3fe532e99333e5e46983ffb1402 | |
| parent | b28f668e267d6b463439e776c335f45508f5c1ad (diff) | |
| download | rust-018323ffc2c38669f594b8f7025a3440ae529d2a.tar.gz rust-018323ffc2c38669f594b8f7025a3440ae529d2a.zip | |
rustc: collapse the remains of Layout into Variants (enums vs everything else).
| -rw-r--r-- | src/librustc/ty/layout.rs | 186 | ||||
| -rw-r--r-- | src/librustc_lint/types.rs | 4 | ||||
| -rw-r--r-- | src/librustc_trans/cabi_x86_64.rs | 22 | ||||
| -rw-r--r-- | src/librustc_trans/debuginfo/metadata.rs | 98 | ||||
| -rw-r--r-- | src/librustc_trans/intrinsic.rs | 7 | ||||
| -rw-r--r-- | src/librustc_trans/mir/constant.rs | 41 | ||||
| -rw-r--r-- | src/librustc_trans/mir/lvalue.rs | 38 | ||||
| -rw-r--r-- | src/librustc_trans/mir/rvalue.rs | 9 | ||||
| -rw-r--r-- | src/librustc_trans/type_of.rs | 19 |
9 files changed, 188 insertions, 236 deletions
diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index dbad77b904e..bfde8a58e49 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -769,33 +769,17 @@ impl Abi { } } -/// Type layout, from which size and alignment can be cheaply computed. -/// For ADTs, it also includes field placement and enum optimizations. -/// NOTE: Because Layout is interned, redundant information should be -/// kept to a minimum, e.g. it includes no sub-component Ty or Layout. #[derive(PartialEq, Eq, Hash, Debug)] -pub enum Layout { - /// TyBool, TyChar, TyInt, TyUint, TyFloat, TyRawPtr, TyRef or TyFnPtr. - Scalar, - - /// SIMD vectors, from structs marked with #[repr(simd)]. - Vector, - - /// TyArray, TySlice or TyStr. - Array, - - // Remaining variants are all ADTs such as structs, enums or tuples. - - /// Single-case enums, and structs/tuples. - Univariant, - - /// Untagged unions. - UntaggedUnion, +pub enum Variants { + /// Single enum variants, structs/tuples, unions, and all non-ADTs. + Single { + index: usize + }, /// General-case enums: for each case there is a struct, and they all have /// all space reserved for the discriminant, and their first field starts /// at a non-0 offset, after where the discriminant would go. - General { + Tagged { discr: Primitive, /// Inclusive wrap-around range of discriminant values, that is, /// if min > max, it represents min..=u64::MAX followed by 0..=max. @@ -806,7 +790,7 @@ pub enum Layout { variants: Vec<CachedLayout>, }, - /// Two cases distinguished by a nullable pointer: the case with discriminant + /// Two cases distinguished by a niche: the case with discriminant /// `nndiscr` is represented by the struct `nonnull`, where field `0` /// is known to be nonnull due to its type; if that field is null, then /// it represents the other case, which is known to be zero sized. @@ -814,7 +798,7 @@ pub enum Layout { /// For example, `std::option::Option` instantiated at a safe pointer type /// is represented such that `None` is a null pointer and `Some` is the /// identity function. - NullablePointer { + NicheFilling { nndiscr: u64, discr: Primitive, variants: Vec<CachedLayout>, @@ -842,8 +826,7 @@ impl<'tcx> fmt::Display for LayoutError<'tcx> { #[derive(PartialEq, Eq, Hash, Debug)] pub struct CachedLayout { - pub variant_index: Option<usize>, - pub layout: Layout, + pub variants: Variants, pub fields: FieldPlacement, pub abi: Abi, pub align: Align, @@ -865,7 +848,7 @@ fn layout_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } tcx.layout_depth.set(depth+1); - let layout = Layout::compute_uncached(tcx, param_env, ty); + let layout = CachedLayout::compute_uncached(tcx, param_env, ty); tcx.layout_depth.set(depth); layout @@ -878,18 +861,17 @@ pub fn provide(providers: &mut ty::maps::Providers) { }; } -impl<'a, 'tcx> Layout { +impl<'a, 'tcx> CachedLayout { fn compute_uncached(tcx: TyCtxt<'a, 'tcx, 'tcx>, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>) - -> Result<&'tcx CachedLayout, LayoutError<'tcx>> { + -> Result<&'tcx Self, LayoutError<'tcx>> { let cx = (tcx, param_env); let dl = cx.data_layout(); let scalar = |value: Primitive| { let align = value.align(dl); tcx.intern_layout(CachedLayout { - variant_index: None, - layout: Layout::Scalar, + variants: Variants::Single { index: 0 }, fields: FieldPlacement::Union(0), abi: Abi::Scalar(value), size: value.size(dl), @@ -1028,8 +1010,7 @@ impl<'a, 'tcx> Layout { } Ok(CachedLayout { - variant_index: None, - layout: Layout::Univariant, + variants: Variants::Single { index: 0 }, fields: FieldPlacement::Arbitrary { offsets, memory_index @@ -1073,8 +1054,7 @@ impl<'a, 'tcx> Layout { memory_index: vec![0, 1] }; Ok(tcx.intern_layout(CachedLayout { - variant_index: None, - layout: Layout::Univariant, + variants: Variants::Single { index: 0 }, fields, abi: Abi::Aggregate { sized: true, @@ -1129,8 +1109,7 @@ impl<'a, 'tcx> Layout { .ok_or(LayoutError::SizeOverflow(ty))?; tcx.intern_layout(CachedLayout { - variant_index: None, - layout: Layout::Array, + variants: Variants::Single { index: 0 }, fields: FieldPlacement::Array { stride: element.size, count @@ -1147,8 +1126,7 @@ impl<'a, 'tcx> Layout { ty::TySlice(element) => { let element = cx.layout_of(element)?; tcx.intern_layout(CachedLayout { - variant_index: None, - layout: Layout::Array, + variants: Variants::Single { index: 0 }, fields: FieldPlacement::Array { stride: element.size, count: 0 @@ -1164,8 +1142,7 @@ impl<'a, 'tcx> Layout { } ty::TyStr => { tcx.intern_layout(CachedLayout { - variant_index: None, - layout: Layout::Array, + variants: Variants::Single { index: 0 }, fields: FieldPlacement::Array { stride: Size::from_bytes(1), count: 0 @@ -1238,8 +1215,7 @@ impl<'a, 'tcx> Layout { let size = size.abi_align(align); tcx.intern_layout(CachedLayout { - variant_index: None, - layout: Layout::Vector, + variants: Variants::Single { index: 0 }, fields: FieldPlacement::Array { stride: element.size, count @@ -1302,8 +1278,7 @@ impl<'a, 'tcx> Layout { } return Ok(tcx.intern_layout(CachedLayout { - variant_index: None, - layout: Layout::UntaggedUnion, + variants: Variants::Single { index: 0 }, fields: FieldPlacement::Union(variants[0].len()), abi: Abi::Aggregate { sized: true, @@ -1332,11 +1307,7 @@ impl<'a, 'tcx> Layout { else { StructKind::AlwaysSized } }; - let mut cached = univariant_uninterned(&variants[0], &def.repr, kind)?; - if def.is_enum() { - cached.variant_index = Some(0); - } - return Ok(tcx.intern_layout(cached)); + return univariant(&variants[0], &def.repr, kind); } let no_explicit_discriminants = def.variants.iter().enumerate() @@ -1359,8 +1330,9 @@ impl<'a, 'tcx> Layout { univariant_uninterned(&variants[1], &def.repr, StructKind::AlwaysSized)? ]; - st[0].variant_index = Some(0); - st[1].variant_index = Some(1); + for (i, v) in st.iter_mut().enumerate() { + v.variants = Variants::Single { index: i }; + } let offset = st[i].fields.offset(field_index) + offset; let CachedLayout { mut abi, @@ -1383,8 +1355,7 @@ impl<'a, 'tcx> Layout { primitive_align = primitive_align.max(discr_align); return Ok(tcx.intern_layout(CachedLayout { - variant_index: None, - layout: Layout::NullablePointer { + variants: Variants::NicheFilling { nndiscr: i as u64, discr, @@ -1426,7 +1397,7 @@ impl<'a, 'tcx> Layout { let mut variants = variants.into_iter().enumerate().map(|(i, field_layouts)| { let mut st = univariant_uninterned(&field_layouts, &def.repr, StructKind::EnumVariant(min_ity))?; - st.variant_index = Some(i); + st.variants = Variants::Single { index: i }; // Find the first field we can't move later // to make room for a larger discriminant. for field in st.fields.index_by_increasing_offset().map(|j| field_layouts[j]) { @@ -1506,8 +1477,7 @@ impl<'a, 'tcx> Layout { let discr = Int(ity, signed); tcx.intern_layout(CachedLayout { - variant_index: None, - layout: Layout::General { + variants: Variants::Tagged { discr, // FIXME: should be u128? @@ -1544,7 +1514,7 @@ impl<'a, 'tcx> Layout { return Err(LayoutError::Unknown(ty)); } ty::TyInfer(_) | ty::TyError => { - bug!("Layout::compute: unexpected type `{}`", ty) + bug!("CachedLayout::compute: unexpected type `{}`", ty) } }) } @@ -1650,8 +1620,8 @@ impl<'a, 'tcx> Layout { } }; - match layout.layout { - Layout::Univariant => { + match layout.variants { + Variants::Single { .. } => { let variant_names = || { adt_def.variants.iter().map(|v|format!("{}", v.name)).collect::<Vec<_>>() }; @@ -1675,8 +1645,8 @@ impl<'a, 'tcx> Layout { } } - Layout::NullablePointer { .. } | - Layout::General { .. } => { + Variants::NicheFilling { .. } | + Variants::Tagged { .. } => { debug!("print-type-size `{:#?}` adt general variants def {}", ty, adt_def.variants.len()); let variant_infos: Vec<_> = @@ -1688,27 +1658,11 @@ impl<'a, 'tcx> Layout { layout.for_variant(i)) }) .collect(); - record(adt_kind.into(), match layout.layout { - Layout::General { discr, .. } => Some(discr.size(tcx)), + record(adt_kind.into(), match layout.variants { + Variants::Tagged { discr, .. } => Some(discr.size(tcx)), _ => None }, variant_infos); } - - Layout::UntaggedUnion => { - debug!("print-type-size t: `{:?}` adt union", ty); - // layout does not currently store info about each - // variant... - record(adt_kind.into(), None, Vec::new()); - } - - // other cases provide little interesting (i.e. adjustable - // via representation tweaks) size info beyond total size. - Layout::Scalar | - Layout::Vector | - Layout::Array => { - debug!("print-type-size t: `{:?}` adt other", ty); - record(adt_kind.into(), None, Vec::new()) - } } } } @@ -1950,7 +1904,7 @@ 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, layout); + CachedLayout::record_layout_for_printing(tcx, ty, param_env, layout); Ok(layout) } @@ -1979,7 +1933,7 @@ 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, layout); + CachedLayout::record_layout_for_printing(tcx_at.tcx, ty, param_env, layout); Ok(layout) } @@ -1987,15 +1941,15 @@ impl<'a, 'tcx> LayoutOf<Ty<'tcx>> for (ty::maps::TyCtxtAt<'a, 'tcx, 'tcx>, impl<'a, 'tcx> TyLayout<'tcx> { pub fn for_variant(&self, variant_index: usize) -> Self { - let cached = match self.layout { - Layout::NullablePointer { ref variants, .. } | - Layout::General { ref variants, .. } => { + let cached = match self.variants { + Variants::Single { .. } => self.cached, + + Variants::NicheFilling { ref variants, .. } | + Variants::Tagged { ref variants, .. } => { &variants[variant_index] } - - _ => self.cached }; - assert_eq!(cached.variant_index, Some(variant_index)); + assert_eq!(cached.variants, Variants::Single { index: variant_index }); TyLayout { ty: self.ty, @@ -2081,26 +2035,17 @@ impl<'a, 'tcx> TyLayout<'tcx> { // ADTs. ty::TyAdt(def, substs) => { - let v = if def.is_enum() { - match self.variant_index { - None => match self.layout { - // Discriminant field for enums (where applicable). - Layout::General { discr, .. } | - Layout::NullablePointer { discr, .. } => { - return cx.layout_of([discr.to_ty(tcx)][i]); - } - _ => { - bug!("TyLayout::field_type: enum `{}` has no discriminant", - self.ty) - } - }, - Some(v) => v + match self.variants { + Variants::Single { index } => { + def.variants[index].fields[i].ty(tcx, substs) } - } else { - 0 - }; - def.variants[v].fields[i].ty(tcx, substs) + // Discriminant field for enums (where applicable). + Variants::Tagged { discr, .. } | + Variants::NicheFilling { discr, .. } => { + return cx.layout_of([discr.to_ty(tcx)][i]); + } + } } ty::TyProjection(_) | ty::TyAnon(..) | ty::TyParam(_) | @@ -2143,18 +2088,18 @@ impl<'a, 'tcx> TyLayout<'tcx> { HasTyCtxt<'tcx> { let tcx = cx.tcx(); - match (&self.layout, self.abi, &self.ty.sty) { + match (&self.variants, self.abi, &self.ty.sty) { // FIXME(eddyb) check this via value ranges on scalars. - (&Layout::Scalar, Abi::Scalar(Pointer), &ty::TyRef(..)) | - (&Layout::Scalar, Abi::Scalar(Pointer), &ty::TyFnPtr(..)) => { + (_, Abi::Scalar(Pointer), &ty::TyRef(..)) | + (_, Abi::Scalar(Pointer), &ty::TyFnPtr(..)) => { Ok(Some((Size::from_bytes(0), Pointer))) } - (&Layout::Scalar, Abi::Scalar(Pointer), &ty::TyAdt(def, _)) if def.is_box() => { + (_, Abi::Scalar(Pointer), &ty::TyAdt(def, _)) if def.is_box() => { Ok(Some((Size::from_bytes(0), Pointer))) } // FIXME(eddyb) check this via value ranges on scalars. - (&Layout::General { discr, .. }, _, &ty::TyAdt(def, _)) => { + (&Variants::Tagged { discr, .. }, _, &ty::TyAdt(def, _)) => { if def.discriminants(tcx).all(|d| d.to_u128_unchecked() != 0) { Ok(Some((self.fields.offset(0), discr))) } else { @@ -2196,20 +2141,18 @@ impl<'a, 'tcx> TyLayout<'tcx> { } } -impl<'gcx> HashStable<StableHashingContext<'gcx>> for Layout { +impl<'gcx> HashStable<StableHashingContext<'gcx>> for Variants { fn hash_stable<W: StableHasherResult>(&self, hcx: &mut StableHashingContext<'gcx>, hasher: &mut StableHasher<W>) { - use ty::layout::Layout::*; + use ty::layout::Variants::*; mem::discriminant(self).hash_stable(hcx, hasher); match *self { - Scalar => {} - Vector => {} - Array => {} - Univariant => {} - UntaggedUnion => {} - General { + Single { index } => { + index.hash_stable(hcx, hasher); + } + Tagged { discr, discr_range: RangeInclusive { start, end }, ref variants, @@ -2219,7 +2162,7 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for Layout { end.hash_stable(hcx, hasher); variants.hash_stable(hcx, hasher); } - NullablePointer { + NicheFilling { nndiscr, ref variants, ref discr, @@ -2279,8 +2222,7 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for Abi { } impl_stable_hash_for!(struct ::ty::layout::CachedLayout { - variant_index, - layout, + variants, fields, abi, size, diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs index 761ca662178..46debcce958 100644 --- a/src/librustc_lint/types.rs +++ b/src/librustc_lint/types.rs @@ -13,7 +13,7 @@ use rustc::hir::def_id::DefId; use rustc::ty::subst::Substs; use rustc::ty::{self, AdtKind, Ty, TyCtxt}; -use rustc::ty::layout::{Layout, LayoutOf}; +use rustc::ty::layout::{self, LayoutOf}; use middle::const_val::ConstVal; use rustc_const_eval::ConstContext; use util::nodemap::FxHashSet; @@ -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, discr, .. } = layout.layout { + if let layout::Variants::Tagged { ref variants, discr, .. } = layout.variants { let discr_size = discr.size(cx.tcx).bytes(); debug!("enum `{}` is {} bytes large with layout:\n{:#?}", diff --git a/src/librustc_trans/cabi_x86_64.rs b/src/librustc_trans/cabi_x86_64.rs index 36ac76aaaa5..d5a51fa1863 100644 --- a/src/librustc_trans/cabi_x86_64.rs +++ b/src/librustc_trans/cabi_x86_64.rs @@ -14,7 +14,7 @@ use abi::{ArgType, ArgAttribute, CastTarget, FnType, LayoutExt, Reg, RegKind}; use context::CrateContext; -use rustc::ty::layout::{self, Layout, TyLayout, Size}; +use rustc::ty::layout::{self, TyLayout, Size}; #[derive(Clone, Copy, PartialEq, Debug)] enum Class { @@ -87,17 +87,15 @@ fn classify_arg<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, arg: &ArgType<'tcx>) } 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.layout { - Layout::General { .. } | - Layout::NullablePointer { .. } => return Err(Memory), - _ => {} - } - for i in 0..layout.fields.count() { - let field_off = off + layout.fields.offset(i); - classify(ccx, layout.field(ccx, i), cls, field_off)?; + match layout.variants { + layout::Variants::Single { .. } => { + for i in 0..layout.fields.count() { + let field_off = off + layout.fields.offset(i); + classify(ccx, layout.field(ccx, i), cls, field_off)?; + } + } + layout::Variants::Tagged { .. } | + layout::Variants::NicheFilling { .. } => return Err(Memory), } } diff --git a/src/librustc_trans/debuginfo/metadata.rs b/src/librustc_trans/debuginfo/metadata.rs index 6a7b35c05e7..a905d35f3d3 100644 --- a/src/librustc_trans/debuginfo/metadata.rs +++ b/src/librustc_trans/debuginfo/metadata.rs @@ -1119,7 +1119,7 @@ fn prepare_union_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, // offset of zero bytes). struct EnumMemberDescriptionFactory<'tcx> { enum_type: Ty<'tcx>, - type_rep: TyLayout<'tcx>, + layout: TyLayout<'tcx>, discriminant_type_metadata: Option<DIType>, containing_scope: DIScope, span: Span, @@ -1129,37 +1129,8 @@ impl<'tcx> EnumMemberDescriptionFactory<'tcx> { fn create_member_descriptions<'a>(&self, cx: &CrateContext<'a, 'tcx>) -> Vec<MemberDescription> { let adt = &self.enum_type.ty_adt_def().unwrap(); - match self.type_rep.layout { - layout::Layout::General { ref variants, .. } => { - let discriminant_info = RegularDiscriminant(self.discriminant_type_metadata - .expect("")); - (0..variants.len()).map(|i| { - let variant = self.type_rep.for_variant(i); - let (variant_type_metadata, member_desc_factory) = - describe_enum_variant(cx, - variant, - &adt.variants[i], - discriminant_info, - self.containing_scope, - self.span); - - let member_descriptions = member_desc_factory - .create_member_descriptions(cx); - - set_members_of_composite_type(cx, - variant_type_metadata, - &member_descriptions); - MemberDescription { - name: "".to_string(), - type_metadata: variant_type_metadata, - offset: Size::from_bytes(0), - size: variant.size, - align: variant.align, - flags: DIFlags::FlagZero - } - }).collect() - }, - layout::Layout::Univariant => { + match self.layout.variants { + layout::Variants::Single { .. } => { assert!(adt.variants.len() <= 1); if adt.variants.is_empty() { @@ -1167,7 +1138,7 @@ impl<'tcx> EnumMemberDescriptionFactory<'tcx> { } else { let (variant_type_metadata, member_description_factory) = describe_enum_variant(cx, - self.type_rep, + self.layout, &adt.variants[0], NoDiscriminant, self.containing_scope, @@ -1184,19 +1155,48 @@ impl<'tcx> EnumMemberDescriptionFactory<'tcx> { name: "".to_string(), type_metadata: variant_type_metadata, offset: Size::from_bytes(0), - size: self.type_rep.size, - align: self.type_rep.align, + size: self.layout.size, + align: self.layout.align, flags: DIFlags::FlagZero } ] } } - layout::Layout::NullablePointer { + layout::Variants::Tagged { ref variants, .. } => { + let discriminant_info = RegularDiscriminant(self.discriminant_type_metadata + .expect("")); + (0..variants.len()).map(|i| { + let variant = self.layout.for_variant(i); + let (variant_type_metadata, member_desc_factory) = + describe_enum_variant(cx, + variant, + &adt.variants[i], + discriminant_info, + self.containing_scope, + self.span); + + let member_descriptions = member_desc_factory + .create_member_descriptions(cx); + + set_members_of_composite_type(cx, + variant_type_metadata, + &member_descriptions); + MemberDescription { + name: "".to_string(), + type_metadata: variant_type_metadata, + offset: Size::from_bytes(0), + size: variant.size, + align: variant.align, + flags: DIFlags::FlagZero + } + }).collect() + } + layout::Variants::NicheFilling { nndiscr, discr, .. } => { - let variant = self.type_rep.for_variant(nndiscr as usize); + let variant = self.layout.for_variant(nndiscr as usize); // Create a description of the non-null variant let (variant_type_metadata, member_description_factory) = describe_enum_variant(cx, @@ -1237,8 +1237,8 @@ impl<'tcx> EnumMemberDescriptionFactory<'tcx> { } } compute_field_path(cx, &mut name, - self.type_rep, - self.type_rep.fields.offset(0), + self.layout, + self.layout.fields.offset(0), discr.size(cx)); name.push_str(&adt.variants[(1 - nndiscr) as usize].name.as_str()); @@ -1253,8 +1253,7 @@ impl<'tcx> EnumMemberDescriptionFactory<'tcx> { flags: DIFlags::FlagZero } ] - }, - ref l @ _ => bug!("Not an enum layout: {:#?}", l) + } } } } @@ -1429,21 +1428,20 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, } }; - let type_rep = cx.layout_of(enum_type); + let layout = cx.layout_of(enum_type); - let discriminant_type_metadata = match type_rep.layout { - layout::Layout::NullablePointer { .. } | - layout::Layout::Univariant { .. } => None, - layout::Layout::General { discr, .. } => Some(discriminant_type_metadata(discr)), - ref l @ _ => bug!("Not an enum layout: {:#?}", l) + let discriminant_type_metadata = match layout.variants { + layout::Variants::Single { .. } | + layout::Variants::NicheFilling { .. } => None, + layout::Variants::Tagged { discr, .. } => Some(discriminant_type_metadata(discr)), }; - match (type_rep.abi, discriminant_type_metadata) { + match (layout.abi, discriminant_type_metadata) { (layout::Abi::Scalar(_), Some(discr)) => return FinalMetadata(discr), _ => {} } - let (enum_type_size, enum_type_align) = type_rep.size_and_align(); + let (enum_type_size, enum_type_align) = layout.size_and_align(); let enum_name = CString::new(enum_name).unwrap(); let unique_type_id_str = CString::new( @@ -1471,7 +1469,7 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, enum_metadata, EnumMDF(EnumMemberDescriptionFactory { enum_type, - type_rep, + layout, discriminant_type_metadata, containing_scope, span, diff --git a/src/librustc_trans/intrinsic.rs b/src/librustc_trans/intrinsic.rs index 45d2f7c69e9..d982fa192b3 100644 --- a/src/librustc_trans/intrinsic.rs +++ b/src/librustc_trans/intrinsic.rs @@ -394,12 +394,7 @@ pub fn trans_intrinsic_call<'a, 'tcx>(bcx: &Builder<'a, 'tcx>, }, "discriminant_value" => { - match substs.type_at(0).sty { - ty::TyAdt(adt, ..) if adt.is_enum() => { - args[0].deref(bcx.ccx).trans_get_discr(bcx, ret_ty) - } - _ => C_null(llret_ty) - } + args[0].deref(bcx.ccx).trans_get_discr(bcx, ret_ty) } "align_offset" => { diff --git a/src/librustc_trans/mir/constant.rs b/src/librustc_trans/mir/constant.rs index 45037a1f198..5a2dcf4fb18 100644 --- a/src/librustc_trans/mir/constant.rs +++ b/src/librustc_trans/mir/constant.rs @@ -1094,8 +1094,26 @@ fn trans_const_adt<'a, 'tcx>( mir::AggregateKind::Adt(_, index, _, _) => index, _ => 0, }; - match l.layout { - layout::Layout::General { .. } => { + match l.variants { + layout::Variants::Single { index } => { + assert_eq!(variant_index, index); + if let layout::Abi::Vector { .. } = l.abi { + Const::new(C_vector(&vals.iter().map(|x| x.llval).collect::<Vec<_>>()), t) + } else if let layout::FieldPlacement::Union(_) = l.fields { + assert_eq!(variant_index, 0); + assert_eq!(vals.len(), 1); + let contents = [ + vals[0].llval, + padding(ccx, l.size - ccx.size_of(vals[0].ty)) + ]; + + Const::new(C_struct(ccx, &contents, l.is_packed()), t) + } else { + assert_eq!(variant_index, 0); + build_const_struct(ccx, l, vals, None) + } + } + layout::Variants::Tagged { .. } => { let discr = match *kind { mir::AggregateKind::Adt(adt_def, _, _, _) => { adt_def.discriminant_for_variant(ccx.tcx(), variant_index) @@ -1112,23 +1130,7 @@ fn trans_const_adt<'a, 'tcx>( build_const_struct(ccx, l.for_variant(variant_index), vals, Some(discr)) } } - layout::Layout::UntaggedUnion => { - assert_eq!(variant_index, 0); - let contents = [ - vals[0].llval, - padding(ccx, l.size - ccx.size_of(vals[0].ty)) - ]; - - Const::new(C_struct(ccx, &contents, l.is_packed()), t) - } - layout::Layout::Univariant => { - assert_eq!(variant_index, 0); - build_const_struct(ccx, l, vals, None) - } - layout::Layout::Vector => { - Const::new(C_vector(&vals.iter().map(|x| x.llval).collect::<Vec<_>>()), t) - } - layout::Layout::NullablePointer { nndiscr, .. } => { + layout::Variants::NicheFilling { nndiscr, .. } => { if variant_index as u64 == nndiscr { build_const_struct(ccx, l.for_variant(variant_index), vals, None) } else { @@ -1137,7 +1139,6 @@ fn trans_const_adt<'a, 'tcx>( Const::new(C_null(ccx.layout_of(t).llvm_type(ccx)), t) } } - _ => bug!("trans_const_adt: cannot handle type {} repreented as {:#?}", t, l) } } diff --git a/src/librustc_trans/mir/lvalue.rs b/src/librustc_trans/mir/lvalue.rs index f10791cae52..5a558e3652b 100644 --- a/src/librustc_trans/mir/lvalue.rs +++ b/src/librustc_trans/mir/lvalue.rs @@ -296,10 +296,13 @@ impl<'a, 'tcx> LvalueRef<'tcx> { /// Obtain the actual discriminant of a value. pub fn trans_get_discr(self, bcx: &Builder<'a, 'tcx>, cast_to: Ty<'tcx>) -> ValueRef { let cast_to = bcx.ccx.layout_of(cast_to).immediate_llvm_type(bcx.ccx); - match self.layout.layout { - layout::Layout::Univariant { .. } | - layout::Layout::UntaggedUnion { .. } => return C_uint(cast_to, 0), - _ => {} + match self.layout.variants { + layout::Variants::Single { index } => { + assert_eq!(index, 0); + return C_uint(cast_to, 0); + } + layout::Variants::Tagged { .. } | + layout::Variants::NicheFilling { .. } => {}, } let discr = self.project_field(bcx, 0); @@ -307,8 +310,10 @@ impl<'a, 'tcx> LvalueRef<'tcx> { layout::Abi::Scalar(discr) => discr, _ => bug!("discriminant not scalar: {:#?}", discr.layout) }; - let (min, max) = match self.layout.layout { - layout::Layout::General { ref discr_range, .. } => (discr_range.start, discr_range.end), + let (min, max) = match self.layout.variants { + layout::Variants::Tagged { ref discr_range, .. } => { + (discr_range.start, discr_range.end) + } _ => (0, u64::max_value()), }; let max_next = max.wrapping_add(1); @@ -333,20 +338,20 @@ impl<'a, 'tcx> LvalueRef<'tcx> { bcx.load(discr.llval, discr.alignment.non_abi()) } }; - match self.layout.layout { - layout::Layout::General { .. } => { + match self.layout.variants { + layout::Variants::Single { .. } => bug!(), + layout::Variants::Tagged { .. } => { let signed = match discr_scalar { layout::Int(_, signed) => signed, _ => false }; bcx.intcast(lldiscr, cast_to, signed) } - layout::Layout::NullablePointer { nndiscr, .. } => { + layout::Variants::NicheFilling { nndiscr, .. } => { let cmp = if nndiscr == 0 { llvm::IntEQ } else { llvm::IntNE }; let zero = C_null(discr.layout.llvm_type(bcx.ccx)); bcx.intcast(bcx.icmp(cmp, lldiscr, zero), cast_to, false) } - _ => bug!("{} is not an enum", self.layout.ty) } } @@ -356,13 +361,17 @@ impl<'a, 'tcx> LvalueRef<'tcx> { let to = self.layout.ty.ty_adt_def().unwrap() .discriminant_for_variant(bcx.tcx(), variant_index) .to_u128_unchecked() as u64; - match self.layout.layout { - layout::Layout::General { .. } => { + match self.layout.variants { + layout::Variants::Single { index } => { + assert_eq!(to, 0); + assert_eq!(variant_index, index); + } + layout::Variants::Tagged { .. } => { let ptr = self.project_field(bcx, 0); bcx.store(C_int(ptr.layout.llvm_type(bcx.ccx), to as i64), ptr.llval, ptr.alignment.non_abi()); } - layout::Layout::NullablePointer { nndiscr, .. } => { + layout::Variants::NicheFilling { nndiscr, .. } => { if to != nndiscr { let use_memset = match self.layout.abi { layout::Abi::Scalar(_) => false, @@ -385,9 +394,6 @@ impl<'a, 'tcx> LvalueRef<'tcx> { } } } - _ => { - assert_eq!(to, 0); - } } } diff --git a/src/librustc_trans/mir/rvalue.rs b/src/librustc_trans/mir/rvalue.rs index 0d183115211..d3677e2eefd 100644 --- a/src/librustc_trans/mir/rvalue.rs +++ b/src/librustc_trans/mir/rvalue.rs @@ -11,7 +11,7 @@ use llvm::{self, ValueRef}; use rustc::ty::{self, Ty}; use rustc::ty::cast::{CastTy, IntTy}; -use rustc::ty::layout::{self, Layout, LayoutOf}; +use rustc::ty::layout::{self, LayoutOf}; use rustc::mir; use rustc::middle::lang_items::ExchangeMallocFnLangItem; use rustc_apfloat::{ieee, Float, Status, Round}; @@ -278,8 +278,10 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> { let ll_t_out = cast.immediate_llvm_type(bcx.ccx); let llval = operand.immediate(); - if let Layout::General { ref discr_range, .. } = operand.layout.layout { - if discr_range.end > discr_range.start { + match operand.layout.variants { + layout::Variants::Tagged { + ref discr_range, .. + } if discr_range.end > discr_range.start => { // We want `table[e as usize]` to not // have bound checks, and this is the most // convenient place to put the `assume`. @@ -290,6 +292,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> { C_uint(ll_t_in, discr_range.end) )); } + _ => {} } let signed = match operand.layout.abi { diff --git a/src/librustc_trans/type_of.rs b/src/librustc_trans/type_of.rs index 52151035a82..2b3ac0386ee 100644 --- a/src/librustc_trans/type_of.rs +++ b/src/librustc_trans/type_of.rs @@ -40,8 +40,13 @@ fn uncached_llvm_type<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, let mut name = String::with_capacity(32); let printer = DefPathBasedNames::new(ccx.tcx(), true, true); printer.push_type_name(layout.ty, &mut name); - if let (&ty::TyAdt(def, _), Some(v)) = (&layout.ty.sty, layout.variant_index) { - write!(&mut name, "::{}", def.variants[v].name).unwrap(); + match (&layout.ty.sty, &layout.variants) { + (&ty::TyAdt(def, _), &layout::Variants::Single { index }) => { + if def.is_enum() && !def.variants.is_empty() { + write!(&mut name, "::{}", def.variants[index].name).unwrap(); + } + } + _ => {} } Some(name) } @@ -206,7 +211,11 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyLayout<'tcx> { // Check the cache. - if let Some(&llty) = ccx.lltypes().borrow().get(&(self.ty, self.variant_index)) { + let variant_index = match self.variants { + layout::Variants::Single { index } => Some(index), + _ => None + }; + if let Some(&llty) = ccx.lltypes().borrow().get(&(self.ty, variant_index)) { return llty; } @@ -221,7 +230,7 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyLayout<'tcx> { let mut defer = None; let llty = if self.ty != normal_ty { let mut layout = ccx.layout_of(normal_ty); - if let Some(v) = self.variant_index { + if let Some(v) = variant_index { layout = layout.for_variant(v); } layout.llvm_type(ccx) @@ -230,7 +239,7 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyLayout<'tcx> { }; debug!("--> mapped {:#?} to llty={:?}", self, llty); - ccx.lltypes().borrow_mut().insert((self.ty, self.variant_index), llty); + ccx.lltypes().borrow_mut().insert((self.ty, variant_index), llty); if let Some((mut llty, layout)) = defer { llty.set_struct_body(&struct_llfields(ccx, layout), layout.is_packed()) |
