Skip to content

Commit 92d63ff

Browse files
committed
Make trans_rec and trans_tup understand overwrite dests
Issue #667
1 parent 8282f7f commit 92d63ff

File tree

1 file changed

+54
-45
lines changed

1 file changed

+54
-45
lines changed

src/comp/middle/trans.rs

+54-45
Original file line numberDiff line numberDiff line change
@@ -4029,30 +4029,56 @@ fn trans_landing_pad(bcx: @block_ctxt,
40294029
fn trans_tup(bcx: @block_ctxt, elts: [@ast::expr], id: ast::node_id,
40304030
dest: dest) -> @block_ctxt {
40314031
let t = node_id_type(bcx.fcx.lcx.ccx, id);
4032+
let (addr, overwrite) = alt dest {
4033+
ignore. {
4034+
for ex in elts { bcx = trans_expr_dps(bcx, ex, ignore); }
4035+
ret bcx;
4036+
}
4037+
save_in(pos) { (pos, none) }
4038+
overwrite(pos, _) {
4039+
let scratch = alloca(bcx, val_ty(pos));
4040+
(scratch, some(pos))
4041+
}
4042+
};
40324043
let temp_cleanups = [], i = 0;
40334044
for e in elts {
4034-
alt dest {
4035-
save_in(addr) {
4036-
let dst = GEP_tup_like_1(bcx, t, addr, [0, i]);
4037-
let e_ty = ty::expr_ty(bcx_tcx(bcx), e);
4038-
bcx = trans_expr_save_in(dst.bcx, e, dst.val);
4039-
add_clean_temp_mem(bcx, dst.val, e_ty);
4040-
temp_cleanups += [dst.val];
4041-
}
4042-
ignore. {
4043-
bcx = trans_expr_dps(bcx, e, ignore);
4044-
}
4045-
}
4045+
let dst = GEP_tup_like_1(bcx, t, addr, [0, i]);
4046+
let e_ty = ty::expr_ty(bcx_tcx(bcx), e);
4047+
bcx = trans_expr_save_in(dst.bcx, e, dst.val);
4048+
add_clean_temp_mem(bcx, dst.val, e_ty);
4049+
temp_cleanups += [dst.val];
40464050
i += 1;
40474051
}
40484052
for cleanup in temp_cleanups { revoke_clean(bcx, cleanup); }
4053+
alt overwrite {
4054+
some(pos) {
4055+
bcx = drop_ty(bcx, pos, t);
4056+
bcx = memmove_ty(bcx, pos, addr, t);
4057+
}
4058+
none. {}
4059+
}
40494060
ret bcx;
40504061
}
40514062

40524063
fn trans_rec(bcx: @block_ctxt, fields: [ast::field],
40534064
base: option::t<@ast::expr>, id: ast::node_id,
40544065
dest: dest) -> @block_ctxt {
40554066
let t = node_id_type(bcx_ccx(bcx), id);
4067+
let (addr, overwrite) = alt dest {
4068+
ignore. {
4069+
for fld in fields {
4070+
bcx = trans_expr_dps(bcx, fld.node.expr, ignore);
4071+
}
4072+
ret bcx;
4073+
}
4074+
save_in(pos) { (pos, none) }
4075+
// The expressions that populate the fields might still use the old
4076+
// record, so we build the new on in a scratch area
4077+
overwrite(pos, _) {
4078+
let scratch = alloca(bcx, val_ty(pos));
4079+
(scratch, some(pos))
4080+
}
4081+
};
40564082

40574083
let base_val = alt base {
40584084
some(bexp) {
@@ -4063,55 +4089,38 @@ fn trans_rec(bcx: @block_ctxt, fields: [ast::field],
40634089
none. { C_nil() }
40644090
};
40654091

4066-
let ty_fields = alt ty::struct(bcx_tcx(bcx), t) {
4067-
ty::ty_rec(f) { f }
4068-
ty::ty_bot. {
4069-
bcx_ccx(bcx).sess.bug("https://github.com/graydon/rust/issues/924")
4070-
}
4071-
};
4092+
let ty_fields = alt ty::struct(bcx_tcx(bcx), t) { ty::ty_rec(f) { f } };
40724093
let temp_cleanups = [], i = 0;
40734094
for tf in ty_fields {
4074-
let fdest = alt dest {
4075-
save_in(addr) {
4076-
let gep = GEP_tup_like_1(bcx, t, addr, [0, i]);
4077-
bcx = gep.bcx;
4078-
some(gep.val)
4079-
}
4080-
ignore. { none }
4081-
};
4095+
let gep = GEP_tup_like_1(bcx, t, addr, [0, i]);
4096+
bcx = gep.bcx;
40824097
// FIXME make this {|f| str::eq(f.node.ident, tf.ident)} again when
40834098
// bug #913 is fixed
40844099
fn test(n: str, f: ast::field) -> bool { str::eq(f.node.ident, n) }
40854100
alt vec::find(bind test(tf.ident, _), fields) {
40864101
some(f) {
4087-
alt fdest {
4088-
some(x) { bcx = trans_expr_save_in(bcx, f.node.expr, x); }
4089-
none. { bcx = trans_expr_dps(bcx, f.node.expr, ignore); }
4090-
}
4102+
bcx = trans_expr_save_in(bcx, f.node.expr, gep.val);
40914103
}
40924104
none. {
4093-
alt fdest {
4094-
some(addr) {
4095-
let gep = GEP_tup_like_1(bcx, t, base_val, [0, i]);
4096-
let val = load_if_immediate(gep.bcx, gep.val, tf.mt.ty);
4097-
bcx = copy_val(gep.bcx, INIT, addr, val, tf.mt.ty);
4098-
}
4099-
none. {}
4100-
}
4101-
}
4102-
}
4103-
alt fdest {
4104-
some(addr) {
4105-
add_clean_temp_mem(bcx, addr, tf.mt.ty);
4106-
temp_cleanups += [addr];
4105+
let base = GEP_tup_like_1(bcx, t, base_val, [0, i]);
4106+
let val = load_if_immediate(base.bcx, base.val, tf.mt.ty);
4107+
bcx = copy_val(base.bcx, INIT, gep.val, val, tf.mt.ty);
41074108
}
4108-
none. {}
41094109
}
4110+
add_clean_temp_mem(bcx, addr, tf.mt.ty);
4111+
temp_cleanups += [addr];
41104112
i += 1;
41114113
}
41124114
// Now revoke the cleanups as we pass responsibility for the data
41134115
// structure on to the caller
41144116
for cleanup in temp_cleanups { revoke_clean(bcx, cleanup); }
4117+
alt overwrite {
4118+
some(pos) {
4119+
bcx = drop_ty(bcx, pos, t);
4120+
bcx = memmove_ty(bcx, pos, addr, t);
4121+
}
4122+
none. {}
4123+
}
41154124
ret bcx;
41164125
}
41174126

0 commit comments

Comments
 (0)