From d9277b163c36448c5fbc39fa089a78256b45ffc1 Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Wed, 9 Mar 2016 14:20:22 +0200 Subject: [PATCH] trans: Make everything used from within at_start Builder-friendly. --- src/librustc_trans/trans/abi.rs | 11 ++-- src/librustc_trans/trans/adt.rs | 53 ++++++++++++------- src/librustc_trans/trans/base.rs | 53 ++++++++++++------- src/librustc_trans/trans/closure.rs | 4 +- src/librustc_trans/trans/common.rs | 4 ++ src/librustc_trans/trans/glue.rs | 42 +++++++-------- src/librustc_trans/trans/intrinsic.rs | 6 ++- src/librustc_trans/trans/mir/block.rs | 10 ++-- src/librustc_trans/trans/mir/lvalue.rs | 33 ++++++++---- src/librustc_trans/trans/mir/mod.rs | 69 ++++++++++++------------- src/librustc_trans/trans/mir/operand.rs | 9 ++-- src/librustc_trans/trans/mir/rvalue.rs | 17 +++--- 12 files changed, 169 insertions(+), 142 deletions(-) diff --git a/src/librustc_trans/trans/abi.rs b/src/librustc_trans/trans/abi.rs index 46a76b60989..192522214e6 100644 --- a/src/librustc_trans/trans/abi.rs +++ b/src/librustc_trans/trans/abi.rs @@ -10,9 +10,8 @@ use llvm::{self, ValueRef}; use trans::base; -use trans::build::B; use trans::builder::Builder; -use trans::common::{type_is_fat_ptr, Block}; +use trans::common::{type_is_fat_ptr, BlockAndBuilder}; use trans::context::CrateContext; use trans::cabi_x86; use trans::cabi_x86_64; @@ -169,18 +168,16 @@ impl ArgType { } } - pub fn store_fn_arg(&self, bcx: Block, idx: &mut usize, dst: ValueRef) { + pub fn store_fn_arg(&self, bcx: &BlockAndBuilder, idx: &mut usize, dst: ValueRef) { if self.pad.is_some() { *idx += 1; } if self.is_ignore() { return; } - let val = llvm::get_param(bcx.fcx.llfn, *idx as c_uint); + let val = llvm::get_param(bcx.fcx().llfn, *idx as c_uint); *idx += 1; - if !bcx.unreachable.get() { - self.store(&B(bcx), val, dst); - } + self.store(bcx, val, dst); } } diff --git a/src/librustc_trans/trans/adt.rs b/src/librustc_trans/trans/adt.rs index 436963ec26d..45a1236647e 100644 --- a/src/librustc_trans/trans/adt.rs +++ b/src/librustc_trans/trans/adt.rs @@ -1065,6 +1065,15 @@ pub fn num_args(r: &Repr, discr: Disr) -> usize { /// Access a field, at a point when the value's case is known. pub fn trans_field_ptr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, r: &Repr<'tcx>, val: MaybeSizedValue, discr: Disr, ix: usize) -> ValueRef { + trans_field_ptr_builder(&bcx.build(), r, val, discr, ix) +} + +/// Access a field, at a point when the value's case is known. +pub fn trans_field_ptr_builder<'blk, 'tcx>(bcx: &BlockAndBuilder<'blk, 'tcx>, + r: &Repr<'tcx>, + val: MaybeSizedValue, + discr: Disr, ix: usize) + -> ValueRef { // 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. @@ -1087,13 +1096,15 @@ pub fn trans_field_ptr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, r: &Repr<'tcx>, assert_eq!(machine::llsize_of_alloc(bcx.ccx(), ty), 0); // The contents of memory at this pointer can't matter, but use // the value that's "reasonable" in case of pointer comparison. - PointerCast(bcx, val.value, ty.ptr_to()) + if bcx.is_unreachable() { return C_undef(ty.ptr_to()); } + bcx.pointercast(val.value, ty.ptr_to()) } RawNullablePointer { nndiscr, nnty, .. } => { assert_eq!(ix, 0); assert_eq!(discr, nndiscr); let ty = type_of::type_of(bcx.ccx(), nnty); - PointerCast(bcx, val.value, ty.ptr_to()) + if bcx.is_unreachable() { return C_undef(ty.ptr_to()); } + bcx.pointercast(val.value, ty.ptr_to()) } StructWrappedNullablePointer { ref nonnull, nndiscr, .. } => { assert_eq!(discr, nndiscr); @@ -1102,33 +1113,39 @@ pub fn trans_field_ptr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, r: &Repr<'tcx>, } } -pub fn struct_field_ptr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, st: &Struct<'tcx>, val: MaybeSizedValue, - ix: usize, needs_cast: bool) -> ValueRef { +fn struct_field_ptr<'blk, 'tcx>(bcx: &BlockAndBuilder<'blk, 'tcx>, + st: &Struct<'tcx>, val: MaybeSizedValue, + ix: usize, needs_cast: bool) -> ValueRef { let ccx = bcx.ccx(); + let fty = st.fields[ix]; + let ll_fty = type_of::in_memory_type_of(bcx.ccx(), fty); + if bcx.is_unreachable() { + return C_undef(ll_fty.ptr_to()); + } + let ptr_val = if needs_cast { let fields = st.fields.iter().map(|&ty| { type_of::in_memory_type_of(ccx, ty) }).collect::>(); let real_ty = Type::struct_(ccx, &fields[..], st.packed); - PointerCast(bcx, val.value, real_ty.ptr_to()) + bcx.pointercast(val.value, real_ty.ptr_to()) } else { val.value }; - let fty = st.fields[ix]; // Simple case - we can just GEP the field // * First field - Always aligned properly // * Packed struct - There is no alignment padding // * Field is sized - pointer is properly aligned already if ix == 0 || st.packed || type_is_sized(bcx.tcx(), fty) { - return StructGEP(bcx, ptr_val, ix); + return bcx.struct_gep(ptr_val, ix); } // If the type of the last field is [T] or str, then we don't need to do // any adjusments match fty.sty { ty::TySlice(..) | ty::TyStr => { - return StructGEP(bcx, ptr_val, ix); + return bcx.struct_gep(ptr_val, ix); } _ => () } @@ -1137,7 +1154,7 @@ pub fn struct_field_ptr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, st: &Struct<'tcx>, v if !val.has_meta() { debug!("Unsized field `{}`, of `{:?}` has no metadata for adjustment", ix, Value(ptr_val)); - return StructGEP(bcx, ptr_val, ix); + return bcx.struct_gep(ptr_val, ix); } let dbloc = DebugLoc::None; @@ -1178,22 +1195,21 @@ pub fn struct_field_ptr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, st: &Struct<'tcx>, v // (unaligned offset + (align - 1)) & -align // Calculate offset - let align_sub_1 = Sub(bcx, align, C_uint(bcx.ccx(), 1u64), dbloc); - let offset = And(bcx, - Add(bcx, unaligned_offset, align_sub_1, dbloc), - Neg(bcx, align, dbloc), - dbloc); + dbloc.apply(bcx.fcx()); + let align_sub_1 = bcx.sub(align, C_uint(bcx.ccx(), 1u64)); + let offset = bcx.and(bcx.add(unaligned_offset, align_sub_1), + bcx.neg(align)); debug!("struct_field_ptr: DST field offset: {:?}", Value(offset)); // Cast and adjust pointer - let byte_ptr = PointerCast(bcx, ptr_val, Type::i8p(bcx.ccx())); - let byte_ptr = GEP(bcx, byte_ptr, &[offset]); + let byte_ptr = bcx.pointercast(ptr_val, Type::i8p(bcx.ccx())); + let byte_ptr = bcx.gep(byte_ptr, &[offset]); // Finally, cast back to the type expected let ll_fty = type_of::in_memory_type_of(bcx.ccx(), fty); debug!("struct_field_ptr: Field type is {:?}", ll_fty); - PointerCast(bcx, byte_ptr, ll_fty.ptr_to()) + bcx.pointercast(byte_ptr, ll_fty.ptr_to()) } pub fn fold_variants<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, @@ -1284,7 +1300,8 @@ pub fn trans_drop_flag_ptr<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, } )); bcx = fold_variants(bcx, r, val, |variant_cx, st, value| { - let ptr = struct_field_ptr(variant_cx, st, MaybeSizedValue::sized(value), + let ptr = struct_field_ptr(&variant_cx.build(), st, + MaybeSizedValue::sized(value), (st.fields.len() - 1), false); datum::Datum::new(ptr, ptr_ty, datum::Lvalue::new("adt::trans_drop_flag_ptr")) .store_to(variant_cx, scratch.val) diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs index 76085b394c1..6add4fee567 100644 --- a/src/librustc_trans/trans/base.rs +++ b/src/librustc_trans/trans/base.rs @@ -911,33 +911,43 @@ pub fn load_if_immediate<'blk, 'tcx>(cx: Block<'blk, 'tcx>, v: ValueRef, t: Ty<' /// differs from the type used for SSA values. Also handles various special cases where the type /// gives us better information about what we are loading. pub fn load_ty<'blk, 'tcx>(cx: Block<'blk, 'tcx>, ptr: ValueRef, t: Ty<'tcx>) -> ValueRef { - if cx.unreachable.get() || type_is_zero_size(cx.ccx(), t) { + if cx.unreachable.get() { return C_undef(type_of::type_of(cx.ccx(), t)); } + load_ty_builder(&B(cx), ptr, t) +} + +pub fn load_ty_builder<'a, 'tcx>(b: &Builder<'a, 'tcx>, ptr: ValueRef, t: Ty<'tcx>) -> ValueRef { + let ccx = b.ccx; + if type_is_zero_size(ccx, t) { + return C_undef(type_of::type_of(ccx, t)); + } unsafe { let global = llvm::LLVMIsAGlobalVariable(ptr); if !global.is_null() && llvm::LLVMIsGlobalConstant(global) == llvm::True { let val = llvm::LLVMGetInitializer(global); if !val.is_null() { - return to_immediate(cx, val, t); + if t.is_bool() { + return llvm::LLVMConstTrunc(val, Type::i1(ccx).to_ref()); + } + return val; } } } - let val = if t.is_bool() { - LoadRangeAssert(cx, ptr, 0, 2, llvm::False) + if t.is_bool() { + b.trunc(b.load_range_assert(ptr, 0, 2, llvm::False), Type::i1(ccx)) } else if t.is_char() { // a char is a Unicode codepoint, and so takes values from 0 // to 0x10FFFF inclusive only. - LoadRangeAssert(cx, ptr, 0, 0x10FFFF + 1, llvm::False) - } else if (t.is_region_ptr() || t.is_unique()) && !common::type_is_fat_ptr(cx.tcx(), t) { - LoadNonNull(cx, ptr) + b.load_range_assert(ptr, 0, 0x10FFFF + 1, llvm::False) + } else if (t.is_region_ptr() || t.is_unique()) && + !common::type_is_fat_ptr(ccx.tcx(), t) { + b.load_nonnull(ptr) } else { - Load(cx, ptr) - }; - - to_immediate(cx, val, t) + b.load(ptr) + } } /// Helper for storing values in memory. Does the necessary conversion if the in-memory type @@ -1644,13 +1654,14 @@ impl<'blk, 'tcx> FunctionContext<'blk, 'tcx> { uninit_reason, arg_scope_id, |bcx, dst| { debug!("FunctionContext::bind_args: {:?}: {:?}", hir_arg, arg_ty); + let b = &bcx.build(); if common::type_is_fat_ptr(bcx.tcx(), arg_ty) { let meta = &self.fn_ty.args[idx]; idx += 1; - arg.store_fn_arg(bcx, &mut llarg_idx, expr::get_dataptr(bcx, dst)); - meta.store_fn_arg(bcx, &mut llarg_idx, expr::get_meta(bcx, dst)); + arg.store_fn_arg(b, &mut llarg_idx, expr::get_dataptr(bcx, dst)); + meta.store_fn_arg(b, &mut llarg_idx, expr::get_meta(bcx, dst)); } else { - arg.store_fn_arg(bcx, &mut llarg_idx, dst); + arg.store_fn_arg(b, &mut llarg_idx, dst); } bcx })) @@ -1672,13 +1683,14 @@ impl<'blk, 'tcx> FunctionContext<'blk, 'tcx> { for (j, &tupled_arg_ty) in tupled_arg_tys.iter().enumerate() { let dst = StructGEP(bcx, llval, j); let arg = &self.fn_ty.args[idx]; + let b = &bcx.build(); if common::type_is_fat_ptr(bcx.tcx(), tupled_arg_ty) { let meta = &self.fn_ty.args[idx]; idx += 1; - arg.store_fn_arg(bcx, &mut llarg_idx, expr::get_dataptr(bcx, dst)); - meta.store_fn_arg(bcx, &mut llarg_idx, expr::get_meta(bcx, dst)); + arg.store_fn_arg(b, &mut llarg_idx, expr::get_dataptr(bcx, dst)); + meta.store_fn_arg(b, &mut llarg_idx, expr::get_meta(bcx, dst)); } else { - arg.store_fn_arg(bcx, &mut llarg_idx, dst); + arg.store_fn_arg(b, &mut llarg_idx, dst); } } bcx @@ -2024,13 +2036,14 @@ pub fn trans_ctor_shim<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, let lldestptr = adt::trans_field_ptr(bcx, &repr, dest_val, Disr::from(disr), i); let arg = &fcx.fn_ty.args[arg_idx]; arg_idx += 1; + let b = &bcx.build(); if common::type_is_fat_ptr(bcx.tcx(), arg_ty) { let meta = &fcx.fn_ty.args[arg_idx]; arg_idx += 1; - arg.store_fn_arg(bcx, &mut llarg_idx, expr::get_dataptr(bcx, lldestptr)); - meta.store_fn_arg(bcx, &mut llarg_idx, expr::get_meta(bcx, lldestptr)); + arg.store_fn_arg(b, &mut llarg_idx, expr::get_dataptr(bcx, lldestptr)); + meta.store_fn_arg(b, &mut llarg_idx, expr::get_meta(bcx, lldestptr)); } else { - arg.store_fn_arg(bcx, &mut llarg_idx, lldestptr); + arg.store_fn_arg(b, &mut llarg_idx, lldestptr); } } adt::trans_set_discr(bcx, &repr, dest, disr); diff --git a/src/librustc_trans/trans/closure.rs b/src/librustc_trans/trans/closure.rs index 24ce44b076f..2036feb31a2 100644 --- a/src/librustc_trans/trans/closure.rs +++ b/src/librustc_trans/trans/closure.rs @@ -53,7 +53,7 @@ fn load_closure_environment<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let llenv = if kind == ty::ClosureKind::FnOnce && !env_arg.is_indirect() { let closure_ty = node_id_type(bcx, id); let llenv = rvalue_scratch_datum(bcx, closure_ty, "closure_env").val; - env_arg.store_fn_arg(bcx, &mut env_idx, llenv); + env_arg.store_fn_arg(&bcx.build(), &mut env_idx, llenv); llenv } else { get_param(bcx.fcx.llfn, env_idx as c_uint) @@ -410,7 +410,7 @@ fn trans_fn_once_adapter_shim<'a, 'tcx>( InitAlloca::Dropped, self_scope_id, |bcx, llval| { let mut llarg_idx = self_idx; - env_arg.store_fn_arg(bcx, &mut llarg_idx, llval); + env_arg.store_fn_arg(&bcx.build(), &mut llarg_idx, llval); bcx.fcx.schedule_lifetime_end(self_scope_id, llval); bcx })).val diff --git a/src/librustc_trans/trans/common.rs b/src/librustc_trans/trans/common.rs index 7872da58ae2..db06b2352fd 100644 --- a/src/librustc_trans/trans/common.rs +++ b/src/librustc_trans/trans/common.rs @@ -688,6 +688,10 @@ impl<'blk, 'tcx> BlockAndBuilder<'blk, 'tcx> { // Methods delegated to bcx + pub fn is_unreachable(&self) -> bool { + self.bcx.unreachable.get() + } + pub fn ccx(&self) -> &'blk CrateContext<'blk, 'tcx> { self.bcx.ccx() } diff --git a/src/librustc_trans/trans/glue.rs b/src/librustc_trans/trans/glue.rs index a2bf4d3f753..4ca5fb07c98 100644 --- a/src/librustc_trans/trans/glue.rs +++ b/src/librustc_trans/trans/glue.rs @@ -371,7 +371,8 @@ fn trans_struct_drop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, bcx.fcx.pop_and_trans_custom_cleanup_scope(bcx, contents_scope) } -pub fn size_and_align_of_dst<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, t: Ty<'tcx>, info: ValueRef) +pub fn size_and_align_of_dst<'blk, 'tcx>(bcx: &BlockAndBuilder<'blk, 'tcx>, + t: Ty<'tcx>, info: ValueRef) -> (ValueRef, ValueRef) { debug!("calculate size of DST: {}; with lost info: {:?}", t, Value(info)); @@ -385,6 +386,10 @@ pub fn size_and_align_of_dst<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, t: Ty<'tcx>, in let align = C_uint(bcx.ccx(), align); return (size, align); } + if bcx.is_unreachable() { + let llty = Type::int(bcx.ccx()); + return (C_undef(llty), C_undef(llty)); + } match t.sty { ty::TyStruct(def, substs) => { let ccx = bcx.ccx(); @@ -407,8 +412,6 @@ pub fn size_and_align_of_dst<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, t: Ty<'tcx>, in let field_ty = monomorphize::field_ty(bcx.tcx(), substs, last_field); let (unsized_size, unsized_align) = size_and_align_of_dst(bcx, field_ty, info); - let dbloc = DebugLoc::None; - // FIXME (#26403, #27023): We should be adding padding // to `sized_size` (to accommodate the `unsized_align` // required of the unsized field that follows) before @@ -417,14 +420,14 @@ pub fn size_and_align_of_dst<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, t: Ty<'tcx>, in // here. But this is where the add would go.) // Return the sum of sizes and max of aligns. - let mut size = Add(bcx, sized_size, unsized_size, dbloc); + let mut size = bcx.add(sized_size, unsized_size); // Issue #27023: If there is a drop flag, *now* we add 1 // to the size. (We can do this without adding any // padding because drop flags do not have any alignment // constraints.) if sizing_type.needs_drop_flag() { - size = Add(bcx, size, C_uint(bcx.ccx(), 1_u64), dbloc); + size = bcx.add(size, C_uint(bcx.ccx(), 1_u64)); } // Choose max of two known alignments (combined value must @@ -435,14 +438,9 @@ pub fn size_and_align_of_dst<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, t: Ty<'tcx>, in // pick the correct alignment statically. C_uint(ccx, std::cmp::max(sized_align, unsized_align)) } - _ => Select(bcx, - ICmp(bcx, - llvm::IntUGT, - sized_align, - unsized_align, - dbloc), - sized_align, - unsized_align) + _ => bcx.select(bcx.icmp(llvm::IntUGT, sized_align, unsized_align), + sized_align, + unsized_align) }; // Issue #27023: must add any necessary padding to `size` @@ -456,19 +454,18 @@ pub fn size_and_align_of_dst<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, t: Ty<'tcx>, in // // `(size + (align-1)) & -align` - let addend = Sub(bcx, align, C_uint(bcx.ccx(), 1_u64), dbloc); - let size = And( - bcx, Add(bcx, size, addend, dbloc), Neg(bcx, align, dbloc), dbloc); + let addend = bcx.sub(align, C_uint(bcx.ccx(), 1_u64)); + let size = bcx.and(bcx.add(size, addend), bcx.neg(align)); (size, align) } ty::TyTrait(..) => { // info points to the vtable and the second entry in the vtable is the // dynamic size of the object. - let info = PointerCast(bcx, info, Type::int(bcx.ccx()).ptr_to()); - let size_ptr = GEPi(bcx, info, &[1]); - let align_ptr = GEPi(bcx, info, &[2]); - (Load(bcx, size_ptr), Load(bcx, align_ptr)) + let info = bcx.pointercast(info, Type::int(bcx.ccx()).ptr_to()); + let size_ptr = bcx.gepi(info, &[1]); + let align_ptr = bcx.gepi(info, &[2]); + (bcx.load(size_ptr), bcx.load(align_ptr)) } ty::TySlice(_) | ty::TyStr => { let unit_ty = t.sequence_element_type(bcx.tcx()); @@ -477,7 +474,7 @@ pub fn size_and_align_of_dst<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, t: Ty<'tcx>, in let llunit_ty = sizing_type_of(bcx.ccx(), unit_ty); let unit_align = llalign_of_min(bcx.ccx(), llunit_ty); let unit_size = llsize_of_alloc(bcx.ccx(), llunit_ty); - (Mul(bcx, info, C_uint(bcx.ccx(), unit_size), DebugLoc::None), + (bcx.mul(info, C_uint(bcx.ccx(), unit_size)), C_uint(bcx.ccx(), unit_align)) } _ => bcx.sess().bug(&format!("Unexpected unsized type, found {}", t)) @@ -522,7 +519,8 @@ fn make_drop_glue<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, v0: ValueRef, g: DropGlueK let bcx = drop_ty(bcx, v0, content_ty, DebugLoc::None); let info = expr::get_meta(bcx, v0); let info = Load(bcx, info); - let (llsize, llalign) = size_and_align_of_dst(bcx, content_ty, info); + let (llsize, llalign) = + size_and_align_of_dst(&bcx.build(), content_ty, info); // `Box` does not allocate. let needs_free = ICmp(bcx, diff --git a/src/librustc_trans/trans/intrinsic.rs b/src/librustc_trans/trans/intrinsic.rs index b99cb2b6331..736803c573e 100644 --- a/src/librustc_trans/trans/intrinsic.rs +++ b/src/librustc_trans/trans/intrinsic.rs @@ -430,7 +430,8 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, (_, "size_of_val") => { let tp_ty = *substs.types.get(FnSpace, 0); if !type_is_sized(tcx, tp_ty) { - let (llsize, _) = glue::size_and_align_of_dst(bcx, tp_ty, llargs[1]); + let (llsize, _) = + glue::size_and_align_of_dst(&bcx.build(), tp_ty, llargs[1]); llsize } else { let lltp_ty = type_of::type_of(ccx, tp_ty); @@ -444,7 +445,8 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, (_, "min_align_of_val") => { let tp_ty = *substs.types.get(FnSpace, 0); if !type_is_sized(tcx, tp_ty) { - let (_, llalign) = glue::size_and_align_of_dst(bcx, tp_ty, llargs[1]); + let (_, llalign) = + glue::size_and_align_of_dst(&bcx.build(), tp_ty, llargs[1]); llalign } else { C_uint(ccx, type_of::align_of(ccx, tp_ty)) diff --git a/src/librustc_trans/trans/mir/block.rs b/src/librustc_trans/trans/mir/block.rs index 547382daab3..0128cceab1e 100644 --- a/src/librustc_trans/trans/mir/block.rs +++ b/src/librustc_trans/trans/mir/block.rs @@ -26,7 +26,7 @@ use trans::glue; use trans::type_::Type; use super::{MirContext, drop}; -use super::lvalue::LvalueRef; +use super::lvalue::{LvalueRef, load_fat_ptr}; use super::operand::OperandRef; use super::operand::OperandValue::{self, FatPtr, Immediate, Ref}; @@ -478,13 +478,9 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> { let base_repr = adt::represent_type(bcx.ccx(), lv_ty); let base = adt::MaybeSizedValue::sized(lv.llval); for (n, &ty) in result_types.iter().enumerate() { - let ptr = bcx.with_block(|bcx| { - adt::trans_field_ptr(bcx, &base_repr, base, Disr(0), n) - }); + let ptr = adt::trans_field_ptr_builder(bcx, &base_repr, base, Disr(0), n); let val = if common::type_is_fat_ptr(bcx.tcx(), ty) { - let (lldata, llextra) = bcx.with_block(|bcx| { - base::load_fat_ptr(bcx, ptr, ty) - }); + let (lldata, llextra) = load_fat_ptr(bcx, ptr); FatPtr(lldata, llextra) } else { // Don't bother loading the value, trans_argument will. diff --git a/src/librustc_trans/trans/mir/lvalue.rs b/src/librustc_trans/trans/mir/lvalue.rs index f109bf07f20..b6f942c4637 100644 --- a/src/librustc_trans/trans/mir/lvalue.rs +++ b/src/librustc_trans/trans/mir/lvalue.rs @@ -12,8 +12,10 @@ use llvm::ValueRef; use rustc::middle::ty::{self, Ty, TypeFoldable}; use rustc::mir::repr as mir; use rustc::mir::tcx::LvalueTy; +use trans::abi; use trans::adt; use trans::base; +use trans::builder::Builder; use trans::common::{self, BlockAndBuilder}; use trans::consts; use trans::machine; @@ -54,6 +56,18 @@ impl<'tcx> LvalueRef<'tcx> { } } +pub fn get_meta(b: &Builder, fat_ptr: ValueRef) -> ValueRef { + b.struct_gep(fat_ptr, abi::FAT_PTR_EXTRA) +} + +pub fn get_dataptr(b: &Builder, fat_ptr: ValueRef) -> ValueRef { + b.struct_gep(fat_ptr, abi::FAT_PTR_ADDR) +} + +pub fn load_fat_ptr(b: &Builder, fat_ptr: ValueRef) -> (ValueRef, ValueRef) { + (b.load(get_dataptr(b, fat_ptr)), b.load(get_meta(b, fat_ptr))) +} + impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> { pub fn lvalue_len(&mut self, bcx: &BlockAndBuilder<'bcx, 'tcx>, @@ -130,14 +144,12 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> { let (llprojected, llextra) = match projection.elem { mir::ProjectionElem::Deref => { let base_ty = tr_base.ty.to_ty(tcx); - bcx.with_block(|bcx| { - if common::type_is_sized(tcx, projected_ty.to_ty(tcx)) { - (base::load_ty(bcx, tr_base.llval, base_ty), - ptr::null_mut()) - } else { - base::load_fat_ptr(bcx, tr_base.llval, base_ty) - } - }) + if common::type_is_sized(tcx, projected_ty.to_ty(tcx)) { + (base::load_ty_builder(bcx, tr_base.llval, base_ty), + ptr::null_mut()) + } else { + load_fat_ptr(bcx, tr_base.llval) + } } mir::ProjectionElem::Field(ref field, _) => { let base_ty = tr_base.ty.to_ty(tcx); @@ -153,9 +165,8 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> { } else { adt::MaybeSizedValue::unsized_(tr_base.llval, tr_base.llextra) }; - let llprojected = bcx.with_block(|bcx| { - adt::trans_field_ptr(bcx, &base_repr, base, Disr(discr), field.index()) - }); + let llprojected = adt::trans_field_ptr_builder(bcx, &base_repr, base, + Disr(discr), field.index()); let llextra = if is_sized { ptr::null_mut() } else { diff --git a/src/librustc_trans/trans/mir/mod.rs b/src/librustc_trans/trans/mir/mod.rs index b7364b30f06..9df2cb712b1 100644 --- a/src/librustc_trans/trans/mir/mod.rs +++ b/src/librustc_trans/trans/mir/mod.rs @@ -14,14 +14,12 @@ use middle::ty; use rustc::mir::repr as mir; use rustc::mir::tcx::LvalueTy; use trans::base; -use trans::build; use trans::common::{self, Block, BlockAndBuilder, FunctionContext}; -use trans::expr; use std::ops::Deref; use std::rc::Rc; -use self::lvalue::LvalueRef; +use self::lvalue::{LvalueRef, get_dataptr, get_meta}; use self::operand::OperandRef; #[derive(Clone)] @@ -185,26 +183,25 @@ fn arg_value_refs<'bcx, 'tcx>(bcx: &BlockAndBuilder<'bcx, 'tcx>, _ => unreachable!("spread argument isn't a tuple?!") }; - let llval = bcx.with_block(|bcx| { - let lltemp = base::alloc_ty(bcx, arg_ty, &format!("arg{}", arg_index)); - for (i, &tupled_arg_ty) in tupled_arg_tys.iter().enumerate() { - let dst = build::StructGEP(bcx, lltemp, i); - let arg = &fcx.fn_ty.args[idx]; + let lltemp = bcx.with_block(|bcx| { + base::alloc_ty(bcx, arg_ty, &format!("arg{}", arg_index)) + }); + for (i, &tupled_arg_ty) in tupled_arg_tys.iter().enumerate() { + let dst = bcx.struct_gep(lltemp, i); + let arg = &fcx.fn_ty.args[idx]; idx += 1; - if common::type_is_fat_ptr(tcx, tupled_arg_ty) { + if common::type_is_fat_ptr(tcx, tupled_arg_ty) { // We pass fat pointers as two words, but inside the tuple // they are the two sub-fields of a single aggregate field. - let meta = &fcx.fn_ty.args[idx]; - idx += 1; - arg.store_fn_arg(bcx, &mut llarg_idx, expr::get_dataptr(bcx, dst)); - meta.store_fn_arg(bcx, &mut llarg_idx, expr::get_meta(bcx, dst)); - } else { - arg.store_fn_arg(bcx, &mut llarg_idx, dst); - } + let meta = &fcx.fn_ty.args[idx]; + idx += 1; + arg.store_fn_arg(bcx, &mut llarg_idx, get_dataptr(bcx, dst)); + meta.store_fn_arg(bcx, &mut llarg_idx, get_meta(bcx, dst)); + } else { + arg.store_fn_arg(bcx, &mut llarg_idx, dst); } - lltemp - }); - return LvalueRef::new_sized(llval, LvalueTy::from_ty(arg_ty)); + } + return LvalueRef::new_sized(lltemp, LvalueTy::from_ty(arg_ty)); } let arg = &fcx.fn_ty.args[idx]; @@ -218,23 +215,23 @@ fn arg_value_refs<'bcx, 'tcx>(bcx: &BlockAndBuilder<'bcx, 'tcx>, llarg_idx += 1; llarg } else { - bcx.with_block(|bcx| { - let lltemp = base::alloc_ty(bcx, arg_ty, &format!("arg{}", arg_index)); - if common::type_is_fat_ptr(tcx, arg_ty) { - // we pass fat pointers as two words, but we want to - // represent them internally as a pointer to two words, - // so make an alloca to store them in. - let meta = &fcx.fn_ty.args[idx]; - idx += 1; - arg.store_fn_arg(bcx, &mut llarg_idx, expr::get_dataptr(bcx, lltemp)); - meta.store_fn_arg(bcx, &mut llarg_idx, expr::get_meta(bcx, lltemp)); - } else { - // otherwise, arg is passed by value, so make a - // temporary and store it there - arg.store_fn_arg(bcx, &mut llarg_idx, lltemp); - } - lltemp - }) + let lltemp = bcx.with_block(|bcx| { + base::alloc_ty(bcx, arg_ty, &format!("arg{}", arg_index)) + }); + if common::type_is_fat_ptr(tcx, arg_ty) { + // we pass fat pointers as two words, but we want to + // represent them internally as a pointer to two words, + // so make an alloca to store them in. + let meta = &fcx.fn_ty.args[idx]; + idx += 1; + arg.store_fn_arg(bcx, &mut llarg_idx, get_dataptr(bcx, lltemp)); + meta.store_fn_arg(bcx, &mut llarg_idx, get_meta(bcx, lltemp)); + } else { + // otherwise, arg is passed by value, so make a + // temporary and store it there + arg.store_fn_arg(bcx, &mut llarg_idx, lltemp); + } + lltemp }; LvalueRef::new_sized(llval, LvalueTy::from_ty(arg_ty)) }).collect() diff --git a/src/librustc_trans/trans/mir/operand.rs b/src/librustc_trans/trans/mir/operand.rs index d1b2025fd4c..6df4502fbc8 100644 --- a/src/librustc_trans/trans/mir/operand.rs +++ b/src/librustc_trans/trans/mir/operand.rs @@ -19,6 +19,7 @@ use trans::glue; use std::fmt; +use super::lvalue::load_fat_ptr; use super::{MirContext, TempRef, drop}; /// The representation of a Rust value. The enum variant is in fact @@ -94,14 +95,10 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> { let val = match datum::appropriate_rvalue_mode(bcx.ccx(), ty) { datum::ByValue => { - bcx.with_block(|bcx| { - OperandValue::Immediate(base::load_ty(bcx, llval, ty)) - }) + OperandValue::Immediate(base::load_ty_builder(bcx, llval, ty)) } datum::ByRef if common::type_is_fat_ptr(bcx.tcx(), ty) => { - let (lldata, llextra) = bcx.with_block(|bcx| { - base::load_fat_ptr(bcx, llval, ty) - }); + let (lldata, llextra) = load_fat_ptr(bcx, llval); OperandValue::FatPtr(lldata, llextra) } datum::ByRef => OperandValue::Ref(llval) diff --git a/src/librustc_trans/trans/mir/rvalue.rs b/src/librustc_trans/trans/mir/rvalue.rs index e31083f05e1..b63af3489b3 100644 --- a/src/librustc_trans/trans/mir/rvalue.rs +++ b/src/librustc_trans/trans/mir/rvalue.rs @@ -21,7 +21,6 @@ use trans::callee::Callee; use trans::common::{self, BlockAndBuilder, Result}; use trans::debuginfo::DebugLoc; use trans::declare; -use trans::expr; use trans::adt; use trans::machine; use trans::type_::Type; @@ -32,7 +31,7 @@ use trans::Disr; use super::MirContext; use super::operand::{OperandRef, OperandValue}; -use super::lvalue::LvalueRef; +use super::lvalue::{LvalueRef, get_dataptr, get_meta}; impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> { pub fn trans_rvalue(&mut self, @@ -100,8 +99,8 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> { let tr_elem = self.trans_operand(&bcx, elem); let count = ConstVal::Integral(ConstInt::Usize(count.value)); let size = self.trans_constval(&bcx, &count, bcx.tcx().types.usize).immediate(); + let base = get_dataptr(&bcx, dest.llval); let bcx = bcx.map_block(|block| { - let base = expr::get_dataptr(block, dest.llval); tvec::iter_vec_raw(block, base, tr_elem.ty, size, |block, llslot, _| { self.store_operand_direct(block, llslot, tr_elem); block @@ -124,9 +123,8 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> { // Do not generate stores and GEPis for zero-sized fields. if !common::type_is_zero_size(bcx.ccx(), op.ty) { let val = adt::MaybeSizedValue::sized(dest.llval); - let lldest_i = bcx.with_block(|bcx| { - adt::trans_field_ptr(bcx, &repr, val, disr, i) - }); + let lldest_i = adt::trans_field_ptr_builder(&bcx, &repr, + val, disr, i); self.store_operand(&bcx, lldest_i, op); } self.set_operand_dropped(&bcx, operand); @@ -186,11 +184,8 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> { let llbase1 = bcx.gepi(llbase, &[from_start]); let adj = common::C_uint(ccx, from_start + from_end); let lllen1 = bcx.sub(lllen, adj); - let (lladdrdest, llmetadest) = bcx.with_block(|bcx| { - (expr::get_dataptr(bcx, dest.llval), expr::get_meta(bcx, dest.llval)) - }); - bcx.store(llbase1, lladdrdest); - bcx.store(lllen1, llmetadest); + bcx.store(llbase1, get_dataptr(&bcx, dest.llval)); + bcx.store(lllen1, get_meta(&bcx, dest.llval)); bcx }