Skip to content

Move std_detect into stdlib #143412

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

Draft
wants to merge 7 commits into
base: master
Choose a base branch
from
Draft
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: 2 additions & 2 deletions library/Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -340,10 +340,10 @@ dependencies = [
name = "std_detect"
version = "0.1.5"
dependencies = [
"alloc",
"cfg-if",
"core",
"libc",
"rustc-std-workspace-alloc",
"rustc-std-workspace-core",
]

[[package]]
Expand Down
7 changes: 2 additions & 5 deletions library/std/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,7 @@ unwind = { path = "../unwind" }
hashbrown = { version = "0.15", default-features = false, features = [
'rustc-dep-of-std',
] }
std_detect = { path = "../stdarch/crates/std_detect", default-features = false, features = [
'rustc-dep-of-std',
] }
std_detect = { path = "../std_detect" }

# Dependencies of the `backtrace` crate
rustc-demangle = { version = "0.1.24", features = ['rustc-dep-of-std'] }
Expand Down Expand Up @@ -117,8 +115,7 @@ debug_refcell = ["core/debug_refcell"]
debug_typeid = ["core/debug_typeid"]


# Enable std_detect default features for stdarch/crates/std_detect:
# https://github.com/rust-lang/stdarch/blob/master/crates/std_detect/Cargo.toml
# Enable std_detect features:
std_detect_file_io = ["std_detect/std_detect_file_io"]
std_detect_dlsym_getauxval = ["std_detect/std_detect_dlsym_getauxval"]

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,20 +22,14 @@ maintenance = { status = "experimental" }

[dependencies]
cfg-if = "1.0.0"

# When built as part of libstd
core = { version = "1.0.0", optional = true, package = "rustc-std-workspace-core" }
alloc = { version = "1.0.0", optional = true, package = "rustc-std-workspace-alloc" }
core = { path = "../core" }
alloc = { path = "../alloc" }

[target.'cfg(not(windows))'.dependencies]
libc = { version = "0.2.0", optional = true, default-features = false }

[features]
default = [ "std_detect_dlsym_getauxval", "std_detect_file_io" ]
default = []
std_detect_file_io = [ "libc" ]
std_detect_dlsym_getauxval = [ "libc" ]
std_detect_env_override = [ "libc" ]
rustc-dep-of-std = [
"core",
"alloc",
]
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@
#![allow(dead_code)] // not used on all platforms

use core::sync::atomic::Ordering;

use core::sync::atomic::AtomicUsize;
use core::sync::atomic::{AtomicUsize, Ordering};

/// Sets the `bit` of `x`.
#[inline]
Expand Down Expand Up @@ -40,31 +38,22 @@ impl Initializer {
/// Tests the `bit` of the cache.
#[inline]
pub(crate) fn test(self, bit: u32) -> bool {
debug_assert!(
bit < CACHE_CAPACITY,
"too many features, time to increase the cache size!"
);
debug_assert!(bit < CACHE_CAPACITY, "too many features, time to increase the cache size!");
test_bit(self.0, bit)
}

/// Sets the `bit` of the cache.
#[inline]
pub(crate) fn set(&mut self, bit: u32) {
debug_assert!(
bit < CACHE_CAPACITY,
"too many features, time to increase the cache size!"
);
debug_assert!(bit < CACHE_CAPACITY, "too many features, time to increase the cache size!");
let v = self.0;
self.0 = set_bit(v, bit);
}

/// Unsets the `bit` of the cache.
#[inline]
pub(crate) fn unset(&mut self, bit: u32) {
debug_assert!(
bit < CACHE_CAPACITY,
"too many features, time to increase the cache size!"
);
debug_assert!(bit < CACHE_CAPACITY, "too many features, time to increase the cache size!");
let v = self.0;
self.0 = unset_bit(v, bit);
}
Expand All @@ -73,11 +62,7 @@ impl Initializer {
/// This global variable is a cache of the features supported by the CPU.
// Note: the third slot is only used in x86
// Another Slot can be added if needed without any change to `Initializer`
static CACHE: [Cache; 3] = [
Cache::uninitialized(),
Cache::uninitialized(),
Cache::uninitialized(),
];
static CACHE: [Cache; 3] = [Cache::uninitialized(), Cache::uninitialized(), Cache::uninitialized()];

/// Feature cache with capacity for `size_of::<usize>() * 8 - 1` features.
///
Expand All @@ -104,19 +89,14 @@ impl Cache {
#[inline]
pub(crate) fn test(&self, bit: u32) -> Option<bool> {
let cached = self.0.load(Ordering::Relaxed);
if cached == 0 {
None
} else {
Some(test_bit(cached as u128, bit))
}
if cached == 0 { None } else { Some(test_bit(cached as u128, bit)) }
}

/// Initializes the cache.
#[inline]
fn initialize(&self, value: usize) -> usize {
debug_assert_eq!((value & !Cache::MASK), 0);
self.0
.store(value | Cache::INITIALIZED_BIT, Ordering::Relaxed);
self.0.store(value | Cache::INITIALIZED_BIT, Ordering::Relaxed);
value
}
}
Expand Down Expand Up @@ -217,7 +197,5 @@ pub(crate) fn test(bit: u32) -> bool {
} else {
(bit - 2 * Cache::CAPACITY, 2)
};
CACHE[idx]
.test(relative_bit)
.unwrap_or_else(|| detect_and_initialize().test(bit))
CACHE[idx].test(relative_bit).unwrap_or_else(|| detect_and_initialize().test(bit))
}
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ macro_rules! features {
};
}

#[test]
#[test] //tidy:skip
#[deny(unexpected_cfgs)]
#[deny(unfulfilled_lint_expectations)]
fn unexpected_cfgs() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ mod arch;
#[doc(hidden)]
#[unstable(feature = "stdarch_internal", issue = "none")]
pub use self::arch::__is_feature_detected;

pub(crate) use self::arch::Feature;

mod bit;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,10 @@
//! - [Linux documentation](https://www.kernel.org/doc/Documentation/arm64/cpu-feature-registers.txt)
//! - [ARM documentation](https://developer.arm.com/documentation/ddi0601/2022-12/AArch64-Registers?lang=en)

use crate::detect::{Feature, cache};
use core::arch::asm;

use crate::detect::{Feature, cache};

/// Try to read the features from the system registers.
///
/// This will cause SIGILL if the current OS is not trapping the mrs instruction.
Expand Down Expand Up @@ -104,10 +105,7 @@ pub(crate) fn parse_system_registers(
let sha2 = bits_shift(aa64isar0, 15, 12) >= 1;
enable_feature(Feature::sha2, asimd && sha1 && sha2);
enable_feature(Feature::rdm, asimd && bits_shift(aa64isar0, 31, 28) >= 1);
enable_feature(
Feature::dotprod,
asimd && bits_shift(aa64isar0, 47, 44) >= 1,
);
enable_feature(Feature::dotprod, asimd && bits_shift(aa64isar0, 47, 44) >= 1);
enable_feature(Feature::sve, asimd && bits_shift(aa64pfr0, 35, 32) >= 1);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@
//!
//! <https://developer.apple.com/documentation/kernel/1387446-sysctlbyname/determining_instruction_set_characteristics>

use crate::detect::{Feature, cache};
use core::ffi::CStr;

use crate::detect::{Feature, cache};

#[inline]
fn _sysctlbyname(name: &CStr) -> bool {
use libc;
Expand All @@ -14,13 +15,7 @@ fn _sysctlbyname(name: &CStr) -> bool {
let enabled_ptr = &mut enabled as *mut i32 as *mut libc::c_void;

let ret = unsafe {
libc::sysctlbyname(
name.as_ptr(),
enabled_ptr,
&mut enabled_len,
core::ptr::null_mut(),
0,
)
libc::sysctlbyname(name.as_ptr(), enabled_ptr, &mut enabled_len, core::ptr::null_mut(), 0)
};

match ret {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,8 @@ fn archauxv(key: libc::c_int) -> usize {
// https://github.com/freebsd/freebsd-src/blob/release/11.4.0/sys/sys/auxv.h
// FreeBSD 11 support in std has been removed in Rust 1.75 (https://github.com/rust-lang/rust/pull/114521),
// so we can safely use this function.
let res = libc::elf_aux_info(
key,
&mut out as *mut libc::c_ulong as *mut libc::c_void,
OUT_LEN,
);
let res =
libc::elf_aux_info(key, &mut out as *mut libc::c_ulong as *mut libc::c_void, OUT_LEN);
// If elf_aux_info fails, `out` will be left at zero (which is the proper default value).
debug_assert!(res == 0 || out == 0);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -343,14 +343,8 @@ impl AtHwcap {
enable_feature(Feature::sve2, sve2);
enable_feature(Feature::sve2p1, self.sve2p1 && sve2);
// SVE2 extensions require SVE2 and crypto features
enable_feature(
Feature::sve2_aes,
self.sveaes && self.svepmull && sve2 && self.aes,
);
enable_feature(
Feature::sve2_sm4,
self.svesm4 && sve2 && self.sm3 && self.sm4,
);
enable_feature(Feature::sve2_aes, self.sveaes && self.svepmull && sve2 && self.aes);
enable_feature(Feature::sve2_sm4, self.svesm4 && sve2 && self.sm3 && self.sm4);
enable_feature(
Feature::sve2_sha3,
self.svesha3 && sve2 && self.sha512 && self.sha3 && self.sha1 && self.sha2,
Expand Down Expand Up @@ -401,84 +395,4 @@ impl AtHwcap {

#[cfg(target_endian = "little")]
#[cfg(test)]
mod tests {
use super::*;

#[cfg(feature = "std_detect_file_io")]
mod auxv_from_file {
use super::auxvec::auxv_from_file;
use super::*;
// The baseline hwcaps used in the (artificial) auxv test files.
fn baseline_hwcaps() -> AtHwcap {
AtHwcap {
fp: true,
asimd: true,
aes: true,
pmull: true,
sha1: true,
sha2: true,
crc32: true,
atomics: true,
fphp: true,
asimdhp: true,
asimdrdm: true,
lrcpc: true,
dcpop: true,
asimddp: true,
ssbs: true,
..AtHwcap::default()
}
}

#[test]
fn linux_empty_hwcap2_aarch64() {
let file = concat!(
env!("CARGO_MANIFEST_DIR"),
"/src/detect/test_data/linux-empty-hwcap2-aarch64.auxv"
);
println!("file: {file}");
let v = auxv_from_file(file).unwrap();
println!("HWCAP : 0x{:0x}", v.hwcap);
println!("HWCAP2: 0x{:0x}", v.hwcap2);
assert_eq!(AtHwcap::from(v), baseline_hwcaps());
}
#[test]
fn linux_no_hwcap2_aarch64() {
let file = concat!(
env!("CARGO_MANIFEST_DIR"),
"/src/detect/test_data/linux-no-hwcap2-aarch64.auxv"
);
println!("file: {file}");
let v = auxv_from_file(file).unwrap();
println!("HWCAP : 0x{:0x}", v.hwcap);
println!("HWCAP2: 0x{:0x}", v.hwcap2);
assert_eq!(AtHwcap::from(v), baseline_hwcaps());
}
#[test]
fn linux_hwcap2_aarch64() {
let file = concat!(
env!("CARGO_MANIFEST_DIR"),
"/src/detect/test_data/linux-hwcap2-aarch64.auxv"
);
println!("file: {file}");
let v = auxv_from_file(file).unwrap();
println!("HWCAP : 0x{:0x}", v.hwcap);
println!("HWCAP2: 0x{:0x}", v.hwcap2);
assert_eq!(
AtHwcap::from(v),
AtHwcap {
// Some other HWCAP bits.
paca: true,
pacg: true,
// HWCAP2-only bits.
dcpodp: true,
frint: true,
rng: true,
bti: true,
mte: true,
..baseline_hwcaps()
}
);
}
}
}
mod tests;
Loading
Loading