提交 081caf5b 编写于 作者: M Marijn Haverbeke

Do not check for self-assign unless dest is initialized

Also, give copy_val and move_val a more sane return type.
上级 c930af74
...@@ -2086,7 +2086,6 @@ fn lazily_emit_tydesc_glue(cx: &@block_ctxt, field: int, ...@@ -2086,7 +2086,6 @@ fn lazily_emit_tydesc_glue(cx: &@block_ctxt, field: int,
make_generic_glue(lcx, cx.sp, ti.ty, glue_fn, make_generic_glue(lcx, cx.sp, ti.ty, glue_fn,
copy_helper(make_copy_glue), copy_helper(make_copy_glue),
ti.ty_params, "copy"); ti.ty_params, "copy");
} }
} }
} }
...@@ -2319,8 +2318,34 @@ fn duplicate_heap_parts_if_necessary(cx: &@block_ctxt, vptr: ValueRef, ...@@ -2319,8 +2318,34 @@ fn duplicate_heap_parts_if_necessary(cx: &@block_ctxt, vptr: ValueRef,
tag copy_action { INIT; DROP_EXISTING; } tag copy_action { INIT; DROP_EXISTING; }
// These are the types that are passed by pointer.
fn type_is_structural_or_param(tcx: &ty::ctxt, t: ty::t) -> bool {
if ty::type_is_structural(tcx, t) { ret true; }
alt ty::struct(tcx, t) {
ty::ty_param(_, _) { ret true; }
_ { ret false; }
}
}
fn copy_val(cx: &@block_ctxt, action: copy_action, dst: ValueRef, fn copy_val(cx: &@block_ctxt, action: copy_action, dst: ValueRef,
src: ValueRef, t: &ty::t) -> result { src: ValueRef, t: &ty::t) -> @block_ctxt {
if type_is_structural_or_param(bcx_ccx(cx).tcx, t) &&
action == DROP_EXISTING {
let do_copy_cx = new_sub_block_ctxt(cx, "do_copy");
let next_cx = new_sub_block_ctxt(cx, "next");
let self_assigning =
cx.build.ICmp(lib::llvm::LLVMIntNE,
cx.build.PointerCast(dst, val_ty(src)), src);
cx.build.CondBr(self_assigning, do_copy_cx.llbb, next_cx.llbb);
do_copy_cx = copy_val_no_check(do_copy_cx, action, dst, src, t);
do_copy_cx.build.Br(next_cx.llbb);
ret next_cx;
}
ret copy_val_no_check(cx, action, dst, src, t);
}
fn copy_val_no_check(cx: &@block_ctxt, action: copy_action, dst: ValueRef,
src: ValueRef, t: &ty::t) -> @block_ctxt {
let ccx = bcx_ccx(cx); let ccx = bcx_ccx(cx);
// FIXME this is just a clunky stopgap. we should do proper checking in an // FIXME this is just a clunky stopgap. we should do proper checking in an
// earlier pass. // earlier pass.
...@@ -2329,36 +2354,26 @@ fn copy_val(cx: &@block_ctxt, action: copy_action, dst: ValueRef, ...@@ -2329,36 +2354,26 @@ fn copy_val(cx: &@block_ctxt, action: copy_action, dst: ValueRef,
} }
if ty::type_is_scalar(ccx.tcx, t) || ty::type_is_native(ccx.tcx, t) { if ty::type_is_scalar(ccx.tcx, t) || ty::type_is_native(ccx.tcx, t) {
ret rslt(cx, cx.build.Store(src, dst)); cx.build.Store(src, dst);
ret cx;
} else if ty::type_is_nil(ccx.tcx, t) || ty::type_is_bot(ccx.tcx, t) { } else if ty::type_is_nil(ccx.tcx, t) || ty::type_is_bot(ccx.tcx, t) {
ret rslt(cx, C_nil()); ret cx;
} else if ty::type_is_boxed(ccx.tcx, t) { } else if ty::type_is_boxed(ccx.tcx, t) {
let bcx; let bcx = if action == DROP_EXISTING {
if action == DROP_EXISTING { drop_ty(cx, cx.build.Load(dst), t).bcx
bcx = drop_ty(cx, cx.build.Load(dst), t).bcx; } else { cx };
} else { bcx = cx; }
bcx = take_ty(bcx, src, t).bcx; bcx = take_ty(bcx, src, t).bcx;
ret rslt(bcx, bcx.build.Store(src, dst)); bcx.build.Store(src, dst);
} else if ty::type_is_structural(ccx.tcx, t) || ret bcx;
ty::type_has_dynamic_size(ccx.tcx, t) { } else if type_is_structural_or_param(ccx.tcx, t) {
// Check for self-assignment. let bcx = if action == DROP_EXISTING {
let do_copy_cx = new_sub_block_ctxt(cx, "do_copy"); drop_ty(cx, dst, t).bcx
let next_cx = new_sub_block_ctxt(cx, "next"); } else { cx };
let self_assigning = bcx = memmove_ty(bcx, dst, src, t).bcx;
cx.build.ICmp(lib::llvm::LLVMIntNE, bcx = take_ty(bcx, dst, t).bcx;
cx.build.PointerCast(dst, val_ty(src)), src); ret bcx;
cx.build.CondBr(self_assigning, do_copy_cx.llbb, next_cx.llbb);
if action == DROP_EXISTING {
do_copy_cx = drop_ty(do_copy_cx, dst, t).bcx;
}
do_copy_cx = memmove_ty(do_copy_cx, dst, src, t).bcx;
do_copy_cx = take_ty(do_copy_cx, dst, t).bcx;
do_copy_cx.build.Br(next_cx.llbb);
ret rslt(next_cx, C_nil());
} }
ccx.sess.bug("unexpected type in trans::copy_val: " + ccx.sess.bug("unexpected type in trans::copy_val_no_check: " +
ty_to_str(ccx.tcx, t)); ty_to_str(ccx.tcx, t));
} }
...@@ -2368,18 +2383,17 @@ fn copy_val(cx: &@block_ctxt, action: copy_action, dst: ValueRef, ...@@ -2368,18 +2383,17 @@ fn copy_val(cx: &@block_ctxt, action: copy_action, dst: ValueRef,
// FIXME: We always zero out the source. Ideally we would detect the // FIXME: We always zero out the source. Ideally we would detect the
// case where a variable is always deinitialized by block exit and thus // case where a variable is always deinitialized by block exit and thus
// doesn't need to be dropped. // doesn't need to be dropped.
// FIXME: This can return only a block_ctxt, not a result.
fn move_val(cx: @block_ctxt, action: copy_action, dst: ValueRef, fn move_val(cx: @block_ctxt, action: copy_action, dst: ValueRef,
src: &lval_result, t: &ty::t) -> result { src: &lval_result, t: &ty::t) -> @block_ctxt {
let src_val = src.res.val; let src_val = src.res.val;
if ty::type_is_scalar(bcx_tcx(cx), t) || if ty::type_is_scalar(bcx_tcx(cx), t) ||
ty::type_is_native(bcx_tcx(cx), t) { ty::type_is_native(bcx_tcx(cx), t) {
if src.is_mem { src_val = cx.build.Load(src_val); } if src.is_mem { src_val = cx.build.Load(src_val); }
cx.build.Store(src_val, dst); cx.build.Store(src_val, dst);
ret rslt(cx, C_nil()); ret cx;
} else if ty::type_is_nil(bcx_tcx(cx), t) || } else if ty::type_is_nil(bcx_tcx(cx), t) ||
ty::type_is_bot(bcx_tcx(cx), t) { ty::type_is_bot(bcx_tcx(cx), t) {
ret rslt(cx, C_nil()); ret cx;
} else if ty::type_is_unique(bcx_tcx(cx), t) || } else if ty::type_is_unique(bcx_tcx(cx), t) ||
ty::type_is_boxed(bcx_tcx(cx), t) { ty::type_is_boxed(bcx_tcx(cx), t) {
if src.is_mem { src_val = cx.build.Load(src_val); } if src.is_mem { src_val = cx.build.Load(src_val); }
...@@ -2387,20 +2401,20 @@ fn move_val(cx: @block_ctxt, action: copy_action, dst: ValueRef, ...@@ -2387,20 +2401,20 @@ fn move_val(cx: @block_ctxt, action: copy_action, dst: ValueRef,
cx = drop_ty(cx, cx.build.Load(dst), t).bcx; cx = drop_ty(cx, cx.build.Load(dst), t).bcx;
} }
cx.build.Store(src_val, dst); cx.build.Store(src_val, dst);
if src.is_mem { ret zero_alloca(cx, src.res.val, t); } if src.is_mem { ret zero_alloca(cx, src.res.val, t).bcx; }
// If we're here, it must be a temporary. // If we're here, it must be a temporary.
revoke_clean(cx, src_val); revoke_clean(cx, src_val);
ret rslt(cx, C_nil()); ret cx;
} else if ty::type_is_structural(bcx_tcx(cx), t) || } else if ty::type_is_structural(bcx_tcx(cx), t) ||
ty::type_has_dynamic_size(bcx_tcx(cx), t) { ty::type_has_dynamic_size(bcx_tcx(cx), t) {
if action == DROP_EXISTING { cx = drop_ty(cx, dst, t).bcx; } if action == DROP_EXISTING { cx = drop_ty(cx, dst, t).bcx; }
cx = memmove_ty(cx, dst, src_val, t).bcx; cx = memmove_ty(cx, dst, src_val, t).bcx;
if src.is_mem { if src.is_mem {
ret zero_alloca(cx, src_val, t); ret zero_alloca(cx, src_val, t).bcx;
} else { // Temporary value } else { // Temporary value
revoke_clean(cx, src_val); revoke_clean(cx, src_val);
ret rslt(cx, C_nil()); ret cx;
} }
} }
bcx_ccx(cx).sess.bug("unexpected type in trans::move_val: " + bcx_ccx(cx).sess.bug("unexpected type in trans::move_val: " +
...@@ -2408,7 +2422,7 @@ fn move_val(cx: @block_ctxt, action: copy_action, dst: ValueRef, ...@@ -2408,7 +2422,7 @@ fn move_val(cx: @block_ctxt, action: copy_action, dst: ValueRef,
} }
fn move_val_if_temp(cx: @block_ctxt, action: copy_action, dst: ValueRef, fn move_val_if_temp(cx: @block_ctxt, action: copy_action, dst: ValueRef,
src: &lval_result, t: &ty::t) -> result { src: &lval_result, t: &ty::t) -> @block_ctxt {
// Lvals in memory are not temporaries. Copy them. // Lvals in memory are not temporaries. Copy them.
if src.is_mem { if src.is_mem {
...@@ -2560,8 +2574,8 @@ fn trans_unary(cx: &@block_ctxt, op: ast::unop, e: &@ast::expr, ...@@ -2560,8 +2574,8 @@ fn trans_unary(cx: &@block_ctxt, op: ast::unop, e: &@ast::expr,
let llety = T_ptr(type_of(bcx_ccx(sub.bcx), e.span, e_ty)); let llety = T_ptr(type_of(bcx_ccx(sub.bcx), e.span, e_ty));
body = sub.bcx.build.PointerCast(body, llety); body = sub.bcx.build.PointerCast(body, llety);
} }
let res = move_val_if_temp(sub.bcx, INIT, body, lv, e_ty); let bcx = move_val_if_temp(sub.bcx, INIT, body, lv, e_ty);
ret rslt(res.bcx, sub.box); ret rslt(bcx, sub.box);
} }
ast::deref. { ast::deref. {
bcx_ccx(cx).sess.bug("deref expressions should have been \ bcx_ccx(cx).sess.bug("deref expressions should have been \
...@@ -2901,10 +2915,8 @@ fn trans_append(cx: &@block_ctxt, t: &ty::t, orig_lhs: ValueRef, ...@@ -2901,10 +2915,8 @@ fn trans_append(cx: &@block_ctxt, t: &ty::t, orig_lhs: ValueRef,
let copy_src = let copy_src =
load_if_immediate(copy_loop_body_cx, copy_src_ptr, unit_ty); load_if_immediate(copy_loop_body_cx, copy_src_ptr, unit_ty);
rs = let post_copy_cx = copy_val
copy_val(copy_loop_body_cx, INIT, copy_dest_ptr, copy_src, (copy_loop_body_cx, INIT, copy_dest_ptr, copy_src, unit_ty);
unit_ty);
let post_copy_cx = rs.bcx;
// Increment both pointers. // Increment both pointers.
if ty::type_has_dynamic_size(bcx_tcx(cx), t) { if ty::type_has_dynamic_size(bcx_tcx(cx), t) {
// We have to increment by the dynamically-computed size. // We have to increment by the dynamically-computed size.
...@@ -3104,10 +3116,8 @@ fn trans_add(cx: &@block_ctxt, vec_ty: ty::t, lhs: ValueRef, ...@@ -3104,10 +3116,8 @@ fn trans_add(cx: &@block_ctxt, vec_ty: ty::t, lhs: ValueRef,
rhs_copy_cx.llbb); rhs_copy_cx.llbb);
let dest_ptr_lhs_copy = lhs_do_copy_cx.build.Load(dest_ptr_ptr); let dest_ptr_lhs_copy = lhs_do_copy_cx.build.Load(dest_ptr_ptr);
let lhs_val = load_if_immediate(lhs_do_copy_cx, lhs_ptr, unit_ty); let lhs_val = load_if_immediate(lhs_do_copy_cx, lhs_ptr, unit_ty);
rs = lhs_do_copy_cx = copy_val(lhs_do_copy_cx, INIT, dest_ptr_lhs_copy,
copy_val(lhs_do_copy_cx, INIT, dest_ptr_lhs_copy, lhs_val, lhs_val, unit_ty);
unit_ty);
lhs_do_copy_cx = rs.bcx;
// Increment both pointers. // Increment both pointers.
if ty::type_has_dynamic_size(bcx_tcx(cx), unit_ty) { if ty::type_has_dynamic_size(bcx_tcx(cx), unit_ty) {
...@@ -3133,10 +3143,8 @@ fn trans_add(cx: &@block_ctxt, vec_ty: ty::t, lhs: ValueRef, ...@@ -3133,10 +3143,8 @@ fn trans_add(cx: &@block_ctxt, vec_ty: ty::t, lhs: ValueRef,
next_cx.llbb); next_cx.llbb);
let dest_ptr_rhs_copy = rhs_do_copy_cx.build.Load(dest_ptr_ptr); let dest_ptr_rhs_copy = rhs_do_copy_cx.build.Load(dest_ptr_ptr);
let rhs_val = load_if_immediate(rhs_do_copy_cx, rhs_ptr, unit_ty); let rhs_val = load_if_immediate(rhs_do_copy_cx, rhs_ptr, unit_ty);
rs = rhs_do_copy_cx = copy_val(rhs_do_copy_cx, INIT, dest_ptr_rhs_copy,
copy_val(rhs_do_copy_cx, INIT, dest_ptr_rhs_copy, rhs_val, rhs_val, unit_ty);
unit_ty);
rhs_do_copy_cx = rs.bcx;
// Increment both pointers. // Increment both pointers.
if ty::type_has_dynamic_size(bcx_tcx(cx), unit_ty) { if ty::type_has_dynamic_size(bcx_tcx(cx), unit_ty) {
...@@ -3227,8 +3235,8 @@ fn trans_evec_add(cx: &@block_ctxt, t: &ty::t, lhs: ValueRef, rhs: ValueRef) ...@@ -3227,8 +3235,8 @@ fn trans_evec_add(cx: &@block_ctxt, t: &ty::t, lhs: ValueRef, rhs: ValueRef)
-> result { -> result {
let r = alloc_ty(cx, t); let r = alloc_ty(cx, t);
let tmp = r.val; let tmp = r.val;
r = copy_val(r.bcx, INIT, tmp, lhs, t); let bcx = copy_val(r.bcx, INIT, tmp, lhs, t);
let bcx = trans_evec_append(r.bcx, t, tmp, rhs).bcx; let bcx = trans_evec_append(bcx, t, tmp, rhs).bcx;
tmp = load_if_immediate(bcx, tmp, t); tmp = load_if_immediate(bcx, tmp, t);
add_clean_temp(cx, tmp, t); add_clean_temp(cx, tmp, t);
ret rslt(bcx, tmp); ret rslt(bcx, tmp);
...@@ -3486,10 +3494,10 @@ fn inner(cx: &@block_ctxt, local: @ast::local, curr: ValueRef, t: ty::t, ...@@ -3486,10 +3494,10 @@ fn inner(cx: &@block_ctxt, local: @ast::local, curr: ValueRef, t: ty::t,
outer_next_cx, "for loop scope"); outer_next_cx, "for loop scope");
cx.build.Br(scope_cx.llbb); cx.build.Br(scope_cx.llbb);
let local_res = alloc_local(scope_cx, local); let local_res = alloc_local(scope_cx, local);
let loc_r = copy_val(local_res.bcx, INIT, local_res.val, curr, t); let bcx = copy_val(local_res.bcx, INIT, local_res.val, curr, t);
add_clean(scope_cx, local_res.val, t); add_clean(scope_cx, local_res.val, t);
let bcx = let bcx =
trans_alt::bind_irrefutable_pat(loc_r.bcx, local.node.pat, trans_alt::bind_irrefutable_pat(bcx, local.node.pat,
local_res.val, cx.fcx.lllocals, local_res.val, cx.fcx.lllocals,
false); false);
bcx = trans_block(bcx, body, return).bcx; bcx = trans_block(bcx, body, return).bcx;
...@@ -3587,8 +3595,7 @@ fn build_environment(bcx: @block_ctxt, lltydescs: [ValueRef], ...@@ -3587,8 +3595,7 @@ fn build_environment(bcx: @block_ctxt, lltydescs: [ValueRef],
GEP_tup_like(bcx, bindings_ty, bindings.val, [0, i as int]); GEP_tup_like(bcx, bindings_ty, bindings.val, [0, i as int]);
bcx = bound.bcx; bcx = bound.bcx;
if copying { if copying {
bcx = bcx = move_val_if_temp(bcx, INIT, bound.val, lv, bound_tys[i]);
move_val_if_temp(bcx, INIT, bound.val, lv, bound_tys[i]).bcx;
} else { bcx.build.Store(lv.res.val, bound.val); } } else { bcx.build.Store(lv.res.val, bound.val); }
i += 1u; i += 1u;
} }
...@@ -4548,7 +4555,7 @@ fn trans_arg_expr(cx: &@block_ctxt, arg: &ty::arg, lldestty0: TypeRef, ...@@ -4548,7 +4555,7 @@ fn trans_arg_expr(cx: &@block_ctxt, arg: &ty::arg, lldestty0: TypeRef,
// Do nothing for temporaries, just give them to callee // Do nothing for temporaries, just give them to callee
} else if ty::type_is_structural(ccx.tcx, e_ty) { } else if ty::type_is_structural(ccx.tcx, e_ty) {
let dst = alloc_ty(bcx, e_ty); let dst = alloc_ty(bcx, e_ty);
bcx = copy_val(dst.bcx, INIT, dst.val, val, e_ty).bcx; bcx = copy_val(dst.bcx, INIT, dst.val, val, e_ty);
val = dst.val; val = dst.val;
add_clean_temp(bcx, val, e_ty); add_clean_temp(bcx, val, e_ty);
} else { } else {
...@@ -4797,7 +4804,7 @@ fn trans_tup(cx: &@block_ctxt, elts: &[@ast::expr], id: ast::node_id) -> ...@@ -4797,7 +4804,7 @@ fn trans_tup(cx: &@block_ctxt, elts: &[@ast::expr], id: ast::node_id) ->
let src = trans_lval(bcx, e); let src = trans_lval(bcx, e);
bcx = src.res.bcx; bcx = src.res.bcx;
let dst_res = GEP_tup_like(bcx, t, tup_val, [0, i]); let dst_res = GEP_tup_like(bcx, t, tup_val, [0, i]);
bcx = move_val_if_temp(dst_res.bcx, INIT, dst_res.val, src, e_ty).bcx; bcx = move_val_if_temp(dst_res.bcx, INIT, dst_res.val, src, e_ty);
i += 1; i += 1;
} }
ret rslt(bcx, tup_val); ret rslt(bcx, tup_val);
...@@ -4891,7 +4898,7 @@ fn trans_ivec(bcx: @block_ctxt, args: &[@ast::expr], id: ast::node_id) -> ...@@ -4891,7 +4898,7 @@ fn trans_ivec(bcx: @block_ctxt, args: &[@ast::expr], id: ast::node_id) ->
} else { } else {
lleltptr = bcx.build.InBoundsGEP(llfirsteltptr, [C_uint(i)]); lleltptr = bcx.build.InBoundsGEP(llfirsteltptr, [C_uint(i)]);
} }
bcx = move_val_if_temp(bcx, INIT, lleltptr, lv, unit_ty).bcx; bcx = move_val_if_temp(bcx, INIT, lleltptr, lv, unit_ty);
i += 1u; i += 1u;
} }
ret rslt(bcx, llvecptr); ret rslt(bcx, llvecptr);
...@@ -4926,9 +4933,8 @@ fn trans_rec(cx: &@block_ctxt, fields: &[ast::field], ...@@ -4926,9 +4933,8 @@ fn trans_rec(cx: &@block_ctxt, fields: &[ast::field],
if str::eq(f.node.ident, tf.ident) { if str::eq(f.node.ident, tf.ident) {
expr_provided = true; expr_provided = true;
let lv = trans_lval(bcx, f.node.expr); let lv = trans_lval(bcx, f.node.expr);
bcx = bcx = move_val_if_temp(lv.res.bcx, INIT, dst_res.val,
move_val_if_temp(lv.res.bcx, INIT, dst_res.val, lv, lv, e_ty);
e_ty).bcx;
break; break;
} }
} }
...@@ -4936,9 +4942,7 @@ fn trans_rec(cx: &@block_ctxt, fields: &[ast::field], ...@@ -4936,9 +4942,7 @@ fn trans_rec(cx: &@block_ctxt, fields: &[ast::field],
let src_res = GEP_tup_like(bcx, t, base_val, [0, i]); let src_res = GEP_tup_like(bcx, t, base_val, [0, i]);
src_res = src_res =
rslt(src_res.bcx, load_if_immediate(bcx, src_res.val, e_ty)); rslt(src_res.bcx, load_if_immediate(bcx, src_res.val, e_ty));
bcx = bcx = copy_val(src_res.bcx, INIT, dst_res.val, src_res.val, e_ty);
copy_val(src_res.bcx, INIT, dst_res.val, src_res.val,
e_ty).bcx;
} }
i += 1; i += 1;
} }
...@@ -5023,10 +5027,9 @@ fn trans_expr_out(cx: &@block_ctxt, e: &@ast::expr, output: out_method) -> ...@@ -5023,10 +5027,9 @@ fn trans_expr_out(cx: &@block_ctxt, e: &@ast::expr, output: out_method) ->
let t = ty::expr_ty(bcx_tcx(cx), src); let t = ty::expr_ty(bcx_tcx(cx), src);
// FIXME: calculate copy init-ness in typestate. // FIXME: calculate copy init-ness in typestate.
let move_res = let bcx = move_val(rhs_res.res.bcx, DROP_EXISTING, lhs_res.res.val,
move_val(rhs_res.res.bcx, DROP_EXISTING, lhs_res.res.val, rhs_res, rhs_res, t);
t); ret rslt(bcx, C_nil());
ret rslt(move_res.bcx, C_nil());
} }
ast::expr_assign(dst, src) { ast::expr_assign(dst, src) {
let lhs_res = trans_lval(cx, dst); let lhs_res = trans_lval(cx, dst);
...@@ -5035,10 +5038,9 @@ fn trans_expr_out(cx: &@block_ctxt, e: &@ast::expr, output: out_method) -> ...@@ -5035,10 +5038,9 @@ fn trans_expr_out(cx: &@block_ctxt, e: &@ast::expr, output: out_method) ->
let rhs = trans_lval(lhs_res.res.bcx, src); let rhs = trans_lval(lhs_res.res.bcx, src);
let t = ty::expr_ty(bcx_tcx(cx), src); let t = ty::expr_ty(bcx_tcx(cx), src);
// FIXME: calculate copy init-ness in typestate. // FIXME: calculate copy init-ness in typestate.
let copy_res = let bcx = move_val_if_temp(rhs.res.bcx, DROP_EXISTING,
move_val_if_temp(rhs.res.bcx, DROP_EXISTING, lhs_res.res.val, rhs, lhs_res.res.val, rhs, t);
t); ret rslt(bcx, C_nil());
ret rslt(copy_res.bcx, C_nil());
} }
ast::expr_swap(dst, src) { ast::expr_swap(dst, src) {
let lhs_res = trans_lval(cx, dst); let lhs_res = trans_lval(cx, dst);
...@@ -5083,10 +5085,9 @@ fn trans_expr_out(cx: &@block_ctxt, e: &@ast::expr, output: out_method) -> ...@@ -5083,10 +5085,9 @@ fn trans_expr_out(cx: &@block_ctxt, e: &@ast::expr, output: out_method) ->
trans_eager_binop(rhs_res.bcx, op, lhs_val, t, rhs_res.val, t); trans_eager_binop(rhs_res.bcx, op, lhs_val, t, rhs_res.val, t);
// FIXME: calculate copy init-ness in typestate. // FIXME: calculate copy init-ness in typestate.
// This is always a temporary, so can always be safely moved // This is always a temporary, so can always be safely moved
let move_res = let bcx = move_val(v.bcx, DROP_EXISTING, lhs_res.res.val,
move_val(v.bcx, DROP_EXISTING, lhs_res.res.val,
lval_val(v.bcx, v.val), t); lval_val(v.bcx, v.val), t);
ret rslt(move_res.bcx, C_nil()); ret rslt(bcx, C_nil());
} }
ast::expr_bind(f, args) { ret trans_bind(cx, f, args, e.id); } ast::expr_bind(f, args) { ret trans_bind(cx, f, args, e.id); }
ast::expr_call(f, args) { ast::expr_call(f, args) {
...@@ -5425,9 +5426,9 @@ fn trans_ret(cx: &@block_ctxt, e: &option::t<@ast::expr>) -> result { ...@@ -5425,9 +5426,9 @@ fn trans_ret(cx: &@block_ctxt, e: &option::t<@ast::expr>) -> result {
_ { false } _ { false }
}; };
if is_local { if is_local {
bcx = move_val(bcx, INIT, cx.fcx.llretptr, lv, t).bcx; bcx = move_val(bcx, INIT, cx.fcx.llretptr, lv, t);
} else { } else {
bcx = move_val_if_temp(bcx, INIT, cx.fcx.llretptr, lv, t).bcx; bcx = move_val_if_temp(bcx, INIT, cx.fcx.llretptr, lv, t);
} }
} }
_ { _ {
...@@ -5476,11 +5477,11 @@ fn init_local(bcx: @block_ctxt, local: &@ast::local) -> result { ...@@ -5476,11 +5477,11 @@ fn init_local(bcx: @block_ctxt, local: &@ast::local) -> result {
// the value. // the value.
ty = node_id_type(bcx_ccx(bcx), init.expr.id); ty = node_id_type(bcx_ccx(bcx), init.expr.id);
let sub = trans_lval(bcx, init.expr); let sub = trans_lval(bcx, init.expr);
bcx = move_val_if_temp(sub.res.bcx, INIT, llptr, sub, ty).bcx; bcx = move_val_if_temp(sub.res.bcx, INIT, llptr, sub, ty);
} }
ast::init_move. { ast::init_move. {
let sub = trans_lval(bcx, init.expr); let sub = trans_lval(bcx, init.expr);
bcx = move_val(sub.res.bcx, INIT, llptr, sub, ty).bcx; bcx = move_val(sub.res.bcx, INIT, llptr, sub, ty);
} }
} }
} }
...@@ -5750,7 +5751,7 @@ fn accept_out_method(expr: &@ast::expr) -> bool { ...@@ -5750,7 +5751,7 @@ fn accept_out_method(expr: &@ast::expr) -> bool {
// The output method is to save the value at target, // The output method is to save the value at target,
// and we didn't pass it to the recursive trans_expr // and we didn't pass it to the recursive trans_expr
// call. // call.
bcx = move_val_if_temp(bcx, INIT, target, lv, r_ty).bcx; bcx = move_val_if_temp(bcx, INIT, target, lv, r_ty);
r = rslt(bcx, C_nil()); r = rslt(bcx, C_nil());
} }
return. { } return. { }
...@@ -6134,7 +6135,7 @@ fn trans_res_ctor(cx: @local_ctxt, sp: &span, dtor: &ast::_fn, ...@@ -6134,7 +6135,7 @@ fn trans_res_ctor(cx: @local_ctxt, sp: &span, dtor: &ast::_fn,
let dst = GEP_tup_like(bcx, tup_t, llretptr, [0, 1]); let dst = GEP_tup_like(bcx, tup_t, llretptr, [0, 1]);
bcx = dst.bcx; bcx = dst.bcx;
bcx = copy_val(bcx, INIT, dst.val, arg, arg_t).bcx; bcx = copy_val(bcx, INIT, dst.val, arg, arg_t);
let flag = GEP_tup_like(bcx, tup_t, llretptr, [0, 0]); let flag = GEP_tup_like(bcx, tup_t, llretptr, [0, 0]);
bcx = flag.bcx; bcx = flag.bcx;
bcx.build.Store(C_int(1), flag.val); bcx.build.Store(C_int(1), flag.val);
...@@ -6223,8 +6224,7 @@ fn trans_tag_variant(cx: @local_ctxt, tag_id: ast::node_id, ...@@ -6223,8 +6224,7 @@ fn trans_tag_variant(cx: @local_ctxt, tag_id: ast::node_id,
ty::type_has_dynamic_size(cx.ccx.tcx, arg_ty) { ty::type_has_dynamic_size(cx.ccx.tcx, arg_ty) {
llargval = llargptr; llargval = llargptr;
} else { llargval = bcx.build.Load(llargptr); } } else { llargval = bcx.build.Load(llargptr); }
rslt = copy_val(bcx, INIT, lldestptr, llargval, arg_ty); bcx = copy_val(bcx, INIT, lldestptr, llargval, arg_ty);
bcx = rslt.bcx;
i += 1u; i += 1u;
} }
bcx = trans_block_cleanups(bcx, find_scope_cx(bcx)); bcx = trans_block_cleanups(bcx, find_scope_cx(bcx));
......
...@@ -156,7 +156,7 @@ fn trans_obj(cx: @local_ctxt, sp: &span, ob: &ast::_obj, ...@@ -156,7 +156,7 @@ fn trans_obj(cx: @local_ctxt, sp: &span, ob: &ast::_obj,
let capture = let capture =
GEP_tup_like(bcx, typarams_ty, body_typarams.val, [0, i]); GEP_tup_like(bcx, typarams_ty, body_typarams.val, [0, i]);
bcx = capture.bcx; bcx = capture.bcx;
bcx = copy_val(bcx, INIT, capture.val, typaram, tydesc_ty).bcx; bcx = copy_val(bcx, INIT, capture.val, typaram, tydesc_ty);
i += 1; i += 1;
} }
...@@ -174,7 +174,7 @@ fn trans_obj(cx: @local_ctxt, sp: &span, ob: &ast::_obj, ...@@ -174,7 +174,7 @@ fn trans_obj(cx: @local_ctxt, sp: &span, ob: &ast::_obj,
let field = let field =
GEP_tup_like(bcx, fields_ty, body_fields.val, [0, i]); GEP_tup_like(bcx, fields_ty, body_fields.val, [0, i]);
bcx = field.bcx; bcx = field.bcx;
bcx = copy_val(bcx, INIT, field.val, arg, arg_tys[i].ty).bcx; bcx = copy_val(bcx, INIT, field.val, arg, arg_tys[i].ty);
i += 1; i += 1;
} }
none. { none. {
...@@ -345,7 +345,7 @@ fn trans_anon_obj(bcx: @block_ctxt, sp: &span, anon_obj: &ast::anon_obj, ...@@ -345,7 +345,7 @@ fn trans_anon_obj(bcx: @block_ctxt, sp: &span, anon_obj: &ast::anon_obj,
bcx = field.bcx; bcx = field.bcx;
bcx = bcx =
copy_val(bcx, INIT, field.val, additional_field_vals[i].val, copy_val(bcx, INIT, field.val, additional_field_vals[i].val,
additional_field_tys[i]).bcx; additional_field_tys[i]);
i += 1; i += 1;
} }
...@@ -363,9 +363,8 @@ fn trans_anon_obj(bcx: @block_ctxt, sp: &span, anon_obj: &ast::anon_obj, ...@@ -363,9 +363,8 @@ fn trans_anon_obj(bcx: @block_ctxt, sp: &span, anon_obj: &ast::anon_obj,
GEP_tup_like(bcx, body_ty, body, GEP_tup_like(bcx, body_ty, body,
[0, abi::obj_body_elt_inner_obj]); [0, abi::obj_body_elt_inner_obj]);
bcx = body_inner_obj.bcx; bcx = body_inner_obj.bcx;
bcx = bcx = copy_val(bcx, INIT, body_inner_obj.val, inner_obj_val.val,
copy_val(bcx, INIT, body_inner_obj.val, inner_obj_val.val, inner_obj_ty);
inner_obj_ty).bcx;
} }
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册