diff options
| author | Patrick Walton <[email protected]> | 2011-04-15 18:14:29 -0700 |
|---|---|---|
| committer | Patrick Walton <[email protected]> | 2011-04-15 18:14:29 -0700 |
| commit | 0c288720b6d02f67a6f8002041a305f1986abc5c (patch) | |
| tree | 02bf7928870af373db76c5256399e810012fe8d8 /src/comp | |
| parent | rustc: Use a regular vector instead of a hash table for type descriptors (diff) | |
| download | rust-0c288720b6d02f67a6f8002041a305f1986abc5c.tar.xz rust-0c288720b6d02f67a6f8002041a305f1986abc5c.zip | |
rustc: Capture type parameters into for-each blocks. Add a test case.
Diffstat (limited to 'src/comp')
| -rw-r--r-- | src/comp/middle/trans.rs | 35 |
1 files changed, 33 insertions, 2 deletions
diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 3d6b547c..9181e52a 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -3298,8 +3298,9 @@ fn trans_for_each(@block_ctxt cx, } // Create an environment and populate it with the bindings. + auto tydesc_count = _vec.len[ValueRef](cx.fcx.lltydescs); auto llenvptrty = T_closure_ptr(cx.fcx.ccx.tn, T_ptr(T_nil()), - val_ty(llbindingsptr), 0u); + val_ty(llbindingsptr), tydesc_count); auto llenvptr = alloca(cx, llvm.LLVMGetElementType(llenvptrty)); auto llbindingsptrptr = cx.build.GEP(llenvptr, @@ -3308,6 +3309,20 @@ fn trans_for_each(@block_ctxt cx, C_int(2))); cx.build.Store(llbindingsptr, llbindingsptrptr); + // Copy in our type descriptors, in case the iterator body needs to refer + // to them. + auto lltydescsptr = cx.build.GEP(llenvptr, + vec(C_int(0), + C_int(abi.box_rc_field_body), + C_int(3))); + auto i = 0u; + while (i < tydesc_count) { + auto lltydescptr = cx.build.GEP(lltydescsptr, + vec(C_int(0), C_int(i as int))); + cx.build.Store(cx.fcx.lltydescs.(i), lltydescptr); + i += 1u; + } + // Step 2: Declare foreach body function. let str s = mangle_name_by_seq(cx.fcx.ccx, "foreach"); @@ -3339,7 +3354,7 @@ fn trans_for_each(@block_ctxt cx, vec(C_int(0), C_int(abi.box_rc_field_body), C_int(2))); auto llremotebindingsptr = bcx.build.Load(llremotebindingsptrptr); - auto i = 0u; + i = 0u; while (i < upvar_count) { auto upvar_id = upvars.(i); auto llupvarptrptr = bcx.build.GEP(llremotebindingsptr, @@ -3350,6 +3365,22 @@ fn trans_for_each(@block_ctxt cx, i += 1u; } + // Populate the type parameters from the environment. + auto llremotetydescsptr = bcx.build.GEP(llremoteenvptr, + vec(C_int(0), + C_int(abi.box_rc_field_body), + C_int(3))); + + i = 0u; + while (i < tydesc_count) { + auto llremotetydescptr = bcx.build.GEP(llremotetydescsptr, + vec(C_int(0), + C_int(i as int))); + auto llremotetydesc = bcx.build.Load(llremotetydescptr); + fcx.lltydescs += vec(llremotetydesc); + 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); |