parent
92d63ffa65
commit
94db38a530
@ -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
|
||||
|
@ -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
|
||||
|
@ -13,7 +13,8 @@
|
||||
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 @@
|
||||
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)
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user