about summary refs log tree commit diff
diff options
context:
space:
mode:
authorBrian Anderson <andersrb@gmail.com>2011-02-13 00:49:04 -0500
committerGraydon Hoare <graydon@mozilla.com>2011-02-14 08:31:52 -0800
commit0ebfb8227c190609e80af3fb52b9813c4b282cc0 (patch)
treec5cbe15ad6f58065d2d344d1fde83728c050a2d8
parentbd56dd9f2aca1967c92d3cc613dcc199c878026c (diff)
downloadrust-0ebfb8227c190609e80af3fb52b9813c4b282cc0.tar.gz
rust-0ebfb8227c190609e80af3fb52b9813c4b282cc0.zip
Add support for unsigned binops. Closes #57
-rw-r--r--src/Makefile2
-rw-r--r--src/comp/middle/trans.rs70
-rw-r--r--src/test/run-pass/arith-unsigned.rs24
3 files changed, 80 insertions, 16 deletions
diff --git a/src/Makefile b/src/Makefile
index d55a63c2797..3457864cca7 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -408,6 +408,7 @@ TASK_XFAILS := test/run-pass/task-comm-8.rs \
 TEST_XFAILS_BOOT :=  $(TASK_XFAILS) \
                     $(NOMINAL_TAG_XFAILS) \
                     $(CONST_TAG_XFAILS) \
+                    test/run-pass/arith-unsigned.rs \
                     test/run-pass/child-outlives-parent.rs \
                     test/run-pass/clone-with-exterior.rs \
                     test/run-pass/constrained-type.rs \
@@ -450,6 +451,7 @@ TEST_XFAILS_RUSTC := $(filter-out \
                         arith-0.rs \
                         arith-1.rs \
                         arith-2.rs \
+                        arith-unsigned.rs \
                         auto-instantiate.rs \
                         autoderef-full-lval.rs \
                         bind-exterior.rs \
diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs
index bedfad97980..c1a4aa6f62a 100644
--- a/src/comp/middle/trans.rs
+++ b/src/comp/middle/trans.rs
@@ -1840,33 +1840,67 @@ fn trans_unary(@block_ctxt cx, ast.unop op,
 
 // FIXME: implement proper structural comparison.
 
-fn trans_compare(@block_ctxt cx, ast.binop op,
+fn trans_compare(@block_ctxt cx, ast.binop op, @ty.t intype,
                  ValueRef lhs, ValueRef rhs) -> ValueRef {
     auto cmp = lib.llvm.LLVMIntEQ;
     alt (op) {
         case (ast.eq) { cmp = lib.llvm.LLVMIntEQ; }
         case (ast.ne) { cmp = lib.llvm.LLVMIntNE; }
 
-        // FIXME (issue #57): switch by signedness.
-        case (ast.lt) { cmp = lib.llvm.LLVMIntSLT; }
-        case (ast.le) { cmp = lib.llvm.LLVMIntSLE; }
-        case (ast.ge) { cmp = lib.llvm.LLVMIntSGE; }
-        case (ast.gt) { cmp = lib.llvm.LLVMIntSGT; }
+        case (ast.lt) {
+            if (ty.type_is_signed(intype)) {
+                cmp = lib.llvm.LLVMIntSLT;
+            } else {
+                cmp = lib.llvm.LLVMIntULT;
+            }
+        }
+        case (ast.le) {
+            if (ty.type_is_signed(intype)) {
+                cmp = lib.llvm.LLVMIntSLE;
+            } else {
+                cmp = lib.llvm.LLVMIntULE;
+            }
+        }
+        case (ast.gt) {
+            if (ty.type_is_signed(intype)) {
+                cmp = lib.llvm.LLVMIntSGT;
+            } else {
+                cmp = lib.llvm.LLVMIntUGT;
+            }
+        }
+        case (ast.ge) {
+            if (ty.type_is_signed(intype)) {
+                cmp = lib.llvm.LLVMIntSGE;
+            } else {
+                cmp = lib.llvm.LLVMIntUGE;
+            }
+        }
     }
     ret cx.build.ICmp(cmp, lhs, rhs);
 }
 
-fn trans_eager_binop(@block_ctxt cx, ast.binop op,
+fn trans_eager_binop(@block_ctxt cx, ast.binop op, @ty.t intype,
                      ValueRef lhs, ValueRef rhs) -> ValueRef {
 
     alt (op) {
         case (ast.add) { ret cx.build.Add(lhs, rhs); }
         case (ast.sub) { ret cx.build.Sub(lhs, rhs); }
 
-        // FIXME (issue #57): switch by signedness.
         case (ast.mul) { ret cx.build.Mul(lhs, rhs); }
-        case (ast.div) { ret cx.build.SDiv(lhs, rhs); }
-        case (ast.rem) { ret cx.build.SRem(lhs, rhs); }
+        case (ast.div) {
+            if (ty.type_is_signed(intype)) {
+                ret cx.build.SDiv(lhs, rhs);
+            } else {
+                ret cx.build.UDiv(lhs, rhs);
+            }
+        }
+        case (ast.rem) {
+            if (ty.type_is_signed(intype)) {
+                ret cx.build.SRem(lhs, rhs);
+            } else {
+                ret cx.build.URem(lhs, rhs);
+            }
+        }
 
         case (ast.bitor) { ret cx.build.Or(lhs, rhs); }
         case (ast.bitand) { ret cx.build.And(lhs, rhs); }
@@ -1875,7 +1909,7 @@ fn trans_eager_binop(@block_ctxt cx, ast.binop op,
         case (ast.lsr) { ret cx.build.LShr(lhs, rhs); }
         case (ast.asr) { ret cx.build.AShr(lhs, rhs); }
         case (_) {
-            ret trans_compare(cx, op, lhs, rhs);
+            ret trans_compare(cx, op, intype, lhs, rhs);
         }
     }
     fail;
@@ -1950,10 +1984,12 @@ fn trans_binary(@block_ctxt cx, ast.binop op,
         case (_) {
             // Remaining cases are eager:
             auto lhs = trans_expr(cx, a);
-            lhs = autoderef(lhs.bcx, lhs.val, ty.expr_ty(a));
+            auto lhty = ty.expr_ty(a);
+            lhs = autoderef(lhs.bcx, lhs.val, lhty);
             auto rhs = trans_expr(lhs.bcx, b);
-            rhs = autoderef(rhs.bcx, rhs.val, ty.expr_ty(b));
-            ret res(rhs.bcx, trans_eager_binop(rhs.bcx, op,
+            auto rhty = ty.expr_ty(b);
+            rhs = autoderef(rhs.bcx, rhs.val, rhty);
+            ret res(rhs.bcx, trans_eager_binop(rhs.bcx, op, lhty,
                                                lhs.val, rhs.val));
         }
     }
@@ -2142,7 +2178,8 @@ fn trans_pat_match(@block_ctxt cx, @ast.pat pat, ValueRef llval,
 
         case (ast.pat_lit(?lt, ?ann)) {
             auto lllit = trans_lit(cx.fcx.ccx, *lt, ann);
-            auto lleq = trans_compare(cx, ast.eq, llval, lllit);
+            auto lltype = ty.ann_to_type(ann);
+            auto lleq = trans_compare(cx, ast.eq, lltype, llval, lllit);
 
             auto matched_cx = new_sub_block_ctxt(cx, "matched_cx");
             cx.build.CondBr(lleq, matched_cx.llbb, next_cx.llbb);
@@ -3035,7 +3072,8 @@ fn trans_expr(@block_ctxt cx, @ast.expr e) -> result {
             auto lhs_val = load_scalar_or_boxed(lhs_res.res.bcx,
                                                 lhs_res.res.val, t);
             auto rhs_res = trans_expr(lhs_res.res.bcx, src);
-            auto v = trans_eager_binop(rhs_res.bcx, op, lhs_val, rhs_res.val);
+            auto v = trans_eager_binop(rhs_res.bcx, op, t,
+                                       lhs_val, rhs_res.val);
             // FIXME: calculate copy init-ness in typestate.
             ret copy_ty(rhs_res.bcx, DROP_EXISTING,
                         lhs_res.res.val, v, t);
diff --git a/src/test/run-pass/arith-unsigned.rs b/src/test/run-pass/arith-unsigned.rs
new file mode 100644
index 00000000000..3fac37142f8
--- /dev/null
+++ b/src/test/run-pass/arith-unsigned.rs
@@ -0,0 +1,24 @@
+// Unsigned integer operations
+
+fn main() {
+  check (0u8 < 255u8);
+  check (0u8 <= 255u8);
+  check (255u8 > 0u8);
+  check (255u8 >= 0u8);
+  check (250u8 / 10u8 == 25u8);
+  check (255u8 % 10u8 == 5u8);
+  check (0u16 < 60000u16);
+  check (0u16 <= 60000u16);
+  check (60000u16 > 0u16);
+  check (60000u16 >= 0u16);
+  check (60000u16 / 10u16 == 6000u16);
+  check (60005u16 % 10u16 == 5u16);
+  check (0u32 < 4000000000u32);
+  check (0u32 <= 4000000000u32);
+  check (4000000000u32 > 0u32);
+  check (4000000000u32 >= 0u32);
+  check (4000000000u32 / 10u32 == 400000000u32);
+  check (4000000005u32 % 10u32 == 5u32);
+
+  // 64-bit numbers have some flakiness yet. Not tested
+}