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
This commit is contained in:
parent
9d74cf08b8
commit
9493c37455
|
@ -7,7 +7,10 @@ version = "0.1.0"
|
||||||
rlibc = { git = "https://github.com/alexcrichton/rlibc", optional = true }
|
rlibc = { git = "https://github.com/alexcrichton/rlibc", optional = true }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
|
gcc_s = { path = "gcc_s" }
|
||||||
quickcheck = "0.3.1"
|
quickcheck = "0.3.1"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["rlibc/weak"]
|
default = ["rlibc/weak"]
|
||||||
|
|
||||||
|
[workspace]
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
[package]
|
||||||
|
authors = ["Jorge Aparicio <japaricious@gmail.com>"]
|
||||||
|
name = "gcc_s"
|
||||||
|
version = "0.1.0"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
libloading = "0.3.0"
|
|
@ -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<Library> = 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<unsafe extern fn($($i),+) -> $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);
|
|
@ -199,6 +199,8 @@ pub extern fn __aeabi_fadd(a: f32, b: f32) -> f32 {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use core::{f32, f64};
|
use core::{f32, f64};
|
||||||
|
|
||||||
|
use gcc_s;
|
||||||
use qc::{U32, U64};
|
use qc::{U32, U64};
|
||||||
use float::Float;
|
use float::Float;
|
||||||
|
|
||||||
|
@ -213,15 +215,23 @@ mod tests {
|
||||||
fn addsf3(a: U32, b: U32) -> bool {
|
fn addsf3(a: U32, b: U32) -> bool {
|
||||||
let (a, b) = (f32::from_repr(a.0), f32::from_repr(b.0));
|
let (a, b) = (f32::from_repr(a.0), f32::from_repr(b.0));
|
||||||
let x = super::__addsf3(a, b);
|
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 {
|
fn adddf3(a: U64, b: U64) -> bool {
|
||||||
let (a, b) = (f64::from_repr(a.0), f64::from_repr(b.0));
|
let (a, b) = (f64::from_repr(a.0), f64::from_repr(b.0));
|
||||||
let x = super::__adddf3(a, b);
|
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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -72,13 +72,19 @@ mulo!(__mulodi4: i64);
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
use gcc_s;
|
||||||
use qc::{I32, I64, U64};
|
use qc::{I32, I64, U64};
|
||||||
|
|
||||||
quickcheck! {
|
quickcheck! {
|
||||||
fn muldi(a: U64, b: U64) -> bool {
|
fn muldi(a: U64, b: U64) -> bool {
|
||||||
let (a, b) = (a.0, b.0);
|
let (a, b) = (a.0, b.0);
|
||||||
let r = super::__muldi3(a, b);
|
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 {
|
fn mulosi(a: I32, b: I32) -> bool {
|
||||||
|
@ -88,7 +94,17 @@ mod tests {
|
||||||
if overflow != 0 && overflow != 1 {
|
if overflow != 0 && overflow != 1 {
|
||||||
return false;
|
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 {
|
fn mulodi(a: I64, b: I64) -> bool {
|
||||||
|
@ -98,7 +114,17 @@ mod tests {
|
||||||
if overflow != 0 && overflow != 1 {
|
if overflow != 0 && overflow != 1 {
|
||||||
return false;
|
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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,6 +52,7 @@ divmod!(__divmoddi4, __divdi3: i64);
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
use gcc_s;
|
||||||
use quickcheck::TestResult;
|
use quickcheck::TestResult;
|
||||||
use qc::{U32, U64};
|
use qc::{U32, U64};
|
||||||
|
|
||||||
|
@ -62,7 +63,12 @@ mod tests {
|
||||||
TestResult::discard()
|
TestResult::discard()
|
||||||
} else {
|
} else {
|
||||||
let q = super::__divdi3(n, d);
|
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()
|
TestResult::discard()
|
||||||
} else {
|
} else {
|
||||||
let r = super::__moddi3(n, d);
|
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 {
|
} else {
|
||||||
let mut r = 0;
|
let mut r = 0;
|
||||||
let q = super::__divmoddi4(n, d, &mut r);
|
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()
|
TestResult::discard()
|
||||||
} else {
|
} else {
|
||||||
let q = super::__divsi3(n, d);
|
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()
|
TestResult::discard()
|
||||||
} else {
|
} else {
|
||||||
let r = super::__modsi3(n, d);
|
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 {
|
} else {
|
||||||
let mut r = 0;
|
let mut r = 0;
|
||||||
let q = super::__divmodsi4(n, d, &mut r);
|
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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,6 +60,7 @@ lshr!(__lshrdi3: u64);
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
use gcc_s;
|
||||||
use quickcheck::TestResult;
|
use quickcheck::TestResult;
|
||||||
use qc::{I64, U64};
|
use qc::{I64, U64};
|
||||||
|
|
||||||
|
@ -71,7 +72,12 @@ mod tests {
|
||||||
TestResult::discard()
|
TestResult::discard()
|
||||||
} else {
|
} else {
|
||||||
let r = super::__ashldi3(a, b);
|
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()
|
TestResult::discard()
|
||||||
} else {
|
} else {
|
||||||
let r = super::__ashrdi3(a, b);
|
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()
|
TestResult::discard()
|
||||||
} else {
|
} else {
|
||||||
let r = super::__lshrdi3(a, b);
|
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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -228,6 +228,7 @@ pub extern "C" fn __udivmoddi4(n: u64, d: u64, rem: Option<&mut u64>) -> u64 {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
use gcc_s;
|
||||||
use quickcheck::TestResult;
|
use quickcheck::TestResult;
|
||||||
use qc::{U32, U64};
|
use qc::{U32, U64};
|
||||||
|
|
||||||
|
@ -238,7 +239,12 @@ mod tests {
|
||||||
TestResult::discard()
|
TestResult::discard()
|
||||||
} else {
|
} else {
|
||||||
let q = super::__udivdi3(n, d);
|
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()
|
TestResult::discard()
|
||||||
} else {
|
} else {
|
||||||
let r = super::__umoddi3(n, d);
|
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 {
|
} else {
|
||||||
let mut r = 0;
|
let mut r = 0;
|
||||||
let q = super::__udivmoddi4(n, d, Some(&mut r));
|
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()
|
TestResult::discard()
|
||||||
} else {
|
} else {
|
||||||
let q = super::__udivsi3(n, d);
|
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()
|
TestResult::discard()
|
||||||
} else {
|
} else {
|
||||||
let r = super::__umodsi3(n, d);
|
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 {
|
} else {
|
||||||
let mut r = 0;
|
let mut r = 0;
|
||||||
let q = super::__udivmodsi4(n, d, Some(&mut r));
|
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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,9 @@ extern crate quickcheck;
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
extern crate core;
|
extern crate core;
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
extern crate gcc_s;
|
||||||
|
|
||||||
#[cfg(all(not(windows), not(target_os = "macos")))]
|
#[cfg(all(not(windows), not(target_os = "macos")))]
|
||||||
extern crate rlibc;
|
extern crate rlibc;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue