diff options
| author | Brian Anderson <banderson@mozilla.com> | 2011-09-19 14:20:15 -0700 |
|---|---|---|
| committer | Brian Anderson <banderson@mozilla.com> | 2011-09-19 14:28:04 -0700 |
| commit | dd1cf63515d7703344cf18f8f44e8a1a1dedcd5f (patch) | |
| tree | 4c6a59a66e5f373d6fc09936233833e19e469e2e /src/comp | |
| parent | 432e931a2ab6a0e642a39f71b15e86dd3bfe3c9a (diff) | |
Build records in two phases to avoid cleanups on partial records
Diffstat (limited to 'src/comp')
| -rw-r--r-- | src/comp/middle/trans.rs | 47 |
1 files changed, 42 insertions, 5 deletions
diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 5cddc193529..fa56780e8db 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -3973,6 +3973,21 @@ fn trans_rec(cx: @block_ctxt, fields: [ast::field], } let ty_fields: [ty::field] = []; alt ty::struct(bcx_tcx(cx), t) { ty::ty_rec(flds) { ty_fields = flds; } } + + tag fieldsrc { + provided(lval_result); + inherited(ValueRef); + } + type fieldval = { + dst: ValueRef, + src: fieldsrc, + ty: ty::t + }; + let fieldvals: [fieldval] = []; + + // We build the record in two stages so that we don't have to clean up a + // partial record if we fail: first collect all the values, then construct + // the record. for tf: ty::field in ty_fields { let e_ty = tf.mt.ty; // FIXME: constraint on argument? @@ -3984,8 +3999,12 @@ fn trans_rec(cx: @block_ctxt, fields: [ast::field], if str::eq(f.node.ident, tf.ident) { expr_provided = true; let lv = trans_lval(bcx, f.node.expr); - bcx = - move_val_if_temp(lv.bcx, INIT, dst_res.val, lv, e_ty); + bcx = lv.bcx; + fieldvals += [{ + dst: dst_res.val, + src: provided(lv), + ty: e_ty + }]; break; } } @@ -3993,12 +4012,30 @@ fn trans_rec(cx: @block_ctxt, fields: [ast::field], // FIXME: constraint on argument? check type_is_tup_like(bcx, t); let src_res = GEP_tup_like(bcx, t, base_val, [0, i]); - src_res = - rslt(src_res.bcx, load_if_immediate(bcx, src_res.val, e_ty)); - bcx = copy_val(src_res.bcx, INIT, dst_res.val, src_res.val, e_ty); + bcx = src_res.bcx; + fieldvals += [{ + dst: dst_res.val, + src: inherited(src_res.val), + ty: e_ty + }]; } i += 1; } + + // Now build the record + for fieldval in fieldvals { + alt fieldval.src { + provided(lv) { + bcx = move_val_if_temp(bcx, INIT, fieldval.dst, + lv, fieldval.ty); + } + inherited(val) { + let val = load_if_immediate(bcx, val, fieldval.ty); + bcx = copy_val(bcx, INIT, fieldval.dst, val, fieldval.ty); + } + } + } + add_clean_temp(cx, rec_val, t); ret rslt(bcx, rec_val); } |
