diff --git a/src/librustc_trans/mir/block.rs b/src/librustc_trans/mir/block.rs index 356d3e7372b9f..9a4cfb6f98485 100644 --- a/src/librustc_trans/mir/block.rs +++ b/src/librustc_trans/mir/block.rs @@ -11,7 +11,7 @@ use llvm::{self, ValueRef, BasicBlockRef}; use rustc_const_eval::{ErrKind, ConstEvalErr, note_const_eval_err}; use rustc::middle::lang_items; -use rustc::ty::{self, layout}; +use rustc::ty::{self, layout, TypeFoldable}; use rustc::mir; use abi::{Abi, FnType, ArgType}; use adt; @@ -435,10 +435,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> { if intrinsic == Some("transmute") { let &(ref dest, target) = destination.as_ref().unwrap(); - self.with_lvalue_ref(&bcx, dest, |this, dest| { - this.trans_transmute(&bcx, &args[0], dest); - }); - + self.trans_transmute(&bcx, &args[0], dest); funclet_br(self, bcx, target); return; } @@ -877,7 +874,34 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> { } fn trans_transmute(&mut self, bcx: &Builder<'a, 'tcx>, - src: &mir::Operand<'tcx>, dst: LvalueRef<'tcx>) { + src: &mir::Operand<'tcx>, + dst: &mir::Lvalue<'tcx>) { + if let mir::Lvalue::Local(index) = *dst { + match self.locals[index] { + LocalRef::Lvalue(lvalue) => self.trans_transmute_into(bcx, src, &lvalue), + LocalRef::Operand(None) => { + let lvalue_ty = self.monomorphized_lvalue_ty(dst); + assert!(!lvalue_ty.has_erasable_regions()); + let lvalue = LvalueRef::alloca(bcx, lvalue_ty, "transmute_temp"); + self.trans_transmute_into(bcx, src, &lvalue); + let op = self.trans_load(bcx, lvalue.llval, lvalue.alignment, lvalue_ty); + self.locals[index] = LocalRef::Operand(Some(op)); + } + LocalRef::Operand(Some(_)) => { + let ty = self.monomorphized_lvalue_ty(dst); + assert!(common::type_is_zero_size(bcx.ccx, ty), + "assigning to initialized SSAtemp"); + } + } + } else { + let dst = self.trans_lvalue(bcx, dst); + self.trans_transmute_into(bcx, src, &dst); + } + } + + fn trans_transmute_into(&mut self, bcx: &Builder<'a, 'tcx>, + src: &mir::Operand<'tcx>, + dst: &LvalueRef<'tcx>) { let mut val = self.trans_operand(bcx, src); if let ty::TyFnDef(def_id, substs, _) = val.ty.sty { let llouttype = type_of::type_of(bcx.ccx, dst.ty.to_ty(bcx.tcx())); diff --git a/src/librustc_trans/mir/lvalue.rs b/src/librustc_trans/mir/lvalue.rs index 6800fa341524e..2538f32031fdb 100644 --- a/src/librustc_trans/mir/lvalue.rs +++ b/src/librustc_trans/mir/lvalue.rs @@ -15,10 +15,9 @@ use rustc::mir::tcx::LvalueTy; use rustc_data_structures::indexed_vec::Idx; use adt; use builder::Builder; -use common::{self, CrateContext, C_uint, C_undef}; +use common::{self, CrateContext, C_uint}; use consts; use machine; -use type_of::type_of; use type_of; use type_::Type; use value::Value; @@ -416,47 +415,6 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> { result } - // Perform an action using the given Lvalue. - // If the Lvalue is an empty LocalRef::Operand, then a temporary stack slot - // is created first, then used as an operand to update the Lvalue. - // - // FIXME: this is only called from transmute; please remove it. - pub fn with_lvalue_ref(&mut self, bcx: &Builder<'a, 'tcx>, - lvalue: &mir::Lvalue<'tcx>, f: F) -> U - where F: FnOnce(&mut Self, LvalueRef<'tcx>) -> U - { - if let mir::Lvalue::Local(index) = *lvalue { - match self.locals[index] { - LocalRef::Lvalue(lvalue) => f(self, lvalue), - LocalRef::Operand(None) => { - let lvalue_ty = self.monomorphized_lvalue_ty(lvalue); - assert!(!lvalue_ty.has_erasable_regions()); - let lvalue = LvalueRef::alloca(bcx, lvalue_ty, "lvalue_temp"); - let ret = f(self, lvalue); - let op = self.trans_load(bcx, lvalue.llval, lvalue.alignment, lvalue_ty); - self.locals[index] = LocalRef::Operand(Some(op)); - ret - } - LocalRef::Operand(Some(_)) => { - // See comments in LocalRef::new_operand as to why - // we always have Some in a ZST LocalRef::Operand. - let ty = self.monomorphized_lvalue_ty(lvalue); - if common::type_is_zero_size(bcx.ccx, ty) { - // Pass an undef pointer as no stores can actually occur. - let llptr = C_undef(type_of(bcx.ccx, ty).ptr_to()); - f(self, LvalueRef::new_sized(llptr, LvalueTy::from_ty(ty), - Alignment::AbiAligned)) - } else { - bug!("Lvalue local already set"); - } - } - } - } else { - let lvalue = self.trans_lvalue(bcx, lvalue); - f(self, lvalue) - } - } - /// Adjust the bitwidth of an index since LLVM is less forgiving /// than we are. ///