]> git.lizzy.rs Git - rust.git/commitdiff
Change trans_field_ptr to utilize LvalueTy to determine discriminant.
authorMark Simulacrum <mark.simulacrum@gmail.com>
Mon, 2 Jan 2017 16:06:01 +0000 (09:06 -0700)
committerMark Simulacrum <mark.simulacrum@gmail.com>
Wed, 4 Jan 2017 18:37:42 +0000 (11:37 -0700)
src/librustc_trans/adt.rs
src/librustc_trans/base.rs
src/librustc_trans/glue.rs
src/librustc_trans/intrinsic.rs
src/librustc_trans/mir/block.rs
src/librustc_trans/mir/lvalue.rs
src/librustc_trans/mir/rvalue.rs

index 14882dd433ba7987b885613049595b6321c203b3..a541306f99a12ad234248210f55495639fb176b0 100644 (file)
@@ -48,6 +48,7 @@
 use llvm::{ValueRef, True, IntEQ, IntNE};
 use rustc::ty::layout;
 use rustc::ty::{self, Ty, AdtKind};
+use rustc::mir::tcx::LvalueTy;
 use mir::lvalue::LvalueRef;
 use common::*;
 use builder::Builder;
@@ -476,31 +477,33 @@ fn assert_discr_in_range(min: Disr, max: Disr, discr: Disr) {
 pub fn trans_field_ptr<'a, 'tcx>(
     bcx: &Builder<'a, 'tcx>,
     val: LvalueRef<'tcx>,
-    discr: Disr,
-    ix: usize
+    ix: usize,
 ) -> ValueRef {
+    let discr = match val.ty {
+        LvalueTy::Ty { .. } => 0,
+        LvalueTy::Downcast { variant_index, .. } => variant_index,
+    };
     let t = val.ty.to_ty(bcx.tcx());
     let l = bcx.ccx.layout_of(t);
-    debug!("trans_field_ptr on {} represented as {:#?}", t, l);
     // Note: if this ever needs to generate conditionals (e.g., if we
     // decide to do some kind of cdr-coding-like non-unique repr
     // someday), it will need to return a possibly-new bcx as well.
     match *l {
         layout::Univariant { ref variant, .. } => {
-            assert_eq!(discr, Disr(0));
+            assert_eq!(discr, 0);
             struct_field_ptr(bcx, &variant,
              &compute_fields(bcx.ccx, t, 0, false),
              val, ix, false)
         }
         layout::Vector { count, .. } => {
-            assert_eq!(discr.0, 0);
+            assert_eq!(discr, 0);
             assert!((ix as u64) < count);
             bcx.struct_gep(val.llval, ix)
         }
         layout::General { discr: d, ref variants, .. } => {
-            let mut fields = compute_fields(bcx.ccx, t, discr.0 as usize, false);
+            let mut fields = compute_fields(bcx.ccx, t, discr, false);
             fields.insert(0, d.to_ty(&bcx.tcx(), false));
-            struct_field_ptr(bcx, &variants[discr.0 as usize],
+            struct_field_ptr(bcx, &variants[discr],
              &fields,
              val, ix + 1, true)
         }
@@ -510,7 +513,7 @@ pub fn trans_field_ptr<'a, 'tcx>(
             bcx.pointercast(val.llval, ty.ptr_to())
         }
         layout::RawNullablePointer { nndiscr, .. } |
-        layout::StructWrappedNullablePointer { nndiscr,  .. } if discr.0 != nndiscr => {
+        layout::StructWrappedNullablePointer { nndiscr,  .. } if discr as u64 != nndiscr => {
             let nullfields = compute_fields(bcx.ccx, t, (1-nndiscr) as usize, false);
             // The unit-like case might have a nonzero number of unit-like fields.
             // (e.d., Result of Either with (), as one side.)
@@ -521,14 +524,14 @@ pub fn trans_field_ptr<'a, 'tcx>(
         layout::RawNullablePointer { nndiscr, .. } => {
             let nnty = compute_fields(bcx.ccx, t, nndiscr as usize, false)[0];
             assert_eq!(ix, 0);
-            assert_eq!(discr.0, nndiscr);
+            assert_eq!(discr as u64, nndiscr);
             let ty = type_of::type_of(bcx.ccx, nnty);
             bcx.pointercast(val.llval, ty.ptr_to())
         }
         layout::StructWrappedNullablePointer { ref nonnull, nndiscr, .. } => {
-            assert_eq!(discr.0, nndiscr);
+            assert_eq!(discr as u64, nndiscr);
             struct_field_ptr(bcx, &nonnull,
-             &compute_fields(bcx.ccx, t, discr.0 as usize, false),
+             &compute_fields(bcx.ccx, t, discr, false),
              val, ix, false)
         }
         _ => bug!("element access in type without elements: {} represented as {:#?}", t, l)
index a329b01cc160821f1aa031c7a600edc97f40b9db..581406476763934da2406da29d7d13b434ca1163 100644 (file)
@@ -37,6 +37,7 @@
 use rustc::hir::def_id::{DefId, LOCAL_CRATE};
 use middle::lang_items::StartFnLangItem;
 use rustc::ty::subst::Substs;
+use rustc::mir::tcx::LvalueTy;
 use rustc::traits;
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc::ty::adjustment::CustomCoerceUnsized;
@@ -288,8 +289,8 @@ pub fn coerce_unsized_into<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
                     continue;
                 }
 
-                let src_f = adt::trans_field_ptr(bcx, src, Disr(0), i);
-                let dst_f = adt::trans_field_ptr(bcx, dst, Disr(0), i);
+                let src_f = adt::trans_field_ptr(bcx, src, i);
+                let dst_f = adt::trans_field_ptr(bcx, dst, i);
                 if src_fty == dst_fty {
                     memcpy_ty(bcx, dst_f, src_f, src_fty, None);
                 } else {
@@ -622,11 +623,16 @@ pub fn trans_ctor_shim<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
             bcx.alloca(fn_ty.ret.memory_ty(ccx), "sret_slot")
         };
         // Can return unsized value
-        let dest_val = LvalueRef::new_sized_ty(dest, sig.output());
+        let mut dest_val = LvalueRef::new_sized_ty(dest, sig.output());
+        dest_val.ty = LvalueTy::Downcast {
+            adt_def: sig.output().ty_adt_def().unwrap(),
+            substs: substs,
+            variant_index: disr.0 as usize,
+        };
         let mut llarg_idx = fn_ty.ret.is_indirect() as usize;
         let mut arg_idx = 0;
         for (i, arg_ty) in sig.inputs().iter().enumerate() {
-            let lldestptr = adt::trans_field_ptr(&bcx, dest_val, Disr::from(disr), i);
+            let lldestptr = adt::trans_field_ptr(&bcx, dest_val, i);
             let arg = &fn_ty.args[arg_idx];
             arg_idx += 1;
             if common::type_is_fat_ptr(bcx.ccx, arg_ty) {
index f3977004b336dd285b07b06219ba25aec2b83759..0b186d4938ba77fb248b365c553990a9015017be 100644 (file)
@@ -20,8 +20,9 @@
 use middle::lang_items::BoxFreeFnLangItem;
 use rustc::ty::subst::{Substs};
 use rustc::traits;
-use rustc::ty::{self, AdtKind, Ty, TypeFoldable};
+use rustc::ty::{self, AdtDef, AdtKind, Ty, TypeFoldable};
 use rustc::ty::subst::Kind;
+use rustc::mir::tcx::LvalueTy;
 use mir::lvalue::LvalueRef;
 use adt;
 use base::*;
@@ -395,14 +396,22 @@ pub fn size_and_align_of_dst<'a, 'tcx>(bcx: &Builder<'a, 'tcx>, t: Ty<'tcx>, inf
 
 // Iterates through the elements of a structural type, dropping them.
 fn drop_structural_ty<'a, 'tcx>(cx: Builder<'a, 'tcx>, ptr: LvalueRef<'tcx>) -> Builder<'a, 'tcx> {
-    fn iter_variant<'a, 'tcx>(cx: &Builder<'a, 'tcx>,
+    fn iter_variant<'a, 'tcx>(cx: &'a Builder<'a, 'tcx>,
                               av: LvalueRef<'tcx>,
-                              variant: &'tcx ty::VariantDef,
-                              substs: &Substs<'tcx>) {
+                              adt_def: &'tcx AdtDef,
+                              variant_index: usize,
+                              substs: &'tcx Substs<'tcx>) {
+        let variant = &adt_def.variants[variant_index];
         let tcx = cx.tcx();
         for (i, field) in variant.fields.iter().enumerate() {
             let arg = monomorphize::field_ty(tcx, substs, field);
-            let field_ptr = adt::trans_field_ptr(&cx, av, Disr::from(variant.disr_val), i);
+            let mut av = av.clone();
+            av.ty = LvalueTy::Downcast {
+                adt_def: adt_def,
+                substs: substs,
+                variant_index: variant_index,
+            };
+            let field_ptr = adt::trans_field_ptr(&cx, av, i);
             drop_ty(&cx, LvalueRef::new_sized_ty(field_ptr, arg));
         }
     }
@@ -412,7 +421,7 @@ fn iter_variant<'a, 'tcx>(cx: &Builder<'a, 'tcx>,
     match t.sty {
         ty::TyClosure(def_id, substs) => {
             for (i, upvar_ty) in substs.upvar_tys(def_id, cx.tcx()).enumerate() {
-                let llupvar = adt::trans_field_ptr(&cx, ptr, Disr(0), i);
+                let llupvar = adt::trans_field_ptr(&cx, ptr, i);
                 drop_ty(&cx, LvalueRef::new_sized_ty(llupvar, upvar_ty));
             }
         }
@@ -430,7 +439,7 @@ fn iter_variant<'a, 'tcx>(cx: &Builder<'a, 'tcx>,
         }
         ty::TyTuple(ref args) => {
             for (i, arg) in args.iter().enumerate() {
-                let llfld_a = adt::trans_field_ptr(&cx, ptr, Disr(0), i);
+                let llfld_a = adt::trans_field_ptr(&cx, ptr, i);
                 drop_ty(&cx, LvalueRef::new_sized_ty(llfld_a, *arg));
             }
         }
@@ -438,7 +447,13 @@ fn iter_variant<'a, 'tcx>(cx: &Builder<'a, 'tcx>,
             AdtKind::Struct => {
                 let VariantInfo { fields, discr } = VariantInfo::from_ty(cx.tcx(), t, None);
                 for (i, &Field(_, field_ty)) in fields.iter().enumerate() {
-                    let llfld_a = adt::trans_field_ptr(&cx, ptr, Disr::from(discr), i);
+                    let mut ptr = ptr.clone();
+                    ptr.ty = LvalueTy::Downcast {
+                        adt_def: adt,
+                        substs: substs,
+                        variant_index: Disr::from(discr).0 as usize,
+                    };
+                    let llfld_a = adt::trans_field_ptr(&cx, ptr, i);
                     let ptr = if cx.ccx.shared().type_is_sized(field_ty) {
                         LvalueRef::new_sized_ty(llfld_a, field_ty)
                     } else {
@@ -460,7 +475,7 @@ fn iter_variant<'a, 'tcx>(cx: &Builder<'a, 'tcx>,
                     (adt::BranchKind::Single, None) => {
                         if n_variants != 0 {
                             assert!(n_variants == 1);
-                            iter_variant(&cx, ptr, &adt.variants[0], substs);
+                            iter_variant(&cx, ptr, &adt, 0, substs);
                         }
                     }
                     (adt::BranchKind::Switch, Some(lldiscrim_a)) => {
@@ -485,13 +500,13 @@ fn iter_variant<'a, 'tcx>(cx: &Builder<'a, 'tcx>,
                         let llswitch = cx.switch(lldiscrim_a, ret_void_cx.llbb(), n_variants);
                         let next_cx = cx.build_new_block("enum-iter-next");
 
-                        for variant in &adt.variants {
+                        for (i, variant) in adt.variants.iter().enumerate() {
                             let variant_cx_name = format!("enum-iter-variant-{}",
                                 &variant.disr_val.to_string());
                             let variant_cx = cx.build_new_block(&variant_cx_name);
                             let case_val = adt::trans_case(&cx, t, Disr::from(variant.disr_val));
                             variant_cx.add_case(llswitch, case_val, variant_cx.llbb());
-                            iter_variant(&variant_cx, ptr, variant, substs);
+                            iter_variant(&variant_cx, ptr, &adt, i, substs);
                             variant_cx.br(next_cx.llbb());
                         }
                         cx = next_cx;
index b80c707f37697c3d00879d96071c4c49f1cf1abb..9a06a242aa7575cc2ee573e8e951bc9ec4a626e1 100644 (file)
@@ -25,7 +25,6 @@
 use machine;
 use type_::Type;
 use rustc::ty::{self, Ty};
-use Disr;
 use rustc::hir;
 use syntax::ast;
 use syntax::symbol::Symbol;
@@ -553,7 +552,7 @@ fn modify_as_needed<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
                         let arg = LvalueRef::new_sized_ty(llarg, arg_type);
                         (0..contents.len())
                             .map(|i| {
-                                bcx.load(adt::trans_field_ptr(bcx, arg, Disr(0), i))
+                                bcx.load(adt::trans_field_ptr(bcx, arg, i))
                             })
                             .collect()
                     }
index 77ce17006baa0d81b64f105794dabce93bfb74fa..ccaa4140122bd04e4d2104aacb5e85d57e5898bb 100644 (file)
@@ -709,7 +709,7 @@ fn trans_arguments_untupled(&mut self,
             Ref(llval) => {
                 for (n, &ty) in arg_types.iter().enumerate() {
                     let ptr = adt::trans_field_ptr(
-                        bcx, LvalueRef::new_sized_ty(llval, tuple.ty), Disr(0), n
+                        bcx, LvalueRef::new_sized_ty(llval, tuple.ty), n
                     );
                     let val = if common::type_is_fat_ptr(bcx.ccx, ty) {
                         let (lldata, llextra) = base::load_fat_ptr(bcx, ptr, ty);
index fe8f92c679801141c034b7031cb4932cf60823ab..5f97dfa22cd549b23d71038d9a61978cf3854aa1 100644 (file)
@@ -20,7 +20,6 @@
 use machine;
 use type_of::type_of;
 use type_of;
-use Disr;
 
 use std::ptr;
 
@@ -48,6 +47,13 @@ pub fn new_sized_ty(llval: ValueRef, ty: Ty<'tcx>) -> LvalueRef<'tcx> {
         LvalueRef::new_sized(llval, LvalueTy::from_ty(ty))
     }
 
+    pub fn new_unsized(llval: ValueRef, llextra: ValueRef, ty: LvalueTy<'tcx>) -> LvalueRef<'tcx> {
+        LvalueRef {
+            llval: llval,
+            llextra: llextra,
+            ty: ty,
+        }
+    }
     pub fn new_unsized_ty(llval: ValueRef, llextra: ValueRef, ty: Ty<'tcx>) -> LvalueRef<'tcx> {
         LvalueRef {
             llval: llval,
@@ -140,26 +146,14 @@ pub fn trans_lvalue(&mut self,
                 let (llprojected, llextra) = match projection.elem {
                     mir::ProjectionElem::Deref => bug!(),
                     mir::ProjectionElem::Field(ref field, _) => {
-                        let base_ty = tr_base.ty.to_ty(tcx);
-                        let discr = match tr_base.ty {
-                            LvalueTy::Ty { .. } => 0,
-                            LvalueTy::Downcast { adt_def: _, substs: _, variant_index: v } => v,
-                        };
-                        let discr = discr as u64;
                         let is_sized = self.ccx.shared().type_is_sized(projected_ty.to_ty(tcx));
                         let base = if is_sized {
-                            LvalueRef::new_sized_ty(tr_base.llval, base_ty)
-                        } else {
-                            LvalueRef::new_unsized_ty(tr_base.llval, tr_base.llextra, base_ty)
-                        };
-                        let llprojected = adt::trans_field_ptr(bcx, base, Disr(discr),
-                            field.index());
-                        let llextra = if is_sized {
-                            ptr::null_mut()
+                            LvalueRef::new_sized(tr_base.llval, tr_base.ty)
                         } else {
-                            tr_base.llextra
+                            LvalueRef::new_unsized(tr_base.llval, tr_base.llextra, tr_base.ty)
                         };
-                        (llprojected, llextra)
+                        let llprojected = adt::trans_field_ptr(bcx, base, field.index());
+                        (llprojected, base.llextra)
                     }
                     mir::ProjectionElem::Index(ref index) => {
                         let index = self.trans_operand(bcx, index);
index 9a3d63f18e8b40565dba954aee93148737f56ecb..cc468ac18fdd9c2bcca468a79b9ef3504e29ea1e 100644 (file)
@@ -12,6 +12,7 @@
 use rustc::ty::{self, Ty};
 use rustc::ty::cast::{CastTy, IntTy};
 use rustc::ty::layout::Layout;
+use rustc::mir::tcx::LvalueTy;
 use rustc::mir;
 use middle::lang_items::ExchangeMallocFnLangItem;
 
@@ -102,7 +103,7 @@ pub fn trans_rvalue(&mut self,
 
             mir::Rvalue::Aggregate(ref kind, ref operands) => {
                 match *kind {
-                    mir::AggregateKind::Adt(adt_def, variant_index, _, active_field_index) => {
+                    mir::AggregateKind::Adt(adt_def, variant_index, substs, active_field_index) => {
                         let disr = Disr::from(adt_def.variants[variant_index].disr_val);
                         let dest_ty = dest.ty.to_ty(bcx.tcx());
                         adt::trans_set_discr(&bcx, dest_ty, dest.llval, Disr::from(disr));
@@ -110,9 +111,14 @@ pub fn trans_rvalue(&mut self,
                             let op = self.trans_operand(&bcx, operand);
                             // Do not generate stores and GEPis for zero-sized fields.
                             if !common::type_is_zero_size(bcx.ccx, op.ty) {
-                                let val = LvalueRef::new_sized_ty(dest.llval, dest_ty);
+                                let mut val = LvalueRef::new_sized(dest.llval, dest.ty);
                                 let field_index = active_field_index.unwrap_or(i);
-                                let lldest_i = adt::trans_field_ptr(&bcx, val, disr, field_index);
+                                val.ty = LvalueTy::Downcast {
+                                    adt_def: adt_def,
+                                    substs: self.monomorphize(&substs),
+                                    variant_index: disr.0 as usize,
+                                };
+                                let lldest_i = adt::trans_field_ptr(&bcx, val, field_index);
                                 self.store_operand(&bcx, lldest_i, op, None);
                             }
                         }