aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPatrick Walton <[email protected]>2011-03-11 12:02:51 -0800
committerPatrick Walton <[email protected]>2011-03-11 12:02:51 -0800
commit37007a4d01c487a4fbd21306796a118c125a8906 (patch)
treebc92a97a3d3315ccfc42e6df75d0d1139f9c8505 /src
parentrustc: Resolve upvars as necessary (diff)
downloadrust-37007a4d01c487a4fbd21306796a118c125a8906.tar.xz
rust-37007a4d01c487a4fbd21306796a118c125a8906.zip
rustc: Populate the upvar environment when calling iterator bodies. Un-XFAIL test/run-pass/iter-range.rs.
Diffstat (limited to 'src')
-rw-r--r--src/Makefile1
-rw-r--r--src/comp/middle/trans.rs76
2 files changed, 71 insertions, 6 deletions
diff --git a/src/Makefile b/src/Makefile
index 21366b6b..ccb09990 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -454,7 +454,6 @@ TEST_XFAILS_RUSTC := $(addprefix test/run-pass/, \
foreach-put-structured.rs \
foreach-simple-outer-slot.rs \
generic-iter-frame.rs \
- iter-range.rs \
iter-ret.rs \
lazychan.rs \
lib-bitv.rs \
diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs
index 47bd63c8..17ec85c7 100644
--- a/src/comp/middle/trans.rs
+++ b/src/comp/middle/trans.rs
@@ -3008,12 +3008,49 @@ fn trans_for_each(@block_ctxt cx,
}
auto upvars = collect_upvars(cx, body, decl_id);
- if (_vec.len[ast.def_id](upvars) > 0u) {
- cx.fcx.ccx.sess.unimpl("upvars in for each");
- fail;
+ auto upvar_count = _vec.len[ast.def_id](upvars);
+
+ auto llbindingsptr;
+ if (upvar_count > 0u) {
+ // Gather up the upvars.
+ let vec[ValueRef] llbindings = vec();
+ let vec[TypeRef] llbindingtys = vec();
+ for (ast.def_id did in upvars) {
+ auto llbinding;
+ alt (cx.fcx.lllocals.find(did)) {
+ case (none[ValueRef]) {
+ llbinding = cx.fcx.llupvars.get(did);
+ }
+ case (some[ValueRef](?llval)) { llbinding = llval; }
+ }
+ llbindings += vec(llbinding);
+ llbindingtys += vec(val_ty(llbinding));
+ }
+
+ // Create an array of bindings and copy in aliases to the upvars.
+ llbindingsptr = cx.build.Alloca(T_struct(llbindingtys));
+ auto i = 0u;
+ while (i < upvar_count) {
+ auto llbindingptr = cx.build.GEP(llbindingsptr,
+ vec(C_int(0), C_int(i as int)));
+ cx.build.Store(llbindings.(i), llbindingptr);
+ i += 1u;
+ }
+ } else {
+ // Null bindings.
+ llbindingsptr = C_null(T_ptr(T_i8()));
}
- auto env_ty = T_opaque_closure_ptr(cx.fcx.ccx.tn);
+ // Create an environment and populate it with the bindings.
+ auto llenvptrty = T_closure_ptr(cx.fcx.ccx.tn, T_ptr(T_nil()),
+ val_ty(llbindingsptr), 0u);
+ auto llenvptr = cx.build.Alloca(llvm.LLVMGetElementType(llenvptrty));
+
+ auto llbindingsptrptr = cx.build.GEP(llenvptr,
+ vec(C_int(0),
+ C_int(abi.box_rc_field_body),
+ C_int(2)));
+ cx.build.Store(llbindingsptr, llbindingsptrptr);
// Step 2: Declare foreach body function.
@@ -3041,7 +3078,30 @@ fn trans_for_each(@block_ctxt cx,
auto fcx = new_fn_ctxt(cx.fcx.ccx, lliterbody);
auto bcx = new_top_block_ctxt(fcx);
- // FIXME: populate lllocals from llenv here.
+ // Populate the upvars from the environment.
+ auto llremoteenvptr = bcx.build.PointerCast(fcx.llenv, llenvptrty);
+ auto llremotebindingsptrptr = bcx.build.GEP(llremoteenvptr,
+ vec(C_int(0), C_int(abi.box_rc_field_body), C_int(2)));
+ auto llremotebindingsptr = bcx.build.Load(llremotebindingsptrptr);
+
+ auto i = 0u;
+ while (i < upvar_count) {
+ auto upvar_id = upvars.(i);
+ auto llupvarptrptr = bcx.build.GEP(llremotebindingsptr,
+ vec(C_int(0), C_int(i as int)));
+ auto llupvarptr = bcx.build.Load(llupvarptrptr);
+ fcx.llupvars.insert(upvar_id, llupvarptr);
+
+ i += 1u;
+ }
+
+ // Treat the loop variable as an upvar as well. We copy it to an alloca
+ // as usual.
+ auto lllvar = llvm.LLVMGetParam(fcx.llfn, 3u);
+ auto lllvarptr = bcx.build.Alloca(val_ty(lllvar));
+ bcx.build.Store(lllvar, lllvarptr);
+ fcx.llupvars.insert(decl_id, lllvarptr);
+
auto res = trans_block(bcx, body);
res.bcx.build.RetVoid();
@@ -3059,6 +3119,12 @@ fn trans_for_each(@block_ctxt cx,
C_int(abi.fn_field_code)));
cx.build.Store(lliterbody, code_cell);
+ auto env_cell = cx.build.GEP(pair, vec(C_int(0),
+ C_int(abi.fn_field_box)));
+ auto llenvblobptr = cx.build.PointerCast(llenvptr,
+ T_opaque_closure_ptr(cx.fcx.ccx.tn));
+ cx.build.Store(llenvblobptr, env_cell);
+
// log "lliterbody: " + val_str(cx.fcx.ccx.tn, lliterbody);
ret trans_call(cx, f,
some[ValueRef](cx.build.Load(pair)),