Implement drop for trait objects

This commit is contained in:
bjorn3 2019-02-07 20:45:15 +01:00
parent e506ff1ddb
commit 1eba7e5f5e
5 changed files with 67 additions and 51 deletions

View file

@ -294,6 +294,12 @@ pub struct Box<T: ?Sized>(*mut T);
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Box<U>> for Box<T> {}
impl<T: ?Sized> Drop for Box<T> {
fn drop(&mut self) {
// drop is currently performed by compiler.
}
}
#[lang = "exchange_malloc"]
// Make it available to jited mini_core_hello_world
// FIXME remove next line when jit supports linking rlibs
@ -302,6 +308,12 @@ unsafe fn allocate(size: usize, _align: usize) -> *mut u8 {
libc::malloc(size)
}
#[lang = "box_free"]
#[inline(always)]
unsafe fn box_free<T: ?Sized>(ptr: *mut T) {
libc::free(ptr as *mut u8);
}
#[lang = "drop"]
pub trait Drop {
fn drop(&mut self);
@ -327,6 +339,7 @@ pub mod libc {
extern "C" {
pub fn puts(s: *const u8);
pub fn malloc(size: usize) -> *mut u8;
pub fn free(ptr: *mut u8);
pub fn memcpy(dst: *mut u8, src: *const u8, size: usize);
pub fn memmove(dst: *mut u8, src: *const u8, size: usize);
pub fn strncpy(dst: *mut u8, src: *const u8, size: usize);

View file

@ -62,6 +62,10 @@ impl Drop for NoisyDropInner {
}
}
impl SomeTrait for NoisyDrop {
fn object_safe(&self) {}
}
enum Ordering {
Less = -1,
Equal = 0,
@ -152,10 +156,10 @@ fn main() {
intrinsics::size_of_val(&MyDst([0u8; 4]) as &MyDst<[u8]>);
}
let _ = NoisyDrop {
text: "Outer got dropped!\0",
let _ = box NoisyDrop {
text: "Boxed outer got dropped!\0",
inner: NoisyDropInner,
};
} as Box<SomeTrait>;
const FUNC_REF: Option<fn()> = Some(main);
match FUNC_REF {

View file

@ -671,6 +671,25 @@ pub fn codegen_call_inner<'a, 'tcx: 'a>(
}
}
pub fn codegen_drop<'a, 'tcx: 'a>(
fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
drop_place: CPlace<'tcx>,
drop_fn_ty: Ty<'tcx>,
) {
let (ptr, vtable) = drop_place.to_addr_maybe_unsized(fx);
let drop_fn = crate::vtable::drop_fn_of_obj(fx, vtable.unwrap());
let fn_sig = ty_fn_sig(fx.tcx, drop_fn_ty);
match get_pass_mode(fx.tcx, fn_sig.output(), true) {
PassMode::NoPass => {},
_ => unreachable!(),
};
let sig = fx.bcx.import_signature(clif_sig_from_fn_sig(fx.tcx, fn_sig));
fx.bcx.ins().call_indirect(sig, drop_fn, &[ptr]);
}
pub fn codegen_return(fx: &mut FunctionCx<impl Backend>) {
match get_pass_mode(fx.tcx, fx.return_type(), true) {
PassMode::NoPass | PassMode::ByRef => {

View file

@ -242,7 +242,8 @@ fn codegen_fn_content<'a, 'tcx: 'a>(fx: &mut FunctionCx<'a, 'tcx, impl Backend>)
TerminatorKind::Yield { .. }
| TerminatorKind::FalseEdges { .. }
| TerminatorKind::FalseUnwind { .. }
| TerminatorKind::DropAndReplace { .. } => {
| TerminatorKind::DropAndReplace { .. }
| TerminatorKind::GeneratorDrop => {
bug!("shouldn't exist at trans {:?}", bb_data.terminator());
}
TerminatorKind::Drop {
@ -258,23 +259,23 @@ fn codegen_fn_content<'a, 'tcx: 'a>(fx: &mut FunctionCx<'a, 'tcx, impl Backend>)
// we don't actually need to drop anything
} else {
let drop_place = trans_place(fx, location);
let arg_place = CPlace::new_stack_slot(
fx,
fx.tcx.mk_ref(
&ty::RegionKind::ReErased,
TypeAndMut {
ty,
mutbl: crate::rustc::hir::Mutability::MutMutable,
},
),
);
drop_place.write_place_ref(fx, arg_place);
let drop_fn_ty = drop_fn.ty(fx.tcx);
match ty.sty {
ty::Dynamic(..) => {
fx.tcx.sess.warn("Drop for trait object");
crate::abi::codegen_drop(fx, drop_place, drop_fn_ty);
}
_ => {
let drop_fn_ty = drop_fn.ty(fx.tcx);
let arg_place = CPlace::new_stack_slot(
fx,
fx.tcx.mk_ref(
&ty::RegionKind::ReErased,
TypeAndMut {
ty,
mutbl: crate::rustc::hir::Mutability::MutMutable,
},
),
);
drop_place.write_place_ref(fx, arg_place);
let arg_value = arg_place.to_cvalue(fx);
crate::abi::codegen_call_inner(
fx,
@ -285,45 +286,11 @@ fn codegen_fn_content<'a, 'tcx: 'a>(fx: &mut FunctionCx<'a, 'tcx, impl Backend>)
);
}
}
/*
let (args1, args2);
/*let mut args = if let Some(llextra) = place.llextra {
args2 = [place.llval, llextra];
&args2[..]
} else {
args1 = [place.llval];
&args1[..]
};*/
let (drop_fn, fn_ty) = match ty.sty {
ty::Dynamic(..) => {
let fn_ty = drop_fn.ty(bx.cx.tcx);
let sig = common::ty_fn_sig(bx.cx, fn_ty);
let sig = bx.tcx().normalize_erasing_late_bound_regions(
ty::ParamEnv::reveal_all(),
&sig,
);
let fn_ty = FnType::new_vtable(bx.cx, sig, &[]);
let vtable = args[1];
args = &args[..1];
(meth::DESTRUCTOR.get_fn(&bx, vtable, &fn_ty), fn_ty)
}
_ => {
let value = place.to_cvalue(fx);
(callee::get_fn(bx.cx, drop_fn),
FnType::of_instance(bx.cx, &drop_fn))
}
};
do_call(self, bx, fn_ty, drop_fn, args,
Some((ReturnDest::Nothing, target)),
unwind);*/
}
let target_ebb = fx.get_ebb(*target);
fx.bcx.ins().jump(target_ebb, &[]);
}
TerminatorKind::GeneratorDrop => {
unimplemented!("terminator GeneratorDrop");
}
};
}

View file

@ -6,6 +6,19 @@ const DROP_FN_INDEX: usize = 0;
const SIZE_INDEX: usize = 1;
const ALIGN_INDEX: usize = 2;
pub fn drop_fn_of_obj<'a, 'tcx: 'a>(
fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
vtable: Value,
) -> Value {
let usize_size = fx.layout_of(fx.tcx.types.usize).size.bytes() as usize;
fx.bcx.ins().load(
pointer_ty(fx.tcx),
MemFlags::new(),
vtable,
(DROP_FN_INDEX * usize_size) as i32,
)
}
pub fn size_of_obj<'a, 'tcx: 'a>(
fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
vtable: Value,