Add public-test-deps feature for better visibility control

This commit is contained in:
Aaron Kutch
2021-06-02 13:11:28 -05:00
parent 31e3ae708c
commit fdcc30c3a3
13 changed files with 64 additions and 29 deletions

View File

@@ -64,6 +64,10 @@ no-lang-items = []
# Only used in the compiler's build system # Only used in the compiler's build system
rustc-dep-of-std = ['compiler-builtins', 'core'] 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]] [[example]]
name = "intrinsics" name = "intrinsics"
required-features = ["compiler-builtins"] required-features = ["compiler-builtins"]

View File

@@ -11,9 +11,9 @@ pub mod mul;
pub mod pow; pub mod pow;
pub mod sub; pub mod sub;
public_test_dep! {
/// Trait for some basic operations on floats /// Trait for some basic operations on floats
#[doc(hidden)] pub(crate) trait Float:
pub trait Float:
Copy Copy
+ core::fmt::Debug + core::fmt::Debug
+ PartialEq + PartialEq
@@ -99,6 +99,7 @@ pub trait Float:
/// Returns if `self` is subnormal /// Returns if `self` is subnormal
fn is_subnormal(self) -> bool; fn is_subnormal(self) -> bool;
} }
}
macro_rules! float_impl { macro_rules! float_impl {
($ty:ident, $ity:ident, $sity:ident, $expty:ident, $bits:expr, $significand_bits:expr) => { ($ty:ident, $ity:ident, $sity:ident, $expty:ident, $bits:expr, $significand_bits:expr) => {

View File

@@ -3,9 +3,9 @@
// adding a zero check at the beginning, but `__clzsi2` has a precondition that `x != 0`. // 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. // 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`. /// Returns the number of leading binary zeros in `x`.
#[doc(hidden)] pub(crate) fn usize_leading_zeros_default(x: usize) -> usize {
pub 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 // 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 // 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 // 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 // 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. // 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 // 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 // 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 // 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. // 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`. /// Returns the number of leading binary zeros in `x`.
#[doc(hidden)] pub(crate) fn usize_leading_zeros_riscv(x: usize) -> usize {
pub fn usize_leading_zeros_riscv(x: usize) -> usize {
let mut x = x; let mut x = x;
// the number of potential leading zeros // the number of potential leading zeros
let mut z = usize::MAX.count_ones() as usize; 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`. // If `x != 0` then `x == 1` and subtracts one potential zero from `z`.
z - x z - x
} }
}
intrinsics! { intrinsics! {
#[maybe_use_optimized_c_shim] #[maybe_use_optimized_c_shim]

View File

@@ -11,9 +11,9 @@ pub mod udiv;
pub use self::leading_zeros::__clzsi2; pub use self::leading_zeros::__clzsi2;
public_test_dep! {
/// Trait for some basic operations on integers /// Trait for some basic operations on integers
#[doc(hidden)] pub(crate) trait Int:
pub trait Int:
Copy Copy
+ core::fmt::Debug + core::fmt::Debug
+ PartialEq + PartialEq
@@ -81,6 +81,7 @@ pub trait Int:
fn overflowing_add(self, other: Self) -> (Self, bool); fn overflowing_add(self, other: Self) -> (Self, bool);
fn leading_zeros(self) -> u32; fn leading_zeros(self) -> u32;
} }
}
macro_rules! int_impl_common { macro_rules! int_impl_common {
($ty:ty) => { ($ty:ty) => {
@@ -255,10 +256,10 @@ int_impl!(i32, u32);
int_impl!(i64, u64); int_impl!(i64, u64);
int_impl!(i128, u128); int_impl!(i128, u128);
public_test_dep! {
/// Trait for integers twice the bit width of another integer. This is implemented for all /// 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. /// primitives except for `u8`, because there is not a smaller primitive.
#[doc(hidden)] pub(crate) trait DInt: Int {
pub trait DInt: Int {
/// Integer that is half the bit width of the integer this trait is implemented for /// Integer that is half the bit width of the integer this trait is implemented for
type H: HInt<D = Self> + Int; type H: HInt<D = Self> + Int;
@@ -271,11 +272,12 @@ pub trait DInt: Int {
/// Constructs an integer using lower and higher half parts /// Constructs an integer using lower and higher half parts
fn from_lo_hi(lo: Self::H, hi: Self::H) -> Self; 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 /// 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. /// primitives except for `u128`, because it there is not a larger primitive.
#[doc(hidden)] pub(crate) trait HInt: Int {
pub trait HInt: Int {
/// Integer that is double the bit width of the integer this trait is implemented for /// Integer that is double the bit width of the integer this trait is implemented for
type D: DInt<H = Self> + Int; type D: DInt<H = Self> + Int;
@@ -291,6 +293,7 @@ pub trait HInt: Int {
/// Widening multiplication. This cannot overflow. /// Widening multiplication. This cannot overflow.
fn widen_mul(self, rhs: Self) -> Self::D; fn widen_mul(self, rhs: Self) -> Self::D;
} }
}
macro_rules! impl_d_int { macro_rules! impl_d_int {
($($X:ident $D:ident),*) => { ($($X:ident $D:ident),*) => {
@@ -353,11 +356,12 @@ impl_h_int!(
i64 u64 i128 i64 u64 i128
); );
public_test_dep! {
/// Trait to express (possibly lossy) casting of integers /// Trait to express (possibly lossy) casting of integers
#[doc(hidden)] pub(crate) trait CastInto<T: Copy>: Copy {
pub trait CastInto<T: Copy>: Copy {
fn cast(self) -> T; fn cast(self) -> T;
} }
}
macro_rules! cast_into { macro_rules! cast_into {
($ty:ty) => { ($ty:ty) => {

View File

@@ -3,8 +3,7 @@
/// assembly instruction that can divide a 128 bit integer by a 64 bit integer if the quotient fits /// 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 /// 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. /// construct a full 128 bit by 128 bit division.
#[doc(hidden)] #[allow(unused_macros)]
#[macro_export]
macro_rules! impl_asymmetric { macro_rules! impl_asymmetric {
( (
$fn:ident, // name of the unsigned division function $fn:ident, // name of the unsigned division function

View File

@@ -4,8 +4,7 @@
/// predicate instructions. For architectures with predicated instructions, one of the algorithms /// 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 /// described in the documentation of these functions probably has higher performance, and a custom
/// assembly routine should be used instead. /// assembly routine should be used instead.
#[doc(hidden)] #[allow(unused_macros)]
#[macro_export]
macro_rules! impl_binary_long { macro_rules! impl_binary_long {
( (
$fn:ident, // name of the unsigned division function $fn:ident, // name of the unsigned division function

View File

@@ -2,8 +2,7 @@
/// binary long division to divide integers larger than what hardware division by itself can do. This /// 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 /// function is intended for microarchitectures that have division hardware, but not fast enough
/// multiplication hardware for `impl_trifecta` to be faster. /// multiplication hardware for `impl_trifecta` to be faster.
#[doc(hidden)] #[allow(unused_macros)]
#[macro_export]
macro_rules! impl_delegate { macro_rules! impl_delegate {
( (
$fn:ident, // name of the unsigned division function $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`. /// Returns `n / d` and sets `*rem = n % d`.
/// ///
/// This specialization exists because: /// 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. /// 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 /// - 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. /// delegate algorithm strategy the only reasonably fast way to perform `u128` division.
#[doc(hidden)] // used on SPARC
pub fn u128_divide_sparc(duo: u128, div: u128, rem: &mut u128) -> u128 { #[allow(dead_code)]
pub(crate) fn u128_divide_sparc(duo: u128, div: u128, rem: &mut u128) -> u128 {
use super::*; use super::*;
let duo_lo = duo as u64; let duo_lo = duo as u64;
let duo_hi = (duo >> 64) 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 {
} }
} }
} }
}

View File

@@ -53,6 +53,13 @@ mod binary_long;
#[macro_use] #[macro_use]
mod delegate; 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; pub use self::delegate::u128_divide_sparc;
#[macro_use] #[macro_use]

View File

@@ -1,6 +1,5 @@
/// Creates a function used by some division algorithms to compute the "normalization shift". /// Creates a function used by some division algorithms to compute the "normalization shift".
#[doc(hidden)] #[allow(unused_macros)]
#[macro_export]
macro_rules! impl_normalization_shift { macro_rules! impl_normalization_shift {
( (
$name:ident, // name of the normalization shift function $name:ident, // name of the normalization shift function

View File

@@ -2,8 +2,7 @@
/// larger than the largest hardware integer division supported. These functions use large radix /// 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 /// division algorithms that require both fast division and very fast widening multiplication on the
/// target microarchitecture. Otherwise, `impl_delegate` should be used instead. /// target microarchitecture. Otherwise, `impl_delegate` should be used instead.
#[doc(hidden)] #[allow(unused_macros)]
#[macro_export]
macro_rules! impl_trifecta { macro_rules! impl_trifecta {
( (
$fn:ident, // name of the unsigned division function $fn:ident, // name of the unsigned division function

View File

@@ -1,5 +1,8 @@
pub use int::specialized_div_rem::u128_divide_sparc; #[cfg(not(feature = "public-test-deps"))]
use int::specialized_div_rem::*; pub(crate) use int::specialized_div_rem::*;
#[cfg(feature = "public-test-deps")]
pub use int::specialized_div_rem::*;
intrinsics! { intrinsics! {
#[maybe_use_optimized_c_shim] #[maybe_use_optimized_c_shim]

View File

@@ -1,5 +1,21 @@
//! Macros shared throughout the compiler-builtins implementation //! 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 "main macro" used for defining intrinsics.
/// ///
/// The compiler-builtins library is super platform-specific with tons of crazy /// The compiler-builtins library is super platform-specific with tons of crazy

View File

@@ -17,7 +17,7 @@ rand_xoshiro = "0.6"
[dependencies.compiler_builtins] [dependencies.compiler_builtins]
path = ".." path = ".."
default-features = false 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] [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" } test = { git = "https://github.com/japaric/utest" }