diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index d9b635276f8..8902e76e7df 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -2178,50 +2178,45 @@ fn node_type(cx: @crate_ctxt, sp: span, id: ast::node_id) -> TypeRef { type_of(cx, sp, ty) } -fn trans_unary(cx: @block_ctxt, op: ast::unop, e: @ast::expr, - id: ast::node_id) -> result { - let e_ty = ty::expr_ty(bcx_tcx(cx), e); +fn trans_unary(bcx: @block_ctxt, op: ast::unop, e: @ast::expr, + id: ast::node_id, dest: dest) -> @block_ctxt { + if dest == ignore { ret trans_expr_dps(bcx, e, ignore); } + let e_ty = ty::expr_ty(bcx_tcx(bcx), e); alt op { ast::not. { - let sub = trans_expr(cx, e); - ret rslt(sub.bcx, Not(sub.bcx, sub.val)); + let {bcx, val} = trans_expr(bcx, e); + ret store_in_dest(bcx, Not(bcx, val), dest); } ast::neg. { - let sub = trans_expr(cx, e); - if ty::struct(bcx_tcx(cx), e_ty) == ty::ty_float { - ret rslt(sub.bcx, FNeg(sub.bcx, sub.val)); - } else { ret rslt(sub.bcx, Neg(sub.bcx, sub.val)); } + let {bcx, val} = trans_expr(bcx, e); + let neg = if ty::struct(bcx_tcx(bcx), e_ty) == ty::ty_float { + FNeg(bcx, val) + } else { Neg(bcx, val) }; + ret store_in_dest(bcx, neg, dest); } ast::box(_) { - let lv = trans_lval(cx, e); - let box_ty = node_id_type(bcx_ccx(lv.bcx), id); - let sub = trans_malloc_boxed(lv.bcx, e_ty); - let body = sub.body; - add_clean_temp(cx, sub.box, box_ty); - + let {bcx, box, body} = trans_malloc_boxed(bcx, e_ty); + add_clean_free(bcx, box, false); // Cast the body type to the type of the value. This is needed to // make tags work, since tags have a different LLVM type depending // on whether they're boxed or not. - let sub_ccx = bcx_ccx(sub.bcx); - if check type_has_static_size(sub_ccx, e_ty) { + let ccx = bcx_ccx(bcx); + if check type_has_static_size(ccx, e_ty) { let e_sp = e.span; - let llety = T_ptr(type_of(sub_ccx, e_sp, e_ty)); - body = PointerCast(sub.bcx, body, llety); - } else { - } // FIXME: can remove the else{} once we have - // a new snapshot - - - let bcx = move_val_if_temp(sub.bcx, INIT, body, lv, e_ty); - ret rslt(bcx, sub.box); + let llety = T_ptr(type_of(ccx, e_sp, e_ty)); + body = PointerCast(bcx, body, llety); + } + bcx = trans_expr_save_in(bcx, e, body); + revoke_clean(bcx, box); + ret store_in_dest(bcx, box, dest); } ast::uniq(_) { - ret trans_uniq::trans_uniq(cx, e, id); + ret trans_uniq::trans_uniq(bcx, e, id, dest); } ast::deref. { - bcx_ccx(cx).sess.bug("deref expressions should have been \ - translated using trans_lval(), not \ - trans_unary()"); + bcx_ccx(bcx).sess.bug("deref expressions should have been \ + translated using trans_lval(), not \ + trans_unary()"); } } } @@ -2498,7 +2493,7 @@ fn join_returns(parent_cx: @block_ctxt, in_cxs: [@block_ctxt], ret out; } -// Used to put an immediate value in a dest +// Used to put an immediate value in a dest. fn store_in_dest(bcx: @block_ctxt, val: ValueRef, dest: dest) -> @block_ctxt { alt dest { ignore. {} @@ -4092,23 +4087,23 @@ fn trans_rec(bcx: @block_ctxt, fields: [ast::field], let ty_fields = alt ty::struct(bcx_tcx(bcx), t) { ty::ty_rec(f) { f } }; let temp_cleanups = [], i = 0; for tf in ty_fields { - let gep = GEP_tup_like_1(bcx, t, addr, [0, i]); - bcx = gep.bcx; + let dst = GEP_tup_like_1(bcx, t, addr, [0, i]); + bcx = dst.bcx; // FIXME make this {|f| str::eq(f.node.ident, tf.ident)} again when // bug #913 is fixed 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, gep.val); + bcx = trans_expr_save_in(bcx, f.node.expr, dst.val); } none. { let base = GEP_tup_like_1(bcx, t, base_val, [0, i]); let val = load_if_immediate(base.bcx, base.val, tf.mt.ty); - bcx = copy_val(base.bcx, INIT, gep.val, val, tf.mt.ty); + bcx = copy_val(base.bcx, INIT, dst.val, val, tf.mt.ty); } } - add_clean_temp_mem(bcx, addr, tf.mt.ty); - temp_cleanups += [addr]; + add_clean_temp_mem(bcx, dst.val, tf.mt.ty); + temp_cleanups += [dst.val]; i += 1; } // Now revoke the cleanups as we pass responsibility for the data @@ -4193,9 +4188,6 @@ fn trans_expr(cx: @block_ctxt, e: @ast::expr) -> result { if sub.is_mem { v = load_if_immediate(sub.bcx, v, t); } ret rslt(sub.bcx, v); } - ast::expr_unary(op, x) { - ret trans_unary(cx, op, x, e.id); - } // Fall through to DPS-style _ { ret dps_to_result(cx, {|bcx, dest| trans_expr_dps(bcx, e, dest)}, @@ -4259,6 +4251,12 @@ fn trans_expr_dps(bcx: @block_ctxt, e: @ast::expr, dest: dest) ast::expr_lit(lit) { ret trans_lit(bcx, *lit, dest); } ast::expr_vec(args, _) { ret tvec::trans_vec(bcx, args, e.id, dest); } ast::expr_binary(op, x, y) { ret trans_binary(bcx, op, x, y, dest); } + ast::expr_unary(op, x) { + if op == ast::deref { + ret trans_expr_backwards_compat(bcx, e, dest); + } + ret trans_unary(bcx, op, x, e.id, dest); + } ast::expr_break. { assert dest == ignore; @@ -4365,42 +4363,45 @@ fn trans_expr_dps(bcx: @block_ctxt, e: @ast::expr, dest: dest) ast::expr_mac(_) { ret bcx_ccx(bcx).sess.bug("unexpanded macro"); } // Convert back from result to DPS - _ { - let lv = trans_lval(bcx, e); - let {bcx, val, is_mem} = lv; - let ty = ty::expr_ty(bcx_tcx(bcx), e); - alt dest { - by_val(cell) { - if !is_mem { - revoke_clean(bcx, val); - *cell = val; - } else if ty::type_is_unique(bcx_tcx(bcx), ty) { - // Do a song and a dance to work around the fact that take_ty - // for unique boxes overwrites the pointer. - let oldval = Load(bcx, val); - bcx = take_ty(bcx, val, ty); - *cell = Load(bcx, val); - Store(bcx, oldval, val); - } else { - bcx = take_ty(bcx, val, ty); - *cell = Load(bcx, val); - } - } - by_ref(cell) { - assert is_mem; - *cell = val; - } - save_in(loc) { bcx = move_val_if_temp(bcx, INIT, loc, lv, ty); } - overwrite(loc, _) { - bcx = move_val_if_temp(bcx, DROP_EXISTING, loc, lv, ty); - } - ignore. {} - } - ret bcx; - } + _ { ret trans_expr_backwards_compat(bcx, e, dest); } } } +fn trans_expr_backwards_compat(bcx: @block_ctxt, e: @ast::expr, dest: dest) + -> @block_ctxt { + let lv = trans_lval(bcx, e); + let {bcx, val, is_mem} = lv; + let ty = ty::expr_ty(bcx_tcx(bcx), e); + alt dest { + by_val(cell) { + if !is_mem { + revoke_clean(bcx, val); + *cell = val; + } else if ty::type_is_unique(bcx_tcx(bcx), ty) { + // Do a song and a dance to work around the fact that take_ty + // for unique boxes overwrites the pointer. + let oldval = Load(bcx, val); + bcx = take_ty(bcx, val, ty); + *cell = Load(bcx, val); + Store(bcx, oldval, val); + } else { + bcx = take_ty(bcx, val, ty); + *cell = Load(bcx, val); + } + } + by_ref(cell) { + assert is_mem; + *cell = val; + } + save_in(loc) { bcx = move_val_if_temp(bcx, INIT, loc, lv, ty); } + overwrite(loc, _) { + bcx = move_val_if_temp(bcx, DROP_EXISTING, loc, lv, ty); + } + ignore. {} + } + ret bcx; +} + // We pass structural values around the compiler "by pointer" and // non-structural values (scalars, boxes, pointers) "by value". We call the // latter group "immediates" and, in some circumstances when we know we have a diff --git a/src/comp/middle/trans_common.rs b/src/comp/middle/trans_common.rs index d46bcf08ac3..eb6b6c9f311 100644 --- a/src/comp/middle/trans_common.rs +++ b/src/comp/middle/trans_common.rs @@ -288,6 +288,13 @@ fn add_clean_temp_mem(cx: @block_ctxt, val: ValueRef, ty: ty::t) { scope_cx.cleanups += [clean_temp(val, bind drop_ty(_, val, ty))]; scope_cx.lpad_dirty = true; } +fn add_clean_free(cx: @block_ctxt, ptr: ValueRef, shared: bool) { + let scope_cx = find_scope_cx(cx); + let free_fn = if shared { bind trans::trans_shared_free(_, ptr) } + else { bind trans::trans_non_gc_free(_, ptr) }; + scope_cx.cleanups += [clean_temp(ptr, free_fn)]; + scope_cx.lpad_dirty = true; +} // Note that this only works for temporaries. We should, at some point, move // to a system where we can also cancel the cleanup on local variables, but diff --git a/src/comp/middle/trans_uniq.rs b/src/comp/middle/trans_uniq.rs index 68e9117de01..52865564c04 100644 --- a/src/comp/middle/trans_uniq.rs +++ b/src/comp/middle/trans_uniq.rs @@ -13,7 +13,8 @@ import trans::{ trans_shared_free, drop_ty, new_sub_block_ctxt, - load_if_immediate + load_if_immediate, + dest }; export trans_uniq, make_free_glue, type_is_unique_box, copy_val, @@ -23,31 +24,15 @@ pure fn type_is_unique_box(bcx: @block_ctxt, ty: ty::t) -> bool { ty::type_is_unique_box(bcx_tcx(bcx), ty) } -fn trans_uniq(cx: @block_ctxt, contents: @ast::expr, - node_id: ast::node_id) -> result { - let bcx = cx; - - let lv = trans_lval(bcx, contents); - bcx = lv.bcx; - - let uniq_ty = node_id_type(bcx_ccx(cx), node_id); - - if ty::type_is_bot(bcx_tcx(bcx), uniq_ty) { - // FIXME: Seems to work, obviously not 'right'. Story of my life. - // Probably works because the builder turns lv.val into undef - ret rslt(bcx, lv.val); - } - +fn trans_uniq(bcx: @block_ctxt, contents: @ast::expr, + node_id: ast::node_id, dest: dest) -> @block_ctxt { + let uniq_ty = node_id_type(bcx_ccx(bcx), node_id); check type_is_unique_box(bcx, uniq_ty); - let content_ty = content_ty(bcx, uniq_ty); let {bcx, val: llptr} = alloc_uniq(bcx, uniq_ty); - - add_clean_temp(bcx, llptr, uniq_ty); - - bcx = move_val_if_temp(bcx, INIT, llptr, lv, - content_ty); - - ret rslt(bcx, llptr); + add_clean_free(bcx, llptr, true); + bcx = trans::trans_expr_save_in(bcx, contents, llptr); + revoke_clean(bcx, llptr); + ret trans::store_in_dest(bcx, llptr, dest); } fn alloc_uniq(cx: @block_ctxt, uniq_ty: ty::t) diff --git a/src/comp/middle/trans_vec.rs b/src/comp/middle/trans_vec.rs index aa5f9fc7ea2..cda37664ec1 100644 --- a/src/comp/middle/trans_vec.rs +++ b/src/comp/middle/trans_vec.rs @@ -116,10 +116,11 @@ fn trans_vec(bcx: @block_ctxt, args: [@ast::expr], id: ast::node_id, llunitty: llunitty} = alloc(bcx, vec_ty, vec::len(args), dest); + let vptr = Load(bcx, vptrptr); + add_clean_free(bcx, vptr, true); // Store the individual elements. let dataptr = get_dataptr(bcx, vptrptr, llunitty); - add_clean_temp_mem(bcx, vptrptr, vec_ty); - let i = 0u, temp_cleanups = [vptrptr]; + let i = 0u, temp_cleanups = [vptr]; for e in args { let lv = trans_lval(bcx, e); bcx = lv.bcx;