@@ -145,11 +145,7 @@ fn type_of_fn_full(cx: &@crate_ctxt, sp: &span, proto: ast::proto,
145
145
// *input* type of the function we're given as our iter-block
146
146
// argument.
147
147
atys +=
148
- ~[ T_fn_pair ( * cx,
149
- type_of_fn_full ( cx, sp, ast:: proto_fn, false ,
150
- ~[ { mode: ty:: mo_alias ( false ) ,
151
- ty: output} ] , ty:: mk_nil ( cx. tcx ) ,
152
- 0 u) ) ] ;
148
+ ~[ type_of_inner ( cx, sp, ty:: mk_iter_body_fn ( cx. tcx , output) ) ] ;
153
149
}
154
150
155
151
// ... then explicit args.
@@ -863,15 +859,13 @@ fn trans_malloc_boxed_raw(cx: &@block_ctxt, t: ty::t) -> result {
863
859
// trans_malloc_boxed: usefully wraps trans_malloc_box_raw; allocates a box,
864
860
// initializes the reference count to 1, and pulls out the body and rc
865
861
fn trans_malloc_boxed ( cx : & @block_ctxt , t : ty:: t ) ->
866
- { bcx : @block_ctxt , box : ValueRef , rc : ValueRef , body : ValueRef } {
862
+ { bcx : @block_ctxt , box : ValueRef , body : ValueRef } {
867
863
let res = trans_malloc_boxed_raw ( cx, t) ;
868
864
let box = res. val ;
869
- let rc = res. bcx . build . GEP ( box,
870
- ~[ C_int ( 0 ) , C_int ( abi:: box_rc_field_refcnt) ] ) ;
865
+ let rc = GEPi ( res. bcx , box, ~[ 0 , abi:: box_rc_field_refcnt] ) ;
871
866
res. bcx . build . Store ( C_int ( 1 ) , rc) ;
872
- let body = res. bcx . build . GEP ( box,
873
- ~[ C_int ( 0 ) , C_int ( abi:: box_rc_field_body) ] ) ;
874
- ret { bcx : res. bcx , box : res. val , rc : rc, body : body} ;
867
+ let body = GEPi ( res. bcx , box, ~[ 0 , abi:: box_rc_field_body] ) ;
868
+ ret { bcx : res. bcx , box : res. val , body : body} ;
875
869
}
876
870
877
871
// Type descriptor and type glue stuff
@@ -3645,11 +3639,13 @@ fn trans_for(cx: &@block_ctxt, local: &@ast::local, seq: &@ast::expr,
3645
3639
3646
3640
// Iterator translation
3647
3641
3648
- // build_environment_heap and build_environment are very similar. It
3649
- // would be nice to unify them.
3650
-
3651
- fn build_environment_heap ( bcx : @block_ctxt , lltydescs : ValueRef [ ] ,
3652
- bound_tys : ty:: t [ ] , bound_vals : lval_result [ ] )
3642
+ // Given a block context and a list of tydescs and values to bind
3643
+ // construct a closure out of them. If copying is true, it is a
3644
+ // heap allocated closure that copies the upvars into environment.
3645
+ // Otherwise, it is stack allocated and copies pointers to the upvars.
3646
+ fn build_environment ( bcx : @block_ctxt , lltydescs : ValueRef [ ] ,
3647
+ bound_tys : ty:: t [ ] , bound_vals : lval_result [ ] ,
3648
+ copying : bool )
3653
3649
-> { ptr : ValueRef , ptrty : ty:: t , bcx : @block_ctxt } {
3654
3650
// Synthesize a closure type.
3655
3651
@@ -3682,18 +3678,29 @@ fn build_environment_heap(bcx: @block_ctxt, lltydescs: ValueRef[],
3682
3678
let closure_ty: ty:: t = ty:: mk_imm_tup ( bcx_tcx ( bcx) , closure_tys) ;
3683
3679
3684
3680
// Allocate a box that can hold something closure-sized.
3685
- let r = trans_malloc_boxed ( bcx, closure_ty) ;
3681
+ let r = if copying {
3682
+ trans_malloc_boxed ( bcx, closure_ty)
3683
+ } else {
3684
+ // We need to dummy up a box on the stack
3685
+ let ty = ty:: mk_imm_tup ( bcx_tcx ( bcx) ,
3686
+ ~[ ty:: mk_int ( bcx_tcx ( bcx) ) , closure_ty] ) ;
3687
+ let r = alloc_ty ( bcx, ty) ;
3688
+ let body = GEPi ( bcx, r. val , ~[ 0 , abi:: box_rc_field_body] ) ;
3689
+ { bcx: r. bcx , box: r. val , body: body}
3690
+ } ;
3686
3691
bcx = r. bcx ;
3687
3692
let closure = r. body ;
3688
3693
3689
3694
// Store bindings tydesc.
3690
- let bound_tydesc = GEPi ( bcx, closure, ~[ 0 , abi:: closure_elt_tydesc] ) ;
3691
- let ti = none;
3692
- let bindings_tydesc = get_tydesc ( bcx, bindings_ty, true , ti) ;
3693
- lazily_emit_tydesc_glue ( bcx, abi:: tydesc_field_drop_glue, ti) ;
3694
- lazily_emit_tydesc_glue ( bcx, abi:: tydesc_field_free_glue, ti) ;
3695
- bcx = bindings_tydesc. bcx ;
3696
- bcx. build . Store ( bindings_tydesc. val , bound_tydesc) ;
3695
+ if copying {
3696
+ let bound_tydesc = GEPi ( bcx, closure, ~[ 0 , abi:: closure_elt_tydesc] ) ;
3697
+ let ti = none;
3698
+ let bindings_tydesc = get_tydesc ( bcx, bindings_ty, true , ti) ;
3699
+ lazily_emit_tydesc_glue ( bcx, abi:: tydesc_field_drop_glue, ti) ;
3700
+ lazily_emit_tydesc_glue ( bcx, abi:: tydesc_field_free_glue, ti) ;
3701
+ bcx = bindings_tydesc. bcx ;
3702
+ bcx. build . Store ( bindings_tydesc. val , bound_tydesc) ;
3703
+ }
3697
3704
3698
3705
// Copy expr values into boxed bindings.
3699
3706
let i = 0 u;
@@ -3704,8 +3711,13 @@ fn build_environment_heap(bcx: @block_ctxt, lltydescs: ValueRef[],
3704
3711
for lv: lval_result in bound_vals {
3705
3712
let bound = GEP_tup_like ( bcx, bindings_ty, bindings. val ,
3706
3713
~[ 0 , i as int ] ) ;
3707
- bcx = move_val_if_temp ( bound. bcx , INIT ,
3708
- bound. val , lv, bound_tys. ( i) ) . bcx ;
3714
+ bcx = bound. bcx ;
3715
+ if copying {
3716
+ bcx = move_val_if_temp ( bcx, INIT ,
3717
+ bound. val , lv, bound_tys. ( i) ) . bcx ;
3718
+ } else {
3719
+ bcx. build . Store ( lv. res . val , bound. val ) ;
3720
+ }
3709
3721
i += 1 u;
3710
3722
}
3711
3723
@@ -3725,78 +3737,27 @@ fn build_environment_heap(bcx: @block_ctxt, lltydescs: ValueRef[],
3725
3737
ret { ptr : r. box , ptrty : closure_ty, bcx : bcx} ;
3726
3738
}
3727
3739
3728
- fn build_copying_closure ( cx : & @block_ctxt , upvars : & @ast:: node_id [ ] )
3740
+ // Given a context and a list of upvars, build a closure. This just
3741
+ // collects the upvars and packages them up for build_environment.
3742
+ fn build_closure ( cx : & @block_ctxt , upvars : & @ast:: node_id [ ] , copying : bool )
3729
3743
-> { ptr : ValueRef , ptrty : ty:: t , bcx : @block_ctxt } {
3730
3744
let closure_vals: lval_result [ ] = ~[ ] ;
3731
3745
let closure_tys: ty:: t [ ] = ~[ ] ;
3732
- for nid: ast:: node_id in * upvars {
3733
- closure_vals += ~[ trans_var ( cx, cx. sp , nid) ] ;
3734
- closure_tys += ~[ ty:: node_id_to_monotype ( bcx_tcx ( cx) , nid) ] ;
3735
- }
3736
-
3737
- ret build_environment_heap ( cx, cx. fcx . lltydescs ,
3738
- closure_tys, closure_vals) ;
3739
- }
3740
-
3741
- // Given a block context and a list of upvars, construct a closure that
3742
- // contains pointers to all of the upvars and all of the tydescs in
3743
- // scope. Return the ValueRef and TypeRef corresponding to the closure.
3744
- fn build_environment ( cx : & @block_ctxt , upvars : & @ast:: node_id [ ] ) ->
3745
- { ptr : ValueRef , ptrty : TypeRef } {
3746
- let has_iterbody = !option:: is_none ( cx. fcx . lliterbody ) ;
3747
- let llbindingsptr;
3748
-
3749
- if std:: ivec:: len ( * upvars) > 0 u || has_iterbody {
3750
- // Gather up the upvars.
3751
- let llbindings: ValueRef [ ] = ~[ ] ;
3752
- let llbindingtys: TypeRef [ ] = ~[ ] ;
3753
- if has_iterbody {
3754
- llbindings += ~[ option:: get ( cx. fcx . lliterbody ) ] ;
3755
- llbindingtys += ~[ val_ty ( llbindings. ( 0 ) ) ] ;
3746
+ // If we need to, package up the iterator body to call
3747
+ if !copying && !option:: is_none ( cx. fcx . lliterbody ) {
3748
+ closure_vals += ~[ lval_mem ( cx, option:: get ( cx. fcx . lliterbody ) ) ] ;
3749
+ closure_tys += ~[ option:: get ( cx. fcx . iterbodyty ) ] ;
3756
3750
}
3751
+ // Package up the upvars
3757
3752
for nid: ast:: node_id in * upvars {
3758
- let llbinding = trans_var ( cx, cx. sp , nid) . res . val ;
3759
- llbindings += ~[ llbinding] ;
3760
- llbindingtys += ~[ val_ty ( llbinding) ] ;
3761
- }
3762
-
3763
- // Create an array of bindings and copy in aliases to the upvars.
3764
- llbindingsptr = alloca ( cx, T_struct ( llbindingtys) ) ;
3765
- let upvar_count = std:: ivec:: len ( llbindings) ;
3766
- let i = 0 u;
3767
- while i < upvar_count {
3768
- let llbindingptr = GEPi ( cx, llbindingsptr, ~[ 0 , i as int ] ) ;
3769
- cx. build . Store ( llbindings. ( i) , llbindingptr) ;
3770
- i += 1 u;
3753
+ closure_vals += ~[ trans_var ( cx, cx. sp , nid) ] ;
3754
+ let ty = ty:: node_id_to_monotype ( bcx_tcx ( cx) , nid) ;
3755
+ if !copying { ty = ty:: mk_mut_ptr ( bcx_tcx ( cx) , ty) ; }
3756
+ closure_tys += ~[ ty] ;
3771
3757
}
3772
- } else {
3773
- // Null bindings.
3774
- llbindingsptr = C_null ( T_ptr ( T_i8 ( ) ) ) ;
3775
- }
3776
-
3777
- // Create an environment and populate it with the bindings.
3778
- let tydesc_count = std:: ivec:: len ( cx. fcx . lltydescs ) ;
3779
- let llenvptrty =
3780
- T_closure_ptr ( * bcx_ccx ( cx) , val_ty ( llbindingsptr) , tydesc_count) ;
3781
- let llenvptr = alloca ( cx, llvm:: LLVMGetElementType ( llenvptrty) ) ;
3782
- let llbindingsptrptr =
3783
- GEPi ( cx, llenvptr,
3784
- ~[ 0 , abi:: box_rc_field_body, abi:: closure_elt_bindings] ) ;
3785
- cx. build . Store ( llbindingsptr, llbindingsptrptr) ;
3786
-
3787
- // Copy in our type descriptors, in case the iterator body needs to refer
3788
- // to them.
3789
- let lltydescsptr =
3790
- GEPi ( cx, llenvptr,
3791
- ~[ 0 , abi:: box_rc_field_body, abi:: closure_elt_ty_params] ) ;
3792
- let i = 0 u;
3793
- while i < tydesc_count {
3794
- let lltydescptr = GEPi ( cx, lltydescsptr, ~[ 0 , i as int ] ) ;
3795
- cx. build . Store ( cx. fcx . lltydescs . ( i) , lltydescptr) ;
3796
- i += 1 u;
3797
- }
3798
3758
3799
- ret { ptr : llenvptr, ptrty : llenvptrty} ;
3759
+ ret build_environment ( cx, cx. fcx . lltydescs ,
3760
+ closure_tys, closure_vals, copying) ;
3800
3761
}
3801
3762
3802
3763
// Return a pointer to the stored typarams in a closure.
@@ -3829,8 +3790,12 @@ fn find_environment_tydescs(bcx: &@block_ctxt, envty: &ty::t,
3829
3790
}
3830
3791
}
3831
3792
3832
- fn load_environment_heap ( enclosing_cx : & @block_ctxt , fcx : & @fn_ctxt ,
3833
- envty : & ty:: t , upvars : & @ast:: node_id [ ] ) {
3793
+ // Given an enclosing block context, a new function context, a closure type,
3794
+ // and a list of upvars, generate code to load and populate the environment
3795
+ // with the upvars and type descriptors.
3796
+ fn load_environment ( enclosing_cx : & @block_ctxt , fcx : & @fn_ctxt ,
3797
+ envty : & ty:: t , upvars : & @ast:: node_id [ ] ,
3798
+ copying : bool ) {
3834
3799
let bcx = new_raw_block_ctxt ( fcx, fcx. llcopyargs ) ;
3835
3800
3836
3801
let ty = ty:: mk_imm_box ( bcx_tcx ( bcx) , envty) ;
@@ -3852,54 +3817,25 @@ fn load_environment_heap(enclosing_cx: &@block_ctxt, fcx: &@fn_ctxt,
3852
3817
// Populate the upvars from the environment.
3853
3818
let path = ~[ 0 , abi:: box_rc_field_body, abi:: closure_elt_bindings] ;
3854
3819
i = 0 u;
3855
- for upvar_id : ast :: node_id in * upvars {
3856
- let llupvarptr =
3857
- GEP_tup_like ( bcx , ty , llclosure , path + ~ [ i as int ] ) ;
3858
- bcx = llupvarptr . bcx ;
3859
- let def_id = ast :: def_id_of_def ( bcx_tcx ( bcx) . def_map . get ( upvar_id ) ) ;
3860
- fcx . llupvars . insert ( def_id . node , llupvarptr . val ) ;
3820
+ // If this is an aliasing closure/for-each body, we need to load
3821
+ // the iterbody.
3822
+ if !copying && !option :: is_none ( enclosing_cx . fcx . lliterbody ) {
3823
+ let iterbodyptr = GEP_tup_like ( bcx, ty , llclosure , path + ~ [ 0 ] ) ;
3824
+ fcx . lliterbody = some ( bcx. build . Load ( iterbodyptr . val ) ) ;
3825
+ bcx = iterbodyptr . bcx ;
3861
3826
i += 1 u;
3862
3827
}
3863
- }
3864
-
3865
-
3866
- // Given an enclosing block context, a new function context, a closure type,
3867
- // and a list of upvars, generate code to load and populate the environment
3868
- // with the upvars and type descriptors.
3869
- fn load_environment ( enclosing_cx : & @block_ctxt , fcx : & @fn_ctxt ,
3870
- llenvptrty : TypeRef , upvars : & @ast:: node_id [ ] ) {
3871
- let bcx = new_raw_block_ctxt ( fcx, fcx. llcopyargs ) ;
3872
-
3873
- // Populate the upvars from the environment.
3874
- let llenvptr = bcx. build . PointerCast ( fcx. llenv , llenvptrty) ;
3875
- llenvptr = GEPi ( bcx, llenvptr, ~[ 0 , abi:: box_rc_field_body] ) ;
3876
- let llbindingsptrptr =
3877
- GEPi ( bcx, llenvptr, ~[ 0 , abi:: closure_elt_bindings] ) ;
3878
- let llbindingsptr = bcx. build . Load ( llbindingsptrptr) ;
3879
-
3880
- let i = 0 u;
3881
- if !option:: is_none ( enclosing_cx. fcx . lliterbody ) {
3882
- i += 1 u;
3883
- let lliterbodyptr = GEPi ( bcx, llbindingsptr, ~[ 0 , 0 ] ) ;
3884
- fcx. lliterbody = some ( bcx. build . Load ( lliterbodyptr) ) ;
3885
- }
3828
+ // Load the acutal upvars.
3886
3829
for upvar_id: ast:: node_id in * upvars {
3887
- let llupvarptrptr = GEPi ( bcx, llbindingsptr, ~[ 0 , i as int ] ) ;
3888
- let llupvarptr = bcx. build . Load ( llupvarptrptr) ;
3830
+ let upvarptr =
3831
+ GEP_tup_like ( bcx, ty, llclosure, path + ~[ i as int ] ) ;
3832
+ bcx = upvarptr. bcx ;
3833
+ let llupvarptr = upvarptr. val ;
3834
+ if !copying { llupvarptr = bcx. build . Load ( llupvarptr) ; }
3889
3835
let def_id = ast:: def_id_of_def ( bcx_tcx ( bcx) . def_map . get ( upvar_id) ) ;
3890
3836
fcx. llupvars . insert ( def_id. node , llupvarptr) ;
3891
3837
i += 1 u;
3892
3838
}
3893
-
3894
- // Populate the type parameters from the environment.
3895
- let lltydescsptr = GEPi ( bcx, llenvptr, ~[ 0 , abi:: closure_elt_ty_params] ) ;
3896
- let tydesc_count = std:: ivec:: len ( enclosing_cx. fcx . lltydescs ) ;
3897
- i = 0 u;
3898
- while i < tydesc_count {
3899
- let lltydescptr = GEPi ( bcx, lltydescsptr, ~[ 0 , i as int ] ) ;
3900
- fcx. lltydescs += ~[ bcx. build . Load ( lltydescptr) ] ;
3901
- i += 1 u;
3902
- }
3903
3839
}
3904
3840
3905
3841
fn trans_for_each ( cx : & @block_ctxt , local : & @ast:: local , seq : & @ast:: expr ,
@@ -3934,7 +3870,7 @@ fn trans_for_each(cx: &@block_ctxt, local: &@ast::local, seq: &@ast::expr,
3934
3870
let decl_ty = node_id_type ( lcx. ccx , local. node . id ) ;
3935
3871
let upvars = get_freevars ( lcx. ccx . tcx , body. node . id ) ;
3936
3872
3937
- let llenv = build_environment ( cx, upvars) ;
3873
+ let llenv = build_closure ( cx, upvars, false ) ;
3938
3874
3939
3875
// Step 2: Declare foreach body function.
3940
3876
let s: str =
@@ -3946,16 +3882,16 @@ fn trans_for_each(cx: &@block_ctxt, local: &@ast::local, seq: &@ast::expr,
3946
3882
// pointer along with the foreach-body-fn pointer into a 'normal' fn pair
3947
3883
// and pass it in as a first class fn-arg to the iterator.
3948
3884
let iter_body_llty =
3949
- type_of_fn_full ( lcx. ccx , cx. sp , ast:: proto_fn, false ,
3950
- ~[ { mode: ty:: mo_alias ( false ) , ty: decl_ty} ] ,
3951
- ty:: mk_nil ( lcx. ccx . tcx ) , 0 u) ;
3885
+ type_of_fn_from_ty ( lcx. ccx , cx. sp ,
3886
+ ty:: mk_iter_body_fn ( lcx. ccx . tcx , decl_ty) , 0 u) ;
3952
3887
let lliterbody: ValueRef =
3953
3888
decl_internal_fastcall_fn ( lcx. ccx . llmod , s, iter_body_llty) ;
3954
3889
let fcx = new_fn_ctxt_w_id ( lcx, cx. sp , lliterbody, body. node . id ) ;
3890
+ fcx. iterbodyty = cx. fcx . iterbodyty ;
3955
3891
3956
3892
// Generate code to load the environment out of the
3957
3893
// environment pointer.
3958
- load_environment ( cx, fcx, llenv. ptrty , upvars) ;
3894
+ load_environment ( cx, fcx, llenv. ptrty , upvars, false ) ;
3959
3895
3960
3896
let bcx = new_top_block_ctxt ( fcx) ;
3961
3897
// Add bindings for the loop variable alias.
@@ -4684,8 +4620,8 @@ fn trans_bind_1(cx: &@block_ctxt, f: &@ast::expr, f_res: &lval_result,
4684
4620
}
4685
4621
4686
4622
// Actually construct the closure
4687
- let closure = build_environment_heap ( bcx, lltydescs,
4688
- bound_tys, bound_vals) ;
4623
+ let closure = build_environment ( bcx, lltydescs,
4624
+ bound_tys, bound_vals, true ) ;
4689
4625
bcx = closure. bcx ;
4690
4626
4691
4627
// Make thunk
@@ -6236,6 +6172,7 @@ fn new_fn_ctxt_w_id(cx: @local_ctxt, sp: &span, llfndecl: ValueRef,
6236
6172
mutable lldynamicallocas : llbbs. da ,
6237
6173
mutable llself: none[ val_self_pair] ,
6238
6174
mutable lliterbody : none[ ValueRef ] ,
6175
+ mutable iterbodyty : none[ ty:: t] ,
6239
6176
llargs : llargs,
6240
6177
llobjfields : llobjfields,
6241
6178
lllocals : lllocals,
@@ -6271,7 +6208,6 @@ fn create_llargs_for_fn_args(cx: &@fn_ctxt, proto: ast::proto,
6271
6208
// Skip the implicit arguments 0, 1, and 2. TODO: Pull out 3u and define
6272
6209
// it as a constant, since we're using it in several places in trans this
6273
6210
// way.
6274
-
6275
6211
let arg_n = 3 u;
6276
6212
alt ty_self {
6277
6213
some( tt) { cx. llself = some[ val_self_pair] ( { v: cx. llenv , t: tt} ) ; }
@@ -6286,18 +6222,18 @@ fn create_llargs_for_fn_args(cx: &@fn_ctxt, proto: ast::proto,
6286
6222
}
6287
6223
}
6288
6224
}
6225
+
6289
6226
// If the function is actually an iter, populate the lliterbody field of
6290
6227
// the function context with the ValueRef that we get from
6291
6228
// llvm::LLVMGetParam for the iter's body.
6292
-
6293
6229
if proto == ast:: proto_iter {
6230
+ cx. iterbodyty = some ( ty:: mk_iter_body_fn ( fcx_tcx ( cx) , ret_ty) ) ;
6294
6231
let llarg = llvm:: LLVMGetParam ( cx. llfn , arg_n) ;
6295
6232
assert ( llarg as int != 0 ) ;
6296
6233
cx. lliterbody = some[ ValueRef ] ( llarg) ;
6297
6234
arg_n += 1 u;
6298
6235
}
6299
6236
6300
-
6301
6237
// Populate the llargs field of the function context with the ValueRefs
6302
6238
// that we get from llvm::LLVMGetParam for each argument.
6303
6239
for arg: ast:: arg in args {
@@ -6468,15 +6404,9 @@ fn trans_closure(bcx_maybe: &option::t[@block_ctxt],
6468
6404
let bcx = option:: get ( bcx_maybe) ;
6469
6405
let upvars = get_freevars ( cx. ccx . tcx , id) ;
6470
6406
6471
- let env = if ( f. proto == ast:: proto_block) {
6472
- let llenv = build_environment ( bcx, upvars) ;
6473
- load_environment ( bcx, fcx, llenv. ptrty , upvars) ;
6474
- { ptr: llenv. ptr , bcx: bcx}
6475
- } else {
6476
- let llenv = build_copying_closure ( bcx, upvars) ;
6477
- load_environment_heap ( bcx, fcx, llenv. ptrty , upvars) ;
6478
- { ptr: llenv. ptr , bcx: llenv. bcx }
6479
- } ;
6407
+ let copying = f. proto == ast:: proto_closure;
6408
+ let env = build_closure ( bcx, upvars, copying) ;
6409
+ load_environment ( bcx, fcx, env. ptrty , upvars, copying) ;
6480
6410
6481
6411
let closure = create_real_fn_pair ( env. bcx , option:: get ( llfnty) ,
6482
6412
llfndecl, env. ptr ) ;
0 commit comments