@@ -90,9 +90,6 @@ import dvec::extensions;
9090// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
9191
9292enum environment_value {
93- // Evaluate expr and store result in env (used for bind).
94- env_expr( @ast:: expr , ty:: t ) ,
95-
9693 // Copy the value from this llvm ValueRef into the environment.
9794 env_copy( ValueRef , ty:: t , lval_kind ) ,
9895
@@ -105,7 +102,6 @@ enum environment_value {
105102
106103fn ev_to_str ( ccx : @crate_ctxt , ev : environment_value ) -> str {
107104 alt ev {
108- env_expr( ex, _) { expr_to_str ( ex) }
109105 env_copy( v, t, lk) { #fmt ( "copy(%s,%s)" , val_str ( ccx. tn , v) ,
110106 ty_to_str ( ccx. tcx , t) ) }
111107 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 {
123119// Given a closure ty, emits a corresponding tuple ty
124120fn mk_closure_tys ( tcx : ty:: ctxt ,
125121 bound_values : ~[ environment_value ] )
126- -> ( ty:: t , ~ [ ty :: t ] ) {
122+ -> ty:: t {
127123 let mut bound_tys = ~[ ] ;
128124
129125 // Compute the closed over data
@@ -132,15 +128,14 @@ fn mk_closure_tys(tcx: ty::ctxt,
132128 env_copy( _, t, _) { t }
133129 env_move( _, t, _) { t }
134130 env_ref( _, t, _) { t }
135- env_expr( _, t) { t }
136131 } ) ;
137132 }
138133 let bound_data_ty = ty:: mk_tup ( tcx, bound_tys) ;
139134 // FIXME[mono] remove tuple of tydescs from closure types (#2531)
140135 let cdata_ty = ty:: mk_tup ( tcx, ~[ ty:: mk_tup ( tcx, ~[ ] ) ,
141136 bound_data_ty] ) ;
142137 #debug[ "cdata_ty=%s" , ty_to_str ( tcx, cdata_ty) ] ;
143- ret ( cdata_ty, bound_tys ) ;
138+ ret cdata_ty;
144139}
145140
146141fn allocate_cbox ( bcx : block ,
@@ -196,8 +191,7 @@ fn store_environment(bcx: block,
196191 let ccx = bcx. ccx ( ) , tcx = ccx. tcx ;
197192
198193 // 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) ;
201195
202196 // allocate closure in the heap
203197 let llbox = allocate_cbox ( bcx, ck, cdata_ty) ;
@@ -225,11 +219,6 @@ fn store_environment(bcx: block,
225219 let bound_data = GEPi ( bcx, llbox,
226220 ~[ 0 u, abi:: box_field_body, abi:: closure_body_bindings, i] ) ;
227221 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- }
233222 env_copy( val, ty, owned) {
234223 let val1 = load_if_immediate ( bcx, val, ty) ;
235224 bcx = base:: copy_val ( bcx, INIT , bound_data, val1, ty) ;
@@ -415,70 +404,6 @@ fn trans_expr_fn(bcx: block,
415404 ret bcx;
416405}
417406
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-
482407fn make_fn_glue (
483408 cx : block ,
484409 v : ValueRef ,
@@ -611,163 +536,3 @@ fn make_opaque_cbox_free_glue(
611536 }
612537 }
613538}
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