From dfa7b161aa197f99ab0f9b74fbaa008d7371e488 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Tue, 7 Feb 2017 09:41:26 -0500 Subject: [PATCH 1/3] use AAPCS calling convention on all aeabi intrinsics also, on ARM, inline(always) the actual implementation of the intrinsics so we end with code like this: ``` 00000000 <__aeabi_dadd>: (implementation here) ``` instead of "trampolines" like this: ``` 00000000 <__aeabi_dadd>: (shuffle registers) (call __adddf3) 00000000 <__adddf3>: (implementation here) ``` closes #116 --- src/arm.rs | 40 ++++++++++++++++++++-------------------- src/float/add.rs | 3 ++- src/int/mul.rs | 3 ++- src/int/sdiv.rs | 3 ++- src/int/shift.rs | 4 ++++ src/int/udiv.rs | 3 ++- src/lib.rs | 4 ++++ 7 files changed, 36 insertions(+), 24 deletions(-) diff --git a/src/arm.rs b/src/arm.rs index 345ff24..67947a1 100644 --- a/src/arm.rs +++ b/src/arm.rs @@ -62,44 +62,44 @@ pub unsafe fn __aeabi_ldivmod() { // TODO: These aeabi_* functions should be defined as aliases #[cfg_attr(not(test), no_mangle)] -pub extern "C" fn __aeabi_dadd(a: f64, b: f64) -> f64 { +pub extern "aapcs" fn __aeabi_dadd(a: f64, b: f64) -> f64 { ::float::add::__adddf3(a, b) } #[cfg_attr(not(test), no_mangle)] -pub extern "C" fn __aeabi_fadd(a: f32, b: f32) -> f32 { +pub extern "aapcs" fn __aeabi_fadd(a: f32, b: f32) -> f32 { ::float::add::__addsf3(a, b) } #[cfg(not(all(feature = "c", target_arch = "arm", not(target_os = "ios"), not(thumbv6m))))] #[cfg_attr(not(test), no_mangle)] -pub extern "C" fn __aeabi_idiv(a: i32, b: i32) -> i32 { +pub extern "aapcs" fn __aeabi_idiv(a: i32, b: i32) -> i32 { ::int::sdiv::__divsi3(a, b) } #[cfg_attr(not(test), no_mangle)] -pub extern "C" fn __aeabi_lasr(a: i64, b: u32) -> i64 { +pub extern "aapcs" fn __aeabi_lasr(a: i64, b: u32) -> i64 { ::int::shift::__ashrdi3(a, b) } #[cfg_attr(not(test), no_mangle)] -pub extern "C" fn __aeabi_llsl(a: u64, b: u32) -> u64 { +pub extern "aapcs" fn __aeabi_llsl(a: u64, b: u32) -> u64 { ::int::shift::__ashldi3(a, b) } #[cfg_attr(not(test), no_mangle)] -pub extern "C" fn __aeabi_llsr(a: u64, b: u32) -> u64 { +pub extern "aapcs" fn __aeabi_llsr(a: u64, b: u32) -> u64 { ::int::shift::__lshrdi3(a, b) } #[cfg_attr(not(test), no_mangle)] -pub extern "C" fn __aeabi_lmul(a: u64, b: u64) -> u64 { +pub extern "aapcs" fn __aeabi_lmul(a: u64, b: u64) -> u64 { ::int::mul::__muldi3(a, b) } #[cfg(not(all(feature = "c", target_arch = "arm", not(target_os = "ios"), not(thumbv6m))))] #[cfg_attr(not(test), no_mangle)] -pub extern "C" fn __aeabi_uidiv(a: u32, b: u32) -> u32 { +pub extern "aapcs" fn __aeabi_uidiv(a: u32, b: u32) -> u32 { ::int::udiv::__udivsi3(a, b) } @@ -113,55 +113,55 @@ extern "C" { // FIXME: The `*4` and `*8` variants should be defined as aliases. #[cfg_attr(not(test), no_mangle)] -pub unsafe extern "C" fn __aeabi_memcpy(dest: *mut u8, src: *const u8, n: usize) { +pub unsafe extern "aapcs" fn __aeabi_memcpy(dest: *mut u8, src: *const u8, n: usize) { memcpy(dest, src, n); } #[cfg_attr(not(test), no_mangle)] -pub unsafe extern "C" fn __aeabi_memcpy4(dest: *mut u8, src: *const u8, n: usize) { +pub unsafe extern "aapcs" fn __aeabi_memcpy4(dest: *mut u8, src: *const u8, n: usize) { memcpy(dest, src, n); } #[cfg_attr(not(test), no_mangle)] -pub unsafe extern "C" fn __aeabi_memcpy8(dest: *mut u8, src: *const u8, n: usize) { +pub unsafe extern "aapcs" fn __aeabi_memcpy8(dest: *mut u8, src: *const u8, n: usize) { memcpy(dest, src, n); } #[cfg_attr(not(test), no_mangle)] -pub unsafe extern "C" fn __aeabi_memmove(dest: *mut u8, src: *const u8, n: usize) { +pub unsafe extern "aapcs" fn __aeabi_memmove(dest: *mut u8, src: *const u8, n: usize) { memmove(dest, src, n); } #[cfg_attr(not(test), no_mangle)] -pub unsafe extern "C" fn __aeabi_memmove4(dest: *mut u8, src: *const u8, n: usize) { +pub unsafe extern "aapcs" fn __aeabi_memmove4(dest: *mut u8, src: *const u8, n: usize) { memmove(dest, src, n); } #[cfg_attr(not(test), no_mangle)] -pub unsafe extern "C" fn __aeabi_memmove8(dest: *mut u8, src: *const u8, n: usize) { +pub unsafe extern "aapcs" fn __aeabi_memmove8(dest: *mut u8, src: *const u8, n: usize) { memmove(dest, src, n); } // Note the different argument order #[cfg_attr(not(test), no_mangle)] -pub unsafe extern "C" fn __aeabi_memset(dest: *mut u8, n: usize, c: i32) { +pub unsafe extern "aapcs" fn __aeabi_memset(dest: *mut u8, n: usize, c: i32) { memset(dest, c, n); } #[cfg_attr(not(test), no_mangle)] -pub unsafe extern "C" fn __aeabi_memset4(dest: *mut u8, n: usize, c: i32) { +pub unsafe extern "aapcs" fn __aeabi_memset4(dest: *mut u8, n: usize, c: i32) { memset(dest, c, n); } #[cfg_attr(not(test), no_mangle)] -pub unsafe extern "C" fn __aeabi_memset8(dest: *mut u8, n: usize, c: i32) { +pub unsafe extern "aapcs" fn __aeabi_memset8(dest: *mut u8, n: usize, c: i32) { memset(dest, c, n); } #[cfg_attr(not(test), no_mangle)] -pub unsafe extern "C" fn __aeabi_memclr(dest: *mut u8, n: usize) { +pub unsafe extern "aapcs" fn __aeabi_memclr(dest: *mut u8, n: usize) { memset(dest, 0, n); } #[cfg_attr(not(test), no_mangle)] -pub unsafe extern "C" fn __aeabi_memclr4(dest: *mut u8, n: usize) { +pub unsafe extern "aapcs" fn __aeabi_memclr4(dest: *mut u8, n: usize) { memset(dest, 0, n); } #[cfg_attr(not(test), no_mangle)] -pub unsafe extern "C" fn __aeabi_memclr8(dest: *mut u8, n: usize) { +pub unsafe extern "aapcs" fn __aeabi_memclr8(dest: *mut u8, n: usize) { memset(dest, 0, n); } diff --git a/src/float/add.rs b/src/float/add.rs index 0b2490a..8bb5b4b 100644 --- a/src/float/add.rs +++ b/src/float/add.rs @@ -7,7 +7,8 @@ macro_rules! add { ($intrinsic:ident: $ty:ty) => { /// Returns `a + b` #[allow(unused_parens)] - #[cfg_attr(not(test), no_mangle)] + #[cfg_attr(all(not(test), not(target_arch = "arm")), no_mangle)] + #[cfg_attr(all(not(test), target_arch = "arm"), inline(always))] pub extern fn $intrinsic(a: $ty, b: $ty) -> $ty { let one = Wrapping(1 as <$ty as Float>::Int); let zero = Wrapping(0 as <$ty as Float>::Int); diff --git a/src/int/mul.rs b/src/int/mul.rs index 27709e5..046382a 100644 --- a/src/int/mul.rs +++ b/src/int/mul.rs @@ -4,7 +4,8 @@ use int::Int; macro_rules! mul { ($intrinsic:ident: $ty:ty) => { /// Returns `a * b` - #[cfg_attr(not(test), no_mangle)] + #[cfg_attr(all(not(test), not(target_arch = "arm")), no_mangle)] + #[cfg_attr(all(not(test), target_arch = "arm"), inline(always))] pub extern "C" fn $intrinsic(a: $ty, b: $ty) -> $ty { let half_bits = <$ty>::bits() / 4; let lower_mask = !0 >> half_bits; diff --git a/src/int/sdiv.rs b/src/int/sdiv.rs index 023fad4..2676428 100644 --- a/src/int/sdiv.rs +++ b/src/int/sdiv.rs @@ -42,7 +42,8 @@ macro_rules! mod_ { macro_rules! divmod { ($intrinsic:ident, $div:ident: $ty:ty) => { /// Returns `a / b` and sets `*rem = n % d` - #[cfg_attr(not(test), no_mangle)] + #[cfg_attr(all(not(test), not(target_arch = "arm")), no_mangle)] + #[cfg_attr(all(not(test), target_arch = "arm"), inline(always))] pub extern "C" fn $intrinsic(a: $ty, b: $ty, rem: &mut $ty) -> $ty { #[cfg(all(feature = "c", any(target_arch = "x86")))] extern { diff --git a/src/int/shift.rs b/src/int/shift.rs index e5dc38f..b93b7bf 100644 --- a/src/int/shift.rs +++ b/src/int/shift.rs @@ -4,6 +4,8 @@ macro_rules! ashl { ($intrinsic:ident: $ty:ty) => { /// Returns `a << b`, requires `b < $ty::bits()` #[cfg_attr(not(test), no_mangle)] + #[cfg_attr(all(not(test), not(target_arch = "arm")), no_mangle)] + #[cfg_attr(all(not(test), target_arch = "arm"), inline(always))] pub extern "C" fn $intrinsic(a: $ty, b: u32) -> $ty { let half_bits = <$ty>::bits() / 2; if b & half_bits != 0 { @@ -21,6 +23,8 @@ macro_rules! ashr { ($intrinsic:ident: $ty:ty) => { /// Returns arithmetic `a >> b`, requires `b < $ty::bits()` #[cfg_attr(not(test), no_mangle)] + #[cfg_attr(all(not(test), not(target_arch = "arm")), no_mangle)] + #[cfg_attr(all(not(test), target_arch = "arm"), inline(always))] pub extern "C" fn $intrinsic(a: $ty, b: u32) -> $ty { let half_bits = <$ty>::bits() / 2; if b & half_bits != 0 { diff --git a/src/int/udiv.rs b/src/int/udiv.rs index 57d5fe5..820c4cf 100644 --- a/src/int/udiv.rs +++ b/src/int/udiv.rs @@ -3,7 +3,8 @@ use int::{Int, LargeInt}; /// Returns `n / d` #[cfg(not(all(feature = "c", target_arch = "arm", not(target_os = "ios"), not(thumbv6m))))] -#[cfg_attr(not(test), no_mangle)] +#[cfg_attr(all(not(test), not(target_arch = "arm")), no_mangle)] +#[cfg_attr(all(not(test), target_arch = "arm"), inline(always))] pub extern "C" fn __udivsi3(n: u32, d: u32) -> u32 { // Special cases if d == 0 { diff --git a/src/lib.rs b/src/lib.rs index 0a80ad2..0da336e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -28,6 +28,10 @@ // NOTE cfg(all(feature = "c", ..)) indicate that compiler-rt provides an arch optimized // implementation of that intrinsic and we'll prefer to use that +// NOTE(aapcs, aeabi, arm) ARM targets use intrinsics named __aeabi_* instead of the intrinsics +// that follow "x86 naming convention" (e.g. addsf3). Those aeabi intrinsics must adhere to the +// AAPCS calling convention (`extern "aapcs"`) because that's how LLVM will call them. + // TODO(rust-lang/rust#37029) use e.g. checked_div(_).unwrap_or_else(|| abort()) macro_rules! udiv { ($a:expr, $b:expr) => { From 57085be2ead77399202f8151e7233c3eb218ecb3 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Tue, 7 Feb 2017 12:51:18 -0500 Subject: [PATCH 2/3] ARM: keep some non-aeabi symbols around - multi3: there's no aeabi equivalent - divmod{s,d}i4: these are directly called by __aeabi_{l,i}divmod - add{s,d}f3: required by the C sub{s,d}f3 implementation but make sure they also use the AAPCS calling convention --- src/float/add.rs | 20 ++++++++++++++------ src/int/mul.rs | 20 ++++++++++++++------ src/int/sdiv.rs | 15 +++++++++------ src/int/udiv.rs | 6 +++--- 4 files changed, 40 insertions(+), 21 deletions(-) diff --git a/src/float/add.rs b/src/float/add.rs index 8bb5b4b..65a7186 100644 --- a/src/float/add.rs +++ b/src/float/add.rs @@ -4,12 +4,11 @@ use core::num::Wrapping; use float::Float; macro_rules! add { - ($intrinsic:ident: $ty:ty) => { + ($abi:tt, $intrinsic:ident: $ty:ty) => { /// Returns `a + b` #[allow(unused_parens)] - #[cfg_attr(all(not(test), not(target_arch = "arm")), no_mangle)] - #[cfg_attr(all(not(test), target_arch = "arm"), inline(always))] - pub extern fn $intrinsic(a: $ty, b: $ty) -> $ty { + #[cfg_attr(not(test), no_mangle)] + pub extern $abi fn $intrinsic(a: $ty, b: $ty) -> $ty { let one = Wrapping(1 as <$ty as Float>::Int); let zero = Wrapping(0 as <$ty as Float>::Int); @@ -182,8 +181,17 @@ macro_rules! add { } } -add!(__addsf3: f32); -add!(__adddf3: f64); +#[cfg(target_arch = "arm")] +add!("aapcs", __addsf3: f32); + +#[cfg(not(target_arch = "arm"))] +add!("C", __addsf3: f32); + +#[cfg(target_arch = "arm")] +add!("aapcs", __adddf3: f64); + +#[cfg(not(target_arch = "arm"))] +add!("C", __adddf3: f64); // NOTE(cfg) for some reason, on arm*-unknown-linux-gnueabi*, our implementation doesn't // match the output of its gcc_s or compiler-rt counterpart. Until we investigate further, we'll diff --git a/src/int/mul.rs b/src/int/mul.rs index 046382a..64ceb72 100644 --- a/src/int/mul.rs +++ b/src/int/mul.rs @@ -2,11 +2,11 @@ use int::LargeInt; use int::Int; macro_rules! mul { - ($intrinsic:ident: $ty:ty) => { + ($(#[$attr:meta])+ | + $abi:tt, $intrinsic:ident: $ty:ty) => { /// Returns `a * b` - #[cfg_attr(all(not(test), not(target_arch = "arm")), no_mangle)] - #[cfg_attr(all(not(test), target_arch = "arm"), inline(always))] - pub extern "C" fn $intrinsic(a: $ty, b: $ty) -> $ty { + $(#[$attr])+ + pub extern $abi fn $intrinsic(a: $ty, b: $ty) -> $ty { let half_bits = <$ty>::bits() / 4; let lower_mask = !0 >> half_bits; let mut low = (a.low() & lower_mask).wrapping_mul(b.low() & lower_mask); @@ -74,9 +74,17 @@ macro_rules! mulo { } #[cfg(not(all(feature = "c", target_arch = "x86")))] -mul!(__muldi3: u64); +mul!(#[cfg_attr(all(not(test), not(target_arch = "arm")), no_mangle)] + #[cfg_attr(all(not(test), target_arch = "arm"), inline(always))] + | "C", __muldi3: u64); -mul!(__multi3: i128); +#[cfg(not(target_arch = "arm"))] +mul!(#[cfg_attr(not(test), no_mangle)] + | "C", __multi3: i128); + +#[cfg(target_arch = "arm")] +mul!(#[cfg_attr(not(test), no_mangle)] + | "aapcs", __multi3: i128); mulo!(__mulosi4: i32); mulo!(__mulodi4: i64); diff --git a/src/int/sdiv.rs b/src/int/sdiv.rs index 2676428..7a3e6e7 100644 --- a/src/int/sdiv.rs +++ b/src/int/sdiv.rs @@ -40,11 +40,10 @@ macro_rules! mod_ { } macro_rules! divmod { - ($intrinsic:ident, $div:ident: $ty:ty) => { + ($abi:tt, $intrinsic:ident, $div:ident: $ty:ty) => { /// Returns `a / b` and sets `*rem = n % d` - #[cfg_attr(all(not(test), not(target_arch = "arm")), no_mangle)] - #[cfg_attr(all(not(test), target_arch = "arm"), inline(always))] - pub extern "C" fn $intrinsic(a: $ty, b: $ty, rem: &mut $ty) -> $ty { + #[cfg_attr(not(test), no_mangle)] + pub extern $abi fn $intrinsic(a: $ty, b: $ty, rem: &mut $ty) -> $ty { #[cfg(all(feature = "c", any(target_arch = "x86")))] extern { fn $div(a: $ty, b: $ty) -> $ty; @@ -87,9 +86,13 @@ mod_!(__modti3: i128, u128); mod_!(__modti3: i128, u128, ::U64x2, ::sconv); #[cfg(not(all(feature = "c", target_arch = "arm", not(target_os = "ios"))))] -divmod!(__divmodsi4, __divsi3: i32); +divmod!("C", __divmodsi4, __divsi3: i32); -divmod!(__divmoddi4, __divdi3: i64); +#[cfg(target_arch = "arm")] +divmod!("aapcs", __divmoddi4, __divdi3: i64); + +#[cfg(not(target_arch = "arm"))] +divmod!("C", __divmoddi4, __divdi3: i64); #[cfg(test)] mod tests { diff --git a/src/int/udiv.rs b/src/int/udiv.rs index 820c4cf..453ab00 100644 --- a/src/int/udiv.rs +++ b/src/int/udiv.rs @@ -80,15 +80,15 @@ pub extern "C" fn __umodsi3(n: u32, d: u32) -> u32 { #[cfg(not(all(feature = "c", target_arch = "arm", not(target_os = "ios"), not(thumbv6m))))] #[cfg_attr(not(test), no_mangle)] pub extern "C" fn __udivmodsi4(n: u32, d: u32, rem: Option<&mut u32>) -> u32 { - #[cfg(all(feature = "c", target_arch = "arm", not(target_os = "ios")))] + #[cfg(all(feature = "c", target_arch = "arm", not(target_os = "ios"), not(thumbv6m)))] extern "C" { fn __udivsi3(n: u32, d: u32) -> u32; } let q = match () { - #[cfg(all(feature = "c", target_arch = "arm", not(target_os = "ios")))] + #[cfg(all(feature = "c", target_arch = "arm", not(target_os = "ios"), not(thumbv6m)))] () => unsafe { __udivsi3(n, d) }, - #[cfg(not(all(feature = "c", target_arch = "arm", not(target_os = "ios"))))] + #[cfg(not(all(feature = "c", target_arch = "arm", not(target_os = "ios"), not(thumbv6m))))] () => __udivsi3(n, d), }; if let Some(rem) = rem { From 47b45d1d62ab57d65ee3bf2e2fbf5678e87a3d90 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Tue, 7 Feb 2017 23:07:51 -0500 Subject: [PATCH 3/3] adjust the check! macro to accept AAPCS intrinsics --- src/float/add.rs | 4 ++-- src/float/pow.rs | 4 ++-- src/int/mul.rs | 10 +++++----- src/int/sdiv.rs | 31 +++++++++++++++++++++++-------- src/int/shift.rs | 12 ++++++------ src/int/udiv.rs | 18 +++++++++--------- src/qc.rs | 7 +++++-- 7 files changed, 52 insertions(+), 34 deletions(-) diff --git a/src/float/add.rs b/src/float/add.rs index 65a7186..992d149 100644 --- a/src/float/add.rs +++ b/src/float/add.rs @@ -203,14 +203,14 @@ mod tests { use qc::{F32, F64}; check! { - fn __addsf3(f: extern fn(f32, f32) -> f32, + fn __addsf3(f: extern "C" fn(f32, f32) -> f32, a: F32, b: F32) -> Option { Some(F32(f(a.0, b.0))) } - fn __adddf3(f: extern fn(f64, f64) -> f64, + fn __adddf3(f: extern "C" fn(f64, f64) -> f64, a: F64, b: F64) -> Option { Some(F64(f(a.0, b.0))) diff --git a/src/float/pow.rs b/src/float/pow.rs index 290d0f5..52aba5d 100644 --- a/src/float/pow.rs +++ b/src/float/pow.rs @@ -34,13 +34,13 @@ mod tests { use qc::{I32, F32, F64}; check! { - fn __powisf2(f: extern fn(f32, i32) -> f32, + fn __powisf2(f: extern "C" fn(f32, i32) -> f32, a: F32, b: I32) -> Option { Some(F32(f(a.0, b.0))) } - fn __powidf2(f: extern fn(f64, i32) -> f64, + fn __powidf2(f: extern "C" fn(f64, i32) -> f64, a: F64, b: I32) -> Option { Some(F64(f(a.0, b.0))) diff --git a/src/int/mul.rs b/src/int/mul.rs index 64ceb72..7b0d033 100644 --- a/src/int/mul.rs +++ b/src/int/mul.rs @@ -99,12 +99,12 @@ mod tests { use qc::{I32, I64, U64}; check! { - fn __muldi3(f: extern fn(u64, u64) -> u64, a: U64, b: U64) + fn __muldi3(f: extern "C" fn(u64, u64) -> u64, a: U64, b: U64) -> Option { Some(f(a.0, b.0)) } - fn __mulosi4(f: extern fn(i32, i32, &mut i32) -> i32, + fn __mulosi4(f: extern "C" fn(i32, i32, &mut i32) -> i32, a: I32, b: I32) -> Option<(i32, i32)> { let (a, b) = (a.0, b.0); @@ -116,7 +116,7 @@ mod tests { Some((r, overflow)) } - fn __mulodi4(f: extern fn(i64, i64, &mut i32) -> i64, + fn __mulodi4(f: extern "C" fn(i64, i64, &mut i32) -> i64, a: I64, b: I64) -> Option<(i64, i32)> { let (a, b) = (a.0, b.0); @@ -139,11 +139,11 @@ mod tests_i128 { use qc::I128; check! { - fn __multi3(f: extern fn(i128, i128) -> i128, a: I128, b: I128) + fn __multi3(f: extern "C" fn(i128, i128) -> i128, a: I128, b: I128) -> Option { Some(f(a.0, b.0)) } - fn __muloti4(f: extern fn(i128, i128, &mut i32) -> i128, + fn __muloti4(f: extern "C" fn(i128, i128, &mut i32) -> i128, a: I128, b: I128) -> Option<(i128, i32)> { let (a, b) = (a.0, b.0); diff --git a/src/int/sdiv.rs b/src/int/sdiv.rs index 7a3e6e7..51d9c37 100644 --- a/src/int/sdiv.rs +++ b/src/int/sdiv.rs @@ -99,7 +99,7 @@ mod tests { use qc::{U32, U64}; check! { - fn __divdi3(f: extern fn(i64, i64) -> i64, n: U64, d: U64) -> Option { + fn __divdi3(f: extern "C" fn(i64, i64) -> i64, n: U64, d: U64) -> Option { let (n, d) = (n.0 as i64, d.0 as i64); if d == 0 { None @@ -108,7 +108,7 @@ mod tests { } } - fn __moddi3(f: extern fn(i64, i64) -> i64, n: U64, d: U64) -> Option { + fn __moddi3(f: extern "C" fn(i64, i64) -> i64, n: U64, d: U64) -> Option { let (n, d) = (n.0 as i64, d.0 as i64); if d == 0 { None @@ -117,7 +117,8 @@ mod tests { } } - fn __divmoddi4(f: extern fn(i64, i64, &mut i64) -> i64, + #[cfg(target_arch = "arm")] + fn __divmoddi4(f: extern "aapcs" fn(i64, i64, &mut i64) -> i64, n: U64, d: U64) -> Option<(i64, i64)> { let (n, d) = (n.0 as i64, d.0 as i64); @@ -130,7 +131,21 @@ mod tests { } } - fn __divsi3(f: extern fn(i32, i32) -> i32, + #[cfg(not(target_arch = "arm"))] + fn __divmoddi4(f: extern "C" fn(i64, i64, &mut i64) -> i64, + n: U64, + d: U64) -> Option<(i64, i64)> { + let (n, d) = (n.0 as i64, d.0 as i64); + if d == 0 { + None + } else { + let mut r = 0; + let q = f(n, d, &mut r); + Some((q, r)) + } + } + + fn __divsi3(f: extern "C" fn(i32, i32) -> i32, n: U32, d: U32) -> Option { let (n, d) = (n.0 as i32, d.0 as i32); @@ -141,7 +156,7 @@ mod tests { } } - fn __modsi3(f: extern fn(i32, i32) -> i32, + fn __modsi3(f: extern "C" fn(i32, i32) -> i32, n: U32, d: U32) -> Option { let (n, d) = (n.0 as i32, d.0 as i32); @@ -152,7 +167,7 @@ mod tests { } } - fn __divmodsi4(f: extern fn(i32, i32, &mut i32) -> i32, + fn __divmodsi4(f: extern "C" fn(i32, i32, &mut i32) -> i32, n: U32, d: U32) -> Option<(i32, i32)> { let (n, d) = (n.0 as i32, d.0 as i32); @@ -176,7 +191,7 @@ mod tests_i128 { use qc::U128; check! { - fn __divti3(f: extern fn(i128, i128) -> i128, n: U128, d: U128) -> Option { + fn __divti3(f: extern "C" fn(i128, i128) -> i128, n: U128, d: U128) -> Option { let (n, d) = (n.0 as i128, d.0 as i128); if d == 0 { None @@ -185,7 +200,7 @@ mod tests_i128 { } } - fn __modti3(f: extern fn(i128, i128) -> i128, n: U128, d: U128) -> Option { + fn __modti3(f: extern "C" fn(i128, i128) -> i128, n: U128, d: U128) -> Option { let (n, d) = (n.0 as i128, d.0 as i128); if d == 0 { None diff --git a/src/int/shift.rs b/src/int/shift.rs index b93b7bf..fdd2f6c 100644 --- a/src/int/shift.rs +++ b/src/int/shift.rs @@ -79,7 +79,7 @@ mod tests { // NOTE We purposefully stick to `u32` for `b` here because we want "small" values (b < 64) check! { - fn __ashldi3(f: extern fn(u64, u32) -> u64, a: U64, b: u32) -> Option { + fn __ashldi3(f: extern "C" fn(u64, u32) -> u64, a: U64, b: u32) -> Option { let a = a.0; if b >= 64 { None @@ -88,7 +88,7 @@ mod tests { } } - fn __ashrdi3(f: extern fn(i64, u32) -> i64, a: I64, b: u32) -> Option { + fn __ashrdi3(f: extern "C" fn(i64, u32) -> i64, a: I64, b: u32) -> Option { let a = a.0; if b >= 64 { None @@ -97,7 +97,7 @@ mod tests { } } - fn __lshrdi3(f: extern fn(u64, u32) -> u64, a: U64, b: u32) -> Option { + fn __lshrdi3(f: extern "C" fn(u64, u32) -> u64, a: U64, b: u32) -> Option { let a = a.0; if b >= 64 { None @@ -118,7 +118,7 @@ mod tests_i128 { // NOTE We purposefully stick to `u32` for `b` here because we want "small" values (b < 64) check! { - fn __ashlti3(f: extern fn(u128, u32) -> u128, a: U128, b: u32) -> Option { + fn __ashlti3(f: extern "C" fn(u128, u32) -> u128, a: U128, b: u32) -> Option { let a = a.0; if b >= 64 { None @@ -127,7 +127,7 @@ mod tests_i128 { } } - fn __ashrti3(f: extern fn(i128, u32) -> i128, a: I128, b: u32) -> Option { + fn __ashrti3(f: extern "C" fn(i128, u32) -> i128, a: I128, b: u32) -> Option { let a = a.0; if b >= 64 { None @@ -136,7 +136,7 @@ mod tests_i128 { } } - fn __lshrti3(f: extern fn(u128, u32) -> u128, a: U128, b: u32) -> Option { + fn __lshrti3(f: extern "C" fn(u128, u32) -> u128, a: U128, b: u32) -> Option { let a = a.0; if b >= 128 { None diff --git a/src/int/udiv.rs b/src/int/udiv.rs index 453ab00..6c125bb 100644 --- a/src/int/udiv.rs +++ b/src/int/udiv.rs @@ -318,7 +318,7 @@ mod tests { use qc::{U32, U64}; check! { - fn __udivdi3(f: extern fn(u64, u64) -> u64, n: U64, d: U64) -> Option { + fn __udivdi3(f: extern "C" fn(u64, u64) -> u64, n: U64, d: U64) -> Option { let (n, d) = (n.0, d.0); if d == 0 { None @@ -327,7 +327,7 @@ mod tests { } } - fn __umoddi3(f: extern fn(u64, u64) -> u64, n: U64, d: U64) -> Option { + fn __umoddi3(f: extern "C" fn(u64, u64) -> u64, n: U64, d: U64) -> Option { let (n, d) = (n.0, d.0); if d == 0 { None @@ -336,7 +336,7 @@ mod tests { } } - fn __udivmoddi4(f: extern fn(u64, u64, Option<&mut u64>) -> u64, + fn __udivmoddi4(f: extern "C" fn(u64, u64, Option<&mut u64>) -> u64, n: U64, d: U64) -> Option<(u64, u64)> { let (n, d) = (n.0, d.0); @@ -349,7 +349,7 @@ mod tests { } } - fn __udivsi3(f: extern fn(u32, u32) -> u32, n: U32, d: U32) -> Option { + fn __udivsi3(f: extern "C" fn(u32, u32) -> u32, n: U32, d: U32) -> Option { let (n, d) = (n.0, d.0); if d == 0 { None @@ -358,7 +358,7 @@ mod tests { } } - fn __umodsi3(f: extern fn(u32, u32) -> u32, n: U32, d: U32) -> Option { + fn __umodsi3(f: extern "C" fn(u32, u32) -> u32, n: U32, d: U32) -> Option { let (n, d) = (n.0, d.0); if d == 0 { None @@ -367,7 +367,7 @@ mod tests { } } - fn __udivmodsi4(f: extern fn(u32, u32, Option<&mut u32>) -> u32, + fn __udivmodsi4(f: extern "C" fn(u32, u32, Option<&mut u32>) -> u32, n: U32, d: U32) -> Option<(u32, u32)> { let (n, d) = (n.0, d.0); @@ -391,7 +391,7 @@ mod tests_i128 { use qc::U128; check! { - fn __udivti3(f: extern fn(u128, u128) -> u128, + fn __udivti3(f: extern "C" fn(u128, u128) -> u128, n: U128, d: U128) -> Option { let (n, d) = (n.0, d.0); @@ -402,7 +402,7 @@ mod tests_i128 { } } - fn __umodti3(f: extern fn(u128, u128) -> u128, + fn __umodti3(f: extern "C" fn(u128, u128) -> u128, n: U128, d: U128) -> Option { let (n, d) = (n.0, d.0); @@ -413,7 +413,7 @@ mod tests_i128 { } } - fn __udivmodti4(f: extern fn(u128, u128, Option<&mut u128>) -> u128, + fn __udivmodti4(f: extern "C" fn(u128, u128, Option<&mut u128>) -> u128, n: U128, d: U128) -> Option { let (n, d) = (n.0, d.0); diff --git a/src/qc.rs b/src/qc.rs index ea0faac..306508f 100644 --- a/src/qc.rs +++ b/src/qc.rs @@ -240,7 +240,8 @@ arbitrary_float!(F64: f64); // fails. macro_rules! check { ($( - fn $name:ident($f:ident: extern fn($($farg:ty),*) -> $fret:ty, + $(#[$cfg:meta])* + fn $name:ident($f:ident: extern $abi:tt fn($($farg:ty),*) -> $fret:ty, $($arg:ident: $t:ty),*) -> Option<$ret:ty> { @@ -248,7 +249,8 @@ macro_rules! check { } )*) => ( $( - fn $name($f: extern fn($($farg),*) -> $fret, + $(#[$cfg])* + fn $name($f: extern $abi fn($($farg),*) -> $fret, $($arg: $t),*) -> Option<$ret> { $($code)* } @@ -260,6 +262,7 @@ macro_rules! check { use quickcheck::TestResult; $( + $(#[$cfg])* #[test] fn $name() { fn my_check($($arg:$t),*) -> TestResult {