Skip to content

Commit 5951898

Browse files
committed
Implement drop support (fixes rust-lang#11)
1 parent 770461f commit 5951898

File tree

4 files changed

+143
-21
lines changed

4 files changed

+143
-21
lines changed

examples/mini_core.rs

+5
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,11 @@ unsafe fn allocate(size: usize, _align: usize) -> *mut u8 {
197197
&mut MY_TINY_HEAP as *mut [u8; 16] as *mut u8
198198
}
199199

200+
#[lang = "drop"]
201+
pub trait Drop {
202+
fn drop(&mut self);
203+
}
204+
200205
pub mod intrinsics {
201206
extern "rust-intrinsic" {
202207
pub fn abort() -> !;

examples/mini_core_hello_world.rs

+28
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,29 @@ impl SomeTrait for &'static str {
4949
}
5050
}
5151

52+
struct NoisyDrop {
53+
text: &'static str,
54+
inner: NoisyDropInner,
55+
}
56+
57+
struct NoisyDropInner;
58+
59+
impl Drop for NoisyDrop {
60+
fn drop(&mut self) {
61+
unsafe {
62+
puts(self.text as *const str as *const u8);
63+
}
64+
}
65+
}
66+
67+
impl Drop for NoisyDropInner {
68+
fn drop(&mut self) {
69+
unsafe {
70+
puts("Inner got dropped!\0" as *const str as *const u8);
71+
}
72+
}
73+
}
74+
5275
#[lang = "start"]
5376
fn start<T: Termination + 'static>(
5477
main: fn() -> T,
@@ -91,4 +114,9 @@ fn main() {
91114
panic(&("", "", 0, 0));
92115
}
93116
}
117+
118+
let _ = NoisyDrop {
119+
text: "Outer got dropped!\0",
120+
inner: NoisyDropInner,
121+
};
94122
}

src/abi.rs

+34-16
Original file line numberDiff line numberDiff line change
@@ -433,7 +433,7 @@ pub fn codegen_fn_prelude<'a, 'tcx: 'a>(
433433
.jump(*fx.ebb_map.get(&START_BLOCK).unwrap(), &[]);
434434
}
435435

436-
pub fn codegen_call<'a, 'tcx: 'a>(
436+
pub fn codegen_terminator_call<'a, 'tcx: 'a>(
437437
fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
438438
func: &Operand<'tcx>,
439439
args: &[Operand<'tcx>],
@@ -466,19 +466,42 @@ pub fn codegen_call<'a, 'tcx: 'a>(
466466

467467
let destination = destination
468468
.as_ref()
469-
.map(|(place, bb)| (trans_place(fx, place), *bb));
470-
471-
if codegen_intrinsic_call(fx, fn_ty, sig, &args, destination) {
472-
return;
469+
.map(|&(ref place, bb)| (trans_place(fx, place), bb));
470+
471+
if !codegen_intrinsic_call(fx, fn_ty, &args, destination) {
472+
codegen_call_inner(
473+
fx,
474+
Some(func),
475+
fn_ty,
476+
args,
477+
destination.map(|(place, _)| place),
478+
);
479+
480+
if let Some((_, dest)) = destination {
481+
let ret_ebb = fx.get_ebb(dest);
482+
fx.bcx.ins().jump(ret_ebb, &[]);
483+
} else {
484+
fx.bcx.ins().trap(TrapCode::User(!0));
485+
}
473486
}
487+
}
488+
489+
pub fn codegen_call_inner<'a, 'tcx: 'a>(
490+
fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
491+
func: Option<&Operand<'tcx>>,
492+
fn_ty: Ty<'tcx>,
493+
args: Vec<CValue<'tcx>>,
494+
ret_place: Option<CPlace<'tcx>>,
495+
) {
496+
let sig = ty_fn_sig(fx.tcx, fn_ty);
474497

475498
let ret_layout = fx.layout_of(sig.output());
476499

477500
let output_pass_mode = get_pass_mode(fx.tcx, sig.abi, sig.output(), true);
478501
let return_ptr = match output_pass_mode {
479502
PassMode::NoPass => None,
480-
PassMode::ByRef => match destination {
481-
Some((place, _)) => Some(place.expect_addr()),
503+
PassMode::ByRef => match ret_place {
504+
Some(ret_place) => Some(ret_place.expect_addr()),
482505
None => Some(fx.bcx.ins().iconst(fx.module.pointer_type(), 0)),
483506
},
484507
PassMode::ByVal(_) => None,
@@ -504,7 +527,7 @@ pub fn codegen_call<'a, 'tcx: 'a>(
504527
Some(ptr)
505528
} else {
506529
func_ref = if instance.is_none() {
507-
let func = trans_operand(fx, func);
530+
let func = trans_operand(fx, func.expect("indirect call without func Operand"));
508531
Some(func.load_value(fx))
509532
} else {
510533
None
@@ -534,19 +557,13 @@ pub fn codegen_call<'a, 'tcx: 'a>(
534557
match output_pass_mode {
535558
PassMode::NoPass => {}
536559
PassMode::ByVal(_) => {
537-
if let Some((ret_place, _)) = destination {
560+
if let Some(ret_place) = ret_place {
538561
let results = fx.bcx.inst_results(call_inst);
539562
ret_place.write_cvalue(fx, CValue::ByVal(results[0], ret_layout));
540563
}
541564
}
542565
PassMode::ByRef => {}
543566
}
544-
if let Some((_, dest)) = destination {
545-
let ret_ebb = fx.get_ebb(dest);
546-
fx.bcx.ins().jump(ret_ebb, &[]);
547-
} else {
548-
fx.bcx.ins().trap(TrapCode::User(!0));
549-
}
550567
}
551568

552569
pub fn codegen_return(fx: &mut FunctionCx<impl Backend>) {
@@ -565,11 +582,12 @@ pub fn codegen_return(fx: &mut FunctionCx<impl Backend>) {
565582
fn codegen_intrinsic_call<'a, 'tcx: 'a>(
566583
fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
567584
fn_ty: Ty<'tcx>,
568-
sig: FnSig<'tcx>,
569585
args: &[CValue<'tcx>],
570586
destination: Option<(CPlace<'tcx>, BasicBlock)>,
571587
) -> bool {
572588
if let ty::FnDef(def_id, substs) = fn_ty.sty {
589+
let sig = ty_fn_sig(fx.tcx, fn_ty);
590+
573591
if sig.abi == Abi::RustIntrinsic {
574592
let intrinsic = fx.tcx.item_name(def_id).as_str();
575593
let intrinsic = &intrinsic[..];

src/base.rs

+76-5
Original file line numberDiff line numberDiff line change
@@ -224,19 +224,90 @@ fn codegen_fn_content<'a, 'tcx: 'a>(fx: &mut FunctionCx<'a, 'tcx, impl Backend>)
224224
destination,
225225
cleanup: _,
226226
} => {
227-
crate::abi::codegen_call(fx, func, args, destination);
227+
crate::abi::codegen_terminator_call(fx, func, args, destination);
228228
}
229229
TerminatorKind::Resume | TerminatorKind::Abort | TerminatorKind::Unreachable => {
230230
fx.bcx.ins().trap(TrapCode::User(!0));
231231
}
232232
TerminatorKind::Yield { .. }
233233
| TerminatorKind::FalseEdges { .. }
234-
| TerminatorKind::FalseUnwind { .. } => {
234+
| TerminatorKind::FalseUnwind { .. }
235+
| TerminatorKind::DropAndReplace { .. } => {
235236
bug!("shouldn't exist at trans {:?}", bb_data.terminator());
236237
}
237-
TerminatorKind::Drop { target, .. } | TerminatorKind::DropAndReplace { target, .. } => {
238-
// TODO call drop impl
239-
// unimplemented!("terminator {:?}", bb_data.terminator());
238+
TerminatorKind::Drop {
239+
location,
240+
target,
241+
unwind: _,
242+
} => {
243+
let ty = location.ty(fx.mir, fx.tcx).to_ty(fx.tcx);
244+
let ty = fx.monomorphize(&ty);
245+
let drop_fn = ::rustc_mir::monomorphize::resolve_drop_in_place(fx.tcx, ty);
246+
247+
if let ty::InstanceDef::DropGlue(_, None) = drop_fn.def {
248+
// we don't actually need to drop anything
249+
} else {
250+
let drop_place = trans_place(fx, location);
251+
let arg_place = CPlace::temp(
252+
fx,
253+
fx.tcx.mk_ref(
254+
&ty::RegionKind::ReErased,
255+
TypeAndMut {
256+
ty,
257+
mutbl: ::rustc::hir::Mutability::MutMutable,
258+
},
259+
),
260+
);
261+
drop_place.write_place_ref(fx, arg_place);
262+
match ty.sty {
263+
ty::Dynamic(..) => {
264+
unimplemented!("Drop for trait object");
265+
}
266+
_ => {
267+
let drop_fn_ty = drop_fn.ty(fx.tcx);
268+
let arg_value = arg_place.to_cvalue(fx);
269+
crate::abi::codegen_call_inner(
270+
fx,
271+
None,
272+
drop_fn_ty,
273+
vec![arg_value],
274+
None,
275+
);
276+
}
277+
}
278+
/*
279+
let (args1, args2);
280+
/*let mut args = if let Some(llextra) = place.llextra {
281+
args2 = [place.llval, llextra];
282+
&args2[..]
283+
} else {
284+
args1 = [place.llval];
285+
&args1[..]
286+
};*/
287+
let (drop_fn, fn_ty) = match ty.sty {
288+
ty::Dynamic(..) => {
289+
let fn_ty = drop_fn.ty(bx.cx.tcx);
290+
let sig = common::ty_fn_sig(bx.cx, fn_ty);
291+
let sig = bx.tcx().normalize_erasing_late_bound_regions(
292+
ty::ParamEnv::reveal_all(),
293+
&sig,
294+
);
295+
let fn_ty = FnType::new_vtable(bx.cx, sig, &[]);
296+
let vtable = args[1];
297+
args = &args[..1];
298+
(meth::DESTRUCTOR.get_fn(&bx, vtable, &fn_ty), fn_ty)
299+
}
300+
_ => {
301+
let value = place.to_cvalue(fx);
302+
(callee::get_fn(bx.cx, drop_fn),
303+
FnType::of_instance(bx.cx, &drop_fn))
304+
}
305+
};
306+
do_call(self, bx, fn_ty, drop_fn, args,
307+
Some((ReturnDest::Nothing, target)),
308+
unwind);*/
309+
}
310+
240311
let target_ebb = fx.get_ebb(*target);
241312
fx.bcx.ins().jump(target_ebb, &[]);
242313
}

0 commit comments

Comments
 (0)