about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2012-09-14 12:01:43 -0700
committerNiko Matsakis <niko@alum.mit.edu>2012-09-14 12:03:28 -0700
commit044fbea416c8778ec8f653b93941dca6f2e9213e (patch)
tree0fce008bd25b7d137873a205eb08dd077c1b6c2f /src
parentbbfc6f89455b207b65972181ae4401941215b6a9 (diff)
downloadrust-044fbea416c8778ec8f653b93941dca6f2e9213e.tar.gz
rust-044fbea416c8778ec8f653b93941dca6f2e9213e.zip
Adapt callee to avoid intermediary for move/copy arguments (cc #3402)
Diffstat (limited to 'src')
-rw-r--r--src/rustc/middle/trans/callee.rs168
1 files changed, 88 insertions, 80 deletions
diff --git a/src/rustc/middle/trans/callee.rs b/src/rustc/middle/trans/callee.rs
index 4c33bd2b432..b812b3deb37 100644
--- a/src/rustc/middle/trans/callee.rs
+++ b/src/rustc/middle/trans/callee.rs
@@ -484,6 +484,7 @@ fn trans_arg_expr(bcx: block,
 {
     let _icx = bcx.insn_ctxt("trans_arg_expr");
     let ccx = bcx.ccx();
+    let mut bcx = bcx;
 
     debug!("trans_arg_expr(formal_ty=(%?,%s), arg_expr=%s, \
             ret_flag=%?)",
@@ -492,97 +493,104 @@ fn trans_arg_expr(bcx: block,
            ret_flag.map(|v| bcx.val_str(v)));
     let _indenter = indenter();
 
-    // translate the arg expr to a datum
-    let arg_datumblock = match ret_flag {
-        None => expr::trans_to_datum(bcx, arg_expr),
-
-        // If there is a ret_flag, this *must* be a loop body
-        Some(_) => {
-            match arg_expr.node {
-                ast::expr_loop_body(
-                    blk @ @{node:ast::expr_fn_block(decl, body, cap), _}) =>
-                {
-                    let scratch_ty = expr_ty(bcx, blk);
-                    let scratch = alloc_ty(bcx, scratch_ty);
-                    let arg_ty = expr_ty(bcx, arg_expr);
-                    let proto = ty::ty_fn_proto(arg_ty);
-                    let bcx = closure::trans_expr_fn(
-                        bcx, proto, decl, body, blk.id,
-                        cap, Some(ret_flag), expr::SaveIn(scratch));
-                    DatumBlock {bcx: bcx,
-                                datum: Datum {val: scratch,
-                                              ty: scratch_ty,
-                                              mode: ByRef,
-                                              source: FromRvalue}}
-                }
-                _ => {
-                    bcx.sess().impossible_case(
-                        arg_expr.span, ~"ret_flag with non-loop-\
-                                         body expr");
-                }
-            }
-        }
-    };
-    let mut arg_datum = arg_datumblock.datum;
-    let mut bcx = arg_datumblock.bcx;
-
-    debug!("   arg datum: %s", arg_datum.to_str(bcx.ccx()));
-
     // finally, deal with the various modes
     let arg_mode = ty::resolved_mode(ccx.tcx, formal_ty.mode);
     let mut val;
-    if ty::type_is_bot(arg_datum.ty) {
-        // For values of type _|_, we generate an
-        // "undef" value, as such a value should never
-        // be inspected. It's important for the value
-        // to have type lldestty (the callee's expected type).
-        let llformal_ty = type_of::type_of(ccx, formal_ty.ty);
-        val = llvm::LLVMGetUndef(llformal_ty);
-    } else {
-        match arg_mode {
-            ast::by_ref | ast::by_mutbl_ref => {
-                val = arg_datum.to_ref_llval(bcx);
-            }
+    match arg_mode {
+        ast::by_ref | ast::by_mutbl_ref => {
+            let datum = unpack_datum!(bcx, {
+                trans_arg_expr_to_datum(bcx, arg_expr, ret_flag)
+            });
+            val = datum.to_ref_llval(bcx);
+        }
 
-            ast::by_val => {
-                // NB: avoid running the take glue.
-                val = arg_datum.to_value_llval(bcx);
-            }
+        ast::by_val => {
+            let datum = unpack_datum!(bcx, {
+                trans_arg_expr_to_datum(bcx, arg_expr, ret_flag)
+            });
+            val = datum.to_value_llval(bcx);
+        }
 
-            ast::by_copy | ast::by_move => {
-                let scratch = scratch_datum(bcx, arg_datum.ty, false);
+        ast::by_copy | ast::by_move => {
+            let scratch = scratch_datum(bcx, formal_ty.ty, false);
+            bcx = trans_arg_expr_into(bcx, arg_expr, ret_flag,
+                                      expr::SaveIn(scratch.val));
+
+            // Technically, ownership of val passes to the callee.
+            // However, we must cleanup should we fail before the
+            // callee is actually invoked.
+            scratch.add_clean(bcx);
+            vec::push(*temp_cleanups, scratch.val);
+            val = scratch.val;
+        }
+    }
 
-                if arg_mode == ast::by_move {
-                    // NDM---Doesn't seem like this should be necessary
-                    if !arg_datum.store_will_move() {
-                        bcx.sess().span_bug(
-                            arg_expr.span,
-                            fmt!("move mode but datum will not store: %s",
-                                 arg_datum.to_str(bcx.ccx())));
-                    }
-                }
+    /*
+    if formal_ty.ty != arg_datum.ty {
+        // this could happen due to e.g. subtyping
+        let llformal_ty = type_of::type_of_explicit_arg(ccx, formal_ty);
+        debug!("casting actual type (%s) to match formal (%s)",
+               bcx.val_str(val), bcx.llty_str(llformal_ty));
+        val = PointerCast(bcx, val, llformal_ty);
+    }
+    */
 
-                arg_datum.store_to_datum(bcx, INIT, scratch);
+    debug!("--- trans_arg_expr passing %s", val_str(bcx.ccx().tn, val));
+    return rslt(bcx, val);
 
-                // Technically, ownership of val passes to the callee.
-                // However, we must cleanup should we fail before the
-                // callee is actually invoked.
-                scratch.add_clean(bcx);
-                vec::push(*temp_cleanups, scratch.val);
-                val = scratch.val;
-          }
-        }
+    fn trans_arg_expr_to_datum(bcx: block,
+                               arg_expr: @ast::expr,
+                               ret_flag: Option<ValueRef>) -> DatumBlock {
+        match ret_flag {
+            None => {
+                expr::trans_to_datum(bcx, arg_expr)
+            }
 
-        if formal_ty.ty != arg_datum.ty {
-            // this could happen due to e.g. subtyping
-            let llformal_ty = type_of::type_of_explicit_arg(ccx, formal_ty);
-            debug!("casting actual type (%s) to match formal (%s)",
-                   bcx.val_str(val), bcx.llty_str(llformal_ty));
-            val = PointerCast(bcx, val, llformal_ty);
+            // If there is a ret_flag, this *must* be a loop body
+            Some(_) => {
+                match arg_expr.node {
+                    ast::expr_loop_body(
+                        blk @ @{node:ast::expr_fn_block(decl, body,
+                                                        cap), _}) =>
+                    {
+                        let scratch_ty = expr_ty(bcx, blk);
+                        let scratch = alloc_ty(bcx, scratch_ty);
+                        let arg_ty = expr_ty(bcx, arg_expr);
+                        let proto = ty::ty_fn_proto(arg_ty);
+                        let bcx = closure::trans_expr_fn(
+                            bcx, proto, decl, body, blk.id,
+                            cap, Some(ret_flag), expr::SaveIn(scratch));
+                        DatumBlock {bcx: bcx,
+                                    datum: Datum {val: scratch,
+                                                  ty: scratch_ty,
+                                                  mode: ByRef,
+                                                  source: FromRvalue}}
+                    }
+                    _ => {
+                        bcx.sess().impossible_case(
+                            arg_expr.span, ~"ret_flag with non-loop-\
+                                             body expr");
+                    }
+                }
+            }
         }
     }
 
-    debug!("--- trans_arg_expr passing %s", val_str(bcx.ccx().tn, val));
-    return rslt(bcx, val);
+    fn trans_arg_expr_into(bcx: block,
+                           arg_expr: @ast::expr,
+                           ret_flag: Option<ValueRef>,
+                           dest: expr::Dest) -> block {
+        match ret_flag {
+            None => {
+                expr::trans_into(bcx, arg_expr, dest)
+            }
+
+            Some(_) => {
+                let DatumBlock {bcx, datum} =
+                    trans_arg_expr_to_datum(bcx, arg_expr, ret_flag);
+                datum.store_to_dest(bcx, dest)
+            }
+        }
+    }
 }