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)
|
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>) {
|
pub fn trans_instance<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, instance: Instance<'tcx>) {
|
||||||
let _s = if ccx.sess().trans_stats() {
|
let _s = if ccx.sess().trans_stats() {
|
||||||
let mut instance_name = String::new();
|
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 fcx = FunctionContext::new(ccx, llfndecl, fn_ty, None, false);
|
||||||
let bcx = fcx.get_entry_block();
|
let bcx = fcx.get_entry_block();
|
||||||
|
|
||||||
if !fcx.fn_ty.ret.is_ignore() {
|
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 dest_val = adt::MaybeSizedValue::sized(dest); // Can return unsized value
|
||||||
let mut llarg_idx = fcx.fn_ty.ret.is_indirect() as usize;
|
let mut llarg_idx = fcx.fn_ty.ret.is_indirect() as usize;
|
||||||
let mut arg_idx = 0;
|
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);
|
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> {
|
pub fn llvm_linkage_by_name(name: &str) -> Option<Linkage> {
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
pub use self::CalleeData::*;
|
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::hir::def_id::DefId;
|
||||||
use rustc::ty::subst::Substs;
|
use rustc::ty::subst::Substs;
|
||||||
use rustc::traits;
|
use rustc::traits;
|
||||||
@ -390,8 +390,8 @@ fn trans_fn_once_adapter_shim<'a, 'tcx>(
|
|||||||
let fn_ret = callee.ty.fn_ret();
|
let fn_ret = callee.ty.fn_ret();
|
||||||
let fn_ty = callee.direct_fn_type(bcx.ccx(), &[]);
|
let fn_ty = callee.direct_fn_type(bcx.ccx(), &[]);
|
||||||
|
|
||||||
let first_llarg = if fn_ty.ret.is_indirect() {
|
let first_llarg = if fn_ty.ret.is_indirect() && !fcx.fn_ty.ret.is_ignore() {
|
||||||
fcx.llretslotptr
|
Some(get_param(fcx.llfn, 0))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
@ -409,17 +409,16 @@ fn trans_fn_once_adapter_shim<'a, 'tcx>(
|
|||||||
}
|
}
|
||||||
fn_ty.apply_attrs_callsite(llret);
|
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() {
|
if fn_ret.0.is_never() {
|
||||||
bcx.unreachable();
|
bcx.unreachable();
|
||||||
}
|
}
|
||||||
self_scope.trans(&bcx);
|
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);
|
ccx.instances().borrow_mut().insert(method_instance, lloncefn);
|
||||||
|
|
||||||
@ -539,9 +538,31 @@ fn trans_fn_pointer_shim<'a, 'tcx>(
|
|||||||
data: Fn(llfnpointer),
|
data: Fn(llfnpointer),
|
||||||
ty: bare_fn_ty
|
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);
|
ccx.fn_pointer_shims().borrow_mut().insert(bare_fn_ty_maybe_ref, llfn);
|
||||||
|
|
||||||
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.
|
// type, so we don't need to explicitly cast the function parameter.
|
||||||
|
|
||||||
let bcx = make_drop_glue(bcx, get_param(llfn, 0), g);
|
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>,
|
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 bcx = fcx.get_entry_block();
|
||||||
|
|
||||||
let llargs = get_params(fcx.llfn);
|
let llargs = get_params(fcx.llfn);
|
||||||
callee.call(&bcx, &llargs[fcx.fn_ty.ret.is_indirect() as usize..], fcx.llretslotptr, None);
|
let fn_ret = callee.ty.fn_ret();
|
||||||
fcx.build_return_block(&bcx);
|
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
|
llfn
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user