mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 16:24:46 +00:00
Inline and cleanup build_return_block
This commit is contained in:
parent
515d14f094
commit
97a2096e5e
@ -564,68 +564,6 @@ pub fn alloc_ty<'a, 'tcx>(bcx: &BlockAndBuilder<'a, 'tcx>, ty: Ty<'tcx>, name: &
|
||||
bcx.fcx().alloca(type_of::type_of(bcx.ccx(), ty), name)
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> FunctionContext<'a, 'tcx> {
|
||||
// Builds the return block for a function.
|
||||
pub fn build_return_block(&self, ret_cx: &BlockAndBuilder<'a, 'tcx>) {
|
||||
if self.llretslotptr.is_none() || self.fn_ty.ret.is_indirect() {
|
||||
return ret_cx.ret_void();
|
||||
}
|
||||
|
||||
let retslot = self.llretslotptr.unwrap();
|
||||
let retptr = Value(retslot);
|
||||
let llty = self.fn_ty.ret.original_ty;
|
||||
match (retptr.get_dominating_store(ret_cx), self.fn_ty.ret.cast) {
|
||||
// If there's only a single store to the ret slot, we can directly return
|
||||
// the value that was stored and omit the store and the alloca.
|
||||
// However, we only want to do this when there is no cast needed.
|
||||
(Some(s), None) => {
|
||||
let mut retval = s.get_operand(0).unwrap().get();
|
||||
s.erase_from_parent();
|
||||
|
||||
if retptr.has_no_uses() {
|
||||
retptr.erase_from_parent();
|
||||
}
|
||||
|
||||
if self.fn_ty.ret.is_indirect() {
|
||||
ret_cx.store(retval, get_param(self.llfn, 0));
|
||||
ret_cx.ret_void()
|
||||
} else {
|
||||
if llty == Type::i1(self.ccx) {
|
||||
retval = ret_cx.trunc(retval, llty);
|
||||
}
|
||||
ret_cx.ret(retval)
|
||||
}
|
||||
}
|
||||
(_, cast_ty) if self.fn_ty.ret.is_indirect() => {
|
||||
// Otherwise, copy the return value to the ret slot.
|
||||
assert_eq!(cast_ty, None);
|
||||
let llsz = llsize_of(self.ccx, self.fn_ty.ret.ty);
|
||||
let llalign = llalign_of_min(self.ccx, self.fn_ty.ret.ty);
|
||||
call_memcpy(&ret_cx, get_param(self.llfn, 0),
|
||||
retslot, llsz, llalign as u32);
|
||||
ret_cx.ret_void()
|
||||
}
|
||||
(_, Some(cast_ty)) => {
|
||||
let load = ret_cx.load(ret_cx.pointercast(retslot, cast_ty.ptr_to()));
|
||||
let llalign = llalign_of_min(self.ccx, self.fn_ty.ret.ty);
|
||||
unsafe {
|
||||
llvm::LLVMSetAlignment(load, llalign);
|
||||
}
|
||||
ret_cx.ret(load)
|
||||
}
|
||||
(_, None) => {
|
||||
let retval = if llty == Type::i1(self.ccx) {
|
||||
let val = ret_cx.load_range_assert(retslot, 0, 2, llvm::False);
|
||||
ret_cx.trunc(val, llty)
|
||||
} else {
|
||||
ret_cx.load(retslot)
|
||||
};
|
||||
ret_cx.ret(retval)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn trans_instance<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, instance: Instance<'tcx>) {
|
||||
let _s = if ccx.sess().trans_stats() {
|
||||
let mut instance_name = String::new();
|
||||
@ -683,9 +621,17 @@ pub fn trans_ctor_shim<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
||||
|
||||
let fcx = FunctionContext::new(ccx, llfndecl, fn_ty, None, false);
|
||||
let bcx = fcx.get_entry_block();
|
||||
|
||||
if !fcx.fn_ty.ret.is_ignore() {
|
||||
let dest = fcx.llretslotptr.unwrap();
|
||||
// But if there are no nested returns, we skip the indirection
|
||||
// and have a single retslot
|
||||
let dest = if fcx.fn_ty.ret.is_indirect() {
|
||||
get_param(fcx.llfn, 0)
|
||||
} else {
|
||||
// We create an alloca to hold a pointer of type `ret.original_ty`
|
||||
// which will hold the pointer to the right alloca which has the
|
||||
// final ret value
|
||||
fcx.alloca(fcx.fn_ty.ret.memory_ty(ccx), "sret_slot")
|
||||
};
|
||||
let dest_val = adt::MaybeSizedValue::sized(dest); // Can return unsized value
|
||||
let mut llarg_idx = fcx.fn_ty.ret.is_indirect() as usize;
|
||||
let mut arg_idx = 0;
|
||||
@ -703,9 +649,32 @@ pub fn trans_ctor_shim<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
||||
}
|
||||
}
|
||||
adt::trans_set_discr(&bcx, sig.output(), dest, disr);
|
||||
}
|
||||
|
||||
fcx.build_return_block(&bcx);
|
||||
if fcx.fn_ty.ret.is_indirect() {
|
||||
bcx.ret_void();
|
||||
return;
|
||||
}
|
||||
|
||||
if let Some(cast_ty) = fcx.fn_ty.ret.cast {
|
||||
let load = bcx.load(bcx.pointercast(dest, cast_ty.ptr_to()));
|
||||
let llalign = llalign_of_min(fcx.ccx, fcx.fn_ty.ret.ty);
|
||||
unsafe {
|
||||
llvm::LLVMSetAlignment(load, llalign);
|
||||
}
|
||||
bcx.ret(load)
|
||||
} else {
|
||||
let llty = fcx.fn_ty.ret.original_ty;
|
||||
let retval = if llty == Type::i1(fcx.ccx) {
|
||||
let val = bcx.load_range_assert(dest, 0, 2, llvm::False);
|
||||
bcx.trunc(val, llty)
|
||||
} else {
|
||||
bcx.load(dest)
|
||||
};
|
||||
bcx.ret(retval)
|
||||
}
|
||||
} else {
|
||||
bcx.ret_void();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn llvm_linkage_by_name(name: &str) -> Option<Linkage> {
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
pub use self::CalleeData::*;
|
||||
|
||||
use llvm::{self, ValueRef, get_params};
|
||||
use llvm::{self, ValueRef, get_param, get_params};
|
||||
use rustc::hir::def_id::DefId;
|
||||
use rustc::ty::subst::Substs;
|
||||
use rustc::traits;
|
||||
@ -390,8 +390,8 @@ fn trans_fn_once_adapter_shim<'a, 'tcx>(
|
||||
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() {
|
||||
fcx.llretslotptr
|
||||
let first_llarg = if fn_ty.ret.is_indirect() && !fcx.fn_ty.ret.is_ignore() {
|
||||
Some(get_param(fcx.llfn, 0))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
@ -409,17 +409,16 @@ fn trans_fn_once_adapter_shim<'a, 'tcx>(
|
||||
}
|
||||
fn_ty.apply_attrs_callsite(llret);
|
||||
|
||||
if !fn_ty.ret.is_indirect() {
|
||||
if let Some(llretslot) = fcx.llretslotptr {
|
||||
fn_ty.ret.store(&bcx, llret, llretslot);
|
||||
}
|
||||
}
|
||||
|
||||
if fn_ret.0.is_never() {
|
||||
bcx.unreachable();
|
||||
}
|
||||
self_scope.trans(&bcx);
|
||||
fcx.build_return_block(&bcx);
|
||||
|
||||
if fcx.fn_ty.ret.is_indirect() || fcx.fn_ty.ret.is_ignore() {
|
||||
bcx.ret_void();
|
||||
} else {
|
||||
bcx.ret(llret);
|
||||
}
|
||||
|
||||
ccx.instances().borrow_mut().insert(method_instance, lloncefn);
|
||||
|
||||
@ -539,9 +538,31 @@ fn trans_fn_pointer_shim<'a, 'tcx>(
|
||||
data: Fn(llfnpointer),
|
||||
ty: bare_fn_ty
|
||||
};
|
||||
callee.call(&bcx, &llargs[(self_idx + 1)..], fcx.llretslotptr, None);
|
||||
fcx.build_return_block(&bcx);
|
||||
|
||||
let fn_ret = callee.ty.fn_ret();
|
||||
let fn_ty = callee.direct_fn_type(ccx, &[]);
|
||||
|
||||
let mut args = Vec::new();
|
||||
|
||||
if fn_ty.ret.is_indirect() {
|
||||
if !fn_ty.ret.is_ignore() {
|
||||
args.push(get_param(fcx.llfn, 0));
|
||||
}
|
||||
}
|
||||
args.extend_from_slice(&llargs[(self_idx + 1)..]);
|
||||
|
||||
let llret = bcx.call(llfnpointer, &args, None);
|
||||
fn_ty.apply_attrs_callsite(llret);
|
||||
|
||||
if fn_ret.0.is_never() {
|
||||
bcx.unreachable();
|
||||
}
|
||||
|
||||
if fn_ty.ret.is_indirect() || fcx.fn_ty.ret.is_ignore() {
|
||||
bcx.ret_void();
|
||||
} else {
|
||||
bcx.ret(llret);
|
||||
}
|
||||
ccx.fn_pointer_shims().borrow_mut().insert(bare_fn_ty_maybe_ref, llfn);
|
||||
|
||||
llfn
|
||||
|
@ -201,7 +201,7 @@ pub fn implement_drop_glue<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, g: DropGlueKi
|
||||
// type, so we don't need to explicitly cast the function parameter.
|
||||
|
||||
let bcx = make_drop_glue(bcx, get_param(llfn, 0), g);
|
||||
fcx.build_return_block(&bcx);
|
||||
bcx.ret_void();
|
||||
}
|
||||
|
||||
fn trans_custom_dtor<'a, 'tcx>(mut bcx: BlockAndBuilder<'a, 'tcx>,
|
||||
|
@ -85,8 +85,24 @@ pub fn trans_object_shim<'a, 'tcx>(ccx: &'a CrateContext<'a, 'tcx>,
|
||||
let bcx = fcx.get_entry_block();
|
||||
|
||||
let llargs = get_params(fcx.llfn);
|
||||
callee.call(&bcx, &llargs[fcx.fn_ty.ret.is_indirect() as usize..], fcx.llretslotptr, None);
|
||||
fcx.build_return_block(&bcx);
|
||||
let fn_ret = callee.ty.fn_ret();
|
||||
let fn_ty = callee.direct_fn_type(ccx, &[]);
|
||||
|
||||
let mut args = Vec::new();
|
||||
|
||||
args.extend_from_slice(&llargs);
|
||||
let llret = bcx.call(callee.reify(ccx), &args, None);
|
||||
fn_ty.apply_attrs_callsite(llret);
|
||||
|
||||
if fn_ret.0.is_never() {
|
||||
bcx.unreachable();
|
||||
}
|
||||
|
||||
if fn_ty.ret.is_indirect() || fcx.fn_ty.ret.is_ignore() {
|
||||
bcx.ret_void();
|
||||
} else {
|
||||
bcx.ret(llret);
|
||||
}
|
||||
|
||||
llfn
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user