@@ -601,7 +601,7 @@ fn type_of_explicit_args(&@crate_ctxt cx, &ast::span sp,
601
601
assert ( arg. mode == ty:: mo_alias) ;
602
602
atys += [ T_typaram_ptr ( cx. tn ) ] ;
603
603
} else {
604
- let TypeRef t;
604
+ let TypeRef t;
605
605
alt ( arg. mode ) {
606
606
case ( ty:: mo_alias) {
607
607
t = T_ptr ( type_of_inner ( cx, sp, arg. ty ) ) ;
@@ -5867,22 +5867,24 @@ fn trans_spawn(&@block_ctxt cx,
5867
5867
//
5868
5868
// 3. Fill the tuple with the arguments we evaluated.
5869
5869
//
5870
- // 4. Pass a pointer to the spawnee function and the argument tuple to
5871
- // upcall_start_task.
5870
+ // 3.5. Generate a wrapper function that takes the tuple and unpacks it to
5871
+ // call the real task.
5872
+ //
5873
+ // 4. Pass a pointer to the wrapper function and the argument tuple to
5874
+ // upcall_start_task. In order to do this, we need to allocate another
5875
+ // tuple that matches the arguments expected by rust_task::start.
5872
5876
//
5873
5877
// 5. Oh yeah, we have to create the task before we start it...
5874
5878
5875
5879
// Translate the arguments, remembering their types and where the values
5876
5880
// ended up.
5877
5881
5878
- // There are 3 integers, for magic.
5879
- let vec[ ty:: t] arg_tys = [ ty:: idx_int, ty:: idx_int, ty:: idx_int] ;
5882
+ let vec[ ty:: t] arg_tys = [ ] ;
5880
5883
let vec[ ValueRef ] arg_vals = [ ] ;
5881
5884
for ( @ast:: expr e in args) {
5882
5885
auto arg = trans_expr( bcx, e) ;
5883
5886
5884
5887
bcx = arg. bcx;
5885
-
5886
5888
vec:: push[ ValueRef ] ( arg_vals, arg. val) ;
5887
5889
vec:: push[ ty:: t] ( arg_tys,
5888
5890
ty:: expr_ty( cx. fcx. lcx. ccx. tcx,
@@ -5895,8 +5897,7 @@ fn trans_spawn(&@block_ctxt cx,
5895
5897
// Allocate and fill the tuple.
5896
5898
auto llargs = alloc_ty( bcx, args_ty) ;
5897
5899
5898
- // 3 to skip all the magic
5899
- auto i = 3 u;
5900
+ auto i = 0 u;
5900
5901
for ( ValueRef v in arg_vals) {
5901
5902
// log_err #fmt("ty(llargs) = %s",
5902
5903
// val_str(bcx.fcx.lcx.ccx.tn, llargs.val));
@@ -5919,45 +5920,21 @@ fn trans_spawn(&@block_ctxt cx,
5919
5920
[ bcx. fcx. lltaskptr, lltname] ) ;
5920
5921
5921
5922
// Okay, start the task.
5922
- // First we find the function
5923
- auto fnptr = trans_lval( bcx, func) . res;
5924
- bcx = fnptr. bcx;
5925
-
5926
- auto llfnptr = bcx. build. GEP ( fnptr. val,
5927
- [ C_int ( 0 ) , C_int ( 0 ) ] ) ;
5928
- log_err "Casting llfnptr" ;
5929
- auto llfnptrptr_i = bcx. build. PointerCast ( llfnptr,
5930
- T_ptr ( T_int ( ) ) ) ;
5931
- // We'd better dereference this one more time, since that one points into
5932
- // the symbol table or something.
5933
- auto llfnptr_i = bcx. build. Load ( llfnptrptr_i) ;
5934
-
5935
- log_err "Cassting llargs" ;
5923
+
5936
5924
auto llargs_i = bcx. build. PointerCast ( llargs. val,
5937
- T_int ( ) ) ;
5925
+ T_int ( ) ) ;
5938
5926
5939
- auto args_size = size_of( bcx, args_ty) . val;
5927
+ // Generate the wrapper function
5928
+ auto wrapper = mk_spawn_wrapper( bcx, tname, func, args_ty) ;
5929
+ bcx = wrapper. bcx;
5930
+ auto llfnptr_i = bcx. build. PointerCast ( wrapper. val, T_int ( ) ) ;
5931
+ // TODO: this next line might be necessary...
5932
+ //llfnptr_i = bcx.build.Load(llfnptr_i);
5940
5933
5934
+ // And start the task
5941
5935
bcx. build. Call ( bcx. fcx. lcx. ccx. upcalls. start_task,
5942
5936
[ bcx. fcx. lltaskptr, new_task,
5943
- llfnptr_i, llargs_i, args_size] ) ;
5944
-
5945
- /*
5946
- alt(dom) {
5947
- case(ast::dom_implicit) {
5948
- // TODO
5949
- log_err "Spawning implicit domain tasks is not implemented.";
5950
- //fail;
5951
- }
5952
-
5953
- case(ast::dom_thread) {
5954
- // TODO
5955
- log_err "Spawining new thread tasks is not implemented.";
5956
- // TODO: for now use the normal unimpl thing.
5957
- fail;
5958
- }
5959
- }
5960
- */
5937
+ llfnptr_i, llargs_i] ) ;
5961
5938
5962
5939
auto task_ty = node_ann_type( bcx. fcx. lcx. ccx, ann) ;
5963
5940
auto dropref = clean( bind drop_ty( _, new_task, task_ty) ) ;
@@ -5966,6 +5943,101 @@ fn trans_spawn(&@block_ctxt cx,
5966
5943
ret res( bcx, new_task) ;
5967
5944
}
5968
5945
5946
+ fn mk_spawn_wrapper( & @block_ctxt cx,
5947
+ & str tname,
5948
+ & @ast:: expr func,
5949
+ & ty:: t args_ty) -> result {
5950
+ auto llmod = cx. fcx. lcx. ccx. llmod;
5951
+ let TypeRef args_ty_tref = type_of( cx. fcx. lcx. ccx, cx. sp, args_ty) ;
5952
+ //let TypeRef wrapper_fn_type = T_fn([args_ty_tref], T_void());
5953
+
5954
+ let TypeRef wrapper_fn_type =
5955
+ type_of_fn( cx. fcx. lcx. ccx, cx. sp, ast:: proto_fn,
5956
+ [ rec( mode = ty:: mo_alias, ty = args_ty) ] ,
5957
+ ty:: idx_nil,
5958
+ 0 u) ;
5959
+
5960
+ log_err #fmt( "wrapper args type: %s" ,
5961
+ ty_str( cx. fcx. lcx. ccx. tn, args_ty_tref) ) ;
5962
+ log_err #fmt( "wrapper fn desired type: %s" ,
5963
+ ty_str( cx. fcx. lcx. ccx. tn, wrapper_fn_type) ) ;
5964
+
5965
+ // TODO: construct a name based on tname
5966
+ auto llfndecl = decl_cdecl_fn( llmod, "spawn_wrap" ,
5967
+ wrapper_fn_type) ;
5968
+
5969
+ log_err #fmt( "spawn wrapper decl type: %s" ,
5970
+ val_str( cx. fcx. lcx. ccx. tn, llfndecl) ) ;
5971
+
5972
+ auto fcx = new_fn_ctxt( cx. fcx. lcx, cx. sp, llfndecl) ;
5973
+
5974
+ auto fbcx = new_top_block_ctxt( fcx) ;
5975
+
5976
+ log_err #fmt( "spawn wrapper type: %s" , val_str( fcx. lcx. ccx. tn,
5977
+ fcx. llfn) ) ;
5978
+
5979
+ // 3u to skip the three implicit args
5980
+ let ValueRef arg = llvm:: LLVMGetParam ( fcx. llfn, 3 u) ;
5981
+
5982
+ log_err #fmt( "arg type: %s" , val_str( fbcx. fcx. lcx. ccx. tn, arg) ) ;
5983
+
5984
+ let vec[ ValueRef ] child_args =
5985
+ [ llvm:: LLVMGetParam ( fcx. llfn, 0 u) ,
5986
+ llvm:: LLVMGetParam ( fcx. llfn, 1 u) ,
5987
+ llvm:: LLVMGetParam ( fcx. llfn, 2 u) ] ;
5988
+
5989
+ // unpack the arguments
5990
+ alt( ty:: struct( fcx. lcx. ccx. tcx, args_ty) ) {
5991
+ case( ty:: ty_tup( ?elements) ) {
5992
+ auto i = 0 ;
5993
+ for ( ty:: mt m in elements) {
5994
+ log_err #fmt( "GEP arg %d" , i) ;
5995
+ auto src = fbcx. build. GEP ( arg, [ C_int ( 0 ) , C_int ( i) ] ) ;
5996
+ i += 1 ;
5997
+
5998
+ log_err #fmt( "generating load of type %s" ,
5999
+ val_str( fbcx. fcx. lcx. ccx. tn,
6000
+ src) ) ;
6001
+
6002
+ auto child_arg = fbcx. build. Load ( src) ;
6003
+
6004
+ child_args += [ child_arg] ;
6005
+ }
6006
+ }
6007
+ }
6008
+
6009
+ // Find the function
6010
+ auto fnptr = trans_lval( fbcx, func) . res;
6011
+ fbcx = fnptr. bcx;
6012
+
6013
+ log_err "SPAWN 1" ;
6014
+ auto llfnptr = fbcx. build. GEP ( fnptr. val,
6015
+ [ C_int ( 0 ) , C_int ( 0 ) ] ) ;
6016
+ auto llfn = fbcx. build. Load ( llfnptr) ;
6017
+
6018
+ log_err #fmt( "Generating call to child function: %s" ,
6019
+ val_str( fbcx. fcx. lcx. ccx. tn,
6020
+ llfn) ) ;
6021
+
6022
+ auto i = 0 ;
6023
+ for ( ValueRef v in child_args) {
6024
+ log_err #fmt( "Arg %d: %s" ,
6025
+ i,
6026
+ val_str( fbcx. fcx. lcx. ccx. tn,
6027
+ v) ) ;
6028
+ i += 1 ;
6029
+ }
6030
+
6031
+ fbcx. build. Call ( llfn,
6032
+ child_args) ;
6033
+ fbcx. build. RetVoid ( ) ;
6034
+
6035
+ finish_fn( fcx, fbcx. llbb) ;
6036
+
6037
+ // TODO: make sure we clean up everything we need to.
6038
+ ret res( cx, llfndecl) ;
6039
+ }
6040
+
5969
6041
fn trans_send( & @block_ctxt cx, & @ast:: expr lhs, & @ast:: expr rhs,
5970
6042
& ast:: ann ann) -> result {
5971
6043
auto bcx = cx;
0 commit comments