Implement drop support (fixes #11)
This commit is contained in:
parent
770461f57d
commit
59518987ed
4 changed files with 142 additions and 20 deletions
|
@ -197,6 +197,11 @@ unsafe fn allocate(size: usize, _align: usize) -> *mut u8 {
|
||||||
&mut MY_TINY_HEAP as *mut [u8; 16] as *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 {
|
pub mod intrinsics {
|
||||||
extern "rust-intrinsic" {
|
extern "rust-intrinsic" {
|
||||||
pub fn abort() -> !;
|
pub fn abort() -> !;
|
||||||
|
|
|
@ -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"]
|
#[lang = "start"]
|
||||||
fn start<T: Termination + 'static>(
|
fn start<T: Termination + 'static>(
|
||||||
main: fn() -> T,
|
main: fn() -> T,
|
||||||
|
@ -91,4 +114,9 @@ fn main() {
|
||||||
panic(&("", "", 0, 0));
|
panic(&("", "", 0, 0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let _ = NoisyDrop {
|
||||||
|
text: "Outer got dropped!\0",
|
||||||
|
inner: NoisyDropInner,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
48
src/abi.rs
48
src/abi.rs
|
@ -433,7 +433,7 @@ pub fn codegen_fn_prelude<'a, 'tcx: 'a>(
|
||||||
.jump(*fx.ebb_map.get(&START_BLOCK).unwrap(), &[]);
|
.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>,
|
fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
|
||||||
func: &Operand<'tcx>,
|
func: &Operand<'tcx>,
|
||||||
args: &[Operand<'tcx>],
|
args: &[Operand<'tcx>],
|
||||||
|
@ -466,19 +466,42 @@ pub fn codegen_call<'a, 'tcx: 'a>(
|
||||||
|
|
||||||
let destination = destination
|
let destination = destination
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|(place, bb)| (trans_place(fx, place), *bb));
|
.map(|&(ref place, bb)| (trans_place(fx, place), bb));
|
||||||
|
|
||||||
if codegen_intrinsic_call(fx, fn_ty, sig, &args, destination) {
|
if !codegen_intrinsic_call(fx, fn_ty, &args, destination) {
|
||||||
return;
|
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 ret_layout = fx.layout_of(sig.output());
|
||||||
|
|
||||||
let output_pass_mode = get_pass_mode(fx.tcx, sig.abi, sig.output(), true);
|
let output_pass_mode = get_pass_mode(fx.tcx, sig.abi, sig.output(), true);
|
||||||
let return_ptr = match output_pass_mode {
|
let return_ptr = match output_pass_mode {
|
||||||
PassMode::NoPass => None,
|
PassMode::NoPass => None,
|
||||||
PassMode::ByRef => match destination {
|
PassMode::ByRef => match ret_place {
|
||||||
Some((place, _)) => Some(place.expect_addr()),
|
Some(ret_place) => Some(ret_place.expect_addr()),
|
||||||
None => Some(fx.bcx.ins().iconst(fx.module.pointer_type(), 0)),
|
None => Some(fx.bcx.ins().iconst(fx.module.pointer_type(), 0)),
|
||||||
},
|
},
|
||||||
PassMode::ByVal(_) => None,
|
PassMode::ByVal(_) => None,
|
||||||
|
@ -504,7 +527,7 @@ pub fn codegen_call<'a, 'tcx: 'a>(
|
||||||
Some(ptr)
|
Some(ptr)
|
||||||
} else {
|
} else {
|
||||||
func_ref = if instance.is_none() {
|
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))
|
Some(func.load_value(fx))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
@ -534,19 +557,13 @@ pub fn codegen_call<'a, 'tcx: 'a>(
|
||||||
match output_pass_mode {
|
match output_pass_mode {
|
||||||
PassMode::NoPass => {}
|
PassMode::NoPass => {}
|
||||||
PassMode::ByVal(_) => {
|
PassMode::ByVal(_) => {
|
||||||
if let Some((ret_place, _)) = destination {
|
if let Some(ret_place) = ret_place {
|
||||||
let results = fx.bcx.inst_results(call_inst);
|
let results = fx.bcx.inst_results(call_inst);
|
||||||
ret_place.write_cvalue(fx, CValue::ByVal(results[0], ret_layout));
|
ret_place.write_cvalue(fx, CValue::ByVal(results[0], ret_layout));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PassMode::ByRef => {}
|
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>) {
|
pub fn codegen_return(fx: &mut FunctionCx<impl Backend>) {
|
||||||
|
@ -565,11 +582,12 @@ pub fn codegen_return(fx: &mut FunctionCx<impl Backend>) {
|
||||||
fn codegen_intrinsic_call<'a, 'tcx: 'a>(
|
fn codegen_intrinsic_call<'a, 'tcx: 'a>(
|
||||||
fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
|
fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
|
||||||
fn_ty: Ty<'tcx>,
|
fn_ty: Ty<'tcx>,
|
||||||
sig: FnSig<'tcx>,
|
|
||||||
args: &[CValue<'tcx>],
|
args: &[CValue<'tcx>],
|
||||||
destination: Option<(CPlace<'tcx>, BasicBlock)>,
|
destination: Option<(CPlace<'tcx>, BasicBlock)>,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
if let ty::FnDef(def_id, substs) = fn_ty.sty {
|
if let ty::FnDef(def_id, substs) = fn_ty.sty {
|
||||||
|
let sig = ty_fn_sig(fx.tcx, fn_ty);
|
||||||
|
|
||||||
if sig.abi == Abi::RustIntrinsic {
|
if sig.abi == Abi::RustIntrinsic {
|
||||||
let intrinsic = fx.tcx.item_name(def_id).as_str();
|
let intrinsic = fx.tcx.item_name(def_id).as_str();
|
||||||
let intrinsic = &intrinsic[..];
|
let intrinsic = &intrinsic[..];
|
||||||
|
|
81
src/base.rs
81
src/base.rs
|
@ -224,19 +224,90 @@ fn codegen_fn_content<'a, 'tcx: 'a>(fx: &mut FunctionCx<'a, 'tcx, impl Backend>)
|
||||||
destination,
|
destination,
|
||||||
cleanup: _,
|
cleanup: _,
|
||||||
} => {
|
} => {
|
||||||
crate::abi::codegen_call(fx, func, args, destination);
|
crate::abi::codegen_terminator_call(fx, func, args, destination);
|
||||||
}
|
}
|
||||||
TerminatorKind::Resume | TerminatorKind::Abort | TerminatorKind::Unreachable => {
|
TerminatorKind::Resume | TerminatorKind::Abort | TerminatorKind::Unreachable => {
|
||||||
fx.bcx.ins().trap(TrapCode::User(!0));
|
fx.bcx.ins().trap(TrapCode::User(!0));
|
||||||
}
|
}
|
||||||
TerminatorKind::Yield { .. }
|
TerminatorKind::Yield { .. }
|
||||||
| TerminatorKind::FalseEdges { .. }
|
| TerminatorKind::FalseEdges { .. }
|
||||||
| TerminatorKind::FalseUnwind { .. } => {
|
| TerminatorKind::FalseUnwind { .. }
|
||||||
|
| TerminatorKind::DropAndReplace { .. } => {
|
||||||
bug!("shouldn't exist at trans {:?}", bb_data.terminator());
|
bug!("shouldn't exist at trans {:?}", bb_data.terminator());
|
||||||
}
|
}
|
||||||
TerminatorKind::Drop { target, .. } | TerminatorKind::DropAndReplace { target, .. } => {
|
TerminatorKind::Drop {
|
||||||
// TODO call drop impl
|
location,
|
||||||
// unimplemented!("terminator {:?}", bb_data.terminator());
|
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);
|
let target_ebb = fx.get_ebb(*target);
|
||||||
fx.bcx.ins().jump(target_ebb, &[]);
|
fx.bcx.ins().jump(target_ebb, &[]);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue