1// This file defines all the identifier enums and target-aware logic.
2
3use crate::triple::{Endianness, PointerWidth, Triple};
4use alloc::borrow::Cow;
5use alloc::boxed::Box;
6use alloc::format;
7use alloc::string::String;
8use core::fmt;
9use core::hash::{Hash, Hasher};
10use core::str::FromStr;
11
12/// The "architecture" field, which in some cases also specifies a specific
13/// subarchitecture.
14#[cfg_attr(feature = "rust_1_40", non_exhaustive)]
15#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
16#[allow(missing_docs)]
17pub enum Architecture {
18 Unknown,
19 Arm(ArmArchitecture),
20 AmdGcn,
21 Aarch64(Aarch64Architecture),
22 Asmjs,
23 Avr,
24 Bpfeb,
25 Bpfel,
26 Hexagon,
27 X86_32(X86_32Architecture),
28 M68k,
29 LoongArch64,
30 Mips32(Mips32Architecture),
31 Mips64(Mips64Architecture),
32 Msp430,
33 Nvptx64,
34 Powerpc,
35 Powerpc64,
36 Powerpc64le,
37 Riscv32(Riscv32Architecture),
38 Riscv64(Riscv64Architecture),
39 S390x,
40 Sparc,
41 Sparc64,
42 Sparcv9,
43 Wasm32,
44 Wasm64,
45 X86_64,
46 /// x86_64 target that only supports Haswell-compatible Intel chips.
47 X86_64h,
48 XTensa,
49 Clever(CleverArchitecture),
50 /// A software machine that produces zero-knowledge proofs of the execution.
51 ///
52 /// See https://wiki.polygon.technology/docs/category/zk-assembly/
53 #[cfg(feature = "arch_zkasm")]
54 ZkAsm,
55}
56
57#[cfg_attr(feature = "rust_1_40", non_exhaustive)]
58#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
59#[allow(missing_docs)]
60pub enum ArmArchitecture {
61 Arm, // Generic arm
62 Armeb,
63 Armv4,
64 Armv4t,
65 Armv5t,
66 Armv5te,
67 Armv5tej,
68 Armv6,
69 Armv6j,
70 Armv6k,
71 Armv6z,
72 Armv6kz,
73 Armv6t2,
74 Armv6m,
75 Armv7,
76 Armv7a,
77 Armv7k,
78 Armv7ve,
79 Armv7m,
80 Armv7r,
81 Armv7s,
82 Armv8,
83 Armv8a,
84 Armv8_1a,
85 Armv8_2a,
86 Armv8_3a,
87 Armv8_4a,
88 Armv8_5a,
89 Armv8mBase,
90 Armv8mMain,
91 Armv8r,
92
93 Armebv7r,
94
95 Thumbeb,
96 Thumbv4t,
97 Thumbv5te,
98 Thumbv6m,
99 Thumbv7a,
100 Thumbv7em,
101 Thumbv7m,
102 Thumbv7neon,
103 Thumbv8mBase,
104 Thumbv8mMain,
105}
106
107#[cfg_attr(feature = "rust_1_40", non_exhaustive)]
108#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
109#[allow(missing_docs)]
110pub enum Aarch64Architecture {
111 Aarch64,
112 Aarch64be,
113}
114
115// #[cfg_attr(feature = "rust_1_40", non_exhaustive)]
116// #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
117// #[allow(missing_docs)]
118// pub enum ArmFpu {
119// Vfp,
120// Vfpv2,
121// Vfpv3,
122// Vfpv3Fp16,
123// Vfpv3Xd,
124// Vfpv3XdFp16,
125// Neon,
126// NeonVfpv3,
127// NeonVfpv4,
128// Vfpv4,
129// Vfpv4D16,
130// Fpv4SpD16,
131// Fpv5SpD16,
132// Fpv5D16,
133// FpArmv8,
134// NeonFpArmv8,
135// CryptoNeonFpArmv8,
136// }
137
138impl ArmArchitecture {
139 /// Test if this architecture uses the Thumb instruction set.
140 #[rustfmt::skip]
141 pub fn is_thumb(self) -> bool {
142 use ArmArchitecture::*;
143
144 match self {
145 Arm
146 | Armeb
147 | Armv4
148 | Armv4t
149 | Armv5t
150 | Armv5te
151 | Armv5tej
152 | Armv6
153 | Armv6j
154 | Armv6k
155 | Armv6z
156 | Armv6kz
157 | Armv6t2
158 | Armv6m
159 | Armv7
160 | Armv7a
161 | Armv7k
162 | Armv7ve
163 | Armv7m
164 | Armv7r
165 | Armv7s
166 | Armv8
167 | Armv8a
168 | Armv8_1a
169 | Armv8_2a
170 | Armv8_3a
171 | Armv8_4a
172 | Armv8_5a
173 | Armv8mBase
174 | Armv8mMain
175 | Armv8r
176 | Armebv7r => false,
177 Thumbeb
178 | Thumbv4t
179 | Thumbv5te
180 | Thumbv6m
181 | Thumbv7a
182 | Thumbv7em
183 | Thumbv7m
184 | Thumbv7neon
185 | Thumbv8mBase
186 | Thumbv8mMain => true,
187 }
188 }
189
190 // pub fn has_fpu(self) -> Result<&'static [ArmFpu], ()> {
191
192 // }
193
194 /// Return the pointer bit width of this target's architecture.
195 #[rustfmt::skip]
196 pub fn pointer_width(self) -> PointerWidth {
197 use ArmArchitecture::*;
198
199 match self {
200 Arm
201 | Armeb
202 | Armv4
203 | Armv4t
204 | Armv5t
205 | Armv5te
206 | Armv5tej
207 | Armv6
208 | Armv6j
209 | Armv6k
210 | Armv6z
211 | Armv6kz
212 | Armv6t2
213 | Armv6m
214 | Armv7
215 | Armv7a
216 | Armv7k
217 | Armv7ve
218 | Armv7m
219 | Armv7r
220 | Armv7s
221 | Armv8
222 | Armv8a
223 | Armv8_1a
224 | Armv8_2a
225 | Armv8_3a
226 | Armv8_4a
227 | Armv8_5a
228 | Armv8mBase
229 | Armv8mMain
230 | Armv8r
231 | Armebv7r
232 | Thumbeb
233 | Thumbv4t
234 | Thumbv5te
235 | Thumbv6m
236 | Thumbv7a
237 | Thumbv7em
238 | Thumbv7m
239 | Thumbv7neon
240 | Thumbv8mBase
241 | Thumbv8mMain => PointerWidth::U32,
242 }
243 }
244
245 /// Return the endianness of this architecture.
246 #[rustfmt::skip]
247 pub fn endianness(self) -> Endianness {
248 use ArmArchitecture::*;
249
250 match self {
251 Arm
252 | Armv4
253 | Armv4t
254 | Armv5t
255 | Armv5te
256 | Armv5tej
257 | Armv6
258 | Armv6j
259 | Armv6k
260 | Armv6z
261 | Armv6kz
262 | Armv6t2
263 | Armv6m
264 | Armv7
265 | Armv7a
266 | Armv7k
267 | Armv7ve
268 | Armv7m
269 | Armv7r
270 | Armv7s
271 | Armv8
272 | Armv8a
273 | Armv8_1a
274 | Armv8_2a
275 | Armv8_3a
276 | Armv8_4a
277 | Armv8_5a
278 | Armv8mBase
279 | Armv8mMain
280 | Armv8r
281 | Thumbv4t
282 | Thumbv5te
283 | Thumbv6m
284 | Thumbv7a
285 | Thumbv7em
286 | Thumbv7m
287 | Thumbv7neon
288 | Thumbv8mBase
289 | Thumbv8mMain => Endianness::Little,
290 Armeb | Armebv7r | Thumbeb => Endianness::Big,
291 }
292 }
293
294 /// Convert into a string
295 pub fn into_str(self) -> Cow<'static, str> {
296 use ArmArchitecture::*;
297
298 match self {
299 Arm => Cow::Borrowed("arm"),
300 Armeb => Cow::Borrowed("armeb"),
301 Armv4 => Cow::Borrowed("armv4"),
302 Armv4t => Cow::Borrowed("armv4t"),
303 Armv5t => Cow::Borrowed("armv5t"),
304 Armv5te => Cow::Borrowed("armv5te"),
305 Armv5tej => Cow::Borrowed("armv5tej"),
306 Armv6 => Cow::Borrowed("armv6"),
307 Armv6j => Cow::Borrowed("armv6j"),
308 Armv6k => Cow::Borrowed("armv6k"),
309 Armv6z => Cow::Borrowed("armv6z"),
310 Armv6kz => Cow::Borrowed("armv6kz"),
311 Armv6t2 => Cow::Borrowed("armv6t2"),
312 Armv6m => Cow::Borrowed("armv6m"),
313 Armv7 => Cow::Borrowed("armv7"),
314 Armv7a => Cow::Borrowed("armv7a"),
315 Armv7k => Cow::Borrowed("armv7k"),
316 Armv7ve => Cow::Borrowed("armv7ve"),
317 Armv7m => Cow::Borrowed("armv7m"),
318 Armv7r => Cow::Borrowed("armv7r"),
319 Armv7s => Cow::Borrowed("armv7s"),
320 Armv8 => Cow::Borrowed("armv8"),
321 Armv8a => Cow::Borrowed("armv8a"),
322 Armv8_1a => Cow::Borrowed("armv8.1a"),
323 Armv8_2a => Cow::Borrowed("armv8.2a"),
324 Armv8_3a => Cow::Borrowed("armv8.3a"),
325 Armv8_4a => Cow::Borrowed("armv8.4a"),
326 Armv8_5a => Cow::Borrowed("armv8.5a"),
327 Armv8mBase => Cow::Borrowed("armv8m.base"),
328 Armv8mMain => Cow::Borrowed("armv8m.main"),
329 Armv8r => Cow::Borrowed("armv8r"),
330 Thumbeb => Cow::Borrowed("thumbeb"),
331 Thumbv4t => Cow::Borrowed("thumbv4t"),
332 Thumbv5te => Cow::Borrowed("thumbv5te"),
333 Thumbv6m => Cow::Borrowed("thumbv6m"),
334 Thumbv7a => Cow::Borrowed("thumbv7a"),
335 Thumbv7em => Cow::Borrowed("thumbv7em"),
336 Thumbv7m => Cow::Borrowed("thumbv7m"),
337 Thumbv7neon => Cow::Borrowed("thumbv7neon"),
338 Thumbv8mBase => Cow::Borrowed("thumbv8m.base"),
339 Thumbv8mMain => Cow::Borrowed("thumbv8m.main"),
340 Armebv7r => Cow::Borrowed("armebv7r"),
341 }
342 }
343}
344
345impl Aarch64Architecture {
346 /// Test if this architecture uses the Thumb instruction set.
347 pub fn is_thumb(self) -> bool {
348 match self {
349 Aarch64Architecture::Aarch64 | Aarch64Architecture::Aarch64be => false,
350 }
351 }
352
353 // pub fn has_fpu(self) -> Result<&'static [ArmFpu], ()> {
354
355 // }
356
357 /// Return the pointer bit width of this target's architecture.
358 ///
359 /// This function is only aware of the CPU architecture so it is not aware
360 /// of ilp32 ABIs.
361 pub fn pointer_width(self) -> PointerWidth {
362 match self {
363 Aarch64Architecture::Aarch64 | Aarch64Architecture::Aarch64be => PointerWidth::U64,
364 }
365 }
366
367 /// Return the endianness of this architecture.
368 pub fn endianness(self) -> Endianness {
369 match self {
370 Aarch64Architecture::Aarch64 => Endianness::Little,
371 Aarch64Architecture::Aarch64be => Endianness::Big,
372 }
373 }
374
375 /// Convert into a string
376 pub fn into_str(self) -> Cow<'static, str> {
377 use Aarch64Architecture::*;
378
379 match self {
380 Aarch64 => Cow::Borrowed("aarch64"),
381 Aarch64be => Cow::Borrowed("aarch64_be"),
382 }
383 }
384}
385
386#[cfg_attr(feature = "rust_1_40", non_exhaustive)]
387#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
388#[allow(missing_docs)]
389pub enum CleverArchitecture {
390 Clever,
391 Clever1_0,
392}
393
394impl CleverArchitecture {
395 /// Convert into a string
396 pub fn into_str(self) -> Cow<'static, str> {
397 use CleverArchitecture::*;
398
399 match self {
400 Clever => Cow::Borrowed("clever"),
401 Clever1_0 => Cow::Borrowed("clever1.0"),
402 }
403 }
404}
405
406/// An enum for all 32-bit RISC-V architectures.
407#[cfg_attr(feature = "rust_1_40", non_exhaustive)]
408#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
409#[allow(missing_docs)]
410pub enum Riscv32Architecture {
411 Riscv32,
412 Riscv32gc,
413 Riscv32i,
414 Riscv32im,
415 Riscv32imac,
416 Riscv32imc,
417}
418
419impl Riscv32Architecture {
420 /// Convert into a string
421 pub fn into_str(self) -> Cow<'static, str> {
422 use Riscv32Architecture::*;
423
424 match self {
425 Riscv32 => Cow::Borrowed("riscv32"),
426 Riscv32gc => Cow::Borrowed("riscv32gc"),
427 Riscv32i => Cow::Borrowed("riscv32i"),
428 Riscv32im => Cow::Borrowed("riscv32im"),
429 Riscv32imac => Cow::Borrowed("riscv32imac"),
430 Riscv32imc => Cow::Borrowed("riscv32imc"),
431 }
432 }
433}
434
435/// An enum for all 64-bit RISC-V architectures.
436#[cfg_attr(feature = "rust_1_40", non_exhaustive)]
437#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
438#[allow(missing_docs)]
439pub enum Riscv64Architecture {
440 Riscv64,
441 Riscv64gc,
442 Riscv64imac,
443}
444
445impl Riscv64Architecture {
446 /// Convert into a string
447 pub fn into_str(self) -> Cow<'static, str> {
448 use Riscv64Architecture::*;
449
450 match self {
451 Riscv64 => Cow::Borrowed("riscv64"),
452 Riscv64gc => Cow::Borrowed("riscv64gc"),
453 Riscv64imac => Cow::Borrowed("riscv64imac"),
454 }
455 }
456}
457
458/// An enum for all 32-bit x86 architectures.
459#[cfg_attr(feature = "rust_1_40", non_exhaustive)]
460#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
461#[allow(missing_docs)]
462pub enum X86_32Architecture {
463 I386,
464 I586,
465 I686,
466}
467
468impl X86_32Architecture {
469 /// Convert into a string
470 pub fn into_str(self) -> Cow<'static, str> {
471 use X86_32Architecture::*;
472
473 match self {
474 I386 => Cow::Borrowed("i386"),
475 I586 => Cow::Borrowed("i586"),
476 I686 => Cow::Borrowed("i686"),
477 }
478 }
479}
480
481/// An enum for all 32-bit MIPS architectures (not just "MIPS32").
482#[cfg_attr(feature = "rust_1_40", non_exhaustive)]
483#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
484#[allow(missing_docs)]
485pub enum Mips32Architecture {
486 Mips,
487 Mipsel,
488 Mipsisa32r6,
489 Mipsisa32r6el,
490}
491
492impl Mips32Architecture {
493 /// Convert into a string
494 pub fn into_str(self) -> Cow<'static, str> {
495 use Mips32Architecture::*;
496
497 match self {
498 Mips => Cow::Borrowed("mips"),
499 Mipsel => Cow::Borrowed("mipsel"),
500 Mipsisa32r6 => Cow::Borrowed("mipsisa32r6"),
501 Mipsisa32r6el => Cow::Borrowed("mipsisa32r6el"),
502 }
503 }
504}
505
506/// An enum for all 64-bit MIPS architectures (not just "MIPS64").
507#[cfg_attr(feature = "rust_1_40", non_exhaustive)]
508#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
509#[allow(missing_docs)]
510pub enum Mips64Architecture {
511 Mips64,
512 Mips64el,
513 Mipsisa64r6,
514 Mipsisa64r6el,
515}
516
517impl Mips64Architecture {
518 /// Convert into a string
519 pub fn into_str(self) -> Cow<'static, str> {
520 use Mips64Architecture::*;
521
522 match self {
523 Mips64 => Cow::Borrowed("mips64"),
524 Mips64el => Cow::Borrowed("mips64el"),
525 Mipsisa64r6 => Cow::Borrowed("mipsisa64r6"),
526 Mipsisa64r6el => Cow::Borrowed("mipsisa64r6el"),
527 }
528 }
529}
530
531/// A string for a `Vendor::Custom` that can either be used in `const`
532/// contexts or hold dynamic strings.
533#[derive(Clone, Debug, Eq)]
534pub enum CustomVendor {
535 /// An owned `String`. This supports the general case.
536 Owned(Box<String>),
537 /// A static `str`, so that `CustomVendor` can be constructed in `const`
538 /// contexts.
539 Static(&'static str),
540}
541
542impl CustomVendor {
543 /// Extracts a string slice.
544 pub fn as_str(&self) -> &str {
545 match self {
546 CustomVendor::Owned(s: &Box) => s,
547 CustomVendor::Static(s: &&str) => s,
548 }
549 }
550}
551
552impl PartialEq for CustomVendor {
553 fn eq(&self, other: &Self) -> bool {
554 self.as_str() == other.as_str()
555 }
556}
557
558impl Hash for CustomVendor {
559 fn hash<H: Hasher>(&self, state: &mut H) {
560 self.as_str().hash(state)
561 }
562}
563
564/// The "vendor" field, which in practice is little more than an arbitrary
565/// modifier.
566#[cfg_attr(feature = "rust_1_40", non_exhaustive)]
567#[derive(Clone, Debug, PartialEq, Eq, Hash)]
568#[allow(missing_docs)]
569pub enum Vendor {
570 Unknown,
571 Amd,
572 Apple,
573 Espressif,
574 Experimental,
575 Fortanix,
576 Ibm,
577 Kmc,
578 Nintendo,
579 Nvidia,
580 Pc,
581 Rumprun,
582 Sun,
583 Uwp,
584 Wrs,
585
586 /// A custom vendor. "Custom" in this context means that the vendor is
587 /// not specifically recognized by upstream Autotools, LLVM, Rust, or other
588 /// relevant authorities on triple naming. It's useful for people building
589 /// and using locally patched toolchains.
590 ///
591 /// Outside of such patched environments, users of `target-lexicon` should
592 /// treat `Custom` the same as `Unknown` and ignore the string.
593 Custom(CustomVendor),
594}
595
596impl Vendor {
597 /// Extracts a string slice.
598 pub fn as_str(&self) -> &str {
599 use Vendor::*;
600
601 match self {
602 Unknown => "unknown",
603 Amd => "amd",
604 Apple => "apple",
605 Espressif => "espressif",
606 Experimental => "experimental",
607 Fortanix => "fortanix",
608 Ibm => "ibm",
609 Kmc => "kmc",
610 Nintendo => "nintendo",
611 Nvidia => "nvidia",
612 Pc => "pc",
613 Rumprun => "rumprun",
614 Sun => "sun",
615 Uwp => "uwp",
616 Wrs => "wrs",
617 Custom(name) => name.as_str(),
618 }
619 }
620}
621
622/// The "operating system" field, which sometimes implies an environment, and
623/// sometimes isn't an actual operating system.
624#[cfg_attr(feature = "rust_1_40", non_exhaustive)]
625#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
626#[allow(missing_docs)]
627pub enum OperatingSystem {
628 Unknown,
629 Aix,
630 AmdHsa,
631 Bitrig,
632 Cloudabi,
633 Cuda,
634 Darwin,
635 Dragonfly,
636 Emscripten,
637 Espidf,
638 Freebsd,
639 Fuchsia,
640 Haiku,
641 Hermit,
642 Horizon,
643 Illumos,
644 Ios,
645 L4re,
646 Linux,
647 MacOSX { major: u16, minor: u16, patch: u16 },
648 Nebulet,
649 Netbsd,
650 None_,
651 Openbsd,
652 Psp,
653 Redox,
654 Solaris,
655 SolidAsp3,
656 Tvos,
657 Uefi,
658 VxWorks,
659 Wasi,
660 WasiP1,
661 WasiP2,
662 Watchos,
663 Windows,
664}
665
666impl OperatingSystem {
667 /// Convert into a string
668 pub fn into_str(self) -> Cow<'static, str> {
669 use OperatingSystem::*;
670
671 match self {
672 Unknown => Cow::Borrowed("unknown"),
673 Aix => Cow::Borrowed("aix"),
674 AmdHsa => Cow::Borrowed("amdhsa"),
675 Bitrig => Cow::Borrowed("bitrig"),
676 Cloudabi => Cow::Borrowed("cloudabi"),
677 Cuda => Cow::Borrowed("cuda"),
678 Darwin => Cow::Borrowed("darwin"),
679 Dragonfly => Cow::Borrowed("dragonfly"),
680 Emscripten => Cow::Borrowed("emscripten"),
681 Espidf => Cow::Borrowed("espidf"),
682 Freebsd => Cow::Borrowed("freebsd"),
683 Fuchsia => Cow::Borrowed("fuchsia"),
684 Haiku => Cow::Borrowed("haiku"),
685 Hermit => Cow::Borrowed("hermit"),
686 Horizon => Cow::Borrowed("horizon"),
687 Illumos => Cow::Borrowed("illumos"),
688 Ios => Cow::Borrowed("ios"),
689 L4re => Cow::Borrowed("l4re"),
690 Linux => Cow::Borrowed("linux"),
691 MacOSX {
692 major,
693 minor,
694 patch,
695 } => Cow::Owned(format!("macosx{}.{}.{}", major, minor, patch)),
696 Nebulet => Cow::Borrowed("nebulet"),
697 Netbsd => Cow::Borrowed("netbsd"),
698 None_ => Cow::Borrowed("none"),
699 Openbsd => Cow::Borrowed("openbsd"),
700 Psp => Cow::Borrowed("psp"),
701 Redox => Cow::Borrowed("redox"),
702 Solaris => Cow::Borrowed("solaris"),
703 SolidAsp3 => Cow::Borrowed("solid_asp3"),
704 Tvos => Cow::Borrowed("tvos"),
705 Uefi => Cow::Borrowed("uefi"),
706 VxWorks => Cow::Borrowed("vxworks"),
707 Wasi => Cow::Borrowed("wasi"),
708 WasiP1 => Cow::Borrowed("wasip1"),
709 WasiP2 => Cow::Borrowed("wasip2"),
710 Watchos => Cow::Borrowed("watchos"),
711 Windows => Cow::Borrowed("windows"),
712 }
713 }
714}
715
716/// The "environment" field, which specifies an ABI environment on top of the
717/// operating system. In many configurations, this field is omitted, and the
718/// environment is implied by the operating system.
719#[cfg_attr(feature = "rust_1_40", non_exhaustive)]
720#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
721#[allow(missing_docs)]
722pub enum Environment {
723 Unknown,
724 AmdGiz,
725 Android,
726 Androideabi,
727 Eabi,
728 Eabihf,
729 Gnu,
730 Gnuabi64,
731 Gnueabi,
732 Gnueabihf,
733 Gnuspe,
734 Gnux32,
735 GnuIlp32,
736 GnuLlvm,
737 HermitKernel,
738 LinuxKernel,
739 Macabi,
740 Musl,
741 Musleabi,
742 Musleabihf,
743 Muslabi64,
744 Msvc,
745 Newlib,
746 Kernel,
747 Uclibc,
748 Uclibceabi,
749 Uclibceabihf,
750 Sgx,
751 Sim,
752 Softfloat,
753 Spe,
754 Threads,
755}
756
757impl Environment {
758 /// Convert into a string
759 pub fn into_str(self) -> Cow<'static, str> {
760 use Environment::*;
761
762 match self {
763 Unknown => Cow::Borrowed("unknown"),
764 AmdGiz => Cow::Borrowed("amdgiz"),
765 Android => Cow::Borrowed("android"),
766 Androideabi => Cow::Borrowed("androideabi"),
767 Eabi => Cow::Borrowed("eabi"),
768 Eabihf => Cow::Borrowed("eabihf"),
769 Gnu => Cow::Borrowed("gnu"),
770 Gnuabi64 => Cow::Borrowed("gnuabi64"),
771 Gnueabi => Cow::Borrowed("gnueabi"),
772 Gnueabihf => Cow::Borrowed("gnueabihf"),
773 Gnuspe => Cow::Borrowed("gnuspe"),
774 Gnux32 => Cow::Borrowed("gnux32"),
775 GnuIlp32 => Cow::Borrowed("gnu_ilp32"),
776 GnuLlvm => Cow::Borrowed("gnullvm"),
777 HermitKernel => Cow::Borrowed("hermitkernel"),
778 LinuxKernel => Cow::Borrowed("linuxkernel"),
779 Macabi => Cow::Borrowed("macabi"),
780 Musl => Cow::Borrowed("musl"),
781 Musleabi => Cow::Borrowed("musleabi"),
782 Musleabihf => Cow::Borrowed("musleabihf"),
783 Muslabi64 => Cow::Borrowed("muslabi64"),
784 Msvc => Cow::Borrowed("msvc"),
785 Newlib => Cow::Borrowed("newlib"),
786 Kernel => Cow::Borrowed("kernel"),
787 Uclibc => Cow::Borrowed("uclibc"),
788 Uclibceabi => Cow::Borrowed("uclibceabi"),
789 Uclibceabihf => Cow::Borrowed("uclibceabihf"),
790 Sgx => Cow::Borrowed("sgx"),
791 Sim => Cow::Borrowed("sim"),
792 Softfloat => Cow::Borrowed("softfloat"),
793 Spe => Cow::Borrowed("spe"),
794 Threads => Cow::Borrowed("threads"),
795 }
796 }
797}
798
799/// The "binary format" field, which is usually omitted, and the binary format
800/// is implied by the other fields.
801#[cfg_attr(feature = "rust_1_40", non_exhaustive)]
802#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
803#[allow(missing_docs)]
804pub enum BinaryFormat {
805 Unknown,
806 Elf,
807 Coff,
808 Macho,
809 Wasm,
810 Xcoff,
811}
812
813impl BinaryFormat {
814 /// Convert into a string
815 pub fn into_str(self) -> Cow<'static, str> {
816 use BinaryFormat::*;
817
818 match self {
819 Unknown => Cow::Borrowed("unknown"),
820 Elf => Cow::Borrowed("elf"),
821 Coff => Cow::Borrowed("coff"),
822 Macho => Cow::Borrowed("macho"),
823 Wasm => Cow::Borrowed("wasm"),
824 Xcoff => Cow::Borrowed("xcoff"),
825 }
826 }
827}
828
829impl Architecture {
830 /// Return the endianness of this architecture.
831 #[rustfmt::skip]
832 pub fn endianness(self) -> Result<Endianness, ()> {
833 use Architecture::*;
834
835 match self {
836 Unknown => Err(()),
837 Arm(arm) => Ok(arm.endianness()),
838 Aarch64(aarch) => Ok(aarch.endianness()),
839 AmdGcn
840 | Asmjs
841 | Avr
842 | Bpfel
843 | Hexagon
844 | X86_32(_)
845 | LoongArch64
846 | Mips64(Mips64Architecture::Mips64el)
847 | Mips32(Mips32Architecture::Mipsel)
848 | Mips32(Mips32Architecture::Mipsisa32r6el)
849 | Mips64(Mips64Architecture::Mipsisa64r6el)
850 | Msp430
851 | Nvptx64
852 | Powerpc64le
853 | Riscv32(_)
854 | Riscv64(_)
855 | Wasm32
856 | Wasm64
857 | X86_64
858 | X86_64h
859 | XTensa
860 | Clever(_) => Ok(Endianness::Little),
861 Bpfeb
862 | M68k
863 | Mips32(Mips32Architecture::Mips)
864 | Mips64(Mips64Architecture::Mips64)
865 | Mips32(Mips32Architecture::Mipsisa32r6)
866 | Mips64(Mips64Architecture::Mipsisa64r6)
867 | Powerpc
868 | Powerpc64
869 | S390x
870 | Sparc
871 | Sparc64
872 | Sparcv9 => Ok(Endianness::Big),
873 #[cfg(feature="arch_zkasm")]
874 ZkAsm => Ok(Endianness::Big),
875 }
876
877 }
878
879 /// Return the pointer bit width of this target's architecture.
880 ///
881 /// This function is only aware of the CPU architecture so it is not aware
882 /// of ilp32 and x32 ABIs.
883 #[rustfmt::skip]
884 pub fn pointer_width(self) -> Result<PointerWidth, ()> {
885 use Architecture::*;
886
887 match self {
888 Unknown => Err(()),
889 Avr | Msp430 => Ok(PointerWidth::U16),
890 Arm(arm) => Ok(arm.pointer_width()),
891 Aarch64(aarch) => Ok(aarch.pointer_width()),
892 Asmjs
893 | Hexagon
894 | X86_32(_)
895 | Riscv32(_)
896 | Sparc
897 | Wasm32
898 | M68k
899 | Mips32(_)
900 | Powerpc
901 | XTensa => Ok(PointerWidth::U32),
902 AmdGcn
903 | Bpfeb
904 | Bpfel
905 | Powerpc64le
906 | Riscv64(_)
907 | X86_64
908 | X86_64h
909 | Mips64(_)
910 | Nvptx64
911 | Powerpc64
912 | S390x
913 | Sparc64
914 | Sparcv9
915 | LoongArch64
916 | Wasm64
917 | Clever(_) => Ok(PointerWidth::U64),
918 #[cfg(feature="arch_zkasm")]
919 ZkAsm => Ok(PointerWidth::U64),
920 }
921 }
922
923 /// Checks if this Architecture is some variant of Clever-ISA
924 pub fn is_clever(&self) -> bool {
925 match self {
926 Architecture::Clever(_) => true,
927 _ => false,
928 }
929 }
930
931 /// Convert into a string
932 pub fn into_str(self) -> Cow<'static, str> {
933 use Architecture::*;
934
935 match self {
936 Arm(arm) => arm.into_str(),
937 Aarch64(aarch) => aarch.into_str(),
938 Unknown => Cow::Borrowed("unknown"),
939 AmdGcn => Cow::Borrowed("amdgcn"),
940 Asmjs => Cow::Borrowed("asmjs"),
941 Avr => Cow::Borrowed("avr"),
942 Bpfeb => Cow::Borrowed("bpfeb"),
943 Bpfel => Cow::Borrowed("bpfel"),
944 Hexagon => Cow::Borrowed("hexagon"),
945 X86_32(x86_32) => x86_32.into_str(),
946 LoongArch64 => Cow::Borrowed("loongarch64"),
947 M68k => Cow::Borrowed("m68k"),
948 Mips32(mips32) => mips32.into_str(),
949 Mips64(mips64) => mips64.into_str(),
950 Msp430 => Cow::Borrowed("msp430"),
951 Nvptx64 => Cow::Borrowed("nvptx64"),
952 Powerpc => Cow::Borrowed("powerpc"),
953 Powerpc64 => Cow::Borrowed("powerpc64"),
954 Powerpc64le => Cow::Borrowed("powerpc64le"),
955 Riscv32(riscv32) => riscv32.into_str(),
956 Riscv64(riscv64) => riscv64.into_str(),
957 S390x => Cow::Borrowed("s390x"),
958 Sparc => Cow::Borrowed("sparc"),
959 Sparc64 => Cow::Borrowed("sparc64"),
960 Sparcv9 => Cow::Borrowed("sparcv9"),
961 Wasm32 => Cow::Borrowed("wasm32"),
962 Wasm64 => Cow::Borrowed("wasm64"),
963 X86_64 => Cow::Borrowed("x86_64"),
964 X86_64h => Cow::Borrowed("x86_64h"),
965 XTensa => Cow::Borrowed("xtensa"),
966 Clever(ver) => ver.into_str(),
967 #[cfg(feature = "arch_zkasm")]
968 ZkAsm => Cow::Borrowed("zkasm"),
969 }
970 }
971}
972
973/// Return the binary format implied by this target triple, ignoring its
974/// `binary_format` field.
975pub(crate) fn default_binary_format(triple: &Triple) -> BinaryFormat {
976 match triple.operating_system {
977 OperatingSystem::None_ => match triple.environment {
978 Environment::Eabi | Environment::Eabihf => BinaryFormat::Elf,
979 _ => BinaryFormat::Unknown,
980 },
981 OperatingSystem::Aix => BinaryFormat::Xcoff,
982 OperatingSystem::Darwin
983 | OperatingSystem::Ios
984 | OperatingSystem::MacOSX { .. }
985 | OperatingSystem::Watchos
986 | OperatingSystem::Tvos => BinaryFormat::Macho,
987 OperatingSystem::Windows => BinaryFormat::Coff,
988 OperatingSystem::Nebulet
989 | OperatingSystem::Emscripten
990 | OperatingSystem::VxWorks
991 | OperatingSystem::Wasi
992 | OperatingSystem::Unknown => match triple.architecture {
993 Architecture::Wasm32 | Architecture::Wasm64 => BinaryFormat::Wasm,
994 _ => BinaryFormat::Unknown,
995 },
996 _ => BinaryFormat::Elf,
997 }
998}
999
1000impl fmt::Display for ArmArchitecture {
1001 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1002 f.write_str(&self.into_str())
1003 }
1004}
1005
1006impl fmt::Display for Aarch64Architecture {
1007 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1008 f.write_str(&self.into_str())
1009 }
1010}
1011
1012impl fmt::Display for CleverArchitecture {
1013 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1014 f.write_str(&self.into_str())
1015 }
1016}
1017
1018impl fmt::Display for Riscv32Architecture {
1019 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1020 f.write_str(&self.into_str())
1021 }
1022}
1023
1024impl fmt::Display for Riscv64Architecture {
1025 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1026 f.write_str(&self.into_str())
1027 }
1028}
1029
1030impl fmt::Display for X86_32Architecture {
1031 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1032 f.write_str(&self.into_str())
1033 }
1034}
1035
1036impl fmt::Display for Mips32Architecture {
1037 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1038 f.write_str(&self.into_str())
1039 }
1040}
1041
1042impl fmt::Display for Mips64Architecture {
1043 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1044 f.write_str(&self.into_str())
1045 }
1046}
1047
1048impl fmt::Display for Architecture {
1049 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1050 f.write_str(&self.into_str())
1051 }
1052}
1053
1054impl FromStr for ArmArchitecture {
1055 type Err = ();
1056
1057 fn from_str(s: &str) -> Result<Self, ()> {
1058 use ArmArchitecture::*;
1059
1060 Ok(match s {
1061 "arm" => Arm,
1062 "armeb" => Armeb,
1063 "armv4" => Armv4,
1064 "armv4t" => Armv4t,
1065 "armv5t" => Armv5t,
1066 "armv5te" => Armv5te,
1067 "armv5tej" => Armv5tej,
1068 "armv6" => Armv6,
1069 "armv6j" => Armv6j,
1070 "armv6k" => Armv6k,
1071 "armv6z" => Armv6z,
1072 "armv6kz" => Armv6kz,
1073 "armv6t2" => Armv6t2,
1074 "armv6m" => Armv6m,
1075 "armv7" => Armv7,
1076 "armv7a" => Armv7a,
1077 "armv7k" => Armv7k,
1078 "armv7ve" => Armv7ve,
1079 "armv7m" => Armv7m,
1080 "armv7r" => Armv7r,
1081 "armv7s" => Armv7s,
1082 "armv8" => Armv8,
1083 "armv8a" => Armv8a,
1084 "armv8.1a" => Armv8_1a,
1085 "armv8.2a" => Armv8_2a,
1086 "armv8.3a" => Armv8_3a,
1087 "armv8.4a" => Armv8_4a,
1088 "armv8.5a" => Armv8_5a,
1089 "armv8m.base" => Armv8mBase,
1090 "armv8m.main" => Armv8mMain,
1091 "armv8r" => Armv8r,
1092 "thumbeb" => Thumbeb,
1093 "thumbv4t" => Thumbv4t,
1094 "thumbv5te" => Thumbv5te,
1095 "thumbv6m" => Thumbv6m,
1096 "thumbv7a" => Thumbv7a,
1097 "thumbv7em" => Thumbv7em,
1098 "thumbv7m" => Thumbv7m,
1099 "thumbv7neon" => Thumbv7neon,
1100 "thumbv8m.base" => Thumbv8mBase,
1101 "thumbv8m.main" => Thumbv8mMain,
1102 "armebv7r" => Armebv7r,
1103 _ => return Err(()),
1104 })
1105 }
1106}
1107
1108impl FromStr for Aarch64Architecture {
1109 type Err = ();
1110
1111 fn from_str(s: &str) -> Result<Self, ()> {
1112 use Aarch64Architecture::*;
1113
1114 Ok(match s {
1115 "aarch64" => Aarch64,
1116 "arm64" => Aarch64,
1117 "aarch64_be" => Aarch64be,
1118 _ => return Err(()),
1119 })
1120 }
1121}
1122
1123impl FromStr for CleverArchitecture {
1124 type Err = ();
1125 fn from_str(s: &str) -> Result<Self, ()> {
1126 match s {
1127 "clever" => Ok(CleverArchitecture::Clever),
1128 "clever1.0" => Ok(CleverArchitecture::Clever1_0),
1129 _ => Err(()),
1130 }
1131 }
1132}
1133
1134impl FromStr for Riscv32Architecture {
1135 type Err = ();
1136
1137 fn from_str(s: &str) -> Result<Self, ()> {
1138 use Riscv32Architecture::*;
1139
1140 Ok(match s {
1141 "riscv32" => Riscv32,
1142 "riscv32gc" => Riscv32gc,
1143 "riscv32i" => Riscv32i,
1144 "riscv32im" => Riscv32im,
1145 "riscv32imac" => Riscv32imac,
1146 "riscv32imc" => Riscv32imc,
1147 _ => return Err(()),
1148 })
1149 }
1150}
1151
1152impl FromStr for Riscv64Architecture {
1153 type Err = ();
1154
1155 fn from_str(s: &str) -> Result<Self, ()> {
1156 use Riscv64Architecture::*;
1157
1158 Ok(match s {
1159 "riscv64" => Riscv64,
1160 "riscv64gc" => Riscv64gc,
1161 "riscv64imac" => Riscv64imac,
1162 _ => return Err(()),
1163 })
1164 }
1165}
1166
1167impl FromStr for X86_32Architecture {
1168 type Err = ();
1169
1170 fn from_str(s: &str) -> Result<Self, ()> {
1171 use X86_32Architecture::*;
1172
1173 Ok(match s {
1174 "i386" => I386,
1175 "i586" => I586,
1176 "i686" => I686,
1177 _ => return Err(()),
1178 })
1179 }
1180}
1181
1182impl FromStr for Mips32Architecture {
1183 type Err = ();
1184
1185 fn from_str(s: &str) -> Result<Self, ()> {
1186 use Mips32Architecture::*;
1187
1188 Ok(match s {
1189 "mips" => Mips,
1190 "mipsel" => Mipsel,
1191 "mipsisa32r6" => Mipsisa32r6,
1192 "mipsisa32r6el" => Mipsisa32r6el,
1193 _ => return Err(()),
1194 })
1195 }
1196}
1197
1198impl FromStr for Mips64Architecture {
1199 type Err = ();
1200
1201 fn from_str(s: &str) -> Result<Self, ()> {
1202 use Mips64Architecture::*;
1203
1204 Ok(match s {
1205 "mips64" => Mips64,
1206 "mips64el" => Mips64el,
1207 "mipsisa64r6" => Mipsisa64r6,
1208 "mipsisa64r6el" => Mipsisa64r6el,
1209 _ => return Err(()),
1210 })
1211 }
1212}
1213
1214impl FromStr for Architecture {
1215 type Err = ();
1216
1217 fn from_str(s: &str) -> Result<Self, ()> {
1218 use Architecture::*;
1219
1220 Ok(match s {
1221 "unknown" => Unknown,
1222 "amdgcn" => AmdGcn,
1223 "asmjs" => Asmjs,
1224 "avr" => Avr,
1225 "bpfeb" => Bpfeb,
1226 "bpfel" => Bpfel,
1227 "hexagon" => Hexagon,
1228 "loongarch64" => LoongArch64,
1229 "m68k" => M68k,
1230 "msp430" => Msp430,
1231 "nvptx64" => Nvptx64,
1232 "powerpc" => Powerpc,
1233 "powerpc64" => Powerpc64,
1234 "powerpc64le" => Powerpc64le,
1235 "s390x" => S390x,
1236 "sparc" => Sparc,
1237 "sparc64" => Sparc64,
1238 "sparcv9" => Sparcv9,
1239 "wasm32" => Wasm32,
1240 "wasm64" => Wasm64,
1241 "x86_64" => X86_64,
1242 "x86_64h" => X86_64h,
1243 "xtensa" => XTensa,
1244 #[cfg(feature = "arch_zkasm")]
1245 "zkasm" => ZkAsm,
1246 _ => {
1247 if let Ok(arm) = ArmArchitecture::from_str(s) {
1248 Arm(arm)
1249 } else if let Ok(aarch64) = Aarch64Architecture::from_str(s) {
1250 Aarch64(aarch64)
1251 } else if let Ok(riscv32) = Riscv32Architecture::from_str(s) {
1252 Riscv32(riscv32)
1253 } else if let Ok(riscv64) = Riscv64Architecture::from_str(s) {
1254 Riscv64(riscv64)
1255 } else if let Ok(x86_32) = X86_32Architecture::from_str(s) {
1256 X86_32(x86_32)
1257 } else if let Ok(mips32) = Mips32Architecture::from_str(s) {
1258 Mips32(mips32)
1259 } else if let Ok(mips64) = Mips64Architecture::from_str(s) {
1260 Mips64(mips64)
1261 } else if let Ok(clever) = CleverArchitecture::from_str(s) {
1262 Clever(clever)
1263 } else {
1264 return Err(());
1265 }
1266 }
1267 })
1268 }
1269}
1270
1271impl fmt::Display for Vendor {
1272 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1273 f.write_str(self.as_str())
1274 }
1275}
1276
1277impl FromStr for Vendor {
1278 type Err = ();
1279
1280 fn from_str(s: &str) -> Result<Self, ()> {
1281 use Vendor::*;
1282
1283 Ok(match s {
1284 "unknown" => Unknown,
1285 "amd" => Amd,
1286 "apple" => Apple,
1287 "espressif" => Espressif,
1288 "experimental" => Experimental,
1289 "fortanix" => Fortanix,
1290 "ibm" => Ibm,
1291 "kmc" => Kmc,
1292 "nintendo" => Nintendo,
1293 "nvidia" => Nvidia,
1294 "pc" => Pc,
1295 "rumprun" => Rumprun,
1296 "sun" => Sun,
1297 "uwp" => Uwp,
1298 "wrs" => Wrs,
1299 custom => {
1300 #[cfg(not(feature = "std"))]
1301 use alloc::borrow::ToOwned;
1302
1303 // A custom vendor. Since triple syntax is so loosely defined,
1304 // be as conservative as we can to avoid potential ambiguities.
1305 // We err on the side of being too strict here, as we can
1306 // always relax it if needed.
1307
1308 // Don't allow empty string names.
1309 if custom.is_empty() {
1310 return Err(());
1311 }
1312
1313 // Don't allow any other recognized name as a custom vendor,
1314 // since vendors can be omitted in some contexts.
1315 if Architecture::from_str(custom).is_ok()
1316 || OperatingSystem::from_str(custom).is_ok()
1317 || Environment::from_str(custom).is_ok()
1318 || BinaryFormat::from_str(custom).is_ok()
1319 {
1320 return Err(());
1321 }
1322
1323 // Require the first character to be an ascii lowercase.
1324 if !custom.chars().next().unwrap().is_ascii_lowercase() {
1325 return Err(());
1326 }
1327
1328 // Restrict the set of characters permitted in a custom vendor.
1329 let has_restricted = custom.chars().any(|c: char| {
1330 !(c.is_ascii_lowercase() || c.is_ascii_digit() || c == '_' || c == '.')
1331 });
1332
1333 if has_restricted {
1334 return Err(());
1335 }
1336
1337 Custom(CustomVendor::Owned(Box::new(custom.to_owned())))
1338 }
1339 })
1340 }
1341}
1342
1343impl fmt::Display for OperatingSystem {
1344 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1345 use OperatingSystem::*;
1346
1347 match *self {
1348 MacOSX {
1349 major: u16,
1350 minor: u16,
1351 patch: u16,
1352 } => write!(f, "macosx{}.{}.{}", major, minor, patch),
1353 os: OperatingSystem => f.write_str(&os.into_str()),
1354 }
1355 }
1356}
1357
1358impl FromStr for OperatingSystem {
1359 type Err = ();
1360
1361 fn from_str(s: &str) -> Result<Self, ()> {
1362 use OperatingSystem::*;
1363
1364 // TODO also parse version number for darwin and ios OSes
1365 if s.starts_with("macosx") {
1366 // Parse operating system names like `macosx10.7.0`.
1367 let s = &s["macosx".len()..];
1368 let mut parts = s.split('.').map(|num| num.parse::<u16>());
1369
1370 macro_rules! get_part {
1371 () => {
1372 if let Some(Ok(part)) = parts.next() {
1373 part
1374 } else {
1375 return Err(());
1376 }
1377 };
1378 }
1379
1380 let major = get_part!();
1381 let minor = get_part!();
1382 let patch = get_part!();
1383
1384 if parts.next().is_some() {
1385 return Err(());
1386 }
1387
1388 return Ok(MacOSX {
1389 major,
1390 minor,
1391 patch,
1392 });
1393 }
1394
1395 Ok(match s {
1396 "unknown" => Unknown,
1397 "aix" => Aix,
1398 "amdhsa" => AmdHsa,
1399 "bitrig" => Bitrig,
1400 "cloudabi" => Cloudabi,
1401 "cuda" => Cuda,
1402 "darwin" => Darwin,
1403 "dragonfly" => Dragonfly,
1404 "emscripten" => Emscripten,
1405 "freebsd" => Freebsd,
1406 "fuchsia" => Fuchsia,
1407 "haiku" => Haiku,
1408 "hermit" => Hermit,
1409 "horizon" => Horizon,
1410 "illumos" => Illumos,
1411 "ios" => Ios,
1412 "l4re" => L4re,
1413 "linux" => Linux,
1414 "nebulet" => Nebulet,
1415 "netbsd" => Netbsd,
1416 "none" => None_,
1417 "openbsd" => Openbsd,
1418 "psp" => Psp,
1419 "redox" => Redox,
1420 "solaris" => Solaris,
1421 "solid_asp3" => SolidAsp3,
1422 "tvos" => Tvos,
1423 "uefi" => Uefi,
1424 "vxworks" => VxWorks,
1425 "wasi" => Wasi,
1426 "wasip1" => WasiP1,
1427 "wasip2" => WasiP2,
1428 "watchos" => Watchos,
1429 "windows" => Windows,
1430 "espidf" => Espidf,
1431 _ => return Err(()),
1432 })
1433 }
1434}
1435
1436impl fmt::Display for Environment {
1437 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1438 f.write_str(&self.into_str())
1439 }
1440}
1441
1442impl FromStr for Environment {
1443 type Err = ();
1444
1445 fn from_str(s: &str) -> Result<Self, ()> {
1446 use Environment::*;
1447
1448 Ok(match s {
1449 "unknown" => Unknown,
1450 "amdgiz" => AmdGiz,
1451 "android" => Android,
1452 "androideabi" => Androideabi,
1453 "eabi" => Eabi,
1454 "eabihf" => Eabihf,
1455 "gnu" => Gnu,
1456 "gnuabi64" => Gnuabi64,
1457 "gnueabi" => Gnueabi,
1458 "gnueabihf" => Gnueabihf,
1459 "gnuspe" => Gnuspe,
1460 "gnux32" => Gnux32,
1461 "gnu_ilp32" => GnuIlp32,
1462 "gnullvm" => GnuLlvm,
1463 "hermitkernel" => HermitKernel,
1464 "linuxkernel" => LinuxKernel,
1465 "macabi" => Macabi,
1466 "musl" => Musl,
1467 "musleabi" => Musleabi,
1468 "musleabihf" => Musleabihf,
1469 "muslabi64" => Muslabi64,
1470 "msvc" => Msvc,
1471 "newlib" => Newlib,
1472 "kernel" => Kernel,
1473 "uclibc" => Uclibc,
1474 "uclibceabi" => Uclibceabi,
1475 "uclibceabihf" => Uclibceabihf,
1476 "sgx" => Sgx,
1477 "sim" => Sim,
1478 "softfloat" => Softfloat,
1479 "spe" => Spe,
1480 "threads" => Threads,
1481 _ => return Err(()),
1482 })
1483 }
1484}
1485
1486impl fmt::Display for BinaryFormat {
1487 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1488 f.write_str(&self.into_str())
1489 }
1490}
1491
1492impl FromStr for BinaryFormat {
1493 type Err = ();
1494
1495 fn from_str(s: &str) -> Result<Self, ()> {
1496 use BinaryFormat::*;
1497
1498 Ok(match s {
1499 "unknown" => Unknown,
1500 "elf" => Elf,
1501 "coff" => Coff,
1502 "macho" => Macho,
1503 "wasm" => Wasm,
1504 "xcoff" => Xcoff,
1505 _ => return Err(()),
1506 })
1507 }
1508}
1509
1510#[cfg(test)]
1511mod tests {
1512 use super::*;
1513 use alloc::string::ToString;
1514
1515 #[test]
1516 fn roundtrip_known_triples() {
1517 // This list is constructed from:
1518 // - targets emitted by "rustup target list"
1519 // - targets emitted by "rustc +nightly --print target-list"
1520 // - targets contributors have added
1521 let targets = [
1522 "aarch64-apple-darwin",
1523 "aarch64-apple-ios",
1524 "aarch64-apple-ios-macabi",
1525 "aarch64-apple-ios-sim",
1526 "aarch64-apple-tvos",
1527 "aarch64-apple-watchos-sim",
1528 "aarch64_be-unknown-linux-gnu",
1529 "aarch64_be-unknown-linux-gnu_ilp32",
1530 "aarch64_be-unknown-netbsd",
1531 "aarch64-fuchsia",
1532 "aarch64-kmc-solid_asp3",
1533 "aarch64-linux-android",
1534 //"aarch64-nintendo-switch-freestanding", // TODO
1535 "aarch64-pc-windows-gnullvm",
1536 "aarch64-pc-windows-msvc",
1537 "aarch64-unknown-cloudabi",
1538 "aarch64-unknown-freebsd",
1539 "aarch64-unknown-hermit",
1540 "aarch64-unknown-linux-gnu",
1541 "aarch64-unknown-linux-gnu_ilp32",
1542 "aarch64-unknown-linux-musl",
1543 "aarch64-unknown-netbsd",
1544 "aarch64-unknown-none",
1545 "aarch64-unknown-none-softfloat",
1546 "aarch64-unknown-openbsd",
1547 "aarch64-unknown-redox",
1548 "aarch64-unknown-uefi",
1549 "aarch64-uwp-windows-msvc",
1550 "aarch64-wrs-vxworks",
1551 //"arm64_32-apple-watchos", // TODO
1552 "armeb-unknown-linux-gnueabi",
1553 "amdgcn-amd-amdhsa",
1554 "amdgcn-amd-amdhsa-amdgiz",
1555 "armebv7r-none-eabi",
1556 "armebv7r-none-eabihf",
1557 "arm-linux-androideabi",
1558 "arm-unknown-linux-gnueabi",
1559 "arm-unknown-linux-gnueabihf",
1560 "arm-unknown-linux-musleabi",
1561 "arm-unknown-linux-musleabihf",
1562 "armv4t-none-eabi",
1563 "armv4t-unknown-linux-gnueabi",
1564 "armv5te-none-eabi",
1565 "armv5te-unknown-linux-gnueabi",
1566 "armv5te-unknown-linux-musleabi",
1567 "armv5te-unknown-linux-uclibceabi",
1568 "armv6k-nintendo-3ds",
1569 "armv6-unknown-freebsd",
1570 "armv6-unknown-netbsd-eabihf",
1571 "armv7a-kmc-solid_asp3-eabi",
1572 "armv7a-kmc-solid_asp3-eabihf",
1573 "armv7a-none-eabi",
1574 "armv7a-none-eabihf",
1575 "armv7-apple-ios",
1576 "armv7k-apple-watchos",
1577 "armv7-linux-androideabi",
1578 "armv7r-none-eabi",
1579 "armv7r-none-eabihf",
1580 "armv7s-apple-ios",
1581 "armv7-unknown-cloudabi-eabihf",
1582 "armv7-unknown-freebsd",
1583 "armv7-unknown-linux-gnueabi",
1584 "armv7-unknown-linux-gnueabihf",
1585 "armv7-unknown-linux-musleabi",
1586 "armv7-unknown-linux-musleabihf",
1587 "armv7-unknown-linux-uclibceabi",
1588 "armv7-unknown-linux-uclibceabihf",
1589 "armv7-unknown-netbsd-eabihf",
1590 "armv7-wrs-vxworks-eabihf",
1591 "asmjs-unknown-emscripten",
1592 //"avr-unknown-gnu-atmega328", // TODO
1593 "avr-unknown-unknown",
1594 "bpfeb-unknown-none",
1595 "bpfel-unknown-none",
1596 "hexagon-unknown-linux-musl",
1597 "i386-apple-ios",
1598 "i586-pc-windows-msvc",
1599 "i586-unknown-linux-gnu",
1600 "i586-unknown-linux-musl",
1601 "i686-apple-darwin",
1602 "i686-linux-android",
1603 "i686-apple-macosx10.7.0",
1604 "i686-pc-windows-gnu",
1605 "i686-pc-windows-msvc",
1606 "i686-unknown-cloudabi",
1607 "i686-unknown-dragonfly",
1608 "i686-unknown-freebsd",
1609 "i686-unknown-haiku",
1610 "i686-unknown-linux-gnu",
1611 "i686-unknown-linux-musl",
1612 "i686-unknown-netbsd",
1613 "i686-unknown-openbsd",
1614 "i686-unknown-uefi",
1615 "i686-uwp-windows-gnu",
1616 "i686-uwp-windows-msvc",
1617 "i686-wrs-vxworks",
1618 "loongarch64-unknown-linux-gnu",
1619 "m68k-unknown-linux-gnu",
1620 "mips64el-unknown-linux-gnuabi64",
1621 "mips64el-unknown-linux-muslabi64",
1622 "mips64-openwrt-linux-musl",
1623 "mips64-unknown-linux-gnuabi64",
1624 "mips64-unknown-linux-muslabi64",
1625 "mipsel-sony-psp",
1626 "mipsel-unknown-linux-gnu",
1627 "mipsel-unknown-linux-musl",
1628 "mipsel-unknown-linux-uclibc",
1629 "mipsel-unknown-none",
1630 "mipsisa32r6el-unknown-linux-gnu",
1631 "mipsisa32r6-unknown-linux-gnu",
1632 "mipsisa64r6el-unknown-linux-gnuabi64",
1633 "mipsisa64r6-unknown-linux-gnuabi64",
1634 "mips-unknown-linux-gnu",
1635 "mips-unknown-linux-musl",
1636 "mips-unknown-linux-uclibc",
1637 "msp430-none-elf",
1638 "nvptx64-nvidia-cuda",
1639 "powerpc64le-unknown-freebsd",
1640 "powerpc64le-unknown-linux-gnu",
1641 "powerpc64le-unknown-linux-musl",
1642 "powerpc64-ibm-aix",
1643 "powerpc64-unknown-freebsd",
1644 "powerpc64-unknown-linux-gnu",
1645 "powerpc64-unknown-linux-musl",
1646 "powerpc64-unknown-openbsd",
1647 "powerpc64-wrs-vxworks",
1648 "powerpc-ibm-aix",
1649 "powerpc-unknown-freebsd",
1650 "powerpc-unknown-linux-gnu",
1651 "powerpc-unknown-linux-gnuspe",
1652 "powerpc-unknown-linux-musl",
1653 "powerpc-unknown-netbsd",
1654 "powerpc-unknown-openbsd",
1655 "powerpc-wrs-vxworks",
1656 "powerpc-wrs-vxworks-spe",
1657 "riscv32gc-unknown-linux-gnu",
1658 "riscv32gc-unknown-linux-musl",
1659 "riscv32imac-unknown-none-elf",
1660 //"riscv32imac-unknown-xous-elf", // TODO
1661 "riscv32imc-esp-espidf",
1662 "riscv32imc-unknown-none-elf",
1663 "riscv32im-unknown-none-elf",
1664 "riscv32i-unknown-none-elf",
1665 "riscv64gc-unknown-freebsd",
1666 "riscv64gc-unknown-linux-gnu",
1667 "riscv64gc-unknown-linux-musl",
1668 "riscv64gc-unknown-netbsd",
1669 "riscv64gc-unknown-none-elf",
1670 "riscv64gc-unknown-openbsd",
1671 "riscv64imac-unknown-none-elf",
1672 "s390x-unknown-linux-gnu",
1673 "s390x-unknown-linux-musl",
1674 "sparc64-unknown-linux-gnu",
1675 "sparc64-unknown-netbsd",
1676 "sparc64-unknown-openbsd",
1677 "sparc-unknown-linux-gnu",
1678 "sparcv9-sun-solaris",
1679 "thumbv4t-none-eabi",
1680 "thumbv5te-none-eabi",
1681 "thumbv6m-none-eabi",
1682 "thumbv7a-pc-windows-msvc",
1683 "thumbv7a-uwp-windows-msvc",
1684 "thumbv7em-none-eabi",
1685 "thumbv7em-none-eabihf",
1686 "thumbv7m-none-eabi",
1687 "thumbv7neon-linux-androideabi",
1688 "thumbv7neon-unknown-linux-gnueabihf",
1689 "thumbv7neon-unknown-linux-musleabihf",
1690 "thumbv8m.base-none-eabi",
1691 "thumbv8m.main-none-eabi",
1692 "thumbv8m.main-none-eabihf",
1693 "wasm32-experimental-emscripten",
1694 "wasm32-unknown-emscripten",
1695 "wasm32-unknown-unknown",
1696 "wasm32-wasi",
1697 "wasm32-wasip1-threads",
1698 "wasm32-wasip1",
1699 "wasm32-wasip2",
1700 "wasm64-unknown-unknown",
1701 "wasm64-wasi",
1702 "x86_64-apple-darwin",
1703 "x86_64h-apple-darwin",
1704 "x86_64-apple-ios",
1705 "x86_64-apple-ios-macabi",
1706 "x86_64-apple-tvos",
1707 "x86_64-apple-watchos-sim",
1708 "x86_64-fortanix-unknown-sgx",
1709 "x86_64-fuchsia",
1710 "x86_64-linux-android",
1711 "x86_64-linux-kernel", // Changed to x86_64-unknown-none-linuxkernel in 1.53.0
1712 "x86_64-apple-macosx10.7.0",
1713 "x86_64-pc-solaris",
1714 "x86_64-pc-windows-gnu",
1715 "x86_64-pc-windows-gnullvm",
1716 "x86_64-pc-windows-msvc",
1717 "x86_64-rumprun-netbsd", // Removed in 1.53.0
1718 "x86_64-sun-solaris",
1719 "x86_64-unknown-bitrig",
1720 "x86_64-unknown-cloudabi",
1721 "x86_64-unknown-dragonfly",
1722 "x86_64-unknown-freebsd",
1723 "x86_64-unknown-haiku",
1724 "x86_64-unknown-hermit",
1725 "x86_64-unknown-hermit-kernel", // Changed to x86_64-unknown-none-hermitkernel in 1.53.0
1726 "x86_64-unknown-illumos",
1727 "x86_64-unknown-l4re-uclibc",
1728 "x86_64-unknown-linux-gnu",
1729 "x86_64-unknown-linux-gnux32",
1730 "x86_64-unknown-linux-musl",
1731 "x86_64-unknown-netbsd",
1732 "x86_64-unknown-none",
1733 "x86_64-unknown-none-hermitkernel",
1734 "x86_64-unknown-none-linuxkernel",
1735 "x86_64-unknown-openbsd",
1736 "x86_64-unknown-redox",
1737 "x86_64-unknown-uefi",
1738 "x86_64-uwp-windows-gnu",
1739 "x86_64-uwp-windows-msvc",
1740 "x86_64-wrs-vxworks",
1741 "xtensa-esp32-espidf",
1742 "clever-unknown-elf",
1743 #[cfg(feature = "arch_zkasm")]
1744 "zkasm-unknown-unknown",
1745 ];
1746
1747 for target in targets.iter() {
1748 let t = Triple::from_str(target).expect("can't parse target");
1749 assert_ne!(t.architecture, Architecture::Unknown);
1750 assert_eq!(t.to_string(), *target, "{:#?}", t);
1751 }
1752 }
1753
1754 #[test]
1755 fn thumbv7em_none_eabihf() {
1756 let t = Triple::from_str("thumbv7em-none-eabihf").expect("can't parse target");
1757 assert_eq!(
1758 t.architecture,
1759 Architecture::Arm(ArmArchitecture::Thumbv7em)
1760 );
1761 assert_eq!(t.vendor, Vendor::Unknown);
1762 assert_eq!(t.operating_system, OperatingSystem::None_);
1763 assert_eq!(t.environment, Environment::Eabihf);
1764 assert_eq!(t.binary_format, BinaryFormat::Elf);
1765 }
1766
1767 #[test]
1768 fn custom_vendors() {
1769 // Test various invalid cases.
1770 assert!(Triple::from_str("x86_64--linux").is_err());
1771 assert!(Triple::from_str("x86_64-42-linux").is_err());
1772 assert!(Triple::from_str("x86_64-__customvendor__-linux").is_err());
1773 assert!(Triple::from_str("x86_64-^-linux").is_err());
1774 assert!(Triple::from_str("x86_64- -linux").is_err());
1775 assert!(Triple::from_str("x86_64-CustomVendor-linux").is_err());
1776 assert!(Triple::from_str("x86_64-linux-linux").is_err());
1777 assert!(Triple::from_str("x86_64-x86_64-linux").is_err());
1778 assert!(Triple::from_str("x86_64-elf-linux").is_err());
1779 assert!(Triple::from_str("x86_64-gnu-linux").is_err());
1780 assert!(Triple::from_str("x86_64-linux-customvendor").is_err());
1781 assert!(Triple::from_str("customvendor").is_err());
1782 assert!(Triple::from_str("customvendor-x86_64").is_err());
1783 assert!(Triple::from_str("x86_64-").is_err());
1784 assert!(Triple::from_str("x86_64--").is_err());
1785
1786 // Test various Unicode things.
1787 assert!(
1788 Triple::from_str("x86_64-𝓬𝓾𝓼𝓽𝓸𝓶𝓿𝓮𝓷𝓭𝓸𝓻-linux").is_err(),
1789 "unicode font hazard"
1790 );
1791 assert!(
1792 Triple::from_str("x86_64-ćúśtőḿvéńdőŕ-linux").is_err(),
1793 "diacritical mark stripping hazard"
1794 );
1795 assert!(
1796 Triple::from_str("x86_64-customvendοr-linux").is_err(),
1797 "homoglyph hazard"
1798 );
1799 assert!(Triple::from_str("x86_64-customvendor-linux").is_ok());
1800 assert!(
1801 Triple::from_str("x86_64-ffi-linux").is_err(),
1802 "normalization hazard"
1803 );
1804 assert!(Triple::from_str("x86_64-ffi-linux").is_ok());
1805 assert!(
1806 Triple::from_str("x86_64-custom‍vendor-linux").is_err(),
1807 "zero-width character hazard"
1808 );
1809 assert!(
1810 Triple::from_str("x86_64-customvendor-linux").is_err(),
1811 "BOM hazard"
1812 );
1813
1814 // Test some valid cases.
1815 let t = Triple::from_str("x86_64-customvendor-linux")
1816 .expect("can't parse target with custom vendor");
1817 assert_eq!(t.architecture, Architecture::X86_64);
1818 assert_eq!(
1819 t.vendor,
1820 Vendor::Custom(CustomVendor::Static("customvendor"))
1821 );
1822 assert_eq!(t.operating_system, OperatingSystem::Linux);
1823 assert_eq!(t.environment, Environment::Unknown);
1824 assert_eq!(t.binary_format, BinaryFormat::Elf);
1825 assert_eq!(t.to_string(), "x86_64-customvendor-linux");
1826
1827 let t =
1828 Triple::from_str("x86_64-customvendor").expect("can't parse target with custom vendor");
1829 assert_eq!(t.architecture, Architecture::X86_64);
1830 assert_eq!(
1831 t.vendor,
1832 Vendor::Custom(CustomVendor::Static("customvendor"))
1833 );
1834 assert_eq!(t.operating_system, OperatingSystem::Unknown);
1835 assert_eq!(t.environment, Environment::Unknown);
1836 assert_eq!(t.binary_format, BinaryFormat::Unknown);
1837
1838 assert_eq!(
1839 Triple::from_str("unknown-foo"),
1840 Ok(Triple {
1841 architecture: Architecture::Unknown,
1842 vendor: Vendor::Custom(CustomVendor::Static("foo")),
1843 operating_system: OperatingSystem::Unknown,
1844 environment: Environment::Unknown,
1845 binary_format: BinaryFormat::Unknown,
1846 })
1847 );
1848 }
1849}
1850