Skip to content

Commit 9966bbd

Browse files
committed
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.
1 parent a65cc1e commit 9966bbd

File tree

4 files changed

+36
-23
lines changed

4 files changed

+36
-23
lines changed

src/librustc/ty/layout.rs

Lines changed: 29 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -717,16 +717,18 @@ impl<'a, 'gcx, 'tcx> Struct {
717717

718718
/// Find the path leading to a non-zero leaf field, starting from
719719
/// the given type and recursing through aggregates.
720+
/// The tuple is `(path, source_path)1,
721+
/// where `path` is in memory order and `source_path` in source order.
720722
// FIXME(eddyb) track value ranges and traverse already optimized enums.
721723
fn non_zero_field_in_type(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
722724
ty: Ty<'gcx>)
723-
-> Result<Option<FieldPath>, LayoutError<'gcx>> {
725+
-> Result<Option<(FieldPath, FieldPath)>, LayoutError<'gcx>> {
724726
let tcx = infcx.tcx.global_tcx();
725727
match (ty.layout(infcx)?, &ty.sty) {
726728
(&Scalar { non_zero: true, .. }, _) |
727-
(&CEnum { non_zero: true, .. }, _) => Ok(Some(vec![])),
729+
(&CEnum { non_zero: true, .. }, _) => Ok(Some((vec![], vec![]))),
728730
(&FatPointer { non_zero: true, .. }, _) => {
729-
Ok(Some(vec![FAT_PTR_ADDR as u32]))
731+
Ok(Some((vec![FAT_PTR_ADDR as u32], vec![FAT_PTR_ADDR as u32])))
730732
}
731733

732734
// Is this the NonZero lang item wrapping a pointer or integer type?
@@ -737,10 +739,11 @@ impl<'a, 'gcx, 'tcx> Struct {
737739
// FIXME(eddyb) also allow floating-point types here.
738740
Scalar { value: Int(_), non_zero: false } |
739741
Scalar { value: Pointer, non_zero: false } => {
740-
Ok(Some(vec![0]))
742+
Ok(Some((vec![0], vec![0])))
741743
}
742744
FatPointer { non_zero: false, .. } => {
743-
Ok(Some(vec![FAT_PTR_ADDR as u32, 0]))
745+
let tmp = vec![FAT_PTR_ADDR as u32, 0];
746+
Ok(Some((tmp.clone(), tmp)))
744747
}
745748
_ => Ok(None)
746749
}
@@ -749,7 +752,7 @@ impl<'a, 'gcx, 'tcx> Struct {
749752
// Perhaps one of the fields of this struct is non-zero
750753
// let's recurse and find out
751754
(&Univariant { ref variant, .. }, &ty::TyAdt(def, substs)) if def.is_struct() => {
752-
Struct::non_zero_field_path(infcx, def.struct_variant().fields
755+
Struct::non_zero_field_paths(infcx, def.struct_variant().fields
753756
.iter().map(|field| {
754757
field.ty(tcx, substs)
755758
}),
@@ -759,19 +762,19 @@ impl<'a, 'gcx, 'tcx> Struct {
759762
// Perhaps one of the upvars of this closure is non-zero
760763
(&Univariant { ref variant, .. }, &ty::TyClosure(def, substs)) => {
761764
let upvar_tys = substs.upvar_tys(def, tcx);
762-
Struct::non_zero_field_path(infcx, upvar_tys,
765+
Struct::non_zero_field_paths(infcx, upvar_tys,
763766
Some(&variant.memory_index[..]))
764767
}
765768
// Can we use one of the fields in this tuple?
766769
(&Univariant { ref variant, .. }, &ty::TyTuple(tys)) => {
767-
Struct::non_zero_field_path(infcx, tys.iter().cloned(),
770+
Struct::non_zero_field_paths(infcx, tys.iter().cloned(),
768771
Some(&variant.memory_index[..]))
769772
}
770773

771774
// Is this a fixed-size array of something non-zero
772775
// with at least one element?
773776
(_, &ty::TyArray(ety, d)) if d > 0 => {
774-
Struct::non_zero_field_path(infcx, Some(ety).into_iter(), None)
777+
Struct::non_zero_field_paths(infcx, Some(ety).into_iter(), None)
775778
}
776779

777780
(_, &ty::TyProjection(_)) | (_, &ty::TyAnon(..)) => {
@@ -789,20 +792,23 @@ impl<'a, 'gcx, 'tcx> Struct {
789792

790793
/// Find the path leading to a non-zero leaf field, starting from
791794
/// the given set of fields and recursing through aggregates.
792-
fn non_zero_field_path<I>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
795+
// / Returns Some((path, source_path)) on success.
796+
/// `path` is translated to memory order. `source_path` is not.
797+
fn non_zero_field_paths<I>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
793798
fields: I,
794799
permutation: Option<&[u32]>)
795-
-> Result<Option<FieldPath>, LayoutError<'gcx>>
800+
-> Result<Option<(FieldPath, FieldPath)>, LayoutError<'gcx>>
796801
where I: Iterator<Item=Ty<'gcx>> {
797802
for (i, ty) in fields.enumerate() {
798-
if let Some(mut path) = Struct::non_zero_field_in_type(infcx, ty)? {
803+
if let Some((mut path, mut source_path)) = Struct::non_zero_field_in_type(infcx, ty)? {
804+
source_path.push(i as u32);
799805
let index = if let Some(p) = permutation {
800806
p[i] as usize
801807
} else {
802808
i
803809
};
804810
path.push(index as u32);
805-
return Ok(Some(path));
811+
return Ok(Some((path, source_path)));
806812
}
807813
}
808814
Ok(None)
@@ -965,7 +971,9 @@ pub enum Layout {
965971
nndiscr: u64,
966972
nonnull: Struct,
967973
// N.B. There is a 0 at the start, for LLVM GEP through a pointer.
968-
discrfield: FieldPath
974+
discrfield: FieldPath,
975+
// Like discrfield, but in source order. For debuginfo.
976+
discrfield_source: FieldPath
969977
}
970978
}
971979

@@ -1242,10 +1250,11 @@ impl<'a, 'gcx, 'tcx> Layout {
12421250
if !Struct::would_be_zero_sized(dl, other_fields)? {
12431251
continue;
12441252
}
1245-
let path = Struct::non_zero_field_path(infcx,
1253+
let paths = Struct::non_zero_field_paths(infcx,
12461254
variants[discr].iter().cloned(),
12471255
None)?;
1248-
let mut path = if let Some(p) = path { p } else { continue };
1256+
let (mut path, mut path_source) = if let Some(p) = paths { p }
1257+
else { continue };
12491258

12501259
// FIXME(eddyb) should take advantage of a newtype.
12511260
if path == &[0] && variants[discr].len() == 1 {
@@ -1273,11 +1282,14 @@ impl<'a, 'gcx, 'tcx> Layout {
12731282
*path.last_mut().unwrap() = i;
12741283
path.push(0); // For GEP through a pointer.
12751284
path.reverse();
1285+
path_source.push(0);
1286+
path_source.reverse();
12761287

12771288
return success(StructWrappedNullablePointer {
12781289
nndiscr: discr as u64,
12791290
nonnull: st,
1280-
discrfield: path
1291+
discrfield: path,
1292+
discrfield_source: path_source
12811293
});
12821294
}
12831295
}

src/librustc_trans/base.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1870,7 +1870,8 @@ fn gather_type_sizes<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
18701870
match **layout {
18711871
Layout::StructWrappedNullablePointer { nonnull: ref variant_layout,
18721872
nndiscr,
1873-
discrfield: _ } => {
1873+
discrfield: _,
1874+
discrfield_source: _ } => {
18741875
debug!("print-type-size t: `{:?}` adt struct-wrapped nullable nndiscr {} is {:?}",
18751876
ty, nndiscr, variant_layout);
18761877
let variant_def = &adt_def.variants[nndiscr as usize];

src/librustc_trans/debuginfo/metadata.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1258,7 +1258,7 @@ impl<'tcx> EnumMemberDescriptionFactory<'tcx> {
12581258
},
12591259
layout::StructWrappedNullablePointer { nonnull: ref struct_def,
12601260
nndiscr,
1261-
ref discrfield, ..} => {
1261+
ref discrfield_source, ..} => {
12621262
// Create a description of the non-null variant
12631263
let (variant_type_metadata, variant_llvm_type, member_description_factory) =
12641264
describe_enum_variant(cx,
@@ -1281,12 +1281,12 @@ impl<'tcx> EnumMemberDescriptionFactory<'tcx> {
12811281
// member's name.
12821282
let null_variant_index = (1 - nndiscr) as usize;
12831283
let null_variant_name = adt.variants[null_variant_index].name;
1284-
let discrfield = discrfield.iter()
1284+
let discrfield_source = discrfield_source.iter()
12851285
.skip(1)
12861286
.map(|x| x.to_string())
12871287
.collect::<Vec<_>>().join("$");
12881288
let union_member_name = format!("RUST$ENCODED$ENUM${}${}",
1289-
discrfield,
1289+
discrfield_source,
12901290
null_variant_name);
12911291

12921292
// Create the (singleton) list of descriptions of union members.

src/test/debuginfo/struct-in-enum.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,11 @@
1919
// gdb-command:run
2020

2121
// gdb-command:print case1
22-
// 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}}
22+
// gdbg-check:$1 = {{RUST$ENUM$DISR = Case1, __0 = 0, __1 = {x = 2088533116, y = 2088533116, z = 31868}}, {RUST$ENUM$DISR = Case1, [...]}}
2323
// gdbr-check:$1 = struct_in_enum::Regular::Case1(0, struct_in_enum::Struct {x: 2088533116, y: 2088533116, z: 31868})
2424

2525
// gdb-command:print case2
26-
// 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}}
26+
// gdbg-check:$2 = {{RUST$ENUM$DISR = Case2, [...]}, {RUST$ENUM$DISR = Case2, __0 = 0, __1 = 1229782938247303441, __2 = 4369}}
2727
// gdbr-check:$2 = struct_in_enum::Regular::Case2(0, 1229782938247303441, 4369)
2828

2929
// gdb-command:print univariant

0 commit comments

Comments
 (0)