Auto merge of #31307 - nagisa:mir-drop-terminator, r=nikomatsakis
The scope of these refactorings is a little bit bigger than the title implies. See each commit for details. I’m submitting this for nitpicking now (the first 4 commits), because I feel the basic idea/implementation is sound and should work. I will eventually expand this PR to cover the translator changes necessary for all this to work (+ tests), ~~and perhaps implement a dynamic dropping scheme while I’m at it as well.~~ r? @nikomatsakis
This commit is contained in:
commit
5147c1f2c0
25 changed files with 554 additions and 339 deletions
|
|
@ -18,10 +18,11 @@ use trans::base;
|
|||
use trans::build;
|
||||
use trans::common::{self, Block, LandingPad};
|
||||
use trans::debuginfo::DebugLoc;
|
||||
use trans::Disr;
|
||||
use trans::foreign;
|
||||
use trans::glue;
|
||||
use trans::type_of;
|
||||
use trans::type_::Type;
|
||||
use trans::Disr;
|
||||
|
||||
use super::MirContext;
|
||||
use super::operand::OperandValue::{FatPtr, Immediate, Ref};
|
||||
|
|
@ -94,7 +95,39 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
|
|||
base::build_return_block(bcx.fcx, bcx, return_ty, DebugLoc::None);
|
||||
}
|
||||
|
||||
mir::Terminator::Call { ref func, ref args, ref kind } => {
|
||||
mir::Terminator::Drop { ref value, target, unwind } => {
|
||||
let lvalue = self.trans_lvalue(bcx, value);
|
||||
let ty = lvalue.ty.to_ty(bcx.tcx());
|
||||
// Double check for necessity to drop
|
||||
if !glue::type_needs_drop(bcx.tcx(), ty) {
|
||||
build::Br(bcx, self.llblock(target), DebugLoc::None);
|
||||
return;
|
||||
}
|
||||
let drop_fn = glue::get_drop_glue(bcx.ccx(), ty);
|
||||
let drop_ty = glue::get_drop_glue_type(bcx.ccx(), ty);
|
||||
let llvalue = if drop_ty != ty {
|
||||
build::PointerCast(bcx, lvalue.llval,
|
||||
type_of::type_of(bcx.ccx(), drop_ty).ptr_to())
|
||||
} else {
|
||||
lvalue.llval
|
||||
};
|
||||
if let Some(unwind) = unwind {
|
||||
let uwbcx = self.bcx(unwind);
|
||||
let unwind = self.make_landing_pad(uwbcx);
|
||||
build::Invoke(bcx,
|
||||
drop_fn,
|
||||
&[llvalue],
|
||||
self.llblock(target),
|
||||
unwind.llbb,
|
||||
None,
|
||||
DebugLoc::None);
|
||||
} else {
|
||||
build::Call(bcx, drop_fn, &[llvalue], None, DebugLoc::None);
|
||||
build::Br(bcx, self.llblock(target), DebugLoc::None);
|
||||
}
|
||||
}
|
||||
|
||||
mir::Terminator::Call { ref func, ref args, ref destination, ref cleanup } => {
|
||||
// Create the callee. This will always be a fn ptr and hence a kind of scalar.
|
||||
let callee = self.trans_operand(bcx, func);
|
||||
let attrs = attributes::from_fn_type(bcx.ccx(), callee.ty);
|
||||
|
|
@ -115,7 +148,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
|
|||
};
|
||||
|
||||
// Prepare the return value destination
|
||||
let (ret_dest_ty, must_copy_dest) = if let Some(d) = kind.destination() {
|
||||
let (ret_dest_ty, must_copy_dest) = if let Some((ref d, _)) = *destination {
|
||||
let dest = self.trans_lvalue(bcx, d);
|
||||
let ret_ty = dest.ty.to_ty(bcx.tcx());
|
||||
if !is_foreign && type_of::return_uses_outptr(bcx.ccx(), ret_ty) {
|
||||
|
|
@ -144,9 +177,9 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
|
|||
}
|
||||
|
||||
// Many different ways to call a function handled here
|
||||
match (is_foreign, base::avoid_invoke(bcx), kind) {
|
||||
match (is_foreign, base::avoid_invoke(bcx), cleanup, destination) {
|
||||
// The two cases below are the only ones to use LLVM’s `invoke`.
|
||||
(false, false, &mir::CallKind::DivergingCleanup(cleanup)) => {
|
||||
(false, false, &Some(cleanup), &None) => {
|
||||
let cleanup = self.bcx(cleanup);
|
||||
let landingpad = self.make_landing_pad(cleanup);
|
||||
let unreachable_blk = self.unreachable_block();
|
||||
|
|
@ -158,14 +191,13 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
|
|||
Some(attrs),
|
||||
debugloc);
|
||||
},
|
||||
(false, false, &mir::CallKind::ConvergingCleanup { ref targets, .. }) => {
|
||||
let cleanup = self.bcx(targets.1);
|
||||
(false, false, &Some(cleanup), &Some((_, success))) => {
|
||||
let cleanup = self.bcx(cleanup);
|
||||
let landingpad = self.make_landing_pad(cleanup);
|
||||
let (target, postinvoke) = if must_copy_dest {
|
||||
(bcx.fcx.new_block("", None),
|
||||
Some(self.bcx(targets.0)))
|
||||
(bcx.fcx.new_block("", None), Some(self.bcx(success)))
|
||||
} else {
|
||||
(self.bcx(targets.0), None)
|
||||
(self.bcx(success), None)
|
||||
};
|
||||
let invokeret = build::Invoke(bcx,
|
||||
callee.immediate(),
|
||||
|
|
@ -205,19 +237,11 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
|
|||
build::Br(target, postinvoketarget.llbb, debugloc);
|
||||
}
|
||||
},
|
||||
(false, _, &mir::CallKind::DivergingCleanup(_)) |
|
||||
(false, _, &mir::CallKind::Diverging) => {
|
||||
(false, _, _, &None) => {
|
||||
build::Call(bcx, callee.immediate(), &llargs[..], Some(attrs), debugloc);
|
||||
build::Unreachable(bcx);
|
||||
}
|
||||
(false, _, k@&mir::CallKind::ConvergingCleanup { .. }) |
|
||||
(false, _, k@&mir::CallKind::Converging { .. }) => {
|
||||
// FIXME: Bug #20046
|
||||
let target = match *k {
|
||||
mir::CallKind::ConvergingCleanup { targets, .. } => targets.0,
|
||||
mir::CallKind::Converging { target, .. } => target,
|
||||
_ => unreachable!()
|
||||
};
|
||||
(false, _, _, &Some((_, target))) => {
|
||||
let llret = build::Call(bcx,
|
||||
callee.immediate(),
|
||||
&llargs[..],
|
||||
|
|
@ -231,7 +255,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
|
|||
build::Br(bcx, self.llblock(target), debugloc);
|
||||
}
|
||||
// Foreign functions
|
||||
(true, _, k) => {
|
||||
(true, _, _, destination) => {
|
||||
let (dest, _) = ret_dest_ty
|
||||
.expect("return destination is not set");
|
||||
bcx = foreign::trans_native_call(bcx,
|
||||
|
|
@ -241,13 +265,9 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
|
|||
&llargs[..],
|
||||
arg_tys,
|
||||
debugloc);
|
||||
match *k {
|
||||
mir::CallKind::ConvergingCleanup { targets, .. } =>
|
||||
build::Br(bcx, self.llblock(targets.0), debugloc),
|
||||
mir::CallKind::Converging { target, .. } =>
|
||||
build::Br(bcx, self.llblock(target), debugloc),
|
||||
_ => ()
|
||||
};
|
||||
if let Some((_, target)) = *destination {
|
||||
build::Br(bcx, self.llblock(target), debugloc);
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -82,13 +82,13 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
|
|||
constant: &mir::Constant<'tcx>)
|
||||
-> OperandRef<'tcx>
|
||||
{
|
||||
let ty = bcx.monomorphize(&constant.ty);
|
||||
match constant.literal {
|
||||
mir::Literal::Item { def_id, kind, substs } => {
|
||||
let substs = bcx.tcx().mk_substs(bcx.monomorphize(&substs));
|
||||
self.trans_item_ref(bcx, ty, kind, substs, def_id)
|
||||
self.trans_item_ref(bcx, constant.ty, kind, substs, def_id)
|
||||
}
|
||||
mir::Literal::Value { ref value } => {
|
||||
let ty = bcx.monomorphize(&constant.ty);
|
||||
self.trans_constval(bcx, value, ty)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
|
|||
assert!(lvalue.llextra != ptr::null_mut());
|
||||
lvalue.llextra
|
||||
}
|
||||
_ => bcx.sess().bug("unexpected type in get_base_and_len"),
|
||||
_ => bcx.sess().bug("unexpected type in lvalue_len"),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -195,8 +195,8 @@ fn arg_value_refs<'bcx, 'tcx>(bcx: Block<'bcx, 'tcx>,
|
|||
mod analyze;
|
||||
mod block;
|
||||
mod constant;
|
||||
mod lvalue;
|
||||
mod rvalue;
|
||||
mod operand;
|
||||
mod statement;
|
||||
mod did;
|
||||
mod lvalue;
|
||||
mod operand;
|
||||
mod rvalue;
|
||||
mod statement;
|
||||
|
|
|
|||
|
|
@ -8,11 +8,8 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use rustc::middle::ty::LvaluePreference;
|
||||
use rustc::mir::repr as mir;
|
||||
use trans::common::Block;
|
||||
use trans::debuginfo::DebugLoc;
|
||||
use trans::glue;
|
||||
|
||||
use super::MirContext;
|
||||
use super::TempRef;
|
||||
|
|
@ -51,20 +48,6 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
mir::StatementKind::Drop(mir::DropKind::Deep, ref lvalue) => {
|
||||
let tr_lvalue = self.trans_lvalue(bcx, lvalue);
|
||||
let ty = tr_lvalue.ty.to_ty(bcx.tcx());
|
||||
glue::drop_ty(bcx, tr_lvalue.llval, ty, DebugLoc::None)
|
||||
}
|
||||
|
||||
mir::StatementKind::Drop(mir::DropKind::Free, ref lvalue) => {
|
||||
let tr_lvalue = self.trans_lvalue(bcx, lvalue);
|
||||
let ty = tr_lvalue.ty.to_ty(bcx.tcx());
|
||||
let content_ty = ty.builtin_deref(true, LvaluePreference::NoPreference);
|
||||
let content_ty = content_ty.unwrap().ty;
|
||||
glue::trans_exchange_free_ty(bcx, tr_lvalue.llval, content_ty, DebugLoc::None)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue