summary refs log tree commit diff
path: root/src/comp
diff options
context:
space:
mode:
authorMichael Sullivan <sully@msully.net>2011-08-15 18:18:19 -0700
committerMichael Sullivan <sully@msully.net>2011-08-16 12:13:21 -0700
commita9c46e29bcd4d8b1dcbeb9de40fb5bc7a2747aec (patch)
tree93d3cc4591a218f641722ce202801bfba992fbe7 /src/comp
parent2f61848b24bcb04f4eee3bd16851d3e654d66e20 (diff)
downloadrust-a9c46e29bcd4d8b1dcbeb9de40fb5bc7a2747aec.tar.gz
rust-a9c46e29bcd4d8b1dcbeb9de40fb5bc7a2747aec.zip
Don't put the target in the bind closure if it is statically known. Closes #177.
Diffstat (limited to 'src/comp')
-rw-r--r--src/comp/middle/trans.rs52
1 files changed, 33 insertions, 19 deletions
diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs
index 54aff99ffd7..805d478e99f 100644
--- a/src/comp/middle/trans.rs
+++ b/src/comp/middle/trans.rs
@@ -4212,7 +4212,9 @@ fn trans_cast(cx: &@block_ctxt, e: &@ast::expr, id: ast::node_id) -> result {
 fn trans_bind_thunk(cx: &@local_ctxt, sp: &span, incoming_fty: &ty::t,
                     outgoing_fty: &ty::t, args: &[option::t[@ast::expr]],
                     env_ty: &ty::t, bound_tys: &[ty::t],
-                    ty_param_count: uint) -> {val: ValueRef, ty: TypeRef} {
+                    ty_param_count: uint,
+                    target_fn: &option::t[ValueRef]) ->
+    {val: ValueRef, ty: TypeRef} {
 
     // Here we're not necessarily constructing a thunk in the sense of
     // "function with no arguments".  The result of compiling 'bind f(foo,
@@ -4270,16 +4272,22 @@ fn trans_bind_thunk(cx: &@local_ctxt, sp: &span, incoming_fty: &ty::t,
     // creating.  (In our running example, target is the function f.)  Pick
     // out the pointer to the target function from the environment. The
     // target function lives in the first binding spot.
-    let lltarget =
-        GEP_tup_like(bcx, closure_ty, llclosure,
-                     ~[0, abi::box_rc_field_body,
-                       abi::closure_elt_bindings, 0]);
-    bcx = lltarget.bcx;
+    let (lltarget, starting_idx) = alt target_fn {
+      some(lltarget) { (lltarget, 0) }
+      none. {
+        let lltarget =
+            GEP_tup_like(bcx, closure_ty, llclosure,
+                         ~[0, abi::box_rc_field_body,
+                           abi::closure_elt_bindings, 0]);
+        bcx = lltarget.bcx;
+        (lltarget.val, 1)
+      }
+    };
 
     // And then, pick out the target function's own environment.  That's what
     // we'll use as the environment the thunk gets.
     let lltargetclosure =
-        bcx.build.GEP(lltarget.val, ~[C_int(0), C_int(abi::fn_field_box)]);
+        bcx.build.GEP(lltarget, ~[C_int(0), C_int(abi::fn_field_box)]);
     lltargetclosure = bcx.build.Load(lltargetclosure);
 
     // Get f's return type, which will also be the return type of the entire
@@ -4315,7 +4323,7 @@ fn trans_bind_thunk(cx: &@local_ctxt, sp: &span, incoming_fty: &ty::t,
     }
 
     let a: uint = 3u; // retptr, task ptr, env come first
-    let b: int = 1;
+    let b: int = starting_idx;
     let outgoing_arg_index: uint = 0u;
     let llout_arg_tys: [TypeRef] =
         type_of_explicit_args(cx.ccx, sp, outgoing_args);
@@ -4377,7 +4385,7 @@ fn trans_bind_thunk(cx: &@local_ctxt, sp: &span, incoming_fty: &ty::t,
     }
 
     let lltargetfn =
-        bcx.build.GEP(lltarget.val, ~[C_int(0), C_int(abi::fn_field_code)]);
+        bcx.build.GEP(lltarget, ~[C_int(0), C_int(abi::fn_field_code)]);
 
     // Cast the outgoing function to the appropriate type.
     // This is necessary because the type of the function that we have
@@ -4427,16 +4435,21 @@ fn trans_bind_1(cx: &@block_ctxt, f: &@ast::expr, f_res: &lval_result,
     }
     let bcx = f_res.res.bcx;
 
-    // Cast the function we are binding to be the type that the closure
-    // will expect it to have. The type the closure knows about has the
-    // type parameters substituted with the real types.
-    let llclosurety = T_ptr(type_of(bcx_ccx(cx), cx.sp, outgoing_fty));
-    let src_loc = bcx.build.PointerCast(f_res.res.val, llclosurety);
-    let bound_f = {res: {bcx: bcx, val: src_loc} with f_res};
 
-    // Arrange for the bound function to live in the first binding spot.
-    let bound_tys: [ty::t] = ~[outgoing_fty];
-    let bound_vals: [lval_result] = ~[bound_f];
+    // Arrange for the bound function to live in the first binding spot
+    // if the function is not statically known.
+    let (bound_tys, bound_vals, target_res) = if f_res.is_mem {
+        // Cast the function we are binding to be the type that the closure
+        // will expect it to have. The type the closure knows about has the
+        // type parameters substituted with the real types.
+        let llclosurety = T_ptr(type_of(bcx_ccx(cx), cx.sp, outgoing_fty));
+        let src_loc = bcx.build.PointerCast(f_res.res.val, llclosurety);
+        let bound_f = {res: {bcx: bcx, val: src_loc} with f_res};
+        (~[outgoing_fty], ~[bound_f], none)
+    } else {
+        (~[], ~[], some(f_res.res.val))
+    };
+
     // Translate the bound expressions.
     for e: @ast::expr in bound {
         let lv = trans_lval(bcx, e);
@@ -4455,7 +4468,8 @@ fn trans_bind_1(cx: &@block_ctxt, f: &@ast::expr, f_res: &lval_result,
     let pair_ty = node_id_type(bcx_ccx(cx), id);
     let llthunk =
         trans_bind_thunk(cx.fcx.lcx, cx.sp, pair_ty, outgoing_fty_real,
-                         args, closure.ptrty, bound_tys, ty_param_count);
+                         args, closure.ptrty, bound_tys, ty_param_count,
+                         target_res);
 
     // Construct the function pair
     let pair_v = create_real_fn_pair(bcx, llthunk.ty, llthunk.val,