Skip to content

Add public-test-deps feature for better visibility control #424

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 3, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"]
Expand Down
5 changes: 3 additions & 2 deletions src/float/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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) => {
Expand Down
10 changes: 6 additions & 4 deletions src/int/leading_zeros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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]
Expand Down
20 changes: 12 additions & 8 deletions src/int/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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) => {
Expand Down Expand Up @@ -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<D = Self> + Int;

Expand All @@ -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<H = Self> + Int;

Expand All @@ -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),*) => {
Expand Down Expand Up @@ -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<T: Copy>: Copy {
pub(crate) trait CastInto<T: Copy>: Copy {
fn cast(self) -> T;
}
}

macro_rules! cast_into {
($ty:ty) => {
Expand Down
3 changes: 1 addition & 2 deletions src/int/specialized_div_rem/asymmetric.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 1 addition & 2 deletions src/int/specialized_div_rem/binary_long.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
10 changes: 6 additions & 4 deletions src/int/specialized_div_rem/delegate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -186,15 +185,17 @@ macro_rules! impl_delegate {
};
}

public_test_dep! {
/// Returns `n / d` and sets `*rem = n % d`.
///
/// This specialization exists because:
/// - The LLVM backend for 32-bit SPARC cannot compile functions that return `(u128, u128)`,
/// 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;
Expand Down Expand Up @@ -315,3 +316,4 @@ pub fn u128_divide_sparc(duo: u128, div: u128, rem: &mut u128) -> u128 {
}
}
}
}
7 changes: 7 additions & 0 deletions src/int/specialized_div_rem/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
3 changes: 1 addition & 2 deletions src/int/specialized_div_rem/norm_shift.rs
Original file line number Diff line number Diff line change
@@ -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
Expand Down
3 changes: 1 addition & 2 deletions src/int/specialized_div_rem/trifecta.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
7 changes: 5 additions & 2 deletions src/int/udiv.rs
Original file line number Diff line number Diff line change
@@ -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]
Expand Down
16 changes: 16 additions & 0 deletions src/macros.rs
Original file line number Diff line number Diff line change
@@ -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
Expand Down
2 changes: 1 addition & 1 deletion testcrate/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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" }
Expand Down