Skip to content

Commit 0ebfb82

Browse files
brsongraydon
authored andcommitted
Add support for unsigned binops. Closes #57
1 parent bd56dd9 commit 0ebfb82

File tree

3 files changed

+80
-16
lines changed

3 files changed

+80
-16
lines changed

Diff for: src/Makefile

+2
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,7 @@ TASK_XFAILS := test/run-pass/task-comm-8.rs \
408408
TEST_XFAILS_BOOT := $(TASK_XFAILS) \
409409
$(NOMINAL_TAG_XFAILS) \
410410
$(CONST_TAG_XFAILS) \
411+
test/run-pass/arith-unsigned.rs \
411412
test/run-pass/child-outlives-parent.rs \
412413
test/run-pass/clone-with-exterior.rs \
413414
test/run-pass/constrained-type.rs \
@@ -450,6 +451,7 @@ TEST_XFAILS_RUSTC := $(filter-out \
450451
arith-0.rs \
451452
arith-1.rs \
452453
arith-2.rs \
454+
arith-unsigned.rs \
453455
auto-instantiate.rs \
454456
autoderef-full-lval.rs \
455457
bind-exterior.rs \

Diff for: src/comp/middle/trans.rs

+54-16
Original file line numberDiff line numberDiff line change
@@ -1840,33 +1840,67 @@ fn trans_unary(@block_ctxt cx, ast.unop op,
18401840

18411841
// FIXME: implement proper structural comparison.
18421842

1843-
fn trans_compare(@block_ctxt cx, ast.binop op,
1843+
fn trans_compare(@block_ctxt cx, ast.binop op, @ty.t intype,
18441844
ValueRef lhs, ValueRef rhs) -> ValueRef {
18451845
auto cmp = lib.llvm.LLVMIntEQ;
18461846
alt (op) {
18471847
case (ast.eq) { cmp = lib.llvm.LLVMIntEQ; }
18481848
case (ast.ne) { cmp = lib.llvm.LLVMIntNE; }
18491849

1850-
// FIXME (issue #57): switch by signedness.
1851-
case (ast.lt) { cmp = lib.llvm.LLVMIntSLT; }
1852-
case (ast.le) { cmp = lib.llvm.LLVMIntSLE; }
1853-
case (ast.ge) { cmp = lib.llvm.LLVMIntSGE; }
1854-
case (ast.gt) { cmp = lib.llvm.LLVMIntSGT; }
1850+
case (ast.lt) {
1851+
if (ty.type_is_signed(intype)) {
1852+
cmp = lib.llvm.LLVMIntSLT;
1853+
} else {
1854+
cmp = lib.llvm.LLVMIntULT;
1855+
}
1856+
}
1857+
case (ast.le) {
1858+
if (ty.type_is_signed(intype)) {
1859+
cmp = lib.llvm.LLVMIntSLE;
1860+
} else {
1861+
cmp = lib.llvm.LLVMIntULE;
1862+
}
1863+
}
1864+
case (ast.gt) {
1865+
if (ty.type_is_signed(intype)) {
1866+
cmp = lib.llvm.LLVMIntSGT;
1867+
} else {
1868+
cmp = lib.llvm.LLVMIntUGT;
1869+
}
1870+
}
1871+
case (ast.ge) {
1872+
if (ty.type_is_signed(intype)) {
1873+
cmp = lib.llvm.LLVMIntSGE;
1874+
} else {
1875+
cmp = lib.llvm.LLVMIntUGE;
1876+
}
1877+
}
18551878
}
18561879
ret cx.build.ICmp(cmp, lhs, rhs);
18571880
}
18581881

1859-
fn trans_eager_binop(@block_ctxt cx, ast.binop op,
1882+
fn trans_eager_binop(@block_ctxt cx, ast.binop op, @ty.t intype,
18601883
ValueRef lhs, ValueRef rhs) -> ValueRef {
18611884

18621885
alt (op) {
18631886
case (ast.add) { ret cx.build.Add(lhs, rhs); }
18641887
case (ast.sub) { ret cx.build.Sub(lhs, rhs); }
18651888

1866-
// FIXME (issue #57): switch by signedness.
18671889
case (ast.mul) { ret cx.build.Mul(lhs, rhs); }
1868-
case (ast.div) { ret cx.build.SDiv(lhs, rhs); }
1869-
case (ast.rem) { ret cx.build.SRem(lhs, rhs); }
1890+
case (ast.div) {
1891+
if (ty.type_is_signed(intype)) {
1892+
ret cx.build.SDiv(lhs, rhs);
1893+
} else {
1894+
ret cx.build.UDiv(lhs, rhs);
1895+
}
1896+
}
1897+
case (ast.rem) {
1898+
if (ty.type_is_signed(intype)) {
1899+
ret cx.build.SRem(lhs, rhs);
1900+
} else {
1901+
ret cx.build.URem(lhs, rhs);
1902+
}
1903+
}
18701904

18711905
case (ast.bitor) { ret cx.build.Or(lhs, rhs); }
18721906
case (ast.bitand) { ret cx.build.And(lhs, rhs); }
@@ -1875,7 +1909,7 @@ fn trans_eager_binop(@block_ctxt cx, ast.binop op,
18751909
case (ast.lsr) { ret cx.build.LShr(lhs, rhs); }
18761910
case (ast.asr) { ret cx.build.AShr(lhs, rhs); }
18771911
case (_) {
1878-
ret trans_compare(cx, op, lhs, rhs);
1912+
ret trans_compare(cx, op, intype, lhs, rhs);
18791913
}
18801914
}
18811915
fail;
@@ -1950,10 +1984,12 @@ fn trans_binary(@block_ctxt cx, ast.binop op,
19501984
case (_) {
19511985
// Remaining cases are eager:
19521986
auto lhs = trans_expr(cx, a);
1953-
lhs = autoderef(lhs.bcx, lhs.val, ty.expr_ty(a));
1987+
auto lhty = ty.expr_ty(a);
1988+
lhs = autoderef(lhs.bcx, lhs.val, lhty);
19541989
auto rhs = trans_expr(lhs.bcx, b);
1955-
rhs = autoderef(rhs.bcx, rhs.val, ty.expr_ty(b));
1956-
ret res(rhs.bcx, trans_eager_binop(rhs.bcx, op,
1990+
auto rhty = ty.expr_ty(b);
1991+
rhs = autoderef(rhs.bcx, rhs.val, rhty);
1992+
ret res(rhs.bcx, trans_eager_binop(rhs.bcx, op, lhty,
19571993
lhs.val, rhs.val));
19581994
}
19591995
}
@@ -2142,7 +2178,8 @@ fn trans_pat_match(@block_ctxt cx, @ast.pat pat, ValueRef llval,
21422178

21432179
case (ast.pat_lit(?lt, ?ann)) {
21442180
auto lllit = trans_lit(cx.fcx.ccx, *lt, ann);
2145-
auto lleq = trans_compare(cx, ast.eq, llval, lllit);
2181+
auto lltype = ty.ann_to_type(ann);
2182+
auto lleq = trans_compare(cx, ast.eq, lltype, llval, lllit);
21462183

21472184
auto matched_cx = new_sub_block_ctxt(cx, "matched_cx");
21482185
cx.build.CondBr(lleq, matched_cx.llbb, next_cx.llbb);
@@ -3035,7 +3072,8 @@ fn trans_expr(@block_ctxt cx, @ast.expr e) -> result {
30353072
auto lhs_val = load_scalar_or_boxed(lhs_res.res.bcx,
30363073
lhs_res.res.val, t);
30373074
auto rhs_res = trans_expr(lhs_res.res.bcx, src);
3038-
auto v = trans_eager_binop(rhs_res.bcx, op, lhs_val, rhs_res.val);
3075+
auto v = trans_eager_binop(rhs_res.bcx, op, t,
3076+
lhs_val, rhs_res.val);
30393077
// FIXME: calculate copy init-ness in typestate.
30403078
ret copy_ty(rhs_res.bcx, DROP_EXISTING,
30413079
lhs_res.res.val, v, t);

Diff for: src/test/run-pass/arith-unsigned.rs

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Unsigned integer operations
2+
3+
fn main() {
4+
check (0u8 < 255u8);
5+
check (0u8 <= 255u8);
6+
check (255u8 > 0u8);
7+
check (255u8 >= 0u8);
8+
check (250u8 / 10u8 == 25u8);
9+
check (255u8 % 10u8 == 5u8);
10+
check (0u16 < 60000u16);
11+
check (0u16 <= 60000u16);
12+
check (60000u16 > 0u16);
13+
check (60000u16 >= 0u16);
14+
check (60000u16 / 10u16 == 6000u16);
15+
check (60005u16 % 10u16 == 5u16);
16+
check (0u32 < 4000000000u32);
17+
check (0u32 <= 4000000000u32);
18+
check (4000000000u32 > 0u32);
19+
check (4000000000u32 >= 0u32);
20+
check (4000000000u32 / 10u32 == 400000000u32);
21+
check (4000000005u32 % 10u32 == 5u32);
22+
23+
// 64-bit numbers have some flakiness yet. Not tested
24+
}

0 commit comments

Comments
 (0)