Skip to content

Commit ab6d121

Browse files
committed
[DO NOT MERGE] RISC-V: OS-independent implication logic
RFC: where to put `imply_features`? 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).
1 parent 3d38df5 commit ab6d121

File tree

1 file changed

+64
-11
lines changed
  • crates/std_detect/src/detect/os/linux

1 file changed

+64
-11
lines changed

crates/std_detect/src/detect/os/linux/riscv.rs

+64-11
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,65 @@
33
use super::auxvec;
44
use crate::detect::{Feature, bit, cache};
55

6+
/// Imply features by the given set of enabled features.
7+
///
8+
/// Note that it does not perform any consistency checks including existence of
9+
/// conflicting extensions and/or complicated requirements. Eliminating such
10+
/// inconsistencies is the responsibility of the feature detection logic and
11+
/// its provider(s).
12+
pub(crate) fn imply_features(mut value: cache::Initializer) -> cache::Initializer {
13+
// Expect that the optimizer turns repeated operations into
14+
// a fewer number of bit-manipulation operations.
15+
macro_rules! imply {
16+
// Regular implication: A1 => (B1[, B2...]), A2 => (B1[, B2...]) and so on.
17+
($($from: ident)|+ => $($to: ident)&+) => {
18+
if [$(Feature::$from as u32),+].iter().any(|&x| value.test(x)) {
19+
$(
20+
value.set(Feature::$to as u32);
21+
)+
22+
}
23+
};
24+
// Implication with multiple requirements: A1 && A2 ... => (B1[, B2...]).
25+
($($from: ident)&+ => $($to: ident)&+) => {
26+
if [$(Feature::$from as u32),+].iter().all(|&x| value.test(x)) {
27+
$(
28+
value.set(Feature::$to as u32);
29+
)+
30+
}
31+
};
32+
}
33+
macro_rules! group {
34+
($group: ident == $($member: ident)&+) => {
35+
// Forward implication as defined in the specifications.
36+
imply!($group => $($member)&+);
37+
// Reverse implication to "group extension" from its members.
38+
// This is not a part of specifications but convenient for feature
39+
// detection and implemented in e.g. LLVM.
40+
imply!($($member)&+ => $group);
41+
};
42+
}
43+
44+
group!(zkn == zbkb & zbkc & zbkx & zkne & zknd & zknh);
45+
group!(zks == zbkb & zbkc & zbkx & zksed & zksh);
46+
group!(zk == zkn & zkr & zkt);
47+
48+
group!(a == zalrsc & zaamo);
49+
50+
group!(b == zba & zbb & zbs);
51+
52+
imply!(zhinx => zhinxmin);
53+
imply!(zdinx | zhinxmin => zfinx);
54+
55+
imply!(zfh => zfhmin);
56+
imply!(q => d);
57+
imply!(d | zfhmin => f);
58+
59+
imply!(zicntr | zihpm | zkr | f | zfinx => zicsr);
60+
imply!(s | h => zicsr);
61+
62+
value
63+
}
64+
665
/// Read list of supported features from the auxiliary vector.
766
pub(crate) fn detect_features() -> cache::Initializer {
867
let mut value = cache::Initializer::default();
@@ -12,22 +71,16 @@ pub(crate) fn detect_features() -> cache::Initializer {
1271
}
1372
};
1473

15-
// Use auxiliary vector to enable single-letter ISA extensions and Zicsr.
74+
// Use auxiliary vector to enable single-letter ISA extensions.
1675
// The values are part of the platform-specific [asm/hwcap.h][hwcap]
1776
//
1877
// [hwcap]: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/riscv/include/uapi/asm/hwcap.h?h=v6.14
1978
let auxv = auxvec::auxv().expect("read auxvec"); // should not fail on RISC-V platform
2079
#[allow(clippy::eq_op)]
21-
let has_a = bit::test(auxv.hwcap, (b'a' - b'a').into());
22-
enable_feature(Feature::a, has_a);
23-
enable_feature(Feature::zalrsc, has_a);
24-
enable_feature(Feature::zaamo, has_a);
80+
enable_feature(Feature::a, bit::test(auxv.hwcap, (b'a' - b'a').into()));
2581
enable_feature(Feature::c, bit::test(auxv.hwcap, (b'c' - b'a').into()));
26-
let has_d = bit::test(auxv.hwcap, (b'd' - b'a').into());
27-
let has_f = bit::test(auxv.hwcap, (b'f' - b'a').into());
28-
enable_feature(Feature::d, has_d);
29-
enable_feature(Feature::f, has_d | has_f);
30-
enable_feature(Feature::zicsr, has_d | has_f);
82+
enable_feature(Feature::d, bit::test(auxv.hwcap, (b'd' - b'a').into()));
83+
enable_feature(Feature::f, bit::test(auxv.hwcap, (b'f' - b'a').into()));
3184
enable_feature(Feature::h, bit::test(auxv.hwcap, (b'h' - b'a').into()));
3285
enable_feature(Feature::m, bit::test(auxv.hwcap, (b'm' - b'a').into()));
3386

@@ -48,5 +101,5 @@ pub(crate) fn detect_features() -> cache::Initializer {
48101
// to detect when Rust is used to write Linux kernel modules.
49102
// These should be more than Auxvec way to detect supervisor features.
50103

51-
value
104+
imply_features(value)
52105
}

0 commit comments

Comments
 (0)