Implement drop for trait objects
This commit is contained in:
parent
e506ff1ddb
commit
1eba7e5f5e
5 changed files with 67 additions and 51 deletions
|
@ -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);
|
||||
|
|
|
@ -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 {
|
||||
|
|
19
src/abi.rs
19
src/abi.rs
|
@ -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 => {
|
||||
|
|
63
src/base.rs
63
src/base.rs
|
@ -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");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Add table
Reference in a new issue