]> git.lizzy.rs Git - rust.git/commitdiff
get basic code generation working, clone type descs for lambda[send]
authorNiko Matsakis <niko@alum.mit.edu>
Mon, 12 Dec 2011 04:42:37 +0000 (20:42 -0800)
committerNiko Matsakis <niko@alum.mit.edu>
Wed, 14 Dec 2011 22:32:20 +0000 (14:32 -0800)
src/comp/back/upcall.rs
src/comp/middle/trans.rs
src/rt/rust_internal.h
src/rt/rust_upcall.cpp

index 71f33ccb3729017a53ea1204ef02aa90e9f34f05..1530e5c1453b6903de716df4f2c206fd0aea9c65 100644 (file)
@@ -17,6 +17,7 @@
      shared_malloc: ValueRef,
      shared_free: ValueRef,
      mark: ValueRef,
+     clone_type_desc: ValueRef,
      get_type_desc: ValueRef,
      vec_grow: ValueRef,
      vec_push: ValueRef,
@@ -54,12 +55,18 @@ fn decl(llmod: ModuleRef, name: str, tys: [TypeRef], rv: TypeRef) ->
           malloc:
               d("malloc", [size_t, T_ptr(tydesc_type)],
                 T_ptr(T_i8())),
-          free: dv("free", [T_ptr(T_i8()), int_t]),
+          free:
+              dv("free", [T_ptr(T_i8()), int_t]),
           shared_malloc:
               d("shared_malloc", [size_t, T_ptr(tydesc_type)],
                 T_ptr(T_i8())),
-          shared_free: dv("shared_free", [T_ptr(T_i8())]),
-          mark: d("mark", [T_ptr(T_i8())], int_t),
+          shared_free:
+              dv("shared_free", [T_ptr(T_i8())]),
+          mark:
+              d("mark", [T_ptr(T_i8())], int_t),
+          clone_type_desc:
+              d("clone_type_desc", [T_ptr(tydesc_type)],
+                T_ptr(tydesc_type)),
           get_type_desc:
               d("get_type_desc",
                 [T_ptr(T_nil()), size_t,
@@ -67,8 +74,7 @@ fn decl(llmod: ModuleRef, name: str, tys: [TypeRef], rv: TypeRef) ->
                  T_ptr(T_ptr(tydesc_type)), int_t],
                 T_ptr(tydesc_type)),
           vec_grow:
-              dv("vec_grow", [T_ptr(T_ptr(opaque_vec_t)),
-                              int_t]),
+              dv("vec_grow", [T_ptr(T_ptr(opaque_vec_t)), int_t]),
           vec_push:
               dv("vec_push",
                 [T_ptr(T_ptr(opaque_vec_t)), T_ptr(tydesc_type),
@@ -80,18 +86,24 @@ fn decl(llmod: ModuleRef, name: str, tys: [TypeRef], rv: TypeRef) ->
                   T_i8()]),
           log_type:
               dv("log_type", [T_ptr(tydesc_type), T_ptr(T_i8()), T_i32()]),
-          dynastack_mark: d("dynastack_mark", [], T_ptr(T_i8())),
+          dynastack_mark:
+              d("dynastack_mark", [], T_ptr(T_i8())),
           dynastack_alloc:
               d("dynastack_alloc_2", [size_t, T_ptr(tydesc_type)],
                 T_ptr(T_i8())),
-          dynastack_free: dv("dynastack_free", [T_ptr(T_i8())]),
-          alloc_c_stack: d("alloc_c_stack", [size_t], T_ptr(T_i8())),
-          call_shim_on_c_stack: d("call_shim_on_c_stack",
-                                  // arguments: void *args, void *fn_ptr
-                                  [T_ptr(T_i8()), T_ptr(T_i8())],
-                                  int_t),
-          rust_personality: d("rust_personality", [], T_i32()),
-          reset_stack_limit: dv("reset_stack_limit", [])
+          dynastack_free:
+              dv("dynastack_free", [T_ptr(T_i8())]),
+          alloc_c_stack:
+              d("alloc_c_stack", [size_t], T_ptr(T_i8())),
+          call_shim_on_c_stack:
+              d("call_shim_on_c_stack",
+                // arguments: void *args, void *fn_ptr
+                [T_ptr(T_i8()), T_ptr(T_i8())],
+                int_t),
+          rust_personality:
+              d("rust_personality", [], T_i32()),
+          reset_stack_limit:
+              dv("reset_stack_limit", [])
          };
 }
 //
index b8e73b118d052a49c34909b825ca72855d9bab66..95aa6cf3849207f3950dcf119315895f53067fbf 100644 (file)
@@ -2188,19 +2188,20 @@ fn trans_expr_fn(bcx: @block_ctxt, f: ast::_fn, sp: span,
     let s = mangle_internal_name_by_path(ccx, sub_cx.path);
     let llfn = decl_internal_cdecl_fn(ccx.llmod, s, llfnty);
 
-    let copying = alt f.proto {
-      ast::proto_shared(_) | ast::proto_send. { true }
-      ast::proto_bare. | ast::proto_block. { false }
+    let mode = alt f.proto {
+      ast::proto_shared(_) { for_closure }
+      ast::proto_send. { for_send }
+      ast::proto_bare. | ast::proto_block. { for_block }
     };
     let env;
     alt f.proto {
       ast::proto_block. | ast::proto_shared(_) | ast::proto_send. {
         let upvars = get_freevars(ccx.tcx, id);
-        let env_r = build_closure(bcx, upvars, copying);
+        let env_r = build_closure(bcx, upvars, mode);
         env = env_r.ptr;
         bcx = env_r.bcx;
         trans_closure(sub_cx, sp, f, llfn, none, [], id, {|fcx|
-            load_environment(bcx, fcx, env_r.ptrty, upvars, copying);
+            load_environment(bcx, fcx, env_r.ptrty, upvars, mode);
         });
       }
       ast::proto_bare. {
@@ -2560,7 +2561,7 @@ fn inner(bcx: @block_ctxt, local: @ast::local, curr: ValueRef, t: ty::t,
 // Otherwise, it is stack allocated and copies pointers to the upvars.
 fn build_environment(bcx: @block_ctxt, lltydescs: [ValueRef],
                      bound_values: [environment_value],
-                     copying: bool) ->
+                     mode: closure_constr_mode) ->
    {ptr: ValueRef, ptrty: ty::t, bcx: @block_ctxt} {
     let ccx = bcx_ccx(bcx);
     let tcx = bcx_tcx(bcx);
@@ -2602,13 +2603,15 @@ fn build_environment(bcx: @block_ctxt, lltydescs: [ValueRef],
 
     let temp_cleanups = [], bcx = bcx;
     // Allocate a box that can hold something closure-sized.
-    let (closure, box) = if copying {
+    let (closure, box) = alt mode {
+      for_closure. | for_send. {
         let r = trans_malloc_boxed(bcx, closure_ty);
         add_clean_free(bcx, r.box, false);
         temp_cleanups += [r.box];
         bcx = r.bcx;
         (r.body, r.box)
-    } else {
+      }
+      for_block. {
         // We need to dummy up a box on the stack
         let ty = ty::mk_tup(tcx, [ty::mk_int(tcx), closure_ty]);
         let r = alloc_ty(bcx, ty);
@@ -2618,10 +2621,12 @@ fn build_environment(bcx: @block_ctxt, lltydescs: [ValueRef],
               C_int(ccx, 2),
               GEPi(bcx, r.val, [0, abi::box_rc_field_refcnt]));
         (GEPi(bcx, r.val, [0, abi::box_rc_field_body]), r.val)
+      }
     };
 
     // Store bindings tydesc.
-    if copying {
+    alt mode {
+      for_closure. | for_send. {
         let bound_tydesc = GEPi(bcx, closure, [0, abi::closure_elt_tydesc]);
         let ti = none;
         let bindings_tydesc =
@@ -2630,6 +2635,8 @@ fn build_environment(bcx: @block_ctxt, lltydescs: [ValueRef],
         lazily_emit_tydesc_glue(bcx, abi::tydesc_field_free_glue, ti);
         bcx = bindings_tydesc.bcx;
         Store(bcx, bindings_tydesc.val, bound_tydesc);
+      }
+      for_block. {}
     }
 
     // Copy expr values into boxed bindings.
@@ -2651,12 +2658,15 @@ fn build_environment(bcx: @block_ctxt, lltydescs: [ValueRef],
             temp_cleanups += [bound.val];
           }
           env_direct(val, ty, is_mem) {
-            if copying {
+            alt mode {
+              for_closure. | for_send. {
                 let val1 = is_mem ? load_if_immediate(bcx, val, ty) : val;
                 bcx = copy_val(bcx, INIT, bound.val, val1, ty);
-            } else {
+              }
+              for_block. {
                 let addr = is_mem ? val : do_spill_noroot(bcx, val);
                 Store(bcx, addr, bound.val);
+              }
             }
           }
         }
@@ -2675,17 +2685,33 @@ fn build_environment(bcx: @block_ctxt, lltydescs: [ValueRef],
     i = 0u;
     for td: ValueRef in lltydescs {
         let ty_param_slot = GEPi(bcx, ty_params_slot.val, [0, i as int]);
-        Store(bcx, td, ty_param_slot);
+        alt mode {
+          for_closure. | for_block. {
+            Store(bcx, td, ty_param_slot);
+          }
+          for_send. {
+            let cloned_td = Call(bcx, ccx.upcalls.clone_type_desc, [td]);
+            Store(bcx, cloned_td, ty_param_slot);
+          }
+        }
         i += 1u;
     }
 
     ret {ptr: box, ptrty: closure_ty, bcx: bcx};
 }
 
+tag closure_constr_mode {
+    for_block;
+    for_closure;
+    for_send;
+}
+
 // Given a context and a list of upvars, build a closure. This just
 // collects the upvars and packages them up for build_environment.
-fn build_closure(cx: @block_ctxt, upvars: @[ast::def], copying: bool) ->
-   {ptr: ValueRef, ptrty: ty::t, bcx: @block_ctxt} {
+fn build_closure(cx: @block_ctxt,
+                 upvars: @[ast::def],
+                 mode: closure_constr_mode)
+    -> {ptr: ValueRef, ptrty: ty::t, bcx: @block_ctxt} {
     // If we need to, package up the iterator body to call
     let env_vals = [];
     // Package up the upvars
@@ -2693,10 +2719,13 @@ fn build_closure(cx: @block_ctxt, upvars: @[ast::def], copying: bool) ->
         let lv = trans_local_var(cx, def);
         let nid = ast_util::def_id_of_def(def).node;
         let ty = ty::node_id_to_monotype(bcx_tcx(cx), nid);
-        if !copying { ty = ty::mk_mut_ptr(bcx_tcx(cx), ty); }
+        alt mode {
+          for_block. { ty = ty::mk_mut_ptr(bcx_tcx(cx), ty); }
+          for_send. | for_closure. {}
+        }
         env_vals += [env_direct(lv.val, ty, lv.kind == owned)];
     }
-    ret build_environment(cx, copy cx.fcx.lltydescs, env_vals, copying);
+    ret build_environment(cx, copy cx.fcx.lltydescs, env_vals, mode);
 }
 
 // Return a pointer to the stored typarams in a closure.
@@ -2734,7 +2763,7 @@ fn find_environment_tydescs(bcx: @block_ctxt, envty: ty::t, closure: ValueRef)
 // and a list of upvars, generate code to load and populate the environment
 // with the upvars and type descriptors.
 fn load_environment(enclosing_cx: @block_ctxt, fcx: @fn_ctxt, envty: ty::t,
-                    upvars: @[ast::def], copying: bool) {
+                    upvars: @[ast::def], mode: closure_constr_mode) {
     let bcx = new_raw_block_ctxt(fcx, fcx.llloadenv);
 
     let ty = ty::mk_imm_box(bcx_tcx(bcx), envty);
@@ -2769,7 +2798,10 @@ fn load_environment(enclosing_cx: @block_ctxt, fcx: @fn_ctxt, envty: ty::t,
         let upvarptr = GEP_tup_like(bcx, ty, llclosure, path + [i as int]);
         bcx = upvarptr.bcx;
         let llupvarptr = upvarptr.val;
-        if !copying { llupvarptr = Load(bcx, llupvarptr); }
+        alt mode {
+          for_block. { llupvarptr = Load(bcx, llupvarptr); }
+          for_send. | for_closure. { }
+        }
         let def_id = ast_util::def_id_of_def(upvar_def);
         fcx.llupvars.insert(def_id.node, llupvarptr);
         i += 1u;
@@ -3532,7 +3564,8 @@ fn trans_bind_1(cx: @block_ctxt, outgoing_fty: ty::t,
 
     // Actually construct the closure
     let closure = build_environment(bcx, lltydescs, env_vals +
-                                    vec::map({|x| env_expr(x)}, bound), true);
+                                    vec::map({|x| env_expr(x)}, bound),
+                                    for_closure);
     bcx = closure.bcx;
 
     // Make thunk
index 1e65d701e8f31958083f3c8fa55c5430b6f32b79..889b5f62018457ab36a0f2dd9c3040db7ad7af34 100644 (file)
@@ -279,6 +279,8 @@ struct type_desc {
     const type_desc *descs[];
 };
 
+extern "C" type_desc *rust_clone_type_desc(type_desc*);
+
 #include "circular_buffer.h"
 #include "rust_task.h"
 #include "rust_port.h"
index 811a6b36df0eb4947554c1382620847ab5a5ea73..d91e282d2e235ae5b2a8a9d8bf4236fb03c477f6 100644 (file)
@@ -195,6 +195,39 @@ upcall_shared_free(void* ptr) {
     SWITCH_STACK(&args, upcall_s_shared_free);
 }
 
+struct s_clone_type_desc_args {
+    const type_desc *td;
+    type_desc *res;
+};
+
+void upcall_s_clone_type_desc(s_clone_type_desc_args *args)
+{
+    // Copy the main part of the type descriptor:
+    const type_desc *td = args->td;
+    int n_descs = td->n_descs;
+    size_t sz = sizeof(type_desc) + sizeof(type_desc*) * n_descs;
+    args->res = (type_desc*) malloc(sz);
+    memcpy(args->res, td, sizeof(type_desc));
+
+    // Recursively copy any referenced descriptors:
+    for (int i = 0; i < n_descs; i++) {
+        s_clone_type_desc_args rec_args = { td->descs[i], 0 };
+        upcall_s_clone_type_desc(&rec_args);
+        args->res->descs[i] = rec_args.res;
+    }
+}
+
+/**
+ * Called to deep-clone type descriptors so they can be attached to a sendable
+ * function.  Eventually this should perhaps move to a centralized hashtable.
+ */
+type_desc *
+upcall_clone_type_desc(type_desc *td) {
+    s_clone_type_desc_args args = { td, 0 };
+    SWITCH_STACK(&args, upcall_s_clone_type_desc);
+    return args.res;
+}
+
 struct s_get_type_desc_args {
     type_desc *retval;
     size_t size;