trans: Make everything used from within at_start Builder-friendly.
This commit is contained in:
parent
82fad1dfc7
commit
d9277b163c
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 @@ 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);
|
||||
|
@ -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 @@ 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()
|
||||
}
|
||||
|
@ -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::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.
|
||||
|
@ -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 {
|
||||
|
@ -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()
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user