about summary refs log tree commit diff
path: root/src/comp/middle
diff options
context:
space:
mode:
authorMarijn Haverbeke <marijnh@gmail.com>2011-09-27 10:50:18 +0200
committerMarijn Haverbeke <marijnh@gmail.com>2011-09-27 17:30:54 +0200
commit8282f7fe805087f26ed60a6a5cba0abe50637d39 (patch)
tree02b9cb47a4b1d5a1d1552854e2d05e8c19c1154a /src/comp/middle
parent806e74fbf50febd4509a61dac9abcb7c9c4efd86 (diff)
downloadrust-8282f7fe805087f26ed60a6a5cba0abe50637d39.tar.gz
rust-8282f7fe805087f26ed60a6a5cba0abe50637d39.zip
Move expr_binary into trans_expr_dps
Issue #667
Diffstat (limited to 'src/comp/middle')
-rw-r--r--src/comp/middle/trans.rs196
-rw-r--r--src/comp/middle/trans_alt.rs5
-rw-r--r--src/comp/middle/trans_vec.rs37
3 files changed, 115 insertions, 123 deletions
diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs
index 25887cc1fe8..8650fa514e8 100644
--- a/src/comp/middle/trans.rs
+++ b/src/comp/middle/trans.rs
@@ -2158,10 +2158,7 @@ fn trans_lit(cx: @block_ctxt, lit: ast::lit, dest: dest) -> @block_ctxt {
     alt lit.node {
       ast::lit_str(s) { ret tvec::trans_str(cx, s, dest); }
       _ {
-        let cell = alt dest { by_val(c) { c }
-                             _ { bcx_ccx(cx).sess.span_note(lit.span, "here"); fail; }};
-        *cell = trans_crate_lit(bcx_ccx(cx), lit);
-        ret cx;
+        ret store_in_dest(cx, trans_crate_lit(bcx_ccx(cx), lit), dest);
       }
     }
 }
@@ -2253,8 +2250,9 @@ fn trans_compare(cx: @block_ctxt, op: ast::binop, lhs: ValueRef,
 // Important to get types for both lhs and rhs, because one might be _|_
 // and the other not.
 fn trans_eager_binop(cx: @block_ctxt, op: ast::binop, lhs: ValueRef,
-                     lhs_t: ty::t, rhs: ValueRef, rhs_t: ty::t) -> result {
-
+                     lhs_t: ty::t, rhs: ValueRef, rhs_t: ty::t, dest: dest)
+    -> @block_ctxt {
+    if dest == ignore { ret cx; }
     let is_float = false;
     let intype = lhs_t;
     if ty::type_is_bot(bcx_tcx(cx), intype) { intype = rhs_t; }
@@ -2263,45 +2261,47 @@ fn trans_eager_binop(cx: @block_ctxt, op: ast::binop, lhs: ValueRef,
       ty::ty_float. { is_float = true; }
       _ { is_float = false; }
     }
-    alt op {
+    if op == ast::add && ty::type_is_sequence(bcx_tcx(cx), intype) {
+        ret tvec::trans_add(cx, intype, lhs, rhs, dest);
+    }
+    let val = alt op {
       ast::add. {
-        if ty::type_is_sequence(bcx_tcx(cx), intype) {
-            ret tvec::trans_add(cx, intype, lhs, rhs);
-        }
-        if is_float {
-            ret rslt(cx, FAdd(cx, lhs, rhs));
-        } else { ret rslt(cx, Add(cx, lhs, rhs)); }
+        if is_float { FAdd(cx, lhs, rhs) }
+        else { Add(cx, lhs, rhs) }
       }
       ast::sub. {
-        if is_float {
-            ret rslt(cx, FSub(cx, lhs, rhs));
-        } else { ret rslt(cx, Sub(cx, lhs, rhs)); }
+        if is_float { FSub(cx, lhs, rhs) }
+        else { Sub(cx, lhs, rhs) }
       }
       ast::mul. {
-        if is_float {
-            ret rslt(cx, FMul(cx, lhs, rhs));
-        } else { ret rslt(cx, Mul(cx, lhs, rhs)); }
+        if is_float { FMul(cx, lhs, rhs) }
+        else { Mul(cx, lhs, rhs) }
       }
       ast::div. {
-        if is_float { ret rslt(cx, FDiv(cx, lhs, rhs)); }
-        if ty::type_is_signed(bcx_tcx(cx), intype) {
-            ret rslt(cx, SDiv(cx, lhs, rhs));
-        } else { ret rslt(cx, UDiv(cx, lhs, rhs)); }
+        if is_float { FDiv(cx, lhs, rhs) }
+        else if ty::type_is_signed(bcx_tcx(cx), intype) {
+            SDiv(cx, lhs, rhs)
+        } else { UDiv(cx, lhs, rhs) }
       }
       ast::rem. {
-        if is_float { ret rslt(cx, FRem(cx, lhs, rhs)); }
-        if ty::type_is_signed(bcx_tcx(cx), intype) {
-            ret rslt(cx, SRem(cx, lhs, rhs));
-        } else { ret rslt(cx, URem(cx, lhs, rhs)); }
+        if is_float { FRem(cx, lhs, rhs) }
+        else if ty::type_is_signed(bcx_tcx(cx), intype) {
+            SRem(cx, lhs, rhs)
+        } else { URem(cx, lhs, rhs) }
+      }
+      ast::bitor. { Or(cx, lhs, rhs) }
+      ast::bitand. { And(cx, lhs, rhs) }
+      ast::bitxor. { Xor(cx, lhs, rhs) }
+      ast::lsl. { Shl(cx, lhs, rhs) }
+      ast::lsr. { LShr(cx, lhs, rhs) }
+      ast::asr. { AShr(cx, lhs, rhs) }
+      _ {
+        let cmpr = trans_compare(cx, op, lhs, lhs_t, rhs, rhs_t);
+        cx = cmpr.bcx;
+        cmpr.val
       }
-      ast::bitor. { ret rslt(cx, Or(cx, lhs, rhs)); }
-      ast::bitand. { ret rslt(cx, And(cx, lhs, rhs)); }
-      ast::bitxor. { ret rslt(cx, Xor(cx, lhs, rhs)); }
-      ast::lsl. { ret rslt(cx, Shl(cx, lhs, rhs)); }
-      ast::lsr. { ret rslt(cx, LShr(cx, lhs, rhs)); }
-      ast::asr. { ret rslt(cx, AShr(cx, lhs, rhs)); }
-      _ { ret trans_compare(cx, op, lhs, lhs_t, rhs, rhs_t); }
-    }
+    };
+    ret store_in_dest(cx, val, dest);
 }
 
 fn trans_assign_op(bcx: @block_ctxt, op: ast::binop, dst: @ast::expr,
@@ -2334,11 +2334,8 @@ fn trans_assign_op(bcx: @block_ctxt, op: ast::binop, dst: @ast::expr,
         }
     }
     let lhs_val = load_if_immediate(rhs_res.bcx, lhs_res.val, t);
-    let v = trans_eager_binop(rhs_res.bcx, op, lhs_val, t, rhs_res.val, t);
-    // FIXME: calculate copy init-ness in typestate.
-    // This is always a temporary, so can always be safely moved
-    ret move_val(v.bcx, DROP_EXISTING, lhs_res.val,
-                 lval_val(v.bcx, v.val), t);
+    ret trans_eager_binop(rhs_res.bcx, op, lhs_val, t, rhs_res.val, t,
+                          overwrite(lhs_res.val, t));
 }
 
 fn autoderef(cx: @block_ctxt, v: ValueRef, t: ty::t) -> result_t {
@@ -2390,84 +2387,55 @@ fn autoderef(cx: @block_ctxt, v: ValueRef, t: ty::t) -> result_t {
     ret {bcx: cx, val: v1, ty: t1};
 }
 
-fn trans_binary(cx: @block_ctxt, op: ast::binop, a: @ast::expr, b: @ast::expr)
-   -> result {
+fn trans_lazy_binop(bcx: @block_ctxt, op: ast::binop, a: @ast::expr,
+                    b: @ast::expr, dest: dest) -> @block_ctxt {
+    let is_and = alt op { ast::and. { true } ast::or. { false } };
+    let lhs_res = trans_expr(bcx, a);
+    if lhs_res.bcx.unreachable { ret lhs_res.bcx; }
+    let rhs_cx = new_scope_block_ctxt(lhs_res.bcx, "rhs");
+    let rhs_res = trans_expr(rhs_cx, b);
+
+    let lhs_past_cx = new_scope_block_ctxt(lhs_res.bcx, "lhs");
+    // The following line ensures that any cleanups for rhs
+    // are done within the block for rhs. This is necessary
+    // because and/or are lazy. So the rhs may never execute,
+    // and the cleanups can't be pushed into later code.
+    let rhs_bcx = trans_block_cleanups(rhs_res.bcx, rhs_cx);
+    if is_and {
+        CondBr(lhs_res.bcx, lhs_res.val, rhs_cx.llbb, lhs_past_cx.llbb);
+    } else {
+        CondBr(lhs_res.bcx, lhs_res.val, lhs_past_cx.llbb, rhs_cx.llbb);
+    }
 
+    let join_cx = new_sub_block_ctxt(bcx, "join");
+    Br(lhs_past_cx, join_cx.llbb);
+    if rhs_bcx.unreachable {
+        ret store_in_dest(join_cx, C_bool(!is_and), dest);
+    }
+    Br(rhs_bcx, join_cx.llbb);
+    let phi = Phi(join_cx, T_bool(), [C_bool(!is_and), rhs_res.val],
+                  [lhs_past_cx.llbb, rhs_bcx.llbb]);
+    ret store_in_dest(join_cx, phi, dest);
+}
+
+fn trans_binary(cx: @block_ctxt, op: ast::binop, a: @ast::expr, b: @ast::expr,
+                dest: dest) -> @block_ctxt {
     // First couple cases are lazy:
     alt op {
-      ast::and. {
-        // Lazy-eval and
-        let lhs_res = trans_expr(cx, a);
-        let rhs_cx = new_scope_block_ctxt(lhs_res.bcx, "rhs");
-        let rhs_res = trans_expr(rhs_cx, b);
-
-        let lhs_false_cx = new_scope_block_ctxt(lhs_res.bcx, "lhs false");
-        let lhs_false_res = rslt(lhs_false_cx, C_bool(false));
-
-        // The following line ensures that any cleanups for rhs
-        // are done within the block for rhs. This is necessary
-        // because and/or are lazy. So the rhs may never execute,
-        // and the cleanups can't be pushed into later code.
-        let rhs_bcx = trans_block_cleanups(rhs_res.bcx, rhs_cx);
-        CondBr(lhs_res.bcx, lhs_res.val, rhs_cx.llbb, lhs_false_cx.llbb);
-        ret join_results(cx, T_bool(),
-                         [lhs_false_res, {bcx: rhs_bcx, val: rhs_res.val}]);
-      }
-      ast::or. {
-        // Lazy-eval or
-        let lhs_res = trans_expr(cx, a);
-        let rhs_cx = new_scope_block_ctxt(lhs_res.bcx, "rhs");
-        let rhs_res = trans_expr(rhs_cx, b);
-        let lhs_true_cx = new_scope_block_ctxt(lhs_res.bcx, "lhs true");
-        let lhs_true_res = rslt(lhs_true_cx, C_bool(true));
-
-        // see the and case for an explanation
-        let rhs_bcx = trans_block_cleanups(rhs_res.bcx, rhs_cx);
-        CondBr(lhs_res.bcx, lhs_res.val, lhs_true_cx.llbb, rhs_cx.llbb);
-        ret join_results(cx, T_bool(),
-                         [lhs_true_res, {bcx: rhs_bcx, val: rhs_res.val}]);
+      ast::and. | ast::or. {
+        ret trans_lazy_binop(cx, op, a, b, dest);
       }
       _ {
         // Remaining cases are eager:
         let lhs = trans_expr(cx, a);
         let rhs = trans_expr(lhs.bcx, b);
-
         ret trans_eager_binop(rhs.bcx, op, lhs.val,
                               ty::expr_ty(bcx_tcx(cx), a), rhs.val,
-                              ty::expr_ty(bcx_tcx(cx), b));
+                              ty::expr_ty(bcx_tcx(cx), b), dest);
       }
     }
 }
 
-fn join_results(parent_cx: @block_ctxt, t: TypeRef, ins: [result]) -> result {
-    let live: [result] = [];
-    let vals: [ValueRef] = [];
-    let bbs: [BasicBlockRef] = [];
-    for r: result in ins {
-        if !r.bcx.unreachable {
-            live += [r];
-            vals += [r.val];
-            bbs += [r.bcx.llbb];
-        }
-    }
-    alt std::vec::len::<result>(live) {
-      0u {
-        // No incoming edges are live, so we're in dead-code-land.
-        // Arbitrarily pick the first dead edge, since the caller
-        // is just going to propagate it outward.
-        assert (std::vec::len::<result>(ins) >= 1u);
-        ret ins[0];
-      }
-      _ {/* fall through */ }
-    }
-    // We have >1 incoming edges. Make a join block and br+phi them into it.
-
-    let join_cx = new_sub_block_ctxt(parent_cx, "join");
-    for r: result in live { Br(r.bcx, join_cx.llbb); }
-    let phi = Phi(join_cx, t, vals, bbs);
-    ret rslt(join_cx, phi);
-}
-
 // FIXME remove once all uses have been converted to join_returns
 fn join_branches(parent_cx: @block_ctxt, ins: [result]) -> @block_ctxt {
     let out = new_sub_block_ctxt(parent_cx, "join");
@@ -2483,6 +2451,7 @@ tag dest {
     by_val(@mutable ValueRef);
     by_ref(@mutable ValueRef);
     save_in(ValueRef);
+    overwrite(ValueRef, ty::t);
     ignore;
 }
 
@@ -2529,6 +2498,20 @@ fn join_returns(parent_cx: @block_ctxt, in_cxs: [@block_ctxt],
     ret out;
 }
 
+// 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. {}
+      by_val(cell) { *cell = val; }
+      save_in(addr) { Store(bcx, val, addr); }
+      overwrite(addr, tp) {
+        bcx = drop_ty(bcx, addr, tp);
+        Store(bcx, val, addr);
+      }
+    }
+    ret bcx;
+}
+
 // 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,
@@ -4135,7 +4118,6 @@ fn trans_rec(bcx: @block_ctxt, fields: [ast::field],
 fn trans_expr(cx: @block_ctxt, e: @ast::expr) -> result {
     // Fixme Fill in cx.sp
     alt e.node {
-      ast::expr_binary(op, x, y) { ret trans_binary(cx, op, x, y); }
       ast::expr_fn(f) {
         let ccx = bcx_ccx(cx);
         let fty = node_id_type(ccx, e.id);
@@ -4267,6 +4249,7 @@ fn trans_expr_dps(bcx: @block_ctxt, e: @ast::expr, dest: dest)
       ast::expr_tup(args) { ret trans_tup(bcx, args, e.id, 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_break. {
         assert dest == ignore;
@@ -4399,6 +4382,9 @@ fn trans_expr_dps(bcx: @block_ctxt, e: @ast::expr, dest: dest)
             *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;
diff --git a/src/comp/middle/trans_alt.rs b/src/comp/middle/trans_alt.rs
index c9375115d3c..87adda1f18f 100644
--- a/src/comp/middle/trans_alt.rs
+++ b/src/comp/middle/trans_alt.rs
@@ -36,9 +36,10 @@ fn trans_opt(bcx: @block_ctxt, o: opt) -> result {
       lit(l) {
         alt l.node {
           ast::lit_str(s) {
-            let {bcx, val: dst} =
-                trans::alloc_ty(bcx, ty::mk_str(bcx_tcx(bcx)));
+            let strty = ty::mk_str(bcx_tcx(bcx));
+            let {bcx, val: dst} = trans::alloc_ty(bcx, strty);
             bcx = trans_vec::trans_str(bcx, s, trans::save_in(dst));
+            add_clean_temp(bcx, dst, strty);
             ret rslt(bcx, dst);
           }
           _ {
diff --git a/src/comp/middle/trans_vec.rs b/src/comp/middle/trans_vec.rs
index 0536f0ab12d..aa5f9fc7ea2 100644
--- a/src/comp/middle/trans_vec.rs
+++ b/src/comp/middle/trans_vec.rs
@@ -100,9 +100,14 @@ fn make_drop_glue(bcx: @block_ctxt, vptrptr: ValueRef, vec_ty: ty::t) ->
     ret next_cx;
 }
 
-// FIXME handle dest == ignore
 fn trans_vec(bcx: @block_ctxt, args: [@ast::expr], id: ast::node_id,
              dest: dest) -> @block_ctxt {
+    if dest == trans::ignore {
+        for arg in args {
+            bcx = trans::trans_expr_dps(bcx, arg, trans::ignore);
+        }
+        ret bcx;
+    }
     let vec_ty = node_id_type(bcx_ccx(bcx), id);
     let {bcx: bcx,
          val: vptrptr,
@@ -113,17 +118,20 @@ fn trans_vec(bcx: @block_ctxt, args: [@ast::expr], id: ast::node_id,
 
     // Store the individual elements.
     let dataptr = get_dataptr(bcx, vptrptr, llunitty);
-    let i = 0u;
+    add_clean_temp_mem(bcx, vptrptr, vec_ty);
+    let i = 0u, temp_cleanups = [vptrptr];
     for e in args {
         let lv = trans_lval(bcx, e);
         bcx = lv.bcx;
-        let lleltptr =
-            if ty::type_has_dynamic_size(bcx_tcx(bcx), unit_ty) {
-                InBoundsGEP(bcx, dataptr, [Mul(bcx, C_uint(i), llunitsz)])
-            } else { InBoundsGEP(bcx, dataptr, [C_uint(i)]) };
+        let lleltptr = if ty::type_has_dynamic_size(bcx_tcx(bcx), unit_ty) {
+            InBoundsGEP(bcx, dataptr, [Mul(bcx, C_uint(i), llunitsz)])
+        } else { InBoundsGEP(bcx, dataptr, [C_uint(i)]) };
         bcx = move_val_if_temp(bcx, INIT, lleltptr, lv, unit_ty);
+        add_clean_temp_mem(bcx, lleltptr, unit_ty);
+        temp_cleanups += [lleltptr];
         i += 1u;
     }
+    for clean in temp_cleanups { revoke_clean(bcx, clean); }
     ret bcx;
 }
 fn trans_str(bcx: @block_ctxt, s: str, dest: dest) -> @block_ctxt {
@@ -213,12 +221,11 @@ fn trans_append_literal(bcx: @block_ctxt, vptrptr: ValueRef, vec_ty: ty::t,
 }
 
 fn trans_add(bcx: @block_ctxt, vec_ty: ty::t, lhsptr: ValueRef,
-             rhsptr: ValueRef) -> result {
-    let strings =
-        alt ty::struct(bcx_tcx(bcx), vec_ty) {
-          ty::ty_str. { true }
-          ty::ty_vec(_) { false }
-        };
+             rhsptr: ValueRef, dest: dest) -> @block_ctxt {
+    let strings = alt ty::struct(bcx_tcx(bcx), vec_ty) {
+      ty::ty_str. { true }
+      ty::ty_vec(_) { false }
+    };
     let unit_ty = ty::sequence_element_type(bcx_tcx(bcx), vec_ty);
     let llunitty = type_of_or_i8(bcx, unit_ty);
     let {bcx: bcx, val: llunitsz} = size_of(bcx, unit_ty);
@@ -229,9 +236,8 @@ 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 {bcx: bcx, val: new_vec_ptr_ptr} = alloc_ty(bcx, vec_ty);
+    let new_vec_ptr_ptr = alt dest { trans::save_in(a) { a } };
     Store(bcx, new_vec_ptr, new_vec_ptr_ptr);
-    add_clean_temp(bcx, new_vec_ptr_ptr, vec_ty);
 
     let write_ptr_ptr =
         do_spill_noroot(bcx, get_dataptr(bcx, new_vec_ptr_ptr, llunitty));
@@ -252,8 +258,7 @@ 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);
-    let bcx = iter_vec_raw(bcx, rhsptr, vec_ty, rhs_fill, copy_fn);
-    ret rslt(bcx, new_vec_ptr_ptr);
+    ret iter_vec_raw(bcx, rhsptr, vec_ty, rhs_fill, copy_fn);
 }
 
 type val_and_ty_fn = fn(@block_ctxt, ValueRef, ty::t) -> result;