|
| 1 | +//! Stuff for handling `#[target_feature]` (needed for unsafe check). |
| 2 | +
|
| 3 | +use std::sync::LazyLock; |
| 4 | + |
| 5 | +use hir_def::attr::Attrs; |
| 6 | +use hir_def::tt; |
| 7 | +use intern::{sym, Symbol}; |
| 8 | +use rustc_hash::{FxHashMap, FxHashSet}; |
| 9 | + |
| 10 | +#[derive(Debug, Default)] |
| 11 | +pub struct TargetFeatures { |
| 12 | + pub(crate) enabled: FxHashSet<Symbol>, |
| 13 | +} |
| 14 | + |
| 15 | +impl TargetFeatures { |
| 16 | + pub fn from_attrs(attrs: &Attrs) -> Self { |
| 17 | + let mut result = TargetFeatures::from_attrs_no_implications(attrs); |
| 18 | + result.expand_implications(); |
| 19 | + result |
| 20 | + } |
| 21 | + |
| 22 | + fn expand_implications(&mut self) { |
| 23 | + let all_implications = LazyLock::force(&TARGET_FEATURE_IMPLICATIONS); |
| 24 | + let mut queue = self.enabled.iter().cloned().collect::<Vec<_>>(); |
| 25 | + while let Some(feature) = queue.pop() { |
| 26 | + if let Some(implications) = all_implications.get(&feature) { |
| 27 | + for implication in implications { |
| 28 | + if self.enabled.insert(implication.clone()) { |
| 29 | + queue.push(implication.clone()); |
| 30 | + } |
| 31 | + } |
| 32 | + } |
| 33 | + } |
| 34 | + } |
| 35 | + |
| 36 | + /// Retrieves the target features from the attributes, and does not expand the target features implied by them. |
| 37 | + pub(crate) fn from_attrs_no_implications(attrs: &Attrs) -> Self { |
| 38 | + let enabled = attrs |
| 39 | + .by_key(&sym::target_feature) |
| 40 | + .tt_values() |
| 41 | + .filter_map(|tt| { |
| 42 | + match tt.token_trees().flat_tokens() { |
| 43 | + [ |
| 44 | + tt::TokenTree::Leaf(tt::Leaf::Ident(enable_ident)), |
| 45 | + tt::TokenTree::Leaf(tt::Leaf::Punct(tt::Punct { char: '=', .. })), |
| 46 | + tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal { kind: tt::LitKind::Str, symbol: features, .. })), |
| 47 | + ] if enable_ident.sym == sym::enable => Some(features), |
| 48 | + _ => None, |
| 49 | + } |
| 50 | + }) |
| 51 | + .flat_map(|features| features.as_str().split(',').map(Symbol::intern)) |
| 52 | + .collect(); |
| 53 | + Self { enabled } |
| 54 | + } |
| 55 | +} |
| 56 | + |
| 57 | +// List of the target features each target feature implies. |
| 58 | +// Ideally we'd depend on rustc for this, but rustc_target doesn't compile on stable, |
| 59 | +// and t-compiler prefers for it to stay this way. |
| 60 | + |
| 61 | +static TARGET_FEATURE_IMPLICATIONS: LazyLock<FxHashMap<Symbol, Box<[Symbol]>>> = |
| 62 | + LazyLock::new(|| { |
| 63 | + let mut result = FxHashMap::<Symbol, FxHashSet<Symbol>>::default(); |
| 64 | + for &(feature_str, implications) in TARGET_FEATURE_IMPLICATIONS_RAW { |
| 65 | + let feature = Symbol::intern(feature_str); |
| 66 | + let implications = implications.iter().copied().map(Symbol::intern); |
| 67 | + // Some target features appear in two archs, e.g. Arm and x86. |
| 68 | + // Sometimes they contain different implications, e.g. `aes`. |
| 69 | + // We should probably choose by the active arch, but for now just merge them. |
| 70 | + result.entry(feature).or_default().extend(implications); |
| 71 | + } |
| 72 | + let mut result = result |
| 73 | + .into_iter() |
| 74 | + .map(|(feature, implications)| (feature, Box::from_iter(implications))) |
| 75 | + .collect::<FxHashMap<_, _>>(); |
| 76 | + result.shrink_to_fit(); |
| 77 | + result |
| 78 | + }); |
| 79 | + |
| 80 | +// spellchecker:off |
| 81 | +const TARGET_FEATURE_IMPLICATIONS_RAW: &[(&str, &[&str])] = &[ |
| 82 | + // Arm |
| 83 | + ("aes", &["neon"]), |
| 84 | + ("dotprod", &["neon"]), |
| 85 | + ("fp-armv8", &["vfp4"]), |
| 86 | + ("fp16", &["neon"]), |
| 87 | + ("i8mm", &["neon"]), |
| 88 | + ("neon", &["vfp3"]), |
| 89 | + ("sha2", &["neon"]), |
| 90 | + ("v6", &["v5te"]), |
| 91 | + ("v6k", &["v6"]), |
| 92 | + ("v6t2", &["v6k", "thumb2"]), |
| 93 | + ("v7", &["v6t2"]), |
| 94 | + ("v8", &["v7"]), |
| 95 | + ("vfp3", &["vfp2", "d32"]), |
| 96 | + ("vfp4", &["vfp3"]), |
| 97 | + // Aarch64 |
| 98 | + ("aes", &["neon"]), |
| 99 | + ("dotprod", &["neon"]), |
| 100 | + ("dpb2", &["dpb"]), |
| 101 | + ("f32mm", &["sve"]), |
| 102 | + ("f64mm", &["sve"]), |
| 103 | + ("fcma", &["neon"]), |
| 104 | + ("fhm", &["fp16"]), |
| 105 | + ("fp16", &["neon"]), |
| 106 | + ("fp8", &["faminmax", "lut", "bf16"]), |
| 107 | + ("fp8dot2", &["fp8dot4"]), |
| 108 | + ("fp8dot4", &["fp8fma"]), |
| 109 | + ("fp8fma", &["fp8"]), |
| 110 | + ("jsconv", &["neon"]), |
| 111 | + ("lse128", &["lse"]), |
| 112 | + ("rcpc2", &["rcpc"]), |
| 113 | + ("rcpc3", &["rcpc2"]), |
| 114 | + ("rdm", &["neon"]), |
| 115 | + ("sha2", &["neon"]), |
| 116 | + ("sha3", &["sha2"]), |
| 117 | + ("sm4", &["neon"]), |
| 118 | + ("sme", &["bf16"]), |
| 119 | + ("sme-b16b16", &["bf16", "sme2", "sve-b16b16"]), |
| 120 | + ("sme-f16f16", &["sme2"]), |
| 121 | + ("sme-f64f64", &["sme"]), |
| 122 | + ("sme-f8f16", &["sme-f8f32"]), |
| 123 | + ("sme-f8f32", &["sme2", "fp8"]), |
| 124 | + ("sme-fa64", &["sme", "sve2"]), |
| 125 | + ("sme-i16i64", &["sme"]), |
| 126 | + ("sme2", &["sme"]), |
| 127 | + ("sme2p1", &["sme2"]), |
| 128 | + ("ssve-fp8dot2", &["ssve-fp8dot4"]), |
| 129 | + ("ssve-fp8dot4", &["ssve-fp8fma"]), |
| 130 | + ("ssve-fp8fma", &["sme2", "fp8"]), |
| 131 | + ("sve", &["neon"]), |
| 132 | + ("sve-b16b16", &["bf16"]), |
| 133 | + ("sve2", &["sve"]), |
| 134 | + ("sve2-aes", &["sve2", "aes"]), |
| 135 | + ("sve2-bitperm", &["sve2"]), |
| 136 | + ("sve2-sha3", &["sve2", "sha3"]), |
| 137 | + ("sve2-sm4", &["sve2", "sm4"]), |
| 138 | + ("sve2p1", &["sve2"]), |
| 139 | + ("v8.1a", &["crc", "lse", "rdm", "pan", "lor", "vh"]), |
| 140 | + ("v8.2a", &["v8.1a", "ras", "dpb"]), |
| 141 | + ("v8.3a", &["v8.2a", "rcpc", "paca", "pacg", "jsconv"]), |
| 142 | + ("v8.4a", &["v8.3a", "dotprod", "dit", "flagm"]), |
| 143 | + ("v8.5a", &["v8.4a", "ssbs", "sb", "dpb2", "bti"]), |
| 144 | + ("v8.6a", &["v8.5a", "bf16", "i8mm"]), |
| 145 | + ("v8.7a", &["v8.6a", "wfxt"]), |
| 146 | + ("v8.8a", &["v8.7a", "hbc", "mops"]), |
| 147 | + ("v8.9a", &["v8.8a", "cssc"]), |
| 148 | + ("v9.1a", &["v9a", "v8.6a"]), |
| 149 | + ("v9.2a", &["v9.1a", "v8.7a"]), |
| 150 | + ("v9.3a", &["v9.2a", "v8.8a"]), |
| 151 | + ("v9.4a", &["v9.3a", "v8.9a"]), |
| 152 | + ("v9.5a", &["v9.4a"]), |
| 153 | + ("v9a", &["v8.5a", "sve2"]), |
| 154 | + // x86 |
| 155 | + ("aes", &["sse2"]), |
| 156 | + ("amx-bf16", &["amx-tile"]), |
| 157 | + ("amx-complex", &["amx-tile"]), |
| 158 | + ("amx-fp16", &["amx-tile"]), |
| 159 | + ("amx-int8", &["amx-tile"]), |
| 160 | + ("avx", &["sse4.2"]), |
| 161 | + ("avx2", &["avx"]), |
| 162 | + ("avx512bf16", &["avx512bw"]), |
| 163 | + ("avx512bitalg", &["avx512bw"]), |
| 164 | + ("avx512bw", &["avx512f"]), |
| 165 | + ("avx512cd", &["avx512f"]), |
| 166 | + ("avx512dq", &["avx512f"]), |
| 167 | + ("avx512f", &["avx2", "fma", "f16c"]), |
| 168 | + ("avx512fp16", &["avx512bw", "avx512vl", "avx512dq"]), |
| 169 | + ("avx512ifma", &["avx512f"]), |
| 170 | + ("avx512vbmi", &["avx512bw"]), |
| 171 | + ("avx512vbmi2", &["avx512bw"]), |
| 172 | + ("avx512vl", &["avx512f"]), |
| 173 | + ("avx512vnni", &["avx512f"]), |
| 174 | + ("avx512vp2intersect", &["avx512f"]), |
| 175 | + ("avx512vpopcntdq", &["avx512f"]), |
| 176 | + ("avxifma", &["avx2"]), |
| 177 | + ("avxneconvert", &["avx2"]), |
| 178 | + ("avxvnni", &["avx2"]), |
| 179 | + ("avxvnniint16", &["avx2"]), |
| 180 | + ("avxvnniint8", &["avx2"]), |
| 181 | + ("f16c", &["avx"]), |
| 182 | + ("fma", &["avx"]), |
| 183 | + ("gfni", &["sse2"]), |
| 184 | + ("kl", &["sse2"]), |
| 185 | + ("pclmulqdq", &["sse2"]), |
| 186 | + ("sha", &["sse2"]), |
| 187 | + ("sha512", &["avx2"]), |
| 188 | + ("sm3", &["avx"]), |
| 189 | + ("sm4", &["avx2"]), |
| 190 | + ("sse2", &["sse"]), |
| 191 | + ("sse3", &["sse2"]), |
| 192 | + ("sse4.1", &["ssse3"]), |
| 193 | + ("sse4.2", &["sse4.1"]), |
| 194 | + ("sse4a", &["sse3"]), |
| 195 | + ("ssse3", &["sse3"]), |
| 196 | + ("vaes", &["avx2", "aes"]), |
| 197 | + ("vpclmulqdq", &["avx", "pclmulqdq"]), |
| 198 | + ("widekl", &["kl"]), |
| 199 | + ("xop", &[/*"fma4", */ "avx", "sse4a"]), |
| 200 | + ("xsavec", &["xsave"]), |
| 201 | + ("xsaveopt", &["xsave"]), |
| 202 | + ("xsaves", &["xsave"]), |
| 203 | + // Hexagon |
| 204 | + ("hvx-length128b", &["hvx"]), |
| 205 | + // PowerPC |
| 206 | + ("power10-vector", &["power9-vector"]), |
| 207 | + ("power8-altivec", &["altivec"]), |
| 208 | + ("power8-crypto", &["power8-altivec"]), |
| 209 | + ("power8-vector", &["vsx", "power8-altivec"]), |
| 210 | + ("power9-altivec", &["power8-altivec"]), |
| 211 | + ("power9-vector", &["power8-vector", "power9-altivec"]), |
| 212 | + ("vsx", &["altivec"]), |
| 213 | + // MIPS |
| 214 | + // RISC-V |
| 215 | + ("a", &["zaamo", "zalrsc"]), |
| 216 | + ("d", &["f"]), |
| 217 | + ("zabha", &["zaamo"]), |
| 218 | + ("zdinx", &["zfinx"]), |
| 219 | + ("zfh", &["zfhmin"]), |
| 220 | + ("zfhmin", &["f"]), |
| 221 | + ("zhinx", &["zhinxmin"]), |
| 222 | + ("zhinxmin", &["zfinx"]), |
| 223 | + ("zk", &["zkn", "zkr", "zkt"]), |
| 224 | + ("zkn", &["zbkb", "zbkc", "zbkx", "zkne", "zknd", "zknh"]), |
| 225 | + ("zks", &["zbkb", "zbkc", "zbkx", "zksed", "zksh"]), |
| 226 | + // WASM |
| 227 | + ("relaxed-simd", &["simd128"]), |
| 228 | + // BPF |
| 229 | + ("alu32", &[]), |
| 230 | + // CSKY |
| 231 | + ("10e60", &["7e10"]), |
| 232 | + ("2e3", &["e2"]), |
| 233 | + ("3e3r2", &["3e3r1", "doloop"]), |
| 234 | + ("3e3r3", &["doloop"]), |
| 235 | + ("3e7", &["2e3"]), |
| 236 | + ("7e10", &["3e7"]), |
| 237 | + ("e1", &["elrw"]), |
| 238 | + ("e2", &["e2"]), |
| 239 | + ("mp", &["2e3"]), |
| 240 | + ("mp1e2", &["3e7"]), |
| 241 | + // LoongArch |
| 242 | + ("d", &["f"]), |
| 243 | + ("lasx", &["lsx"]), |
| 244 | + ("lsx", &["d"]), |
| 245 | + // IBM Z |
| 246 | + ("nnp-assist", &["vector"]), |
| 247 | + ("vector-enhancements-1", &["vector"]), |
| 248 | + ("vector-enhancements-2", &["vector-enhancements-1"]), |
| 249 | + ("vector-packed-decimal", &["vector"]), |
| 250 | + ("vector-packed-decimal-enhancement", &["vector-packed-decimal"]), |
| 251 | + ("vector-packed-decimal-enhancement-2", &["vector-packed-decimal-enhancement"]), |
| 252 | + // SPARC |
| 253 | + // m68k |
| 254 | + ("isa-68010", &["isa-68000"]), |
| 255 | + ("isa-68020", &["isa-68010"]), |
| 256 | + ("isa-68030", &["isa-68020"]), |
| 257 | + ("isa-68040", &["isa-68030", "isa-68882"]), |
| 258 | + ("isa-68060", &["isa-68040"]), |
| 259 | + ("isa-68882", &["isa-68881"]), |
| 260 | +]; |
| 261 | +// spellchecker:on |
0 commit comments