Switching over to wrappers for spawning functions of multiple arguments. Doesn't quite work yet.
This commit is contained in:
parent
842bf7cad1
commit
d49998f0ed
6 changed files with 163 additions and 59 deletions
|
|
@ -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(),
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue