1use core::fmt;
16use core::str::FromStr;
17
18use crate::{Error, TargetTuple};
19
20#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
25pub enum Tier {
26 Supported,
30 SupportedWithEvidence,
33 InProgress,
35 Recognized,
41}
42
43impl Tier {
44 pub const fn number(self) -> u8 {
46 match self {
47 Tier::Supported => 1,
48 Tier::SupportedWithEvidence => 2,
49 Tier::InProgress => 3,
50 Tier::Recognized => 4,
51 }
52 }
53
54 pub const fn describe(self) -> &'static str {
57 match self {
58 Tier::Supported => "supported",
59 Tier::SupportedWithEvidence => "supported, with the evidence column saying how",
60 Tier::InProgress => "in progress, named in the table, not claimed",
61 Tier::Recognized => "recognized",
62 }
63 }
64
65 pub const fn compiles_and_links(self) -> bool {
70 !matches!(self, Tier::Recognized)
71 }
72}
73
74impl fmt::Display for Tier {
75 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
76 write!(f, "{}", self.number())
77 }
78}
79
80#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
83pub enum Host {
84 Yes,
86 Planned,
88 No,
90}
91
92impl Host {
93 pub const fn as_str(self) -> &'static str {
95 match self {
96 Host::Yes => "yes",
97 Host::Planned => "later",
98 Host::No => "no",
99 }
100 }
101}
102
103impl fmt::Display for Host {
104 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
105 f.write_str(self.as_str())
106 }
107}
108
109#[derive(Debug, Clone, Copy, PartialEq, Eq)]
111pub struct TargetEntry {
112 pub tuple: &'static str,
115 pub tier: Tier,
117 pub planned: Tier,
119 pub host: Host,
121 pub note: &'static str,
123}
124
125impl TargetEntry {
126 pub fn parse(&self) -> Result<TargetTuple, Error> {
132 TargetTuple::from_str(self.tuple)
133 }
134}
135
136pub const TARGETS: &[TargetEntry] = &[
143 TargetEntry {
145 tuple: "x86_64-linux-gnu",
146 tier: Tier::SupportedWithEvidence,
147 planned: Tier::Supported,
148 host: Host::Yes,
149 note: "the reference target, and everything is measured here first",
150 },
151 TargetEntry {
152 tuple: "x86_64-linux-musl",
153 tier: Tier::Recognized,
154 planned: Tier::Supported,
155 host: Host::Yes,
156 note: "the easiest sysroot in existence, and the first cross target",
157 },
158 TargetEntry {
159 tuple: "aarch64-linux-gnu",
160 tier: Tier::Recognized,
161 planned: Tier::Supported,
162 host: Host::Yes,
163 note: "char is unsigned here and signed on x86-64, which is the classic bug",
164 },
165 TargetEntry {
166 tuple: "aarch64-linux-musl",
167 tier: Tier::Recognized,
168 planned: Tier::Supported,
169 host: Host::Yes,
170 note: "the pair that proves the libc and the architecture are separate axes",
171 },
172 TargetEntry {
173 tuple: "riscv64-linux-gnu",
174 tier: Tier::Recognized,
175 planned: Tier::Supported,
176 host: Host::Planned,
177 note: "the middle end canary, with no condition codes and no complex addressing",
178 },
179 TargetEntry {
180 tuple: "riscv64-linux-musl",
181 tier: Tier::Recognized,
182 planned: Tier::SupportedWithEvidence,
183 host: Host::No,
184 note: "",
185 },
186 TargetEntry {
187 tuple: "i686-linux-gnu",
188 tier: Tier::Recognized,
189 planned: Tier::SupportedWithEvidence,
190 host: Host::No,
191 note: "x87 long double is the type here rather than a corner case",
192 },
193 TargetEntry {
194 tuple: "armv7-linux-gnueabihf",
195 tier: Tier::Recognized,
196 planned: Tier::SupportedWithEvidence,
197 host: Host::No,
198 note: "soft, softfp and hard is an ABI, so it is in the tuple",
199 },
200 TargetEntry {
201 tuple: "armv7-linux-musleabihf",
202 tier: Tier::Recognized,
203 planned: Tier::SupportedWithEvidence,
204 host: Host::No,
205 note: "",
206 },
207 TargetEntry {
208 tuple: "loongarch64-linux-gnu",
209 tier: Tier::Recognized,
210 planned: Tier::SupportedWithEvidence,
211 host: Host::No,
212 note: "LP64D only, and r21 is reserved by the psABI and used by Linux as a percpu base",
213 },
214 TargetEntry {
215 tuple: "powerpc64le-linux-gnu",
216 tier: Tier::Recognized,
217 planned: Tier::SupportedWithEvidence,
218 host: Host::No,
219 note: "ELFv2, with the TOC and the split between local and global entry points",
220 },
221 TargetEntry {
222 tuple: "s390x-linux-gnu",
223 tier: Tier::Recognized,
224 planned: Tier::SupportedWithEvidence,
225 host: Host::No,
226 note: "the big endian row, and the only one with a commercial user base",
227 },
228 TargetEntry {
229 tuple: "aarch64-linux-android",
230 tier: Tier::Recognized,
231 planned: Tier::SupportedWithEvidence,
232 host: Host::No,
233 note: "bionic, API level stub sets, and the packed relocation trap below API 35",
234 },
235 TargetEntry {
236 tuple: "x86_64-linux-android",
237 tier: Tier::Recognized,
238 planned: Tier::InProgress,
239 host: Host::No,
240 note: "the emulator target, which is cheap once aarch64 works",
241 },
242 TargetEntry {
243 tuple: "riscv64-linux-android",
244 tier: Tier::Recognized,
245 planned: Tier::Recognized,
246 host: Host::No,
247 note: "requires an RVA23 baseline, so it is recognized only",
248 },
249 TargetEntry {
250 tuple: "x86_64-linux-gnux32",
251 tier: Tier::Recognized,
252 planned: Tier::Recognized,
253 host: Host::No,
254 note: "ILP32 on a 64-bit ISA, and it exists to prove the data model field is real",
255 },
256 TargetEntry {
258 tuple: "aarch64-macos",
259 tier: Tier::Recognized,
260 planned: Tier::Supported,
261 host: Host::Yes,
262 note: "the four AAPCS64 divergences of the compiler repository's document 12.3",
263 },
264 TargetEntry {
265 tuple: "x86_64-macos",
266 tier: Tier::Recognized,
267 planned: Tier::SupportedWithEvidence,
268 host: Host::Yes,
269 note: "still shipping, and Rosetta makes it how an aarch64 host tests x86-64",
270 },
271 TargetEntry {
272 tuple: "aarch64-ios",
273 tier: Tier::Recognized,
274 planned: Tier::InProgress,
275 host: Host::No,
276 note: "a distinct OS from macOS, with its own platform value and availability macros",
277 },
278 TargetEntry {
279 tuple: "aarch64-ios-simulator",
280 tier: Tier::Recognized,
281 planned: Tier::Recognized,
282 host: Host::No,
283 note: "three table rows rather than work, once the Darwin path exists",
284 },
285 TargetEntry {
286 tuple: "aarch64-ios-macabi",
287 tier: Tier::Recognized,
288 planned: Tier::Recognized,
289 host: Host::No,
290 note: "Mac Catalyst, which zig added in 0.16 and which costs a platform value",
291 },
292 TargetEntry {
294 tuple: "x86_64-windows-gnu",
295 tier: Tier::Recognized,
296 planned: Tier::Supported,
297 host: Host::Yes,
298 note: "mingw-w64, and the default env for Windows because it is the one we can ship",
299 },
300 TargetEntry {
301 tuple: "x86_64-windows-msvc",
302 tier: Tier::Recognized,
303 planned: Tier::SupportedWithEvidence,
304 host: Host::Yes,
305 note: "needs a fetched SDK, so the ABI is ours and the dialect is not",
306 },
307 TargetEntry {
308 tuple: "aarch64-windows-gnu",
309 tier: Tier::Recognized,
310 planned: Tier::SupportedWithEvidence,
311 host: Host::Yes,
312 note: "",
313 },
314 TargetEntry {
315 tuple: "aarch64-windows-msvc",
316 tier: Tier::Recognized,
317 planned: Tier::InProgress,
318 host: Host::Yes,
319 note: "",
320 },
321 TargetEntry {
322 tuple: "arm64ec-windows-msvc",
323 tier: Tier::Recognized,
324 planned: Tier::Recognized,
325 host: Host::No,
326 note: "a separate symbol namespace, thunks and hybrid images, declined in document 06.8",
327 },
328 TargetEntry {
329 tuple: "i686-windows-gnu",
330 tier: Tier::Recognized,
331 planned: Tier::InProgress,
332 host: Host::No,
333 note: "stdcall, fastcall and thiscall decoration, the only place C has mangling",
334 },
335 TargetEntry {
337 tuple: "x86_64-freebsd",
338 tier: Tier::Recognized,
339 planned: Tier::SupportedWithEvidence,
340 host: Host::Planned,
341 note: "stub libraries, as zig does, and FreeBSD 14 or later",
342 },
343 TargetEntry {
344 tuple: "aarch64-freebsd",
345 tier: Tier::Recognized,
346 planned: Tier::SupportedWithEvidence,
347 host: Host::Planned,
348 note: "",
349 },
350 TargetEntry {
351 tuple: "x86_64-netbsd",
352 tier: Tier::Recognized,
353 planned: Tier::InProgress,
354 host: Host::No,
355 note: "NetBSD 10.1 or later",
356 },
357 TargetEntry {
358 tuple: "aarch64-netbsd",
359 tier: Tier::Recognized,
360 planned: Tier::InProgress,
361 host: Host::No,
362 note: "",
363 },
364 TargetEntry {
365 tuple: "x86_64-openbsd",
366 tier: Tier::Recognized,
367 planned: Tier::InProgress,
368 host: Host::No,
369 note: "dynamic libc only, and zig took a whole release to add it",
370 },
371 TargetEntry {
372 tuple: "x86_64-illumos",
373 tier: Tier::Recognized,
374 planned: Tier::Recognized,
375 host: Host::No,
376 note: "open, therefore admissible, therefore not excluded on principle",
377 },
378 TargetEntry {
379 tuple: "x86_64-none",
380 tier: Tier::InProgress,
381 planned: Tier::Supported,
382 host: Host::No,
383 note: "the kernel target, which rung 4 needs and needs at tier 1",
384 },
385 TargetEntry {
386 tuple: "aarch64-none",
387 tier: Tier::InProgress,
388 planned: Tier::Supported,
389 host: Host::No,
390 note: "",
391 },
392 TargetEntry {
393 tuple: "riscv64-none",
394 tier: Tier::InProgress,
395 planned: Tier::Supported,
396 host: Host::No,
397 note: "",
398 },
399 TargetEntry {
400 tuple: "i686-none",
401 tier: Tier::InProgress,
402 planned: Tier::SupportedWithEvidence,
403 host: Host::No,
404 note: "capped at its architecture's tier, per the note at the top of this module",
405 },
406 TargetEntry {
407 tuple: "armv7-none-eabi",
408 tier: Tier::InProgress,
409 planned: Tier::SupportedWithEvidence,
410 host: Host::No,
411 note: "soft float, because a bare metal core may have no FPU",
412 },
413 TargetEntry {
414 tuple: "armv7m-none-eabi",
415 tier: Tier::InProgress,
416 planned: Tier::SupportedWithEvidence,
417 host: Host::No,
418 note: "Thumb only, and the smallest target in the table",
419 },
420 TargetEntry {
421 tuple: "wasm32-wasip1",
422 tier: Tier::Recognized,
423 planned: Tier::SupportedWithEvidence,
424 host: Host::No,
425 note: "one linear memory, no signals, and structured control flow",
426 },
427 TargetEntry {
428 tuple: "wasm32-wasip3",
429 tier: Tier::Recognized,
430 planned: Tier::InProgress,
431 host: Host::No,
432 note: "a different ABI from p1 and p2, with the stack pointer and TLS base in a context",
433 },
434 TargetEntry {
435 tuple: "wasm32-none",
436 tier: Tier::Recognized,
437 planned: Tier::SupportedWithEvidence,
438 host: Host::No,
439 note: "freestanding wasm, which is the second back end without the libc question",
440 },
441];
442
443pub fn lookup(target: &TargetTuple) -> Option<&'static TargetEntry> {
448 let canonical = target.to_canonical_string();
449 TARGETS.iter().find(|entry| entry.tuple == canonical)
450}
451
452pub fn counts_by_planned_tier() -> [usize; 4] {
457 let mut counts = [0usize; 4];
458 for entry in TARGETS {
459 counts[usize::from(entry.planned.number()) - 1] += 1;
460 }
461 counts
462}
463
464pub fn planned_working_count() -> usize {
467 TARGETS.iter().filter(|entry| entry.planned.compiles_and_links()).count()
468}