Add public-test-deps feature for better visibility control
This commit is contained in:
@@ -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"]
|
||||||
|
|||||||
@@ -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) => {
|
||||||
|
|||||||
@@ -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]
|
||||||
|
|||||||
@@ -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) => {
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -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]
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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]
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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" }
|
||||||
|
|||||||
Reference in New Issue
Block a user