@@ -67,6 +67,12 @@ import syntax::print::pprust::path_to_str;
67
67
68
68
import trans_common:: * ;
69
69
70
+ import trans_comm:: trans_port;
71
+ import trans_comm:: trans_chan;
72
+ import trans_comm:: trans_spawn;
73
+ import trans_comm:: trans_send;
74
+ import trans_comm:: trans_recv;
75
+
70
76
obj namegen( mutable int i) {
71
77
fn next ( str prefix ) -> str { i += 1 ; ret prefix + int:: str ( i) ; }
72
78
}
@@ -6217,287 +6223,6 @@ fn trans_be(&@block_ctxt cx, &@ast::expr e) -> result {
6217
6223
ret trans_ret( cx, some( e) ) ;
6218
6224
}
6219
6225
6220
- fn trans_port( & @block_ctxt cx, ast:: node_id id) -> result {
6221
- auto t = node_id_type( cx. fcx. lcx. ccx, id) ;
6222
- auto unit_ty;
6223
- alt ( ty:: struct ( cx. fcx. lcx. ccx. tcx, t) ) {
6224
- case ( ty:: ty_port( ?t) ) { unit_ty = t; }
6225
- case ( _) { cx. fcx. lcx. ccx. sess. bug( "non-port type in trans_port") ; }
6226
- }
6227
- auto bcx = cx;
6228
- auto unit_sz = size_of( bcx, unit_ty) ;
6229
- bcx = unit_sz. bcx;
6230
- auto port_raw_val =
6231
- bcx. build. Call ( bcx. fcx. lcx. ccx. upcalls. new_port,
6232
- ~[ bcx. fcx. lltaskptr, unit_sz. val] ) ;
6233
- auto llty = type_of( cx. fcx. lcx. ccx, cx. sp, t) ;
6234
- auto port_val = bcx. build. PointerCast ( port_raw_val, llty) ;
6235
- add_clean_temp( bcx, port_val, t) ;
6236
- ret rslt( bcx, port_val) ;
6237
- }
6238
-
6239
- fn trans_chan( & @block_ctxt cx, & @ast:: expr e, ast:: node_id id) -> result {
6240
- auto bcx = cx;
6241
- auto prt = trans_expr( bcx, e) ;
6242
- bcx = prt. bcx;
6243
- auto prt_val = bcx. build. PointerCast ( prt. val, T_opaque_port_ptr ( ) ) ;
6244
- auto chan_raw_val =
6245
- bcx. build. Call ( bcx. fcx. lcx. ccx. upcalls. new_chan,
6246
- ~[ bcx. fcx. lltaskptr, prt_val] ) ;
6247
- auto chan_ty = node_id_type( bcx. fcx. lcx. ccx, id) ;
6248
- auto chan_llty = type_of( bcx. fcx. lcx. ccx, e. span, chan_ty) ;
6249
- auto chan_val = bcx. build. PointerCast ( chan_raw_val, chan_llty) ;
6250
- add_clean_temp( bcx, chan_val, chan_ty) ;
6251
- ret rslt( bcx, chan_val) ;
6252
- }
6253
-
6254
- fn trans_spawn( & @block_ctxt cx, & ast:: spawn_dom dom, & option:: t[ str ] name,
6255
- & @ast:: expr func, & ( @ast:: expr) [ ] args, ast:: node_id id)
6256
- -> result {
6257
- auto bcx = cx;
6258
- // Make the task name
6259
-
6260
- auto tname =
6261
- alt ( name) {
6262
- case ( none) {
6263
- auto argss = std:: ivec:: map( expr_to_str, args) ;
6264
- #fmt( "%s( %s) ", expr_to_str( func) ,
6265
- str :: connect_ivec( argss, ", ") )
6266
- }
6267
- case ( some( ?n) ) { n }
6268
- } ;
6269
- // Generate code
6270
- //
6271
- // This is a several step process. The following things need to happen
6272
- // (not necessarily in order):
6273
- //
6274
- // 1. Evaluate all the arguments to the spawnee.
6275
- //
6276
- // 2. Alloca a tuple that holds these arguments (they must be in reverse
6277
- // order, so that they match the expected stack layout for the spawnee)
6278
- //
6279
- // 3. Fill the tuple with the arguments we evaluated.
6280
- //
6281
- // 3.5. Generate a wrapper function that takes the tuple and unpacks it to
6282
- // call the real task.
6283
- //
6284
- // 4. Pass a pointer to the wrapper function and the argument tuple to
6285
- // upcall_start_task. In order to do this, we need to allocate another
6286
- // tuple that matches the arguments expected by rust_task::start.
6287
- //
6288
- // 5. Oh yeah, we have to create the task before we start it...
6289
-
6290
- // But first, we'll create a task.
6291
-
6292
- let ValueRef lltname = C_str ( bcx. fcx. lcx. ccx, tname) ;
6293
- auto new_task =
6294
- bcx. build. Call ( bcx. fcx. lcx. ccx. upcalls. new_task,
6295
- ~[ bcx. fcx. lltaskptr, lltname] ) ;
6296
-
6297
- // Translate the arguments, remembering their types and where the values
6298
- // ended up.
6299
-
6300
- let ty:: t[ ] arg_tys = ~[ ] ;
6301
- let ValueRef [ ] arg_vals = ~[ ] ;
6302
- for ( @ast:: expr e in args) {
6303
- auto e_ty = ty:: expr_ty( cx. fcx. lcx. ccx. tcx, e) ;
6304
- auto arg = trans_expr( bcx, e) ;
6305
-
6306
- arg = deep_copy( arg. bcx, arg. val, e_ty, new_task) ;
6307
-
6308
- bcx = arg. bcx;
6309
-
6310
- arg_vals += ~[ arg. val] ;
6311
- arg_tys += ~[ e_ty] ;
6312
- }
6313
- // Make the tuple.
6314
-
6315
- auto args_ty = ty:: mk_imm_tup( cx. fcx. lcx. ccx. tcx, arg_tys) ;
6316
- // Allocate and fill the tuple.
6317
-
6318
- auto llargs = alloc_ty( bcx, args_ty) ;
6319
- auto i = 0 u;
6320
- for ( ValueRef v in arg_vals) {
6321
- // log_err #fmt("ty(llargs) = %s",
6322
- // val_str(bcx.fcx.lcx.ccx.tn, llargs.val));
6323
-
6324
- auto target = bcx. build. GEP ( llargs. val, ~[ C_int ( 0 ) , C_int ( i as int) ] ) ;
6325
- // log_err #fmt("ty(v) = %s", val_str(bcx.fcx.lcx.ccx.tn, v));
6326
- // log_err #fmt("ty(target) = %s",
6327
- // val_str(bcx.fcx.lcx.ccx.tn, target));
6328
-
6329
- bcx. build. Store ( v, target) ;
6330
- i += 1 u;
6331
- }
6332
-
6333
- // Generate the wrapper function
6334
- auto wrapper = mk_spawn_wrapper( bcx, func, args_ty) ;
6335
- bcx = wrapper. bcx;
6336
- auto llfnptr_i = bcx. build. PointerCast ( wrapper. val, T_int ( ) ) ;
6337
-
6338
- // And start the task
6339
- auto llargs_i = bcx. build. PointerCast ( llargs. val, T_int ( ) ) ;
6340
- auto args_size = size_of( bcx, args_ty) . val;
6341
- bcx. build. Call ( bcx. fcx. lcx. ccx. upcalls. start_task,
6342
- ~[ bcx. fcx. lltaskptr, new_task, llfnptr_i, llargs_i,
6343
- args_size] ) ;
6344
- auto task_ty = node_id_type( bcx. fcx. lcx. ccx, id) ;
6345
- add_clean_temp( bcx, new_task, task_ty) ;
6346
- ret rslt( bcx, new_task) ;
6347
- }
6348
-
6349
- fn mk_spawn_wrapper( & @block_ctxt cx, & @ast:: expr func, & ty:: t args_ty) ->
6350
- result {
6351
- auto llmod = cx. fcx. lcx. ccx. llmod;
6352
- let TypeRef wrapper_fn_type =
6353
- type_of_fn( cx. fcx. lcx. ccx, cx. sp, ast:: proto_fn,
6354
- ~[ rec( mode=ty:: mo_alias( false) , ty=args_ty) ] , ty:: idx_nil,
6355
- 0 u) ;
6356
- // TODO: construct a name based on tname
6357
-
6358
- let str wrap_name =
6359
- mangle_internal_name_by_path_and_seq( cx. fcx. lcx. ccx, cx. fcx. lcx. path,
6360
- "spawn_wrapper") ;
6361
- auto llfndecl = decl_cdecl_fn( llmod, wrap_name, wrapper_fn_type) ;
6362
- auto fcx = new_fn_ctxt( cx. fcx. lcx, cx. sp, llfndecl) ;
6363
- auto fbcx = new_top_block_ctxt( fcx) ;
6364
- // 3u to skip the three implicit args
6365
-
6366
- let ValueRef arg = llvm:: LLVMGetParam ( fcx. llfn, 3 u) ;
6367
- let ValueRef [ ] child_args =
6368
- ~[ llvm:: LLVMGetParam ( fcx. llfn, 0 u) , llvm:: LLVMGetParam ( fcx. llfn, 1 u) ,
6369
- llvm:: LLVMGetParam ( fcx. llfn, 2 u) ] ;
6370
- // unpack the arguments
6371
-
6372
- alt ( ty:: struct ( fcx. lcx. ccx. tcx, args_ty) ) {
6373
- case ( ty:: ty_tup( ?elements) ) {
6374
- auto i = 0 ;
6375
- for ( ty:: mt m in elements) {
6376
- auto src = fbcx. build. GEP ( arg, ~[ C_int ( 0 ) , C_int ( i) ] ) ;
6377
- i += 1 ;
6378
- auto child_arg = fbcx. build. Load ( src) ;
6379
- child_args += ~[ child_arg] ;
6380
- }
6381
- }
6382
- }
6383
- // Find the function
6384
-
6385
- auto fnptr = trans_lval( fbcx, func) . res;
6386
- fbcx = fnptr. bcx;
6387
- auto llfnptr = fbcx. build. GEP ( fnptr. val, ~[ C_int ( 0 ) , C_int ( 0 ) ] ) ;
6388
- auto llfn = fbcx. build. Load ( llfnptr) ;
6389
- fbcx. build. FastCall ( llfn, child_args) ;
6390
- fbcx. build. RetVoid ( ) ;
6391
- finish_fn( fcx, fbcx. llbb) ;
6392
- // TODO: make sure we clean up everything we need to.
6393
-
6394
- ret rslt( cx, llfndecl) ;
6395
- }
6396
-
6397
- // Does a deep copy of a value. This is needed for passing arguments to child
6398
- // tasks, and for sending things through channels. There are probably some
6399
- // uniqueness optimizations and things we can do here for tasks in the same
6400
- // domain.
6401
- fn deep_copy( & @block_ctxt bcx, ValueRef v, ty:: t t, ValueRef target_task)
6402
- -> result
6403
- {
6404
- // TODO: make sure all paths add any reference counting that they need to.
6405
-
6406
- // TODO: Teach deep copy to understand everything else it needs to.
6407
-
6408
- auto tcx = bcx. fcx. lcx. ccx. tcx;
6409
- if ( ty:: type_is_scalar( tcx, t) ) {
6410
- ret rslt( bcx, v) ;
6411
- }
6412
- else if ( ty:: type_is_str( tcx, t) ) {
6413
- ret rslt( bcx,
6414
- bcx. build. Call ( bcx. fcx. lcx. ccx. upcalls. dup_str,
6415
- ~[ bcx. fcx. lltaskptr, target_task, v] ) ) ;
6416
- }
6417
- else if ( ty:: type_is_chan( tcx, t) ) {
6418
- // If this is a channel, we need to clone it.
6419
- auto chan_ptr = bcx. build. PointerCast ( v, T_opaque_chan_ptr ( ) ) ;
6420
-
6421
- auto chan_raw_val =
6422
- bcx. build. Call ( bcx. fcx. lcx. ccx. upcalls. clone_chan,
6423
- ~[ bcx. fcx. lltaskptr, target_task, chan_ptr] ) ;
6424
-
6425
- // Cast back to the type the context was expecting.
6426
- auto chan_val = bcx. build. PointerCast ( chan_raw_val,
6427
- val_ty( v) ) ;
6428
-
6429
- ret rslt( bcx, chan_val) ;
6430
- }
6431
- else if ( ty:: type_is_structural( tcx, t) ) {
6432
- fn inner_deep_copy( & @block_ctxt bcx, ValueRef v, ty:: t t) -> result {
6433
- log_err "Unimplemented type for deep_copy. ";
6434
- fail;
6435
- }
6436
-
6437
- ret iter_structural_ty( bcx, v, t, inner_deep_copy) ;
6438
- }
6439
- else {
6440
- bcx. fcx. lcx. ccx. sess. bug( "unexpected type in " +
6441
- "trans:: deep_copy: " +
6442
- ty_to_str( tcx, t) ) ;
6443
- }
6444
- }
6445
-
6446
- fn trans_send( & @block_ctxt cx, & @ast:: expr lhs, & @ast:: expr rhs,
6447
- ast:: node_id id) -> result {
6448
- auto bcx = cx;
6449
- auto chn = trans_expr( bcx, lhs) ;
6450
- bcx = chn. bcx;
6451
- auto data = trans_lval( bcx, rhs) ;
6452
- bcx = data. res. bcx;
6453
- auto chan_ty = node_id_type( cx. fcx. lcx. ccx, id) ;
6454
- auto unit_ty;
6455
- alt ( ty:: struct ( cx. fcx. lcx. ccx. tcx, chan_ty) ) {
6456
- case ( ty:: ty_chan( ?t) ) { unit_ty = t; }
6457
- case ( _) { bcx. fcx. lcx. ccx. sess. bug( "non-chan type in trans_send") ; }
6458
- }
6459
- auto data_alloc = alloc_ty( bcx, unit_ty) ;
6460
- bcx = data_alloc. bcx;
6461
- auto data_tmp = move_val_if_temp( bcx, INIT , data_alloc. val,
6462
- data, unit_ty) ;
6463
- bcx = data_tmp. bcx;
6464
- add_clean_temp( bcx, data_alloc. val, unit_ty) ;
6465
- auto llchanval = bcx. build. PointerCast ( chn. val, T_opaque_chan_ptr ( ) ) ;
6466
- auto lldataptr = bcx. build. PointerCast ( data_alloc. val, T_ptr ( T_i8 ( ) ) ) ;
6467
- bcx. build. Call ( bcx. fcx. lcx. ccx. upcalls. send,
6468
- ~[ bcx. fcx. lltaskptr, llchanval, lldataptr] ) ;
6469
- ret rslt( bcx, chn. val) ;
6470
- }
6471
-
6472
- fn trans_recv( & @block_ctxt cx, & @ast:: expr lhs, & @ast:: expr rhs,
6473
- ast:: node_id id) -> result {
6474
- auto bcx = cx;
6475
- auto data = trans_lval( bcx, rhs) ;
6476
- assert ( data. is_mem) ;
6477
- bcx = data. res. bcx;
6478
- auto unit_ty = node_id_type( bcx. fcx. lcx. ccx, id) ;
6479
- // FIXME: calculate copy init-ness in typestate.
6480
-
6481
- ret recv_val( bcx, data. res. val, lhs, unit_ty, DROP_EXISTING ) ;
6482
- }
6483
-
6484
- fn recv_val( & @block_ctxt cx, ValueRef to, & @ast:: expr from, & ty:: t unit_ty,
6485
- copy_action action) -> result {
6486
- auto bcx = cx;
6487
- auto prt = trans_expr( bcx, from) ;
6488
- bcx = prt. bcx;
6489
- auto lldataptr = bcx. build. PointerCast ( to, T_ptr ( T_ptr ( T_i8 ( ) ) ) ) ;
6490
- auto llportptr = bcx. build. PointerCast ( prt. val, T_opaque_port_ptr ( ) ) ;
6491
- bcx. build. Call ( bcx. fcx. lcx. ccx. upcalls. recv,
6492
- ~[ bcx. fcx. lltaskptr, lldataptr, llportptr] ) ;
6493
- auto data_load = load_if_immediate( bcx, to, unit_ty) ;
6494
- auto cp = copy_val( bcx, action, to, data_load, unit_ty) ;
6495
- bcx = cp. bcx;
6496
- // TODO: Any cleanup need to be done here?
6497
- ret rslt( bcx, to) ;
6498
- }
6499
-
6500
-
6501
6226
/*
6502
6227
6503
6228
Suppose we create an anonymous object my_b from a regular object a:
@@ -6818,9 +6543,6 @@ fn init_local(&@block_ctxt cx, &@ast::local local) -> result {
6818
6543
auto sub = trans_lval( bcx, init. expr) ;
6819
6544
bcx = move_val( sub. res. bcx, INIT , llptr, sub, ty) . bcx;
6820
6545
}
6821
- case ( ast:: init_recv) {
6822
- bcx = recv_val( bcx, llptr, init. expr, ty, INIT ) . bcx;
6823
- }
6824
6546
}
6825
6547
}
6826
6548
case ( _) { bcx = zero_alloca( bcx, llptr, ty) . bcx; }
0 commit comments