about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorGraydon Hoare <graydon@mozilla.com>2011-03-07 18:13:39 -0800
committerGraydon Hoare <graydon@mozilla.com>2011-03-07 18:13:56 -0800
commit0d60918855aefde24ee8d72238b167ef1b09628b (patch)
treeb635665cb95aea7665a04223ec4c64135fc5cdd9 /src
parent3473ff3bff2ed2286080812417068552d6b9df31 (diff)
Most of the way through genericizing bind properly with new malloc path. Still getting the thunk call wrong.
Diffstat (limited to 'src')
-rw-r--r--src/comp/middle/trans.rs87
-rw-r--r--src/test/run-pass/generic-bind.rs9
2 files changed, 56 insertions, 40 deletions
diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs
index a282c0a240c..fffa325f34e 100644
--- a/src/comp/middle/trans.rs
+++ b/src/comp/middle/trans.rs
@@ -387,6 +387,10 @@ fn T_closure_ptr(type_names tn,
                  TypeRef lltarget_ty,
                  TypeRef llbindings_ty,
                  uint n_ty_params) -> TypeRef {
+
+    // NB: keep this in sync with code in trans_bind; we're making
+    // an LLVM typeref structure that has the same "shape" as the ty.t
+    // it constructs.
     ret T_ptr(T_box(T_struct(vec(T_ptr(T_tydesc(tn)),
                                  lltarget_ty,
                                  llbindings_ty,
@@ -3322,7 +3326,7 @@ fn trans_bind_thunk(@crate_ctxt cx,
                     @ty.t incoming_fty,
                     @ty.t outgoing_fty,
                     vec[option.t[@ast.expr]] args,
-                    TypeRef llclosure_ty,
+                    @ty.t closure_ty,
                     vec[@ty.t] bound_tys,
                     uint ty_param_count) -> ValueRef {
     // Construct a thunk-call with signature incoming_fty, and that copies
@@ -3335,21 +3339,15 @@ fn trans_bind_thunk(@crate_ctxt cx,
     auto fcx = new_fn_ctxt(cx, llthunk);
     auto bcx = new_top_block_ctxt(fcx);
 
-    auto llclosure = bcx.build.PointerCast(fcx.llenv, llclosure_ty);
-
-    auto llbody = bcx.build.GEP(llclosure,
-                                vec(C_int(0),
-                                    C_int(abi.box_rc_field_body)));
-
-    auto lltarget = bcx.build.GEP(llbody,
-                                  vec(C_int(0),
-                                      C_int(abi.closure_elt_target)));
-
-    auto llbound = bcx.build.GEP(llbody,
-                                 vec(C_int(0),
-                                     C_int(abi.closure_elt_bindings)));
+    auto llclosure_ptr_ty = type_of(cx, plain_ty(ty.ty_box(closure_ty)));
+    auto llclosure = bcx.build.PointerCast(fcx.llenv, llclosure_ptr_ty);
 
-    auto lltargetclosure = bcx.build.GEP(lltarget,
+    auto lltarget = GEP_tup_like(bcx, closure_ty, llclosure,
+                                 vec(0,
+                                     abi.box_rc_field_body,
+                                     abi.closure_elt_target));
+    bcx = lltarget.bcx;
+    auto lltargetclosure = bcx.build.GEP(lltarget.val,
                                          vec(C_int(0),
                                              C_int(abi.fn_field_box)));
     lltargetclosure = bcx.build.Load(lltargetclosure);
@@ -3370,10 +3368,13 @@ fn trans_bind_thunk(@crate_ctxt cx,
     let uint i = 0u;
     while (i < ty_param_count) {
         auto lltyparam_ptr =
-            bcx.build.GEP(llbody, vec(C_int(0),
-                                      C_int(abi.closure_elt_ty_params),
-                                      C_int(i as int)));
-        llargs += vec(bcx.build.Load(lltyparam_ptr));
+            GEP_tup_like(bcx, closure_ty, llclosure,
+                         vec(0,
+                             abi.box_rc_field_body,
+                             abi.closure_elt_ty_params,
+                             (i as int)));
+        bcx = lltyparam_ptr.bcx;
+        llargs += vec(bcx.build.Load(lltyparam_ptr.val));
         i += 1u;
     }
 
@@ -3385,11 +3386,15 @@ fn trans_bind_thunk(@crate_ctxt cx,
 
             // Arg provided at binding time; thunk copies it from closure.
             case (some[@ast.expr](_)) {
-                let ValueRef bound_arg = bcx.build.GEP(llbound,
-                                                       vec(C_int(0),
-                                                           C_int(b)));
+                auto bound_arg =
+                    GEP_tup_like(bcx, closure_ty, llclosure,
+                                 vec(0,
+                                     abi.box_rc_field_body,
+                                     abi.closure_elt_bindings,
+                                     b));
                 // FIXME: possibly support passing aliases someday.
-                llargs += bcx.build.Load(bound_arg);
+                bcx = bound_arg.bcx;
+                llargs += bcx.build.Load(bound_arg.val);
                 b += 1;
             }
 
@@ -3412,7 +3417,7 @@ fn trans_bind_thunk(@crate_ctxt cx,
     }
 
     // FIXME: turn this call + ret into a tail call.
-    auto lltargetfn = bcx.build.GEP(lltarget,
+    auto lltargetfn = bcx.build.GEP(lltarget.val,
                                     vec(C_int(0),
                                         C_int(abi.fn_field_code)));
     lltargetfn = bcx.build.Load(lltargetfn);
@@ -3479,21 +3484,26 @@ fn trans_bind(@block_ctxt cx, @ast.expr f,
                 i += 1u;
             }
 
-            // Get the type of the bound function.
-            let TypeRef lltarget_ty = type_of(bcx.fcx.ccx, outgoing_fty);
-
             // Synthesize a closure type.
             let @ty.t bindings_ty = plain_ty(ty.ty_tup(bound_tys));
-            let TypeRef llbindings_ty = type_of(bcx.fcx.ccx, bindings_ty);
-            let TypeRef llclosure_ty = T_closure_ptr(cx.fcx.ccx.tn,
-                                                     lltarget_ty,
-                                                     llbindings_ty,
-                                                     ty_param_count);
-
-            // Malloc a box for the body.
-            // FIXME: this isn't generic-safe
-            auto r = trans_raw_malloc(bcx, llclosure_ty,
-                llsize_of(llvm.LLVMGetElementType(llclosure_ty)));
+
+            // NB: keep this in sync with T_closure_ptr; we're making
+            // a ty.t structure that has the same "shape" as the LLVM type
+            // it constructs.
+            let @ty.t tydesc_ty = plain_ty(ty.ty_type);
+
+            let vec[@ty.t] captured_tys =
+                _vec.init_elt[@ty.t](tydesc_ty, ty_param_count);
+
+            let vec[@ty.t] closure_tys =
+                vec(tydesc_ty,
+                    outgoing_fty,
+                    bindings_ty,
+                    plain_ty(ty.ty_tup(captured_tys)));
+
+            let @ty.t closure_ty = plain_ty(ty.ty_tup(closure_tys));
+
+            auto r = trans_malloc_boxed(bcx, closure_ty);
             auto box = r.val;
             bcx = r.bcx;
             auto rc = bcx.build.GEP(box,
@@ -3561,9 +3571,10 @@ fn trans_bind(@block_ctxt cx, @ast.expr f,
                                                C_int(abi.fn_field_code)));
 
             let @ty.t pair_ty = node_ann_type(cx.fcx.ccx, ann);
+
             let ValueRef llthunk =
                 trans_bind_thunk(cx.fcx.ccx, pair_ty, outgoing_fty,
-                                 args, llclosure_ty, bound_tys,
+                                 args, closure_ty, bound_tys,
                                  ty_param_count);
 
             bcx.build.Store(llthunk, pair_code);
diff --git a/src/test/run-pass/generic-bind.rs b/src/test/run-pass/generic-bind.rs
index 61085eb5485..5f44bceef44 100644
--- a/src/test/run-pass/generic-bind.rs
+++ b/src/test/run-pass/generic-bind.rs
@@ -3,6 +3,11 @@ fn id[T](&T t) -> T {
 }
 
 fn main() {
-  auto f = bind id[int](_);
-  check (f(10) == 10);
+  auto t = tup(1,2,3,4,5,6,7);
+  check (t._5 == 6);
+  // FIXME: this needs to work.
+  // auto f0 = bind id[tup(int,int,int,int,int,int,int)](t);
+  auto f1 = bind id[tup(int,int,int,int,int,int,int)](_);
+  // check (f0()._5 == 6);
+  check (f1(t)._5 == 6);
 }