diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index c16092666f7..319d4789efa 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -619,10 +619,6 @@ impl Primitive { } } -/// Path through fields of nested structures. -// FIXME(eddyb) use small vector optimization for the common case. -pub type FieldPath = Vec; - /// A structure, a product type in ADT terms. #[derive(PartialEq, Eq, Hash, Debug)] pub struct Struct { @@ -848,20 +844,19 @@ impl<'a, 'tcx> Struct { fn non_zero_field_in_type(tcx: TyCtxt<'a, 'tcx, 'tcx>, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>) - -> Result, LayoutError<'tcx>> { + -> Result, LayoutError<'tcx>> { let layout = ty.layout(tcx, param_env)?; match (layout, &ty.sty) { (&Scalar { non_zero: true, value, .. }, _) => { - Ok(Some((Size::from_bytes(0), value, vec![]))) + Ok(Some((Size::from_bytes(0), value))) } (&CEnum { non_zero: true, discr, .. }, _) => { - Ok(Some((Size::from_bytes(0), Int(discr), vec![]))) + Ok(Some((Size::from_bytes(0), Int(discr)))) } (&FatPointer { non_zero: true, .. }, _) => { Ok(Some((layout.field_offset(tcx, FAT_PTR_ADDR, None), - Pointer, - vec![FAT_PTR_ADDR as u32]))) + Pointer))) } // Is this the NonZero lang item wrapping a pointer or integer type? @@ -873,15 +868,12 @@ impl<'a, 'tcx> Struct { // FIXME(eddyb) also allow floating-point types here. Scalar { value: value @ Int(_), non_zero: false } | Scalar { value: value @ Pointer, non_zero: false } => { - Ok(Some((layout.field_offset(tcx, 0, None), - value, - vec![0]))) + Ok(Some((layout.field_offset(tcx, 0, None), value))) } FatPointer { non_zero: false, .. } => { Ok(Some((layout.field_offset(tcx, 0, None) + field.field_offset(tcx, FAT_PTR_ADDR, None), - Pointer, - vec![FAT_PTR_ADDR as u32, 0]))) + Pointer))) } _ => Ok(None) } @@ -890,31 +882,22 @@ impl<'a, 'tcx> Struct { // Perhaps one of the fields of this struct is non-zero // let's recurse and find out (&Univariant { ref variant, .. }, &ty::TyAdt(def, substs)) if def.is_struct() => { - Struct::non_zero_field( + variant.non_zero_field( tcx, param_env, def.struct_variant().fields.iter().map(|field| { field.ty(tcx, substs) - }), - &variant.offsets) + })) } // Perhaps one of the upvars of this closure is non-zero (&Univariant { ref variant, .. }, &ty::TyClosure(def, substs)) => { let upvar_tys = substs.upvar_tys(def, tcx); - Struct::non_zero_field( - tcx, - param_env, - upvar_tys, - &variant.offsets) + variant.non_zero_field(tcx, param_env, upvar_tys) } // Can we use one of the fields in this tuple? (&Univariant { ref variant, .. }, &ty::TyTuple(tys, _)) => { - Struct::non_zero_field( - tcx, - param_env, - tys.iter().cloned(), - &variant.offsets) + variant.non_zero_field(tcx, param_env, tys.iter().cloned()) } // Is this a fixed-size array of something non-zero @@ -927,11 +910,7 @@ impl<'a, 'tcx> Struct { } } if count.val.to_const_int().unwrap().to_u64().unwrap() != 0 { - Struct::non_zero_field( - tcx, - param_env, - Some(ety).into_iter(), - &[Size::from_bytes(0)]) + Struct::non_zero_field_in_type(tcx, param_env, ety) } else { Ok(None) } @@ -953,17 +932,15 @@ impl<'a, 'tcx> Struct { /// Find the offset of a non-zero leaf field, starting from /// the given set of fields and recursing through aggregates. /// Returns Some((offset, primitive, source_path)) on success. - fn non_zero_field(tcx: TyCtxt<'a, 'tcx, 'tcx>, + fn non_zero_field(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, param_env: ty::ParamEnv<'tcx>, - fields: I, - offsets: &[Size]) - -> Result, LayoutError<'tcx>> + fields: I) + -> Result, LayoutError<'tcx>> where I: Iterator> { - for (i, ty) in fields.enumerate() { + for (ty, &field_offset) in fields.zip(&self.offsets) { let r = Struct::non_zero_field_in_type(tcx, param_env, ty)?; - if let Some((offset, primitive, mut source_path)) = r { - source_path.push(i as u32); - return Ok(Some((offsets[i] + offset, primitive, source_path))); + if let Some((offset, primitive)) = r { + return Ok(Some((field_offset + offset, primitive))); } } Ok(None) @@ -1152,8 +1129,6 @@ pub enum Layout { nonnull: Struct, discr: Primitive, discr_offset: Size, - /// Like discr_offset, but the source field path. For debuginfo. - discrfield_source: FieldPath } } @@ -1452,11 +1427,9 @@ impl<'a, 'tcx> Layout { .collect::, _>>()?, &def.repr, StructKind::AlwaysSizedUnivariant, ty)?; - let field = Struct::non_zero_field(tcx, - param_env, - variants[discr].iter().cloned(), - &st.offsets)?; - let (offset, primitive, mut path_source) = if let Some(f) = field { f } + let field = st.non_zero_field(tcx, param_env, + variants[discr].iter().cloned())?; + let (offset, primitive) = if let Some(f) = field { f } else { continue }; // FIXME(eddyb) should take advantage of a newtype. @@ -1468,15 +1441,11 @@ impl<'a, 'tcx> Layout { }); } - // We have to fix the source path here. - path_source.reverse(); - return success(StructWrappedNullablePointer { nndiscr: discr as u64, nonnull: st, discr: primitive, discr_offset: offset, - discrfield_source: path_source }); } } @@ -1875,8 +1844,7 @@ impl<'a, 'tcx> Layout { Layout::StructWrappedNullablePointer { nonnull: ref variant_layout, nndiscr, discr: _, - discr_offset: _, - discrfield_source: _ } => { + discr_offset: _ } => { debug!("print-type-size t: `{:?}` adt struct-wrapped nullable nndiscr {} is {:?}", ty, nndiscr, variant_layout); let variant_def = &adt_def.variants[nndiscr as usize]; @@ -2418,13 +2386,11 @@ impl<'gcx> HashStable> for Layout ref nonnull, ref discr, discr_offset, - ref discrfield_source } => { nndiscr.hash_stable(hcx, hasher); nonnull.hash_stable(hcx, hasher); discr.hash_stable(hcx, hasher); discr_offset.hash_stable(hcx, hasher); - discrfield_source.hash_stable(hcx, hasher); } } } diff --git a/src/librustc_trans/debuginfo/metadata.rs b/src/librustc_trans/debuginfo/metadata.rs index 82c975c751f..98402b5e8c5 100644 --- a/src/librustc_trans/debuginfo/metadata.rs +++ b/src/librustc_trans/debuginfo/metadata.rs @@ -39,6 +39,7 @@ use rustc::util::common::path2cstr; use libc::{c_uint, c_longlong}; use std::ffi::CString; +use std::fmt::Write; use std::ptr; use std::path::Path; use syntax::ast; @@ -1286,9 +1287,12 @@ impl<'tcx> EnumMemberDescriptionFactory<'tcx> { } ] }, - layout::StructWrappedNullablePointer { nonnull: ref struct_def, - nndiscr, - ref discrfield_source, ..} => { + layout::StructWrappedNullablePointer { + nonnull: ref struct_def, + nndiscr, + discr, + discr_offset + } => { // Create a description of the non-null variant let (variant_type_metadata, member_description_factory) = describe_enum_variant(cx, @@ -1309,19 +1313,37 @@ impl<'tcx> EnumMemberDescriptionFactory<'tcx> { // Encode the information about the null variant in the union // member's name. - let null_variant_index = (1 - nndiscr) as usize; - let null_variant_name = adt.variants[null_variant_index].name; - let discrfield_source = discrfield_source.iter() - .map(|x| x.to_string()) - .collect::>().join("$"); - let union_member_name = format!("RUST$ENCODED$ENUM${}${}", - discrfield_source, - null_variant_name); + let mut name = String::from("RUST$ENCODED$ENUM$"); + // HACK(eddyb) the debuggers should just handle offset+size + // of discriminant instead of us having to recover its path. + fn compute_field_path<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, + name: &mut String, + layout: TyLayout<'tcx>, + offset: Size, + size: Size) { + for i in 0..layout.field_count() { + let field_offset = layout.field_offset(ccx, i); + if field_offset > offset { + continue; + } + let inner_offset = offset - field_offset; + let field = layout.field(ccx, i); + if inner_offset + size <= field.size(ccx) { + write!(name, "{}$", i).unwrap(); + compute_field_path(ccx, name, field, inner_offset, size); + } + } + } + compute_field_path(cx, &mut name, + self.type_rep, + discr_offset, + discr.size(cx)); + name.push_str(&adt.variants[(1 - nndiscr) as usize].name.as_str()); // Create the (singleton) list of descriptions of union members. vec![ MemberDescription { - name: union_member_name, + name, type_metadata: variant_type_metadata, offset: Size::from_bytes(0), size: struct_def.stride(),