Skip to content

Commit 90a7b90

Browse files
author
Eric Holk
committed
---
yaml --- r: 3933 b: refs/heads/master c: 827e300 h: refs/heads/master i: 3931: 26aeb87 v: v3
1 parent 36bc0b8 commit 90a7b90

File tree

4 files changed

+312
-285
lines changed

4 files changed

+312
-285
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
---
2-
refs/heads/master: ce6a77e24e066f4158b1d6b2c15d619994587884
2+
refs/heads/master: 827e3004851ff28f4394bf62d4a9fe29728ebe70

trunk/src/comp/middle/trans.rs

Lines changed: 6 additions & 284 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,12 @@ import syntax::print::pprust::path_to_str;
6767

6868
import trans_common::*;
6969

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+
7076
obj namegen(mutable int i) {
7177
fn next(str prefix) -> str { i += 1; ret prefix + int::str(i); }
7278
}
@@ -6217,287 +6223,6 @@ fn trans_be(&@block_ctxt cx, &@ast::expr e) -> result {
62176223
ret trans_ret(cx, some(e));
62186224
}
62196225

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 = 0u;
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 += 1u;
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-
0u);
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, 3u);
6367-
let ValueRef[] child_args =
6368-
~[llvm::LLVMGetParam(fcx.llfn, 0u), llvm::LLVMGetParam(fcx.llfn, 1u),
6369-
llvm::LLVMGetParam(fcx.llfn, 2u)];
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-
65016226
/*
65026227
65036228
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 {
68186543
auto sub = trans_lval(bcx, init.expr);
68196544
bcx = move_val(sub.res.bcx, INIT, llptr, sub, ty).bcx;
68206545
}
6821-
case (ast::init_recv) {
6822-
bcx = recv_val(bcx, llptr, init.expr, ty, INIT).bcx;
6823-
}
68246546
}
68256547
}
68266548
case (_) { bcx = zero_alloca(bcx, llptr, ty).bcx; }

0 commit comments

Comments
 (0)