From ea0ebe41c7dc04374ec0e7e1173bb32b374d02fb Mon Sep 17 00:00:00 2001 From: Mark Simulacrum Date: Mon, 2 Jan 2017 09:06:01 -0700 Subject: [PATCH] Change trans_field_ptr to utilize LvalueTy to determine discriminant. --- src/librustc_trans/adt.rs | 25 +++++++++++---------- src/librustc_trans/base.rs | 14 ++++++++---- src/librustc_trans/glue.rs | 37 ++++++++++++++++++++++---------- src/librustc_trans/intrinsic.rs | 3 +-- src/librustc_trans/mir/block.rs | 2 +- src/librustc_trans/mir/lvalue.rs | 28 ++++++++++-------------- src/librustc_trans/mir/rvalue.rs | 12 ++++++++--- 7 files changed, 72 insertions(+), 49 deletions(-) diff --git a/src/librustc_trans/adt.rs b/src/librustc_trans/adt.rs index 14882dd433ba7..a541306f99a12 100644 --- a/src/librustc_trans/adt.rs +++ b/src/librustc_trans/adt.rs @@ -48,6 +48,7 @@ use std; 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) diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index a329b01cc1608..5814064767639 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -37,6 +37,7 @@ use llvm; 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) { diff --git a/src/librustc_trans/glue.rs b/src/librustc_trans/glue.rs index f3977004b336d..0b186d4938ba7 100644 --- a/src/librustc_trans/glue.rs +++ b/src/librustc_trans/glue.rs @@ -20,8 +20,9 @@ use llvm::{ValueRef, get_param}; 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 drop_structural_ty<'a, 'tcx>(cx: Builder<'a, 'tcx>, ptr: LvalueRef<'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 drop_structural_ty<'a, 'tcx>(cx: Builder<'a, 'tcx>, ptr: LvalueRef<'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 drop_structural_ty<'a, 'tcx>(cx: Builder<'a, 'tcx>, ptr: LvalueRef<'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 drop_structural_ty<'a, 'tcx>(cx: Builder<'a, 'tcx>, ptr: LvalueRef<'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 drop_structural_ty<'a, 'tcx>(cx: Builder<'a, 'tcx>, ptr: LvalueRef<'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; diff --git a/src/librustc_trans/intrinsic.rs b/src/librustc_trans/intrinsic.rs index b80c707f37697..9a06a242aa757 100644 --- a/src/librustc_trans/intrinsic.rs +++ b/src/librustc_trans/intrinsic.rs @@ -25,7 +25,6 @@ use type_of; 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 @@ pub fn trans_intrinsic_call<'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() } diff --git a/src/librustc_trans/mir/block.rs b/src/librustc_trans/mir/block.rs index 77ce17006baa0..ccaa4140122bd 100644 --- a/src/librustc_trans/mir/block.rs +++ b/src/librustc_trans/mir/block.rs @@ -709,7 +709,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> { 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); diff --git a/src/librustc_trans/mir/lvalue.rs b/src/librustc_trans/mir/lvalue.rs index fe8f92c679801..5f97dfa22cd54 100644 --- a/src/librustc_trans/mir/lvalue.rs +++ b/src/librustc_trans/mir/lvalue.rs @@ -20,7 +20,6 @@ use consts; use machine; use type_of::type_of; use type_of; -use Disr; use std::ptr; @@ -48,6 +47,13 @@ impl<'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 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> { 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); diff --git a/src/librustc_trans/mir/rvalue.rs b/src/librustc_trans/mir/rvalue.rs index 9a3d63f18e8b4..cc468ac18fdd9 100644 --- a/src/librustc_trans/mir/rvalue.rs +++ b/src/librustc_trans/mir/rvalue.rs @@ -12,6 +12,7 @@ use llvm::{self, ValueRef}; 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 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> { 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 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> { 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); } }