diff --git a/src/librustc_trans/callee.rs b/src/librustc_trans/callee.rs index 982a8e9514c..2e09f7273f1 100644 --- a/src/librustc_trans/callee.rs +++ b/src/librustc_trans/callee.rs @@ -27,7 +27,6 @@ use base::*; use common::{ self, BlockAndBuilder, CrateContext, FunctionContext, SharedCrateContext }; -use cleanup::CleanupScope; use consts; use declare; use value::Value; @@ -351,7 +350,7 @@ fn trans_fn_once_adapter_shim<'a, 'tcx>( attributes::set_frame_pointer_elimination(ccx, lloncefn); let fcx = FunctionContext::new(ccx, lloncefn, fn_ty, None); - let bcx = fcx.init(false); + let mut bcx = fcx.init(false); // the first argument (`self`) will be the (by value) closure env. @@ -391,8 +390,39 @@ fn trans_fn_once_adapter_shim<'a, 'tcx>( // Call the by-ref closure body with `self` in a cleanup scope, // to drop `self` when the body returns, or in case it unwinds. let mut self_scope = fcx.schedule_drop_mem(llenv, closure_ty); - let bcx = trans_call_fn_once_adapter_shim( - bcx, callee, &llargs[self_idx..], dest, &mut self_scope); + let fn_ret = callee.ty.fn_ret(); + let fn_ty = callee.direct_fn_type(bcx.ccx(), &[]); + + let first_llarg = if fn_ty.ret.is_indirect() { + dest + } else { + None + }; + let llargs = first_llarg.into_iter().chain(llargs[self_idx..].iter().cloned()) + .collect::>(); + + let llfn = callee.reify(bcx.ccx()); + let llret; + if self_scope.is_some() && !bcx.sess().no_landing_pads() { + let normal_bcx = bcx.fcx().build_new_block("normal-return"); + let landing_pad = bcx.fcx().get_landing_pad(self_scope.as_mut().unwrap()); + + llret = bcx.invoke(llfn, &llargs[..], normal_bcx.llbb(), landing_pad, None); + bcx = normal_bcx; + } else { + llret = bcx.call(llfn, &llargs[..], None); + } + fn_ty.apply_attrs_callsite(llret); + + if !fn_ty.ret.is_indirect() { + if let Some(llretslot) = dest { + fn_ty.ret.store(&bcx, llret, llretslot); + } + } + + if fn_ret.0.is_never() { + bcx.unreachable(); + } fcx.trans_scope(&bcx, self_scope); fcx.finish(&bcx); @@ -706,67 +736,3 @@ fn trans_call_inner<'a, 'blk, 'tcx>(bcx: BlockAndBuilder<'blk, 'tcx>, (bcx, llret) } - -// This is a cleaned up version of trans_call_inner. -fn trans_call_fn_once_adapter_shim<'a, 'blk, 'tcx>( - bcx: BlockAndBuilder<'blk, 'tcx>, - callee: Callee<'tcx>, - args: &[ValueRef], - opt_llretslot: Option, - cleanup_scope: &mut Option>, -) -> BlockAndBuilder<'blk, 'tcx> { - let fn_ret = callee.ty.fn_ret(); - let fn_ty = callee.direct_fn_type(bcx.ccx(), &[]); - - // If there no destination, return must be direct, with no cast. - if opt_llretslot.is_none() { - assert!(!fn_ty.ret.is_indirect() && fn_ty.ret.cast.is_none()); - } - - let mut llargs = Vec::new(); - - if fn_ty.ret.is_indirect() { - let mut llretslot = opt_llretslot.unwrap(); - if let Some(ty) = fn_ty.ret.cast { - llretslot = bcx.pointercast(llretslot, ty.ptr_to()); - } - llargs.push(llretslot); - } - - llargs.extend_from_slice(args); - - let llfn = match callee.data { - Fn(f) => f, - _ => bug!("expected fn pointer callee, found {:?}", callee) - }; - - let _icx = push_ctxt("invoke_"); - let (llret, bcx) = if cleanup_scope.is_some() && !bcx.sess().no_landing_pads() { - let normal_bcx = bcx.fcx().build_new_block("normal-return"); - let landing_pad = bcx.fcx().get_landing_pad(cleanup_scope.as_mut().unwrap()); - - let llresult = bcx.invoke(llfn, &llargs[..], normal_bcx.llbb(), landing_pad, None); - (llresult, normal_bcx) - } else { - let llresult = bcx.call(llfn, &llargs[..], None); - (llresult, bcx) - }; - fn_ty.apply_attrs_callsite(llret); - - // If the function we just called does not use an outpointer, - // store the result into the rust outpointer. Cast the outpointer - // type to match because some ABIs will use a different type than - // the Rust type. e.g., a {u32,u32} struct could be returned as - // u64. - if !fn_ty.ret.is_indirect() { - if let Some(llretslot) = opt_llretslot { - fn_ty.ret.store(&bcx, llret, llretslot); - } - } - - if fn_ret.0.is_never() { - bcx.unreachable(); - } - - bcx -} diff --git a/src/librustc_trans/glue.rs b/src/librustc_trans/glue.rs index 549f1db22e7..a6e9af57aae 100644 --- a/src/librustc_trans/glue.rs +++ b/src/librustc_trans/glue.rs @@ -22,9 +22,7 @@ use rustc::traits; use rustc::ty::{self, AdtKind, Ty, TyCtxt, TypeFoldable}; use adt; use base::*; -use callee::{Callee, CalleeData}; -use cleanup::CleanupScope; -use meth; +use callee::Callee; use common::*; use machine::*; use monomorphize; @@ -224,7 +222,7 @@ pub fn implement_drop_glue<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fcx.finish(&bcx); } -fn trans_custom_dtor<'blk, 'tcx>(bcx: BlockAndBuilder<'blk, 'tcx>, +fn trans_custom_dtor<'blk, 'tcx>(mut bcx: BlockAndBuilder<'blk, 'tcx>, t: Ty<'tcx>, v0: ValueRef, shallow_drop: bool) @@ -272,60 +270,19 @@ fn trans_custom_dtor<'blk, 'tcx>(bcx: BlockAndBuilder<'blk, 'tcx>, }; let dtor_did = def.destructor().unwrap(); let callee = Callee::def(bcx.ccx(), dtor_did, vtbl.substs); - let bcx = trans_call_custom_dtor(bcx, callee, args, &mut contents_scope); - bcx.fcx().trans_scope(&bcx, contents_scope); - bcx -} - -// Inlined and simplified version of callee::trans_call_inner -fn trans_call_custom_dtor<'a, 'blk, 'tcx>( - bcx: BlockAndBuilder<'blk, 'tcx>, - callee: Callee<'tcx>, - args: &[ValueRef], - cleanup_scope: &mut Option>, -) -> BlockAndBuilder<'blk, 'tcx> { - let fn_ret = callee.ty.fn_ret(); let fn_ty = callee.direct_fn_type(bcx.ccx(), &[]); - - // Return must be direct, with no cast. - assert!(!fn_ty.ret.is_indirect() && fn_ty.ret.cast.is_none()); - - let mut llargs = Vec::new(); - - let llfn = match callee.data { - CalleeData::Virtual(idx) => { - llargs.push(args[0]); - - let fn_ptr = meth::get_virtual_method(&bcx, args[1], idx); - let llty = fn_ty.llvm_type(&bcx.ccx()).ptr_to(); - let llfn = bcx.pointercast(fn_ptr, llty); - llargs.extend_from_slice(&args[2..]); - llfn - } - CalleeData::Fn(f) => { - llargs.extend_from_slice(args); - f - } - _ => bug!("Expected virtual or fn pointer callee, found {:?}", callee) - }; - - let _icx = push_ctxt("invoke_"); - let (llret, bcx) = if cleanup_scope.is_some() && !bcx.sess().no_landing_pads() { + let llret; + if contents_scope.is_some() && !bcx.sess().no_landing_pads() { let normal_bcx = bcx.fcx().build_new_block("normal-return"); - let landing_pad = bcx.fcx().get_landing_pad(cleanup_scope.as_mut().unwrap()); + let landing_pad = bcx.fcx().get_landing_pad(contents_scope.as_mut().unwrap()); - let llresult = bcx.invoke(llfn, &llargs[..], normal_bcx.llbb(), landing_pad, None); - (llresult, normal_bcx) + llret = bcx.invoke(callee.reify(bcx.ccx()), args, normal_bcx.llbb(), landing_pad, None); + bcx = normal_bcx; } else { - let llresult = bcx.call(llfn, &llargs[..], None); - (llresult, bcx) - }; - fn_ty.apply_attrs_callsite(llret); - - if fn_ret.0.is_never() { - bcx.unreachable(); + llret = bcx.call(callee.reify(bcx.ccx()), args, None); } - + fn_ty.apply_attrs_callsite(llret); + bcx.fcx().trans_scope(&bcx, contents_scope); bcx }