diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/librustc_trans/common.rs | 21 | ||||
| -rw-r--r-- | src/librustc_trans/intrinsic.rs | 6 | ||||
| -rw-r--r-- | src/librustc_trans/mir/analyze.rs | 9 | ||||
| -rw-r--r-- | src/librustc_trans/mir/block.rs | 33 | ||||
| -rw-r--r-- | src/librustc_trans/mir/constant.rs | 7 | ||||
| -rw-r--r-- | src/librustc_trans/mir/lvalue.rs | 8 | ||||
| -rw-r--r-- | src/librustc_trans/mir/mod.rs | 8 | ||||
| -rw-r--r-- | src/librustc_trans/mir/operand.rs | 76 | ||||
| -rw-r--r-- | src/librustc_trans/mir/rvalue.rs | 3 | ||||
| -rw-r--r-- | src/librustc_trans/type_of.rs | 19 |
10 files changed, 84 insertions, 106 deletions
diff --git a/src/librustc_trans/common.rs b/src/librustc_trans/common.rs index f476416619e..03ae58fd941 100644 --- a/src/librustc_trans/common.rs +++ b/src/librustc_trans/common.rs @@ -28,7 +28,7 @@ use type_of::LayoutLlvmExt; use value::Value; use rustc::traits; use rustc::ty::{self, Ty, TyCtxt}; -use rustc::ty::layout::{self, HasDataLayout, LayoutOf}; +use rustc::ty::layout::{HasDataLayout, LayoutOf}; use rustc::ty::subst::{Kind, Subst, Substs}; use rustc::hir; @@ -54,25 +54,6 @@ pub fn type_is_fat_ptr<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) -> } } -/// Returns true if the type is represented as a pair of immediates. -pub fn type_is_imm_pair<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) - -> bool { - let layout = ccx.layout_of(ty); - match layout.fields { - layout::FieldPlacement::Arbitrary { .. } => { - // There must be only 2 fields. - if layout.fields.count() != 2 { - return false; - } - - // The two fields must be both immediates. - layout.field(ccx, 0).is_llvm_immediate() && - layout.field(ccx, 1).is_llvm_immediate() - } - _ => false - } -} - pub fn type_needs_drop<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty: Ty<'tcx>) -> bool { ty.needs_drop(tcx, ty::ParamEnv::empty(traits::Reveal::All)) } diff --git a/src/librustc_trans/intrinsic.rs b/src/librustc_trans/intrinsic.rs index d982fa192b3..7d08090cd7e 100644 --- a/src/librustc_trans/intrinsic.rs +++ b/src/librustc_trans/intrinsic.rs @@ -675,10 +675,8 @@ pub fn trans_intrinsic_call<'a, 'tcx>(bcx: &Builder<'a, 'tcx>, let ptr = bcx.pointercast(llresult, ty.llvm_type(ccx).ptr_to()); bcx.store(llval, ptr, Some(ccx.align_of(ret_ty))); } else { - OperandRef { - val: OperandValue::Immediate(llval), - layout: result.layout - }.unpack_if_pair(bcx).val.store(bcx, result); + OperandRef::from_immediate_or_packed_pair(bcx, llval, result.layout) + .val.store(bcx, result); } } } diff --git a/src/librustc_trans/mir/analyze.rs b/src/librustc_trans/mir/analyze.rs index 93780aefe4d..bf822249a64 100644 --- a/src/librustc_trans/mir/analyze.rs +++ b/src/librustc_trans/mir/analyze.rs @@ -19,7 +19,6 @@ use rustc::mir::visit::{Visitor, LvalueContext}; use rustc::mir::traversal; use rustc::ty; use rustc::ty::layout::LayoutOf; -use common; use type_of::LayoutLlvmExt; use super::MirContext; @@ -32,10 +31,11 @@ pub fn lvalue_locals<'a, 'tcx>(mircx: &MirContext<'a, 'tcx>) -> BitVector { for (index, ty) in mir.local_decls.iter().map(|l| l.ty).enumerate() { let ty = mircx.monomorphize(&ty); debug!("local {} has type {:?}", index, ty); - if mircx.ccx.layout_of(ty).is_llvm_immediate() { + let layout = mircx.ccx.layout_of(ty); + if layout.is_llvm_immediate() { // These sorts of types are immediates that we can store // in an ValueRef without an alloca. - } else if common::type_is_imm_pair(mircx.ccx, ty) { + } else if layout.is_llvm_scalar_pair(mircx.ccx) { // We allow pairs and uses of any of their 2 fields. } else { // These sorts of types require an alloca. Note that @@ -145,7 +145,8 @@ impl<'mir, 'a, 'tcx> Visitor<'tcx> for LocalAnalyzer<'mir, 'a, 'tcx> { let ty = proj.base.ty(self.cx.mir, self.cx.ccx.tcx()); let ty = self.cx.monomorphize(&ty.to_ty(self.cx.ccx.tcx())); - if common::type_is_imm_pair(self.cx.ccx, ty) { + let layout = self.cx.ccx.layout_of(ty); + if layout.is_llvm_scalar_pair(self.cx.ccx) { return; } } diff --git a/src/librustc_trans/mir/block.rs b/src/librustc_trans/mir/block.rs index d1b6e9073b8..e739037b07d 100644 --- a/src/librustc_trans/mir/block.rs +++ b/src/librustc_trans/mir/block.rs @@ -135,11 +135,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> { if let Some((ret_dest, target)) = destination { let ret_bcx = this.get_builder(target); this.set_debug_loc(&ret_bcx, terminator.source_info); - let op = OperandRef { - val: Immediate(invokeret), - layout: fn_ty.ret.layout, - }; - this.store_return(&ret_bcx, ret_dest, &fn_ty.ret, op); + this.store_return(&ret_bcx, ret_dest, &fn_ty.ret, invokeret); } } else { let llret = bcx.call(fn_ptr, &llargs, cleanup_bundle); @@ -153,11 +149,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> { } if let Some((ret_dest, target)) = destination { - let op = OperandRef { - val: Immediate(llret), - layout: fn_ty.ret.layout, - }; - this.store_return(&bcx, ret_dest, &fn_ty.ret, op); + this.store_return(&bcx, ret_dest, &fn_ty.ret, llret); funclet_br(this, bcx, target); } else { bcx.unreachable(); @@ -252,7 +244,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> { if let Ref(llval, align) = op.val { bcx.load(llval, align.non_abi()) } else { - op.pack_if_pair(&bcx).immediate() + op.immediate_or_packed_pair(&bcx) } }; bcx.ret(llval); @@ -545,12 +537,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> { terminator.source_info.span); if let ReturnDest::IndirectOperand(dst, _) = ret_dest { - // Make a fake operand for store_return - let op = OperandRef { - val: Ref(dst.llval, Alignment::AbiAligned), - layout: fn_ty.ret.layout, - }; - self.store_return(&bcx, ret_dest, &fn_ty.ret, op); + self.store_return(&bcx, ret_dest, &fn_ty.ret, dst.llval); } if let Some((_, target)) = *destination { @@ -649,7 +636,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> { op.val.store(bcx, scratch); (scratch.llval, Alignment::AbiAligned, true) } else { - (op.pack_if_pair(bcx).immediate(), Alignment::AbiAligned, false) + (op.immediate_or_packed_pair(bcx), Alignment::AbiAligned, false) } } Ref(llval, align @ Alignment::Packed(_)) if arg.is_indirect() => { @@ -915,12 +902,12 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> { bcx: &Builder<'a, 'tcx>, dest: ReturnDest<'tcx>, ret_ty: &ArgType<'tcx>, - op: OperandRef<'tcx>) { + llval: ValueRef) { use self::ReturnDest::*; match dest { Nothing => (), - Store(dst) => ret_ty.store(bcx, op.immediate(), dst), + Store(dst) => ret_ty.store(bcx, llval, dst), IndirectOperand(tmp, index) => { let op = tmp.load(bcx); tmp.storage_dead(bcx); @@ -929,14 +916,14 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> { DirectOperand(index) => { // If there is a cast, we have to store and reload. let op = if ret_ty.cast.is_some() { - let tmp = LvalueRef::alloca(bcx, op.layout, "tmp_ret"); + let tmp = LvalueRef::alloca(bcx, ret_ty.layout, "tmp_ret"); tmp.storage_live(bcx); - ret_ty.store(bcx, op.immediate(), tmp); + ret_ty.store(bcx, llval, tmp); let op = tmp.load(bcx); tmp.storage_dead(bcx); op } else { - op.unpack_if_pair(bcx) + OperandRef::from_immediate_or_packed_pair(bcx, llval, ret_ty.layout) }; self.locals[index] = LocalRef::Operand(Some(op)); } diff --git a/src/librustc_trans/mir/constant.rs b/src/librustc_trans/mir/constant.rs index 542893bd62b..3196300a706 100644 --- a/src/librustc_trans/mir/constant.rs +++ b/src/librustc_trans/mir/constant.rs @@ -139,13 +139,14 @@ impl<'a, 'tcx> Const<'tcx> { } pub fn to_operand(&self, ccx: &CrateContext<'a, 'tcx>) -> OperandRef<'tcx> { - let llty = ccx.layout_of(self.ty).immediate_llvm_type(ccx); + let layout = ccx.layout_of(self.ty); + let llty = layout.immediate_llvm_type(ccx); let llvalty = val_ty(self.llval); - let val = if llty == llvalty && common::type_is_imm_pair(ccx, self.ty) { + let val = if llty == llvalty && layout.is_llvm_scalar_pair(ccx) { let (a, b) = self.get_pair(ccx); OperandValue::Pair(a, b) - } else if llty == llvalty && ccx.layout_of(self.ty).is_llvm_immediate() { + } else if llty == llvalty && layout.is_llvm_immediate() { // If the types match, we can use the value directly. OperandValue::Immediate(self.llval) } else { diff --git a/src/librustc_trans/mir/lvalue.rs b/src/librustc_trans/mir/lvalue.rs index c6eb822ec87..8340d865eb1 100644 --- a/src/librustc_trans/mir/lvalue.rs +++ b/src/librustc_trans/mir/lvalue.rs @@ -16,7 +16,7 @@ use rustc::mir::tcx::LvalueTy; use rustc_data_structures::indexed_vec::Idx; use base; use builder::Builder; -use common::{self, CrateContext, C_usize, C_u8, C_u32, C_uint, C_int, C_null, C_uint_big}; +use common::{CrateContext, C_usize, C_u8, C_u32, C_uint, C_int, C_null, C_uint_big}; use consts; use type_of::LayoutLlvmExt; use type_::Type; @@ -175,10 +175,10 @@ impl<'a, 'tcx> LvalueRef<'tcx> { load }; OperandValue::Immediate(base::to_immediate(bcx, llval, self.layout)) - } else if common::type_is_imm_pair(bcx.ccx, self.layout.ty) { + } else if self.layout.is_llvm_scalar_pair(bcx.ccx) { OperandValue::Pair( - self.project_field(bcx, 0).load(bcx).pack_if_pair(bcx).immediate(), - self.project_field(bcx, 1).load(bcx).pack_if_pair(bcx).immediate()) + self.project_field(bcx, 0).load(bcx).immediate(), + self.project_field(bcx, 1).load(bcx).immediate()) } else { OperandValue::Ref(self.llval, self.alignment) }; diff --git a/src/librustc_trans/mir/mod.rs b/src/librustc_trans/mir/mod.rs index 38719fedede..6f9d32b1a37 100644 --- a/src/librustc_trans/mir/mod.rs +++ b/src/librustc_trans/mir/mod.rs @@ -475,11 +475,9 @@ fn arg_local_refs<'a, 'tcx>(bcx: &Builder<'a, 'tcx>, let llarg = llvm::get_param(bcx.llfn(), llarg_idx as c_uint); bcx.set_value_name(llarg, &name); llarg_idx += 1; - let operand = OperandRef { - val: OperandValue::Immediate(llarg), - layout: arg.layout - }; - return LocalRef::Operand(Some(operand.unpack_if_pair(bcx))); + return LocalRef::Operand(Some( + OperandRef::from_immediate_or_packed_pair(bcx, llarg, arg.layout) + )); } else { let tmp = LvalueRef::alloca(bcx, arg.layout, &name); arg.store_fn_arg(bcx, &mut llarg_idx, tmp); diff --git a/src/librustc_trans/mir/operand.rs b/src/librustc_trans/mir/operand.rs index 5659072fa93..3e7aa9d0db5 100644 --- a/src/librustc_trans/mir/operand.rs +++ b/src/librustc_trans/mir/operand.rs @@ -15,7 +15,7 @@ use rustc::mir; use rustc_data_structures::indexed_vec::Idx; use base; -use common::{self, CrateContext, C_undef}; +use common::{CrateContext, C_undef}; use builder::Builder; use value::Value; use type_of::LayoutLlvmExt; @@ -24,7 +24,6 @@ use std::fmt; use std::ptr; use super::{MirContext, LocalRef}; -use super::constant::Const; use super::lvalue::{Alignment, LvalueRef}; /// The representation of a Rust value. The enum variant is in fact @@ -84,10 +83,10 @@ impl<'a, 'tcx> OperandRef<'tcx> { pub fn new_zst(ccx: &CrateContext<'a, 'tcx>, layout: TyLayout<'tcx>) -> OperandRef<'tcx> { assert!(layout.is_zst()); - let llty = layout.llvm_type(ccx); - // FIXME(eddyb) ZSTs should always be immediate, not pairs. - // This hack only exists to unpack a constant undef pair. - Const::new(C_undef(llty), layout.ty).to_operand(ccx) + OperandRef { + val: OperandValue::Immediate(C_undef(layout.llvm_type(ccx))), + layout + } } /// Asserts that this operand refers to a scalar and returns @@ -115,12 +114,13 @@ impl<'a, 'tcx> OperandRef<'tcx> { } } - /// If this operand is a Pair, we return an - /// Immediate aggregate with the two values. - pub fn pack_if_pair(mut self, bcx: &Builder<'a, 'tcx>) -> OperandRef<'tcx> { + /// If this operand is a `Pair`, we return an aggregate with the two values. + /// For other cases, see `immediate`. + pub fn immediate_or_packed_pair(self, bcx: &Builder<'a, 'tcx>) -> ValueRef { if let OperandValue::Pair(a, b) = self.val { let llty = self.layout.llvm_type(bcx.ccx); - debug!("Operand::pack_if_pair: packing {:?} into {:?}", self, llty); + debug!("Operand::immediate_or_packed_pair: packing {:?} into {:?}", + self, llty); // Reconstruct the immediate aggregate. let mut llpair = C_undef(llty); let elems = [a, b]; @@ -128,29 +128,33 @@ impl<'a, 'tcx> OperandRef<'tcx> { let elem = base::from_immediate(bcx, elems[i]); llpair = bcx.insert_value(llpair, elem, self.layout.llvm_field_index(i)); } - self.val = OperandValue::Immediate(llpair); + llpair + } else { + self.immediate() } - self } - /// If this operand is a pair in an Immediate, - /// we return a Pair with the two halves. - pub fn unpack_if_pair(mut self, bcx: &Builder<'a, 'tcx>) -> OperandRef<'tcx> { - if let OperandValue::Immediate(llval) = self.val { - // Deconstruct the immediate aggregate. - if common::type_is_imm_pair(bcx.ccx, self.layout.ty) { - debug!("Operand::unpack_if_pair: unpacking {:?}", self); + /// If the type is a pair, we return a `Pair`, otherwise, an `Immediate`. + pub fn from_immediate_or_packed_pair(bcx: &Builder<'a, 'tcx>, + llval: ValueRef, + layout: TyLayout<'tcx>) + -> OperandRef<'tcx> { + let val = if layout.is_llvm_scalar_pair(bcx.ccx) { + debug!("Operand::from_immediate_or_packed_pair: unpacking {:?} @ {:?}", + llval, layout); - let a = bcx.extract_value(llval, self.layout.llvm_field_index(0)); - let a = base::to_immediate(bcx, a, self.layout.field(bcx.ccx, 0)); + // Deconstruct the immediate aggregate. + let a = bcx.extract_value(llval, layout.llvm_field_index(0)); + let a = base::to_immediate(bcx, a, layout.field(bcx.ccx, 0)); - let b = bcx.extract_value(llval, self.layout.llvm_field_index(1)); - let b = base::to_immediate(bcx, b, self.layout.field(bcx.ccx, 1)); + let b = bcx.extract_value(llval, layout.llvm_field_index(1)); + let b = base::to_immediate(bcx, b, layout.field(bcx.ccx, 1)); - self.val = OperandValue::Pair(a, b); - } - } - self + OperandValue::Pair(a, b) + } else { + OperandValue::Immediate(llval) + }; + OperandRef { val, layout } } } @@ -170,16 +174,9 @@ impl<'a, 'tcx> OperandValue { bcx.store(base::from_immediate(bcx, s), dest.llval, dest.alignment.non_abi()); } OperandValue::Pair(a, b) => { - // See comment above about zero-sized values. - let dest_a = dest.project_field(bcx, 0); - if !dest_a.layout.is_zst() { - let a = base::from_immediate(bcx, a); - bcx.store(a, dest_a.llval, dest_a.alignment.non_abi()); - } - let dest_b = dest.project_field(bcx, 1); - if !dest_b.layout.is_zst() { - let b = base::from_immediate(bcx, b); - bcx.store(b, dest_b.llval, dest_b.alignment.non_abi()); + for (i, &x) in [a, b].iter().enumerate() { + OperandValue::Immediate(x) + .store(bcx, dest.project_field(bcx, i)); } } } @@ -218,13 +215,10 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> { (OperandValue::Pair(a, b), &mir::ProjectionElem::Field(ref f, ty)) => { let llval = [a, b][f.index()]; - let op = OperandRef { + return OperandRef { val: OperandValue::Immediate(llval), layout: bcx.ccx.layout_of(self.monomorphize(&ty)) }; - - // Handle nested pairs. - return op.unpack_if_pair(bcx); } _ => {} } diff --git a/src/librustc_trans/mir/rvalue.rs b/src/librustc_trans/mir/rvalue.rs index e52dcd07562..33b1a7e3363 100644 --- a/src/librustc_trans/mir/rvalue.rs +++ b/src/librustc_trans/mir/rvalue.rs @@ -70,9 +70,8 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> { // `CoerceUnsized` can be passed by a where-clause, // so the (generic) MIR may not be able to expand it. let operand = self.trans_operand(&bcx, source); - let operand = operand.pack_if_pair(&bcx); match operand.val { - OperandValue::Pair(..) => bug!(), + OperandValue::Pair(..) | OperandValue::Immediate(_) => { // unsize from an immediate structure. We don't // really need a temporary alloca here, but diff --git a/src/librustc_trans/type_of.rs b/src/librustc_trans/type_of.rs index 529ad51ba8e..6da6f1ebaf0 100644 --- a/src/librustc_trans/type_of.rs +++ b/src/librustc_trans/type_of.rs @@ -174,6 +174,7 @@ pub struct PointeeInfo { pub trait LayoutLlvmExt<'tcx> { fn is_llvm_immediate(&self) -> bool; + fn is_llvm_scalar_pair<'a>(&self, ccx: &CrateContext<'a, 'tcx>) -> bool; fn llvm_type<'a>(&self, ccx: &CrateContext<'a, 'tcx>) -> Type; fn immediate_llvm_type<'a>(&self, ccx: &CrateContext<'a, 'tcx>) -> Type; fn over_align(&self) -> Option<Align>; @@ -192,6 +193,24 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyLayout<'tcx> { } } + fn is_llvm_scalar_pair<'a>(&self, ccx: &CrateContext<'a, 'tcx>) -> bool { + match self.fields { + layout::FieldPlacement::Arbitrary { .. } => { + // There must be only 2 fields. + if self.fields.count() != 2 { + return false; + } + + // The two fields must be both scalars. + match (&self.field(ccx, 0).abi, &self.field(ccx, 1).abi) { + (&layout::Abi::Scalar(_), &layout::Abi::Scalar(_)) => true, + _ => false + } + } + _ => false + } + } + /// Get the LLVM type corresponding to a Rust type, i.e. `rustc::ty::Ty`. /// The pointee type of the pointer in `LvalueRef` is always this type. /// For sized types, it is also the right LLVM type for an `alloca` |
