From 9493c37455380f4fce36da6b417afdcfb7db18e1 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Fri, 16 Sep 2016 15:53:14 -0500 Subject: [PATCH 1/6] test our implementations against gcc_s if it exposes the same intrinsics that we implement -- gcc_s doesn't implement all the intrinsics for all the architectures. closes #65 --- Cargo.toml | 3 +++ gcc_s/Cargo.toml | 7 +++++++ gcc_s/src/lib.rs | 51 ++++++++++++++++++++++++++++++++++++++++++++++ src/float/add.rs | 18 ++++++++++++---- src/int/mul.rs | 32 ++++++++++++++++++++++++++--- src/int/sdiv.rs | 53 ++++++++++++++++++++++++++++++++++++++++++------ src/int/shift.rs | 22 +++++++++++++++++--- src/int/udiv.rs | 53 ++++++++++++++++++++++++++++++++++++++++++------ src/lib.rs | 3 +++ 9 files changed, 220 insertions(+), 22 deletions(-) create mode 100644 gcc_s/Cargo.toml create mode 100644 gcc_s/src/lib.rs diff --git a/Cargo.toml b/Cargo.toml index 48f6ee0..229cec7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,7 +7,10 @@ version = "0.1.0" rlibc = { git = "https://github.com/alexcrichton/rlibc", optional = true } [dev-dependencies] +gcc_s = { path = "gcc_s" } quickcheck = "0.3.1" [features] default = ["rlibc/weak"] + +[workspace] diff --git a/gcc_s/Cargo.toml b/gcc_s/Cargo.toml new file mode 100644 index 0000000..4e3080f --- /dev/null +++ b/gcc_s/Cargo.toml @@ -0,0 +1,7 @@ +[package] +authors = ["Jorge Aparicio "] +name = "gcc_s" +version = "0.1.0" + +[dependencies] +libloading = "0.3.0" diff --git a/gcc_s/src/lib.rs b/gcc_s/src/lib.rs new file mode 100644 index 0000000..b053a5b --- /dev/null +++ b/gcc_s/src/lib.rs @@ -0,0 +1,51 @@ +#![feature(drop_types_in_const)] + +extern crate libloading; + +use std::sync::{Once, ONCE_INIT}; + +use libloading::Library; + +static mut GCC_S: Option = None; + +fn gcc_s() -> &'static Library { + unsafe { + static INIT: Once = ONCE_INIT; + + INIT.call_once(|| { + GCC_S = Some(Library::new("libgcc_s.so.1").unwrap()); + }); + GCC_S.as_ref().unwrap() + } +} + +macro_rules! declare { + ($symbol:ident: fn($($i:ty),+) -> $o:ty) => { + pub fn $symbol() -> Option $o> { + unsafe { + gcc_s().get(concat!("__", stringify!($symbol)).as_bytes()).ok().map(|s| *s) + } + } + } +} + +declare!(ashldi3: fn(u64, u32) -> u64); +declare!(ashrdi3: fn(i64, u32) -> i64); +declare!(divdi3: fn(i64, i64) -> i64); +declare!(divmoddi4: fn(i64, i64, &mut i64) -> i64); +declare!(divmodsi4: fn(i32, i32, &mut i32) -> i32); +declare!(divsi3: fn(i32, i32) -> i32); +declare!(lshrdi3: fn(u64, u32) -> u64); +declare!(moddi3: fn(i64, i64) -> i64); +declare!(modsi3: fn(i32, i32) -> i32); +declare!(muldi3: fn(u64, u64) -> u64); +declare!(mulodi4: fn(i64, i64, &mut i32) -> i64); +declare!(mulosi4: fn(i32, i32, &mut i32) -> i32); +declare!(udivdi3: fn(u64, u64) -> u64); +declare!(udivmoddi4: fn(u64, u64, Option<&mut u64>) -> u64); +declare!(udivmodsi4: fn(u32, u32, Option<&mut u32>) -> u32); +declare!(udivsi3: fn(u32, u32) -> u32); +declare!(umoddi3: fn(u64, u64) -> u64); +declare!(umodsi3: fn(u32, u32) -> u32); +declare!(addsf3: fn(f32, f32) -> f32); +declare!(adddf3: fn(f64, f64) -> f64); diff --git a/src/float/add.rs b/src/float/add.rs index 3ebc92b..13c7aba 100644 --- a/src/float/add.rs +++ b/src/float/add.rs @@ -199,6 +199,8 @@ pub extern fn __aeabi_fadd(a: f32, b: f32) -> f32 { #[cfg(test)] mod tests { use core::{f32, f64}; + + use gcc_s; use qc::{U32, U64}; use float::Float; @@ -213,15 +215,23 @@ mod tests { fn addsf3(a: U32, b: U32) -> bool { let (a, b) = (f32::from_repr(a.0), f32::from_repr(b.0)); let x = super::__addsf3(a, b); - let y = a + b; - x.eq_repr(y) + + if let Some(addsf3) = gcc_s::addsf3() { + x.eq_repr(unsafe { addsf3(a, b) }) + } else { + x.eq_repr(a + b) + } } fn adddf3(a: U64, b: U64) -> bool { let (a, b) = (f64::from_repr(a.0), f64::from_repr(b.0)); let x = super::__adddf3(a, b); - let y = a + b; - x.eq_repr(y) + + if let Some(adddf3) = gcc_s::adddf3() { + x.eq_repr(unsafe { adddf3(a, b) }) + } else { + x.eq_repr(a + b) + } } } diff --git a/src/int/mul.rs b/src/int/mul.rs index 3d68444..4ea65bd 100644 --- a/src/int/mul.rs +++ b/src/int/mul.rs @@ -72,13 +72,19 @@ mulo!(__mulodi4: i64); #[cfg(test)] mod tests { + use gcc_s; use qc::{I32, I64, U64}; quickcheck! { fn muldi(a: U64, b: U64) -> bool { let (a, b) = (a.0, b.0); let r = super::__muldi3(a, b); - r == a.wrapping_mul(b) + + if let Some(muldi3) = gcc_s::muldi3() { + r == unsafe { muldi3(a, b) } + } else { + r == a.wrapping_mul(b) + } } fn mulosi(a: I32, b: I32) -> bool { @@ -88,7 +94,17 @@ mod tests { if overflow != 0 && overflow != 1 { return false; } - (r, overflow != 0) == a.overflowing_mul(b) + + if let Some(mulosi4) = gcc_s::mulosi4() { + let mut gcc_s_overflow = 2; + let gcc_s_r = unsafe { + mulosi4(a, b, &mut gcc_s_overflow) + }; + + (r, overflow) == (gcc_s_r, gcc_s_overflow) + } else { + (r, overflow != 0) == a.overflowing_mul(b) + } } fn mulodi(a: I64, b: I64) -> bool { @@ -98,7 +114,17 @@ mod tests { if overflow != 0 && overflow != 1 { return false; } - (r, overflow != 0) == a.overflowing_mul(b) + + if let Some(mulodi4) = gcc_s::mulodi4() { + let mut gcc_s_overflow = 2; + let gcc_s_r = unsafe { + mulodi4(a, b, &mut gcc_s_overflow) + }; + + (r, overflow) == (gcc_s_r, gcc_s_overflow) + } else { + (r, overflow != 0) == a.overflowing_mul(b) + } } } } diff --git a/src/int/sdiv.rs b/src/int/sdiv.rs index 72ddbca..50ad0e0 100644 --- a/src/int/sdiv.rs +++ b/src/int/sdiv.rs @@ -52,6 +52,7 @@ divmod!(__divmoddi4, __divdi3: i64); #[cfg(test)] mod tests { + use gcc_s; use quickcheck::TestResult; use qc::{U32, U64}; @@ -62,7 +63,12 @@ mod tests { TestResult::discard() } else { let q = super::__divdi3(n, d); - TestResult::from_bool(q == n / d) + + if let Some(divdi3) = gcc_s::divdi3() { + TestResult::from_bool(q == unsafe { divdi3(n, d) }) + } else { + TestResult::from_bool(q == n / d) + } } } @@ -72,7 +78,12 @@ mod tests { TestResult::discard() } else { let r = super::__moddi3(n, d); - TestResult::from_bool(r == n % d) + + if let Some(moddi3) = gcc_s::moddi3() { + TestResult::from_bool(r == unsafe { moddi3(n, d) }) + } else { + TestResult::from_bool(r == n % d) + } } } @@ -83,7 +94,17 @@ mod tests { } else { let mut r = 0; let q = super::__divmoddi4(n, d, &mut r); - TestResult::from_bool(q == n / d && r == n % d) + + if let Some(divmoddi4) = gcc_s::divmoddi4() { + let mut gcc_s_r = 0; + let gcc_s_q = unsafe { + divmoddi4(n, d, &mut gcc_s_r) + }; + + TestResult::from_bool(q == gcc_s_q && r == gcc_s_r) + } else { + TestResult::from_bool(q == n / d && r == n % d) + } } } @@ -93,7 +114,12 @@ mod tests { TestResult::discard() } else { let q = super::__divsi3(n, d); - TestResult::from_bool(q == n / d) + + if let Some(divsi3) = gcc_s::divsi3() { + TestResult::from_bool(q == unsafe { divsi3(n, d)}) + } else { + TestResult::from_bool(q == n / d) + } } } @@ -103,7 +129,12 @@ mod tests { TestResult::discard() } else { let r = super::__modsi3(n, d); - TestResult::from_bool(r == n % d) + + if let Some(modsi3) = gcc_s::modsi3() { + TestResult::from_bool(r == unsafe { modsi3(n, d) }) + } else { + TestResult::from_bool(r == n % d) + } } } @@ -114,7 +145,17 @@ mod tests { } else { let mut r = 0; let q = super::__divmodsi4(n, d, &mut r); - TestResult::from_bool(q == n / d && r == n % d) + + if let Some(divmodsi4) = gcc_s::divmodsi4() { + let mut gcc_s_r = 0; + let gcc_s_q = unsafe { + divmodsi4(n, d, &mut gcc_s_r) + }; + + TestResult::from_bool(q == gcc_s_q && r == gcc_s_r) + } else { + TestResult::from_bool(q == n / d && r == n % d) + } } } } diff --git a/src/int/shift.rs b/src/int/shift.rs index 96ae6db..c7be811 100644 --- a/src/int/shift.rs +++ b/src/int/shift.rs @@ -60,6 +60,7 @@ lshr!(__lshrdi3: u64); #[cfg(test)] mod tests { + use gcc_s; use quickcheck::TestResult; use qc::{I64, U64}; @@ -71,7 +72,12 @@ mod tests { TestResult::discard() } else { let r = super::__ashldi3(a, b); - TestResult::from_bool(r == a << b) + + if let Some(ashldi3) = gcc_s::ashldi3() { + TestResult::from_bool(r == unsafe { ashldi3(a, b) }) + } else { + TestResult::from_bool(r == a << b) + } } } @@ -81,7 +87,12 @@ mod tests { TestResult::discard() } else { let r = super::__ashrdi3(a, b); - TestResult::from_bool(r == a >> b) + + if let Some(ashrdi3) = gcc_s::ashrdi3() { + TestResult::from_bool(r == unsafe { ashrdi3(a, b) }) + } else { + TestResult::from_bool(r == a >> b) + } } } @@ -91,7 +102,12 @@ mod tests { TestResult::discard() } else { let r = super::__lshrdi3(a, b); - TestResult::from_bool(r == a >> b) + + if let Some(lshrdi3) = gcc_s::lshrdi3() { + TestResult::from_bool(r == unsafe { lshrdi3(a, b) }) + } else { + TestResult::from_bool(r == a >> b) + } } } } diff --git a/src/int/udiv.rs b/src/int/udiv.rs index f3ec720..8c9d06f 100644 --- a/src/int/udiv.rs +++ b/src/int/udiv.rs @@ -228,6 +228,7 @@ pub extern "C" fn __udivmoddi4(n: u64, d: u64, rem: Option<&mut u64>) -> u64 { #[cfg(test)] mod tests { + use gcc_s; use quickcheck::TestResult; use qc::{U32, U64}; @@ -238,7 +239,12 @@ mod tests { TestResult::discard() } else { let q = super::__udivdi3(n, d); - TestResult::from_bool(q == n / d) + + if let Some(udivdi3) = gcc_s::udivdi3() { + TestResult::from_bool(q == unsafe { udivdi3(n, d) }) + } else { + TestResult::from_bool(q == n / d) + } } } @@ -248,7 +254,12 @@ mod tests { TestResult::discard() } else { let r = super::__umoddi3(n, d); - TestResult::from_bool(r == n % d) + + if let Some(umoddi3) = gcc_s::umoddi3() { + TestResult::from_bool(r == unsafe { umoddi3(n, d) }) + } else { + TestResult::from_bool(r == n % d) + } } } @@ -259,7 +270,17 @@ mod tests { } else { let mut r = 0; let q = super::__udivmoddi4(n, d, Some(&mut r)); - TestResult::from_bool(q == n / d && r == n % d) + + if let Some(udivmoddi4) = gcc_s::udivmoddi4() { + let mut gcc_s_r = 0; + let gcc_s_q = unsafe { + udivmoddi4(n, d, Some(&mut gcc_s_r)) + }; + + TestResult::from_bool(q == gcc_s_q && r == gcc_s_r) + } else { + TestResult::from_bool(q == n / d && r == n % d) + } } } @@ -269,7 +290,12 @@ mod tests { TestResult::discard() } else { let q = super::__udivsi3(n, d); - TestResult::from_bool(q == n / d) + + if let Some(udivsi3) = gcc_s::udivsi3() { + TestResult::from_bool(q == unsafe { udivsi3(n, d) }) + } else { + TestResult::from_bool(q == n / d) + } } } @@ -279,7 +305,12 @@ mod tests { TestResult::discard() } else { let r = super::__umodsi3(n, d); - TestResult::from_bool(r == n % d) + + if let Some(umodsi3) = gcc_s::umodsi3() { + TestResult::from_bool(r == unsafe { umodsi3(n, d) }) + } else { + TestResult::from_bool(r == n % d) + } } } @@ -290,7 +321,17 @@ mod tests { } else { let mut r = 0; let q = super::__udivmodsi4(n, d, Some(&mut r)); - TestResult::from_bool(q == n / d && r == n % d) + + if let Some(udivmodsi4) = gcc_s::udivmodsi4() { + let mut gcc_s_r = 0; + let gcc_s_q = unsafe { + udivmodsi4(n, d, Some(&mut gcc_s_r)) + }; + + TestResult::from_bool(q == gcc_s_q && r == gcc_s_r) + } else { + TestResult::from_bool(q == n / d && r == n % d) + } } } } diff --git a/src/lib.rs b/src/lib.rs index 9efebcd..cba1604 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -17,6 +17,9 @@ extern crate quickcheck; #[cfg(test)] extern crate core; +#[cfg(test)] +extern crate gcc_s; + #[cfg(all(not(windows), not(target_os = "macos")))] extern crate rlibc; From 08c9ff730c649f88ae851ef7f5e1c3ff0298fa48 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Sat, 17 Sep 2016 19:54:29 -0500 Subject: [PATCH 2/6] osx: link to dylib, windows: always return None --- gcc_s/src/lib.rs | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/gcc_s/src/lib.rs b/gcc_s/src/lib.rs index b053a5b..fa034b0 100644 --- a/gcc_s/src/lib.rs +++ b/gcc_s/src/lib.rs @@ -8,17 +8,34 @@ use libloading::Library; static mut GCC_S: Option = None; +#[cfg(not(windows))] fn gcc_s() -> &'static Library { + #[cfg(not(target_os = "macos"))] + const LIBGCC_S: &'static str = "libgcc_s.so.1"; + + #[cfg(target_os = "macos")] + const LIBGCC_S: &'static str = "libgcc_s.1.dylib"; + unsafe { static INIT: Once = ONCE_INIT; INIT.call_once(|| { - GCC_S = Some(Library::new("libgcc_s.so.1").unwrap()); + GCC_S = Some(Library::new(LIBGCC_S).unwrap()); }); GCC_S.as_ref().unwrap() } } +#[cfg(windows)] +macro_rules! declare { + ($symbol:ident: fn($($i:ty),+) -> $o:ty) => { + pub fn $symbol() -> Option $o> { + None + } + } +} + +#[cfg(not(windows))] macro_rules! declare { ($symbol:ident: fn($($i:ty),+) -> $o:ty) => { pub fn $symbol() -> Option $o> { From 225d4c9d45e4268e78a4a5631666f78e21fd4792 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Sat, 17 Sep 2016 21:10:41 -0500 Subject: [PATCH 3/6] avoid division overflow in idivmod test --- src/arm.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/arm.rs b/src/arm.rs index b46b0ea..903672f 100644 --- a/src/arm.rs +++ b/src/arm.rs @@ -193,7 +193,7 @@ mod tests { fn idivmod(n: U32, d: U32) -> TestResult { let (n, d) = (n.0 as i32, d.0 as i32); - if d == 0 { + if d == 0 || (n == i32::min_value() && d == -1) { TestResult::discard() } else { let q: i32; From 337bd7e209866e816515b34bbb5f849f2fa08e13 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Wed, 21 Sep 2016 21:14:38 -0500 Subject: [PATCH 4/6] armhf: don't compare our impls against gcc_s --- Cargo.toml | 1 + build.rs | 7 +++++++ src/float/add.rs | 23 +++++++++++++++-------- 3 files changed, 23 insertions(+), 8 deletions(-) create mode 100644 build.rs diff --git a/Cargo.toml b/Cargo.toml index 229cec7..d378461 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,6 @@ [package] authors = ["Jorge Aparicio "] +build = "build.rs" name = "rustc_builtins" version = "0.1.0" diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..1ff0c06 --- /dev/null +++ b/build.rs @@ -0,0 +1,7 @@ +use std::env; + +fn main() { + if env::var("TARGET").unwrap().ends_with("hf") { + println!("cargo:rustc-cfg=gnueabihf") + } +} diff --git a/src/float/add.rs b/src/float/add.rs index 13c7aba..0943e2e 100644 --- a/src/float/add.rs +++ b/src/float/add.rs @@ -216,10 +216,15 @@ mod tests { let (a, b) = (f32::from_repr(a.0), f32::from_repr(b.0)); let x = super::__addsf3(a, b); - if let Some(addsf3) = gcc_s::addsf3() { - x.eq_repr(unsafe { addsf3(a, b) }) - } else { - x.eq_repr(a + b) + match gcc_s::addsf3() { + // NOTE(cfg) for some reason, on hard float targets, our implementation doesn't + // match the output of its gcc_s counterpart. Until we investigate further, we'll + // just avoid testing against gcc_s on those targets. Do note that our + // implementation matches the output of the FPU instruction on *hard* float targets + // and matches its gcc_s counterpart on *soft* float targets. + #[cfg(not(gnueabihf))] + Some(addsf3) => x.eq_repr(unsafe { addsf3(a, b) }), + _ => x.eq_repr(a + b), } } @@ -227,10 +232,12 @@ mod tests { let (a, b) = (f64::from_repr(a.0), f64::from_repr(b.0)); let x = super::__adddf3(a, b); - if let Some(adddf3) = gcc_s::adddf3() { - x.eq_repr(unsafe { adddf3(a, b) }) - } else { - x.eq_repr(a + b) + match gcc_s::adddf3() { + // NOTE(cfg) See NOTE above + #[cfg(not(gnueabihf))] + Some(adddf3) => x.eq_repr(unsafe { adddf3(a, b) }), + _ => x.eq_repr(a + b), + } } } From 384c48ce9bdcdf00e50906d70784f64d655b2e6a Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Wed, 21 Sep 2016 21:38:06 -0500 Subject: [PATCH 5/6] don't test always against gcc_s instead test half of the time against gcc_s and the other half test against the native operation (\*). (\*) Not all the targets have available a native version of the intrinsics under test. On those targets we'll end up testing our implementation against itself half of the time. This is not much of a problem because we do several quickcheck runs per intrinsic. --- Cargo.toml | 10 +++++-- src/float/add.rs | 10 ++++--- src/int/mul.rs | 45 +++++++++++++++-------------- src/int/sdiv.rs | 74 +++++++++++++++++++++++++++--------------------- src/int/shift.rs | 31 +++++++++++--------- src/int/udiv.rs | 74 +++++++++++++++++++++++++++--------------------- src/lib.rs | 3 ++ 7 files changed, 141 insertions(+), 106 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index d378461..e086f7c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,11 +5,17 @@ name = "rustc_builtins" version = "0.1.0" [dependencies] -rlibc = { git = "https://github.com/alexcrichton/rlibc", optional = true } + +[dependencies.rlibc] +git = "https://github.com/alexcrichton/rlibc" +optional = true [dev-dependencies] -gcc_s = { path = "gcc_s" } quickcheck = "0.3.1" +rand = "0.3.14" + +[dev-dependencies.gcc_s] +path = "gcc_s" [features] default = ["rlibc/weak"] diff --git a/src/float/add.rs b/src/float/add.rs index 0943e2e..14ff2f4 100644 --- a/src/float/add.rs +++ b/src/float/add.rs @@ -200,9 +200,11 @@ pub extern fn __aeabi_fadd(a: f32, b: f32) -> f32 { mod tests { use core::{f32, f64}; - use gcc_s; - use qc::{U32, U64}; use float::Float; + use qc::{U32, U64}; + + use gcc_s; + use rand; // NOTE The tests below have special handing for NaN values. // Because NaN != NaN, the floating-point representations must be used @@ -223,7 +225,7 @@ mod tests { // implementation matches the output of the FPU instruction on *hard* float targets // and matches its gcc_s counterpart on *soft* float targets. #[cfg(not(gnueabihf))] - Some(addsf3) => x.eq_repr(unsafe { addsf3(a, b) }), + Some(addsf3) if rand::random() => x.eq_repr(unsafe { addsf3(a, b) }), _ => x.eq_repr(a + b), } } @@ -235,7 +237,7 @@ mod tests { match gcc_s::adddf3() { // NOTE(cfg) See NOTE above #[cfg(not(gnueabihf))] - Some(adddf3) => x.eq_repr(unsafe { adddf3(a, b) }), + Some(adddf3) if rand::random() => x.eq_repr(unsafe { adddf3(a, b) }), _ => x.eq_repr(a + b), } diff --git a/src/int/mul.rs b/src/int/mul.rs index 4ea65bd..dea3499 100644 --- a/src/int/mul.rs +++ b/src/int/mul.rs @@ -72,18 +72,19 @@ mulo!(__mulodi4: i64); #[cfg(test)] mod tests { - use gcc_s; use qc::{I32, I64, U64}; + use gcc_s; + use rand; + quickcheck! { fn muldi(a: U64, b: U64) -> bool { let (a, b) = (a.0, b.0); let r = super::__muldi3(a, b); - if let Some(muldi3) = gcc_s::muldi3() { - r == unsafe { muldi3(a, b) } - } else { - r == a.wrapping_mul(b) + match gcc_s::muldi3() { + Some(muldi3) if rand::random() => r == unsafe { muldi3(a, b) }, + _ => r == a.wrapping_mul(b), } } @@ -95,15 +96,16 @@ mod tests { return false; } - if let Some(mulosi4) = gcc_s::mulosi4() { - let mut gcc_s_overflow = 2; - let gcc_s_r = unsafe { - mulosi4(a, b, &mut gcc_s_overflow) - }; + match gcc_s::mulosi4() { + Some(mulosi4) if rand::random() => { + let mut gcc_s_overflow = 2; + let gcc_s_r = unsafe { + mulosi4(a, b, &mut gcc_s_overflow) + }; - (r, overflow) == (gcc_s_r, gcc_s_overflow) - } else { - (r, overflow != 0) == a.overflowing_mul(b) + (r, overflow) == (gcc_s_r, gcc_s_overflow) + }, + _ => (r, overflow != 0) == a.overflowing_mul(b), } } @@ -115,15 +117,16 @@ mod tests { return false; } - if let Some(mulodi4) = gcc_s::mulodi4() { - let mut gcc_s_overflow = 2; - let gcc_s_r = unsafe { - mulodi4(a, b, &mut gcc_s_overflow) - }; + match gcc_s::mulodi4() { + Some(mulodi4) if rand::random() => { + let mut gcc_s_overflow = 2; + let gcc_s_r = unsafe { + mulodi4(a, b, &mut gcc_s_overflow) + }; - (r, overflow) == (gcc_s_r, gcc_s_overflow) - } else { - (r, overflow != 0) == a.overflowing_mul(b) + (r, overflow) == (gcc_s_r, gcc_s_overflow) + }, + _ => (r, overflow != 0) == a.overflowing_mul(b), } } } diff --git a/src/int/sdiv.rs b/src/int/sdiv.rs index 50ad0e0..fcb9ed9 100644 --- a/src/int/sdiv.rs +++ b/src/int/sdiv.rs @@ -52,9 +52,11 @@ divmod!(__divmoddi4, __divdi3: i64); #[cfg(test)] mod tests { + use qc::{U32, U64}; + use gcc_s; use quickcheck::TestResult; - use qc::{U32, U64}; + use rand; quickcheck!{ fn divdi3(n: U64, d: U64) -> TestResult { @@ -64,10 +66,11 @@ mod tests { } else { let q = super::__divdi3(n, d); - if let Some(divdi3) = gcc_s::divdi3() { - TestResult::from_bool(q == unsafe { divdi3(n, d) }) - } else { - TestResult::from_bool(q == n / d) + match gcc_s::divdi3() { + Some(divdi3) if rand::random() => { + TestResult::from_bool(q == unsafe { divdi3(n, d) }) + }, + _ => TestResult::from_bool(q == n / d), } } } @@ -79,10 +82,11 @@ mod tests { } else { let r = super::__moddi3(n, d); - if let Some(moddi3) = gcc_s::moddi3() { - TestResult::from_bool(r == unsafe { moddi3(n, d) }) - } else { - TestResult::from_bool(r == n % d) + match gcc_s::moddi3() { + Some(moddi3) if rand::random() => { + TestResult::from_bool(r == unsafe { moddi3(n, d) }) + }, + _ => TestResult::from_bool(r == n % d), } } } @@ -95,15 +99,16 @@ mod tests { let mut r = 0; let q = super::__divmoddi4(n, d, &mut r); - if let Some(divmoddi4) = gcc_s::divmoddi4() { - let mut gcc_s_r = 0; - let gcc_s_q = unsafe { - divmoddi4(n, d, &mut gcc_s_r) - }; + match gcc_s::divmoddi4() { + Some(divmoddi4) if rand::random() => { + let mut gcc_s_r = 0; + let gcc_s_q = unsafe { + divmoddi4(n, d, &mut gcc_s_r) + }; - TestResult::from_bool(q == gcc_s_q && r == gcc_s_r) - } else { - TestResult::from_bool(q == n / d && r == n % d) + TestResult::from_bool(q == gcc_s_q && r == gcc_s_r) + }, + _ => TestResult::from_bool(q == n / d && r == n % d), } } } @@ -115,10 +120,11 @@ mod tests { } else { let q = super::__divsi3(n, d); - if let Some(divsi3) = gcc_s::divsi3() { - TestResult::from_bool(q == unsafe { divsi3(n, d)}) - } else { - TestResult::from_bool(q == n / d) + match gcc_s::divsi3() { + Some(divsi3) if rand::random() => { + TestResult::from_bool(q == unsafe { divsi3(n, d)}) + }, + _ => TestResult::from_bool(q == n / d), } } } @@ -130,10 +136,11 @@ mod tests { } else { let r = super::__modsi3(n, d); - if let Some(modsi3) = gcc_s::modsi3() { - TestResult::from_bool(r == unsafe { modsi3(n, d) }) - } else { - TestResult::from_bool(r == n % d) + match gcc_s::modsi3() { + Some(modsi3) if rand::random() => { + TestResult::from_bool(r == unsafe { modsi3(n, d) }) + }, + _ => TestResult::from_bool(r == n % d), } } } @@ -146,15 +153,16 @@ mod tests { let mut r = 0; let q = super::__divmodsi4(n, d, &mut r); - if let Some(divmodsi4) = gcc_s::divmodsi4() { - let mut gcc_s_r = 0; - let gcc_s_q = unsafe { - divmodsi4(n, d, &mut gcc_s_r) - }; + match gcc_s::divmodsi4() { + Some(divmodsi4) if rand::random() => { + let mut gcc_s_r = 0; + let gcc_s_q = unsafe { + divmodsi4(n, d, &mut gcc_s_r) + }; - TestResult::from_bool(q == gcc_s_q && r == gcc_s_r) - } else { - TestResult::from_bool(q == n / d && r == n % d) + TestResult::from_bool(q == gcc_s_q && r == gcc_s_r) + }, + _ => TestResult::from_bool(q == n / d && r == n % d), } } } diff --git a/src/int/shift.rs b/src/int/shift.rs index c7be811..bafc9db 100644 --- a/src/int/shift.rs +++ b/src/int/shift.rs @@ -60,9 +60,11 @@ lshr!(__lshrdi3: u64); #[cfg(test)] mod tests { + use qc::{I64, U64}; + use gcc_s; use quickcheck::TestResult; - use qc::{I64, U64}; + use rand; // NOTE We purposefully stick to `u32` for `b` here because we want "small" values (b < 64) quickcheck! { @@ -73,10 +75,11 @@ mod tests { } else { let r = super::__ashldi3(a, b); - if let Some(ashldi3) = gcc_s::ashldi3() { - TestResult::from_bool(r == unsafe { ashldi3(a, b) }) - } else { - TestResult::from_bool(r == a << b) + match gcc_s::ashldi3() { + Some(ashldi3) if rand::random() => { + TestResult::from_bool(r == unsafe { ashldi3(a, b) }) + }, + _ => TestResult::from_bool(r == a << b), } } } @@ -88,10 +91,11 @@ mod tests { } else { let r = super::__ashrdi3(a, b); - if let Some(ashrdi3) = gcc_s::ashrdi3() { - TestResult::from_bool(r == unsafe { ashrdi3(a, b) }) - } else { - TestResult::from_bool(r == a >> b) + match gcc_s::ashrdi3() { + Some(ashrdi3) if rand::random() => { + TestResult::from_bool(r == unsafe { ashrdi3(a, b) }) + }, + _ => TestResult::from_bool(r == a >> b), } } } @@ -103,10 +107,11 @@ mod tests { } else { let r = super::__lshrdi3(a, b); - if let Some(lshrdi3) = gcc_s::lshrdi3() { - TestResult::from_bool(r == unsafe { lshrdi3(a, b) }) - } else { - TestResult::from_bool(r == a >> b) + match gcc_s::lshrdi3() { + Some(lshrdi3) if rand::random() => { + TestResult::from_bool(r == unsafe { lshrdi3(a, b) }) + }, + _ => TestResult::from_bool(r == a >> b), } } } diff --git a/src/int/udiv.rs b/src/int/udiv.rs index 8c9d06f..89793c8 100644 --- a/src/int/udiv.rs +++ b/src/int/udiv.rs @@ -228,9 +228,11 @@ pub extern "C" fn __udivmoddi4(n: u64, d: u64, rem: Option<&mut u64>) -> u64 { #[cfg(test)] mod tests { + use qc::{U32, U64}; + use gcc_s; use quickcheck::TestResult; - use qc::{U32, U64}; + use rand; quickcheck!{ fn udivdi3(n: U64, d: U64) -> TestResult { @@ -240,10 +242,11 @@ mod tests { } else { let q = super::__udivdi3(n, d); - if let Some(udivdi3) = gcc_s::udivdi3() { - TestResult::from_bool(q == unsafe { udivdi3(n, d) }) - } else { - TestResult::from_bool(q == n / d) + match gcc_s::udivdi3() { + Some(udivdi3) if rand::random() => { + TestResult::from_bool(q == unsafe { udivdi3(n, d) }) + }, + _ => TestResult::from_bool(q == n / d), } } } @@ -255,10 +258,11 @@ mod tests { } else { let r = super::__umoddi3(n, d); - if let Some(umoddi3) = gcc_s::umoddi3() { - TestResult::from_bool(r == unsafe { umoddi3(n, d) }) - } else { - TestResult::from_bool(r == n % d) + match gcc_s::umoddi3() { + Some(umoddi3) if rand::random() => { + TestResult::from_bool(r == unsafe { umoddi3(n, d) }) + }, + _ => TestResult::from_bool(r == n % d), } } } @@ -271,15 +275,16 @@ mod tests { let mut r = 0; let q = super::__udivmoddi4(n, d, Some(&mut r)); - if let Some(udivmoddi4) = gcc_s::udivmoddi4() { - let mut gcc_s_r = 0; - let gcc_s_q = unsafe { - udivmoddi4(n, d, Some(&mut gcc_s_r)) - }; + match gcc_s::udivmoddi4() { + Some(udivmoddi4) if rand::random() => { + let mut gcc_s_r = 0; + let gcc_s_q = unsafe { + udivmoddi4(n, d, Some(&mut gcc_s_r)) + }; - TestResult::from_bool(q == gcc_s_q && r == gcc_s_r) - } else { - TestResult::from_bool(q == n / d && r == n % d) + TestResult::from_bool(q == gcc_s_q && r == gcc_s_r) + }, + _ => TestResult::from_bool(q == n / d && r == n % d), } } } @@ -291,10 +296,11 @@ mod tests { } else { let q = super::__udivsi3(n, d); - if let Some(udivsi3) = gcc_s::udivsi3() { - TestResult::from_bool(q == unsafe { udivsi3(n, d) }) - } else { - TestResult::from_bool(q == n / d) + match gcc_s::udivsi3() { + Some(udivsi3) if rand::random() => { + TestResult::from_bool(q == unsafe { udivsi3(n, d) }) + }, + _ => TestResult::from_bool(q == n / d), } } } @@ -306,10 +312,11 @@ mod tests { } else { let r = super::__umodsi3(n, d); - if let Some(umodsi3) = gcc_s::umodsi3() { - TestResult::from_bool(r == unsafe { umodsi3(n, d) }) - } else { - TestResult::from_bool(r == n % d) + match gcc_s::umodsi3() { + Some(umodsi3) if rand::random() => { + TestResult::from_bool(r == unsafe { umodsi3(n, d) }) + }, + _ => TestResult::from_bool(r == n % d), } } } @@ -322,15 +329,16 @@ mod tests { let mut r = 0; let q = super::__udivmodsi4(n, d, Some(&mut r)); - if let Some(udivmodsi4) = gcc_s::udivmodsi4() { - let mut gcc_s_r = 0; - let gcc_s_q = unsafe { - udivmodsi4(n, d, Some(&mut gcc_s_r)) - }; + match gcc_s::udivmodsi4() { + Some(udivmodsi4) if rand::random() => { + let mut gcc_s_r = 0; + let gcc_s_q = unsafe { + udivmodsi4(n, d, Some(&mut gcc_s_r)) + }; - TestResult::from_bool(q == gcc_s_q && r == gcc_s_r) - } else { - TestResult::from_bool(q == n / d && r == n % d) + TestResult::from_bool(q == gcc_s_q && r == gcc_s_r) + }, + _ => TestResult::from_bool(q == n / d && r == n % d), } } } diff --git a/src/lib.rs b/src/lib.rs index cba1604..88bbbec 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -20,6 +20,9 @@ extern crate core; #[cfg(test)] extern crate gcc_s; +#[cfg(test)] +extern crate rand; + #[cfg(all(not(windows), not(target_os = "macos")))] extern crate rlibc; From dafe47bc2ba8715f8379c07dcbd9654dd541f187 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Thu, 22 Sep 2016 11:56:34 -0500 Subject: [PATCH 6/6] fix build.rs we don't want to match musleabihf targets --- build.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.rs b/build.rs index 1ff0c06..298b656 100644 --- a/build.rs +++ b/build.rs @@ -1,7 +1,7 @@ use std::env; fn main() { - if env::var("TARGET").unwrap().ends_with("hf") { + if env::var("TARGET").unwrap().ends_with("gnueabihf") { println!("cargo:rustc-cfg=gnueabihf") } }