From e3626c940524c49d51d586b13375f64a52d44666 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Tue, 27 Sep 2011 20:21:44 +0200 Subject: [PATCH] Use DPS for assignment and local initialization Issue #667 --- src/comp/middle/trans.rs | 51 +++++++++++++-------------------- src/comp/middle/trans_uniq.rs | 2 +- src/comp/middle/trans_vec.rs | 54 +++++++++++++++++++++++------------ 3 files changed, 56 insertions(+), 51 deletions(-) diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 6c8d9d6bb0d..b9b0273d9cc 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -2208,7 +2208,7 @@ fn trans_unary(bcx: @block_ctxt, op: ast::unop, e: @ast::expr, let llety = T_ptr(type_of(ccx, e_sp, e_ty)); body = PointerCast(bcx, body, llety); } - bcx = trans_expr_save_in(bcx, e, body); + bcx = trans_expr_save_in(bcx, e, body, INIT); revoke_clean(bcx, box); ret store_in_dest(bcx, box, dest); } @@ -4033,7 +4033,7 @@ fn trans_tup(bcx: @block_ctxt, elts: [@ast::expr], id: ast::node_id, } save_in(pos) { (pos, none) } overwrite(pos, _) { - let scratch = alloca(bcx, val_ty(pos)); + let scratch = alloca(bcx, llvm::LLVMGetElementType(val_ty(pos))); (scratch, some(pos)) } }; @@ -4041,7 +4041,7 @@ fn trans_tup(bcx: @block_ctxt, elts: [@ast::expr], id: ast::node_id, for e in elts { let dst = GEP_tup_like_1(bcx, t, addr, [0, i]); let e_ty = ty::expr_ty(bcx_tcx(bcx), e); - bcx = trans_expr_save_in(dst.bcx, e, dst.val); + bcx = trans_expr_save_in(dst.bcx, e, dst.val, INIT); add_clean_temp_mem(bcx, dst.val, e_ty); temp_cleanups += [dst.val]; i += 1; @@ -4072,7 +4072,7 @@ fn trans_rec(bcx: @block_ctxt, fields: [ast::field], // The expressions that populate the fields might still use the old // record, so we build the new on in a scratch area overwrite(pos, _) { - let scratch = alloca(bcx, val_ty(pos)); + let scratch = alloca(bcx, llvm::LLVMGetElementType(val_ty(pos))); (scratch, some(pos)) } }; @@ -4096,7 +4096,7 @@ fn trans_rec(bcx: @block_ctxt, fields: [ast::field], fn test(n: str, f: ast::field) -> bool { str::eq(f.node.ident, n) } alt vec::find(bind test(tf.ident, _), fields) { some(f) { - bcx = trans_expr_save_in(bcx, f.node.expr, dst.val); + bcx = trans_expr_save_in(bcx, f.node.expr, dst.val, INIT); } none. { let base = GEP_tup_like_1(bcx, t, base_val, [0, i]); @@ -4198,20 +4198,17 @@ fn trans_expr(cx: @block_ctxt, e: @ast::expr) -> result { } } -// FIXME add support for INIT/DROP_EXISTING -fn trans_expr_save_in(bcx: @block_ctxt, e: @ast::expr, dest: ValueRef) - -> @block_ctxt { +fn trans_expr_save_in(bcx: @block_ctxt, e: @ast::expr, dest: ValueRef, + kind: copy_action) -> @block_ctxt { let tcx = bcx_tcx(bcx), t = ty::expr_ty(tcx, e); - if ty::type_is_bot(tcx, t) || ty::type_is_nil(tcx, t) { - ret trans_expr_dps(bcx, e, ignore); - } else if type_is_immediate(bcx_ccx(bcx), t) { - let cell = empty_dest_cell(); - bcx = trans_expr_dps(bcx, e, by_val(cell)); - Store(bcx, *cell, dest); - ret bcx; + let dst = if ty::type_is_bot(tcx, t) || ty::type_is_nil(tcx, t) { + ignore + } else if kind == INIT { + save_in(dest) } else { - ret trans_expr_dps(bcx, e, save_in(dest)); - } + overwrite(dest, t) + }; + ret trans_expr_dps(bcx, e, dst); } fn trans_expr_by_ref(bcx: @block_ctxt, e: @ast::expr) -> result { @@ -4338,13 +4335,9 @@ fn trans_expr_dps(bcx: @block_ctxt, e: @ast::expr, dest: dest) } ast::expr_assign(dst, src) { assert dest == ignore; - let lhs_res = trans_lval(bcx, dst); - assert (lhs_res.is_mem); - let rhs = trans_lval(lhs_res.bcx, src); - let t = ty::expr_ty(bcx_tcx(bcx), src); - // FIXME: calculate copy init-ness in typestate. - ret move_val_if_temp(rhs.bcx, DROP_EXISTING, lhs_res.val, - rhs, t); + let {bcx, val: lhs_addr, is_mem} = trans_lval(bcx, dst); + assert is_mem; + ret trans_expr_save_in(bcx, src, lhs_addr, DROP_EXISTING); } ast::expr_swap(dst, src) { assert dest == ignore; @@ -4650,7 +4643,7 @@ fn trans_ret(bcx: @block_ctxt, e: option::t<@ast::expr>) -> @block_ctxt { Store(cx, val, bcx.fcx.llretptr); bcx = cx; } else { - bcx = trans_expr_save_in(bcx, x, bcx.fcx.llretptr); + bcx = trans_expr_save_in(bcx, x, bcx.fcx.llretptr, INIT); } } _ {} @@ -4694,13 +4687,9 @@ fn init_local(bcx: @block_ctxt, local: @ast::local) -> @block_ctxt { some(init) { alt init.op { ast::init_assign. { - // Use the type of the RHS because if it's _|_, the LHS - // type might be something else, but we don't want to copy - // the value. - ty = node_id_type(bcx_ccx(bcx), init.expr.id); - let sub = trans_lval(bcx, init.expr); - bcx = move_val_if_temp(sub.bcx, INIT, llptr, sub, ty); + bcx = trans_expr_save_in(bcx, init.expr, llptr, INIT); } + // FIXME[DPS] do a save_in when expr isn't lval ast::init_move. { let sub = trans_lval(bcx, init.expr); bcx = move_val(sub.bcx, INIT, llptr, sub, ty); diff --git a/src/comp/middle/trans_uniq.rs b/src/comp/middle/trans_uniq.rs index 52865564c04..61fbcc87867 100644 --- a/src/comp/middle/trans_uniq.rs +++ b/src/comp/middle/trans_uniq.rs @@ -30,7 +30,7 @@ fn trans_uniq(bcx: @block_ctxt, contents: @ast::expr, check type_is_unique_box(bcx, uniq_ty); let {bcx, val: llptr} = alloc_uniq(bcx, uniq_ty); add_clean_free(bcx, llptr, true); - bcx = trans::trans_expr_save_in(bcx, contents, llptr); + bcx = trans::trans_expr_save_in(bcx, contents, llptr, INIT); revoke_clean(bcx, llptr); ret trans::store_in_dest(bcx, llptr, dest); } diff --git a/src/comp/middle/trans_vec.rs b/src/comp/middle/trans_vec.rs index cda37664ec1..86f23517679 100644 --- a/src/comp/middle/trans_vec.rs +++ b/src/comp/middle/trans_vec.rs @@ -20,7 +20,11 @@ fn get_alloc(bcx: @block_ctxt, vptrptr: ValueRef) -> ValueRef { } fn get_dataptr(bcx: @block_ctxt, vptrptr: ValueRef, unit_ty: TypeRef) -> ValueRef { - let ptr = GEPi(bcx, Load(bcx, vptrptr), [0, abi::vec_elt_elems as int]); + ret get_dataptr_simple(bcx, Load(bcx, vptrptr), unit_ty); +} +fn get_dataptr_simple(bcx: @block_ctxt, vptr: ValueRef, unit_ty: TypeRef) + -> ValueRef { + let ptr = GEPi(bcx, vptr, [0, abi::vec_elt_elems as int]); PointerCast(bcx, ptr, T_ptr(unit_ty)) } @@ -49,8 +53,7 @@ type alloc_result = llunitsz: ValueRef, llunitty: TypeRef}; -fn alloc(bcx: @block_ctxt, vec_ty: ty::t, elts: uint, dest: dest) - -> alloc_result { +fn alloc(bcx: @block_ctxt, vec_ty: ty::t, elts: uint) -> alloc_result { let unit_ty = ty::sequence_element_type(bcx_tcx(bcx), vec_ty); let llunitty = type_of_or_i8(bcx, unit_ty); let llvecty = T_vec(llunitty); @@ -61,11 +64,8 @@ fn alloc(bcx: @block_ctxt, vec_ty: ty::t, elts: uint, dest: dest) let {bcx: bcx, val: vptr} = alloc_raw(bcx, fill, alloc); let vptr = PointerCast(bcx, vptr, T_ptr(llvecty)); - let vptrptr = alt dest { trans::save_in(a) { a } }; - Store(bcx, vptr, vptrptr); -// add_clean_temp(bcx, vptrptr, vec_ty); ret {bcx: bcx, - val: vptrptr, + val: vptr, unit_ty: unit_ty, llunitsz: unit_sz, llunitty: llunitty}; @@ -110,16 +110,15 @@ fn trans_vec(bcx: @block_ctxt, args: [@ast::expr], id: ast::node_id, } let vec_ty = node_id_type(bcx_ccx(bcx), id); let {bcx: bcx, - val: vptrptr, + val: vptr, llunitsz: llunitsz, unit_ty: unit_ty, llunitty: llunitty} = - alloc(bcx, vec_ty, vec::len(args), dest); + alloc(bcx, vec_ty, vec::len(args)); - let vptr = Load(bcx, vptrptr); add_clean_free(bcx, vptr, true); // Store the individual elements. - let dataptr = get_dataptr(bcx, vptrptr, llunitty); + let dataptr = get_dataptr_simple(bcx, vptr, llunitty); let i = 0u, temp_cleanups = [vptr]; for e in args { let lv = trans_lval(bcx, e); @@ -133,17 +132,28 @@ fn trans_vec(bcx: @block_ctxt, args: [@ast::expr], id: ast::node_id, i += 1u; } for clean in temp_cleanups { revoke_clean(bcx, clean); } + let vptrptr = alt dest { + trans::save_in(a) { a } + trans::overwrite(a, t) { bcx = trans::drop_ty(bcx, a, t); a } + }; + Store(bcx, vptr, vptrptr); ret bcx; } + fn trans_str(bcx: @block_ctxt, s: str, dest: dest) -> @block_ctxt { let veclen = std::str::byte_len(s) + 1u; // +1 for \0 - let {bcx: bcx, val: sptrptr, _} = - alloc(bcx, ty::mk_str(bcx_tcx(bcx)), veclen, dest); + let {bcx: bcx, val: sptr, _} = + alloc(bcx, ty::mk_str(bcx_tcx(bcx)), veclen); let llcstr = C_cstr(bcx_ccx(bcx), s); let bcx = - call_memmove(bcx, get_dataptr(bcx, sptrptr, T_i8()), llcstr, + call_memmove(bcx, get_dataptr_simple(bcx, sptr, T_i8()), llcstr, C_uint(veclen)).bcx; + let sptrptr = alt dest { + trans::save_in(a) { a } + trans::overwrite(a, t) { bcx = trans::drop_ty(bcx, a, t); a } + }; + Store(bcx, sptr, sptrptr); ret bcx; } @@ -237,11 +247,9 @@ fn trans_add(bcx: @block_ctxt, vec_ty: ty::t, lhsptr: ValueRef, let new_fill = Add(bcx, lhs_fill, rhs_fill); let {bcx: bcx, val: new_vec_ptr} = alloc_raw(bcx, new_fill, new_fill); new_vec_ptr = PointerCast(bcx, new_vec_ptr, T_ptr(T_vec(llunitty))); - let new_vec_ptr_ptr = alt dest { trans::save_in(a) { a } }; - Store(bcx, new_vec_ptr, new_vec_ptr_ptr); - let write_ptr_ptr = - do_spill_noroot(bcx, get_dataptr(bcx, new_vec_ptr_ptr, llunitty)); + let write_ptr_ptr = do_spill_noroot + (bcx, get_dataptr_simple(bcx, new_vec_ptr, llunitty)); let copy_fn = bind fn (bcx: @block_ctxt, addr: ValueRef, _ty: ty::t, write_ptr_ptr: ValueRef, unit_ty: ty::t, llunitsz: ValueRef) @@ -259,7 +267,15 @@ fn trans_add(bcx: @block_ctxt, vec_ty: ty::t, lhsptr: ValueRef, }(_, _, _, write_ptr_ptr, unit_ty, llunitsz); let bcx = iter_vec_raw(bcx, lhsptr, vec_ty, lhs_fill, copy_fn); - ret iter_vec_raw(bcx, rhsptr, vec_ty, rhs_fill, copy_fn); + bcx = iter_vec_raw(bcx, rhsptr, vec_ty, rhs_fill, copy_fn); + alt dest { + trans::save_in(a) { Store(bcx, new_vec_ptr, a); } + trans::overwrite(a, t) { + bcx = trans::drop_ty(bcx, a, t); + Store(bcx, new_vec_ptr, a); + } + } + ret bcx; } type val_and_ty_fn = fn(@block_ctxt, ValueRef, ty::t) -> result;