]> git.lizzy.rs Git - rust.git/commitdiff
Inline and cleanup build_return_block
authorMark Simulacrum <mark.simulacrum@gmail.com>
Sun, 18 Dec 2016 16:07:35 +0000 (09:07 -0700)
committerMark Simulacrum <mark.simulacrum@gmail.com>
Wed, 21 Dec 2016 03:03:31 +0000 (20:03 -0700)
src/librustc_trans/base.rs
src/librustc_trans/callee.rs
src/librustc_trans/glue.rs
src/librustc_trans/meth.rs

index 1e37f743b6fbe406a1bfa4e3ecc95f778951159d..f9b8b18a5ec2bbcc9f4e9ca904f8f88299eba9f2 100644 (file)
@@ -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> {
index fa24c5ecf2e41d20b6260271ae1a9eadf1c6cade..e0ecd1d8bf57a50fee29dd3c5a73221bb21f7709 100644 (file)
@@ -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
index 936ab0901123dcecfb7b7f7e86ed348621e6a97c..4778f3685546545d2c50c07375c8af132d056c53 100644 (file)
@@ -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>,
index a09838f282b377e9baa03a8a7eac19689f3771db..33b43e9a3ab06ac1234d7886df66aade07630ac2 100644 (file)
@@ -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
 }