diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index e4f186d13df..9831acc4f1d 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -2243,10 +2243,7 @@ fn trans_expr_fn(bcx: @block_ctxt, f: ast::_fn, sp: span, trans_closure(sub_cx, sp, f, llfn, none, [], id, {|_fcx|}); } }; - let addr = alt dest { - save_in(a) { a } - overwrite(a, ty) { bcx = drop_ty(bcx, a, ty); a } - }; + let {bcx, val: addr} = get_dest_addr(bcx, dest); fill_fn_pair(bcx, addr, llfn, env); ret bcx; } @@ -2537,6 +2534,13 @@ fn store_in_dest(bcx: @block_ctxt, val: ValueRef, dest: dest) -> @block_ctxt { ret bcx; } +fn get_dest_addr(bcx: @block_ctxt, dest: dest) -> result { + alt dest { + save_in(a) { rslt(bcx, a) } + overwrite(a, t) { rslt(drop_ty(bcx, a, t), a) } + } +} + // Wrapper through which legacy non-DPS code can use DPS functions fn dps_to_result(bcx: @block_ctxt, work: block(@block_ctxt, dest) -> @block_ctxt, @@ -3675,12 +3679,8 @@ fn trans_bind_1(cx: @block_ctxt, outgoing_fty: ty::t, let lv = lval_maybe_callee_to_lval(f_res, pair_ty); bcx = lv.bcx; // FIXME[DPS] factor this out - let addr = alt dest { - save_in(a) { a } - overwrite(a, ty) { bcx = drop_ty(bcx, a, ty); a } - }; - bcx = memmove_ty(bcx, addr, lv.val, pair_ty); - ret bcx; + let {bcx, val: addr} = get_dest_addr(bcx, dest); + ret memmove_ty(bcx, addr, lv.val, pair_ty); } let closure = alt f_res.env { null_env. { none } @@ -3717,10 +3717,7 @@ fn trans_bind_1(cx: @block_ctxt, outgoing_fty: ty::t, closure.ptrty, ty_param_count, target_res); // Fill the function pair - let addr = alt dest { - save_in(a) { a } - overwrite(a, ty) { bcx = drop_ty(bcx, a, ty); a } - }; + let {bcx, val: addr} = get_dest_addr(bcx, dest); fill_fn_pair(bcx, addr, llthunk.val, closure.ptr); ret bcx; } @@ -4186,25 +4183,18 @@ fn trans_rec(bcx: @block_ctxt, fields: [ast::field], ret bcx; } +// FIXME[DPS] remove this entirely, rename trans_expr_dps to trans_expr fn trans_expr(cx: @block_ctxt, e: @ast::expr) -> result { - // Fixme Fill in cx.sp - alt e.node { - ast::expr_anon_obj(anon_obj) { - ret trans_anon_obj(cx, e.span, anon_obj, e.id); - } - ast::expr_call(_, _) | ast::expr_field(_, _) | ast::expr_index(_, _) | - ast::expr_path(_) | ast::expr_unary(ast::deref., _) { + if expr_is_lval(bcx_tcx(cx), e) { let t = ty::expr_ty(bcx_tcx(cx), e); let sub = trans_lval(cx, e); let v = sub.val; if sub.is_mem { v = load_if_immediate(sub.bcx, v, t); } ret rslt(sub.bcx, v); - } - // Fall through to DPS-style - _ { + } else { + // Fall through to DPS-style ret dps_to_result(cx, {|bcx, dest| trans_expr_dps(bcx, e, dest)}, ty::expr_ty(bcx_tcx(cx), e)); - } } } @@ -4234,6 +4224,9 @@ fn trans_expr_by_ref(bcx: @block_ctxt, e: @ast::expr) -> result { // - exprs returning non-immediates get save_in (or by_ref when lval) fn trans_expr_dps(bcx: @block_ctxt, e: @ast::expr, dest: dest) -> @block_ctxt { + let tcx = bcx_tcx(bcx); + if expr_is_lval(tcx, e) { ret lval_to_dps(bcx, e, dest); } + alt e.node { ast::expr_if(cond, thn, els) | ast::expr_if_check(cond, thn, els) { ret trans_if(bcx, cond, thn, els, dest); @@ -4261,22 +4254,23 @@ fn trans_expr_dps(bcx: @block_ctxt, e: @ast::expr, dest: 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); - } + assert op != ast::deref; // lvals are handled above ret trans_unary(bcx, op, x, e.id, dest); } ast::expr_fn(f) { ret trans_expr_fn(bcx, f, e.span, e.id, dest); } ast::expr_bind(f, args) { ret trans_bind(bcx, f, args, e.id, dest); } ast::expr_copy(a) { - if !expr_is_lval(bcx_tcx(bcx), a) { - ret trans_expr_dps(bcx, a, dest); - } else { - // FIXME[DPS] give this a name that makes more sense - ret trans_expr_backwards_compat(bcx, e, dest); - } + if !expr_is_lval(tcx, a) { ret trans_expr_dps(bcx, a, dest); } + else { ret lval_to_dps(bcx, a, dest); } } ast::expr_cast(val, _) { ret trans_cast(bcx, val, e.id, dest); } + ast::expr_anon_obj(anon_obj) { + ret trans_anon_obj(bcx, e.span, anon_obj, e.id, dest); + } + // FIXME[DPS] untangle non-lval calls and fields from trans_lval + ast::expr_call(_, _) | ast::expr_field(_, _) { + ret lval_to_dps(bcx, e, dest); + } // These return nothing ast::expr_break. { @@ -4366,11 +4360,11 @@ fn trans_expr_dps(bcx: @block_ctxt, e: @ast::expr, dest: dest) let {bcx, val: addr, is_mem} = trans_lval(bcx, dst); assert is_mem; // FIXME: calculate copy init-ness in typestate. - if expr_is_lval(bcx_tcx(bcx), src) { + if expr_is_lval(tcx, src) { ret trans_expr_save_in(bcx, src, addr, DROP_EXISTING); } else { let srclv = trans_lval(bcx, src); - let t = ty::expr_ty(bcx_tcx(bcx), src); + let t = ty::expr_ty(tcx, src); ret move_val(srclv.bcx, DROP_EXISTING, addr, srclv, t); } } @@ -4379,7 +4373,7 @@ fn trans_expr_dps(bcx: @block_ctxt, e: @ast::expr, dest: dest) let lhs_res = trans_lval(bcx, dst); assert (lhs_res.is_mem); let rhs_res = trans_lval(lhs_res.bcx, src); - let t = ty::expr_ty(bcx_tcx(bcx), src); + let t = ty::expr_ty(tcx, src); let {bcx: bcx, val: tmp_alloc} = alloc_ty(rhs_res.bcx, t); // Swap through a temporary. bcx = move_val(bcx, INIT, tmp_alloc, lhs_res, t); @@ -4390,15 +4384,10 @@ fn trans_expr_dps(bcx: @block_ctxt, e: @ast::expr, dest: dest) assert dest == ignore; ret trans_assign_op(bcx, op, dst, src); } - - ast::expr_mac(_) { ret bcx_ccx(bcx).sess.bug("unexpanded macro"); } - // Convert back from result to DPS - _ { ret trans_expr_backwards_compat(bcx, e, dest); } } } -fn trans_expr_backwards_compat(bcx: @block_ctxt, e: @ast::expr, dest: dest) - -> @block_ctxt { +fn lval_to_dps(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); diff --git a/src/comp/middle/trans_objects.rs b/src/comp/middle/trans_objects.rs index 602bd6b5af3..0e4b5292829 100644 --- a/src/comp/middle/trans_objects.rs +++ b/src/comp/middle/trans_objects.rs @@ -213,7 +213,13 @@ fn trans_obj(cx: @local_ctxt, sp: span, ob: ast::_obj, ctor_id: ast::node_id, // instead "inlining" the construction of the object and returning the object // itself. fn trans_anon_obj(bcx: @block_ctxt, sp: span, anon_obj: ast::anon_obj, - id: ast::node_id) -> result { + id: ast::node_id, dest: trans::dest) -> @block_ctxt { + if dest == trans::ignore { + alt anon_obj.inner_obj { + some(e) { ret trans::trans_expr_dps(bcx, e, trans::ignore); } + none. { ret bcx; } + } + } let ccx = bcx_ccx(bcx); @@ -283,43 +289,26 @@ fn trans_anon_obj(bcx: @block_ctxt, sp: span, anon_obj: ast::anon_obj, } } - // Allocate the object that we're going to return. - let pair = alloca(bcx, ccx.rust_object_type); - - // Take care of cleanups. - let t = node_id_type(ccx, id); - add_clean_temp(bcx, pair, t); - - // Grab onto the first and second elements of the pair. - let pair_vtbl = GEP(bcx, pair, [C_int(0), C_int(abi::obj_field_vtbl)]); - let pair_box = GEP(bcx, pair, [C_int(0), C_int(abi::obj_field_box)]); - vtbl = PointerCast(bcx, vtbl, T_ptr(T_empty_struct())); - Store(bcx, vtbl, pair_vtbl); // Next we have to take care of the other half of the pair we're // returning: a boxed (reference-counted) tuple containing a tydesc, // typarams, fields, and a pointer to our inner_obj. let llbox_ty: TypeRef = T_ptr(T_empty_struct()); - if vec::len(additional_fields) == 0u && - anon_obj.inner_obj == none { - - // If the object we're translating has no fields and no inner_obj, - // there's not much to do. - Store(bcx, C_null(llbox_ty), pair_box); - - } else { - + let box = C_null(llbox_ty); + if vec::len(additional_fields) > 0u || anon_obj.inner_obj != none { // Synthesize a type for the object body and hand it off to // trans_malloc_boxed, which allocates a box, including space for a // refcount. let body_ty: ty::t = create_object_body_type(ccx.tcx, additional_field_tys, [], some(inner_obj_ty)); - let box = trans_malloc_boxed(bcx, body_ty); - bcx = box.bcx; - let body = box.body; + let box_r = trans_malloc_boxed(bcx, body_ty); + box = box_r.box; + bcx = box_r.bcx; + add_clean_free(bcx, box, false); + let body = box_r.body; // Put together a tydesc for the body, so that the object can later be // freed by calling through its tydesc. @@ -386,14 +375,15 @@ fn trans_anon_obj(bcx: @block_ctxt, sp: span, anon_obj: ast::anon_obj, inner_obj_ty); } } - - // Store box ptr in outer pair. - let p = PointerCast(bcx, box.box, llbox_ty); - Store(bcx, p, pair_box); + revoke_clean(bcx, box); + box = PointerCast(bcx, box, llbox_ty); } - - // return the object we built. - ret rslt(bcx, pair); + let {bcx, val: pair} = trans::get_dest_addr(bcx, dest); + let pair_vtbl = GEP(bcx, pair, [C_int(0), C_int(abi::obj_field_vtbl)]); + Store(bcx, vtbl, pair_vtbl); + let pair_box = GEP(bcx, pair, [C_int(0), C_int(abi::obj_field_box)]); + Store(bcx, box, pair_box); + ret bcx; } // Used only inside create_vtbl and create_backwarding_vtbl to distinguish diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs index 3e76ce2f93e..ec9821d6d26 100644 --- a/src/comp/middle/ty.rs +++ b/src/comp/middle/ty.rs @@ -1299,14 +1299,14 @@ fn vars_in_type(cx: ctxt, ty: t) -> [int] { } fn type_autoderef(cx: ctxt, t: ty::t) -> ty::t { - let t1: ty::t = t; + let t1 = t; while true { alt struct(cx, t1) { - ty::ty_box(mt) { t1 = mt.ty; } - ty::ty_res(_, inner, tps) { + ty_box(mt) | ty_uniq(mt) { t1 = mt.ty; } + ty_res(_, inner, tps) { t1 = substitute_type_params(cx, tps, inner); } - ty::ty_tag(did, tps) { + ty_tag(did, tps) { let variants = tag_variants(cx, did); if vec::len(variants) != 1u || vec::len(variants[0].args) != 1u { break;