parent
177348fbb4
commit
5f54cc7658
@ -67,6 +67,6 @@ function jit_calc() {
|
||||
## Not yet supported
|
||||
|
||||
* Good non-rust abi support ([several problems](https://github.com/bjorn3/rustc_codegen_cranelift/issues/10))
|
||||
* Checked binops ([some missing instructions in cranelift](https://github.com/bytecodealliance/wasmtime/issues/1044))
|
||||
* Proc macros
|
||||
* Inline assembly ([no cranelift support](https://github.com/bytecodealliance/wasmtime/issues/1041), not coming soon)
|
||||
* SIMD ([tracked here](https://github.com/bjorn3/rustc_codegen_cranelift/issues/171), some basic things work)
|
||||
|
@ -87,6 +87,8 @@ fn main() {
|
||||
panic!();
|
||||
}
|
||||
|
||||
test_checked_mul();
|
||||
|
||||
let _a = 1u32 << 2u8;
|
||||
|
||||
let empty: [i32; 0] = [];
|
||||
@ -258,6 +260,27 @@ unsafe fn test_mm_extract_epi8() {
|
||||
assert_eq!(r2, 3);
|
||||
}
|
||||
|
||||
fn test_checked_mul() {
|
||||
let u: Option<u8> = u8::from_str_radix("1000", 10).ok();
|
||||
assert_eq!(u, None);
|
||||
|
||||
assert_eq!(1u8.checked_mul(255u8), Some(255u8));
|
||||
assert_eq!(255u8.checked_mul(255u8), None);
|
||||
assert_eq!(1i8.checked_mul(127i8), Some(127i8));
|
||||
assert_eq!(127i8.checked_mul(127i8), None);
|
||||
assert_eq!((-1i8).checked_mul(-127i8), Some(127i8));
|
||||
assert_eq!(1i8.checked_mul(-128i8), Some(-128i8));
|
||||
assert_eq!((-128i8).checked_mul(-128i8), None);
|
||||
|
||||
assert_eq!(1u64.checked_mul(u64::max_value()), Some(u64::max_value()));
|
||||
assert_eq!(u64::max_value().checked_mul(u64::max_value()), None);
|
||||
assert_eq!(1i64.checked_mul(i64::max_value()), Some(i64::max_value()));
|
||||
assert_eq!(i64::max_value().checked_mul(i64::max_value()), None);
|
||||
assert_eq!((-1i64).checked_mul(i64::min_value() + 1), Some(i64::max_value()));
|
||||
assert_eq!(1i64.checked_mul(i64::min_value()), Some(i64::min_value()));
|
||||
assert_eq!(i64::min_value().checked_mul(i64::min_value()), None);
|
||||
}
|
||||
|
||||
#[derive(PartialEq)]
|
||||
enum LoopState {
|
||||
Continue(()),
|
||||
|
@ -30,38 +30,10 @@ index 4bc44e9..8e3c7a4 100644
|
||||
|
||||
#[test]
|
||||
fn empty_array_is_always_default() {
|
||||
diff --git a/src/libcore/tests/iter.rs b/src/libcore/tests/iter.rs
|
||||
index c9096b7..be37fcd 100644
|
||||
--- a/src/libcore/tests/iter.rs
|
||||
+++ b/src/libcore/tests/iter.rs
|
||||
@@ -342,6 +342,7 @@ fn test_iterator_step_by_nth() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
+#[ignore] // checked_mul impl not yet checking for overflow
|
||||
fn test_iterator_step_by_nth_overflow() {
|
||||
#[cfg(target_pointer_width = "8")]
|
||||
type Bigger = u16;
|
||||
@@ -2305,6 +2308,7 @@ fn test_repeat_with_take_collect() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
+#[ignore] // checked_mul impl not yet checking for overflow
|
||||
fn test_successors() {
|
||||
let mut powers_of_10 = successors(Some(1_u16), |n| n.checked_mul(10));
|
||||
assert_eq!(powers_of_10.by_ref().collect::<Vec<_>>(), &[1, 10, 100, 1_000, 10_000]);
|
||||
diff --git a/src/libcore/tests/num/mod.rs b/src/libcore/tests/num/mod.rs
|
||||
index a17c094..5bb11d2 100644
|
||||
--- a/src/libcore/tests/num/mod.rs
|
||||
+++ b/src/libcore/tests/num/mod.rs
|
||||
@@ -63,6 +63,7 @@ pub fn test_num<T>(ten: T, two: T) where
|
||||
}
|
||||
|
||||
#[test]
|
||||
+#[ignore] // checked_mul impl not yet checking for overflow
|
||||
fn from_str_issue7588() {
|
||||
let u: Option<u8> = u8::from_str_radix("1000", 10).ok();
|
||||
assert_eq!(u, None);
|
||||
@@ -640,6 +639,7 @@ macro_rules! test_float {
|
||||
mod $modname {
|
||||
// FIXME(nagisa): these tests should test for sign of -0.0
|
||||
@ -78,17 +50,5 @@ index a17c094..5bb11d2 100644
|
||||
fn max() {
|
||||
assert_eq!((0.0 as $fty).max(0.0), 0.0);
|
||||
assert_eq!((-0.0 as $fty).max(-0.0), -0.0);
|
||||
diff --git a/src/libcore/tests/time.rs b/src/libcore/tests/time.rs
|
||||
index fac70c4..9107a02 100644
|
||||
--- a/src/libcore/tests/time.rs
|
||||
+++ b/src/libcore/tests/time.rs
|
||||
@@ -127,6 +127,7 @@ fn mul() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
+#[ignore] // checked_mul impl not yet checking for overflow
|
||||
fn checked_mul() {
|
||||
assert_eq!(Duration::new(0, 1).checked_mul(2), Some(Duration::new(0, 2)));
|
||||
assert_eq!(Duration::new(1, 1).checked_mul(3), Some(Duration::new(3, 3)));
|
||||
--
|
||||
2.21.0 (Apple Git-122)
|
||||
|
46
src/num.rs
46
src/num.rs
@ -245,16 +245,42 @@ pub(crate) fn trans_checked_int_binop<'tcx>(
|
||||
(val, has_overflow)
|
||||
}
|
||||
BinOp::Mul => {
|
||||
let val = fx.bcx.ins().imul(lhs, rhs);
|
||||
/*let val_hi = if !signed {
|
||||
fx.bcx.ins().umulhi(lhs, rhs)
|
||||
} else {
|
||||
fx.bcx.ins().smulhi(lhs, rhs)
|
||||
};
|
||||
let has_overflow = fx.bcx.ins().icmp_imm(IntCC::NotEqual, val_hi, 0);*/
|
||||
// TODO: check for overflow
|
||||
let has_overflow = fx.bcx.ins().bconst(types::B1, false);
|
||||
(val, has_overflow)
|
||||
let ty = fx.bcx.func.dfg.value_type(lhs);
|
||||
match ty {
|
||||
types::I8 | types::I16 | types::I32 if !signed => {
|
||||
let lhs = fx.bcx.ins().uextend(ty.double_width().unwrap(), lhs);
|
||||
let rhs = fx.bcx.ins().uextend(ty.double_width().unwrap(), rhs);
|
||||
let val = fx.bcx.ins().imul(lhs, rhs);
|
||||
let has_overflow = fx.bcx.ins().icmp_imm(IntCC::UnsignedGreaterThan, val, (1 << ty.bits()) - 1);
|
||||
let val = fx.bcx.ins().ireduce(ty, val);
|
||||
(val, has_overflow)
|
||||
}
|
||||
types::I8 | types::I16 | types::I32 if signed => {
|
||||
let lhs = fx.bcx.ins().sextend(ty.double_width().unwrap(), lhs);
|
||||
let rhs = fx.bcx.ins().sextend(ty.double_width().unwrap(), rhs);
|
||||
let val = fx.bcx.ins().imul(lhs, rhs);
|
||||
let has_underflow = fx.bcx.ins().icmp_imm(IntCC::SignedLessThan, val, -(1 << (ty.bits() - 1)));
|
||||
let has_overflow = fx.bcx.ins().icmp_imm(IntCC::SignedGreaterThan, val, (1 << (ty.bits() - 1)) - 1);
|
||||
let val = fx.bcx.ins().ireduce(ty, val);
|
||||
(val, fx.bcx.ins().bor(has_underflow, has_overflow))
|
||||
}
|
||||
types::I64 => {
|
||||
//let val = fx.easy_call("__mulodi4", &[lhs, rhs, overflow_ptr], types::I64);
|
||||
let val = fx.bcx.ins().imul(lhs, rhs);
|
||||
let has_overflow = if !signed {
|
||||
let val_hi = fx.bcx.ins().umulhi(lhs, rhs);
|
||||
fx.bcx.ins().icmp_imm(IntCC::NotEqual, val_hi, 0)
|
||||
} else {
|
||||
let val_hi = fx.bcx.ins().smulhi(lhs, rhs);
|
||||
let not_all_zero = fx.bcx.ins().icmp_imm(IntCC::NotEqual, val_hi, 0);
|
||||
let not_all_ones = fx.bcx.ins().icmp_imm(IntCC::NotEqual, val_hi, u64::try_from((1u128 << ty.bits()) - 1).unwrap() as i64);
|
||||
fx.bcx.ins().band(not_all_zero, not_all_ones)
|
||||
};
|
||||
(val, has_overflow)
|
||||
}
|
||||
types::I128 => unreachable!("i128 should have been handled by codegen_i128::maybe_codegen"),
|
||||
_ => unreachable!("invalid non-integer type {}", ty),
|
||||
}
|
||||
}
|
||||
BinOp::Shl => {
|
||||
let val = fx.bcx.ins().ishl(lhs, rhs);
|
||||
|
Loading…
x
Reference in New Issue
Block a user