diff options
| author | Graydon Hoare <graydon@mozilla.com> | 2010-10-19 17:24:15 -0700 |
|---|---|---|
| committer | Graydon Hoare <graydon@mozilla.com> | 2010-10-19 17:24:15 -0700 |
| commit | 368943998de2dee5f47c8e05e2facb11dfd148b7 (patch) | |
| tree | 07d0768680939bb4475ad6f039f6d826b68e435d /src | |
| parent | 71b1f1d117e2444e4588c67c9aa2772e74ad5678 (diff) | |
| download | rust-368943998de2dee5f47c8e05e2facb11dfd148b7.tar.gz rust-368943998de2dee5f47c8e05e2facb11dfd148b7.zip | |
Translate lazy && and || operators in rustc.
Diffstat (limited to 'src')
| -rw-r--r-- | src/comp/middle/trans.rs | 65 |
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) { } |
