invoke drop glue with a ptr to (data, meta)

This is done by creating a little space on the stack. Hokey, but it's
the simplest fix I can see.
This commit is contained in:
Niko Matsakis 2016-09-13 16:04:27 -04:00
parent c87ba3f122
commit b49a26ec6f
3 changed files with 30 additions and 4 deletions

View File

@ -296,6 +296,7 @@ fn trans_custom_dtor<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
sized_args = [v0];
&sized_args
} else {
// FIXME(#36457) -- we should pass unsized values to drop glue as two arguments
unsized_args = [
Load(bcx, get_dataptr(bcx, v0)),
Load(bcx, get_meta(bcx, v0))
@ -440,7 +441,9 @@ pub fn size_and_align_of_dst<'blk, 'tcx>(bcx: &BlockAndBuilder<'blk, 'tcx>,
}
}
fn make_drop_glue<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, v0: ValueRef, g: DropGlueKind<'tcx>)
fn make_drop_glue<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
v0: ValueRef,
g: DropGlueKind<'tcx>)
-> Block<'blk, 'tcx> {
let t = g.ty();
@ -463,6 +466,7 @@ fn make_drop_glue<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, v0: ValueRef, g: DropGlueK
let llval = get_dataptr(bcx, v0);
let llbox = Load(bcx, llval);
let bcx = drop_ty(bcx, v0, content_ty, DebugLoc::None);
// FIXME(#36457) -- we should pass unsized values to drop glue as two arguments
let info = get_meta(bcx, v0);
let info = Load(bcx, info);
let (llsize, llalign) =
@ -488,6 +492,7 @@ fn make_drop_glue<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, v0: ValueRef, g: DropGlueK
// No support in vtable for distinguishing destroying with
// versus without calling Drop::drop. Assert caller is
// okay with always calling the Drop impl, if any.
// FIXME(#36457) -- we should pass unsized values to drop glue as two arguments
assert!(!skip_dtor);
let data_ptr = get_dataptr(bcx, v0);
let vtable_ptr = Load(bcx, get_meta(bcx, v0));
@ -543,6 +548,7 @@ fn drop_structural_ty<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
let value = if type_is_sized(cx.tcx(), t) {
adt::MaybeSizedValue::sized(av)
} else {
// FIXME(#36457) -- we should pass unsized values as two arguments
let data = Load(cx, get_dataptr(cx, av));
let info = Load(cx, get_meta(cx, av));
adt::MaybeSizedValue::unsized_(data, info)
@ -586,6 +592,7 @@ fn drop_structural_ty<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
let val = if type_is_sized(cx.tcx(), field_ty) {
llfld_a
} else {
// FIXME(#36457) -- we should pass unsized values as two arguments
let scratch = alloc_ty(cx, field_ty, "__fat_ptr_iter");
Store(cx, llfld_a, get_dataptr(cx, scratch));
Store(cx, value.meta, get_meta(cx, scratch));

View File

@ -186,6 +186,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
let ptr = if is_sized {
llargs[0]
} else {
// FIXME(#36457) -- we should pass unsized values as two arguments
let scratch = alloc_ty(bcx, tp_ty, "drop");
call_lifetime_start(bcx, scratch);
Store(bcx, llargs[0], get_dataptr(bcx, scratch));

View File

@ -242,10 +242,28 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
let lvalue = self.trans_lvalue(&bcx, location);
let drop_fn = glue::get_drop_glue(bcx.ccx(), ty);
let drop_ty = glue::get_drop_glue_type(bcx.tcx(), ty);
let llvalue = if drop_ty != ty {
bcx.pointercast(lvalue.llval, type_of::type_of(bcx.ccx(), drop_ty).ptr_to())
let is_sized = common::type_is_sized(bcx.tcx(), ty);
let llvalue = if is_sized {
if drop_ty != ty {
bcx.pointercast(lvalue.llval, type_of::type_of(bcx.ccx(), drop_ty).ptr_to())
} else {
lvalue.llval
}
} else {
lvalue.llval
// FIXME(#36457) Currently drop glue takes sized
// values as a `*(data, meta)`, but elsewhere in
// MIR we pass `(data, meta)` as two separate
// arguments. It would be better to fix drop glue,
// but I am shooting for a quick fix to #35546
// here that can be cleanly backported to beta, so
// I want to avoid touching all of trans.
bcx.with_block(|bcx| {
let scratch = base::alloc_ty(bcx, ty, "drop");
base::call_lifetime_start(bcx, scratch);
build::Store(bcx, lvalue.llval, base::get_dataptr(bcx, scratch));
build::Store(bcx, lvalue.llextra, base::get_meta(bcx, scratch));
scratch
})
};
if let Some(unwind) = unwind {
bcx.invoke(drop_fn,