diff options
| author | Austin Hicks <camlorn@camlorn.net> | 2016-12-02 19:24:24 -0500 |
|---|---|---|
| committer | Austin Hicks <camlorn@camlorn.net> | 2016-12-14 12:28:26 -0500 |
| commit | 9966bbd1b11fcd2866cdbd21146f5e9a0d8ea66c (patch) | |
| tree | dd2e5d55dae54f7bfc9a8a07b605f7969ce49df9 /src | |
| parent | a65cc1ea546bca6cccf4e479e4acd09a8a839ce0 (diff) | |
| download | rust-9966bbd1b11fcd2866cdbd21146f5e9a0d8ea66c.tar.gz rust-9966bbd1b11fcd2866cdbd21146f5e9a0d8ea66c.zip | |
Fix computation of enum names based off the discrfield in the case of the null pointer optimization. This functionality is needed by pretty printers for gdb and lldb.
Diffstat (limited to 'src')
| -rw-r--r-- | src/librustc/ty/layout.rs | 46 | ||||
| -rw-r--r-- | src/librustc_trans/base.rs | 3 | ||||
| -rw-r--r-- | src/librustc_trans/debuginfo/metadata.rs | 6 | ||||
| -rw-r--r-- | src/test/debuginfo/struct-in-enum.rs | 4 |
4 files changed, 36 insertions, 23 deletions
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<Option<FieldPath>, LayoutError<'gcx>> { + -> Result<Option<(FieldPath, FieldPath)>, 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<I>(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<I>(infcx: &InferCtxt<'a, 'gcx, 'tcx>, fields: I, permutation: Option<&[u32]>) - -> Result<Option<FieldPath>, LayoutError<'gcx>> + -> Result<Option<(FieldPath, FieldPath)>, LayoutError<'gcx>> where I: Iterator<Item=Ty<'gcx>> { 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::<Vec<_>>().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 |
