@@ -3720,6 +3720,19 @@ fn build_environment_heap(bcx: @block_ctxt, lltydescs: ValueRef[],
3720
3720
ret { ptr : r. box , ptrty : closure_ty, bcx : bcx} ;
3721
3721
}
3722
3722
3723
+ fn build_copying_closure ( cx : & @block_ctxt , upvars : & @ast:: node_id [ ] )
3724
+ -> { ptr : ValueRef , ptrty : ty:: t , bcx : @block_ctxt } {
3725
+ let closure_vals: lval_result [ ] = ~[ ] ;
3726
+ let closure_tys: ty:: t [ ] = ~[ ] ;
3727
+ for nid: ast:: node_id in * upvars {
3728
+ closure_vals += ~[ trans_var ( cx, cx. sp , nid) ] ;
3729
+ closure_tys += ~[ ty:: node_id_to_monotype ( bcx_tcx ( cx) , nid) ] ;
3730
+ }
3731
+
3732
+ ret build_environment_heap ( cx, cx. fcx . lltydescs ,
3733
+ closure_tys, closure_vals) ;
3734
+ }
3735
+
3723
3736
// Given a block context and a list of upvars, construct a closure that
3724
3737
// contains pointers to all of the upvars and all of the tydescs in
3725
3738
// scope. Return the ValueRef and TypeRef corresponding to the closure.
@@ -3785,6 +3798,43 @@ fn build_environment(cx: &@block_ctxt, upvars: &@ast::node_id[]) ->
3785
3798
ret { ptr : llenvptr, ptrty : llenvptrty} ;
3786
3799
}
3787
3800
3801
+ fn load_environment_heap ( enclosing_cx : & @block_ctxt , fcx : & @fn_ctxt ,
3802
+ envty : & ty:: t , upvars : & @ast:: node_id [ ] ) {
3803
+ let bcx = new_raw_block_ctxt ( fcx, fcx. llcopyargs ) ;
3804
+
3805
+ let llenvptr =
3806
+ bcx. build . GEP ( fcx. llenv , ~[ C_int ( 0 ) , C_int ( abi:: box_rc_field_body) ] ) ;
3807
+ let llenvptrty = T_ptr ( type_of ( bcx_ccx ( bcx) , bcx. sp , envty) ) ; ;
3808
+ llenvptr = bcx. build . PointerCast ( llenvptr, llenvptrty) ;
3809
+
3810
+ // Populate the upvars from the environment.
3811
+ let llbindingsptr =
3812
+ bcx. build . GEP ( llenvptr,
3813
+ ~[ C_int ( 0 ) , C_int ( abi:: closure_elt_bindings) ] ) ;
3814
+ let i = 0 u;
3815
+ for upvar_id: ast:: node_id in * upvars {
3816
+ let llupvarptr =
3817
+ bcx. build . GEP ( llbindingsptr, ~[ C_int ( 0 ) , C_int ( i as int ) ] ) ;
3818
+ let def_id = ast:: def_id_of_def ( bcx_tcx ( bcx) . def_map . get ( upvar_id) ) ;
3819
+ fcx. llupvars . insert ( def_id. node , llupvarptr) ;
3820
+ i += 1 u;
3821
+ }
3822
+
3823
+ // Populate the type parameters from the environment.
3824
+ let lltydescsptr =
3825
+ bcx. build . GEP ( llenvptr,
3826
+ ~[ C_int ( 0 ) , C_int ( abi:: closure_elt_ty_params) ] ) ;
3827
+ let tydesc_count = std:: ivec:: len ( enclosing_cx. fcx . lltydescs ) ;
3828
+ i = 0 u;
3829
+ while i < tydesc_count {
3830
+ let lltydescptr =
3831
+ bcx. build . GEP ( lltydescsptr, ~[ C_int ( 0 ) , C_int ( i as int ) ] ) ;
3832
+ fcx. lltydescs += ~[ bcx. build . Load ( lltydescptr) ] ;
3833
+ i += 1 u;
3834
+ }
3835
+ }
3836
+
3837
+
3788
3838
// Given an enclosing block context, a new function context, a closure type,
3789
3839
// and a list of upvars, generate code to load and populate the environment
3790
3840
// with the upvars and type descriptors.
@@ -6399,21 +6449,24 @@ fn trans_closure(bcx_maybe: &option::t[@block_ctxt],
6399
6449
// Figure out if we need to build a closure and act accordingly
6400
6450
let closure = none;
6401
6451
alt f. proto {
6402
- ast:: proto_block. {
6452
+ ast:: proto_block. | ast :: proto_closure . {
6403
6453
let bcx = option:: get ( bcx_maybe) ;
6404
6454
let upvars = get_freevars ( cx. ccx . tcx , id) ;
6405
6455
6406
- let llenv = build_environment ( bcx, upvars) ;
6456
+ let llenvptr = if ( f. proto == ast:: proto_block) {
6457
+ let llenv = build_environment ( bcx, upvars) ;
6458
+ load_environment ( bcx, fcx, llenv. ptrty , upvars) ;
6459
+ llenv. ptr
6460
+ } else {
6461
+ let llenv = build_copying_closure ( bcx, upvars) ;
6462
+ load_environment_heap ( bcx, fcx, llenv. ptrty , upvars) ;
6463
+ llenv. ptr
6464
+ } ;
6407
6465
6408
- // Generate code to load the environment out of the
6409
- // environment pointer.
6410
- load_environment ( bcx, fcx, llenv. ptrty , upvars) ;
6411
- // Build the closure.
6412
6466
closure =
6413
6467
some ( create_real_fn_pair ( bcx, option:: get ( llfnty) , llfndecl,
6414
- llenv . ptr ) ) ;
6468
+ llenvptr ) ) ;
6415
6469
}
6416
- ast:: proto_closure. { fail "copy capture not implemented yet" ; }
6417
6470
_ { }
6418
6471
}
6419
6472
0 commit comments