diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index 8021fc3ba15..7a8a34788d2 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -717,16 +717,18 @@ impl<'a, 'gcx, 'tcx> Struct { /// Find the path leading to a non-zero leaf field, starting from /// the given type and recursing through aggregates. + /// The tuple is `(path, source_path)1, + /// where `path` is in memory order and `source_path` in source order. // FIXME(eddyb) track value ranges and traverse already optimized enums. fn non_zero_field_in_type(infcx: &InferCtxt<'a, 'gcx, 'tcx>, ty: Ty<'gcx>) - -> Result, LayoutError<'gcx>> { + -> Result, LayoutError<'gcx>> { let tcx = infcx.tcx.global_tcx(); match (ty.layout(infcx)?, &ty.sty) { (&Scalar { non_zero: true, .. }, _) | - (&CEnum { non_zero: true, .. }, _) => Ok(Some(vec![])), + (&CEnum { non_zero: true, .. }, _) => Ok(Some((vec![], vec![]))), (&FatPointer { non_zero: true, .. }, _) => { - Ok(Some(vec![FAT_PTR_ADDR as u32])) + Ok(Some((vec![FAT_PTR_ADDR as u32], vec![FAT_PTR_ADDR as u32]))) } // Is this the NonZero lang item wrapping a pointer or integer type? @@ -737,10 +739,11 @@ impl<'a, 'gcx, 'tcx> Struct { // FIXME(eddyb) also allow floating-point types here. Scalar { value: Int(_), non_zero: false } | Scalar { value: Pointer, non_zero: false } => { - Ok(Some(vec![0])) + Ok(Some((vec![0], vec![0]))) } FatPointer { non_zero: false, .. } => { - Ok(Some(vec![FAT_PTR_ADDR as u32, 0])) + let tmp = vec![FAT_PTR_ADDR as u32, 0]; + Ok(Some((tmp.clone(), tmp))) } _ => Ok(None) } @@ -749,7 +752,7 @@ impl<'a, 'gcx, '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_path(infcx, def.struct_variant().fields + Struct::non_zero_field_paths(infcx, def.struct_variant().fields .iter().map(|field| { field.ty(tcx, substs) }), @@ -759,19 +762,19 @@ impl<'a, 'gcx, 'tcx> Struct { // 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_path(infcx, upvar_tys, + Struct::non_zero_field_paths(infcx, upvar_tys, Some(&variant.memory_index[..])) } // Can we use one of the fields in this tuple? (&Univariant { ref variant, .. }, &ty::TyTuple(tys)) => { - Struct::non_zero_field_path(infcx, tys.iter().cloned(), + Struct::non_zero_field_paths(infcx, tys.iter().cloned(), Some(&variant.memory_index[..])) } // Is this a fixed-size array of something non-zero // with at least one element? (_, &ty::TyArray(ety, d)) if d > 0 => { - Struct::non_zero_field_path(infcx, Some(ety).into_iter(), None) + Struct::non_zero_field_paths(infcx, Some(ety).into_iter(), None) } (_, &ty::TyProjection(_)) | (_, &ty::TyAnon(..)) => { @@ -789,20 +792,23 @@ impl<'a, 'gcx, 'tcx> Struct { /// Find the path leading to a non-zero leaf field, starting from /// the given set of fields and recursing through aggregates. - fn non_zero_field_path(infcx: &InferCtxt<'a, 'gcx, 'tcx>, + // / Returns Some((path, source_path)) on success. + /// `path` is translated to memory order. `source_path` is not. + fn non_zero_field_paths(infcx: &InferCtxt<'a, 'gcx, 'tcx>, fields: I, permutation: Option<&[u32]>) - -> Result, LayoutError<'gcx>> + -> Result, LayoutError<'gcx>> where I: Iterator> { for (i, ty) in fields.enumerate() { - if let Some(mut path) = Struct::non_zero_field_in_type(infcx, ty)? { + if let Some((mut path, mut source_path)) = Struct::non_zero_field_in_type(infcx, ty)? { + source_path.push(i as u32); let index = if let Some(p) = permutation { p[i] as usize } else { i }; path.push(index as u32); - return Ok(Some(path)); + return Ok(Some((path, source_path))); } } Ok(None) @@ -965,7 +971,9 @@ pub enum Layout { nndiscr: u64, nonnull: Struct, // N.B. There is a 0 at the start, for LLVM GEP through a pointer. - discrfield: FieldPath + discrfield: FieldPath, + // Like discrfield, but in source order. For debuginfo. + discrfield_source: FieldPath } } @@ -1242,10 +1250,11 @@ impl<'a, 'gcx, 'tcx> Layout { if !Struct::would_be_zero_sized(dl, other_fields)? { continue; } - let path = Struct::non_zero_field_path(infcx, + let paths = Struct::non_zero_field_paths(infcx, variants[discr].iter().cloned(), None)?; - let mut path = if let Some(p) = path { p } else { continue }; + let (mut path, mut path_source) = if let Some(p) = paths { p } + else { continue }; // FIXME(eddyb) should take advantage of a newtype. if path == &[0] && variants[discr].len() == 1 { @@ -1273,11 +1282,14 @@ impl<'a, 'gcx, 'tcx> Layout { *path.last_mut().unwrap() = i; path.push(0); // For GEP through a pointer. path.reverse(); + path_source.push(0); + path_source.reverse(); return success(StructWrappedNullablePointer { nndiscr: discr as u64, nonnull: st, - discrfield: path + discrfield: path, + discrfield_source: path_source }); } } diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index c379ec7da90..c7f21427a0c 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -1870,7 +1870,8 @@ fn gather_type_sizes<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { match **layout { Layout::StructWrappedNullablePointer { nonnull: ref variant_layout, nndiscr, - discrfield: _ } => { + discrfield: _, + discrfield_source: _ } => { debug!("print-type-size t: `{:?}` adt struct-wrapped nullable nndiscr {} is {:?}", ty, nndiscr, variant_layout); let variant_def = &adt_def.variants[nndiscr as usize]; diff --git a/src/librustc_trans/debuginfo/metadata.rs b/src/librustc_trans/debuginfo/metadata.rs index f6b5bde6ebb..f9600be1c66 100644 --- a/src/librustc_trans/debuginfo/metadata.rs +++ b/src/librustc_trans/debuginfo/metadata.rs @@ -1258,7 +1258,7 @@ impl<'tcx> EnumMemberDescriptionFactory<'tcx> { }, layout::StructWrappedNullablePointer { nonnull: ref struct_def, nndiscr, - ref discrfield, ..} => { + ref discrfield_source, ..} => { // Create a description of the non-null variant let (variant_type_metadata, variant_llvm_type, member_description_factory) = describe_enum_variant(cx, @@ -1281,12 +1281,12 @@ impl<'tcx> EnumMemberDescriptionFactory<'tcx> { // member's name. let null_variant_index = (1 - nndiscr) as usize; let null_variant_name = adt.variants[null_variant_index].name; - let discrfield = discrfield.iter() + let discrfield_source = discrfield_source.iter() .skip(1) .map(|x| x.to_string()) .collect::>().join("$"); let union_member_name = format!("RUST$ENCODED$ENUM${}${}", - discrfield, + discrfield_source, null_variant_name); // Create the (singleton) list of descriptions of union members. diff --git a/src/test/debuginfo/struct-in-enum.rs b/src/test/debuginfo/struct-in-enum.rs index d0aceaa4f3f..ffd36ae14ad 100644 --- a/src/test/debuginfo/struct-in-enum.rs +++ b/src/test/debuginfo/struct-in-enum.rs @@ -19,11 +19,11 @@ // gdb-command:run // gdb-command:print case1 -// gdbg-check:$1 = {{RUST$ENUM$DISR = Case1, __0 = 0, __1 = {x = 2088533116, y = 2088533116, z = 31868}}, {RUST$ENUM$DISR = Case1, __0 = 0, __1 = 8970181431921507452, __2 = 31868}} +// gdbg-check:$1 = {{RUST$ENUM$DISR = Case1, __0 = 0, __1 = {x = 2088533116, y = 2088533116, z = 31868}}, {RUST$ENUM$DISR = Case1, [...]}} // gdbr-check:$1 = struct_in_enum::Regular::Case1(0, struct_in_enum::Struct {x: 2088533116, y: 2088533116, z: 31868}) // gdb-command:print case2 -// gdbg-check:$2 = {{RUST$ENUM$DISR = Case2, __0 = 0, __1 = {x = 286331153, y = 286331153, z = 4369}}, {RUST$ENUM$DISR = Case2, __0 = 0, __1 = 1229782938247303441, __2 = 4369}} +// gdbg-check:$2 = {{RUST$ENUM$DISR = Case2, [...]}, {RUST$ENUM$DISR = Case2, __0 = 0, __1 = 1229782938247303441, __2 = 4369}} // gdbr-check:$2 = struct_in_enum::Regular::Case2(0, 1229782938247303441, 4369) // gdb-command:print univariant