Skip to content

Commit 6b40ced

Browse files
msullivanbrson
authored andcommitted
Pull building the environment for for_each into a seperate function.
1 parent c07443e commit 6b40ced

File tree

1 file changed

+61
-47
lines changed

1 file changed

+61
-47
lines changed

src/comp/middle/trans.rs

Lines changed: 61 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -4196,45 +4196,17 @@ fn collect_upvars(&@block_ctxt cx, &ast::block bloc,
41964196
ret result;
41974197
}
41984198

4199-
fn trans_for_each(&@block_ctxt cx, &@ast::local local, &@ast::expr seq,
4200-
&ast::block body) -> result {
4201-
/*
4202-
* The translation is a little .. complex here. Code like:
4203-
*
4204-
* let ty1 p = ...;
4205-
*
4206-
* let ty1 q = ...;
4207-
*
4208-
* foreach (ty v in foo(a,b)) { body(p,q,v) }
4209-
*
4210-
*
4211-
* Turns into a something like so (C/Rust mishmash):
4212-
*
4213-
* type env = { *ty1 p, *ty2 q, ... };
4214-
*
4215-
* let env e = { &p, &q, ... };
4216-
*
4217-
* fn foreach123_body(env* e, ty v) { body(*(e->p),*(e->q),v) }
4218-
*
4219-
* foo([foreach123_body, env*], a, b);
4220-
*
4221-
*/
4222-
4223-
// Step 1: walk body and figure out which references it makes
4224-
// escape. This could be determined upstream, and probably ought
4225-
// to be so, eventualy.
4226-
4227-
auto lcx = cx.fcx.lcx;
4228-
// FIXME: possibly support alias-mode here?
4229-
4230-
auto decl_ty = node_id_type(lcx.ccx, local.node.id);
4231-
auto decl_id = local.node.id;
4232-
auto upvars = collect_upvars(cx, body, decl_id);
4199+
// Given a block context and a list of upvars, construct a closure that
4200+
// contains pointers to all of the upvars and all of the tydescs in
4201+
// scope. Return the ValueRef and TypeRef corresponding to the closure.
4202+
fn build_environment(&@block_ctxt cx, &vec[ast::node_id] upvars) ->
4203+
tup(ValueRef, TypeRef)
4204+
{
42334205
auto upvar_count = vec::len(upvars);
42344206
auto llbindingsptr;
4207+
42354208
if (upvar_count > 0u) {
42364209
// Gather up the upvars.
4237-
42384210
let vec[ValueRef] llbindings = [];
42394211
let vec[TypeRef] llbindingtys = [];
42404212
for (ast::node_id nid in upvars) {
@@ -4253,8 +4225,8 @@ fn trans_for_each(&@block_ctxt cx, &@ast::local local, &@ast::expr seq,
42534225
llbindings += [llbinding];
42544226
llbindingtys += [val_ty(llbinding)];
42554227
}
4256-
// Create an array of bindings and copy in aliases to the upvars.
42574228

4229+
// Create an array of bindings and copy in aliases to the upvars.
42584230
llbindingsptr = alloca(cx, T_struct(llbindingtys));
42594231
auto i = 0u;
42604232
while (i < upvar_count) {
@@ -4265,23 +4237,22 @@ fn trans_for_each(&@block_ctxt cx, &@ast::local local, &@ast::expr seq,
42654237
}
42664238
} else {
42674239
// Null bindings.
4268-
42694240
llbindingsptr = C_null(T_ptr(T_i8()));
42704241
}
4271-
// Create an environment and populate it with the bindings.
42724242

4243+
// Create an environment and populate it with the bindings.
42734244
auto tydesc_count = vec::len[ValueRef](cx.fcx.lltydescs);
42744245
auto llenvptrty =
4275-
T_closure_ptr(lcx.ccx.tn, T_ptr(T_nil()), val_ty(llbindingsptr),
4276-
tydesc_count);
4246+
T_closure_ptr(cx.fcx.lcx.ccx.tn, T_ptr(T_nil()),
4247+
val_ty(llbindingsptr), tydesc_count);
42774248
auto llenvptr = alloca(cx, llvm::LLVMGetElementType(llenvptrty));
42784249
auto llbindingsptrptr =
42794250
cx.build.GEP(llenvptr,
42804251
[C_int(0), C_int(abi::box_rc_field_body), C_int(2)]);
42814252
cx.build.Store(llbindingsptr, llbindingsptrptr);
4253+
42824254
// Copy in our type descriptors, in case the iterator body needs to refer
42834255
// to them.
4284-
42854256
auto lltydescsptr =
42864257
cx.build.GEP(llenvptr,
42874258
[C_int(0), C_int(abi::box_rc_field_body),
@@ -4293,16 +4264,58 @@ fn trans_for_each(&@block_ctxt cx, &@ast::local local, &@ast::expr seq,
42934264
cx.build.Store(cx.fcx.lltydescs.(i), lltydescptr);
42944265
i += 1u;
42954266
}
4296-
// Step 2: Declare foreach body function.
42974267

4268+
ret tup(llenvptr, llenvptrty);
4269+
}
4270+
4271+
fn trans_for_each(&@block_ctxt cx, &@ast::local local, &@ast::expr seq,
4272+
&ast::block body) -> result {
4273+
/*
4274+
* The translation is a little .. complex here. Code like:
4275+
*
4276+
* let ty1 p = ...;
4277+
*
4278+
* let ty1 q = ...;
4279+
*
4280+
* foreach (ty v in foo(a,b)) { body(p,q,v) }
4281+
*
4282+
*
4283+
* Turns into a something like so (C/Rust mishmash):
4284+
*
4285+
* type env = { *ty1 p, *ty2 q, ... };
4286+
*
4287+
* let env e = { &p, &q, ... };
4288+
*
4289+
* fn foreach123_body(env* e, ty v) { body(*(e->p),*(e->q),v) }
4290+
*
4291+
* foo([foreach123_body, env*], a, b);
4292+
*
4293+
*/
4294+
4295+
// Step 1: walk body and figure out which references it makes
4296+
// escape. This could be determined upstream, and probably ought
4297+
// to be so, eventualy.
4298+
auto lcx = cx.fcx.lcx;
4299+
4300+
// FIXME: possibly support alias-mode here?
4301+
auto decl_ty = node_id_type(lcx.ccx, local.node.id);
4302+
auto decl_id = local.node.id;
4303+
auto upvars = collect_upvars(cx, body, decl_id);
4304+
auto upvar_count = vec::len(upvars);
4305+
4306+
auto environment_data = build_environment(cx, upvars);
4307+
auto llenvptr = environment_data._0;
4308+
auto llenvptrty = environment_data._1;
4309+
4310+
// Step 2: Declare foreach body function.
42984311
let str s =
42994312
mangle_internal_name_by_path_and_seq(lcx.ccx, lcx.path, "foreach");
4313+
43004314
// The 'env' arg entering the body function is a fake env member (as in
43014315
// the env-part of the normal rust calling convention) that actually
43024316
// points to a stack allocated env in this frame. We bundle that env
43034317
// pointer along with the foreach-body-fn pointer into a 'normal' fn pair
43044318
// and pass it in as a first class fn-arg to the iterator.
4305-
43064319
auto iter_body_llty =
43074320
type_of_fn_full(lcx.ccx, cx.sp, ast::proto_fn, none[TypeRef],
43084321
[rec(mode=ty::mo_alias(false), ty=decl_ty)],
@@ -4311,8 +4324,8 @@ fn trans_for_each(&@block_ctxt cx, &@ast::local local, &@ast::expr seq,
43114324
decl_internal_fastcall_fn(lcx.ccx.llmod, s, iter_body_llty);
43124325
auto fcx = new_fn_ctxt(lcx, cx.sp, lliterbody);
43134326
auto copy_args_bcx = new_raw_block_ctxt(fcx, fcx.llcopyargs);
4314-
// Populate the upvars from the environment.
43154327

4328+
// Populate the upvars from the environment.
43164329
auto llremoteenvptr =
43174330
copy_args_bcx.build.PointerCast(fcx.llenv, llenvptrty);
43184331
auto llremotebindingsptrptr =
@@ -4321,7 +4334,7 @@ fn trans_for_each(&@block_ctxt cx, &@ast::local local, &@ast::expr seq,
43214334
C_int(abi::closure_elt_bindings)]);
43224335
auto llremotebindingsptr =
43234336
copy_args_bcx.build.Load(llremotebindingsptrptr);
4324-
i = 0u;
4337+
auto i = 0u;
43254338
while (i < upvar_count) {
43264339
auto upvar_id = upvars.(i);
43274340
auto llupvarptrptr =
@@ -4331,12 +4344,13 @@ fn trans_for_each(&@block_ctxt cx, &@ast::local local, &@ast::expr seq,
43314344
fcx.llupvars.insert(upvar_id, llupvarptr);
43324345
i += 1u;
43334346
}
4334-
// Populate the type parameters from the environment.
43354347

4348+
// Populate the type parameters from the environment.
43364349
auto llremotetydescsptr =
43374350
copy_args_bcx.build.GEP(llremoteenvptr,
43384351
[C_int(0), C_int(abi::box_rc_field_body),
43394352
C_int(abi::closure_elt_ty_params)]);
4353+
auto tydesc_count = vec::len[ValueRef](cx.fcx.lltydescs);
43404354
i = 0u;
43414355
while (i < tydesc_count) {
43424356
auto llremotetydescptr =
@@ -4346,8 +4360,8 @@ fn trans_for_each(&@block_ctxt cx, &@ast::local local, &@ast::expr seq,
43464360
fcx.lltydescs += [llremotetydesc];
43474361
i += 1u;
43484362
}
4349-
// Add an upvar for the loop variable alias.
43504363

4364+
// Add an upvar for the loop variable alias.
43514365
fcx.llupvars.insert(decl_id, llvm::LLVMGetParam(fcx.llfn, 3u));
43524366
auto bcx = new_top_block_ctxt(fcx);
43534367
auto lltop = bcx.llbb;

0 commit comments

Comments
 (0)