diff options
| author | Marijn Haverbeke <marijnh@gmail.com> | 2011-08-02 11:44:00 +0200 |
|---|---|---|
| committer | Marijn Haverbeke <marijnh@gmail.com> | 2011-08-02 12:09:15 +0200 |
| commit | f8fa574864a5bd54752fc198438f8c53a8ed5ef0 (patch) | |
| tree | 01662bfbc8d189801822dc5b35fa88bb9f465c53 /src/comp | |
| parent | 043d95a2bdc6a344f1bfc7800b0ed719dbb6c7aa (diff) | |
| download | rust-f8fa574864a5bd54752fc198438f8c53a8ed5ef0.tar.gz rust-f8fa574864a5bd54752fc198438f8c53a8ed5ef0.zip | |
Copy locals created by destructuring on the content of a box
This is required so that assigning to these locals doesn't clobber the content of the box. (A possible optimization would be to only do this copying for locals that actually are assigned to.)
Diffstat (limited to 'src/comp')
| -rw-r--r-- | src/comp/middle/trans.rs | 6 | ||||
| -rw-r--r-- | src/comp/middle/trans_alt.rs | 21 |
2 files changed, 19 insertions, 8 deletions
diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index db06a6ca6cd..53f8b0b0d34 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -3631,7 +3631,7 @@ fn trans_for(cx: &@block_ctxt, local: &@ast::local, seq: &@ast::expr, let loc_r = copy_val(local_res.bcx, INIT, local_res.val, curr, t); add_clean(scope_cx, local_res.val, t); let bcx = trans_alt::bind_irrefutable_pat - (loc_r.bcx, local.node.pat, local_res.val, cx.fcx.lllocals); + (loc_r.bcx, local.node.pat, local_res.val, cx.fcx.lllocals, false); bcx = trans_block(bcx, body, return).bcx; if !bcx.build.is_terminated() { bcx.build.Br(next_cx.llbb); @@ -3982,7 +3982,7 @@ fn trans_for_each(cx: &@block_ctxt, local: &@ast::local, seq: &@ast::expr, // Add bindings for the loop variable alias. bcx = trans_alt::bind_irrefutable_pat (bcx, local.node.pat, llvm::LLVMGetParam(fcx.llfn, 3u), - bcx.fcx.llupvars); + bcx.fcx.llupvars, false); let lltop = bcx.llbb; let r = trans_block(bcx, body, return); finish_fn(fcx, lltop); @@ -5949,7 +5949,7 @@ fn init_local(bcx: @block_ctxt, local: &@ast::local) -> result { _ { bcx = zero_alloca(bcx, llptr, ty).bcx; } } bcx = trans_alt::bind_irrefutable_pat(bcx, local.node.pat, llptr, - bcx.fcx.lllocals); + bcx.fcx.lllocals, false); ret rslt(bcx, llptr); } diff --git a/src/comp/middle/trans_alt.rs b/src/comp/middle/trans_alt.rs index c77a3451266..899ba437cb1 100644 --- a/src/comp/middle/trans_alt.rs +++ b/src/comp/middle/trans_alt.rs @@ -437,12 +437,23 @@ fn trans_alt(cx: &@block_ctxt, expr: &@ast::expr, arms: &ast::arm[], // Not alt-related, but similar to the pattern-munging code above fn bind_irrefutable_pat(bcx: @block_ctxt, pat: &@ast::pat, val: ValueRef, - table: hashmap[ast::node_id, ValueRef]) + table: hashmap[ast::node_id, ValueRef], copy: bool) -> @block_ctxt { let ccx = bcx.fcx.lcx.ccx; alt pat.node { ast::pat_bind(_) { - table.insert(pat.id, val); + if copy { + let ty = ty::node_id_to_monotype(ccx.tcx, pat.id); + let llty = trans::type_of(ccx, pat.span, ty); + let alloc = trans::alloca(bcx, llty); + bcx = trans::memmove_ty(bcx, alloc, val, ty).bcx; + let loaded = trans::load_if_immediate(bcx, alloc, ty); + bcx = trans::copy_ty(bcx, loaded, ty).bcx; + table.insert(pat.id, alloc); + trans_common::add_clean(bcx, alloc, ty); + } else { + table.insert(pat.id, val); + } } ast::pat_tag(_, sub) { if ivec::len(sub) == 0u { ret bcx; } @@ -450,7 +461,7 @@ fn bind_irrefutable_pat(bcx: @block_ctxt, pat: &@ast::pat, val: ValueRef, let args = extract_variant_args(bcx, pat.id, vdefs, val); let i = 0; for argval: ValueRef in args.vals { - bcx = bind_irrefutable_pat(bcx, sub.(i), argval, table); + bcx = bind_irrefutable_pat(bcx, sub.(i), argval, table, copy); i += 1; } } @@ -462,14 +473,14 @@ fn bind_irrefutable_pat(bcx: @block_ctxt, pat: &@ast::pat, val: ValueRef, let ix: uint = ty::field_idx(ccx.sess, pat.span, f.ident, rec_fields); let r = trans::GEP_tup_like(bcx, rec_ty, val, ~[0, ix as int]); - bcx = bind_irrefutable_pat(r.bcx, f.pat, r.val, table); + bcx = bind_irrefutable_pat(r.bcx, f.pat, r.val, table, copy); } } ast::pat_box(inner) { let box = bcx.build.Load(val); let unboxed = bcx.build.InBoundsGEP (box, ~[C_int(0), C_int(back::abi::box_rc_field_body)]); - bcx = bind_irrefutable_pat(bcx, inner, unboxed, table); + bcx = bind_irrefutable_pat(bcx, inner, unboxed, table, true); } ast::pat_wild. | ast::pat_lit(_) {} } |
