Skip to content

Commit d49998f

Browse files
author
Eric Holk
committed
Switching over to wrappers for spawning functions of multiple arguments. Doesn't quite work yet.
1 parent 842bf7c commit d49998f

File tree

6 files changed

+164
-60
lines changed

6 files changed

+164
-60
lines changed

src/comp/back/upcall.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ fn declare_upcalls(type_names tn, ModuleRef llmod) -> @upcalls {
113113
T_ptr(T_tydesc(tn))),
114114
new_task=d("new_task", [T_ptr(T_str())], T_taskptr(tn)),
115115
start_task=d("start_task", [T_taskptr(tn),
116-
T_int(), T_int(), T_size_t()],
116+
T_int(), T_int()],
117117
T_taskptr(tn)),
118118
new_thread=d("new_thread", [T_ptr(T_i8())], T_taskptr(tn)),
119119
start_thread=d("start_thread", [T_taskptr(tn), T_int(), T_int(),

src/comp/middle/trans.rs

Lines changed: 114 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -601,7 +601,7 @@ fn type_of_explicit_args(&@crate_ctxt cx, &ast::span sp,
601601
assert (arg.mode == ty::mo_alias);
602602
atys += [T_typaram_ptr(cx.tn)];
603603
} else {
604-
let TypeRef t;
604+
let TypeRef t;
605605
alt (arg.mode) {
606606
case (ty::mo_alias) {
607607
t = T_ptr(type_of_inner(cx, sp, arg.ty));
@@ -5867,22 +5867,24 @@ fn trans_spawn(&@block_ctxt cx,
58675867
//
58685868
// 3. Fill the tuple with the arguments we evaluated.
58695869
//
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.
58725876
//
58735877
// 5. Oh yeah, we have to create the task before we start it...
58745878

58755879
// Translate the arguments, remembering their types and where the values
58765880
// ended up.
58775881

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 = [];
58805883
let vec[ValueRef] arg_vals = [];
58815884
for(@ast::expr e in args) {
58825885
auto arg = trans_expr(bcx, e);
58835886

58845887
bcx = arg.bcx;
5885-
58865888
vec::push[ValueRef](arg_vals, arg.val);
58875889
vec::push[ty::t](arg_tys,
58885890
ty::expr_ty(cx.fcx.lcx.ccx.tcx,
@@ -5895,8 +5897,7 @@ fn trans_spawn(&@block_ctxt cx,
58955897
// Allocate and fill the tuple.
58965898
auto llargs = alloc_ty(bcx, args_ty);
58975899

5898-
// 3 to skip all the magic
5899-
auto i = 3u;
5900+
auto i = 0u;
59005901
for(ValueRef v in arg_vals) {
59015902
// log_err #fmt("ty(llargs) = %s",
59025903
// val_str(bcx.fcx.lcx.ccx.tn, llargs.val));
@@ -5919,45 +5920,21 @@ fn trans_spawn(&@block_ctxt cx,
59195920
[bcx.fcx.lltaskptr, lltname]);
59205921

59215922
// 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+
59365924
auto llargs_i = bcx.build.PointerCast(llargs.val,
5937-
T_int());
5925+
T_int());
59385926

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);
59405933

5934+
// And start the task
59415935
bcx.build.Call(bcx.fcx.lcx.ccx.upcalls.start_task,
59425936
[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]);
59615938

59625939
auto task_ty = node_ann_type(bcx.fcx.lcx.ccx, ann);
59635940
auto dropref = clean(bind drop_ty(_, new_task, task_ty));
@@ -5966,6 +5943,101 @@ fn trans_spawn(&@block_ctxt cx,
59665943
ret res(bcx, new_task);
59675944
}
59685945

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+
0u);
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, 3u);
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, 0u),
5986+
llvm::LLVMGetParam(fcx.llfn, 1u),
5987+
llvm::LLVMGetParam(fcx.llfn, 2u)];
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+
59696041
fn trans_send(&@block_ctxt cx, &@ast::expr lhs, &@ast::expr rhs,
59706042
&ast::ann ann) -> result {
59716043
auto bcx = cx;

src/rt/rust_task.cpp

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -171,12 +171,7 @@ rust_task::start(uintptr_t spawnee_fn,
171171
src += 1; // spawn-call task slot
172172
src += 1; // spawn-call closure-or-obj slot
173173

174-
spp -= (args_size / sizeof(uintptr_t)) - 1;
175-
memmove(spp, src, args_size);
176-
spp--;
177-
178-
//*spp-- = (uintptr_t) *src; // vec
179-
174+
*spp-- = (uintptr_t) *src; // vec
180175
*spp-- = (uintptr_t) 0x0; // closure-or-obj
181176
*spp-- = (uintptr_t) this; // task
182177
*spp-- = (uintptr_t) dummy_ret; // output address

src/rt/rust_upcall.cpp

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -466,17 +466,21 @@ extern "C" CDECL rust_task *
466466
upcall_start_task(rust_task *spawner,
467467
rust_task *task,
468468
uintptr_t spawnee_fn,
469-
uintptr_t args,
470-
size_t callsz) {
469+
uintptr_t args) {
471470
LOG_UPCALL_ENTRY(spawner);
472471

473472
rust_dom *dom = spawner->dom;
474473
DLOG(dom, task,
475-
"upcall start_task(task %s @0x%" PRIxPTR
476-
", spawnee 0x%" PRIxPTR
477-
", callsz %" PRIdPTR ")", task->name, task,
478-
spawnee_fn, callsz);
479-
task->start(spawnee_fn, args, callsz);
474+
"upcall start_task(task %s @0x%" PRIxPTR
475+
", spawnee 0x%" PRIxPTR ")",
476+
task->name, task,
477+
spawnee_fn);
478+
479+
// we used to be generating this tuple in rustc, but it's easier to do it
480+
// here.
481+
uintptr_t start_args[] = {0, 0, 0, args};
482+
483+
task->start(spawnee_fn, (uintptr_t)&start_args, sizeof(start_args));
480484
return task;
481485
}
482486

src/test/run-pass/spawn.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,11 @@ fn child(int i) {
99
log_err i;
1010
}
1111

12+
// Local Variables:
13+
// mode: rust;
14+
// fill-column: 78;
15+
// indent-tabs-mode: nil
16+
// c-basic-offset: 4
17+
// buffer-file-coding-system: utf-8-unix
18+
// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
19+
// End:

src/test/run-pass/spawn2.rs

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,35 @@
22
// -*- rust -*-
33

44
fn main() {
5-
spawn child(10, 20);
5+
spawn child(10, 20, 30, 40, 50, 60, 70, 80, 90);
66
}
77

8-
fn child(int i, int j) {
9-
log_err i;
10-
log_err j;
8+
fn child(int i1,
9+
int i2,
10+
int i3,
11+
int i4,
12+
int i5,
13+
int i6,
14+
int i7,
15+
int i8,
16+
int i9)
17+
{
18+
log_err i1;
19+
log_err i2;
20+
log_err i3;
21+
log_err i4;
22+
log_err i5;
23+
log_err i6;
24+
log_err i7;
25+
log_err i8;
26+
log_err i9;
1127
}
28+
29+
// Local Variables:
30+
// mode: rust;
31+
// fill-column: 78;
32+
// indent-tabs-mode: nil
33+
// c-basic-offset: 4
34+
// buffer-file-coding-system: utf-8-unix
35+
// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
36+
// End:

0 commit comments

Comments
 (0)