Move last remaining expression types out of trans_expr

Issue #667
This commit is contained in:
Marijn Haverbeke 2011-09-29 11:18:40 +02:00
parent f089f533e8
commit d243ea57f5
3 changed files with 58 additions and 79 deletions

View File

@ -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|}); trans_closure(sub_cx, sp, f, llfn, none, [], id, {|_fcx|});
} }
}; };
let addr = alt dest { let {bcx, val: addr} = get_dest_addr(bcx, dest);
save_in(a) { a }
overwrite(a, ty) { bcx = drop_ty(bcx, a, ty); a }
};
fill_fn_pair(bcx, addr, llfn, env); fill_fn_pair(bcx, addr, llfn, env);
ret bcx; ret bcx;
} }
@ -2537,6 +2534,13 @@ fn store_in_dest(bcx: @block_ctxt, val: ValueRef, dest: dest) -> @block_ctxt {
ret bcx; 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 // Wrapper through which legacy non-DPS code can use DPS functions
fn dps_to_result(bcx: @block_ctxt, fn dps_to_result(bcx: @block_ctxt,
work: block(@block_ctxt, dest) -> @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); let lv = lval_maybe_callee_to_lval(f_res, pair_ty);
bcx = lv.bcx; bcx = lv.bcx;
// FIXME[DPS] factor this out // FIXME[DPS] factor this out
let addr = alt dest { let {bcx, val: addr} = get_dest_addr(bcx, dest);
save_in(a) { a } ret memmove_ty(bcx, addr, lv.val, pair_ty);
overwrite(a, ty) { bcx = drop_ty(bcx, a, ty); a }
};
bcx = memmove_ty(bcx, addr, lv.val, pair_ty);
ret bcx;
} }
let closure = alt f_res.env { let closure = alt f_res.env {
null_env. { none } 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); closure.ptrty, ty_param_count, target_res);
// Fill the function pair // Fill the function pair
let addr = alt dest { let {bcx, val: addr} = get_dest_addr(bcx, dest);
save_in(a) { a }
overwrite(a, ty) { bcx = drop_ty(bcx, a, ty); a }
};
fill_fn_pair(bcx, addr, llthunk.val, closure.ptr); fill_fn_pair(bcx, addr, llthunk.val, closure.ptr);
ret bcx; ret bcx;
} }
@ -4186,25 +4183,18 @@ fn trans_rec(bcx: @block_ctxt, fields: [ast::field],
ret bcx; ret bcx;
} }
// FIXME[DPS] remove this entirely, rename trans_expr_dps to trans_expr
fn trans_expr(cx: @block_ctxt, e: @ast::expr) -> result { fn trans_expr(cx: @block_ctxt, e: @ast::expr) -> result {
// Fixme Fill in cx.sp if expr_is_lval(bcx_tcx(cx), e) {
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., _) {
let t = ty::expr_ty(bcx_tcx(cx), e); let t = ty::expr_ty(bcx_tcx(cx), e);
let sub = trans_lval(cx, e); let sub = trans_lval(cx, e);
let v = sub.val; let v = sub.val;
if sub.is_mem { v = load_if_immediate(sub.bcx, v, t); } if sub.is_mem { v = load_if_immediate(sub.bcx, v, t); }
ret rslt(sub.bcx, v); ret rslt(sub.bcx, v);
} } else {
// Fall through to DPS-style // Fall through to DPS-style
_ {
ret dps_to_result(cx, {|bcx, dest| trans_expr_dps(bcx, e, dest)}, ret dps_to_result(cx, {|bcx, dest| trans_expr_dps(bcx, e, dest)},
ty::expr_ty(bcx_tcx(cx), e)); 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) // - exprs returning non-immediates get save_in (or by_ref when lval)
fn trans_expr_dps(bcx: @block_ctxt, e: @ast::expr, dest: dest) fn trans_expr_dps(bcx: @block_ctxt, e: @ast::expr, dest: dest)
-> @block_ctxt { -> @block_ctxt {
let tcx = bcx_tcx(bcx);
if expr_is_lval(tcx, e) { ret lval_to_dps(bcx, e, dest); }
alt e.node { alt e.node {
ast::expr_if(cond, thn, els) | ast::expr_if_check(cond, thn, els) { ast::expr_if(cond, thn, els) | ast::expr_if_check(cond, thn, els) {
ret trans_if(bcx, cond, thn, els, dest); 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_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_binary(op, x, y) { ret trans_binary(bcx, op, x, y, dest); }
ast::expr_unary(op, x) { ast::expr_unary(op, x) {
if op == ast::deref { assert op != ast::deref; // lvals are handled above
ret trans_expr_backwards_compat(bcx, e, dest);
}
ret trans_unary(bcx, op, x, e.id, dest); 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_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_bind(f, args) { ret trans_bind(bcx, f, args, e.id, dest); }
ast::expr_copy(a) { ast::expr_copy(a) {
if !expr_is_lval(bcx_tcx(bcx), a) { if !expr_is_lval(tcx, a) { ret trans_expr_dps(bcx, a, dest); }
ret trans_expr_dps(bcx, a, dest); else { ret lval_to_dps(bcx, a, dest); }
} else {
// FIXME[DPS] give this a name that makes more sense
ret trans_expr_backwards_compat(bcx, e, dest);
}
} }
ast::expr_cast(val, _) { ret trans_cast(bcx, val, e.id, 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 // These return nothing
ast::expr_break. { 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); let {bcx, val: addr, is_mem} = trans_lval(bcx, dst);
assert is_mem; assert is_mem;
// FIXME: calculate copy init-ness in typestate. // 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); ret trans_expr_save_in(bcx, src, addr, DROP_EXISTING);
} else { } else {
let srclv = trans_lval(bcx, src); 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); 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); let lhs_res = trans_lval(bcx, dst);
assert (lhs_res.is_mem); assert (lhs_res.is_mem);
let rhs_res = trans_lval(lhs_res.bcx, src); 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); let {bcx: bcx, val: tmp_alloc} = alloc_ty(rhs_res.bcx, t);
// Swap through a temporary. // Swap through a temporary.
bcx = move_val(bcx, INIT, tmp_alloc, lhs_res, t); 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; assert dest == ignore;
ret trans_assign_op(bcx, op, dst, src); 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) fn lval_to_dps(bcx: @block_ctxt, e: @ast::expr, dest: dest) -> @block_ctxt {
-> @block_ctxt {
let lv = trans_lval(bcx, e); let lv = trans_lval(bcx, e);
let {bcx, val, is_mem} = lv; let {bcx, val, is_mem} = lv;
let ty = ty::expr_ty(bcx_tcx(bcx), e); let ty = ty::expr_ty(bcx_tcx(bcx), e);

View File

@ -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 // instead "inlining" the construction of the object and returning the object
// itself. // itself.
fn trans_anon_obj(bcx: @block_ctxt, sp: span, anon_obj: ast::anon_obj, 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); 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())); 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 // Next we have to take care of the other half of the pair we're
// returning: a boxed (reference-counted) tuple containing a tydesc, // returning: a boxed (reference-counted) tuple containing a tydesc,
// typarams, fields, and a pointer to our inner_obj. // typarams, fields, and a pointer to our inner_obj.
let llbox_ty: TypeRef = T_ptr(T_empty_struct()); let llbox_ty: TypeRef = T_ptr(T_empty_struct());
if vec::len(additional_fields) == 0u && let box = C_null(llbox_ty);
anon_obj.inner_obj == none { 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 {
// Synthesize a type for the object body and hand it off to // Synthesize a type for the object body and hand it off to
// trans_malloc_boxed, which allocates a box, including space for a // trans_malloc_boxed, which allocates a box, including space for a
// refcount. // refcount.
let body_ty: ty::t = let body_ty: ty::t =
create_object_body_type(ccx.tcx, additional_field_tys, [], create_object_body_type(ccx.tcx, additional_field_tys, [],
some(inner_obj_ty)); some(inner_obj_ty));
let box = trans_malloc_boxed(bcx, body_ty); let box_r = trans_malloc_boxed(bcx, body_ty);
bcx = box.bcx; box = box_r.box;
let body = box.body; 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 // Put together a tydesc for the body, so that the object can later be
// freed by calling through its tydesc. // 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); inner_obj_ty);
} }
} }
revoke_clean(bcx, box);
// Store box ptr in outer pair. box = PointerCast(bcx, box, llbox_ty);
let p = PointerCast(bcx, box.box, llbox_ty);
Store(bcx, p, pair_box);
} }
let {bcx, val: pair} = trans::get_dest_addr(bcx, dest);
// return the object we built. let pair_vtbl = GEP(bcx, pair, [C_int(0), C_int(abi::obj_field_vtbl)]);
ret rslt(bcx, pair); 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 // Used only inside create_vtbl and create_backwarding_vtbl to distinguish

View File

@ -1299,14 +1299,14 @@ fn vars_in_type(cx: ctxt, ty: t) -> [int] {
} }
fn type_autoderef(cx: ctxt, t: ty::t) -> ty::t { fn type_autoderef(cx: ctxt, t: ty::t) -> ty::t {
let t1: ty::t = t; let t1 = t;
while true { while true {
alt struct(cx, t1) { alt struct(cx, t1) {
ty::ty_box(mt) { t1 = mt.ty; } ty_box(mt) | ty_uniq(mt) { t1 = mt.ty; }
ty::ty_res(_, inner, tps) { ty_res(_, inner, tps) {
t1 = substitute_type_params(cx, tps, inner); t1 = substitute_type_params(cx, tps, inner);
} }
ty::ty_tag(did, tps) { ty_tag(did, tps) {
let variants = tag_variants(cx, did); let variants = tag_variants(cx, did);
if vec::len(variants) != 1u || vec::len(variants[0].args) != 1u { if vec::len(variants) != 1u || vec::len(variants[0].args) != 1u {
break; break;