From 2ad41ef64b870e32f38e13a0fd05c4d3bceb287a Mon Sep 17 00:00:00 2001 From: Aaron Kutch Date: Wed, 2 Jun 2021 13:11:28 -0500 Subject: [PATCH] Add public-test-deps feature for better visibility control --- Cargo.toml | 4 ++++ src/float/mod.rs | 5 +++-- src/int/leading_zeros.rs | 10 ++++++---- src/int/mod.rs | 20 ++++++++++++-------- src/int/specialized_div_rem/asymmetric.rs | 3 +-- src/int/specialized_div_rem/binary_long.rs | 3 +-- src/int/specialized_div_rem/delegate.rs | 10 ++++++---- src/int/specialized_div_rem/mod.rs | 7 +++++++ src/int/specialized_div_rem/norm_shift.rs | 3 +-- src/int/specialized_div_rem/trifecta.rs | 3 +-- src/int/udiv.rs | 7 +++++-- src/macros.rs | 16 ++++++++++++++++ testcrate/Cargo.toml | 2 +- 13 files changed, 64 insertions(+), 29 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index f5ba632a0..e1f5cbf8f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -64,6 +64,10 @@ no-lang-items = [] # Only used in the compiler's build system rustc-dep-of-std = ['compiler-builtins', 'core'] +# This makes certain traits and function specializations public that +# are not normally public but are required by the `testcrate` +public-test-deps = [] + [[example]] name = "intrinsics" required-features = ["compiler-builtins"] diff --git a/src/float/mod.rs b/src/float/mod.rs index 69e4dc635..11680e7a9 100644 --- a/src/float/mod.rs +++ b/src/float/mod.rs @@ -11,9 +11,9 @@ pub mod mul; pub mod pow; pub mod sub; +public_test_dep! { /// Trait for some basic operations on floats -#[doc(hidden)] -pub trait Float: +pub(crate) trait Float: Copy + core::fmt::Debug + PartialEq @@ -99,6 +99,7 @@ pub trait Float: /// Returns if `self` is subnormal fn is_subnormal(self) -> bool; } +} macro_rules! float_impl { ($ty:ident, $ity:ident, $sity:ident, $expty:ident, $bits:expr, $significand_bits:expr) => { diff --git a/src/int/leading_zeros.rs b/src/int/leading_zeros.rs index e4a9e5eb2..0265b9a9d 100644 --- a/src/int/leading_zeros.rs +++ b/src/int/leading_zeros.rs @@ -3,9 +3,9 @@ // adding a zero check at the beginning, but `__clzsi2` has a precondition that `x != 0`. // Compilers will insert the check for zero in cases where it is needed. +public_test_dep! { /// Returns the number of leading binary zeros in `x`. -#[doc(hidden)] -pub fn usize_leading_zeros_default(x: usize) -> usize { +pub(crate) fn usize_leading_zeros_default(x: usize) -> usize { // The basic idea is to test if the higher bits of `x` are zero and bisect the number // of leading zeros. It is possible for all branches of the bisection to use the same // code path by conditionally shifting the higher parts down to let the next bisection @@ -69,15 +69,16 @@ pub fn usize_leading_zeros_default(x: usize) -> usize { // on x86_64, it is slightly faster to use the LUT, but this is probably because of OOO // execution effects. Changing to using a LUT and branching is risky for smaller cores. } +} // The above method does not compile well on RISC-V (because of the lack of predicated // instructions), producing code with many branches or using an excessively long // branchless solution. This method takes advantage of the set-if-less-than instruction on // RISC-V that allows `(x >= power-of-two) as usize` to be branchless. +public_test_dep! { /// Returns the number of leading binary zeros in `x`. -#[doc(hidden)] -pub fn usize_leading_zeros_riscv(x: usize) -> usize { +pub(crate) fn usize_leading_zeros_riscv(x: usize) -> usize { let mut x = x; // the number of potential leading zeros let mut z = usize::MAX.count_ones() as usize; @@ -126,6 +127,7 @@ pub fn usize_leading_zeros_riscv(x: usize) -> usize { // If `x != 0` then `x == 1` and subtracts one potential zero from `z`. z - x } +} intrinsics! { #[maybe_use_optimized_c_shim] diff --git a/src/int/mod.rs b/src/int/mod.rs index 080a415de..509f9fdae 100644 --- a/src/int/mod.rs +++ b/src/int/mod.rs @@ -11,9 +11,9 @@ pub mod udiv; pub use self::leading_zeros::__clzsi2; +public_test_dep! { /// Trait for some basic operations on integers -#[doc(hidden)] -pub trait Int: +pub(crate) trait Int: Copy + core::fmt::Debug + PartialEq @@ -81,6 +81,7 @@ pub trait Int: fn overflowing_add(self, other: Self) -> (Self, bool); fn leading_zeros(self) -> u32; } +} macro_rules! int_impl_common { ($ty:ty) => { @@ -255,10 +256,10 @@ int_impl!(i32, u32); int_impl!(i64, u64); int_impl!(i128, u128); +public_test_dep! { /// Trait for integers twice the bit width of another integer. This is implemented for all /// primitives except for `u8`, because there is not a smaller primitive. -#[doc(hidden)] -pub trait DInt: Int { +pub(crate) trait DInt: Int { /// Integer that is half the bit width of the integer this trait is implemented for type H: HInt + Int; @@ -271,11 +272,12 @@ pub trait DInt: Int { /// Constructs an integer using lower and higher half parts fn from_lo_hi(lo: Self::H, hi: Self::H) -> Self; } +} +public_test_dep! { /// Trait for integers half the bit width of another integer. This is implemented for all /// primitives except for `u128`, because it there is not a larger primitive. -#[doc(hidden)] -pub trait HInt: Int { +pub(crate) trait HInt: Int { /// Integer that is double the bit width of the integer this trait is implemented for type D: DInt + Int; @@ -291,6 +293,7 @@ pub trait HInt: Int { /// Widening multiplication. This cannot overflow. fn widen_mul(self, rhs: Self) -> Self::D; } +} macro_rules! impl_d_int { ($($X:ident $D:ident),*) => { @@ -353,11 +356,12 @@ impl_h_int!( i64 u64 i128 ); +public_test_dep! { /// Trait to express (possibly lossy) casting of integers -#[doc(hidden)] -pub trait CastInto: Copy { +pub(crate) trait CastInto: Copy { fn cast(self) -> T; } +} macro_rules! cast_into { ($ty:ty) => { diff --git a/src/int/specialized_div_rem/asymmetric.rs b/src/int/specialized_div_rem/asymmetric.rs index 45da657e9..56ce188a3 100644 --- a/src/int/specialized_div_rem/asymmetric.rs +++ b/src/int/specialized_div_rem/asymmetric.rs @@ -3,8 +3,7 @@ /// assembly instruction that can divide a 128 bit integer by a 64 bit integer if the quotient fits /// in 64 bits. The 128 bit version of this algorithm would use that fast hardware division to /// construct a full 128 bit by 128 bit division. -#[doc(hidden)] -#[macro_export] +#[allow(unused_macros)] macro_rules! impl_asymmetric { ( $fn:ident, // name of the unsigned division function diff --git a/src/int/specialized_div_rem/binary_long.rs b/src/int/specialized_div_rem/binary_long.rs index 7de10e852..0d7822882 100644 --- a/src/int/specialized_div_rem/binary_long.rs +++ b/src/int/specialized_div_rem/binary_long.rs @@ -4,8 +4,7 @@ /// predicate instructions. For architectures with predicated instructions, one of the algorithms /// described in the documentation of these functions probably has higher performance, and a custom /// assembly routine should be used instead. -#[doc(hidden)] -#[macro_export] +#[allow(unused_macros)] macro_rules! impl_binary_long { ( $fn:ident, // name of the unsigned division function diff --git a/src/int/specialized_div_rem/delegate.rs b/src/int/specialized_div_rem/delegate.rs index 135d3402a..330c6e4f8 100644 --- a/src/int/specialized_div_rem/delegate.rs +++ b/src/int/specialized_div_rem/delegate.rs @@ -2,8 +2,7 @@ /// binary long division to divide integers larger than what hardware division by itself can do. This /// function is intended for microarchitectures that have division hardware, but not fast enough /// multiplication hardware for `impl_trifecta` to be faster. -#[doc(hidden)] -#[macro_export] +#[allow(unused_macros)] macro_rules! impl_delegate { ( $fn:ident, // name of the unsigned division function @@ -186,6 +185,7 @@ macro_rules! impl_delegate { }; } +public_test_dep! { /// Returns `n / d` and sets `*rem = n % d`. /// /// This specialization exists because: @@ -193,8 +193,9 @@ macro_rules! impl_delegate { /// so we have to use an old fashioned `&mut u128` argument to return the remainder. /// - 64-bit SPARC does not have u64 * u64 => u128 widening multiplication, which makes the /// delegate algorithm strategy the only reasonably fast way to perform `u128` division. -#[doc(hidden)] -pub fn u128_divide_sparc(duo: u128, div: u128, rem: &mut u128) -> u128 { +// used on SPARC +#[allow(dead_code)] +pub(crate) fn u128_divide_sparc(duo: u128, div: u128, rem: &mut u128) -> u128 { use super::*; let duo_lo = duo as u64; let duo_hi = (duo >> 64) as u64; @@ -315,3 +316,4 @@ pub fn u128_divide_sparc(duo: u128, div: u128, rem: &mut u128) -> u128 { } } } +} diff --git a/src/int/specialized_div_rem/mod.rs b/src/int/specialized_div_rem/mod.rs index 391db765d..f5b2af235 100644 --- a/src/int/specialized_div_rem/mod.rs +++ b/src/int/specialized_div_rem/mod.rs @@ -53,6 +53,13 @@ mod binary_long; #[macro_use] mod delegate; + +// used on SPARC +#[allow(unused_imports)] +#[cfg(not(feature = "public-test-deps"))] +pub(crate) use self::delegate::u128_divide_sparc; + +#[cfg(feature = "public-test-deps")] pub use self::delegate::u128_divide_sparc; #[macro_use] diff --git a/src/int/specialized_div_rem/norm_shift.rs b/src/int/specialized_div_rem/norm_shift.rs index be95d1b92..61b67b6bc 100644 --- a/src/int/specialized_div_rem/norm_shift.rs +++ b/src/int/specialized_div_rem/norm_shift.rs @@ -1,6 +1,5 @@ /// Creates a function used by some division algorithms to compute the "normalization shift". -#[doc(hidden)] -#[macro_export] +#[allow(unused_macros)] macro_rules! impl_normalization_shift { ( $name:ident, // name of the normalization shift function diff --git a/src/int/specialized_div_rem/trifecta.rs b/src/int/specialized_div_rem/trifecta.rs index a9ea60301..7e104053b 100644 --- a/src/int/specialized_div_rem/trifecta.rs +++ b/src/int/specialized_div_rem/trifecta.rs @@ -2,8 +2,7 @@ /// larger than the largest hardware integer division supported. These functions use large radix /// division algorithms that require both fast division and very fast widening multiplication on the /// target microarchitecture. Otherwise, `impl_delegate` should be used instead. -#[doc(hidden)] -#[macro_export] +#[allow(unused_macros)] macro_rules! impl_trifecta { ( $fn:ident, // name of the unsigned division function diff --git a/src/int/udiv.rs b/src/int/udiv.rs index d97178078..2f236346d 100644 --- a/src/int/udiv.rs +++ b/src/int/udiv.rs @@ -1,5 +1,8 @@ -pub use int::specialized_div_rem::u128_divide_sparc; -use int::specialized_div_rem::*; +#[cfg(not(feature = "public-test-deps"))] +pub(crate) use int::specialized_div_rem::*; + +#[cfg(feature = "public-test-deps")] +pub use int::specialized_div_rem::*; intrinsics! { #[maybe_use_optimized_c_shim] diff --git a/src/macros.rs b/src/macros.rs index 56f27164a..214f0795f 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -1,5 +1,21 @@ //! Macros shared throughout the compiler-builtins implementation +/// Changes the visibility to `pub` if feature "public-test-deps" is set +#[cfg(not(feature = "public-test-deps"))] +macro_rules! public_test_dep { + ($(#[$($meta:meta)*])* pub(crate) $ident:ident $($tokens:tt)*) => { + $(#[$($meta)*])* pub(crate) $ident $($tokens)* + }; +} + +/// Changes the visibility to `pub` if feature "public-test-deps" is set +#[cfg(feature = "public-test-deps")] +macro_rules! public_test_dep { + {$(#[$($meta:meta)*])* pub(crate) $ident:ident $($tokens:tt)*} => { + $(#[$($meta)*])* pub $ident $($tokens)* + }; +} + /// The "main macro" used for defining intrinsics. /// /// The compiler-builtins library is super platform-specific with tons of crazy diff --git a/testcrate/Cargo.toml b/testcrate/Cargo.toml index a066a1134..1f77b2554 100644 --- a/testcrate/Cargo.toml +++ b/testcrate/Cargo.toml @@ -17,7 +17,7 @@ rand_xoshiro = "0.6" [dependencies.compiler_builtins] path = ".." default-features = false -features = ["no-lang-items"] +features = ["no-lang-items", "public-test-deps"] [target.'cfg(all(target_arch = "arm", not(any(target_env = "gnu", target_env = "musl")), target_os = "linux"))'.dev-dependencies] test = { git = "https://github.com/japaric/utest" }