@@ -90,9 +90,6 @@ import dvec::extensions;
90
90
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
91
91
92
92
enum environment_value {
93
- // Evaluate expr and store result in env (used for bind).
94
- env_expr( @ast:: expr , ty:: t ) ,
95
-
96
93
// Copy the value from this llvm ValueRef into the environment.
97
94
env_copy( ValueRef , ty:: t , lval_kind ) ,
98
95
@@ -105,7 +102,6 @@ enum environment_value {
105
102
106
103
fn ev_to_str ( ccx : @crate_ctxt , ev : environment_value ) -> str {
107
104
alt ev {
108
- env_expr( ex, _) { expr_to_str ( ex) }
109
105
env_copy( v, t, lk) { #fmt ( "copy(%s,%s)" , val_str ( ccx. tn , v) ,
110
106
ty_to_str ( ccx. tcx , t) ) }
111
107
env_move ( v, t, lk) { #fmt ( "move(%s,%s)" , val_str ( ccx. tn , v) ,
@@ -123,7 +119,7 @@ fn mk_tuplified_uniq_cbox_ty(tcx: ty::ctxt, cdata_ty: ty::t) -> ty::t {
123
119
// Given a closure ty, emits a corresponding tuple ty
124
120
fn mk_closure_tys ( tcx : ty:: ctxt ,
125
121
bound_values : ~[ environment_value ] )
126
- -> ( ty:: t , ~ [ ty :: t ] ) {
122
+ -> ty:: t {
127
123
let mut bound_tys = ~[ ] ;
128
124
129
125
// Compute the closed over data
@@ -132,15 +128,14 @@ fn mk_closure_tys(tcx: ty::ctxt,
132
128
env_copy( _, t, _) { t }
133
129
env_move( _, t, _) { t }
134
130
env_ref( _, t, _) { t }
135
- env_expr( _, t) { t }
136
131
} ) ;
137
132
}
138
133
let bound_data_ty = ty:: mk_tup ( tcx, bound_tys) ;
139
134
// FIXME[mono] remove tuple of tydescs from closure types (#2531)
140
135
let cdata_ty = ty:: mk_tup ( tcx, ~[ ty:: mk_tup ( tcx, ~[ ] ) ,
141
136
bound_data_ty] ) ;
142
137
#debug[ "cdata_ty=%s" , ty_to_str ( tcx, cdata_ty) ] ;
143
- ret ( cdata_ty, bound_tys ) ;
138
+ ret cdata_ty;
144
139
}
145
140
146
141
fn allocate_cbox ( bcx : block ,
@@ -196,8 +191,7 @@ fn store_environment(bcx: block,
196
191
let ccx = bcx. ccx ( ) , tcx = ccx. tcx ;
197
192
198
193
// compute the shape of the closure
199
- let ( cdata_ty, bound_tys) =
200
- mk_closure_tys ( tcx, bound_values) ;
194
+ let cdata_ty = mk_closure_tys ( tcx, bound_values) ;
201
195
202
196
// allocate closure in the heap
203
197
let llbox = allocate_cbox ( bcx, ck, cdata_ty) ;
@@ -225,11 +219,6 @@ fn store_environment(bcx: block,
225
219
let bound_data = GEPi ( bcx, llbox,
226
220
~[ 0 u, abi:: box_field_body, abi:: closure_body_bindings, i] ) ;
227
221
alt bv {
228
- env_expr( e, _) {
229
- bcx = base:: trans_expr_save_in ( bcx, e, bound_data) ;
230
- add_clean_temp_mem ( bcx, bound_data, bound_tys[ i] ) ;
231
- vec:: push ( temp_cleanups, bound_data) ;
232
- }
233
222
env_copy( val, ty, owned) {
234
223
let val1 = load_if_immediate ( bcx, val, ty) ;
235
224
bcx = base:: copy_val ( bcx, INIT , bound_data, val1, ty) ;
@@ -415,70 +404,6 @@ fn trans_expr_fn(bcx: block,
415
404
ret bcx;
416
405
}
417
406
418
- fn trans_bind_1 ( cx : block , outgoing_fty : ty:: t ,
419
- f_res : lval_maybe_callee ,
420
- args : ~[ option < @ast:: expr > ] , pair_ty : ty:: t ,
421
- dest : dest ) -> block {
422
- let _icx = cx. insn_ctxt ( "closure::trans_bind1" ) ;
423
- let ccx = cx. ccx ( ) ;
424
- let mut bound: ~[ @ast:: expr ] = ~[ ] ;
425
- for vec:: each( args) |argopt| {
426
- alt argopt { none { } some( e) { vec:: push( bound, e) ; } }
427
- }
428
- let mut bcx = f_res. bcx ;
429
- if dest == ignore {
430
- for vec:: each( bound) |ex| { bcx = trans_expr ( bcx, ex, ignore) ; }
431
- ret bcx;
432
- }
433
-
434
- if bound. len ( ) == 0 u &&
435
- ( f_res. env == null_env || f_res. env == is_closure) {
436
- // Trivial 'binding': just return the closure
437
- let lv = lval_maybe_callee_to_lval ( f_res, pair_ty) ;
438
- memmove_ty ( lv. bcx , get_dest_addr ( dest) , lv. val , pair_ty) ;
439
- ret lv. bcx ;
440
- }
441
-
442
- // Arrange for the bound function to live in the first binding spot
443
- // if the function is not statically known.
444
- let ( env_vals, target_info) = alt f_res. env {
445
- null_env { ( ~[ ] , target_static( f_res. val) ) }
446
- is_closure {
447
- // Cast the function we are binding to be the type that the
448
- // closure will expect it to have. The type the closure knows
449
- // about has the type parameters substituted with the real types.
450
- let llclosurety = T_ptr ( type_of ( ccx, outgoing_fty) ) ;
451
- let src_loc = PointerCast ( bcx, f_res. val , llclosurety) ;
452
- ( ~[ env_copy ( src_loc, pair_ty, owned) ] , target_closure)
453
- }
454
- self_env( slf, slf_t, none) {
455
- ( ~[ env_copy ( slf, slf_t, owned) ] , target_static_self ( f_res. val ) )
456
- }
457
- self_env ( _, slf_t, some ( slf) ) {
458
- let cast = PointerCast ( bcx, f_res. val , T_ptr ( T_nil ( ) ) ) ;
459
- ( ~[ env_copy ( cast, ty:: mk_nil_ptr ( ccx. tcx ) , owned_imm) ,
460
- env_copy ( slf, slf_t, owned_imm) ] , target_self)
461
- }
462
- } ;
463
-
464
- // Actually construct the closure
465
- let { llbox, cdata_ty, bcx} = store_environment (
466
- bcx, vec:: append ( env_vals,
467
- vec:: map ( bound, |x| {
468
- env_expr ( x, expr_ty ( bcx, x) )
469
- } ) ) ,
470
- ty:: ck_box) ;
471
-
472
- // Make thunk
473
- let llthunk = trans_bind_thunk (
474
- cx. fcx . ccx , cx. fcx . path , pair_ty, outgoing_fty, args,
475
- cdata_ty, target_info) ;
476
-
477
- // Fill the function pair
478
- fill_fn_pair ( bcx, get_dest_addr ( dest) , llthunk. val , llbox) ;
479
- ret bcx;
480
- }
481
-
482
407
fn make_fn_glue (
483
408
cx : block ,
484
409
v : ValueRef ,
@@ -611,163 +536,3 @@ fn make_opaque_cbox_free_glue(
611
536
}
612
537
}
613
538
}
614
-
615
- enum target_info {
616
- target_closure,
617
- target_static( ValueRef ) ,
618
- target_self,
619
- target_static_self( ValueRef ) ,
620
- }
621
-
622
- // pth is cx.path
623
- fn trans_bind_thunk ( ccx : @crate_ctxt ,
624
- path : path ,
625
- incoming_fty : ty:: t ,
626
- outgoing_fty : ty:: t ,
627
- args : ~[ option < @ast:: expr > ] ,
628
- cdata_ty : ty:: t ,
629
- target_info : target_info )
630
- -> { val : ValueRef , ty: TypeRef } {
631
- let _icx = ccx. insn_ctxt ( "closure::trans_bind_thunk" ) ;
632
- let tcx = ccx. tcx ;
633
- #debug[ "trans_bind_thunk[incoming_fty=%s,outgoing_fty=%s,\
634
- cdata_ty=%s]/~",
635
- ty_to_str ( tcx, incoming_fty) ,
636
- ty_to_str ( tcx, outgoing_fty) ,
637
- ty_to_str ( tcx, cdata_ty) ] ;
638
-
639
- // Here we're not necessarily constructing a thunk in the sense of
640
- // "function with no arguments". The result of compiling 'bind f(foo,
641
- // bar, baz)' would be a thunk that, when called, applies f to those
642
- // arguments and returns the result. But we're stretching the meaning of
643
- // the word "thunk" here to also mean the result of compiling, say, 'bind
644
- // f(foo, _, baz)', or any other bind expression that binds f and leaves
645
- // some (or all) of the arguments unbound.
646
-
647
- // Here, 'incoming_fty' is the type of the entire bind expression, while
648
- // 'outgoing_fty' is the type of the function that is having some of its
649
- // arguments bound. If f is a function that takes three arguments of type
650
- // int and returns int, and we're translating, say, 'bind f(3, _, 5)',
651
- // then outgoing_fty is the type of f, which is (int, int, int) -> int,
652
- // and incoming_fty is the type of 'bind f(3, _, 5)', which is int -> int.
653
-
654
- // Once translated, the entire bind expression will be the call f(foo,
655
- // bar, baz) wrapped in a (so-called) thunk that takes 'bar' as its
656
- // argument and that has bindings of 'foo' to 3 and 'baz' to 5 and a
657
- // pointer to 'f' all saved in its environment. So, our job is to
658
- // construct and return that thunk.
659
-
660
- // Give the thunk a name, type, and value.
661
- let s = mangle_internal_name_by_path_and_seq ( ccx, path, @"thunk") ;
662
- let llthunk_ty = get_pair_fn_ty ( type_of ( ccx, incoming_fty) ) ;
663
- let llthunk = decl_internal_cdecl_fn ( ccx. llmod , s, llthunk_ty) ;
664
-
665
- // Create a new function context and block context for the thunk, and hold
666
- // onto a pointer to the first block in the function for later use.
667
- let fcx = new_fn_ctxt ( ccx, path, llthunk, none) ;
668
- let mut bcx = top_scope_block ( fcx, none) ;
669
- let lltop = bcx. llbb ;
670
- // Since we might need to construct derived tydescs that depend on
671
- // our bound tydescs, we need to load tydescs out of the environment
672
- // before derived tydescs are constructed. To do this, we load them
673
- // in the load_env block.
674
- let l_bcx = raw_block ( fcx, fcx. llloadenv ) ;
675
-
676
- // The 'llenv' that will arrive in the thunk we're creating is an
677
- // environment that will contain the values of its arguments and a
678
- // pointer to the original function. This environment is always
679
- // stored like an opaque box (see big comment at the header of the
680
- // file), so we load the body body, which contains the type descr
681
- // and cached data.
682
- let llcdata = base:: opaque_box_body ( l_bcx, cdata_ty, fcx. llenv ) ;
683
-
684
- // "target", in this context, means the function that's having some of its
685
- // arguments bound and that will be called inside the thunk we're
686
- // creating. (In our running example, target is the function f.) Pick
687
- // out the pointer to the target function from the environment. The
688
- // target function lives in the first binding spot.
689
- let ( lltargetfn, lltargetenv, starting_idx) = alt target_info {
690
- target_static( fptr) {
691
- ( fptr, llvm:: LLVMGetUndef ( T_opaque_cbox_ptr ( ccx) ) , 0 u)
692
- }
693
- target_closure {
694
- let pair = GEPi ( bcx, llcdata, ~[ 0 u, abi:: closure_body_bindings, 0 u] ) ;
695
- let lltargetenv =
696
- Load ( bcx, GEPi ( bcx, pair, ~[ 0 u, abi:: fn_field_box] ) ) ;
697
- let lltargetfn = Load
698
- ( bcx, GEPi ( bcx, pair, ~[ 0 u, abi:: fn_field_code] ) ) ;
699
- ( lltargetfn, lltargetenv, 1 u)
700
- }
701
- target_self {
702
- let fptr = Load ( bcx, GEPi ( bcx, llcdata,
703
- ~[ 0 u, abi:: closure_body_bindings, 0 u] ) ) ;
704
- let slfbox =
705
- GEPi ( bcx, llcdata, ~[ 0 u, abi:: closure_body_bindings, 1 u] ) ;
706
- let selfptr =
707
- GEPi ( bcx, Load ( bcx, slfbox) , ~[ 0 u, abi:: box_field_body] ) ;
708
- ( fptr, PointerCast ( bcx, selfptr, T_opaque_cbox_ptr ( ccx) ) , 2 u)
709
- }
710
- target_static_self ( fptr) {
711
- let slfptr =
712
- GEPi ( bcx, llcdata, ~[ 0 u, abi:: closure_body_bindings, 0 u] ) ;
713
- ( fptr, PointerCast ( bcx, slfptr, T_opaque_cbox_ptr ( ccx) ) , 1 u)
714
- }
715
- } ;
716
-
717
- // And then, pick out the target function's own environment. That's what
718
- // we'll use as the environment the thunk gets.
719
-
720
- // Get the types of the arguments to f.
721
- let outgoing_args = ty:: ty_fn_args ( outgoing_fty) ;
722
-
723
- // Set up the three implicit arguments to the thunk.
724
- let mut llargs: ~[ ValueRef ] = ~[ fcx. llretptr , lltargetenv] ;
725
-
726
- let mut a: uint = first_real_arg; // retptr, env come first
727
- let mut b: uint = starting_idx;
728
- let mut outgoing_arg_index: uint = 0 u;
729
- for vec:: each( args) |arg| {
730
- let out_arg = outgoing_args[ outgoing_arg_index] ;
731
- alt arg {
732
- // Arg provided at binding time; thunk copies it from
733
- // closure.
734
- some( e) {
735
- let mut val =
736
- GEPi ( bcx, llcdata, ~[ 0 u, abi:: closure_body_bindings, b] ) ;
737
-
738
- alt ty:: resolved_mode ( tcx, out_arg. mode ) {
739
- ast:: by_val {
740
- val = Load ( bcx, val) ;
741
- }
742
- ast:: by_copy {
743
- let alloc = alloc_ty( bcx, out_arg. ty ) ;
744
- memmove_ty ( bcx, alloc, val, out_arg. ty ) ;
745
- bcx = take_ty ( bcx, alloc, out_arg. ty ) ;
746
- val = alloc;
747
- }
748
- ast:: by_ref | ast:: by_mutbl_ref | ast:: by_move { }
749
- }
750
- vec:: push ( llargs, val) ;
751
- b += 1 u;
752
- }
753
-
754
- // Arg will be provided when the thunk is invoked.
755
- none {
756
- vec : : push ( llargs, llvm:: LLVMGetParam ( llthunk, a as c_uint ) ) ;
757
- a += 1 u;
758
- }
759
- }
760
- outgoing_arg_index += 1 u;
761
- }
762
-
763
- // Cast the outgoing function to the appropriate type.
764
- // This is necessary because the type of the function that we have
765
- // in the closure does not know how many type descriptors the function
766
- // needs to take.
767
- let lltargetty = type_of_fn_from_ty ( ccx, outgoing_fty) ;
768
- let lltargetfn = PointerCast ( bcx, lltargetfn, T_ptr ( lltargetty) ) ;
769
- Call ( bcx, lltargetfn, llargs) ;
770
- build_return ( bcx) ;
771
- finish_fn ( fcx, lltop) ;
772
- ret { val : llthunk, ty : llthunk_ty} ;
773
- }
0 commit comments