about summary refs log tree commit diff
path: root/src/comp
diff options
context:
space:
mode:
authorGraydon Hoare <graydon@mozilla.com>2010-10-19 17:24:15 -0700
committerGraydon Hoare <graydon@mozilla.com>2010-10-19 17:24:15 -0700
commit368943998de2dee5f47c8e05e2facb11dfd148b7 (patch)
tree07d0768680939bb4475ad6f039f6d826b68e435d /src/comp
parent71b1f1d117e2444e4588c67c9aa2772e74ad5678 (diff)
downloadrust-368943998de2dee5f47c8e05e2facb11dfd148b7.tar.gz
rust-368943998de2dee5f47c8e05e2facb11dfd148b7.zip
Translate lazy && and || operators in rustc.
Diffstat (limited to 'src/comp')
-rw-r--r--src/comp/middle/trans.rs65
1 files changed, 58 insertions, 7 deletions
diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs
index 2948f63a296..493dea4ce8e 100644
--- a/src/comp/middle/trans.rs
+++ b/src/comp/middle/trans.rs
@@ -137,6 +137,10 @@ fn T_f64() -> TypeRef {
     ret llvm.LLVMDoubleType();
 }
 
+fn T_bool() -> TypeRef {
+    ret T_i1();
+}
+
 fn T_int() -> TypeRef {
     // FIXME: switch on target type.
     ret T_i32();
@@ -228,7 +232,7 @@ fn T_taskptr() -> TypeRef {
 fn type_of(@trans_ctxt cx, @ast.ty t) -> TypeRef {
     alt (t.node) {
         case (ast.ty_nil) { ret T_nil(); }
-        case (ast.ty_bool) { ret T_i1(); }
+        case (ast.ty_bool) { ret T_bool(); }
         case (ast.ty_int) { ret T_int(); }
         case (ast.ty_uint) { ret T_int(); }
         case (ast.ty_machine(?tm)) {
@@ -291,9 +295,9 @@ fn C_nil() -> ValueRef {
 
 fn C_bool(bool b) -> ValueRef {
     if (b) {
-        ret C_integral(1, T_i1());
+        ret C_integral(1, T_bool());
     } else {
-        ret C_integral(0, T_i1());
+        ret C_integral(0, T_bool());
     }
 }
 
@@ -465,6 +469,54 @@ fn trans_unary(@block_ctxt cx, ast.unop op, &ast.expr e) -> result {
 fn trans_binary(@block_ctxt cx, ast.binop op,
                 &ast.expr a, &ast.expr b) -> result {
 
+    // First couple cases are lazy:
+
+    alt (op) {
+        case (ast.and) {
+            // Lazy-eval and
+            auto lhs_res = trans_expr(cx, a);
+
+            auto rhs_cx = new_empty_block_ctxt(cx.fcx);
+            auto rhs_res = trans_expr(rhs_cx, b);
+
+            auto next_cx = new_extension_block_ctxt(cx);
+            rhs_res.bcx.build.Br(next_cx.llbb);
+
+            lhs_res.bcx.build.CondBr(lhs_res.val,
+                                     rhs_cx.llbb,
+                                     next_cx.llbb);
+            auto phi = next_cx.build.Phi(T_bool(),
+                                         vec(lhs_res.val,
+                                             rhs_res.val),
+                                         vec(lhs_res.bcx.llbb,
+                                             rhs_res.bcx.llbb));
+            ret res(next_cx, phi);
+        }
+
+        case (ast.or) {
+            // Lazy-eval or
+            auto lhs_res = trans_expr(cx, a);
+
+            auto rhs_cx = new_empty_block_ctxt(cx.fcx);
+            auto rhs_res = trans_expr(rhs_cx, b);
+
+            auto next_cx = new_extension_block_ctxt(cx);
+            rhs_res.bcx.build.Br(next_cx.llbb);
+
+            lhs_res.bcx.build.CondBr(lhs_res.val,
+                                     next_cx.llbb,
+                                     rhs_cx.llbb);
+            auto phi = next_cx.build.Phi(T_bool(),
+                                         vec(lhs_res.val,
+                                             rhs_res.val),
+                                         vec(lhs_res.bcx.llbb,
+                                             rhs_res.bcx.llbb));
+            ret res(next_cx, phi);
+        }
+    }
+
+    // Remaining cases are eager:
+
     auto lhs = trans_expr(cx, a);
     auto sub = trans_expr(lhs.bcx, b);
 
@@ -774,10 +826,9 @@ fn new_top_block_ctxt(@fn_ctxt fcx) -> @block_ctxt {
 
 }
 
-// Use this when you are making a block_ctxt to replace the
-// current one, i.e. when chaining together sequences of stmts
-// or making sub-blocks you will branch back out of and wish to
-// "carry on" in the parent block's context.
+// Use this when you are making a block_ctxt that starts with a fresh
+// terminator and empty cleanups (no locals, no implicit return when
+// falling off the end).
 fn new_empty_block_ctxt(@fn_ctxt fcx) -> @block_ctxt {
     fn terminate_no_op(@fn_ctxt cx, builder build) {
     }