From 21efd07bc16c2e7614b5f37282d763d6de7d75bb Mon Sep 17 00:00:00 2001 From: Eric Holk Date: Fri, 20 May 2011 18:27:23 -0700 Subject: [PATCH 1/9] New tasks run, but their arguments get lost and something ends up in an infinite loop when the task exits. --- src/comp/middle/trans.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 9c3f5178fec19..643135f940705 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -5932,8 +5932,12 @@ fn trans_spawn(&@block_ctxt cx, auto llfnptr = bcx.build.GEP(fnptr.val, [C_int(0), C_int(0)]); log_err "Casting llfnptr"; - auto llfnptr_i = bcx.build.PointerCast(llfnptr, - T_int()); + auto llfnptrptr_i = bcx.build.PointerCast(llfnptr, + T_ptr(T_int())); + // We'd better dereference this one more time, since that one points into + // the symbol table or something. + auto llfnptr_i = bcx.build.Load(llfnptrptr_i); + log_err "Cassting llargs"; auto llargs_i = bcx.build.PointerCast(llargs.val, T_int()); From bb4c7a9c6818bef1851639f03bb3b5b5a90dd45f Mon Sep 17 00:00:00 2001 From: Eric Holk Date: Mon, 23 May 2011 17:35:15 -0700 Subject: [PATCH 2/9] Arguments seem to be correctly passed to child processes now. --- src/comp/middle/trans.rs | 23 +++++++++++++---------- src/test/run-pass/spawn.rs | 2 +- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 643135f940705..8f2f2f2db1be1 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -5867,7 +5867,9 @@ fn trans_spawn(&@block_ctxt cx, // Translate the arguments, remembering their types and where the values // ended up. - let vec[ty::t] arg_tys = []; + + // There are 3 integers, for magic. + let vec[ty::t] arg_tys = [ty::idx_int, ty::idx_int, ty::idx_int]; let vec[ValueRef] arg_vals = []; for(@ast::expr e in args) { auto arg = trans_expr(bcx, e); @@ -5881,14 +5883,15 @@ fn trans_spawn(&@block_ctxt cx, } // Make the tuple. We have to reverse the types first though. - vec::reverse[ty::t](arg_tys); - vec::reverse[ValueRef](arg_vals); + //vec::reverse[ty::t](arg_tys); + //vec::reverse[ValueRef](arg_vals); auto args_ty = ty::mk_imm_tup(cx.fcx.lcx.ccx.tcx, arg_tys); // Allocate and fill the tuple. auto llargs = alloc_ty(bcx, args_ty); - auto i = vec::len[ValueRef](arg_vals) - 1u; + // 3 to skip all the magic + auto i = 3u; for(ValueRef v in arg_vals) { // log_err #fmt("ty(llargs) = %s", // val_str(bcx.fcx.lcx.ccx.tn, llargs.val)); @@ -5900,7 +5903,7 @@ fn trans_spawn(&@block_ctxt cx, bcx.build.Store(v, target); - i -= 1u; + i += 1u; } // Now we're ready to do the upcall. @@ -5927,8 +5930,6 @@ fn trans_spawn(&@block_ctxt cx, auto fnptr = trans_lval(bcx, func).res; bcx = fnptr.bcx; - auto num_args = vec::len[@ast::expr](args); - auto llfnptr = bcx.build.GEP(fnptr.val, [C_int(0), C_int(0)]); log_err "Casting llfnptr"; @@ -5942,6 +5943,8 @@ fn trans_spawn(&@block_ctxt cx, auto llargs_i = bcx.build.PointerCast(llargs.val, T_int()); + auto args_size = size_of(bcx, args_ty).val; + log_err "Building call to start_task"; log_err #fmt("ty(start_task) = %s", val_str(bcx.fcx.lcx.ccx.tn, @@ -5958,12 +5961,12 @@ fn trans_spawn(&@block_ctxt cx, log_err #fmt("ty(llargs) = %s", val_str(bcx.fcx.lcx.ccx.tn, llargs_i)); - log_err #fmt("ty(num_args) = %s", + log_err #fmt("ty(args_size) = %s", val_str(bcx.fcx.lcx.ccx.tn, - C_int(num_args as int))); + args_size)); bcx.build.Call(bcx.fcx.lcx.ccx.upcalls.start_task, [bcx.fcx.lltaskptr, new_task, - llfnptr_i, llargs_i, C_int(num_args as int)]); + llfnptr_i, llargs_i, args_size]); log_err "Done"; /* diff --git a/src/test/run-pass/spawn.rs b/src/test/run-pass/spawn.rs index ba554fdaf17a0..c6a3ba4bcff96 100644 --- a/src/test/run-pass/spawn.rs +++ b/src/test/run-pass/spawn.rs @@ -8,6 +8,6 @@ fn main() { } fn child(int i) { - log i; + log_err i; } From dad426419c1c93a90d458d8eee307df7ddb0fc05 Mon Sep 17 00:00:00 2001 From: Eric Holk Date: Mon, 23 May 2011 19:29:45 -0700 Subject: [PATCH 3/9] Working on 2 argument spawn. The arguments seem to be copied correctly once, but then they get lost. --- src/comp/middle/trans.rs | 4 +--- src/rt/rust_task.cpp | 8 ++++++-- src/test/run-pass/spawn2.rs | 15 +++++++++++++++ 3 files changed, 22 insertions(+), 5 deletions(-) create mode 100644 src/test/run-pass/spawn2.rs diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 8f2f2f2db1be1..1790ef553f3ce 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -5882,9 +5882,7 @@ fn trans_spawn(&@block_ctxt cx, e)); } - // Make the tuple. We have to reverse the types first though. - //vec::reverse[ty::t](arg_tys); - //vec::reverse[ValueRef](arg_vals); + // Make the tuple. auto args_ty = ty::mk_imm_tup(cx.fcx.lcx.ccx.tcx, arg_tys); // Allocate and fill the tuple. diff --git a/src/rt/rust_task.cpp b/src/rt/rust_task.cpp index e937bd42ffca0..e18259fba6076 100644 --- a/src/rt/rust_task.cpp +++ b/src/rt/rust_task.cpp @@ -171,7 +171,12 @@ rust_task::start(uintptr_t spawnee_fn, src += 1; // spawn-call task slot src += 1; // spawn-call closure-or-obj slot - *spp-- = (uintptr_t) *src; // vec + spp -= (args_size / sizeof(uintptr_t)) - 1; + memmove(spp, src, args_size); + spp--; + + //*spp-- = (uintptr_t) *src; // vec + *spp-- = (uintptr_t) 0x0; // closure-or-obj *spp-- = (uintptr_t) this; // task *spp-- = (uintptr_t) dummy_ret; // output address @@ -179,7 +184,6 @@ rust_task::start(uintptr_t spawnee_fn, I(dom, spp == align_down(spp)); *spp-- = (uintptr_t) (uintptr_t) spawnee_fn; - *spp-- = (uintptr_t) 0x0; // retp *spp-- = (uintptr_t) rust_new_exit_task_glue; diff --git a/src/test/run-pass/spawn2.rs b/src/test/run-pass/spawn2.rs new file mode 100644 index 0000000000000..eca1de89ae0f1 --- /dev/null +++ b/src/test/run-pass/spawn2.rs @@ -0,0 +1,15 @@ +// xfail-stage0 +// xfail-stage1 +// xfail-stage2 +// -*- rust -*- + +use std; + +fn main() { + spawn child(10, 20); +} + +fn child(int i, int j) { + log_err i; + log_err j; +} From a88af906c594f56709ff8e31db1148a08cd52996 Mon Sep 17 00:00:00 2001 From: Eric Holk Date: Tue, 24 May 2011 12:18:42 -0700 Subject: [PATCH 4/9] Programs using spawn terminate --- src/comp/middle/trans.rs | 16 ++++++++++++++++ src/comp/middle/ty.rs | 1 + src/test/run-pass/spawn.rs | 2 +- 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 1790ef553f3ce..723fd1c27144b 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -760,6 +760,9 @@ fn type_of_inner(&@crate_ctxt cx, &ast::span sp, &ty::t t) -> TypeRef { case (ty::ty_chan(?t)) { llty = T_ptr(T_chan(type_of_inner(cx, sp, t))); } + case (ty::ty_task) { + llty = T_taskptr(cx.tn); + } case (ty::ty_tup(?elts)) { let vec[TypeRef] tys = []; for (ty::mt elt in elts) { @@ -2014,6 +2017,11 @@ fn make_free_glue(&@block_ctxt cx, ValueRef v0, &ty::t t) { rslt = res(cx, C_int(0)); } + case (ty::ty_task) { + // TODO: call upcall_kill + rslt = res(cx, C_nil()); + } + case (ty::ty_obj(_)) { auto box_cell = @@ -2107,6 +2115,10 @@ fn make_drop_glue(&@block_ctxt cx, ValueRef v0, &ty::t t) { rslt = decr_refcnt_maybe_free(cx, v0, v0, t); } + case (ty::ty_task) { + rslt = decr_refcnt_maybe_free(cx, v0, v0, t); + } + case (ty::ty_obj(_)) { auto box_cell = cx.build.GEP(v0, @@ -5984,6 +5996,10 @@ fn trans_spawn(&@block_ctxt cx, } */ + auto task_ty = node_ann_type(bcx.fcx.lcx.ccx, ann); + auto dropref = clean(bind drop_ty(_, new_task, task_ty)); + find_scope_cx(bcx).cleanups += [dropref]; + ret res(bcx, new_task); } diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs index 508b2d90a63e2..3d12d16d5284d 100644 --- a/src/comp/middle/ty.rs +++ b/src/comp/middle/ty.rs @@ -951,6 +951,7 @@ fn type_is_boxed(&ctxt cx, &t ty) -> bool { case (ty_box(_)) { ret true; } case (ty_port(_)) { ret true; } case (ty_chan(_)) { ret true; } + case (ty_task) { ret true; } case (_) { ret false; } } fail; diff --git a/src/test/run-pass/spawn.rs b/src/test/run-pass/spawn.rs index c6a3ba4bcff96..bf4c9325d39dc 100644 --- a/src/test/run-pass/spawn.rs +++ b/src/test/run-pass/spawn.rs @@ -4,7 +4,7 @@ // -*- rust -*- fn main() { - spawn child(10); + auto t = spawn child(10); } fn child(int i) { From da0e0b6f5e3cacd5342eb58f78960206639c49c6 Mon Sep 17 00:00:00 2001 From: Eric Holk Date: Tue, 24 May 2011 12:31:59 -0700 Subject: [PATCH 5/9] Removing excessively verbous logging. --- src/comp/middle/trans.rs | 37 ------------------------------------- 1 file changed, 37 deletions(-) diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 723fd1c27144b..069e5bdb25806 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -5855,11 +5855,6 @@ fn trans_spawn(&@block_ctxt cx, } }; - // dump a bunch of information - log_err "Translating Spawn " + - "(The compiled program is not actually running yet, don't worry!"; - log_err #fmt("task name: %s", tname); - // Generate code // // This is a several step process. The following things need to happen @@ -5920,20 +5915,8 @@ fn trans_spawn(&@block_ctxt cx, // But first, we'll create a task. let ValueRef lltname = C_str(bcx.fcx.lcx.ccx, tname); - log_err #fmt("ty(new_task) = %s", - val_str(bcx.fcx.lcx.ccx.tn, - bcx.fcx.lcx.ccx.upcalls.new_task)); - log_err #fmt("ty(lltaskptr) = %s", - val_str(bcx.fcx.lcx.ccx.tn, - bcx.fcx.lltaskptr)); - log_err #fmt("ty(lltname) = %s", - val_str(bcx.fcx.lcx.ccx.tn, - lltname)); - - log_err "Building upcall_new_task"; auto new_task = bcx.build.Call(bcx.fcx.lcx.ccx.upcalls.new_task, [bcx.fcx.lltaskptr, lltname]); - log_err "Done"; // Okay, start the task. // First we find the function @@ -5955,29 +5938,9 @@ fn trans_spawn(&@block_ctxt cx, auto args_size = size_of(bcx, args_ty).val; - log_err "Building call to start_task"; - log_err #fmt("ty(start_task) = %s", - val_str(bcx.fcx.lcx.ccx.tn, - bcx.fcx.lcx.ccx.upcalls.start_task)); - log_err #fmt("ty(lltaskptr) = %s", - val_str(bcx.fcx.lcx.ccx.tn, - bcx.fcx.lltaskptr)); - log_err #fmt("ty(new_task) = %s", - val_str(bcx.fcx.lcx.ccx.tn, - new_task)); - log_err #fmt("ty(llfnptr) = %s", - val_str(bcx.fcx.lcx.ccx.tn, - llfnptr_i)); - log_err #fmt("ty(llargs) = %s", - val_str(bcx.fcx.lcx.ccx.tn, - llargs_i)); - log_err #fmt("ty(args_size) = %s", - val_str(bcx.fcx.lcx.ccx.tn, - args_size)); bcx.build.Call(bcx.fcx.lcx.ccx.upcalls.start_task, [bcx.fcx.lltaskptr, new_task, llfnptr_i, llargs_i, args_size]); - log_err "Done"; /* alt(dom) { From 842bf7cad12dedbbd16e0838f4dd616acc765421 Mon Sep 17 00:00:00 2001 From: Eric Holk Date: Tue, 24 May 2011 15:06:45 -0700 Subject: [PATCH 6/9] Un-XFAILing spawn tests. --- src/test/run-pass/spawn.rs | 2 -- src/test/run-pass/spawn2.rs | 4 ---- 2 files changed, 6 deletions(-) diff --git a/src/test/run-pass/spawn.rs b/src/test/run-pass/spawn.rs index bf4c9325d39dc..7bc2cbc3dd8a0 100644 --- a/src/test/run-pass/spawn.rs +++ b/src/test/run-pass/spawn.rs @@ -1,6 +1,4 @@ // xfail-stage0 -// xfail-stage1 -// xfail-stage2 // -*- rust -*- fn main() { diff --git a/src/test/run-pass/spawn2.rs b/src/test/run-pass/spawn2.rs index eca1de89ae0f1..f5a0e8f289502 100644 --- a/src/test/run-pass/spawn2.rs +++ b/src/test/run-pass/spawn2.rs @@ -1,10 +1,6 @@ // xfail-stage0 -// xfail-stage1 -// xfail-stage2 // -*- rust -*- -use std; - fn main() { spawn child(10, 20); } From d49998f0ed9b0a239b40d30ccfde750f8439cac4 Mon Sep 17 00:00:00 2001 From: Eric Holk Date: Thu, 26 May 2011 18:00:33 -0700 Subject: [PATCH 7/9] Switching over to wrappers for spawning functions of multiple arguments. Doesn't quite work yet. --- src/comp/back/upcall.rs | 2 +- src/comp/middle/trans.rs | 156 ++++++++++++++++++++++++++---------- src/rt/rust_task.cpp | 7 +- src/rt/rust_upcall.cpp | 18 +++-- src/test/run-pass/spawn.rs | 8 ++ src/test/run-pass/spawn2.rs | 33 +++++++- 6 files changed, 164 insertions(+), 60 deletions(-) diff --git a/src/comp/back/upcall.rs b/src/comp/back/upcall.rs index f05ea3d75762c..e80100cc55d6f 100644 --- a/src/comp/back/upcall.rs +++ b/src/comp/back/upcall.rs @@ -113,7 +113,7 @@ fn declare_upcalls(type_names tn, ModuleRef llmod) -> @upcalls { T_ptr(T_tydesc(tn))), new_task=d("new_task", [T_ptr(T_str())], T_taskptr(tn)), start_task=d("start_task", [T_taskptr(tn), - T_int(), T_int(), T_size_t()], + T_int(), T_int()], T_taskptr(tn)), new_thread=d("new_thread", [T_ptr(T_i8())], T_taskptr(tn)), start_thread=d("start_thread", [T_taskptr(tn), T_int(), T_int(), diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 069e5bdb25806..9f3d4b8b3b31e 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -601,7 +601,7 @@ fn type_of_explicit_args(&@crate_ctxt cx, &ast::span sp, assert (arg.mode == ty::mo_alias); atys += [T_typaram_ptr(cx.tn)]; } else { - let TypeRef t; + let TypeRef t; alt (arg.mode) { case (ty::mo_alias) { t = T_ptr(type_of_inner(cx, sp, arg.ty)); @@ -5867,22 +5867,24 @@ fn trans_spawn(&@block_ctxt cx, // // 3. Fill the tuple with the arguments we evaluated. // - // 4. Pass a pointer to the spawnee function and the argument tuple to - // upcall_start_task. + // 3.5. Generate a wrapper function that takes the tuple and unpacks it to + // call the real task. + // + // 4. Pass a pointer to the wrapper function and the argument tuple to + // upcall_start_task. In order to do this, we need to allocate another + // tuple that matches the arguments expected by rust_task::start. // // 5. Oh yeah, we have to create the task before we start it... // Translate the arguments, remembering their types and where the values // ended up. - // There are 3 integers, for magic. - let vec[ty::t] arg_tys = [ty::idx_int, ty::idx_int, ty::idx_int]; + let vec[ty::t] arg_tys = []; let vec[ValueRef] arg_vals = []; for(@ast::expr e in args) { auto arg = trans_expr(bcx, e); bcx = arg.bcx; - vec::push[ValueRef](arg_vals, arg.val); vec::push[ty::t](arg_tys, ty::expr_ty(cx.fcx.lcx.ccx.tcx, @@ -5895,8 +5897,7 @@ fn trans_spawn(&@block_ctxt cx, // Allocate and fill the tuple. auto llargs = alloc_ty(bcx, args_ty); - // 3 to skip all the magic - auto i = 3u; + auto i = 0u; for(ValueRef v in arg_vals) { // log_err #fmt("ty(llargs) = %s", // val_str(bcx.fcx.lcx.ccx.tn, llargs.val)); @@ -5919,45 +5920,21 @@ fn trans_spawn(&@block_ctxt cx, [bcx.fcx.lltaskptr, lltname]); // Okay, start the task. - // First we find the function - auto fnptr = trans_lval(bcx, func).res; - bcx = fnptr.bcx; - - auto llfnptr = bcx.build.GEP(fnptr.val, - [C_int(0), C_int(0)]); - log_err "Casting llfnptr"; - auto llfnptrptr_i = bcx.build.PointerCast(llfnptr, - T_ptr(T_int())); - // We'd better dereference this one more time, since that one points into - // the symbol table or something. - auto llfnptr_i = bcx.build.Load(llfnptrptr_i); - - log_err "Cassting llargs"; + auto llargs_i = bcx.build.PointerCast(llargs.val, - T_int()); + T_int()); - auto args_size = size_of(bcx, args_ty).val; + // Generate the wrapper function + auto wrapper = mk_spawn_wrapper(bcx, tname, func, args_ty); + bcx = wrapper.bcx; + auto llfnptr_i = bcx.build.PointerCast(wrapper.val, T_int()); + // TODO: this next line might be necessary... + //llfnptr_i = bcx.build.Load(llfnptr_i); + // And start the task bcx.build.Call(bcx.fcx.lcx.ccx.upcalls.start_task, [bcx.fcx.lltaskptr, new_task, - llfnptr_i, llargs_i, args_size]); - - /* - alt(dom) { - case(ast::dom_implicit) { - // TODO - log_err "Spawning implicit domain tasks is not implemented."; - //fail; - } - - case(ast::dom_thread) { - // TODO - log_err "Spawining new thread tasks is not implemented."; - // TODO: for now use the normal unimpl thing. - fail; - } - } - */ + llfnptr_i, llargs_i]); auto task_ty = node_ann_type(bcx.fcx.lcx.ccx, ann); auto dropref = clean(bind drop_ty(_, new_task, task_ty)); @@ -5966,6 +5943,101 @@ fn trans_spawn(&@block_ctxt cx, ret res(bcx, new_task); } +fn mk_spawn_wrapper(&@block_ctxt cx, + &str tname, + &@ast::expr func, + &ty::t args_ty) -> result { + auto llmod = cx.fcx.lcx.ccx.llmod; + let TypeRef args_ty_tref = type_of(cx.fcx.lcx.ccx, cx.sp, args_ty); + //let TypeRef wrapper_fn_type = T_fn([args_ty_tref], T_void()); + + let TypeRef wrapper_fn_type = + type_of_fn(cx.fcx.lcx.ccx, cx.sp, ast::proto_fn, + [rec(mode = ty::mo_alias, ty = args_ty)], + ty::idx_nil, + 0u); + + log_err #fmt("wrapper args type: %s", + ty_str(cx.fcx.lcx.ccx.tn, args_ty_tref)); + log_err #fmt("wrapper fn desired type: %s", + ty_str(cx.fcx.lcx.ccx.tn, wrapper_fn_type)); + + // TODO: construct a name based on tname + auto llfndecl = decl_cdecl_fn(llmod, "spawn_wrap", + wrapper_fn_type); + + log_err #fmt("spawn wrapper decl type: %s", + val_str(cx.fcx.lcx.ccx.tn, llfndecl)); + + auto fcx = new_fn_ctxt(cx.fcx.lcx, cx.sp, llfndecl); + + auto fbcx = new_top_block_ctxt(fcx); + + log_err #fmt("spawn wrapper type: %s", val_str(fcx.lcx.ccx.tn, + fcx.llfn)); + + // 3u to skip the three implicit args + let ValueRef arg = llvm::LLVMGetParam(fcx.llfn, 3u); + + log_err #fmt("arg type: %s", val_str(fbcx.fcx.lcx.ccx.tn, arg)); + + let vec[ValueRef] child_args = + [llvm::LLVMGetParam(fcx.llfn, 0u), + llvm::LLVMGetParam(fcx.llfn, 1u), + llvm::LLVMGetParam(fcx.llfn, 2u)]; + + // unpack the arguments + alt(ty::struct(fcx.lcx.ccx.tcx, args_ty)) { + case(ty::ty_tup(?elements)) { + auto i = 0; + for(ty::mt m in elements) { + log_err #fmt("GEP arg %d", i); + auto src = fbcx.build.GEP(arg, [C_int(0), C_int(i)]); + i += 1; + + log_err #fmt("generating load of type %s", + val_str(fbcx.fcx.lcx.ccx.tn, + src)); + + auto child_arg = fbcx.build.Load(src); + + child_args += [child_arg]; + } + } + } + + // Find the function + auto fnptr = trans_lval(fbcx, func).res; + fbcx = fnptr.bcx; + + log_err "SPAWN 1"; + auto llfnptr = fbcx.build.GEP(fnptr.val, + [C_int(0), C_int(0)]); + auto llfn = fbcx.build.Load(llfnptr); + + log_err #fmt("Generating call to child function: %s", + val_str(fbcx.fcx.lcx.ccx.tn, + llfn)); + + auto i = 0; + for(ValueRef v in child_args) { + log_err #fmt("Arg %d: %s", + i, + val_str(fbcx.fcx.lcx.ccx.tn, + v)); + i += 1; + } + + fbcx.build.Call(llfn, + child_args); + fbcx.build.RetVoid(); + + finish_fn(fcx, fbcx.llbb); + + // TODO: make sure we clean up everything we need to. + ret res(cx, llfndecl); +} + fn trans_send(&@block_ctxt cx, &@ast::expr lhs, &@ast::expr rhs, &ast::ann ann) -> result { auto bcx = cx; diff --git a/src/rt/rust_task.cpp b/src/rt/rust_task.cpp index e18259fba6076..b23da1b128468 100644 --- a/src/rt/rust_task.cpp +++ b/src/rt/rust_task.cpp @@ -171,12 +171,7 @@ rust_task::start(uintptr_t spawnee_fn, src += 1; // spawn-call task slot src += 1; // spawn-call closure-or-obj slot - spp -= (args_size / sizeof(uintptr_t)) - 1; - memmove(spp, src, args_size); - spp--; - - //*spp-- = (uintptr_t) *src; // vec - + *spp-- = (uintptr_t) *src; // vec *spp-- = (uintptr_t) 0x0; // closure-or-obj *spp-- = (uintptr_t) this; // task *spp-- = (uintptr_t) dummy_ret; // output address diff --git a/src/rt/rust_upcall.cpp b/src/rt/rust_upcall.cpp index b0c362ecc7a6c..966ddb15eee59 100644 --- a/src/rt/rust_upcall.cpp +++ b/src/rt/rust_upcall.cpp @@ -466,17 +466,21 @@ extern "C" CDECL rust_task * upcall_start_task(rust_task *spawner, rust_task *task, uintptr_t spawnee_fn, - uintptr_t args, - size_t callsz) { + uintptr_t args) { LOG_UPCALL_ENTRY(spawner); rust_dom *dom = spawner->dom; DLOG(dom, task, - "upcall start_task(task %s @0x%" PRIxPTR - ", spawnee 0x%" PRIxPTR - ", callsz %" PRIdPTR ")", task->name, task, - spawnee_fn, callsz); - task->start(spawnee_fn, args, callsz); + "upcall start_task(task %s @0x%" PRIxPTR + ", spawnee 0x%" PRIxPTR ")", + task->name, task, + spawnee_fn); + + // we used to be generating this tuple in rustc, but it's easier to do it + // here. + uintptr_t start_args[] = {0, 0, 0, args}; + + task->start(spawnee_fn, (uintptr_t)&start_args, sizeof(start_args)); return task; } diff --git a/src/test/run-pass/spawn.rs b/src/test/run-pass/spawn.rs index 7bc2cbc3dd8a0..dcee95ada00da 100644 --- a/src/test/run-pass/spawn.rs +++ b/src/test/run-pass/spawn.rs @@ -9,3 +9,11 @@ fn child(int i) { log_err i; } +// Local Variables: +// mode: rust; +// fill-column: 78; +// indent-tabs-mode: nil +// c-basic-offset: 4 +// buffer-file-coding-system: utf-8-unix +// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'"; +// End: diff --git a/src/test/run-pass/spawn2.rs b/src/test/run-pass/spawn2.rs index f5a0e8f289502..13da73db36e6a 100644 --- a/src/test/run-pass/spawn2.rs +++ b/src/test/run-pass/spawn2.rs @@ -2,10 +2,35 @@ // -*- rust -*- fn main() { - spawn child(10, 20); + spawn child(10, 20, 30, 40, 50, 60, 70, 80, 90); } -fn child(int i, int j) { - log_err i; - log_err j; +fn child(int i1, + int i2, + int i3, + int i4, + int i5, + int i6, + int i7, + int i8, + int i9) +{ + log_err i1; + log_err i2; + log_err i3; + log_err i4; + log_err i5; + log_err i6; + log_err i7; + log_err i8; + log_err i9; } + +// Local Variables: +// mode: rust; +// fill-column: 78; +// indent-tabs-mode: nil +// c-basic-offset: 4 +// buffer-file-coding-system: utf-8-unix +// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'"; +// End: From 8cfc388d40673b21282dcdf656cbff3ac8166eca Mon Sep 17 00:00:00 2001 From: Eric Holk Date: Fri, 27 May 2011 15:19:38 -0700 Subject: [PATCH 8/9] Switched calling conventions so that spawn with multiple arguments works. --- src/comp/middle/trans.rs | 11 +++++------ src/rt/rust_upcall.cpp | 2 +- src/test/run-pass/spawn.rs | 4 ++-- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 9f3d4b8b3b31e..835098c3d7fb3 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -5949,7 +5949,6 @@ fn mk_spawn_wrapper(&@block_ctxt cx, &ty::t args_ty) -> result { auto llmod = cx.fcx.lcx.ccx.llmod; let TypeRef args_ty_tref = type_of(cx.fcx.lcx.ccx, cx.sp, args_ty); - //let TypeRef wrapper_fn_type = T_fn([args_ty_tref], T_void()); let TypeRef wrapper_fn_type = type_of_fn(cx.fcx.lcx.ccx, cx.sp, ast::proto_fn, @@ -5963,8 +5962,8 @@ fn mk_spawn_wrapper(&@block_ctxt cx, ty_str(cx.fcx.lcx.ccx.tn, wrapper_fn_type)); // TODO: construct a name based on tname - auto llfndecl = decl_cdecl_fn(llmod, "spawn_wrap", - wrapper_fn_type); + auto llfndecl = decl_fastcall_fn(llmod, "spawn_wrap", + wrapper_fn_type); log_err #fmt("spawn wrapper decl type: %s", val_str(cx.fcx.lcx.ccx.tn, llfndecl)); @@ -6028,10 +6027,10 @@ fn mk_spawn_wrapper(&@block_ctxt cx, i += 1; } - fbcx.build.Call(llfn, - child_args); + fbcx.build.FastCall(llfn, + child_args); fbcx.build.RetVoid(); - + finish_fn(fcx, fbcx.llbb); // TODO: make sure we clean up everything we need to. diff --git a/src/rt/rust_upcall.cpp b/src/rt/rust_upcall.cpp index 966ddb15eee59..6d8734bd43008 100644 --- a/src/rt/rust_upcall.cpp +++ b/src/rt/rust_upcall.cpp @@ -480,7 +480,7 @@ upcall_start_task(rust_task *spawner, // here. uintptr_t start_args[] = {0, 0, 0, args}; - task->start(spawnee_fn, (uintptr_t)&start_args, sizeof(start_args)); + task->start(spawnee_fn, (uintptr_t)start_args, sizeof(start_args)); return task; } diff --git a/src/test/run-pass/spawn.rs b/src/test/run-pass/spawn.rs index dcee95ada00da..6978326d9b1e6 100644 --- a/src/test/run-pass/spawn.rs +++ b/src/test/run-pass/spawn.rs @@ -2,11 +2,11 @@ // -*- rust -*- fn main() { - auto t = spawn child(10); + auto t = spawn child(10); } fn child(int i) { - log_err i; + log_err i; } // Local Variables: From 52795049e72e7064037f4bc59e8faec9a9ade917 Mon Sep 17 00:00:00 2001 From: Eric Holk Date: Fri, 27 May 2011 15:37:19 -0700 Subject: [PATCH 9/9] Generating names for wrappers, removed extra logging --- src/comp/middle/trans.rs | 40 +++++----------------------------------- 1 file changed, 5 insertions(+), 35 deletions(-) diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 835098c3d7fb3..5cb1487925373 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -5925,7 +5925,7 @@ fn trans_spawn(&@block_ctxt cx, T_int()); // Generate the wrapper function - auto wrapper = mk_spawn_wrapper(bcx, tname, func, args_ty); + auto wrapper = mk_spawn_wrapper(bcx, func, args_ty); bcx = wrapper.bcx; auto llfnptr_i = bcx.build.PointerCast(wrapper.val, T_int()); // TODO: this next line might be necessary... @@ -5944,7 +5944,6 @@ fn trans_spawn(&@block_ctxt cx, } fn mk_spawn_wrapper(&@block_ctxt cx, - &str tname, &@ast::expr func, &ty::t args_ty) -> result { auto llmod = cx.fcx.lcx.ccx.llmod; @@ -5956,30 +5955,20 @@ fn mk_spawn_wrapper(&@block_ctxt cx, ty::idx_nil, 0u); - log_err #fmt("wrapper args type: %s", - ty_str(cx.fcx.lcx.ccx.tn, args_ty_tref)); - log_err #fmt("wrapper fn desired type: %s", - ty_str(cx.fcx.lcx.ccx.tn, wrapper_fn_type)); - // TODO: construct a name based on tname - auto llfndecl = decl_fastcall_fn(llmod, "spawn_wrap", + let str wrap_name = mangle_name_by_seq(cx.fcx.lcx.ccx, + [""], + "spawn_wrapper"); + auto llfndecl = decl_fastcall_fn(llmod, wrap_name, wrapper_fn_type); - log_err #fmt("spawn wrapper decl type: %s", - val_str(cx.fcx.lcx.ccx.tn, llfndecl)); - auto fcx = new_fn_ctxt(cx.fcx.lcx, cx.sp, llfndecl); auto fbcx = new_top_block_ctxt(fcx); - log_err #fmt("spawn wrapper type: %s", val_str(fcx.lcx.ccx.tn, - fcx.llfn)); - // 3u to skip the three implicit args let ValueRef arg = llvm::LLVMGetParam(fcx.llfn, 3u); - log_err #fmt("arg type: %s", val_str(fbcx.fcx.lcx.ccx.tn, arg)); - let vec[ValueRef] child_args = [llvm::LLVMGetParam(fcx.llfn, 0u), llvm::LLVMGetParam(fcx.llfn, 1u), @@ -5990,14 +5979,9 @@ fn mk_spawn_wrapper(&@block_ctxt cx, case(ty::ty_tup(?elements)) { auto i = 0; for(ty::mt m in elements) { - log_err #fmt("GEP arg %d", i); auto src = fbcx.build.GEP(arg, [C_int(0), C_int(i)]); i += 1; - log_err #fmt("generating load of type %s", - val_str(fbcx.fcx.lcx.ccx.tn, - src)); - auto child_arg = fbcx.build.Load(src); child_args += [child_arg]; @@ -6009,24 +5993,10 @@ fn mk_spawn_wrapper(&@block_ctxt cx, auto fnptr = trans_lval(fbcx, func).res; fbcx = fnptr.bcx; - log_err "SPAWN 1"; auto llfnptr = fbcx.build.GEP(fnptr.val, [C_int(0), C_int(0)]); auto llfn = fbcx.build.Load(llfnptr); - log_err #fmt("Generating call to child function: %s", - val_str(fbcx.fcx.lcx.ccx.tn, - llfn)); - - auto i = 0; - for(ValueRef v in child_args) { - log_err #fmt("Arg %d: %s", - i, - val_str(fbcx.fcx.lcx.ccx.tn, - v)); - i += 1; - } - fbcx.build.FastCall(llfn, child_args); fbcx.build.RetVoid();