]> git.lizzy.rs Git - rust.git/commitdiff
Fix computation of enum names based off the discrfield in the case of the null pointe...
authorAustin Hicks <camlorn@camlorn.net>
Sat, 3 Dec 2016 00:24:24 +0000 (19:24 -0500)
committerAustin Hicks <camlorn@camlorn.net>
Wed, 14 Dec 2016 17:28:26 +0000 (12:28 -0500)
src/librustc/ty/layout.rs
src/librustc_trans/base.rs
src/librustc_trans/debuginfo/metadata.rs
src/test/debuginfo/struct-in-enum.rs

index 8021fc3ba15cf6099d94eb1f4e9502380da52edf..7a8a34788d2779562cee43ba11c3c5cd2a19ef1d 100644 (file)
@@ -717,16 +717,18 @@ pub fn field_index_by_increasing_offset<'b>(&'b self) -> impl iter::Iterator<Ite
 
     /// 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 @@ fn non_zero_field_in_type(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
                     // 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 @@ fn non_zero_field_in_type(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
             // 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 @@ fn non_zero_field_in_type(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
             // 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 @@ fn non_zero_field_in_type(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
 
     /// 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 @@ pub fn compute_uncached(ty: Ty<'gcx>,
                         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 @@ pub fn compute_uncached(ty: Ty<'gcx>,
                         *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
                         });
                     }
                 }
index c379ec7da90e104248bfaaf7ef80b783c5193ea3..c7f21427a0ceb656c5e6731acbc635dd25ba80cb 100644 (file)
@@ -1870,7 +1870,8 @@ enum Fields<'a> {
         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];
index f6b5bde6ebb445b359427f970ff024971871ab66..f9600be1c6618de0f191152526793cb96c3bebbd 100644 (file)
@@ -1258,7 +1258,7 @@ fn create_member_descriptions<'a>(&self, cx: &CrateContext<'a, '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 @@ fn create_member_descriptions<'a>(&self, cx: &CrateContext<'a, '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.
index d0aceaa4f3f9c2f0de7e925852055b411d96158b..ffd36ae14ad7cd75d3a2659e099d740281d0e8cd 100644 (file)
 // 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