parent
177348fbb4
commit
5f54cc7658
4 changed files with 60 additions and 51 deletions
|
@ -67,6 +67,6 @@ function jit_calc() {
|
||||||
## Not yet supported
|
## Not yet supported
|
||||||
|
|
||||||
* Good non-rust abi support ([several problems](https://github.com/bjorn3/rustc_codegen_cranelift/issues/10))
|
* 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)
|
* 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)
|
* SIMD ([tracked here](https://github.com/bjorn3/rustc_codegen_cranelift/issues/171), some basic things work)
|
||||||
|
|
|
@ -87,6 +87,8 @@ fn main() {
|
||||||
panic!();
|
panic!();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test_checked_mul();
|
||||||
|
|
||||||
let _a = 1u32 << 2u8;
|
let _a = 1u32 << 2u8;
|
||||||
|
|
||||||
let empty: [i32; 0] = [];
|
let empty: [i32; 0] = [];
|
||||||
|
@ -258,6 +260,27 @@ unsafe fn test_mm_extract_epi8() {
|
||||||
assert_eq!(r2, 3);
|
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)]
|
#[derive(PartialEq)]
|
||||||
enum LoopState {
|
enum LoopState {
|
||||||
Continue(()),
|
Continue(()),
|
||||||
|
|
|
@ -30,38 +30,10 @@ index 4bc44e9..8e3c7a4 100644
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn empty_array_is_always_default() {
|
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
|
diff --git a/src/libcore/tests/num/mod.rs b/src/libcore/tests/num/mod.rs
|
||||||
index a17c094..5bb11d2 100644
|
index a17c094..5bb11d2 100644
|
||||||
--- a/src/libcore/tests/num/mod.rs
|
--- a/src/libcore/tests/num/mod.rs
|
||||||
+++ b/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 {
|
@@ -640,6 +639,7 @@ macro_rules! test_float {
|
||||||
mod $modname {
|
mod $modname {
|
||||||
// FIXME(nagisa): these tests should test for sign of -0.0
|
// FIXME(nagisa): these tests should test for sign of -0.0
|
||||||
|
@ -78,17 +50,5 @@ index a17c094..5bb11d2 100644
|
||||||
fn max() {
|
fn max() {
|
||||||
assert_eq!((0.0 as $fty).max(0.0), 0.0);
|
assert_eq!((0.0 as $fty).max(0.0), 0.0);
|
||||||
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)
|
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)
|
(val, has_overflow)
|
||||||
}
|
}
|
||||||
BinOp::Mul => {
|
BinOp::Mul => {
|
||||||
let val = fx.bcx.ins().imul(lhs, rhs);
|
let ty = fx.bcx.func.dfg.value_type(lhs);
|
||||||
/*let val_hi = if !signed {
|
match ty {
|
||||||
fx.bcx.ins().umulhi(lhs, rhs)
|
types::I8 | types::I16 | types::I32 if !signed => {
|
||||||
} else {
|
let lhs = fx.bcx.ins().uextend(ty.double_width().unwrap(), lhs);
|
||||||
fx.bcx.ins().smulhi(lhs, rhs)
|
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::NotEqual, val_hi, 0);*/
|
let has_overflow = fx.bcx.ins().icmp_imm(IntCC::UnsignedGreaterThan, val, (1 << ty.bits()) - 1);
|
||||||
// TODO: check for overflow
|
let val = fx.bcx.ins().ireduce(ty, val);
|
||||||
let has_overflow = fx.bcx.ins().bconst(types::B1, false);
|
(val, has_overflow)
|
||||||
(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 => {
|
BinOp::Shl => {
|
||||||
let val = fx.bcx.ins().ishl(lhs, rhs);
|
let val = fx.bcx.ins().ishl(lhs, rhs);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue