about summary refs log tree commit diff
diff options
context:
space:
mode:
authorGraydon Hoare <graydon@mozilla.com>2011-04-28 11:24:16 -0700
committerGraydon Hoare <graydon@mozilla.com>2011-04-28 11:24:29 -0700
commit6daca7ea8d0ef1f99c928a0b6bacc8cefc17969a (patch)
treebf9232da53c0e4219648a8a8517848c5e1995c57
parent91fe4ae0900c1ef361952a6c8e0647e70598741c (diff)
downloadrust-6daca7ea8d0ef1f99c928a0b6bacc8cefc17969a.tar.gz
rust-6daca7ea8d0ef1f99c928a0b6bacc8cefc17969a.zip
Actually perform take/drop on args (oh my!)
-rw-r--r--src/comp/middle/trans.rs40
1 files changed, 36 insertions, 4 deletions
diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs
index 3e316ab4a24..75c7aa8448b 100644
--- a/src/comp/middle/trans.rs
+++ b/src/comp/middle/trans.rs
@@ -4317,7 +4317,9 @@ fn trans_bind_thunk(@local_ctxt cx,
                              abi.closure_elt_ty_params,
                              (i as int)));
         bcx = lltyparam_ptr.bcx;
-        llargs += vec(bcx.build.Load(lltyparam_ptr.val));
+        auto td = bcx.build.Load(lltyparam_ptr.val);
+        llargs += vec(td);
+        fcx.lltydescs += vec(td);
         i += 1u;
     }
 
@@ -4335,7 +4337,8 @@ fn trans_bind_thunk(@local_ctxt cx,
         alt (arg) {
 
             // Arg provided at binding time; thunk copies it from closure.
-            case (some[@ast.expr](_)) {
+            case (some[@ast.expr](?e)) {
+                auto e_ty = ty.expr_ty(cx.ccx.tcx, e);
                 auto bound_arg =
                     GEP_tup_like(bcx, closure_ty, llclosure,
                                  vec(0,
@@ -4347,7 +4350,13 @@ fn trans_bind_thunk(@local_ctxt cx,
                 auto val = bound_arg.val;
 
                 if (out_arg.mode == ast.val) {
-                    val = bcx.build.Load(val);
+                    if (type_is_immediate(cx.ccx, e_ty)) {
+                        val = bcx.build.Load(val);
+                        bcx = take_ty(bcx, val, e_ty).bcx;
+                    } else {
+                        bcx = take_ty(bcx, val, e_ty).bcx;
+                        val = bcx.build.Load(val);
+                    }
                 } else if (ty.type_contains_params(cx.ccx.tcx,
                                                    out_arg.ty)) {
                     check (out_arg.mode == ast.alias);
@@ -4630,6 +4639,10 @@ fn trans_arg_expr(@block_ctxt cx,
         bcx = re.bcx;
     }
 
+    if (arg.mode != ast.alias) {
+        bcx = take_ty(bcx, val, e_ty).bcx;
+    }
+
     if (ty.type_contains_params(cx.fcx.lcx.ccx.tcx, arg.ty)) {
         auto lldestty = lldestty0;
         if (arg.mode == ast.val) {
@@ -5957,6 +5970,21 @@ fn copy_args_to_allocas(@fn_ctxt fcx,
     fcx.llallocas = bcx.llbb;
 }
 
+fn add_cleanups_for_args(@block_ctxt bcx,
+                         vec[ast.arg] args,
+                         vec[ty.arg] arg_tys) {
+    let uint arg_n = 0u;
+    for (ast.arg aarg in args) {
+        if (aarg.mode != ast.alias) {
+            auto argval = bcx.fcx.llargs.get(aarg.id);
+            find_scope_cx(bcx).cleanups +=
+                vec(clean(bind drop_slot(_, argval, arg_tys.(arg_n).ty)));
+        }
+        arg_n += 1u;
+    }
+}
+
+
 fn is_terminated(@block_ctxt cx) -> bool {
     auto inst = llvm.LLVMGetLastInstruction(cx.llbb);
     ret llvm.LLVMIsATerminatorInst(inst) as int != 0;
@@ -6075,9 +6103,13 @@ fn trans_fn(@local_ctxt cx, &ast._fn f, ast.def_id fid,
         }
     }
 
-    copy_args_to_allocas(fcx, f.decl.inputs, arg_tys_of_fn(fcx.lcx.ccx, ann));
+    auto arg_tys = arg_tys_of_fn(fcx.lcx.ccx, ann);
+    copy_args_to_allocas(fcx, f.decl.inputs, arg_tys);
 
     auto bcx = new_top_block_ctxt(fcx);
+
+    add_cleanups_for_args(bcx, f.decl.inputs, arg_tys);
+
     auto lltop = bcx.llbb;
 
     auto res = trans_block(bcx, f.body);