提交 d9277b16 编写于 作者: E Eduard Burtescu

trans: Make everything used from within at_start Builder-friendly.

上级 82fad1df
......@@ -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 @@ pub fn store(&self, b: &Builder, mut val: ValueRef, dst: ValueRef) {
}
}
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);
}
}
......
......@@ -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::<Vec<_>>();
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)
......
......@@ -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 @@ fn bind_args(&'blk self,
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 @@ fn bind_args(&'blk self,
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);
......
......@@ -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
......
......@@ -688,6 +688,10 @@ pub fn at_start<F, R>(&self, f: F) -> R
// 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()
}
......
......@@ -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<ZeroSizeType>` does not allocate.
let needs_free = ICmp(bcx,
......
......@@ -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))
......
......@@ -26,7 +26,7 @@
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 @@ fn trans_arguments_untupled(&mut self,
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.
......
......@@ -12,8 +12,10 @@
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 @@ pub fn alloca<'bcx>(bcx: &BlockAndBuilder<'bcx, '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 @@ pub fn trans_lvalue(&mut self,
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 @@ pub fn trans_lvalue(&mut self,
} 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 {
......
......@@ -14,14 +14,12 @@
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()
......
......@@ -19,6 +19,7 @@
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 @@ pub fn trans_load(&mut self,
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)
......
......@@ -21,7 +21,6 @@
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 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 @@ pub fn trans_rvalue(&mut self,
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 @@ pub fn trans_rvalue(&mut self,
// 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 @@ pub fn trans_rvalue(&mut self,
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
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册