Skip to content

Commit

Permalink
Implement drop support (fixes rust-lang#11)
Browse files Browse the repository at this point in the history
  • Loading branch information
bjorn3 committed Sep 12, 2018
1 parent 770461f commit 5951898
Show file tree
Hide file tree
Showing 4 changed files with 143 additions and 21 deletions.
5 changes: 5 additions & 0 deletions examples/mini_core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,11 @@ unsafe fn allocate(size: usize, _align: usize) -> *mut u8 {
&mut MY_TINY_HEAP as *mut [u8; 16] as *mut u8
}

#[lang = "drop"]
pub trait Drop {
fn drop(&mut self);
}

pub mod intrinsics {
extern "rust-intrinsic" {
pub fn abort() -> !;
Expand Down
28 changes: 28 additions & 0 deletions examples/mini_core_hello_world.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,29 @@ impl SomeTrait for &'static str {
}
}

struct NoisyDrop {
text: &'static str,
inner: NoisyDropInner,
}

struct NoisyDropInner;

impl Drop for NoisyDrop {
fn drop(&mut self) {
unsafe {
puts(self.text as *const str as *const u8);
}
}
}

impl Drop for NoisyDropInner {
fn drop(&mut self) {
unsafe {
puts("Inner got dropped!\0" as *const str as *const u8);
}
}
}

#[lang = "start"]
fn start<T: Termination + 'static>(
main: fn() -> T,
Expand Down Expand Up @@ -91,4 +114,9 @@ fn main() {
panic(&("", "", 0, 0));
}
}

let _ = NoisyDrop {
text: "Outer got dropped!\0",
inner: NoisyDropInner,
};
}
50 changes: 34 additions & 16 deletions src/abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -433,7 +433,7 @@ pub fn codegen_fn_prelude<'a, 'tcx: 'a>(
.jump(*fx.ebb_map.get(&START_BLOCK).unwrap(), &[]);
}

pub fn codegen_call<'a, 'tcx: 'a>(
pub fn codegen_terminator_call<'a, 'tcx: 'a>(
fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
func: &Operand<'tcx>,
args: &[Operand<'tcx>],
Expand Down Expand Up @@ -466,19 +466,42 @@ pub fn codegen_call<'a, 'tcx: 'a>(

let destination = destination
.as_ref()
.map(|(place, bb)| (trans_place(fx, place), *bb));

if codegen_intrinsic_call(fx, fn_ty, sig, &args, destination) {
return;
.map(|&(ref place, bb)| (trans_place(fx, place), bb));

if !codegen_intrinsic_call(fx, fn_ty, &args, destination) {
codegen_call_inner(
fx,
Some(func),
fn_ty,
args,
destination.map(|(place, _)| place),
);

if let Some((_, dest)) = destination {
let ret_ebb = fx.get_ebb(dest);
fx.bcx.ins().jump(ret_ebb, &[]);
} else {
fx.bcx.ins().trap(TrapCode::User(!0));
}
}
}

pub fn codegen_call_inner<'a, 'tcx: 'a>(
fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
func: Option<&Operand<'tcx>>,
fn_ty: Ty<'tcx>,
args: Vec<CValue<'tcx>>,
ret_place: Option<CPlace<'tcx>>,
) {
let sig = ty_fn_sig(fx.tcx, fn_ty);

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

let output_pass_mode = get_pass_mode(fx.tcx, sig.abi, sig.output(), true);
let return_ptr = match output_pass_mode {
PassMode::NoPass => None,
PassMode::ByRef => match destination {
Some((place, _)) => Some(place.expect_addr()),
PassMode::ByRef => match ret_place {
Some(ret_place) => Some(ret_place.expect_addr()),
None => Some(fx.bcx.ins().iconst(fx.module.pointer_type(), 0)),
},
PassMode::ByVal(_) => None,
Expand All @@ -504,7 +527,7 @@ pub fn codegen_call<'a, 'tcx: 'a>(
Some(ptr)
} else {
func_ref = if instance.is_none() {
let func = trans_operand(fx, func);
let func = trans_operand(fx, func.expect("indirect call without func Operand"));
Some(func.load_value(fx))
} else {
None
Expand Down Expand Up @@ -534,19 +557,13 @@ pub fn codegen_call<'a, 'tcx: 'a>(
match output_pass_mode {
PassMode::NoPass => {}
PassMode::ByVal(_) => {
if let Some((ret_place, _)) = destination {
if let Some(ret_place) = ret_place {
let results = fx.bcx.inst_results(call_inst);
ret_place.write_cvalue(fx, CValue::ByVal(results[0], ret_layout));
}
}
PassMode::ByRef => {}
}
if let Some((_, dest)) = destination {
let ret_ebb = fx.get_ebb(dest);
fx.bcx.ins().jump(ret_ebb, &[]);
} else {
fx.bcx.ins().trap(TrapCode::User(!0));
}
}

pub fn codegen_return(fx: &mut FunctionCx<impl Backend>) {
Expand All @@ -565,11 +582,12 @@ pub fn codegen_return(fx: &mut FunctionCx<impl Backend>) {
fn codegen_intrinsic_call<'a, 'tcx: 'a>(
fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
fn_ty: Ty<'tcx>,
sig: FnSig<'tcx>,
args: &[CValue<'tcx>],
destination: Option<(CPlace<'tcx>, BasicBlock)>,
) -> bool {
if let ty::FnDef(def_id, substs) = fn_ty.sty {
let sig = ty_fn_sig(fx.tcx, fn_ty);

if sig.abi == Abi::RustIntrinsic {
let intrinsic = fx.tcx.item_name(def_id).as_str();
let intrinsic = &intrinsic[..];
Expand Down
81 changes: 76 additions & 5 deletions src/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -224,19 +224,90 @@ fn codegen_fn_content<'a, 'tcx: 'a>(fx: &mut FunctionCx<'a, 'tcx, impl Backend>)
destination,
cleanup: _,
} => {
crate::abi::codegen_call(fx, func, args, destination);
crate::abi::codegen_terminator_call(fx, func, args, destination);
}
TerminatorKind::Resume | TerminatorKind::Abort | TerminatorKind::Unreachable => {
fx.bcx.ins().trap(TrapCode::User(!0));
}
TerminatorKind::Yield { .. }
| TerminatorKind::FalseEdges { .. }
| TerminatorKind::FalseUnwind { .. } => {
| TerminatorKind::FalseUnwind { .. }
| TerminatorKind::DropAndReplace { .. } => {
bug!("shouldn't exist at trans {:?}", bb_data.terminator());
}
TerminatorKind::Drop { target, .. } | TerminatorKind::DropAndReplace { target, .. } => {
// TODO call drop impl
// unimplemented!("terminator {:?}", bb_data.terminator());
TerminatorKind::Drop {
location,
target,
unwind: _,
} => {
let ty = location.ty(fx.mir, fx.tcx).to_ty(fx.tcx);
let ty = fx.monomorphize(&ty);
let drop_fn = ::rustc_mir::monomorphize::resolve_drop_in_place(fx.tcx, ty);

if let ty::InstanceDef::DropGlue(_, None) = drop_fn.def {
// we don't actually need to drop anything
} else {
let drop_place = trans_place(fx, location);
let arg_place = CPlace::temp(
fx,
fx.tcx.mk_ref(
&ty::RegionKind::ReErased,
TypeAndMut {
ty,
mutbl: ::rustc::hir::Mutability::MutMutable,
},
),
);
drop_place.write_place_ref(fx, arg_place);
match ty.sty {
ty::Dynamic(..) => {
unimplemented!("Drop for trait object");
}
_ => {
let drop_fn_ty = drop_fn.ty(fx.tcx);
let arg_value = arg_place.to_cvalue(fx);
crate::abi::codegen_call_inner(
fx,
None,
drop_fn_ty,
vec![arg_value],
None,
);
}
}
/*
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, &[]);
}
Expand Down

0 comments on commit 5951898

Please sign in to comment.