summaryrefslogtreecommitdiffstats
path: root/src/tools/rustfmt/tests/target/cfg_if/detect/os/linux/aarch64.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools/rustfmt/tests/target/cfg_if/detect/os/linux/aarch64.rs')
-rw-r--r--src/tools/rustfmt/tests/target/cfg_if/detect/os/linux/aarch64.rs160
1 files changed, 160 insertions, 0 deletions
diff --git a/src/tools/rustfmt/tests/target/cfg_if/detect/os/linux/aarch64.rs b/src/tools/rustfmt/tests/target/cfg_if/detect/os/linux/aarch64.rs
new file mode 100644
index 000000000..8d874f228
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/cfg_if/detect/os/linux/aarch64.rs
@@ -0,0 +1,160 @@
+//! Run-time feature detection for Aarch64 on Linux.
+
+use super::{auxvec, cpuinfo};
+use crate::detect::{bit, cache, Feature};
+
+/// Performs run-time feature detection.
+#[inline]
+pub fn check_for(x: Feature) -> bool {
+ cache::test(x as u32, detect_features)
+}
+
+/// Try to read the features from the auxiliary vector, and if that fails, try
+/// to read them from /proc/cpuinfo.
+fn detect_features() -> cache::Initializer {
+ if let Ok(auxv) = auxvec::auxv() {
+ let hwcap: AtHwcap = auxv.into();
+ return hwcap.cache();
+ }
+ if let Ok(c) = cpuinfo::CpuInfo::new() {
+ let hwcap: AtHwcap = c.into();
+ return hwcap.cache();
+ }
+ cache::Initializer::default()
+}
+
+/// These values are part of the platform-specific [asm/hwcap.h][hwcap] .
+///
+/// [hwcap]: https://github.com/torvalds/linux/blob/master/arch/arm64/include/uapi/asm/hwcap.h
+struct AtHwcap {
+ fp: bool, // 0
+ asimd: bool, // 1
+ // evtstrm: bool, // 2
+ aes: bool, // 3
+ pmull: bool, // 4
+ sha1: bool, // 5
+ sha2: bool, // 6
+ crc32: bool, // 7
+ atomics: bool, // 8
+ fphp: bool, // 9
+ asimdhp: bool, // 10
+ // cpuid: bool, // 11
+ asimdrdm: bool, // 12
+ // jscvt: bool, // 13
+ // fcma: bool, // 14
+ lrcpc: bool, // 15
+ // dcpop: bool, // 16
+ // sha3: bool, // 17
+ // sm3: bool, // 18
+ // sm4: bool, // 19
+ asimddp: bool, // 20
+ // sha512: bool, // 21
+ sve: bool, // 22
+}
+
+impl From<auxvec::AuxVec> for AtHwcap {
+ /// Reads AtHwcap from the auxiliary vector.
+ fn from(auxv: auxvec::AuxVec) -> Self {
+ AtHwcap {
+ fp: bit::test(auxv.hwcap, 0),
+ asimd: bit::test(auxv.hwcap, 1),
+ // evtstrm: bit::test(auxv.hwcap, 2),
+ aes: bit::test(auxv.hwcap, 3),
+ pmull: bit::test(auxv.hwcap, 4),
+ sha1: bit::test(auxv.hwcap, 5),
+ sha2: bit::test(auxv.hwcap, 6),
+ crc32: bit::test(auxv.hwcap, 7),
+ atomics: bit::test(auxv.hwcap, 8),
+ fphp: bit::test(auxv.hwcap, 9),
+ asimdhp: bit::test(auxv.hwcap, 10),
+ // cpuid: bit::test(auxv.hwcap, 11),
+ asimdrdm: bit::test(auxv.hwcap, 12),
+ // jscvt: bit::test(auxv.hwcap, 13),
+ // fcma: bit::test(auxv.hwcap, 14),
+ lrcpc: bit::test(auxv.hwcap, 15),
+ // dcpop: bit::test(auxv.hwcap, 16),
+ // sha3: bit::test(auxv.hwcap, 17),
+ // sm3: bit::test(auxv.hwcap, 18),
+ // sm4: bit::test(auxv.hwcap, 19),
+ asimddp: bit::test(auxv.hwcap, 20),
+ // sha512: bit::test(auxv.hwcap, 21),
+ sve: bit::test(auxv.hwcap, 22),
+ }
+ }
+}
+
+impl From<cpuinfo::CpuInfo> for AtHwcap {
+ /// Reads AtHwcap from /proc/cpuinfo .
+ fn from(c: cpuinfo::CpuInfo) -> Self {
+ let f = &c.field("Features");
+ AtHwcap {
+ // 64-bit names. FIXME: In 32-bit compatibility mode /proc/cpuinfo will
+ // map some of the 64-bit names to some 32-bit feature names. This does not
+ // cover that yet.
+ fp: f.has("fp"),
+ asimd: f.has("asimd"),
+ // evtstrm: f.has("evtstrm"),
+ aes: f.has("aes"),
+ pmull: f.has("pmull"),
+ sha1: f.has("sha1"),
+ sha2: f.has("sha2"),
+ crc32: f.has("crc32"),
+ atomics: f.has("atomics"),
+ fphp: f.has("fphp"),
+ asimdhp: f.has("asimdhp"),
+ // cpuid: f.has("cpuid"),
+ asimdrdm: f.has("asimdrdm"),
+ // jscvt: f.has("jscvt"),
+ // fcma: f.has("fcma"),
+ lrcpc: f.has("lrcpc"),
+ // dcpop: f.has("dcpop"),
+ // sha3: f.has("sha3"),
+ // sm3: f.has("sm3"),
+ // sm4: f.has("sm4"),
+ asimddp: f.has("asimddp"),
+ // sha512: f.has("sha512"),
+ sve: f.has("sve"),
+ }
+ }
+}
+
+impl AtHwcap {
+ /// Initializes the cache from the feature -bits.
+ ///
+ /// The features are enabled approximately like in LLVM host feature detection:
+ /// https://github.com/llvm-mirror/llvm/blob/master/lib/Support/Host.cpp#L1273
+ fn cache(self) -> cache::Initializer {
+ let mut value = cache::Initializer::default();
+ {
+ let mut enable_feature = |f, enable| {
+ if enable {
+ value.set(f as u32);
+ }
+ };
+
+ enable_feature(Feature::fp, self.fp);
+ // Half-float support requires float support
+ enable_feature(Feature::fp16, self.fp && self.fphp);
+ enable_feature(Feature::pmull, self.pmull);
+ enable_feature(Feature::crc, self.crc32);
+ enable_feature(Feature::lse, self.atomics);
+ enable_feature(Feature::rcpc, self.lrcpc);
+
+ // SIMD support requires float support - if half-floats are
+ // supported, it also requires half-float support:
+ let asimd = self.fp && self.asimd && (!self.fphp | self.asimdhp);
+ enable_feature(Feature::asimd, asimd);
+ // SIMD extensions require SIMD support:
+ enable_feature(Feature::rdm, self.asimdrdm && asimd);
+ enable_feature(Feature::dotprod, self.asimddp && asimd);
+ enable_feature(Feature::sve, self.sve && asimd);
+
+ // Crypto is specified as AES + PMULL + SHA1 + SHA2 per LLVM/hosts.cpp
+ enable_feature(
+ Feature::crypto,
+ self.aes && self.pmull && self.sha1 && self.sha2,
+ );
+ }
+ value
+ }
+}