@@ -43,8 +43,10 @@ import trans::{
43
43
// };
44
44
// };
45
45
//
46
- // NB: this is defined in the code in T_closure_ptr and
47
- // closure_ty_to_tuple_ty (below).
46
+ // NB: this struct is defined in the code in trans_common::T_closure()
47
+ // and mk_closure_ty() below. The former defines the LLVM version and
48
+ // the latter the Rust equivalent. It occurs to me that these could
49
+ // perhaps be unified, but currently they are not.
48
50
//
49
51
// Note that the closure carries a type descriptor that describes
50
52
// itself. Trippy. This is needed because the precise types of the
@@ -64,8 +66,17 @@ import trans::{
64
66
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
65
67
66
68
tag environment_value {
69
+ // Evaluate expr and store result in env (used for bind).
67
70
env_expr( @ast : : expr) ;
68
- env_direct ( ValueRef , ty:: t, bool) ;
71
+
72
+ // Copy the value from this llvm ValueRef into the environment.
73
+ env_copy ( ValueRef , ty:: t, lval_kind) ;
74
+
75
+ // Move the value from this llvm ValueRef into the environment.
76
+ env_move ( ValueRef , ty:: t, lval_kind) ;
77
+
78
+ // Access by reference (used for blocks).
79
+ env_ref ( ValueRef , ty:: t, lval_kind) ;
69
80
}
70
81
71
82
// Given a closure ty, emits a corresponding tuple ty
@@ -143,8 +154,10 @@ fn store_environment(
143
154
let bound_tys = [ ] ;
144
155
for bv in bound_values {
145
156
bound_tys += [ alt bv {
146
- env_direct( _, t, _) { t }
147
- env_expr ( e) { ty:: expr_ty ( tcx, e) }
157
+ env_copy( _, t, _) { t }
158
+ env_move ( _, t, _) { t }
159
+ env_ref ( _, t, _) { t }
160
+ env_expr ( e) { ty:: expr_ty ( tcx, e) }
148
161
} ] ;
149
162
}
150
163
let bound_data_ty = ty:: mk_tup ( tcx, bound_tys) ;
@@ -239,17 +252,29 @@ fn store_environment(
239
252
add_clean_temp_mem ( bcx, bound. val , bound_tys[ i] ) ;
240
253
temp_cleanups += [ bound. val ] ;
241
254
}
242
- env_direct ( val, ty, is_mem) {
243
- alt ck {
244
- ty: : closure_shared. | ty:: closure_send . {
245
- let val1 = is_mem ? load_if_immediate ( bcx, val, ty) : val;
246
- bcx = trans:: copy_val ( bcx, INIT , bound. val , val1, ty) ;
247
- }
248
- ty:: closure_block. {
249
- let addr = is_mem ? val : do_spill_noroot ( bcx , val ) ;
250
- Store ( bcx, addr, bound. val ) ;
251
- }
252
- }
255
+ env_copy ( val, ty, owned. ) {
256
+ let val1 = load_if_immediate ( bcx, val, ty) ;
257
+ bcx = trans:: copy_val ( bcx, INIT , bound. val , val1, ty) ;
258
+ }
259
+ env_copy ( val, ty, owned_imm. ) {
260
+ bcx = trans:: copy_val ( bcx, INIT , bound. val , val, ty) ;
261
+ }
262
+ env_copy ( _, _, temporary. ) {
263
+ fail "Cannot capture temporary upvar" ;
264
+ }
265
+ env_move ( val, ty, kind) {
266
+ let src = { bcx: bcx, val: val, kind: kind} ;
267
+ bcx = move_val ( bcx, INIT , bound. val , src, ty) ;
268
+ }
269
+ env_ref ( val, ty, owned. ) {
270
+ Store ( bcx, val, bound. val ) ;
271
+ }
272
+ env_ref ( val, ty, owned_imm. ) {
273
+ let addr = do_spill_noroot ( bcx, val) ;
274
+ Store ( bcx, addr, bound. val ) ;
275
+ }
276
+ env_ref ( _, _, temporary. ) {
277
+ fail "Cannot capture temporary upvar" ;
253
278
}
254
279
}
255
280
}
@@ -260,25 +285,38 @@ fn store_environment(
260
285
261
286
// Given a context and a list of upvars, build a closure. This just
262
287
// collects the upvars and packages them up for store_environment.
263
- fn build_closure ( cx : @block_ctxt ,
264
- upvars : freevar_info ,
288
+ fn build_closure ( bcx0 : @block_ctxt ,
289
+ cap_vars : [ capture :: capture_var ] ,
265
290
ck : ty:: closure_kind )
266
291
-> closure_result {
267
292
// If we need to, package up the iterator body to call
268
293
let env_vals = [ ] ;
269
- let tcx = bcx_tcx ( cx) ;
270
- // Package up the upvars
271
- vec:: iter ( * upvars) { |upvar|
272
- let lv = trans_local_var ( cx, upvar. def ) ;
273
- let nid = ast_util:: def_id_of_def ( upvar. def ) . node ;
294
+ let bcx = bcx0;
295
+ let tcx = bcx_tcx ( bcx) ;
296
+
297
+ // Package up the captured upvars
298
+ vec:: iter ( cap_vars) { |cap_var|
299
+ let lv = trans_local_var ( bcx, cap_var. def ) ;
300
+ let nid = ast_util:: def_id_of_def ( cap_var. def ) . node ;
274
301
let ty = ty:: node_id_to_monotype ( tcx, nid) ;
275
- alt ck {
276
- ty: : closure_block. { ty = ty:: mk_mut_ptr ( tcx, ty) ; }
277
- ty:: closure_send. | ty:: closure_shared . { }
302
+ alt cap_var. mode {
303
+ capture:: cap_ref. {
304
+ assert ck == ty:: closure_block;
305
+ ty = ty:: mk_mut_ptr ( tcx, ty) ;
306
+ env_vals += [ env_ref ( lv. val , ty, lv. kind ) ] ;
307
+ }
308
+ capture:: cap_copy. {
309
+ env_vals += [ env_copy ( lv. val , ty, lv. kind ) ] ;
310
+ }
311
+ capture:: cap_move. {
312
+ env_vals += [ env_move ( lv. val , ty, lv. kind ) ] ;
313
+ }
314
+ capture:: cap_drop. {
315
+ bcx = drop_ty ( bcx, lv. val , ty) ;
316
+ }
278
317
}
279
- env_vals += [ env_direct ( lv. val , ty, lv. kind == owned) ] ;
280
318
}
281
- ret store_environment ( cx , copy cx . fcx . lltydescs , env_vals, ck) ;
319
+ ret store_environment( bcx , copy bcx . fcx . lltydescs , env_vals, ck) ;
282
320
}
283
321
284
322
// Given an enclosing block context, a new function context, a closure type,
@@ -287,7 +325,7 @@ fn build_closure(cx: @block_ctxt,
287
325
fn load_environment ( enclosing_cx : @block_ctxt ,
288
326
fcx : @fn_ctxt ,
289
327
boxed_closure_ty : ty:: t ,
290
- upvars : freevar_info ,
328
+ cap_vars : [ capture :: capture_var ] ,
291
329
ck : ty:: closure_kind ) {
292
330
let bcx = new_raw_block_ctxt ( fcx, fcx. llloadenv ) ;
293
331
@@ -311,23 +349,34 @@ fn load_environment(enclosing_cx: @block_ctxt,
311
349
312
350
// Populate the upvars from the environment.
313
351
let path = [ 0 , abi:: box_rc_field_body, abi:: closure_elt_bindings] ;
314
- vec:: iteri ( * upvars) { |i, upvar|
315
- check type_is_tup_like ( bcx, boxed_closure_ty) ;
316
- let upvarptr =
317
- GEP_tup_like ( bcx, boxed_closure_ty, llclosure, path + [ i as int ] ) ;
318
- bcx = upvarptr. bcx ;
319
- let llupvarptr = upvarptr. val ;
320
- alt ck {
321
- ty : : closure_block. { llupvarptr = Load ( bcx, llupvarptr) ; }
322
- ty:: closure_send. | ty:: closure_shared . { }
352
+ let i = 0 u;
353
+ vec:: iter ( cap_vars) { |cap_var|
354
+ alt cap_var. mode {
355
+ capture:: cap_drop. { /* ignore */ }
356
+ _ {
357
+ check type_is_tup_like( bcx, boxed_closure_ty) ;
358
+ let upvarptr = GEP_tup_like (
359
+ bcx, boxed_closure_ty, llclosure, path + [ i as int ] ) ;
360
+ bcx = upvarptr. bcx ;
361
+ let llupvarptr = upvarptr. val ;
362
+ alt ck {
363
+ ty : : closure_block. { llupvarptr = Load ( bcx, llupvarptr) ; }
364
+ ty:: closure_send. | ty:: closure_shared . { }
365
+ }
366
+ let def_id = ast_util:: def_id_of_def ( cap_var. def ) ;
367
+ fcx. llupvars . insert ( def_id. node , llupvarptr) ;
368
+ i += 1 u;
369
+ }
323
370
}
324
- let def_id = ast_util:: def_id_of_def ( upvar. def ) ;
325
- fcx. llupvars . insert ( def_id. node , llupvarptr) ;
326
371
}
327
372
}
328
373
329
- fn trans_expr_fn ( bcx : @block_ctxt , f : ast:: _fn , sp : span ,
330
- id : ast:: node_id , dest : dest ) -> @block_ctxt {
374
+ fn trans_expr_fn( bcx: @block_ctxt,
375
+ f: ast:: _fn,
376
+ sp: span,
377
+ id: ast:: node_id,
378
+ cap_clause: ast:: capture_clause,
379
+ dest: dest) -> @block_ctxt {
331
380
if dest == ignore { ret bcx; }
332
381
let ccx = bcx_ccx ( bcx) , bcx = bcx;
333
382
let fty = node_id_type ( ccx, id) ;
@@ -339,10 +388,11 @@ fn trans_expr_fn(bcx: @block_ctxt, f: ast::_fn, sp: span,
339
388
register_fn ( ccx, sp, sub_cx. path , "anon fn" , [ ] , id) ;
340
389
341
390
let trans_closure_env = lambda ( ck: ty:: closure_kind) -> ValueRef {
342
- let upvars = get_freevars ( ccx. tcx , id) ;
343
- let { llbox, box_ty, bcx} = build_closure ( bcx, upvars, ck) ;
391
+ let cap_vars = capture:: compute_capture_vars (
392
+ ccx. tcx , id, f. proto , cap_clause) ;
393
+ let { llbox, box_ty, bcx} = build_closure ( bcx, cap_vars, ck) ;
344
394
trans_closure ( sub_cx, sp, f, llfn, no_self, [ ] , id, { |fcx|
345
- load_environment ( bcx, fcx, box_ty, upvars , ck) ;
395
+ load_environment ( bcx, fcx, box_ty, cap_vars , ck) ;
346
396
} ) ;
347
397
llbox
348
398
} ;
@@ -420,7 +470,7 @@ fn trans_bind_1(cx: @block_ctxt, outgoing_fty: ty::t,
420
470
let sp = cx. sp ;
421
471
let llclosurety = T_ptr ( type_of ( ccx, sp, outgoing_fty) ) ;
422
472
let src_loc = PointerCast ( bcx, cl, llclosurety) ;
423
- ( [ env_direct ( src_loc, pair_ty, true ) ] , none)
473
+ ( [ env_copy ( src_loc, pair_ty, owned ) ] , none)
424
474
}
425
475
none. { ( [ ] , some ( f_res. val ) ) }
426
476
} ;
0 commit comments