@@ -1634,11 +1634,38 @@ fn cast_shift_rhs(op: ast::binop,
1634
1634
}
1635
1635
}
1636
1636
1637
+ fn fail_if_zero ( cx : block , span : span , divmod : ast:: binop ,
1638
+ rhs : ValueRef , rhs_t : ty:: t ) -> block {
1639
+ let text = if divmod == ast:: div {
1640
+ "divide by zero"
1641
+ } else {
1642
+ "modulo zero"
1643
+ } ;
1644
+ let is_zero = alt ty:: get ( rhs_t) . struct {
1645
+ ty:: ty_int ( t) {
1646
+ let zero = C_integral ( T_int_ty ( cx. ccx ( ) , t) , 0u64 , False ) ;
1647
+ ICmp ( cx, lib:: llvm:: IntEQ , rhs, zero)
1648
+ }
1649
+ ty:: ty_uint ( t) {
1650
+ let zero = C_integral ( T_uint_ty ( cx. ccx ( ) , t) , 0u64 , False ) ;
1651
+ ICmp ( cx, lib:: llvm:: IntEQ , rhs, zero)
1652
+ }
1653
+ _ {
1654
+ cx. tcx ( ) . sess . bug ( "fail-if-zero on unexpected type: " +
1655
+ ty_to_str ( cx. ccx ( ) . tcx , rhs_t) ) ;
1656
+ }
1657
+ } ;
1658
+ with_cond ( cx, is_zero) { |bcx|
1659
+ trans_fail ( bcx, some ( span) , text)
1660
+ }
1661
+ }
1662
+
1637
1663
// Important to get types for both lhs and rhs, because one might be _|_
1638
1664
// and the other not.
1639
- fn trans_eager_binop ( cx : block , op : ast:: binop , lhs : ValueRef ,
1665
+ fn trans_eager_binop ( cx : block , span : span , op : ast:: binop , lhs : ValueRef ,
1640
1666
lhs_t : ty:: t , rhs : ValueRef , rhs_t : ty:: t , dest : dest )
1641
1667
-> block {
1668
+ let mut cx = cx;
1642
1669
let _icx = cx. insn_ctxt ( "trans_eager_binop" ) ;
1643
1670
if dest == ignore { ret cx; }
1644
1671
let intype = {
@@ -1667,16 +1694,30 @@ fn trans_eager_binop(cx: block, op: ast::binop, lhs: ValueRef,
1667
1694
else { Mul ( cx, lhs, rhs) }
1668
1695
}
1669
1696
ast:: div {
1670
- if is_float { FDiv ( cx, lhs, rhs) }
1671
- else if ty:: type_is_signed ( intype) {
1672
- SDiv ( cx, lhs, rhs)
1673
- } else { UDiv ( cx, lhs, rhs) }
1697
+ if is_float {
1698
+ FDiv ( cx, lhs, rhs)
1699
+ } else {
1700
+ // Only zero-check integers; fp /0 is NaN
1701
+ cx = fail_if_zero ( cx, span, op, rhs, rhs_t) ;
1702
+ if ty:: type_is_signed ( intype) {
1703
+ SDiv ( cx, lhs, rhs)
1704
+ } else {
1705
+ UDiv ( cx, lhs, rhs)
1706
+ }
1707
+ }
1674
1708
}
1675
1709
ast:: rem {
1676
- if is_float { FRem ( cx, lhs, rhs) }
1677
- else if ty:: type_is_signed ( intype) {
1678
- SRem ( cx, lhs, rhs)
1679
- } else { URem ( cx, lhs, rhs) }
1710
+ if is_float {
1711
+ FRem ( cx, lhs, rhs)
1712
+ } else {
1713
+ // Only zero-check integers; fp %0 is NaN
1714
+ cx = fail_if_zero ( cx, span, op, rhs, rhs_t) ;
1715
+ if ty:: type_is_signed ( intype) {
1716
+ SRem ( cx, lhs, rhs)
1717
+ } else {
1718
+ URem ( cx, lhs, rhs)
1719
+ }
1720
+ }
1680
1721
}
1681
1722
ast:: bitor { Or ( cx, lhs, rhs) }
1682
1723
ast:: bitand { And ( cx, lhs, rhs) }
@@ -1744,7 +1785,8 @@ fn trans_assign_op(bcx: block, ex: @ast::expr, op: ast::binop,
1744
1785
_ { }
1745
1786
}
1746
1787
}
1747
- ret trans_eager_binop ( bcx, op, Load ( bcx, lhs_res. val ) , t, rhs_val, t,
1788
+ ret trans_eager_binop ( bcx, ex. span ,
1789
+ op, Load ( bcx, lhs_res. val ) , t, rhs_val, t,
1748
1790
save_in ( lhs_res. val ) ) ;
1749
1791
}
1750
1792
@@ -1885,7 +1927,8 @@ fn trans_binary(bcx: block, op: ast::binop, lhs: @ast::expr,
1885
1927
// Remaining cases are eager:
1886
1928
let lhs_res = trans_temp_expr ( bcx, lhs) ;
1887
1929
let rhs_res = trans_temp_expr ( lhs_res. bcx , rhs) ;
1888
- ret trans_eager_binop ( rhs_res. bcx , op, lhs_res. val ,
1930
+ ret trans_eager_binop ( rhs_res. bcx , ex. span ,
1931
+ op, lhs_res. val ,
1889
1932
expr_ty ( bcx, lhs) , rhs_res. val ,
1890
1933
expr_ty ( bcx, rhs) , dest) ;
1891
1934
}
0 commit comments