@@ -3008,12 +3008,49 @@ fn trans_for_each(@block_ctxt cx,
3008
3008
}
3009
3009
3010
3010
auto upvars = collect_upvars( cx, body, decl_id) ;
3011
- if ( _vec. len[ ast. def_id] ( upvars) > 0 u) {
3012
- cx. fcx. ccx. sess. unimpl( "upvars in for each") ;
3013
- fail;
3011
+ auto upvar_count = _vec. len[ ast. def_id] ( upvars) ;
3012
+
3013
+ auto llbindingsptr;
3014
+ if ( upvar_count > 0 u) {
3015
+ // Gather up the upvars.
3016
+ let vec[ ValueRef ] llbindings = vec( ) ;
3017
+ let vec[ TypeRef ] llbindingtys = vec( ) ;
3018
+ for ( ast. def_id did in upvars) {
3019
+ auto llbinding;
3020
+ alt ( cx. fcx. lllocals. find( did) ) {
3021
+ case ( none[ ValueRef ] ) {
3022
+ llbinding = cx. fcx. llupvars. get( did) ;
3023
+ }
3024
+ case ( some[ ValueRef ] ( ?llval) ) { llbinding = llval; }
3025
+ }
3026
+ llbindings += vec( llbinding) ;
3027
+ llbindingtys += vec( val_ty( llbinding) ) ;
3028
+ }
3029
+
3030
+ // Create an array of bindings and copy in aliases to the upvars.
3031
+ llbindingsptr = cx. build. Alloca ( T_struct ( llbindingtys) ) ;
3032
+ auto i = 0 u;
3033
+ while ( i < upvar_count) {
3034
+ auto llbindingptr = cx. build. GEP ( llbindingsptr,
3035
+ vec( C_int ( 0 ) , C_int ( i as int) ) ) ;
3036
+ cx. build. Store ( llbindings. ( i) , llbindingptr) ;
3037
+ i += 1 u;
3038
+ }
3039
+ } else {
3040
+ // Null bindings.
3041
+ llbindingsptr = C_null ( T_ptr ( T_i8 ( ) ) ) ;
3014
3042
}
3015
3043
3016
- auto env_ty = T_opaque_closure_ptr ( cx. fcx. ccx. tn) ;
3044
+ // Create an environment and populate it with the bindings.
3045
+ auto llenvptrty = T_closure_ptr ( cx. fcx. ccx. tn, T_ptr ( T_nil ( ) ) ,
3046
+ val_ty( llbindingsptr) , 0 u) ;
3047
+ auto llenvptr = cx. build. Alloca ( llvm. LLVMGetElementType ( llenvptrty) ) ;
3048
+
3049
+ auto llbindingsptrptr = cx. build. GEP ( llenvptr,
3050
+ vec( C_int ( 0 ) ,
3051
+ C_int ( abi. box_rc_field_body) ,
3052
+ C_int ( 2 ) ) ) ;
3053
+ cx. build. Store ( llbindingsptr, llbindingsptrptr) ;
3017
3054
3018
3055
// Step 2: Declare foreach body function.
3019
3056
@@ -3041,7 +3078,30 @@ fn trans_for_each(@block_ctxt cx,
3041
3078
auto fcx = new_fn_ctxt( cx. fcx. ccx, lliterbody) ;
3042
3079
auto bcx = new_top_block_ctxt( fcx) ;
3043
3080
3044
- // FIXME: populate lllocals from llenv here.
3081
+ // Populate the upvars from the environment.
3082
+ auto llremoteenvptr = bcx. build. PointerCast ( fcx. llenv, llenvptrty) ;
3083
+ auto llremotebindingsptrptr = bcx. build. GEP ( llremoteenvptr,
3084
+ vec( C_int ( 0 ) , C_int ( abi. box_rc_field_body) , C_int ( 2 ) ) ) ;
3085
+ auto llremotebindingsptr = bcx. build. Load ( llremotebindingsptrptr) ;
3086
+
3087
+ auto i = 0 u;
3088
+ while ( i < upvar_count) {
3089
+ auto upvar_id = upvars. ( i) ;
3090
+ auto llupvarptrptr = bcx. build. GEP ( llremotebindingsptr,
3091
+ vec( C_int ( 0 ) , C_int ( i as int) ) ) ;
3092
+ auto llupvarptr = bcx. build. Load ( llupvarptrptr) ;
3093
+ fcx. llupvars. insert( upvar_id, llupvarptr) ;
3094
+
3095
+ i += 1 u;
3096
+ }
3097
+
3098
+ // Treat the loop variable as an upvar as well. We copy it to an alloca
3099
+ // as usual.
3100
+ auto lllvar = llvm. LLVMGetParam ( fcx. llfn, 3 u) ;
3101
+ auto lllvarptr = bcx. build. Alloca ( val_ty( lllvar) ) ;
3102
+ bcx. build. Store ( lllvar, lllvarptr) ;
3103
+ fcx. llupvars. insert( decl_id, lllvarptr) ;
3104
+
3045
3105
auto res = trans_block( bcx, body) ;
3046
3106
res. bcx. build. RetVoid ( ) ;
3047
3107
@@ -3059,6 +3119,12 @@ fn trans_for_each(@block_ctxt cx,
3059
3119
C_int ( abi. fn_field_code) ) ) ;
3060
3120
cx. build. Store ( lliterbody, code_cell) ;
3061
3121
3122
+ auto env_cell = cx. build. GEP ( pair, vec( C_int ( 0 ) ,
3123
+ C_int ( abi. fn_field_box) ) ) ;
3124
+ auto llenvblobptr = cx. build. PointerCast ( llenvptr,
3125
+ T_opaque_closure_ptr ( cx. fcx. ccx. tn) ) ;
3126
+ cx. build. Store ( llenvblobptr, env_cell) ;
3127
+
3062
3128
// log "lliterbody: " + val_str(cx.fcx.ccx.tn, lliterbody);
3063
3129
ret trans_call( cx, f,
3064
3130
some[ ValueRef ] ( cx. build. Load ( pair) ) ,
0 commit comments