Skip to content

Commit 37007a4

Browse files
committed
rustc: Populate the upvar environment when calling iterator bodies. Un-XFAIL test/run-pass/iter-range.rs.
1 parent 336f22d commit 37007a4

File tree

2 files changed

+71
-6
lines changed

2 files changed

+71
-6
lines changed

src/Makefile

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -454,7 +454,6 @@ TEST_XFAILS_RUSTC := $(addprefix test/run-pass/, \
454454
foreach-put-structured.rs \
455455
foreach-simple-outer-slot.rs \
456456
generic-iter-frame.rs \
457-
iter-range.rs \
458457
iter-ret.rs \
459458
lazychan.rs \
460459
lib-bitv.rs \

src/comp/middle/trans.rs

Lines changed: 71 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3008,12 +3008,49 @@ fn trans_for_each(@block_ctxt cx,
30083008
}
30093009

30103010
auto upvars = collect_upvars(cx, body, decl_id);
3011-
if (_vec.len[ast.def_id](upvars) > 0u) {
3012-
cx.fcx.ccx.sess.unimpl("upvars in for each");
3013-
fail;
3011+
auto upvar_count = _vec.len[ast.def_id](upvars);
3012+
3013+
auto llbindingsptr;
3014+
if (upvar_count > 0u) {
3015+
// Gather up the upvars.
3016+
let vec[ValueRef] llbindings = vec();
3017+
let vec[TypeRef] llbindingtys = vec();
3018+
for (ast.def_id did in upvars) {
3019+
auto llbinding;
3020+
alt (cx.fcx.lllocals.find(did)) {
3021+
case (none[ValueRef]) {
3022+
llbinding = cx.fcx.llupvars.get(did);
3023+
}
3024+
case (some[ValueRef](?llval)) { llbinding = llval; }
3025+
}
3026+
llbindings += vec(llbinding);
3027+
llbindingtys += vec(val_ty(llbinding));
3028+
}
3029+
3030+
// Create an array of bindings and copy in aliases to the upvars.
3031+
llbindingsptr = cx.build.Alloca(T_struct(llbindingtys));
3032+
auto i = 0u;
3033+
while (i < upvar_count) {
3034+
auto llbindingptr = cx.build.GEP(llbindingsptr,
3035+
vec(C_int(0), C_int(i as int)));
3036+
cx.build.Store(llbindings.(i), llbindingptr);
3037+
i += 1u;
3038+
}
3039+
} else {
3040+
// Null bindings.
3041+
llbindingsptr = C_null(T_ptr(T_i8()));
30143042
}
30153043

3016-
auto env_ty = T_opaque_closure_ptr(cx.fcx.ccx.tn);
3044+
// Create an environment and populate it with the bindings.
3045+
auto llenvptrty = T_closure_ptr(cx.fcx.ccx.tn, T_ptr(T_nil()),
3046+
val_ty(llbindingsptr), 0u);
3047+
auto llenvptr = cx.build.Alloca(llvm.LLVMGetElementType(llenvptrty));
3048+
3049+
auto llbindingsptrptr = cx.build.GEP(llenvptr,
3050+
vec(C_int(0),
3051+
C_int(abi.box_rc_field_body),
3052+
C_int(2)));
3053+
cx.build.Store(llbindingsptr, llbindingsptrptr);
30173054

30183055
// Step 2: Declare foreach body function.
30193056

@@ -3041,7 +3078,30 @@ fn trans_for_each(@block_ctxt cx,
30413078
auto fcx = new_fn_ctxt(cx.fcx.ccx, lliterbody);
30423079
auto bcx = new_top_block_ctxt(fcx);
30433080

3044-
// FIXME: populate lllocals from llenv here.
3081+
// Populate the upvars from the environment.
3082+
auto llremoteenvptr = bcx.build.PointerCast(fcx.llenv, llenvptrty);
3083+
auto llremotebindingsptrptr = bcx.build.GEP(llremoteenvptr,
3084+
vec(C_int(0), C_int(abi.box_rc_field_body), C_int(2)));
3085+
auto llremotebindingsptr = bcx.build.Load(llremotebindingsptrptr);
3086+
3087+
auto i = 0u;
3088+
while (i < upvar_count) {
3089+
auto upvar_id = upvars.(i);
3090+
auto llupvarptrptr = bcx.build.GEP(llremotebindingsptr,
3091+
vec(C_int(0), C_int(i as int)));
3092+
auto llupvarptr = bcx.build.Load(llupvarptrptr);
3093+
fcx.llupvars.insert(upvar_id, llupvarptr);
3094+
3095+
i += 1u;
3096+
}
3097+
3098+
// Treat the loop variable as an upvar as well. We copy it to an alloca
3099+
// as usual.
3100+
auto lllvar = llvm.LLVMGetParam(fcx.llfn, 3u);
3101+
auto lllvarptr = bcx.build.Alloca(val_ty(lllvar));
3102+
bcx.build.Store(lllvar, lllvarptr);
3103+
fcx.llupvars.insert(decl_id, lllvarptr);
3104+
30453105
auto res = trans_block(bcx, body);
30463106
res.bcx.build.RetVoid();
30473107

@@ -3059,6 +3119,12 @@ fn trans_for_each(@block_ctxt cx,
30593119
C_int(abi.fn_field_code)));
30603120
cx.build.Store(lliterbody, code_cell);
30613121

3122+
auto env_cell = cx.build.GEP(pair, vec(C_int(0),
3123+
C_int(abi.fn_field_box)));
3124+
auto llenvblobptr = cx.build.PointerCast(llenvptr,
3125+
T_opaque_closure_ptr(cx.fcx.ccx.tn));
3126+
cx.build.Store(llenvblobptr, env_cell);
3127+
30623128
// log "lliterbody: " + val_str(cx.fcx.ccx.tn, lliterbody);
30633129
ret trans_call(cx, f,
30643130
some[ValueRef](cx.build.Load(pair)),

0 commit comments

Comments
 (0)