diff --git a/Cargo.toml b/Cargo.toml index b3a5cf4..eefb0b2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,7 +25,7 @@ compiler-rt = { path = "compiler-rt" } c = [] weak = ["rlibc/weak"] -[workspace] +[profile.dev] +debug-assertions = false -[profile.release] -lto = true +[workspace] diff --git a/ci/run.sh b/ci/run.sh index 6a0906b..df27e35 100755 --- a/ci/run.sh +++ b/ci/run.sh @@ -31,10 +31,12 @@ esac # Verify that there are no undefined symbols to `panic` within our implementations case $1 in thumb*) - xargo build --features c --target $1 --bin intrinsics --release + xargo rustc --features c --target $1 --bin intrinsics -- -C lto + xargo rustc --features c --target $1 --bin intrinsics --release -- -C lto ;; *) - cargo build --features c --target $1 --bin intrinsics --release + cargo rustc --features c --target $1 --bin intrinsics -- -C lto + cargo rustc --features c --target $1 --bin intrinsics --release -- -C lto ;; esac diff --git a/src/float/pow.rs b/src/float/pow.rs index 14b3b9a..c02c76f 100644 --- a/src/float/pow.rs +++ b/src/float/pow.rs @@ -1,6 +1,7 @@ +use core::intrinsics; macro_rules! pow { - ($intrinsic:ident: $fty:ty, $ity:ty) => { + ($intrinsic:ident: $fty:ty, $ity:ident) => { /// Returns `a` raised to the power `b` #[cfg_attr(not(test), no_mangle)] pub extern "C" fn $intrinsic(a: $fty, b: $ity) -> $fty { @@ -11,7 +12,7 @@ macro_rules! pow { if (b & 1) != 0 { r *= a; } - b /= 2; + b = sdiv!($ity, b, 2); if b == 0 { break; } diff --git a/src/int/sdiv.rs b/src/int/sdiv.rs index d60dda9..6f96b80 100644 --- a/src/int/sdiv.rs +++ b/src/int/sdiv.rs @@ -13,12 +13,7 @@ macro_rules! div { let b = (b ^ s_b) - s_b; let s = s_a ^ s_b; - if b == 0 { - unsafe { - intrinsics::abort() - } - } - let r = (a as $uty) / (b as $uty); + let r = udiv!((a as $uty), (b as $uty)); (r as $ty ^ s) - s } } @@ -34,12 +29,7 @@ macro_rules! mod_ { let s = a >> (<$ty>::bits() - 1); let a = (a ^ s) - s; - if b == 0 { - unsafe { - intrinsics::abort() - } - } - let r = (a as $uty) % (b as $uty); + let r = urem!((a as $uty), (b as $uty)); (r as $ty ^ s) - s } } diff --git a/src/int/udiv.rs b/src/int/udiv.rs index bb1546c..999dcec 100644 --- a/src/int/udiv.rs +++ b/src/int/udiv.rs @@ -109,18 +109,11 @@ pub extern "C" fn __udivmoddi4(n: u64, d: u64, rem: Option<&mut u64>) -> u64 { // 0 X // --- // 0 X - // NOTE This should be unreachable in safe Rust because the program will panic before - // this intrinsic is called - if d.low() == 0 { - unsafe { - intrinsics::abort() - } - } if let Some(rem) = rem { - *rem = u64::from(n.low() % d.low()); + *rem = u64::from(urem!(n.low(), d.low())); } - return u64::from(n.low() / d.low()); + return u64::from(udiv!(n.low(), d.low())); } else { // 0 X // --- @@ -153,9 +146,9 @@ pub extern "C" fn __udivmoddi4(n: u64, d: u64, rem: Option<&mut u64>) -> u64 { // --- // K 0 if let Some(rem) = rem { - *rem = u64::from_parts(0, n.high() % d.high()); + *rem = u64::from_parts(0, urem!(n.high(), d.high())); } - return u64::from(n.high() / d.high()); + return u64::from(udiv!(n.high(), d.high())); } // K K diff --git a/src/lib.rs b/src/lib.rs index acc56c9..351be02 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -13,6 +13,66 @@ // NOTE cfg(all(feature = "c", ..)) indicate that compiler-rt provides an arch optimized // implementation of that intrinsic and we'll prefer to use that +macro_rules! udiv { + ($a:expr, $b:expr) => { + unsafe { + let a = $a; + let b = $b; + + if b == 0 { + intrinsics::abort() + } else { + intrinsics::unchecked_div(a, b) + } + } + } +} + +macro_rules! sdiv { + ($sty:ident, $a:expr, $b:expr) => { + unsafe { + let a = $a; + let b = $b; + + if b == 0 || (b == -1 && a == $sty::min_value()) { + intrinsics::abort() + } else { + intrinsics::unchecked_div(a, b) + } + } + } +} + +macro_rules! urem { + ($a:expr, $b:expr) => { + unsafe { + let a = $a; + let b = $b; + + if b == 0 { + intrinsics::abort() + } else { + intrinsics::unchecked_rem(a, b) + } + } + } +} + +macro_rules! srem { + ($sty:ty, $a:expr, $b:expr) => { + unsafe { + let a = $a; + let b = $b; + + if b == 0 || (b == -1 && a == $sty::min_value()) { + intrinsics::abort() + } else { + intrinsics::unchecked_rem(a, b) + } + } + } +} + #[cfg(test)] #[macro_use] extern crate quickcheck;