Skip to content

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

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Sep 15, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion src/librustc_trans/glue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down Expand Up @@ -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();

Expand All @@ -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) =
Expand All @@ -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));
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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));
Expand Down
1 change: 1 addition & 0 deletions src/librustc_trans/intrinsic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand Down
24 changes: 21 additions & 3 deletions src/librustc_trans/mir/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
28 changes: 28 additions & 0 deletions src/test/run-pass/issue-35546.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// Regression test for #35546. Check that we are able to codegen
// this. Before we had problems because of the drop glue signature
// around dropping a trait object (specifically, when dropping the
// `value` field of `Node<Send>`).

struct Node<T: ?Sized + Send> {
next: Option<Box<Node<Send>>>,
value: T,
}

fn clear(head: &mut Option<Box<Node<Send>>>) {
match head.take() {
Some(node) => *head = node.next,
None => (),
}
}

fn main() {}