
This commit adds the OS-independent extension implication logic for RISC-V. It implements: 1. Regular implication (A → B) a. "the extension A implies the extension B" b. "the extension A requires the extension B" c. "the extension A depends on the extension B" 2. Extension group or shorthand (A == B1 & B2...) a. "the extension A is shorthand for other extensions: B1, B2..." b. "the extension A comprises instructions provided by B1, B2..." This is implemented as (A → B1 & B2... + B1 & B2... → A) where the former is a regular implication as required by specifications and the latter is a "reverse" implication to improve usability. and prepares for: 3. Implication with multiple requirements (A1 & A2... → B) a. "A1 + A2 implies B" b. (implicitly used to implement reverse implication of case 2) Although it uses macros and iterators, good optimizers turn the series of implications into fast bit-manipulation operations. In the case 2 (extension group or shorthand; where a superset extension is just a collection of other subextensions and provides no features by a superset itself), specifications do specify that an extension group implies its members but not vice versa. However, implying an extension group from its members would improve usability on the feature detection (especially when the feature provider does not provide existence of such extension group but provides existence of its members). Similar "reverse implication" on RISC-V is implemented on LLVM. Case 3 is implicitly used to implement reverse implication of case 2 but there's another use case: implication with multiple requirements like "Zcf" and "Zcd" extensions (not yet implemented in this crate for now). To handle extension groups perfectly, we need to loop implication several times (until they converge; normally 2 times and up to 4 times when we add most of `riscv_hwprobe`-based features). To make implementation of that loop possible, `cache::Initializer` is modified to implement `PartialEq` and `Eq`.
std::detect
- Rust's standard library run-time CPU feature detection
The private std::detect
module implements run-time feature detection in Rust's
standard library. This allows detecting whether the CPU the binary runs on
supports certain features, like SIMD instructions.
Usage
std::detect
APIs are available as part of libstd
. Prefer using it via the
standard library than through this crate. Unstable features of std::detect
are
available on nightly Rust behind various feature-gates.
If you need run-time feature detection in #[no_std]
environments, Rust core
library cannot help you. By design, Rust core
is platform independent, but
performing run-time feature detection requires a certain level of cooperation
from the platform.
You can then manually include std_detect
as a dependency to get similar
run-time feature detection support than the one offered by Rust's standard
library. We intend to make std_detect
more flexible and configurable in this
regard to better serve the needs of #[no_std]
targets.
Features
-
std_detect_dlsym_getauxval
(enabled by default, requireslibc
): Enable to uselibc::dlsym
to query whethergetauxval
is linked into the binary. When this is not the case, this feature allows other fallback methods to perform run-time feature detection. When this feature is disabled,std_detect
assumes thatgetauxval
is linked to the binary. If that is not the case the behavior is undefined.Note: This feature is ignored on
*-linux-{gnu,musl,ohos}*
and*-android*
targets because we can safely assumegetauxval
is linked to the binary.*-linux-gnu*
targets (since Rust 1.64) have glibc requirements higher than glibc 2.16 that addedgetauxval
.*-linux-musl*
targets (at least since Rust 1.15) use musl newer than musl 1.1.0 that addedgetauxval
*-linux-ohos*
targets use a fork of musl 1.2*-android*
targets (since Rust 1.68) have the minimum supported API level higher than Android 4.3 (API level 18) that addedgetauxval
.
-
std_detect_file_io
(enabled by default, requiresstd
): Enable to perform run-time feature detection using file APIs (e.g./proc/cpuinfo
, etc.) if other more performant methods fail. This feature requireslibstd
as a dependency, preventing the crate from working on applications in whichstd
is not available.
Platform support
-
All
x86
/x86_64
targets are supported on all platforms by querying thecpuid
instruction directly for the features supported by the hardware and the operating system.std_detect
assumes that the binary is an user-space application. If you need raw support for queryingcpuid
, consider using thecupid
crate. -
Linux/Android:
arm{32, 64}
,mips{32,64}{,el}
,powerpc{32,64}{,le}
,riscv{32,64}
,loongarch64
,s390x
:std_detect
supports these on Linux by querying ELF auxiliary vectors (usinggetauxval
when available), and if that fails, by querying/proc/cpuinfo
.arm64
: partial support for doing run-time feature detection by directly queryingmrs
is implemented for Linux >= 4.11, but not enabled by default.
-
FreeBSD:
arm32
,powerpc64
:std_detect
supports these on FreeBSD by querying ELF auxiliary vectors usingsysctl
.arm64
: run-time feature detection is implemented by directly queryingmrs
.
-
OpenBSD:
arm64
: run-time feature detection is implemented by queryingsysctl
.
-
Windows:
arm64
: run-time feature detection is implemented by queryingIsProcessorFeaturePresent
.
License
This project is licensed under either of
- Apache License, Version 2.0, (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)
at your option.
Contribution
Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in std_detect
by you, as defined in the Apache-2.0 license,
shall be dual licensed as above, without any additional terms or conditions.