Skip to content

Commit 6e65258

Browse files
committed
Get rid of 'overwrite' destination kind
It wasn't safe (computing the rval might invalidate the lval addr), and needlessly complicating things (code was already building up intermediary results to work around other unsafeties). Issue #667
1 parent 6e56ec0 commit 6e65258

File tree

4 files changed

+62
-102
lines changed

4 files changed

+62
-102
lines changed

src/comp/middle/trans.rs

Lines changed: 56 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -2112,6 +2112,7 @@ fn move_val(cx: @block_ctxt, action: copy_action, dst: ValueRef,
21122112
ty_to_str(tcx, t));
21132113
}
21142114

2115+
// FIXME[DPS] rename to store_temp_expr
21152116
fn move_val_if_temp(cx: @block_ctxt, action: copy_action, dst: ValueRef,
21162117
src: lval_result, t: ty::t) -> @block_ctxt {
21172118
// Lvals in memory are not temporaries. Copy them.
@@ -2213,7 +2214,7 @@ fn trans_unary(bcx: @block_ctxt, op: ast::unop, e: @ast::expr,
22132214
let llety = T_ptr(type_of(ccx, e_sp, e_ty));
22142215
body = PointerCast(bcx, body, llety);
22152216
}
2216-
bcx = trans_expr_save_in(bcx, e, body, INIT);
2217+
bcx = trans_expr_save_in(bcx, e, body);
22172218
revoke_clean(bcx, box);
22182219
ret store_in_dest(bcx, box, dest);
22192220
}
@@ -2255,8 +2256,7 @@ fn trans_expr_fn(bcx: @block_ctxt, f: ast::_fn, sp: span,
22552256
trans_closure(sub_cx, sp, f, llfn, none, [], id, {|_fcx|});
22562257
}
22572258
};
2258-
let {bcx, val: addr} = get_dest_addr(bcx, dest);
2259-
fill_fn_pair(bcx, addr, llfn, env);
2259+
fill_fn_pair(bcx, get_dest_addr(dest), llfn, env);
22602260
ret bcx;
22612261
}
22622262

@@ -2357,19 +2357,18 @@ fn trans_assign_op(bcx: @block_ctxt, op: ast::binop, dst: @ast::expr,
23572357
}
23582358
_ { }
23592359
}
2360-
let rhs_res = trans_expr(lhs_res.bcx, src);
2360+
let {bcx, val: rhs_val} = trans_expr(lhs_res.bcx, src);
23612361
if ty::type_is_sequence(tcx, t) {
23622362
alt op {
23632363
ast::add. {
2364-
ret tvec::trans_append(rhs_res.bcx, t, lhs_res.val,
2365-
rhs_res.val);
2364+
ret tvec::trans_append(bcx, t, lhs_res.val, rhs_val);
23662365
}
23672366
_ { }
23682367
}
23692368
}
2370-
let lhs_val = load_if_immediate(rhs_res.bcx, lhs_res.val, t);
2371-
ret trans_eager_binop(rhs_res.bcx, op, lhs_val, t, rhs_res.val, t,
2372-
overwrite(lhs_res.val, t));
2369+
2370+
ret trans_eager_binop(bcx, op, Load(bcx, lhs_res.val), t, rhs_val, t,
2371+
save_in(lhs_res.val));
23732372
}
23742373

23752374
fn autoderef(cx: @block_ctxt, v: ValueRef, t: ty::t) -> result_t {
@@ -2485,7 +2484,6 @@ tag dest {
24852484
by_val(@mutable ValueRef);
24862485
by_ref(@mutable ValueRef);
24872486
save_in(ValueRef);
2488-
overwrite(ValueRef, ty::t);
24892487
ignore;
24902488
}
24912489

@@ -2538,19 +2536,12 @@ fn store_in_dest(bcx: @block_ctxt, val: ValueRef, dest: dest) -> @block_ctxt {
25382536
ignore. {}
25392537
by_val(cell) { *cell = val; }
25402538
save_in(addr) { Store(bcx, val, addr); }
2541-
overwrite(addr, tp) {
2542-
bcx = drop_ty(bcx, addr, tp);
2543-
Store(bcx, val, addr);
2544-
}
25452539
}
25462540
ret bcx;
25472541
}
25482542

2549-
fn get_dest_addr(bcx: @block_ctxt, dest: dest) -> result {
2550-
alt dest {
2551-
save_in(a) { rslt(bcx, a) }
2552-
overwrite(a, t) { rslt(drop_ty(bcx, a, t), a) }
2553-
}
2543+
fn get_dest_addr(dest: dest) -> ValueRef {
2544+
alt dest { save_in(a) { a } }
25542545
}
25552546

25562547
// Wrapper through which legacy non-DPS code can use DPS functions
@@ -2733,7 +2724,7 @@ fn build_environment(bcx: @block_ctxt, lltydescs: [ValueRef],
27332724
bcx = bound.bcx;
27342725
alt bv {
27352726
env_expr(e) {
2736-
bcx = trans_expr_save_in(bcx, e, bound.val, INIT);
2727+
bcx = trans_expr_save_in(bcx, e, bound.val);
27372728
add_clean_temp_mem(bcx, bound.val, bound_tys[i]);
27382729
temp_cleanups += [bound.val];
27392730
}
@@ -3698,8 +3689,7 @@ fn trans_bind_1(cx: @block_ctxt, outgoing_fty: ty::t,
36983689
let lv = lval_maybe_callee_to_lval(f_res, pair_ty);
36993690
bcx = lv.bcx;
37003691
// FIXME[DPS] factor this out
3701-
let {bcx, val: addr} = get_dest_addr(bcx, dest);
3702-
ret memmove_ty(bcx, addr, lv.val, pair_ty);
3692+
ret memmove_ty(bcx, get_dest_addr(dest), lv.val, pair_ty);
37033693
}
37043694
let closure = alt f_res.env {
37053695
null_env. { none }
@@ -3736,8 +3726,7 @@ fn trans_bind_1(cx: @block_ctxt, outgoing_fty: ty::t,
37363726
closure.ptrty, ty_param_count, target_res);
37373727

37383728
// Fill the function pair
3739-
let {bcx, val: addr} = get_dest_addr(bcx, dest);
3740-
fill_fn_pair(bcx, addr, llthunk.val, closure.ptr);
3729+
fill_fn_pair(bcx, get_dest_addr(dest), llthunk.val, closure.ptr);
37413730
ret bcx;
37423731
}
37433732

@@ -3845,7 +3834,7 @@ fn trans_args(cx: @block_ctxt, outer_cx: @block_ctxt, llenv: ValueRef,
38453834
} else { alloca(cx, llretty) }
38463835
}
38473836
save_in(dst) { dst }
3848-
overwrite(_, _) | by_val(_) { alloca(cx, llretty) }
3837+
by_val(_) { alloca(cx, llretty) }
38493838
by_ref(_) { dest_ref = true; alloca(cx, T_ptr(llretty)) }
38503839
};
38513840
// FIXME[DSP] does this always hold?
@@ -3970,10 +3959,6 @@ fn trans_call(in_cx: @block_ctxt, f: @ast::expr,
39703959
}
39713960
}
39723961
save_in(_) { } // Already saved by callee
3973-
overwrite(a, t) {
3974-
bcx = drop_ty(bcx, a, t);
3975-
bcx = memmove_ty(bcx, a, llretslot, ret_ty);
3976-
}
39773962
by_ref(cell) | by_val(cell) {
39783963
*cell = Load(bcx, llretslot);
39793964
}
@@ -4167,55 +4152,38 @@ fn trans_landing_pad(bcx: @block_ctxt,
41674152
fn trans_tup(bcx: @block_ctxt, elts: [@ast::expr], id: ast::node_id,
41684153
dest: dest) -> @block_ctxt {
41694154
let t = node_id_type(bcx.fcx.lcx.ccx, id);
4170-
let (addr, overwrite) = alt dest {
4155+
let addr = alt dest {
41714156
ignore. {
41724157
for ex in elts { bcx = trans_expr_dps(bcx, ex, ignore); }
41734158
ret bcx;
41744159
}
4175-
save_in(pos) { (pos, none) }
4176-
overwrite(pos, _) {
4177-
let scratch = alloca(bcx, llvm::LLVMGetElementType(val_ty(pos)));
4178-
(scratch, some(pos))
4179-
}
4160+
save_in(pos) { pos }
41804161
};
41814162
let temp_cleanups = [], i = 0;
41824163
for e in elts {
41834164
let dst = GEP_tup_like_1(bcx, t, addr, [0, i]);
41844165
let e_ty = ty::expr_ty(bcx_tcx(bcx), e);
4185-
bcx = trans_expr_save_in(dst.bcx, e, dst.val, INIT);
4166+
bcx = trans_expr_save_in(dst.bcx, e, dst.val);
41864167
add_clean_temp_mem(bcx, dst.val, e_ty);
41874168
temp_cleanups += [dst.val];
41884169
i += 1;
41894170
}
41904171
for cleanup in temp_cleanups { revoke_clean(bcx, cleanup); }
4191-
alt overwrite {
4192-
some(pos) {
4193-
bcx = drop_ty(bcx, pos, t);
4194-
bcx = memmove_ty(bcx, pos, addr, t);
4195-
}
4196-
none. {}
4197-
}
41984172
ret bcx;
41994173
}
42004174

42014175
fn trans_rec(bcx: @block_ctxt, fields: [ast::field],
42024176
base: option::t<@ast::expr>, id: ast::node_id,
42034177
dest: dest) -> @block_ctxt {
42044178
let t = node_id_type(bcx_ccx(bcx), id);
4205-
let (addr, overwrite) = alt dest {
4179+
let addr = alt dest {
42064180
ignore. {
42074181
for fld in fields {
42084182
bcx = trans_expr_dps(bcx, fld.node.expr, ignore);
42094183
}
42104184
ret bcx;
42114185
}
4212-
save_in(pos) { (pos, none) }
4213-
// The expressions that populate the fields might still use the old
4214-
// record, so we build the new on in a scratch area
4215-
overwrite(pos, _) {
4216-
let scratch = alloca(bcx, llvm::LLVMGetElementType(val_ty(pos)));
4217-
(scratch, some(pos))
4218-
}
4186+
save_in(pos) { pos }
42194187
};
42204188

42214189
let base_val = alt base {
@@ -4234,7 +4202,7 @@ fn trans_rec(bcx: @block_ctxt, fields: [ast::field],
42344202
bcx = dst.bcx;
42354203
alt vec::find({|f| str::eq(f.node.ident, tf.ident)}, fields) {
42364204
some(f) {
4237-
bcx = trans_expr_save_in(bcx, f.node.expr, dst.val, INIT);
4205+
bcx = trans_expr_save_in(bcx, f.node.expr, dst.val);
42384206
}
42394207
none. {
42404208
let base = GEP_tup_like_1(bcx, t, base_val, [0, i]);
@@ -4249,13 +4217,6 @@ fn trans_rec(bcx: @block_ctxt, fields: [ast::field],
42494217
// Now revoke the cleanups as we pass responsibility for the data
42504218
// structure on to the caller
42514219
for cleanup in temp_cleanups { revoke_clean(bcx, cleanup); }
4252-
alt overwrite {
4253-
some(pos) {
4254-
bcx = drop_ty(bcx, pos, t);
4255-
bcx = memmove_ty(bcx, pos, addr, t);
4256-
}
4257-
none. {}
4258-
}
42594220
ret bcx;
42604221
}
42614222

@@ -4274,19 +4235,37 @@ fn trans_expr(cx: @block_ctxt, e: @ast::expr) -> result {
42744235
}
42754236
}
42764237

4277-
fn trans_expr_save_in(bcx: @block_ctxt, e: @ast::expr, dest: ValueRef,
4278-
kind: copy_action) -> @block_ctxt {
4238+
fn trans_expr_save_in(bcx: @block_ctxt, e: @ast::expr, dest: ValueRef)
4239+
-> @block_ctxt {
42794240
let tcx = bcx_tcx(bcx), t = ty::expr_ty(tcx, e);
42804241
let dst = if ty::type_is_bot(tcx, t) || ty::type_is_nil(tcx, t) {
42814242
ignore
4282-
} else if kind == INIT {
4283-
save_in(dest)
4284-
} else {
4285-
overwrite(dest, t)
4286-
};
4243+
} else { save_in(dest) };
42874244
ret trans_expr_dps(bcx, e, dst);
42884245
}
42894246

4247+
fn trans_temp_expr(bcx: @block_ctxt, e: @ast::expr) -> lval_result {
4248+
if expr_is_lval(bcx_tcx(bcx), e) {
4249+
ret trans_lval(bcx, e);
4250+
} else {
4251+
let tcx = bcx_tcx(bcx);
4252+
let ty = ty::expr_ty(tcx, e);
4253+
if ty::type_is_nil(tcx, ty) || ty::type_is_bot(tcx, ty) {
4254+
bcx = trans_expr_dps(bcx, e, ignore);
4255+
ret {bcx: bcx, val: C_nil(), is_mem: false};
4256+
} else if type_is_immediate(bcx_ccx(bcx), ty) {
4257+
let cell = empty_dest_cell();
4258+
bcx = trans_expr_dps(bcx, e, by_val(cell));
4259+
ret {bcx: bcx, val: *cell, is_mem: false};
4260+
} else {
4261+
let {bcx, val: scratch} = alloc_ty(bcx, ty);
4262+
bcx = trans_expr_dps(bcx, e, save_in(scratch));
4263+
ret {bcx: bcx, val: scratch, is_mem: false};
4264+
}
4265+
}
4266+
}
4267+
4268+
// FIXME[DPS] supersede by trans_temp_expr, get rid of by_ref dests
42904269
fn trans_expr_by_ref(bcx: @block_ctxt, e: @ast::expr) -> result {
42914270
let cell = empty_dest_cell();
42924271
bcx = trans_expr_dps(bcx, e, by_ref(cell));
@@ -4430,22 +4409,20 @@ fn trans_expr_dps(bcx: @block_ctxt, e: @ast::expr, dest: dest)
44304409
}
44314410
ast::expr_assign(dst, src) {
44324411
assert dest == ignore;
4433-
let {bcx, val: lhs_addr, is_mem} = trans_lval(bcx, dst);
4412+
let src_r = trans_temp_expr(bcx, src);
4413+
let {bcx, val: addr, is_mem} = trans_lval(src_r.bcx, dst);
44344414
assert is_mem;
4435-
ret trans_expr_save_in(bcx, src, lhs_addr, DROP_EXISTING);
4415+
ret move_val_if_temp(bcx, DROP_EXISTING, addr, src_r,
4416+
ty::expr_ty(bcx_tcx(bcx), src));
44364417
}
44374418
ast::expr_move(dst, src) {
4419+
// FIXME: calculate copy init-ness in typestate.
44384420
assert dest == ignore;
4439-
let {bcx, val: addr, is_mem} = trans_lval(bcx, dst);
4421+
let src_r = trans_temp_expr(bcx, src);
4422+
let {bcx, val: addr, is_mem} = trans_lval(src_r.bcx, dst);
44404423
assert is_mem;
4441-
// FIXME: calculate copy init-ness in typestate.
4442-
if expr_is_lval(tcx, src) {
4443-
ret trans_expr_save_in(bcx, src, addr, DROP_EXISTING);
4444-
} else {
4445-
let srclv = trans_lval(bcx, src);
4446-
let t = ty::expr_ty(tcx, src);
4447-
ret move_val(srclv.bcx, DROP_EXISTING, addr, srclv, t);
4448-
}
4424+
ret move_val(bcx, DROP_EXISTING, addr, src_r,
4425+
ty::expr_ty(bcx_tcx(bcx), src));
44494426
}
44504427
ast::expr_swap(dst, src) {
44514428
assert dest == ignore;
@@ -4492,9 +4469,6 @@ fn lval_to_dps(bcx: @block_ctxt, e: @ast::expr, dest: dest) -> @block_ctxt {
44924469
*cell = val;
44934470
}
44944471
save_in(loc) { bcx = move_val_if_temp(bcx, INIT, loc, lv, ty); }
4495-
overwrite(loc, _) {
4496-
bcx = move_val_if_temp(bcx, DROP_EXISTING, loc, lv, ty);
4497-
}
44984472
ignore. {}
44994473
}
45004474
ret bcx;
@@ -4746,7 +4720,7 @@ fn trans_ret(bcx: @block_ctxt, e: option::t<@ast::expr>) -> @block_ctxt {
47464720
Store(cx, val, bcx.fcx.llretptr);
47474721
bcx = cx;
47484722
} else {
4749-
bcx = trans_expr_save_in(bcx, x, bcx.fcx.llretptr, INIT);
4723+
bcx = trans_expr_save_in(bcx, x, bcx.fcx.llretptr);
47504724
}
47514725
}
47524726
_ {}
@@ -4784,7 +4758,7 @@ fn init_local(bcx: @block_ctxt, local: @ast::local) -> @block_ctxt {
47844758
some(init) {
47854759
if init.op == ast::init_assign ||
47864760
!expr_is_lval(bcx_tcx(bcx), init.expr) {
4787-
bcx = trans_expr_save_in(bcx, init.expr, llptr, INIT);
4761+
bcx = trans_expr_save_in(bcx, init.expr, llptr);
47884762
} else { // This is a move from an lval, must perform an actual move
47894763
let sub = trans_lval(bcx, init.expr);
47904764
bcx = move_val(sub.bcx, INIT, llptr, sub, ty);

src/comp/middle/trans_objects.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -378,7 +378,7 @@ fn trans_anon_obj(bcx: @block_ctxt, sp: span, anon_obj: ast::anon_obj,
378378
revoke_clean(bcx, box);
379379
box = PointerCast(bcx, box, llbox_ty);
380380
}
381-
let {bcx, val: pair} = trans::get_dest_addr(bcx, dest);
381+
let pair = trans::get_dest_addr(dest);
382382
let pair_vtbl = GEP(bcx, pair, [C_int(0), C_int(abi::obj_field_vtbl)]);
383383
Store(bcx, vtbl, pair_vtbl);
384384
let pair_box = GEP(bcx, pair, [C_int(0), C_int(abi::obj_field_box)]);

src/comp/middle/trans_uniq.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ fn trans_uniq(bcx: @block_ctxt, contents: @ast::expr,
2929
check type_is_unique_box(bcx, uniq_ty);
3030
let {bcx, val: llptr} = alloc_uniq(bcx, uniq_ty);
3131
add_clean_free(bcx, llptr, true);
32-
bcx = trans::trans_expr_save_in(bcx, contents, llptr, INIT);
32+
bcx = trans::trans_expr_save_in(bcx, contents, llptr);
3333
revoke_clean(bcx, llptr);
3434
ret trans::store_in_dest(bcx, llptr, dest);
3535
}

src/comp/middle/trans_vec.rs

Lines changed: 4 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -124,17 +124,13 @@ fn trans_vec(bcx: @block_ctxt, args: [@ast::expr], id: ast::node_id,
124124
let lleltptr = if ty::type_has_dynamic_size(bcx_tcx(bcx), unit_ty) {
125125
InBoundsGEP(bcx, dataptr, [Mul(bcx, C_uint(i), llunitsz)])
126126
} else { InBoundsGEP(bcx, dataptr, [C_uint(i)]) };
127-
bcx = trans::trans_expr_save_in(bcx, e, lleltptr, INIT);
127+
bcx = trans::trans_expr_save_in(bcx, e, lleltptr);
128128
add_clean_temp_mem(bcx, lleltptr, unit_ty);
129129
temp_cleanups += [lleltptr];
130130
i += 1u;
131131
}
132132
for clean in temp_cleanups { revoke_clean(bcx, clean); }
133-
let vptrptr = alt dest {
134-
trans::save_in(a) { a }
135-
trans::overwrite(a, t) { bcx = trans::drop_ty(bcx, a, t); a }
136-
};
137-
Store(bcx, vptr, vptrptr);
133+
Store(bcx, vptr, trans::get_dest_addr(dest));
138134
ret bcx;
139135
}
140136

@@ -147,11 +143,7 @@ fn trans_str(bcx: @block_ctxt, s: str, dest: dest) -> @block_ctxt {
147143
let bcx =
148144
call_memmove(bcx, get_dataptr_simple(bcx, sptr, T_i8()), llcstr,
149145
C_uint(veclen)).bcx;
150-
let sptrptr = alt dest {
151-
trans::save_in(a) { a }
152-
trans::overwrite(a, t) { bcx = trans::drop_ty(bcx, a, t); a }
153-
};
154-
Store(bcx, sptr, sptrptr);
146+
Store(bcx, sptr, trans::get_dest_addr(dest));
155147
ret bcx;
156148
}
157149

@@ -266,13 +258,7 @@ fn trans_add(bcx: @block_ctxt, vec_ty: ty::t, lhsptr: ValueRef,
266258

267259
let bcx = iter_vec_raw(bcx, lhsptr, vec_ty, lhs_fill, copy_fn);
268260
bcx = iter_vec_raw(bcx, rhsptr, vec_ty, rhs_fill, copy_fn);
269-
alt dest {
270-
trans::save_in(a) { Store(bcx, new_vec_ptr, a); }
271-
trans::overwrite(a, t) {
272-
bcx = trans::drop_ty(bcx, a, t);
273-
Store(bcx, new_vec_ptr, a);
274-
}
275-
}
261+
Store(bcx, new_vec_ptr, trans::get_dest_addr(dest));
276262
ret bcx;
277263
}
278264

0 commit comments

Comments
 (0)