Inline and simplify Callee::call duplicates.
This commit is contained in:
parent
cd57bbe27a
commit
3265afa08f
@ -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::<Vec<_>>();
|
||||
|
||||
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<ValueRef>,
|
||||
cleanup_scope: &mut Option<CleanupScope<'tcx>>,
|
||||
) -> 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
|
||||
}
|
||||
|
@ -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<CleanupScope<'tcx>>,
|
||||
) -> 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
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user