Skip to content

Commit 1eba7e5

Browse files
committed
Implement drop for trait objects
1 parent e506ff1 commit 1eba7e5

File tree

5 files changed

+67
-51
lines changed

5 files changed

+67
-51
lines changed

example/mini_core.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,12 @@ pub struct Box<T: ?Sized>(*mut T);
294294

295295
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Box<U>> for Box<T> {}
296296

297+
impl<T: ?Sized> Drop for Box<T> {
298+
fn drop(&mut self) {
299+
// drop is currently performed by compiler.
300+
}
301+
}
302+
297303
#[lang = "exchange_malloc"]
298304
// Make it available to jited mini_core_hello_world
299305
// FIXME remove next line when jit supports linking rlibs
@@ -302,6 +308,12 @@ unsafe fn allocate(size: usize, _align: usize) -> *mut u8 {
302308
libc::malloc(size)
303309
}
304310

311+
#[lang = "box_free"]
312+
#[inline(always)]
313+
unsafe fn box_free<T: ?Sized>(ptr: *mut T) {
314+
libc::free(ptr as *mut u8);
315+
}
316+
305317
#[lang = "drop"]
306318
pub trait Drop {
307319
fn drop(&mut self);
@@ -327,6 +339,7 @@ pub mod libc {
327339
extern "C" {
328340
pub fn puts(s: *const u8);
329341
pub fn malloc(size: usize) -> *mut u8;
342+
pub fn free(ptr: *mut u8);
330343
pub fn memcpy(dst: *mut u8, src: *const u8, size: usize);
331344
pub fn memmove(dst: *mut u8, src: *const u8, size: usize);
332345
pub fn strncpy(dst: *mut u8, src: *const u8, size: usize);

example/mini_core_hello_world.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,10 @@ impl Drop for NoisyDropInner {
6262
}
6363
}
6464

65+
impl SomeTrait for NoisyDrop {
66+
fn object_safe(&self) {}
67+
}
68+
6569
enum Ordering {
6670
Less = -1,
6771
Equal = 0,
@@ -152,10 +156,10 @@ fn main() {
152156
intrinsics::size_of_val(&MyDst([0u8; 4]) as &MyDst<[u8]>);
153157
}
154158

155-
let _ = NoisyDrop {
156-
text: "Outer got dropped!\0",
159+
let _ = box NoisyDrop {
160+
text: "Boxed outer got dropped!\0",
157161
inner: NoisyDropInner,
158-
};
162+
} as Box<SomeTrait>;
159163

160164
const FUNC_REF: Option<fn()> = Some(main);
161165
match FUNC_REF {

src/abi.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -671,6 +671,25 @@ pub fn codegen_call_inner<'a, 'tcx: 'a>(
671671
}
672672
}
673673

674+
pub fn codegen_drop<'a, 'tcx: 'a>(
675+
fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
676+
drop_place: CPlace<'tcx>,
677+
drop_fn_ty: Ty<'tcx>,
678+
) {
679+
let (ptr, vtable) = drop_place.to_addr_maybe_unsized(fx);
680+
let drop_fn = crate::vtable::drop_fn_of_obj(fx, vtable.unwrap());
681+
682+
let fn_sig = ty_fn_sig(fx.tcx, drop_fn_ty);
683+
684+
match get_pass_mode(fx.tcx, fn_sig.output(), true) {
685+
PassMode::NoPass => {},
686+
_ => unreachable!(),
687+
};
688+
689+
let sig = fx.bcx.import_signature(clif_sig_from_fn_sig(fx.tcx, fn_sig));
690+
fx.bcx.ins().call_indirect(sig, drop_fn, &[ptr]);
691+
}
692+
674693
pub fn codegen_return(fx: &mut FunctionCx<impl Backend>) {
675694
match get_pass_mode(fx.tcx, fx.return_type(), true) {
676695
PassMode::NoPass | PassMode::ByRef => {

src/base.rs

Lines changed: 15 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,8 @@ fn codegen_fn_content<'a, 'tcx: 'a>(fx: &mut FunctionCx<'a, 'tcx, impl Backend>)
242242
TerminatorKind::Yield { .. }
243243
| TerminatorKind::FalseEdges { .. }
244244
| TerminatorKind::FalseUnwind { .. }
245-
| TerminatorKind::DropAndReplace { .. } => {
245+
| TerminatorKind::DropAndReplace { .. }
246+
| TerminatorKind::GeneratorDrop => {
246247
bug!("shouldn't exist at trans {:?}", bb_data.terminator());
247248
}
248249
TerminatorKind::Drop {
@@ -258,23 +259,23 @@ fn codegen_fn_content<'a, 'tcx: 'a>(fx: &mut FunctionCx<'a, 'tcx, impl Backend>)
258259
// we don't actually need to drop anything
259260
} else {
260261
let drop_place = trans_place(fx, location);
261-
let arg_place = CPlace::new_stack_slot(
262-
fx,
263-
fx.tcx.mk_ref(
264-
&ty::RegionKind::ReErased,
265-
TypeAndMut {
266-
ty,
267-
mutbl: crate::rustc::hir::Mutability::MutMutable,
268-
},
269-
),
270-
);
271-
drop_place.write_place_ref(fx, arg_place);
262+
let drop_fn_ty = drop_fn.ty(fx.tcx);
272263
match ty.sty {
273264
ty::Dynamic(..) => {
274-
fx.tcx.sess.warn("Drop for trait object");
265+
crate::abi::codegen_drop(fx, drop_place, drop_fn_ty);
275266
}
276267
_ => {
277-
let drop_fn_ty = drop_fn.ty(fx.tcx);
268+
let arg_place = CPlace::new_stack_slot(
269+
fx,
270+
fx.tcx.mk_ref(
271+
&ty::RegionKind::ReErased,
272+
TypeAndMut {
273+
ty,
274+
mutbl: crate::rustc::hir::Mutability::MutMutable,
275+
},
276+
),
277+
);
278+
drop_place.write_place_ref(fx, arg_place);
278279
let arg_value = arg_place.to_cvalue(fx);
279280
crate::abi::codegen_call_inner(
280281
fx,
@@ -285,45 +286,11 @@ fn codegen_fn_content<'a, 'tcx: 'a>(fx: &mut FunctionCx<'a, 'tcx, impl Backend>)
285286
);
286287
}
287288
}
288-
/*
289-
let (args1, args2);
290-
/*let mut args = if let Some(llextra) = place.llextra {
291-
args2 = [place.llval, llextra];
292-
&args2[..]
293-
} else {
294-
args1 = [place.llval];
295-
&args1[..]
296-
};*/
297-
let (drop_fn, fn_ty) = match ty.sty {
298-
ty::Dynamic(..) => {
299-
let fn_ty = drop_fn.ty(bx.cx.tcx);
300-
let sig = common::ty_fn_sig(bx.cx, fn_ty);
301-
let sig = bx.tcx().normalize_erasing_late_bound_regions(
302-
ty::ParamEnv::reveal_all(),
303-
&sig,
304-
);
305-
let fn_ty = FnType::new_vtable(bx.cx, sig, &[]);
306-
let vtable = args[1];
307-
args = &args[..1];
308-
(meth::DESTRUCTOR.get_fn(&bx, vtable, &fn_ty), fn_ty)
309-
}
310-
_ => {
311-
let value = place.to_cvalue(fx);
312-
(callee::get_fn(bx.cx, drop_fn),
313-
FnType::of_instance(bx.cx, &drop_fn))
314-
}
315-
};
316-
do_call(self, bx, fn_ty, drop_fn, args,
317-
Some((ReturnDest::Nothing, target)),
318-
unwind);*/
319289
}
320290

321291
let target_ebb = fx.get_ebb(*target);
322292
fx.bcx.ins().jump(target_ebb, &[]);
323293
}
324-
TerminatorKind::GeneratorDrop => {
325-
unimplemented!("terminator GeneratorDrop");
326-
}
327294
};
328295
}
329296

src/vtable.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,19 @@ const DROP_FN_INDEX: usize = 0;
66
const SIZE_INDEX: usize = 1;
77
const ALIGN_INDEX: usize = 2;
88

9+
pub fn drop_fn_of_obj<'a, 'tcx: 'a>(
10+
fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
11+
vtable: Value,
12+
) -> Value {
13+
let usize_size = fx.layout_of(fx.tcx.types.usize).size.bytes() as usize;
14+
fx.bcx.ins().load(
15+
pointer_ty(fx.tcx),
16+
MemFlags::new(),
17+
vtable,
18+
(DROP_FN_INDEX * usize_size) as i32,
19+
)
20+
}
21+
922
pub fn size_of_obj<'a, 'tcx: 'a>(
1023
fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
1124
vtable: Value,

0 commit comments

Comments
 (0)