1use std::borrow::Cow;
38use std::collections::BTreeMap;
39use std::hash::{Hash, Hasher};
40use std::ops::{Deref, DerefMut};
41use std::path::{Path, PathBuf};
42use std::str::FromStr;
43use std::{fmt, io};
44
45use rustc_abi::{
46 Align, CanonAbi, Endian, ExternAbi, Integer, Size, TargetDataLayout, TargetDataLayoutErrors,
47};
48use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
49use rustc_fs_util::try_canonicalize;
50use rustc_macros::{Decodable, Encodable, HashStable_Generic};
51use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
52use rustc_span::{Symbol, kw, sym};
53use serde_json::Value;
54use tracing::debug;
55
56use crate::json::{Json, ToJson};
57use crate::spec::crt_objects::CrtObjects;
58
59pub mod crt_objects;
60
61mod abi_map;
62mod base;
63mod json;
64
65pub use abi_map::AbiMap;
66pub use base::apple;
67pub use base::avr::ef_avr_arch;
68
69#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
71pub enum Cc {
72 Yes,
73 No,
74}
75
76#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
78pub enum Lld {
79 Yes,
80 No,
81}
82
83#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
104pub enum LinkerFlavor {
105 Gnu(Cc, Lld),
109 Darwin(Cc, Lld),
112 WasmLld(Cc),
116 Unix(Cc),
120 Msvc(Lld),
122 EmCc,
125 Bpf,
128 Ptx,
130 Llbc,
132}
133
134#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
139pub enum LinkerFlavorCli {
140 Gnu(Cc, Lld),
142 Darwin(Cc, Lld),
143 WasmLld(Cc),
144 Unix(Cc),
145 Msvc(Lld),
147 EmCc,
148 Bpf,
149 Ptx,
150 Llbc,
151
152 Gcc,
154 Ld,
155 Lld(LldFlavor),
156 Em,
157}
158
159impl LinkerFlavorCli {
160 pub fn is_unstable(&self) -> bool {
162 match self {
163 LinkerFlavorCli::Gnu(..)
164 | LinkerFlavorCli::Darwin(..)
165 | LinkerFlavorCli::WasmLld(..)
166 | LinkerFlavorCli::Unix(..)
167 | LinkerFlavorCli::Msvc(Lld::Yes)
168 | LinkerFlavorCli::EmCc
169 | LinkerFlavorCli::Bpf
170 | LinkerFlavorCli::Llbc
171 | LinkerFlavorCli::Ptx => true,
172 LinkerFlavorCli::Gcc
173 | LinkerFlavorCli::Ld
174 | LinkerFlavorCli::Lld(..)
175 | LinkerFlavorCli::Msvc(Lld::No)
176 | LinkerFlavorCli::Em => false,
177 }
178 }
179}
180
181#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
182pub enum LldFlavor {
183 Wasm,
184 Ld64,
185 Ld,
186 Link,
187}
188
189impl LldFlavor {
190 pub fn as_str(&self) -> &'static str {
191 match self {
192 LldFlavor::Wasm => "wasm",
193 LldFlavor::Ld64 => "darwin",
194 LldFlavor::Ld => "gnu",
195 LldFlavor::Link => "link",
196 }
197 }
198
199 fn from_str(s: &str) -> Option<Self> {
200 Some(match s {
201 "darwin" => LldFlavor::Ld64,
202 "gnu" => LldFlavor::Ld,
203 "link" => LldFlavor::Link,
204 "wasm" => LldFlavor::Wasm,
205 _ => return None,
206 })
207 }
208}
209
210impl ToJson for LldFlavor {
211 fn to_json(&self) -> Json {
212 self.as_str().to_json()
213 }
214}
215
216impl LinkerFlavor {
217 fn from_cli_json(cli: LinkerFlavorCli, lld_flavor: LldFlavor, is_gnu: bool) -> LinkerFlavor {
222 match cli {
223 LinkerFlavorCli::Gnu(cc, lld) => LinkerFlavor::Gnu(cc, lld),
224 LinkerFlavorCli::Darwin(cc, lld) => LinkerFlavor::Darwin(cc, lld),
225 LinkerFlavorCli::WasmLld(cc) => LinkerFlavor::WasmLld(cc),
226 LinkerFlavorCli::Unix(cc) => LinkerFlavor::Unix(cc),
227 LinkerFlavorCli::Msvc(lld) => LinkerFlavor::Msvc(lld),
228 LinkerFlavorCli::EmCc => LinkerFlavor::EmCc,
229 LinkerFlavorCli::Bpf => LinkerFlavor::Bpf,
230 LinkerFlavorCli::Llbc => LinkerFlavor::Llbc,
231 LinkerFlavorCli::Ptx => LinkerFlavor::Ptx,
232
233 LinkerFlavorCli::Gcc => match lld_flavor {
235 LldFlavor::Ld if is_gnu => LinkerFlavor::Gnu(Cc::Yes, Lld::No),
236 LldFlavor::Ld64 => LinkerFlavor::Darwin(Cc::Yes, Lld::No),
237 LldFlavor::Wasm => LinkerFlavor::WasmLld(Cc::Yes),
238 LldFlavor::Ld | LldFlavor::Link => LinkerFlavor::Unix(Cc::Yes),
239 },
240 LinkerFlavorCli::Ld => match lld_flavor {
241 LldFlavor::Ld if is_gnu => LinkerFlavor::Gnu(Cc::No, Lld::No),
242 LldFlavor::Ld64 => LinkerFlavor::Darwin(Cc::No, Lld::No),
243 LldFlavor::Ld | LldFlavor::Wasm | LldFlavor::Link => LinkerFlavor::Unix(Cc::No),
244 },
245 LinkerFlavorCli::Lld(LldFlavor::Ld) => LinkerFlavor::Gnu(Cc::No, Lld::Yes),
246 LinkerFlavorCli::Lld(LldFlavor::Ld64) => LinkerFlavor::Darwin(Cc::No, Lld::Yes),
247 LinkerFlavorCli::Lld(LldFlavor::Wasm) => LinkerFlavor::WasmLld(Cc::No),
248 LinkerFlavorCli::Lld(LldFlavor::Link) => LinkerFlavor::Msvc(Lld::Yes),
249 LinkerFlavorCli::Em => LinkerFlavor::EmCc,
250 }
251 }
252
253 fn to_cli(self) -> LinkerFlavorCli {
255 match self {
256 LinkerFlavor::Gnu(Cc::Yes, _)
257 | LinkerFlavor::Darwin(Cc::Yes, _)
258 | LinkerFlavor::WasmLld(Cc::Yes)
259 | LinkerFlavor::Unix(Cc::Yes) => LinkerFlavorCli::Gcc,
260 LinkerFlavor::Gnu(_, Lld::Yes) => LinkerFlavorCli::Lld(LldFlavor::Ld),
261 LinkerFlavor::Darwin(_, Lld::Yes) => LinkerFlavorCli::Lld(LldFlavor::Ld64),
262 LinkerFlavor::WasmLld(..) => LinkerFlavorCli::Lld(LldFlavor::Wasm),
263 LinkerFlavor::Gnu(..) | LinkerFlavor::Darwin(..) | LinkerFlavor::Unix(..) => {
264 LinkerFlavorCli::Ld
265 }
266 LinkerFlavor::Msvc(Lld::Yes) => LinkerFlavorCli::Lld(LldFlavor::Link),
267 LinkerFlavor::Msvc(..) => LinkerFlavorCli::Msvc(Lld::No),
268 LinkerFlavor::EmCc => LinkerFlavorCli::Em,
269 LinkerFlavor::Bpf => LinkerFlavorCli::Bpf,
270 LinkerFlavor::Llbc => LinkerFlavorCli::Llbc,
271 LinkerFlavor::Ptx => LinkerFlavorCli::Ptx,
272 }
273 }
274
275 fn to_cli_counterpart(self) -> LinkerFlavorCli {
277 match self {
278 LinkerFlavor::Gnu(cc, lld) => LinkerFlavorCli::Gnu(cc, lld),
279 LinkerFlavor::Darwin(cc, lld) => LinkerFlavorCli::Darwin(cc, lld),
280 LinkerFlavor::WasmLld(cc) => LinkerFlavorCli::WasmLld(cc),
281 LinkerFlavor::Unix(cc) => LinkerFlavorCli::Unix(cc),
282 LinkerFlavor::Msvc(lld) => LinkerFlavorCli::Msvc(lld),
283 LinkerFlavor::EmCc => LinkerFlavorCli::EmCc,
284 LinkerFlavor::Bpf => LinkerFlavorCli::Bpf,
285 LinkerFlavor::Llbc => LinkerFlavorCli::Llbc,
286 LinkerFlavor::Ptx => LinkerFlavorCli::Ptx,
287 }
288 }
289
290 fn infer_cli_hints(cli: LinkerFlavorCli) -> (Option<Cc>, Option<Lld>) {
291 match cli {
292 LinkerFlavorCli::Gnu(cc, lld) | LinkerFlavorCli::Darwin(cc, lld) => {
293 (Some(cc), Some(lld))
294 }
295 LinkerFlavorCli::WasmLld(cc) => (Some(cc), Some(Lld::Yes)),
296 LinkerFlavorCli::Unix(cc) => (Some(cc), None),
297 LinkerFlavorCli::Msvc(lld) => (Some(Cc::No), Some(lld)),
298 LinkerFlavorCli::EmCc => (Some(Cc::Yes), Some(Lld::Yes)),
299 LinkerFlavorCli::Bpf | LinkerFlavorCli::Ptx => (None, None),
300 LinkerFlavorCli::Llbc => (None, None),
301
302 LinkerFlavorCli::Gcc => (Some(Cc::Yes), None),
304 LinkerFlavorCli::Ld => (Some(Cc::No), Some(Lld::No)),
305 LinkerFlavorCli::Lld(_) => (Some(Cc::No), Some(Lld::Yes)),
306 LinkerFlavorCli::Em => (Some(Cc::Yes), Some(Lld::Yes)),
307 }
308 }
309
310 fn infer_linker_hints(linker_stem: &str) -> Result<Self, (Option<Cc>, Option<Lld>)> {
311 let stem = linker_stem
313 .rsplit_once('-')
314 .and_then(|(lhs, rhs)| rhs.chars().all(char::is_numeric).then_some(lhs))
315 .unwrap_or(linker_stem);
316
317 if stem == "llvm-bitcode-linker" {
318 Ok(Self::Llbc)
319 } else if stem == "emcc" || stem == "gcc"
321 || stem.ends_with("-gcc")
322 || stem == "g++"
323 || stem.ends_with("-g++")
324 || stem == "clang"
325 || stem.ends_with("-clang")
326 || stem == "clang++"
327 || stem.ends_with("-clang++")
328 {
329 Err((Some(Cc::Yes), Some(Lld::No)))
330 } else if stem == "wasm-ld"
331 || stem.ends_with("-wasm-ld")
332 || stem == "ld.lld"
333 || stem == "lld"
334 || stem == "rust-lld"
335 || stem == "lld-link"
336 {
337 Err((Some(Cc::No), Some(Lld::Yes)))
338 } else if stem == "ld" || stem.ends_with("-ld") || stem == "link" {
339 Err((Some(Cc::No), Some(Lld::No)))
340 } else {
341 Err((None, None))
342 }
343 }
344
345 fn with_hints(self, (cc_hint, lld_hint): (Option<Cc>, Option<Lld>)) -> LinkerFlavor {
346 match self {
347 LinkerFlavor::Gnu(cc, lld) => {
348 LinkerFlavor::Gnu(cc_hint.unwrap_or(cc), lld_hint.unwrap_or(lld))
349 }
350 LinkerFlavor::Darwin(cc, lld) => {
351 LinkerFlavor::Darwin(cc_hint.unwrap_or(cc), lld_hint.unwrap_or(lld))
352 }
353 LinkerFlavor::WasmLld(cc) => LinkerFlavor::WasmLld(cc_hint.unwrap_or(cc)),
354 LinkerFlavor::Unix(cc) => LinkerFlavor::Unix(cc_hint.unwrap_or(cc)),
355 LinkerFlavor::Msvc(lld) => LinkerFlavor::Msvc(lld_hint.unwrap_or(lld)),
356 LinkerFlavor::EmCc | LinkerFlavor::Bpf | LinkerFlavor::Llbc | LinkerFlavor::Ptx => self,
357 }
358 }
359
360 pub fn with_cli_hints(self, cli: LinkerFlavorCli) -> LinkerFlavor {
361 self.with_hints(LinkerFlavor::infer_cli_hints(cli))
362 }
363
364 pub fn with_linker_hints(self, linker_stem: &str) -> LinkerFlavor {
365 match LinkerFlavor::infer_linker_hints(linker_stem) {
366 Ok(linker_flavor) => linker_flavor,
367 Err(hints) => self.with_hints(hints),
368 }
369 }
370
371 pub fn check_compatibility(self, cli: LinkerFlavorCli) -> Option<String> {
372 let compatible = |cli| {
373 match (self, cli) {
375 (LinkerFlavor::Gnu(..), LinkerFlavorCli::Gnu(..))
377 | (LinkerFlavor::Darwin(..), LinkerFlavorCli::Darwin(..))
378 | (LinkerFlavor::WasmLld(..), LinkerFlavorCli::WasmLld(..))
379 | (LinkerFlavor::Unix(..), LinkerFlavorCli::Unix(..))
380 | (LinkerFlavor::Msvc(..), LinkerFlavorCli::Msvc(..))
381 | (LinkerFlavor::EmCc, LinkerFlavorCli::EmCc)
382 | (LinkerFlavor::Bpf, LinkerFlavorCli::Bpf)
383 | (LinkerFlavor::Llbc, LinkerFlavorCli::Llbc)
384 | (LinkerFlavor::Ptx, LinkerFlavorCli::Ptx) => return true,
385 (LinkerFlavor::Ptx, LinkerFlavorCli::Llbc) => return true,
387 _ => {}
388 }
389
390 cli == self.with_cli_hints(cli).to_cli()
392 };
393 (!compatible(cli)).then(|| {
394 LinkerFlavorCli::all()
395 .iter()
396 .filter(|cli| compatible(**cli))
397 .map(|cli| cli.desc())
398 .intersperse(", ")
399 .collect()
400 })
401 }
402
403 pub fn lld_flavor(self) -> LldFlavor {
404 match self {
405 LinkerFlavor::Gnu(..)
406 | LinkerFlavor::Unix(..)
407 | LinkerFlavor::EmCc
408 | LinkerFlavor::Bpf
409 | LinkerFlavor::Llbc
410 | LinkerFlavor::Ptx => LldFlavor::Ld,
411 LinkerFlavor::Darwin(..) => LldFlavor::Ld64,
412 LinkerFlavor::WasmLld(..) => LldFlavor::Wasm,
413 LinkerFlavor::Msvc(..) => LldFlavor::Link,
414 }
415 }
416
417 pub fn is_gnu(self) -> bool {
418 matches!(self, LinkerFlavor::Gnu(..))
419 }
420
421 pub fn uses_lld(self) -> bool {
423 match self {
425 LinkerFlavor::Gnu(_, Lld::Yes)
426 | LinkerFlavor::Darwin(_, Lld::Yes)
427 | LinkerFlavor::WasmLld(..)
428 | LinkerFlavor::EmCc
429 | LinkerFlavor::Msvc(Lld::Yes) => true,
430 LinkerFlavor::Gnu(..)
431 | LinkerFlavor::Darwin(..)
432 | LinkerFlavor::Msvc(_)
433 | LinkerFlavor::Unix(_)
434 | LinkerFlavor::Bpf
435 | LinkerFlavor::Llbc
436 | LinkerFlavor::Ptx => false,
437 }
438 }
439
440 pub fn uses_cc(self) -> bool {
442 match self {
444 LinkerFlavor::Gnu(Cc::Yes, _)
445 | LinkerFlavor::Darwin(Cc::Yes, _)
446 | LinkerFlavor::WasmLld(Cc::Yes)
447 | LinkerFlavor::Unix(Cc::Yes)
448 | LinkerFlavor::EmCc => true,
449 LinkerFlavor::Gnu(..)
450 | LinkerFlavor::Darwin(..)
451 | LinkerFlavor::WasmLld(_)
452 | LinkerFlavor::Msvc(_)
453 | LinkerFlavor::Unix(_)
454 | LinkerFlavor::Bpf
455 | LinkerFlavor::Llbc
456 | LinkerFlavor::Ptx => false,
457 }
458 }
459
460 pub fn with_lld_enabled(self) -> LinkerFlavor {
463 match self {
464 LinkerFlavor::Gnu(cc, Lld::No) => LinkerFlavor::Gnu(cc, Lld::Yes),
465 LinkerFlavor::Darwin(cc, Lld::No) => LinkerFlavor::Darwin(cc, Lld::Yes),
466 LinkerFlavor::Msvc(Lld::No) => LinkerFlavor::Msvc(Lld::Yes),
467 _ => self,
468 }
469 }
470
471 pub fn with_lld_disabled(self) -> LinkerFlavor {
474 match self {
475 LinkerFlavor::Gnu(cc, Lld::Yes) => LinkerFlavor::Gnu(cc, Lld::No),
476 LinkerFlavor::Darwin(cc, Lld::Yes) => LinkerFlavor::Darwin(cc, Lld::No),
477 LinkerFlavor::Msvc(Lld::Yes) => LinkerFlavor::Msvc(Lld::No),
478 _ => self,
479 }
480 }
481}
482
483macro_rules! linker_flavor_cli_impls {
484 ($(($($flavor:tt)*) $string:literal)*) => (
485 impl LinkerFlavorCli {
486 const fn all() -> &'static [LinkerFlavorCli] {
487 &[$($($flavor)*,)*]
488 }
489
490 pub const fn one_of() -> &'static str {
491 concat!("one of: ", $($string, " ",)*)
492 }
493
494 pub fn from_str(s: &str) -> Option<LinkerFlavorCli> {
495 Some(match s {
496 $($string => $($flavor)*,)*
497 _ => return None,
498 })
499 }
500
501 pub fn desc(self) -> &'static str {
502 match self {
503 $($($flavor)* => $string,)*
504 }
505 }
506 }
507 )
508}
509
510linker_flavor_cli_impls! {
511 (LinkerFlavorCli::Gnu(Cc::No, Lld::No)) "gnu"
512 (LinkerFlavorCli::Gnu(Cc::No, Lld::Yes)) "gnu-lld"
513 (LinkerFlavorCli::Gnu(Cc::Yes, Lld::No)) "gnu-cc"
514 (LinkerFlavorCli::Gnu(Cc::Yes, Lld::Yes)) "gnu-lld-cc"
515 (LinkerFlavorCli::Darwin(Cc::No, Lld::No)) "darwin"
516 (LinkerFlavorCli::Darwin(Cc::No, Lld::Yes)) "darwin-lld"
517 (LinkerFlavorCli::Darwin(Cc::Yes, Lld::No)) "darwin-cc"
518 (LinkerFlavorCli::Darwin(Cc::Yes, Lld::Yes)) "darwin-lld-cc"
519 (LinkerFlavorCli::WasmLld(Cc::No)) "wasm-lld"
520 (LinkerFlavorCli::WasmLld(Cc::Yes)) "wasm-lld-cc"
521 (LinkerFlavorCli::Unix(Cc::No)) "unix"
522 (LinkerFlavorCli::Unix(Cc::Yes)) "unix-cc"
523 (LinkerFlavorCli::Msvc(Lld::Yes)) "msvc-lld"
524 (LinkerFlavorCli::Msvc(Lld::No)) "msvc"
525 (LinkerFlavorCli::EmCc) "em-cc"
526 (LinkerFlavorCli::Bpf) "bpf"
527 (LinkerFlavorCli::Llbc) "llbc"
528 (LinkerFlavorCli::Ptx) "ptx"
529
530 (LinkerFlavorCli::Gcc) "gcc"
532 (LinkerFlavorCli::Ld) "ld"
533 (LinkerFlavorCli::Lld(LldFlavor::Ld)) "ld.lld"
534 (LinkerFlavorCli::Lld(LldFlavor::Ld64)) "ld64.lld"
535 (LinkerFlavorCli::Lld(LldFlavor::Link)) "lld-link"
536 (LinkerFlavorCli::Lld(LldFlavor::Wasm)) "wasm-ld"
537 (LinkerFlavorCli::Em) "em"
538}
539
540impl ToJson for LinkerFlavorCli {
541 fn to_json(&self) -> Json {
542 self.desc().to_json()
543 }
544}
545
546#[derive(Clone, Copy, PartialEq, Debug)]
553pub enum LinkSelfContainedDefault {
554 True,
556
557 False,
559
560 InferredForMusl,
562
563 InferredForMingw,
565
566 WithComponents(LinkSelfContainedComponents),
569}
570
571impl FromStr for LinkSelfContainedDefault {
573 type Err = ();
574
575 fn from_str(s: &str) -> Result<LinkSelfContainedDefault, ()> {
576 Ok(match s {
577 "false" => LinkSelfContainedDefault::False,
578 "true" | "wasm" => LinkSelfContainedDefault::True,
579 "musl" => LinkSelfContainedDefault::InferredForMusl,
580 "mingw" => LinkSelfContainedDefault::InferredForMingw,
581 _ => return Err(()),
582 })
583 }
584}
585
586impl ToJson for LinkSelfContainedDefault {
587 fn to_json(&self) -> Json {
588 match *self {
589 LinkSelfContainedDefault::WithComponents(components) => {
590 let mut map = BTreeMap::new();
594 map.insert("components", components);
595 map.to_json()
596 }
597
598 LinkSelfContainedDefault::True => "true".to_json(),
600 LinkSelfContainedDefault::False => "false".to_json(),
601 LinkSelfContainedDefault::InferredForMusl => "musl".to_json(),
602 LinkSelfContainedDefault::InferredForMingw => "mingw".to_json(),
603 }
604 }
605}
606
607impl LinkSelfContainedDefault {
608 pub fn is_disabled(self) -> bool {
611 self == LinkSelfContainedDefault::False
612 }
613
614 fn json_key(self) -> &'static str {
618 match self {
619 LinkSelfContainedDefault::WithComponents(_) => "link-self-contained",
620 _ => "crt-objects-fallback",
621 }
622 }
623
624 pub fn with_linker() -> LinkSelfContainedDefault {
627 LinkSelfContainedDefault::WithComponents(LinkSelfContainedComponents::LINKER)
628 }
629}
630
631bitflags::bitflags! {
632 #[derive(Clone, Copy, PartialEq, Eq, Default)]
633 pub struct LinkSelfContainedComponents: u8 {
635 const CRT_OBJECTS = 1 << 0;
637 const LIBC = 1 << 1;
639 const UNWIND = 1 << 2;
641 const LINKER = 1 << 3;
643 const SANITIZERS = 1 << 4;
645 const MINGW = 1 << 5;
647 }
648}
649rustc_data_structures::external_bitflags_debug! { LinkSelfContainedComponents }
650
651impl LinkSelfContainedComponents {
652 pub fn from_str(s: &str) -> Option<LinkSelfContainedComponents> {
654 Some(match s {
655 "crto" => LinkSelfContainedComponents::CRT_OBJECTS,
656 "libc" => LinkSelfContainedComponents::LIBC,
657 "unwind" => LinkSelfContainedComponents::UNWIND,
658 "linker" => LinkSelfContainedComponents::LINKER,
659 "sanitizers" => LinkSelfContainedComponents::SANITIZERS,
660 "mingw" => LinkSelfContainedComponents::MINGW,
661 _ => return None,
662 })
663 }
664
665 pub fn as_str(self) -> Option<&'static str> {
669 Some(match self {
670 LinkSelfContainedComponents::CRT_OBJECTS => "crto",
671 LinkSelfContainedComponents::LIBC => "libc",
672 LinkSelfContainedComponents::UNWIND => "unwind",
673 LinkSelfContainedComponents::LINKER => "linker",
674 LinkSelfContainedComponents::SANITIZERS => "sanitizers",
675 LinkSelfContainedComponents::MINGW => "mingw",
676 _ => return None,
677 })
678 }
679
680 fn all_components() -> [LinkSelfContainedComponents; 6] {
682 [
683 LinkSelfContainedComponents::CRT_OBJECTS,
684 LinkSelfContainedComponents::LIBC,
685 LinkSelfContainedComponents::UNWIND,
686 LinkSelfContainedComponents::LINKER,
687 LinkSelfContainedComponents::SANITIZERS,
688 LinkSelfContainedComponents::MINGW,
689 ]
690 }
691
692 pub fn are_any_components_enabled(self) -> bool {
694 !self.is_empty()
695 }
696
697 pub fn is_linker_enabled(self) -> bool {
699 self.contains(LinkSelfContainedComponents::LINKER)
700 }
701
702 pub fn is_crt_objects_enabled(self) -> bool {
704 self.contains(LinkSelfContainedComponents::CRT_OBJECTS)
705 }
706}
707
708impl ToJson for LinkSelfContainedComponents {
709 fn to_json(&self) -> Json {
710 let components: Vec<_> = Self::all_components()
711 .into_iter()
712 .filter(|c| self.contains(*c))
713 .map(|c| {
714 c.as_str().unwrap().to_owned()
717 })
718 .collect();
719
720 components.to_json()
721 }
722}
723
724bitflags::bitflags! {
725 #[derive(Clone, Copy, PartialEq, Eq, Default)]
746 pub struct LinkerFeatures: u8 {
747 const CC = 1 << 0;
749 const LLD = 1 << 1;
751 }
752}
753rustc_data_structures::external_bitflags_debug! { LinkerFeatures }
754
755impl LinkerFeatures {
756 pub fn from_str(s: &str) -> Option<LinkerFeatures> {
758 Some(match s {
759 "cc" => LinkerFeatures::CC,
760 "lld" => LinkerFeatures::LLD,
761 _ => return None,
762 })
763 }
764
765 pub fn is_lld_enabled(self) -> bool {
767 self.contains(LinkerFeatures::LLD)
768 }
769
770 pub fn is_cc_enabled(self) -> bool {
772 self.contains(LinkerFeatures::CC)
773 }
774}
775
776#[derive(Clone, Copy, Debug, PartialEq, Hash, Encodable, Decodable, HashStable_Generic)]
777pub enum PanicStrategy {
778 Unwind,
779 Abort,
780}
781
782#[derive(Clone, Copy, Debug, PartialEq, Hash, Encodable, Decodable, HashStable_Generic)]
783pub enum OnBrokenPipe {
784 Default,
785 Kill,
786 Error,
787 Inherit,
788}
789
790impl PanicStrategy {
791 pub fn desc(&self) -> &str {
792 match *self {
793 PanicStrategy::Unwind => "unwind",
794 PanicStrategy::Abort => "abort",
795 }
796 }
797
798 pub const fn desc_symbol(&self) -> Symbol {
799 match *self {
800 PanicStrategy::Unwind => sym::unwind,
801 PanicStrategy::Abort => sym::abort,
802 }
803 }
804
805 pub const fn all() -> [Symbol; 2] {
806 [Self::Abort.desc_symbol(), Self::Unwind.desc_symbol()]
807 }
808}
809
810impl ToJson for PanicStrategy {
811 fn to_json(&self) -> Json {
812 match *self {
813 PanicStrategy::Abort => "abort".to_json(),
814 PanicStrategy::Unwind => "unwind".to_json(),
815 }
816 }
817}
818
819#[derive(Clone, Copy, Debug, PartialEq, Hash)]
820pub enum RelroLevel {
821 Full,
822 Partial,
823 Off,
824 None,
825}
826
827impl RelroLevel {
828 pub fn desc(&self) -> &str {
829 match *self {
830 RelroLevel::Full => "full",
831 RelroLevel::Partial => "partial",
832 RelroLevel::Off => "off",
833 RelroLevel::None => "none",
834 }
835 }
836}
837
838#[derive(Clone, Copy, Debug, PartialEq, Hash)]
839pub enum SymbolVisibility {
840 Hidden,
841 Protected,
842 Interposable,
843}
844
845impl SymbolVisibility {
846 pub fn desc(&self) -> &str {
847 match *self {
848 SymbolVisibility::Hidden => "hidden",
849 SymbolVisibility::Protected => "protected",
850 SymbolVisibility::Interposable => "interposable",
851 }
852 }
853}
854
855impl FromStr for SymbolVisibility {
856 type Err = ();
857
858 fn from_str(s: &str) -> Result<SymbolVisibility, ()> {
859 match s {
860 "hidden" => Ok(SymbolVisibility::Hidden),
861 "protected" => Ok(SymbolVisibility::Protected),
862 "interposable" => Ok(SymbolVisibility::Interposable),
863 _ => Err(()),
864 }
865 }
866}
867
868impl ToJson for SymbolVisibility {
869 fn to_json(&self) -> Json {
870 match *self {
871 SymbolVisibility::Hidden => "hidden".to_json(),
872 SymbolVisibility::Protected => "protected".to_json(),
873 SymbolVisibility::Interposable => "interposable".to_json(),
874 }
875 }
876}
877
878impl FromStr for RelroLevel {
879 type Err = ();
880
881 fn from_str(s: &str) -> Result<RelroLevel, ()> {
882 match s {
883 "full" => Ok(RelroLevel::Full),
884 "partial" => Ok(RelroLevel::Partial),
885 "off" => Ok(RelroLevel::Off),
886 "none" => Ok(RelroLevel::None),
887 _ => Err(()),
888 }
889 }
890}
891
892impl ToJson for RelroLevel {
893 fn to_json(&self) -> Json {
894 match *self {
895 RelroLevel::Full => "full".to_json(),
896 RelroLevel::Partial => "partial".to_json(),
897 RelroLevel::Off => "off".to_json(),
898 RelroLevel::None => "None".to_json(),
899 }
900 }
901}
902
903#[derive(Clone, Debug, PartialEq, Hash)]
904pub enum SmallDataThresholdSupport {
905 None,
906 DefaultForArch,
907 LlvmModuleFlag(StaticCow<str>),
908 LlvmArg(StaticCow<str>),
909}
910
911impl FromStr for SmallDataThresholdSupport {
912 type Err = ();
913
914 fn from_str(s: &str) -> Result<Self, Self::Err> {
915 if s == "none" {
916 Ok(Self::None)
917 } else if s == "default-for-arch" {
918 Ok(Self::DefaultForArch)
919 } else if let Some(flag) = s.strip_prefix("llvm-module-flag=") {
920 Ok(Self::LlvmModuleFlag(flag.to_string().into()))
921 } else if let Some(arg) = s.strip_prefix("llvm-arg=") {
922 Ok(Self::LlvmArg(arg.to_string().into()))
923 } else {
924 Err(())
925 }
926 }
927}
928
929impl ToJson for SmallDataThresholdSupport {
930 fn to_json(&self) -> Value {
931 match self {
932 Self::None => "none".to_json(),
933 Self::DefaultForArch => "default-for-arch".to_json(),
934 Self::LlvmModuleFlag(flag) => format!("llvm-module-flag={flag}").to_json(),
935 Self::LlvmArg(arg) => format!("llvm-arg={arg}").to_json(),
936 }
937 }
938}
939
940#[derive(Clone, Copy, Debug, PartialEq, Hash)]
941pub enum MergeFunctions {
942 Disabled,
943 Trampolines,
944 Aliases,
945}
946
947impl MergeFunctions {
948 pub fn desc(&self) -> &str {
949 match *self {
950 MergeFunctions::Disabled => "disabled",
951 MergeFunctions::Trampolines => "trampolines",
952 MergeFunctions::Aliases => "aliases",
953 }
954 }
955}
956
957impl FromStr for MergeFunctions {
958 type Err = ();
959
960 fn from_str(s: &str) -> Result<MergeFunctions, ()> {
961 match s {
962 "disabled" => Ok(MergeFunctions::Disabled),
963 "trampolines" => Ok(MergeFunctions::Trampolines),
964 "aliases" => Ok(MergeFunctions::Aliases),
965 _ => Err(()),
966 }
967 }
968}
969
970impl ToJson for MergeFunctions {
971 fn to_json(&self) -> Json {
972 match *self {
973 MergeFunctions::Disabled => "disabled".to_json(),
974 MergeFunctions::Trampolines => "trampolines".to_json(),
975 MergeFunctions::Aliases => "aliases".to_json(),
976 }
977 }
978}
979
980#[derive(Clone, Copy, PartialEq, Hash, Debug)]
981pub enum RelocModel {
982 Static,
983 Pic,
984 Pie,
985 DynamicNoPic,
986 Ropi,
987 Rwpi,
988 RopiRwpi,
989}
990
991impl RelocModel {
992 pub fn desc(&self) -> &str {
993 match *self {
994 RelocModel::Static => "static",
995 RelocModel::Pic => "pic",
996 RelocModel::Pie => "pie",
997 RelocModel::DynamicNoPic => "dynamic-no-pic",
998 RelocModel::Ropi => "ropi",
999 RelocModel::Rwpi => "rwpi",
1000 RelocModel::RopiRwpi => "ropi-rwpi",
1001 }
1002 }
1003 pub const fn desc_symbol(&self) -> Symbol {
1004 match *self {
1005 RelocModel::Static => kw::Static,
1006 RelocModel::Pic => sym::pic,
1007 RelocModel::Pie => sym::pie,
1008 RelocModel::DynamicNoPic => sym::dynamic_no_pic,
1009 RelocModel::Ropi => sym::ropi,
1010 RelocModel::Rwpi => sym::rwpi,
1011 RelocModel::RopiRwpi => sym::ropi_rwpi,
1012 }
1013 }
1014
1015 pub const fn all() -> [Symbol; 7] {
1016 [
1017 RelocModel::Static.desc_symbol(),
1018 RelocModel::Pic.desc_symbol(),
1019 RelocModel::Pie.desc_symbol(),
1020 RelocModel::DynamicNoPic.desc_symbol(),
1021 RelocModel::Ropi.desc_symbol(),
1022 RelocModel::Rwpi.desc_symbol(),
1023 RelocModel::RopiRwpi.desc_symbol(),
1024 ]
1025 }
1026}
1027
1028impl FromStr for RelocModel {
1029 type Err = ();
1030
1031 fn from_str(s: &str) -> Result<RelocModel, ()> {
1032 Ok(match s {
1033 "static" => RelocModel::Static,
1034 "pic" => RelocModel::Pic,
1035 "pie" => RelocModel::Pie,
1036 "dynamic-no-pic" => RelocModel::DynamicNoPic,
1037 "ropi" => RelocModel::Ropi,
1038 "rwpi" => RelocModel::Rwpi,
1039 "ropi-rwpi" => RelocModel::RopiRwpi,
1040 _ => return Err(()),
1041 })
1042 }
1043}
1044
1045impl ToJson for RelocModel {
1046 fn to_json(&self) -> Json {
1047 self.desc().to_json()
1048 }
1049}
1050
1051#[derive(Clone, Copy, PartialEq, Hash, Debug)]
1052pub enum CodeModel {
1053 Tiny,
1054 Small,
1055 Kernel,
1056 Medium,
1057 Large,
1058}
1059
1060impl FromStr for CodeModel {
1061 type Err = ();
1062
1063 fn from_str(s: &str) -> Result<CodeModel, ()> {
1064 Ok(match s {
1065 "tiny" => CodeModel::Tiny,
1066 "small" => CodeModel::Small,
1067 "kernel" => CodeModel::Kernel,
1068 "medium" => CodeModel::Medium,
1069 "large" => CodeModel::Large,
1070 _ => return Err(()),
1071 })
1072 }
1073}
1074
1075impl ToJson for CodeModel {
1076 fn to_json(&self) -> Json {
1077 match *self {
1078 CodeModel::Tiny => "tiny",
1079 CodeModel::Small => "small",
1080 CodeModel::Kernel => "kernel",
1081 CodeModel::Medium => "medium",
1082 CodeModel::Large => "large",
1083 }
1084 .to_json()
1085 }
1086}
1087
1088#[derive(Clone, Copy, PartialEq, Hash, Debug)]
1090pub enum FloatAbi {
1091 Soft,
1092 Hard,
1093}
1094
1095impl FromStr for FloatAbi {
1096 type Err = ();
1097
1098 fn from_str(s: &str) -> Result<FloatAbi, ()> {
1099 Ok(match s {
1100 "soft" => FloatAbi::Soft,
1101 "hard" => FloatAbi::Hard,
1102 _ => return Err(()),
1103 })
1104 }
1105}
1106
1107impl ToJson for FloatAbi {
1108 fn to_json(&self) -> Json {
1109 match *self {
1110 FloatAbi::Soft => "soft",
1111 FloatAbi::Hard => "hard",
1112 }
1113 .to_json()
1114 }
1115}
1116
1117#[derive(Clone, Copy, PartialEq, Hash, Debug)]
1119pub enum RustcAbi {
1120 X86Sse2,
1122 X86Softfloat,
1124}
1125
1126impl FromStr for RustcAbi {
1127 type Err = ();
1128
1129 fn from_str(s: &str) -> Result<RustcAbi, ()> {
1130 Ok(match s {
1131 "x86-sse2" => RustcAbi::X86Sse2,
1132 "x86-softfloat" => RustcAbi::X86Softfloat,
1133 _ => return Err(()),
1134 })
1135 }
1136}
1137
1138impl ToJson for RustcAbi {
1139 fn to_json(&self) -> Json {
1140 match *self {
1141 RustcAbi::X86Sse2 => "x86-sse2",
1142 RustcAbi::X86Softfloat => "x86-softfloat",
1143 }
1144 .to_json()
1145 }
1146}
1147
1148#[derive(Clone, Copy, PartialEq, Hash, Debug)]
1149pub enum TlsModel {
1150 GeneralDynamic,
1151 LocalDynamic,
1152 InitialExec,
1153 LocalExec,
1154 Emulated,
1155}
1156
1157impl FromStr for TlsModel {
1158 type Err = ();
1159
1160 fn from_str(s: &str) -> Result<TlsModel, ()> {
1161 Ok(match s {
1162 "global-dynamic" => TlsModel::GeneralDynamic,
1165 "local-dynamic" => TlsModel::LocalDynamic,
1166 "initial-exec" => TlsModel::InitialExec,
1167 "local-exec" => TlsModel::LocalExec,
1168 "emulated" => TlsModel::Emulated,
1169 _ => return Err(()),
1170 })
1171 }
1172}
1173
1174impl ToJson for TlsModel {
1175 fn to_json(&self) -> Json {
1176 match *self {
1177 TlsModel::GeneralDynamic => "global-dynamic",
1178 TlsModel::LocalDynamic => "local-dynamic",
1179 TlsModel::InitialExec => "initial-exec",
1180 TlsModel::LocalExec => "local-exec",
1181 TlsModel::Emulated => "emulated",
1182 }
1183 .to_json()
1184 }
1185}
1186
1187#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug)]
1189pub enum LinkOutputKind {
1190 DynamicNoPicExe,
1192 DynamicPicExe,
1194 StaticNoPicExe,
1196 StaticPicExe,
1198 DynamicDylib,
1200 StaticDylib,
1202 WasiReactorExe,
1204}
1205
1206impl LinkOutputKind {
1207 fn as_str(&self) -> &'static str {
1208 match self {
1209 LinkOutputKind::DynamicNoPicExe => "dynamic-nopic-exe",
1210 LinkOutputKind::DynamicPicExe => "dynamic-pic-exe",
1211 LinkOutputKind::StaticNoPicExe => "static-nopic-exe",
1212 LinkOutputKind::StaticPicExe => "static-pic-exe",
1213 LinkOutputKind::DynamicDylib => "dynamic-dylib",
1214 LinkOutputKind::StaticDylib => "static-dylib",
1215 LinkOutputKind::WasiReactorExe => "wasi-reactor-exe",
1216 }
1217 }
1218
1219 pub(super) fn from_str(s: &str) -> Option<LinkOutputKind> {
1220 Some(match s {
1221 "dynamic-nopic-exe" => LinkOutputKind::DynamicNoPicExe,
1222 "dynamic-pic-exe" => LinkOutputKind::DynamicPicExe,
1223 "static-nopic-exe" => LinkOutputKind::StaticNoPicExe,
1224 "static-pic-exe" => LinkOutputKind::StaticPicExe,
1225 "dynamic-dylib" => LinkOutputKind::DynamicDylib,
1226 "static-dylib" => LinkOutputKind::StaticDylib,
1227 "wasi-reactor-exe" => LinkOutputKind::WasiReactorExe,
1228 _ => return None,
1229 })
1230 }
1231
1232 pub fn can_link_dylib(self) -> bool {
1233 match self {
1234 LinkOutputKind::StaticNoPicExe | LinkOutputKind::StaticPicExe => false,
1235 LinkOutputKind::DynamicNoPicExe
1236 | LinkOutputKind::DynamicPicExe
1237 | LinkOutputKind::DynamicDylib
1238 | LinkOutputKind::StaticDylib
1239 | LinkOutputKind::WasiReactorExe => true,
1240 }
1241 }
1242}
1243
1244impl fmt::Display for LinkOutputKind {
1245 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1246 f.write_str(self.as_str())
1247 }
1248}
1249
1250pub type LinkArgs = BTreeMap<LinkerFlavor, Vec<StaticCow<str>>>;
1251pub type LinkArgsCli = BTreeMap<LinkerFlavorCli, Vec<StaticCow<str>>>;
1252
1253#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
1258pub enum DebuginfoKind {
1259 #[default]
1261 Dwarf,
1262 DwarfDsym,
1264 Pdb,
1266}
1267
1268impl DebuginfoKind {
1269 fn as_str(&self) -> &'static str {
1270 match self {
1271 DebuginfoKind::Dwarf => "dwarf",
1272 DebuginfoKind::DwarfDsym => "dwarf-dsym",
1273 DebuginfoKind::Pdb => "pdb",
1274 }
1275 }
1276}
1277
1278impl FromStr for DebuginfoKind {
1279 type Err = ();
1280
1281 fn from_str(s: &str) -> Result<Self, ()> {
1282 Ok(match s {
1283 "dwarf" => DebuginfoKind::Dwarf,
1284 "dwarf-dsym" => DebuginfoKind::DwarfDsym,
1285 "pdb" => DebuginfoKind::Pdb,
1286 _ => return Err(()),
1287 })
1288 }
1289}
1290
1291impl ToJson for DebuginfoKind {
1292 fn to_json(&self) -> Json {
1293 self.as_str().to_json()
1294 }
1295}
1296
1297impl fmt::Display for DebuginfoKind {
1298 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1299 f.write_str(self.as_str())
1300 }
1301}
1302
1303#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
1304pub enum SplitDebuginfo {
1305 #[default]
1313 Off,
1314
1315 Packed,
1322
1323 Unpacked,
1330}
1331
1332impl SplitDebuginfo {
1333 fn as_str(&self) -> &'static str {
1334 match self {
1335 SplitDebuginfo::Off => "off",
1336 SplitDebuginfo::Packed => "packed",
1337 SplitDebuginfo::Unpacked => "unpacked",
1338 }
1339 }
1340}
1341
1342impl FromStr for SplitDebuginfo {
1343 type Err = ();
1344
1345 fn from_str(s: &str) -> Result<Self, ()> {
1346 Ok(match s {
1347 "off" => SplitDebuginfo::Off,
1348 "unpacked" => SplitDebuginfo::Unpacked,
1349 "packed" => SplitDebuginfo::Packed,
1350 _ => return Err(()),
1351 })
1352 }
1353}
1354
1355impl ToJson for SplitDebuginfo {
1356 fn to_json(&self) -> Json {
1357 self.as_str().to_json()
1358 }
1359}
1360
1361impl fmt::Display for SplitDebuginfo {
1362 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1363 f.write_str(self.as_str())
1364 }
1365}
1366
1367#[derive(Clone, Debug, PartialEq, Eq)]
1368pub enum StackProbeType {
1369 None,
1371 Inline,
1375 Call,
1377 InlineOrCall { min_llvm_version_for_inline: (u32, u32, u32) },
1380}
1381
1382impl StackProbeType {
1383 fn from_json(json: &Json) -> Result<Self, String> {
1384 let object = json.as_object().ok_or_else(|| "expected a JSON object")?;
1385 let kind = object
1386 .get("kind")
1387 .and_then(|o| o.as_str())
1388 .ok_or_else(|| "expected `kind` to be a string")?;
1389 match kind {
1390 "none" => Ok(StackProbeType::None),
1391 "inline" => Ok(StackProbeType::Inline),
1392 "call" => Ok(StackProbeType::Call),
1393 "inline-or-call" => {
1394 let min_version = object
1395 .get("min-llvm-version-for-inline")
1396 .and_then(|o| o.as_array())
1397 .ok_or_else(|| "expected `min-llvm-version-for-inline` to be an array")?;
1398 let mut iter = min_version.into_iter().map(|v| {
1399 let int = v.as_u64().ok_or_else(
1400 || "expected `min-llvm-version-for-inline` values to be integers",
1401 )?;
1402 u32::try_from(int)
1403 .map_err(|_| "`min-llvm-version-for-inline` values don't convert to u32")
1404 });
1405 let min_llvm_version_for_inline = (
1406 iter.next().unwrap_or(Ok(11))?,
1407 iter.next().unwrap_or(Ok(0))?,
1408 iter.next().unwrap_or(Ok(0))?,
1409 );
1410 Ok(StackProbeType::InlineOrCall { min_llvm_version_for_inline })
1411 }
1412 _ => Err(String::from(
1413 "`kind` expected to be one of `none`, `inline`, `call` or `inline-or-call`",
1414 )),
1415 }
1416 }
1417}
1418
1419impl ToJson for StackProbeType {
1420 fn to_json(&self) -> Json {
1421 Json::Object(match self {
1422 StackProbeType::None => {
1423 [(String::from("kind"), "none".to_json())].into_iter().collect()
1424 }
1425 StackProbeType::Inline => {
1426 [(String::from("kind"), "inline".to_json())].into_iter().collect()
1427 }
1428 StackProbeType::Call => {
1429 [(String::from("kind"), "call".to_json())].into_iter().collect()
1430 }
1431 StackProbeType::InlineOrCall { min_llvm_version_for_inline: (maj, min, patch) } => [
1432 (String::from("kind"), "inline-or-call".to_json()),
1433 (
1434 String::from("min-llvm-version-for-inline"),
1435 Json::Array(vec![maj.to_json(), min.to_json(), patch.to_json()]),
1436 ),
1437 ]
1438 .into_iter()
1439 .collect(),
1440 })
1441 }
1442}
1443
1444#[derive(Default, Clone, Copy, PartialEq, Eq, Hash, Encodable, Decodable, HashStable_Generic)]
1445pub struct SanitizerSet(u16);
1446bitflags::bitflags! {
1447 impl SanitizerSet: u16 {
1448 const ADDRESS = 1 << 0;
1449 const LEAK = 1 << 1;
1450 const MEMORY = 1 << 2;
1451 const THREAD = 1 << 3;
1452 const HWADDRESS = 1 << 4;
1453 const CFI = 1 << 5;
1454 const MEMTAG = 1 << 6;
1455 const SHADOWCALLSTACK = 1 << 7;
1456 const KCFI = 1 << 8;
1457 const KERNELADDRESS = 1 << 9;
1458 const SAFESTACK = 1 << 10;
1459 const DATAFLOW = 1 << 11;
1460 }
1461}
1462rustc_data_structures::external_bitflags_debug! { SanitizerSet }
1463
1464impl SanitizerSet {
1465 const MUTUALLY_EXCLUSIVE: &'static [(SanitizerSet, SanitizerSet)] = &[
1468 (SanitizerSet::ADDRESS, SanitizerSet::MEMORY),
1469 (SanitizerSet::ADDRESS, SanitizerSet::THREAD),
1470 (SanitizerSet::ADDRESS, SanitizerSet::HWADDRESS),
1471 (SanitizerSet::ADDRESS, SanitizerSet::MEMTAG),
1472 (SanitizerSet::ADDRESS, SanitizerSet::KERNELADDRESS),
1473 (SanitizerSet::ADDRESS, SanitizerSet::SAFESTACK),
1474 (SanitizerSet::LEAK, SanitizerSet::MEMORY),
1475 (SanitizerSet::LEAK, SanitizerSet::THREAD),
1476 (SanitizerSet::LEAK, SanitizerSet::KERNELADDRESS),
1477 (SanitizerSet::LEAK, SanitizerSet::SAFESTACK),
1478 (SanitizerSet::MEMORY, SanitizerSet::THREAD),
1479 (SanitizerSet::MEMORY, SanitizerSet::HWADDRESS),
1480 (SanitizerSet::MEMORY, SanitizerSet::KERNELADDRESS),
1481 (SanitizerSet::MEMORY, SanitizerSet::SAFESTACK),
1482 (SanitizerSet::THREAD, SanitizerSet::HWADDRESS),
1483 (SanitizerSet::THREAD, SanitizerSet::KERNELADDRESS),
1484 (SanitizerSet::THREAD, SanitizerSet::SAFESTACK),
1485 (SanitizerSet::HWADDRESS, SanitizerSet::MEMTAG),
1486 (SanitizerSet::HWADDRESS, SanitizerSet::KERNELADDRESS),
1487 (SanitizerSet::HWADDRESS, SanitizerSet::SAFESTACK),
1488 (SanitizerSet::CFI, SanitizerSet::KCFI),
1489 (SanitizerSet::MEMTAG, SanitizerSet::KERNELADDRESS),
1490 (SanitizerSet::KERNELADDRESS, SanitizerSet::SAFESTACK),
1491 ];
1492
1493 pub fn as_str(self) -> Option<&'static str> {
1497 Some(match self {
1498 SanitizerSet::ADDRESS => "address",
1499 SanitizerSet::CFI => "cfi",
1500 SanitizerSet::DATAFLOW => "dataflow",
1501 SanitizerSet::KCFI => "kcfi",
1502 SanitizerSet::KERNELADDRESS => "kernel-address",
1503 SanitizerSet::LEAK => "leak",
1504 SanitizerSet::MEMORY => "memory",
1505 SanitizerSet::MEMTAG => "memtag",
1506 SanitizerSet::SAFESTACK => "safestack",
1507 SanitizerSet::SHADOWCALLSTACK => "shadow-call-stack",
1508 SanitizerSet::THREAD => "thread",
1509 SanitizerSet::HWADDRESS => "hwaddress",
1510 _ => return None,
1511 })
1512 }
1513
1514 pub fn mutually_exclusive(self) -> Option<(SanitizerSet, SanitizerSet)> {
1515 Self::MUTUALLY_EXCLUSIVE
1516 .into_iter()
1517 .find(|&(a, b)| self.contains(*a) && self.contains(*b))
1518 .copied()
1519 }
1520}
1521
1522impl fmt::Display for SanitizerSet {
1524 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1525 let mut first = true;
1526 for s in *self {
1527 let name = s.as_str().unwrap_or_else(|| panic!("unrecognized sanitizer {s:?}"));
1528 if !first {
1529 f.write_str(", ")?;
1530 }
1531 f.write_str(name)?;
1532 first = false;
1533 }
1534 Ok(())
1535 }
1536}
1537
1538impl ToJson for SanitizerSet {
1539 fn to_json(&self) -> Json {
1540 self.into_iter()
1541 .map(|v| Some(v.as_str()?.to_json()))
1542 .collect::<Option<Vec<_>>>()
1543 .unwrap_or_default()
1544 .to_json()
1545 }
1546}
1547
1548#[derive(Clone, Copy, PartialEq, Hash, Debug)]
1549pub enum FramePointer {
1550 Always,
1552 NonLeaf,
1555 MayOmit,
1559}
1560
1561impl FramePointer {
1562 #[inline]
1565 pub fn ratchet(&mut self, rhs: FramePointer) -> FramePointer {
1566 *self = match (*self, rhs) {
1567 (FramePointer::Always, _) | (_, FramePointer::Always) => FramePointer::Always,
1568 (FramePointer::NonLeaf, _) | (_, FramePointer::NonLeaf) => FramePointer::NonLeaf,
1569 _ => FramePointer::MayOmit,
1570 };
1571 *self
1572 }
1573}
1574
1575impl FromStr for FramePointer {
1576 type Err = ();
1577 fn from_str(s: &str) -> Result<Self, ()> {
1578 Ok(match s {
1579 "always" => Self::Always,
1580 "non-leaf" => Self::NonLeaf,
1581 "may-omit" => Self::MayOmit,
1582 _ => return Err(()),
1583 })
1584 }
1585}
1586
1587impl ToJson for FramePointer {
1588 fn to_json(&self) -> Json {
1589 match *self {
1590 Self::Always => "always",
1591 Self::NonLeaf => "non-leaf",
1592 Self::MayOmit => "may-omit",
1593 }
1594 .to_json()
1595 }
1596}
1597
1598#[derive(Clone, Copy, Debug, PartialEq, Hash, Eq)]
1600pub enum StackProtector {
1601 None,
1603
1604 Basic,
1609
1610 Strong,
1615
1616 All,
1618}
1619
1620impl StackProtector {
1621 fn as_str(&self) -> &'static str {
1622 match self {
1623 StackProtector::None => "none",
1624 StackProtector::Basic => "basic",
1625 StackProtector::Strong => "strong",
1626 StackProtector::All => "all",
1627 }
1628 }
1629}
1630
1631impl FromStr for StackProtector {
1632 type Err = ();
1633
1634 fn from_str(s: &str) -> Result<StackProtector, ()> {
1635 Ok(match s {
1636 "none" => StackProtector::None,
1637 "basic" => StackProtector::Basic,
1638 "strong" => StackProtector::Strong,
1639 "all" => StackProtector::All,
1640 _ => return Err(()),
1641 })
1642 }
1643}
1644
1645impl fmt::Display for StackProtector {
1646 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1647 f.write_str(self.as_str())
1648 }
1649}
1650
1651#[derive(PartialEq, Clone, Debug)]
1652pub enum BinaryFormat {
1653 Coff,
1654 Elf,
1655 MachO,
1656 Wasm,
1657 Xcoff,
1658}
1659
1660impl BinaryFormat {
1661 pub fn to_object(&self) -> object::BinaryFormat {
1663 match self {
1664 Self::Coff => object::BinaryFormat::Coff,
1665 Self::Elf => object::BinaryFormat::Elf,
1666 Self::MachO => object::BinaryFormat::MachO,
1667 Self::Wasm => object::BinaryFormat::Wasm,
1668 Self::Xcoff => object::BinaryFormat::Xcoff,
1669 }
1670 }
1671}
1672
1673impl FromStr for BinaryFormat {
1674 type Err = ();
1675 fn from_str(s: &str) -> Result<Self, Self::Err> {
1676 match s {
1677 "coff" => Ok(Self::Coff),
1678 "elf" => Ok(Self::Elf),
1679 "mach-o" => Ok(Self::MachO),
1680 "wasm" => Ok(Self::Wasm),
1681 "xcoff" => Ok(Self::Xcoff),
1682 _ => Err(()),
1683 }
1684 }
1685}
1686
1687impl ToJson for BinaryFormat {
1688 fn to_json(&self) -> Json {
1689 match self {
1690 Self::Coff => "coff",
1691 Self::Elf => "elf",
1692 Self::MachO => "mach-o",
1693 Self::Wasm => "wasm",
1694 Self::Xcoff => "xcoff",
1695 }
1696 .to_json()
1697 }
1698}
1699
1700macro_rules! supported_targets {
1701 ( $(($tuple:literal, $module:ident),)+ ) => {
1702 mod targets {
1703 $(pub(crate) mod $module;)+
1704 }
1705
1706 pub static TARGETS: &[&str] = &[$($tuple),+];
1708
1709 fn load_builtin(target: &str) -> Option<Target> {
1710 let t = match target {
1711 $( $tuple => targets::$module::target(), )+
1712 _ => return None,
1713 };
1714 debug!("got builtin target: {:?}", t);
1715 Some(t)
1716 }
1717
1718 fn load_all_builtins() -> impl Iterator<Item = Target> {
1719 [
1720 $( targets::$module::target, )+
1721 ]
1722 .into_iter()
1723 .map(|f| f())
1724 }
1725
1726 #[cfg(test)]
1727 mod tests {
1728 $(
1730 #[test] fn $module() {
1732 crate::spec::targets::$module::target().test_target()
1733 }
1734 )+
1735 }
1736 };
1737}
1738
1739supported_targets! {
1740 ("x86_64-unknown-linux-gnu", x86_64_unknown_linux_gnu),
1741 ("x86_64-unknown-linux-gnux32", x86_64_unknown_linux_gnux32),
1742 ("i686-unknown-linux-gnu", i686_unknown_linux_gnu),
1743 ("i586-unknown-linux-gnu", i586_unknown_linux_gnu),
1744 ("loongarch64-unknown-linux-gnu", loongarch64_unknown_linux_gnu),
1745 ("loongarch64-unknown-linux-musl", loongarch64_unknown_linux_musl),
1746 ("m68k-unknown-linux-gnu", m68k_unknown_linux_gnu),
1747 ("m68k-unknown-none-elf", m68k_unknown_none_elf),
1748 ("csky-unknown-linux-gnuabiv2", csky_unknown_linux_gnuabiv2),
1749 ("csky-unknown-linux-gnuabiv2hf", csky_unknown_linux_gnuabiv2hf),
1750 ("mips-unknown-linux-gnu", mips_unknown_linux_gnu),
1751 ("mips64-unknown-linux-gnuabi64", mips64_unknown_linux_gnuabi64),
1752 ("mips64el-unknown-linux-gnuabi64", mips64el_unknown_linux_gnuabi64),
1753 ("mipsisa32r6-unknown-linux-gnu", mipsisa32r6_unknown_linux_gnu),
1754 ("mipsisa32r6el-unknown-linux-gnu", mipsisa32r6el_unknown_linux_gnu),
1755 ("mipsisa64r6-unknown-linux-gnuabi64", mipsisa64r6_unknown_linux_gnuabi64),
1756 ("mipsisa64r6el-unknown-linux-gnuabi64", mipsisa64r6el_unknown_linux_gnuabi64),
1757 ("mipsel-unknown-linux-gnu", mipsel_unknown_linux_gnu),
1758 ("powerpc-unknown-linux-gnu", powerpc_unknown_linux_gnu),
1759 ("powerpc-unknown-linux-gnuspe", powerpc_unknown_linux_gnuspe),
1760 ("powerpc-unknown-linux-musl", powerpc_unknown_linux_musl),
1761 ("powerpc-unknown-linux-muslspe", powerpc_unknown_linux_muslspe),
1762 ("powerpc64-ibm-aix", powerpc64_ibm_aix),
1763 ("powerpc64-unknown-linux-gnu", powerpc64_unknown_linux_gnu),
1764 ("powerpc64-unknown-linux-musl", powerpc64_unknown_linux_musl),
1765 ("powerpc64le-unknown-linux-gnu", powerpc64le_unknown_linux_gnu),
1766 ("powerpc64le-unknown-linux-musl", powerpc64le_unknown_linux_musl),
1767 ("s390x-unknown-linux-gnu", s390x_unknown_linux_gnu),
1768 ("s390x-unknown-linux-musl", s390x_unknown_linux_musl),
1769 ("sparc-unknown-linux-gnu", sparc_unknown_linux_gnu),
1770 ("sparc64-unknown-linux-gnu", sparc64_unknown_linux_gnu),
1771 ("arm-unknown-linux-gnueabi", arm_unknown_linux_gnueabi),
1772 ("arm-unknown-linux-gnueabihf", arm_unknown_linux_gnueabihf),
1773 ("armeb-unknown-linux-gnueabi", armeb_unknown_linux_gnueabi),
1774 ("arm-unknown-linux-musleabi", arm_unknown_linux_musleabi),
1775 ("arm-unknown-linux-musleabihf", arm_unknown_linux_musleabihf),
1776 ("armv4t-unknown-linux-gnueabi", armv4t_unknown_linux_gnueabi),
1777 ("armv5te-unknown-linux-gnueabi", armv5te_unknown_linux_gnueabi),
1778 ("armv5te-unknown-linux-musleabi", armv5te_unknown_linux_musleabi),
1779 ("armv5te-unknown-linux-uclibceabi", armv5te_unknown_linux_uclibceabi),
1780 ("armv7-unknown-linux-gnueabi", armv7_unknown_linux_gnueabi),
1781 ("armv7-unknown-linux-gnueabihf", armv7_unknown_linux_gnueabihf),
1782 ("thumbv7neon-unknown-linux-gnueabihf", thumbv7neon_unknown_linux_gnueabihf),
1783 ("thumbv7neon-unknown-linux-musleabihf", thumbv7neon_unknown_linux_musleabihf),
1784 ("armv7-unknown-linux-musleabi", armv7_unknown_linux_musleabi),
1785 ("armv7-unknown-linux-musleabihf", armv7_unknown_linux_musleabihf),
1786 ("aarch64-unknown-linux-gnu", aarch64_unknown_linux_gnu),
1787 ("aarch64-unknown-linux-musl", aarch64_unknown_linux_musl),
1788 ("x86_64-unknown-linux-musl", x86_64_unknown_linux_musl),
1789 ("i686-unknown-linux-musl", i686_unknown_linux_musl),
1790 ("i586-unknown-linux-musl", i586_unknown_linux_musl),
1791 ("mips-unknown-linux-musl", mips_unknown_linux_musl),
1792 ("mipsel-unknown-linux-musl", mipsel_unknown_linux_musl),
1793 ("mips64-unknown-linux-muslabi64", mips64_unknown_linux_muslabi64),
1794 ("mips64el-unknown-linux-muslabi64", mips64el_unknown_linux_muslabi64),
1795 ("hexagon-unknown-linux-musl", hexagon_unknown_linux_musl),
1796 ("hexagon-unknown-none-elf", hexagon_unknown_none_elf),
1797
1798 ("mips-unknown-linux-uclibc", mips_unknown_linux_uclibc),
1799 ("mipsel-unknown-linux-uclibc", mipsel_unknown_linux_uclibc),
1800
1801 ("i686-linux-android", i686_linux_android),
1802 ("x86_64-linux-android", x86_64_linux_android),
1803 ("arm-linux-androideabi", arm_linux_androideabi),
1804 ("armv7-linux-androideabi", armv7_linux_androideabi),
1805 ("thumbv7neon-linux-androideabi", thumbv7neon_linux_androideabi),
1806 ("aarch64-linux-android", aarch64_linux_android),
1807 ("riscv64-linux-android", riscv64_linux_android),
1808
1809 ("aarch64-unknown-freebsd", aarch64_unknown_freebsd),
1810 ("armv6-unknown-freebsd", armv6_unknown_freebsd),
1811 ("armv7-unknown-freebsd", armv7_unknown_freebsd),
1812 ("i686-unknown-freebsd", i686_unknown_freebsd),
1813 ("powerpc-unknown-freebsd", powerpc_unknown_freebsd),
1814 ("powerpc64-unknown-freebsd", powerpc64_unknown_freebsd),
1815 ("powerpc64le-unknown-freebsd", powerpc64le_unknown_freebsd),
1816 ("riscv64gc-unknown-freebsd", riscv64gc_unknown_freebsd),
1817 ("x86_64-unknown-freebsd", x86_64_unknown_freebsd),
1818
1819 ("x86_64-unknown-dragonfly", x86_64_unknown_dragonfly),
1820
1821 ("aarch64-unknown-openbsd", aarch64_unknown_openbsd),
1822 ("i686-unknown-openbsd", i686_unknown_openbsd),
1823 ("powerpc-unknown-openbsd", powerpc_unknown_openbsd),
1824 ("powerpc64-unknown-openbsd", powerpc64_unknown_openbsd),
1825 ("riscv64gc-unknown-openbsd", riscv64gc_unknown_openbsd),
1826 ("sparc64-unknown-openbsd", sparc64_unknown_openbsd),
1827 ("x86_64-unknown-openbsd", x86_64_unknown_openbsd),
1828
1829 ("aarch64-unknown-netbsd", aarch64_unknown_netbsd),
1830 ("aarch64_be-unknown-netbsd", aarch64_be_unknown_netbsd),
1831 ("armv6-unknown-netbsd-eabihf", armv6_unknown_netbsd_eabihf),
1832 ("armv7-unknown-netbsd-eabihf", armv7_unknown_netbsd_eabihf),
1833 ("i586-unknown-netbsd", i586_unknown_netbsd),
1834 ("i686-unknown-netbsd", i686_unknown_netbsd),
1835 ("mipsel-unknown-netbsd", mipsel_unknown_netbsd),
1836 ("powerpc-unknown-netbsd", powerpc_unknown_netbsd),
1837 ("riscv64gc-unknown-netbsd", riscv64gc_unknown_netbsd),
1838 ("sparc64-unknown-netbsd", sparc64_unknown_netbsd),
1839 ("x86_64-unknown-netbsd", x86_64_unknown_netbsd),
1840
1841 ("i686-unknown-haiku", i686_unknown_haiku),
1842 ("x86_64-unknown-haiku", x86_64_unknown_haiku),
1843
1844 ("i686-unknown-hurd-gnu", i686_unknown_hurd_gnu),
1845 ("x86_64-unknown-hurd-gnu", x86_64_unknown_hurd_gnu),
1846
1847 ("aarch64-apple-darwin", aarch64_apple_darwin),
1848 ("arm64e-apple-darwin", arm64e_apple_darwin),
1849 ("x86_64-apple-darwin", x86_64_apple_darwin),
1850 ("x86_64h-apple-darwin", x86_64h_apple_darwin),
1851 ("i686-apple-darwin", i686_apple_darwin),
1852
1853 ("aarch64-unknown-fuchsia", aarch64_unknown_fuchsia),
1854 ("riscv64gc-unknown-fuchsia", riscv64gc_unknown_fuchsia),
1855 ("x86_64-unknown-fuchsia", x86_64_unknown_fuchsia),
1856
1857 ("avr-none", avr_none),
1858
1859 ("x86_64-unknown-l4re-uclibc", x86_64_unknown_l4re_uclibc),
1860
1861 ("aarch64-unknown-redox", aarch64_unknown_redox),
1862 ("i586-unknown-redox", i586_unknown_redox),
1863 ("x86_64-unknown-redox", x86_64_unknown_redox),
1864
1865 ("i386-apple-ios", i386_apple_ios),
1866 ("x86_64-apple-ios", x86_64_apple_ios),
1867 ("aarch64-apple-ios", aarch64_apple_ios),
1868 ("arm64e-apple-ios", arm64e_apple_ios),
1869 ("armv7s-apple-ios", armv7s_apple_ios),
1870 ("x86_64-apple-ios-macabi", x86_64_apple_ios_macabi),
1871 ("aarch64-apple-ios-macabi", aarch64_apple_ios_macabi),
1872 ("aarch64-apple-ios-sim", aarch64_apple_ios_sim),
1873
1874 ("aarch64-apple-tvos", aarch64_apple_tvos),
1875 ("aarch64-apple-tvos-sim", aarch64_apple_tvos_sim),
1876 ("arm64e-apple-tvos", arm64e_apple_tvos),
1877 ("x86_64-apple-tvos", x86_64_apple_tvos),
1878
1879 ("armv7k-apple-watchos", armv7k_apple_watchos),
1880 ("arm64_32-apple-watchos", arm64_32_apple_watchos),
1881 ("x86_64-apple-watchos-sim", x86_64_apple_watchos_sim),
1882 ("aarch64-apple-watchos", aarch64_apple_watchos),
1883 ("aarch64-apple-watchos-sim", aarch64_apple_watchos_sim),
1884
1885 ("aarch64-apple-visionos", aarch64_apple_visionos),
1886 ("aarch64-apple-visionos-sim", aarch64_apple_visionos_sim),
1887
1888 ("armebv7r-none-eabi", armebv7r_none_eabi),
1889 ("armebv7r-none-eabihf", armebv7r_none_eabihf),
1890 ("armv7r-none-eabi", armv7r_none_eabi),
1891 ("armv7r-none-eabihf", armv7r_none_eabihf),
1892 ("armv8r-none-eabihf", armv8r_none_eabihf),
1893
1894 ("armv7-rtems-eabihf", armv7_rtems_eabihf),
1895
1896 ("x86_64-pc-solaris", x86_64_pc_solaris),
1897 ("sparcv9-sun-solaris", sparcv9_sun_solaris),
1898
1899 ("x86_64-unknown-illumos", x86_64_unknown_illumos),
1900 ("aarch64-unknown-illumos", aarch64_unknown_illumos),
1901
1902 ("x86_64-pc-windows-gnu", x86_64_pc_windows_gnu),
1903 ("x86_64-uwp-windows-gnu", x86_64_uwp_windows_gnu),
1904 ("x86_64-win7-windows-gnu", x86_64_win7_windows_gnu),
1905 ("i686-pc-windows-gnu", i686_pc_windows_gnu),
1906 ("i686-uwp-windows-gnu", i686_uwp_windows_gnu),
1907 ("i686-win7-windows-gnu", i686_win7_windows_gnu),
1908
1909 ("aarch64-pc-windows-gnullvm", aarch64_pc_windows_gnullvm),
1910 ("i686-pc-windows-gnullvm", i686_pc_windows_gnullvm),
1911 ("x86_64-pc-windows-gnullvm", x86_64_pc_windows_gnullvm),
1912
1913 ("aarch64-pc-windows-msvc", aarch64_pc_windows_msvc),
1914 ("aarch64-uwp-windows-msvc", aarch64_uwp_windows_msvc),
1915 ("arm64ec-pc-windows-msvc", arm64ec_pc_windows_msvc),
1916 ("x86_64-pc-windows-msvc", x86_64_pc_windows_msvc),
1917 ("x86_64-uwp-windows-msvc", x86_64_uwp_windows_msvc),
1918 ("x86_64-win7-windows-msvc", x86_64_win7_windows_msvc),
1919 ("i686-pc-windows-msvc", i686_pc_windows_msvc),
1920 ("i686-uwp-windows-msvc", i686_uwp_windows_msvc),
1921 ("i686-win7-windows-msvc", i686_win7_windows_msvc),
1922 ("thumbv7a-pc-windows-msvc", thumbv7a_pc_windows_msvc),
1923 ("thumbv7a-uwp-windows-msvc", thumbv7a_uwp_windows_msvc),
1924
1925 ("wasm32-unknown-emscripten", wasm32_unknown_emscripten),
1926 ("wasm32-unknown-unknown", wasm32_unknown_unknown),
1927 ("wasm32v1-none", wasm32v1_none),
1928 ("wasm32-wasip1", wasm32_wasip1),
1929 ("wasm32-wasip2", wasm32_wasip2),
1930 ("wasm32-wasip1-threads", wasm32_wasip1_threads),
1931 ("wasm32-wali-linux-musl", wasm32_wali_linux_musl),
1932 ("wasm64-unknown-unknown", wasm64_unknown_unknown),
1933
1934 ("thumbv6m-none-eabi", thumbv6m_none_eabi),
1935 ("thumbv7m-none-eabi", thumbv7m_none_eabi),
1936 ("thumbv7em-none-eabi", thumbv7em_none_eabi),
1937 ("thumbv7em-none-eabihf", thumbv7em_none_eabihf),
1938 ("thumbv8m.base-none-eabi", thumbv8m_base_none_eabi),
1939 ("thumbv8m.main-none-eabi", thumbv8m_main_none_eabi),
1940 ("thumbv8m.main-none-eabihf", thumbv8m_main_none_eabihf),
1941
1942 ("armv7a-none-eabi", armv7a_none_eabi),
1943 ("armv7a-none-eabihf", armv7a_none_eabihf),
1944 ("armv7a-nuttx-eabi", armv7a_nuttx_eabi),
1945 ("armv7a-nuttx-eabihf", armv7a_nuttx_eabihf),
1946
1947 ("msp430-none-elf", msp430_none_elf),
1948
1949 ("aarch64-unknown-hermit", aarch64_unknown_hermit),
1950 ("riscv64gc-unknown-hermit", riscv64gc_unknown_hermit),
1951 ("x86_64-unknown-hermit", x86_64_unknown_hermit),
1952
1953 ("x86_64-unikraft-linux-musl", x86_64_unikraft_linux_musl),
1954
1955 ("armv7-unknown-trusty", armv7_unknown_trusty),
1956 ("aarch64-unknown-trusty", aarch64_unknown_trusty),
1957 ("x86_64-unknown-trusty", x86_64_unknown_trusty),
1958
1959 ("riscv32i-unknown-none-elf", riscv32i_unknown_none_elf),
1960 ("riscv32im-risc0-zkvm-elf", riscv32im_risc0_zkvm_elf),
1961 ("riscv32im-unknown-none-elf", riscv32im_unknown_none_elf),
1962 ("riscv32ima-unknown-none-elf", riscv32ima_unknown_none_elf),
1963 ("riscv32imc-unknown-none-elf", riscv32imc_unknown_none_elf),
1964 ("riscv32imc-esp-espidf", riscv32imc_esp_espidf),
1965 ("riscv32imac-esp-espidf", riscv32imac_esp_espidf),
1966 ("riscv32imafc-esp-espidf", riscv32imafc_esp_espidf),
1967
1968 ("riscv32e-unknown-none-elf", riscv32e_unknown_none_elf),
1969 ("riscv32em-unknown-none-elf", riscv32em_unknown_none_elf),
1970 ("riscv32emc-unknown-none-elf", riscv32emc_unknown_none_elf),
1971
1972 ("riscv32imac-unknown-none-elf", riscv32imac_unknown_none_elf),
1973 ("riscv32imafc-unknown-none-elf", riscv32imafc_unknown_none_elf),
1974 ("riscv32imac-unknown-xous-elf", riscv32imac_unknown_xous_elf),
1975 ("riscv32gc-unknown-linux-gnu", riscv32gc_unknown_linux_gnu),
1976 ("riscv32gc-unknown-linux-musl", riscv32gc_unknown_linux_musl),
1977 ("riscv64imac-unknown-none-elf", riscv64imac_unknown_none_elf),
1978 ("riscv64gc-unknown-none-elf", riscv64gc_unknown_none_elf),
1979 ("riscv64gc-unknown-linux-gnu", riscv64gc_unknown_linux_gnu),
1980 ("riscv64gc-unknown-linux-musl", riscv64gc_unknown_linux_musl),
1981
1982 ("sparc-unknown-none-elf", sparc_unknown_none_elf),
1983
1984 ("loongarch64-unknown-none", loongarch64_unknown_none),
1985 ("loongarch64-unknown-none-softfloat", loongarch64_unknown_none_softfloat),
1986
1987 ("aarch64-unknown-none", aarch64_unknown_none),
1988 ("aarch64-unknown-none-softfloat", aarch64_unknown_none_softfloat),
1989 ("aarch64-unknown-nuttx", aarch64_unknown_nuttx),
1990
1991 ("x86_64-fortanix-unknown-sgx", x86_64_fortanix_unknown_sgx),
1992
1993 ("x86_64-unknown-uefi", x86_64_unknown_uefi),
1994 ("i686-unknown-uefi", i686_unknown_uefi),
1995 ("aarch64-unknown-uefi", aarch64_unknown_uefi),
1996
1997 ("nvptx64-nvidia-cuda", nvptx64_nvidia_cuda),
1998
1999 ("amdgcn-amd-amdhsa", amdgcn_amd_amdhsa),
2000
2001 ("xtensa-esp32-none-elf", xtensa_esp32_none_elf),
2002 ("xtensa-esp32-espidf", xtensa_esp32_espidf),
2003 ("xtensa-esp32s2-none-elf", xtensa_esp32s2_none_elf),
2004 ("xtensa-esp32s2-espidf", xtensa_esp32s2_espidf),
2005 ("xtensa-esp32s3-none-elf", xtensa_esp32s3_none_elf),
2006 ("xtensa-esp32s3-espidf", xtensa_esp32s3_espidf),
2007
2008 ("i686-wrs-vxworks", i686_wrs_vxworks),
2009 ("x86_64-wrs-vxworks", x86_64_wrs_vxworks),
2010 ("armv7-wrs-vxworks-eabihf", armv7_wrs_vxworks_eabihf),
2011 ("aarch64-wrs-vxworks", aarch64_wrs_vxworks),
2012 ("powerpc-wrs-vxworks", powerpc_wrs_vxworks),
2013 ("powerpc-wrs-vxworks-spe", powerpc_wrs_vxworks_spe),
2014 ("powerpc64-wrs-vxworks", powerpc64_wrs_vxworks),
2015 ("riscv32-wrs-vxworks", riscv32_wrs_vxworks),
2016 ("riscv64-wrs-vxworks", riscv64_wrs_vxworks),
2017
2018 ("aarch64-kmc-solid_asp3", aarch64_kmc_solid_asp3),
2019 ("armv7a-kmc-solid_asp3-eabi", armv7a_kmc_solid_asp3_eabi),
2020 ("armv7a-kmc-solid_asp3-eabihf", armv7a_kmc_solid_asp3_eabihf),
2021
2022 ("mipsel-sony-psp", mipsel_sony_psp),
2023 ("mipsel-sony-psx", mipsel_sony_psx),
2024 ("mipsel-unknown-none", mipsel_unknown_none),
2025 ("mips-mti-none-elf", mips_mti_none_elf),
2026 ("mipsel-mti-none-elf", mipsel_mti_none_elf),
2027 ("thumbv4t-none-eabi", thumbv4t_none_eabi),
2028 ("armv4t-none-eabi", armv4t_none_eabi),
2029 ("thumbv5te-none-eabi", thumbv5te_none_eabi),
2030 ("armv5te-none-eabi", armv5te_none_eabi),
2031
2032 ("aarch64_be-unknown-linux-gnu", aarch64_be_unknown_linux_gnu),
2033 ("aarch64-unknown-linux-gnu_ilp32", aarch64_unknown_linux_gnu_ilp32),
2034 ("aarch64_be-unknown-linux-gnu_ilp32", aarch64_be_unknown_linux_gnu_ilp32),
2035
2036 ("bpfeb-unknown-none", bpfeb_unknown_none),
2037 ("bpfel-unknown-none", bpfel_unknown_none),
2038
2039 ("armv6k-nintendo-3ds", armv6k_nintendo_3ds),
2040
2041 ("aarch64-nintendo-switch-freestanding", aarch64_nintendo_switch_freestanding),
2042
2043 ("armv7-sony-vita-newlibeabihf", armv7_sony_vita_newlibeabihf),
2044
2045 ("armv7-unknown-linux-uclibceabi", armv7_unknown_linux_uclibceabi),
2046 ("armv7-unknown-linux-uclibceabihf", armv7_unknown_linux_uclibceabihf),
2047
2048 ("x86_64-unknown-none", x86_64_unknown_none),
2049
2050 ("aarch64-unknown-teeos", aarch64_unknown_teeos),
2051
2052 ("mips64-openwrt-linux-musl", mips64_openwrt_linux_musl),
2053
2054 ("aarch64-unknown-nto-qnx700", aarch64_unknown_nto_qnx700),
2055 ("aarch64-unknown-nto-qnx710", aarch64_unknown_nto_qnx710),
2056 ("aarch64-unknown-nto-qnx710_iosock", aarch64_unknown_nto_qnx710_iosock),
2057 ("aarch64-unknown-nto-qnx800", aarch64_unknown_nto_qnx800),
2058 ("x86_64-pc-nto-qnx710", x86_64_pc_nto_qnx710),
2059 ("x86_64-pc-nto-qnx710_iosock", x86_64_pc_nto_qnx710_iosock),
2060 ("x86_64-pc-nto-qnx800", x86_64_pc_nto_qnx800),
2061 ("i686-pc-nto-qnx700", i686_pc_nto_qnx700),
2062
2063 ("aarch64-unknown-linux-ohos", aarch64_unknown_linux_ohos),
2064 ("armv7-unknown-linux-ohos", armv7_unknown_linux_ohos),
2065 ("loongarch64-unknown-linux-ohos", loongarch64_unknown_linux_ohos),
2066 ("x86_64-unknown-linux-ohos", x86_64_unknown_linux_ohos),
2067
2068 ("x86_64-unknown-linux-none", x86_64_unknown_linux_none),
2069
2070 ("thumbv6m-nuttx-eabi", thumbv6m_nuttx_eabi),
2071 ("thumbv7a-nuttx-eabi", thumbv7a_nuttx_eabi),
2072 ("thumbv7a-nuttx-eabihf", thumbv7a_nuttx_eabihf),
2073 ("thumbv7m-nuttx-eabi", thumbv7m_nuttx_eabi),
2074 ("thumbv7em-nuttx-eabi", thumbv7em_nuttx_eabi),
2075 ("thumbv7em-nuttx-eabihf", thumbv7em_nuttx_eabihf),
2076 ("thumbv8m.base-nuttx-eabi", thumbv8m_base_nuttx_eabi),
2077 ("thumbv8m.main-nuttx-eabi", thumbv8m_main_nuttx_eabi),
2078 ("thumbv8m.main-nuttx-eabihf", thumbv8m_main_nuttx_eabihf),
2079 ("riscv32imc-unknown-nuttx-elf", riscv32imc_unknown_nuttx_elf),
2080 ("riscv32imac-unknown-nuttx-elf", riscv32imac_unknown_nuttx_elf),
2081 ("riscv32imafc-unknown-nuttx-elf", riscv32imafc_unknown_nuttx_elf),
2082 ("riscv64imac-unknown-nuttx-elf", riscv64imac_unknown_nuttx_elf),
2083 ("riscv64gc-unknown-nuttx-elf", riscv64gc_unknown_nuttx_elf),
2084 ("x86_64-lynx-lynxos178", x86_64_lynx_lynxos178),
2085
2086 ("x86_64-pc-cygwin", x86_64_pc_cygwin),
2087}
2088
2089macro_rules! cvs {
2091 () => {
2092 ::std::borrow::Cow::Borrowed(&[])
2093 };
2094 ($($x:expr),+ $(,)?) => {
2095 ::std::borrow::Cow::Borrowed(&[
2096 $(
2097 ::std::borrow::Cow::Borrowed($x),
2098 )*
2099 ])
2100 };
2101}
2102
2103pub(crate) use cvs;
2104
2105#[derive(Debug, PartialEq)]
2109pub struct TargetWarnings {
2110 unused_fields: Vec<String>,
2111 incorrect_type: Vec<String>,
2112}
2113
2114impl TargetWarnings {
2115 pub fn empty() -> Self {
2116 Self { unused_fields: Vec::new(), incorrect_type: Vec::new() }
2117 }
2118
2119 pub fn warning_messages(&self) -> Vec<String> {
2120 let mut warnings = vec![];
2121 if !self.unused_fields.is_empty() {
2122 warnings.push(format!(
2123 "target json file contains unused fields: {}",
2124 self.unused_fields.join(", ")
2125 ));
2126 }
2127 if !self.incorrect_type.is_empty() {
2128 warnings.push(format!(
2129 "target json file contains fields whose value doesn't have the correct json type: {}",
2130 self.incorrect_type.join(", ")
2131 ));
2132 }
2133 warnings
2134 }
2135}
2136
2137#[derive(Copy, Clone, Debug, PartialEq)]
2140enum TargetKind {
2141 Json,
2142 Builtin,
2143}
2144
2145#[derive(PartialEq, Clone, Debug)]
2149pub struct Target {
2150 pub llvm_target: StaticCow<str>,
2157 pub metadata: TargetMetadata,
2160 pub pointer_width: u32,
2162 pub arch: StaticCow<str>,
2165 pub data_layout: StaticCow<str>,
2167 pub options: TargetOptions,
2169}
2170
2171#[derive(Default, PartialEq, Clone, Debug)]
2175pub struct TargetMetadata {
2176 pub description: Option<StaticCow<str>>,
2179 pub tier: Option<u64>,
2181 pub host_tools: Option<bool>,
2183 pub std: Option<bool>,
2186}
2187
2188impl Target {
2189 pub fn parse_data_layout(&self) -> Result<TargetDataLayout, TargetDataLayoutErrors<'_>> {
2190 let mut dl = TargetDataLayout::parse_from_llvm_datalayout_string(&self.data_layout)?;
2191
2192 if dl.endian != self.endian {
2194 return Err(TargetDataLayoutErrors::InconsistentTargetArchitecture {
2195 dl: dl.endian.as_str(),
2196 target: self.endian.as_str(),
2197 });
2198 }
2199
2200 let target_pointer_width: u64 = self.pointer_width.into();
2201 if dl.pointer_size.bits() != target_pointer_width {
2202 return Err(TargetDataLayoutErrors::InconsistentTargetPointerWidth {
2203 pointer_size: dl.pointer_size.bits(),
2204 target: self.pointer_width,
2205 });
2206 }
2207
2208 dl.c_enum_min_size = self
2209 .c_enum_min_bits
2210 .map_or_else(
2211 || {
2212 self.c_int_width
2213 .parse()
2214 .map_err(|_| String::from("failed to parse c_int_width"))
2215 },
2216 Ok,
2217 )
2218 .and_then(|i| Integer::from_size(Size::from_bits(i)))
2219 .map_err(|err| TargetDataLayoutErrors::InvalidBitsSize { err })?;
2220
2221 Ok(dl)
2222 }
2223}
2224
2225pub trait HasTargetSpec {
2226 fn target_spec(&self) -> &Target;
2227}
2228
2229impl HasTargetSpec for Target {
2230 #[inline]
2231 fn target_spec(&self) -> &Target {
2232 self
2233 }
2234}
2235
2236#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
2238pub enum WasmCAbi {
2239 Spec,
2241 Legacy {
2243 with_lint: bool,
2245 },
2246}
2247
2248pub trait HasWasmCAbiOpt {
2249 fn wasm_c_abi_opt(&self) -> WasmCAbi;
2250}
2251
2252#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
2254pub struct X86Abi {
2255 pub regparm: Option<u32>,
2258 pub reg_struct_return: bool,
2260}
2261
2262pub trait HasX86AbiOpt {
2263 fn x86_abi_opt(&self) -> X86Abi;
2264}
2265
2266type StaticCow<T> = Cow<'static, T>;
2267
2268#[derive(PartialEq, Clone, Debug)]
2277pub struct TargetOptions {
2278 pub endian: Endian,
2280 pub c_int_width: StaticCow<str>,
2282 pub os: StaticCow<str>,
2287 pub env: StaticCow<str>,
2289 pub abi: StaticCow<str>,
2294 pub vendor: StaticCow<str>,
2296
2297 pub linker: Option<StaticCow<str>>,
2299 pub linker_flavor: LinkerFlavor,
2302 linker_flavor_json: LinkerFlavorCli,
2303 lld_flavor_json: LldFlavor,
2304 linker_is_gnu_json: bool,
2305
2306 pub pre_link_objects: CrtObjects,
2308 pub post_link_objects: CrtObjects,
2309 pub pre_link_objects_self_contained: CrtObjects,
2311 pub post_link_objects_self_contained: CrtObjects,
2312 pub link_self_contained: LinkSelfContainedDefault,
2315
2316 pub pre_link_args: LinkArgs,
2318 pre_link_args_json: LinkArgsCli,
2319 pub late_link_args: LinkArgs,
2323 late_link_args_json: LinkArgsCli,
2324 pub late_link_args_dynamic: LinkArgs,
2327 late_link_args_dynamic_json: LinkArgsCli,
2328 pub late_link_args_static: LinkArgs,
2331 late_link_args_static_json: LinkArgsCli,
2332 pub post_link_args: LinkArgs,
2335 post_link_args_json: LinkArgsCli,
2336
2337 pub link_script: Option<StaticCow<str>>,
2341 pub link_env: StaticCow<[(StaticCow<str>, StaticCow<str>)]>,
2343 pub link_env_remove: StaticCow<[StaticCow<str>]>,
2345
2346 pub asm_args: StaticCow<[StaticCow<str>]>,
2348
2349 pub cpu: StaticCow<str>,
2352 pub need_explicit_cpu: bool,
2355 pub features: StaticCow<str>,
2364 pub direct_access_external_data: Option<bool>,
2366 pub dynamic_linking: bool,
2368 pub dll_tls_export: bool,
2370 pub only_cdylib: bool,
2372 pub executables: bool,
2374 pub relocation_model: RelocModel,
2377 pub code_model: Option<CodeModel>,
2380 pub tls_model: TlsModel,
2383 pub disable_redzone: bool,
2385 pub frame_pointer: FramePointer,
2387 pub function_sections: bool,
2389 pub dll_prefix: StaticCow<str>,
2391 pub dll_suffix: StaticCow<str>,
2393 pub exe_suffix: StaticCow<str>,
2395 pub staticlib_prefix: StaticCow<str>,
2397 pub staticlib_suffix: StaticCow<str>,
2399 pub families: StaticCow<[StaticCow<str>]>,
2405 pub abi_return_struct_as_int: bool,
2407 pub is_like_aix: bool,
2410 pub is_like_darwin: bool,
2415 pub is_like_solaris: bool,
2419 pub is_like_windows: bool,
2427 pub is_like_msvc: bool,
2437 pub is_like_wasm: bool,
2439 pub is_like_android: bool,
2441 pub binary_format: BinaryFormat,
2443 pub default_dwarf_version: u32,
2446 pub allows_weak_linkage: bool,
2453 pub has_rpath: bool,
2455 pub no_default_libraries: bool,
2458 pub position_independent_executables: bool,
2464 pub static_position_independent_executables: bool,
2466 pub plt_by_default: bool,
2469 pub relro_level: RelroLevel,
2473 pub archive_format: StaticCow<str>,
2478 pub allow_asm: bool,
2480 pub main_needs_argc_argv: bool,
2483
2484 pub has_thread_local: bool,
2486 pub obj_is_bitcode: bool,
2490 pub bitcode_llvm_cmdline: StaticCow<str>,
2492
2493 pub min_atomic_width: Option<u64>,
2495
2496 pub max_atomic_width: Option<u64>,
2498
2499 pub atomic_cas: bool,
2501
2502 pub panic_strategy: PanicStrategy,
2504
2505 pub crt_static_allows_dylibs: bool,
2507 pub crt_static_default: bool,
2509 pub crt_static_respected: bool,
2511
2512 pub stack_probes: StackProbeType,
2514
2515 pub min_global_align: Option<u64>,
2517
2518 pub default_codegen_units: Option<u64>,
2520
2521 pub default_codegen_backend: Option<StaticCow<str>>,
2531
2532 pub trap_unreachable: bool,
2535
2536 pub requires_lto: bool,
2539
2540 pub singlethread: bool,
2542
2543 pub no_builtins: bool,
2546
2547 pub default_visibility: Option<SymbolVisibility>,
2553
2554 pub emit_debug_gdb_scripts: bool,
2556
2557 pub requires_uwtable: bool,
2561
2562 pub default_uwtable: bool,
2565
2566 pub simd_types_indirect: bool,
2571
2572 pub limit_rdylib_exports: bool,
2574
2575 pub override_export_symbols: Option<StaticCow<[StaticCow<str>]>>,
2578
2579 pub merge_functions: MergeFunctions,
2586
2587 pub mcount: StaticCow<str>,
2589
2590 pub llvm_mcount_intrinsic: Option<StaticCow<str>>,
2592
2593 pub llvm_abiname: StaticCow<str>,
2596
2597 pub llvm_floatabi: Option<FloatAbi>,
2604
2605 pub rustc_abi: Option<RustcAbi>,
2610
2611 pub relax_elf_relocations: bool,
2613
2614 pub llvm_args: StaticCow<[StaticCow<str>]>,
2616
2617 pub use_ctors_section: bool,
2620
2621 pub eh_frame_header: bool,
2625
2626 pub has_thumb_interworking: bool,
2629
2630 pub debuginfo_kind: DebuginfoKind,
2632 pub split_debuginfo: SplitDebuginfo,
2635 pub supported_split_debuginfo: StaticCow<[SplitDebuginfo]>,
2637
2638 pub supported_sanitizers: SanitizerSet,
2644
2645 pub c_enum_min_bits: Option<u64>,
2647
2648 pub generate_arange_section: bool,
2650
2651 pub supports_stack_protector: bool,
2654
2655 pub entry_name: StaticCow<str>,
2658
2659 pub entry_abi: CanonAbi,
2662
2663 pub supports_xray: bool,
2665
2666 small_data_threshold_support: SmallDataThresholdSupport,
2668}
2669
2670fn add_link_args_iter(
2673 link_args: &mut LinkArgs,
2674 flavor: LinkerFlavor,
2675 args: impl Iterator<Item = StaticCow<str>> + Clone,
2676) {
2677 let mut insert = |flavor| link_args.entry(flavor).or_default().extend(args.clone());
2678 insert(flavor);
2679 match flavor {
2680 LinkerFlavor::Gnu(cc, lld) => {
2681 assert_eq!(lld, Lld::No);
2682 insert(LinkerFlavor::Gnu(cc, Lld::Yes));
2683 }
2684 LinkerFlavor::Darwin(cc, lld) => {
2685 assert_eq!(lld, Lld::No);
2686 insert(LinkerFlavor::Darwin(cc, Lld::Yes));
2687 }
2688 LinkerFlavor::Msvc(lld) => {
2689 assert_eq!(lld, Lld::No);
2690 insert(LinkerFlavor::Msvc(Lld::Yes));
2691 }
2692 LinkerFlavor::WasmLld(..)
2693 | LinkerFlavor::Unix(..)
2694 | LinkerFlavor::EmCc
2695 | LinkerFlavor::Bpf
2696 | LinkerFlavor::Llbc
2697 | LinkerFlavor::Ptx => {}
2698 }
2699}
2700
2701fn add_link_args(link_args: &mut LinkArgs, flavor: LinkerFlavor, args: &[&'static str]) {
2702 add_link_args_iter(link_args, flavor, args.iter().copied().map(Cow::Borrowed))
2703}
2704
2705impl TargetOptions {
2706 pub fn supports_comdat(&self) -> bool {
2707 !self.is_like_aix && !self.is_like_darwin
2709 }
2710}
2711
2712impl TargetOptions {
2713 fn link_args(flavor: LinkerFlavor, args: &[&'static str]) -> LinkArgs {
2714 let mut link_args = LinkArgs::new();
2715 add_link_args(&mut link_args, flavor, args);
2716 link_args
2717 }
2718
2719 fn add_pre_link_args(&mut self, flavor: LinkerFlavor, args: &[&'static str]) {
2720 add_link_args(&mut self.pre_link_args, flavor, args);
2721 }
2722
2723 fn update_from_cli(&mut self) {
2724 self.linker_flavor = LinkerFlavor::from_cli_json(
2725 self.linker_flavor_json,
2726 self.lld_flavor_json,
2727 self.linker_is_gnu_json,
2728 );
2729 for (args, args_json) in [
2730 (&mut self.pre_link_args, &self.pre_link_args_json),
2731 (&mut self.late_link_args, &self.late_link_args_json),
2732 (&mut self.late_link_args_dynamic, &self.late_link_args_dynamic_json),
2733 (&mut self.late_link_args_static, &self.late_link_args_static_json),
2734 (&mut self.post_link_args, &self.post_link_args_json),
2735 ] {
2736 args.clear();
2737 for (flavor, args_json) in args_json {
2738 let linker_flavor = self.linker_flavor.with_cli_hints(*flavor);
2739 let linker_flavor = match linker_flavor {
2741 LinkerFlavor::Gnu(cc, _) => LinkerFlavor::Gnu(cc, Lld::No),
2742 LinkerFlavor::Darwin(cc, _) => LinkerFlavor::Darwin(cc, Lld::No),
2743 LinkerFlavor::Msvc(_) => LinkerFlavor::Msvc(Lld::No),
2744 _ => linker_flavor,
2745 };
2746 if !args.contains_key(&linker_flavor) {
2747 add_link_args_iter(args, linker_flavor, args_json.iter().cloned());
2748 }
2749 }
2750 }
2751 }
2752
2753 fn update_to_cli(&mut self) {
2754 self.linker_flavor_json = self.linker_flavor.to_cli_counterpart();
2755 self.lld_flavor_json = self.linker_flavor.lld_flavor();
2756 self.linker_is_gnu_json = self.linker_flavor.is_gnu();
2757 for (args, args_json) in [
2758 (&self.pre_link_args, &mut self.pre_link_args_json),
2759 (&self.late_link_args, &mut self.late_link_args_json),
2760 (&self.late_link_args_dynamic, &mut self.late_link_args_dynamic_json),
2761 (&self.late_link_args_static, &mut self.late_link_args_static_json),
2762 (&self.post_link_args, &mut self.post_link_args_json),
2763 ] {
2764 *args_json = args
2765 .iter()
2766 .map(|(flavor, args)| (flavor.to_cli_counterpart(), args.clone()))
2767 .collect();
2768 }
2769 }
2770}
2771
2772impl Default for TargetOptions {
2773 fn default() -> TargetOptions {
2776 TargetOptions {
2777 endian: Endian::Little,
2778 c_int_width: "32".into(),
2779 os: "none".into(),
2780 env: "".into(),
2781 abi: "".into(),
2782 vendor: "unknown".into(),
2783 linker: option_env!("CFG_DEFAULT_LINKER").map(|s| s.into()),
2784 linker_flavor: LinkerFlavor::Gnu(Cc::Yes, Lld::No),
2785 linker_flavor_json: LinkerFlavorCli::Gcc,
2786 lld_flavor_json: LldFlavor::Ld,
2787 linker_is_gnu_json: true,
2788 link_script: None,
2789 asm_args: cvs![],
2790 cpu: "generic".into(),
2791 need_explicit_cpu: false,
2792 features: "".into(),
2793 direct_access_external_data: None,
2794 dynamic_linking: false,
2795 dll_tls_export: true,
2796 only_cdylib: false,
2797 executables: true,
2798 relocation_model: RelocModel::Pic,
2799 code_model: None,
2800 tls_model: TlsModel::GeneralDynamic,
2801 disable_redzone: false,
2802 frame_pointer: FramePointer::MayOmit,
2803 function_sections: true,
2804 dll_prefix: "lib".into(),
2805 dll_suffix: ".so".into(),
2806 exe_suffix: "".into(),
2807 staticlib_prefix: "lib".into(),
2808 staticlib_suffix: ".a".into(),
2809 families: cvs![],
2810 abi_return_struct_as_int: false,
2811 is_like_aix: false,
2812 is_like_darwin: false,
2813 is_like_solaris: false,
2814 is_like_windows: false,
2815 is_like_msvc: false,
2816 is_like_wasm: false,
2817 is_like_android: false,
2818 binary_format: BinaryFormat::Elf,
2819 default_dwarf_version: 4,
2820 allows_weak_linkage: true,
2821 has_rpath: false,
2822 no_default_libraries: true,
2823 position_independent_executables: false,
2824 static_position_independent_executables: false,
2825 plt_by_default: true,
2826 relro_level: RelroLevel::None,
2827 pre_link_objects: Default::default(),
2828 post_link_objects: Default::default(),
2829 pre_link_objects_self_contained: Default::default(),
2830 post_link_objects_self_contained: Default::default(),
2831 link_self_contained: LinkSelfContainedDefault::False,
2832 pre_link_args: LinkArgs::new(),
2833 pre_link_args_json: LinkArgsCli::new(),
2834 late_link_args: LinkArgs::new(),
2835 late_link_args_json: LinkArgsCli::new(),
2836 late_link_args_dynamic: LinkArgs::new(),
2837 late_link_args_dynamic_json: LinkArgsCli::new(),
2838 late_link_args_static: LinkArgs::new(),
2839 late_link_args_static_json: LinkArgsCli::new(),
2840 post_link_args: LinkArgs::new(),
2841 post_link_args_json: LinkArgsCli::new(),
2842 link_env: cvs![],
2843 link_env_remove: cvs![],
2844 archive_format: "gnu".into(),
2845 main_needs_argc_argv: true,
2846 allow_asm: true,
2847 has_thread_local: false,
2848 obj_is_bitcode: false,
2849 bitcode_llvm_cmdline: "".into(),
2850 min_atomic_width: None,
2851 max_atomic_width: None,
2852 atomic_cas: true,
2853 panic_strategy: PanicStrategy::Unwind,
2854 crt_static_allows_dylibs: false,
2855 crt_static_default: false,
2856 crt_static_respected: false,
2857 stack_probes: StackProbeType::None,
2858 min_global_align: None,
2859 default_codegen_units: None,
2860 default_codegen_backend: None,
2861 trap_unreachable: true,
2862 requires_lto: false,
2863 singlethread: false,
2864 no_builtins: false,
2865 default_visibility: None,
2866 emit_debug_gdb_scripts: true,
2867 requires_uwtable: false,
2868 default_uwtable: false,
2869 simd_types_indirect: true,
2870 limit_rdylib_exports: true,
2871 override_export_symbols: None,
2872 merge_functions: MergeFunctions::Aliases,
2873 mcount: "mcount".into(),
2874 llvm_mcount_intrinsic: None,
2875 llvm_abiname: "".into(),
2876 llvm_floatabi: None,
2877 rustc_abi: None,
2878 relax_elf_relocations: false,
2879 llvm_args: cvs![],
2880 use_ctors_section: false,
2881 eh_frame_header: true,
2882 has_thumb_interworking: false,
2883 debuginfo_kind: Default::default(),
2884 split_debuginfo: Default::default(),
2885 supported_split_debuginfo: Cow::Borrowed(&[SplitDebuginfo::Off]),
2887 supported_sanitizers: SanitizerSet::empty(),
2888 c_enum_min_bits: None,
2889 generate_arange_section: true,
2890 supports_stack_protector: true,
2891 entry_name: "main".into(),
2892 entry_abi: CanonAbi::C,
2893 supports_xray: false,
2894 small_data_threshold_support: SmallDataThresholdSupport::DefaultForArch,
2895 }
2896 }
2897}
2898
2899impl Deref for Target {
2903 type Target = TargetOptions;
2904
2905 #[inline]
2906 fn deref(&self) -> &Self::Target {
2907 &self.options
2908 }
2909}
2910impl DerefMut for Target {
2911 #[inline]
2912 fn deref_mut(&mut self) -> &mut Self::Target {
2913 &mut self.options
2914 }
2915}
2916
2917impl Target {
2918 pub fn is_abi_supported(&self, abi: ExternAbi) -> bool {
2919 let abi_map = AbiMap::from_target(self);
2920 abi_map.canonize_abi(abi, false).is_mapped()
2921 }
2922
2923 pub fn min_atomic_width(&self) -> u64 {
2926 self.min_atomic_width.unwrap_or(8)
2927 }
2928
2929 pub fn max_atomic_width(&self) -> u64 {
2932 self.max_atomic_width.unwrap_or_else(|| self.pointer_width.into())
2933 }
2934
2935 fn check_consistency(&self, kind: TargetKind) -> Result<(), String> {
2938 macro_rules! check {
2939 ($b:expr, $($msg:tt)*) => {
2940 if !$b {
2941 return Err(format!($($msg)*));
2942 }
2943 }
2944 }
2945 macro_rules! check_eq {
2946 ($left:expr, $right:expr, $($msg:tt)*) => {
2947 if ($left) != ($right) {
2948 return Err(format!($($msg)*));
2949 }
2950 }
2951 }
2952 macro_rules! check_ne {
2953 ($left:expr, $right:expr, $($msg:tt)*) => {
2954 if ($left) == ($right) {
2955 return Err(format!($($msg)*));
2956 }
2957 }
2958 }
2959 macro_rules! check_matches {
2960 ($left:expr, $right:pat, $($msg:tt)*) => {
2961 if !matches!($left, $right) {
2962 return Err(format!($($msg)*));
2963 }
2964 }
2965 }
2966
2967 check_eq!(
2968 self.is_like_darwin,
2969 self.vendor == "apple",
2970 "`is_like_darwin` must be set if and only if `vendor` is `apple`"
2971 );
2972 check_eq!(
2973 self.is_like_solaris,
2974 self.os == "solaris" || self.os == "illumos",
2975 "`is_like_solaris` must be set if and only if `os` is `solaris` or `illumos`"
2976 );
2977 check_eq!(
2978 self.is_like_windows,
2979 self.os == "windows" || self.os == "uefi" || self.os == "cygwin",
2980 "`is_like_windows` must be set if and only if `os` is `windows`, `uefi` or `cygwin`"
2981 );
2982 check_eq!(
2983 self.is_like_wasm,
2984 self.arch == "wasm32" || self.arch == "wasm64",
2985 "`is_like_wasm` must be set if and only if `arch` is `wasm32` or `wasm64`"
2986 );
2987 if self.is_like_msvc {
2988 check!(self.is_like_windows, "if `is_like_msvc` is set, `is_like_windows` must be set");
2989 }
2990 if self.os == "emscripten" {
2991 check!(self.is_like_wasm, "the `emcscripten` os only makes sense on wasm-like targets");
2992 }
2993
2994 check_eq!(
2996 self.is_like_darwin,
2997 matches!(self.linker_flavor, LinkerFlavor::Darwin(..)),
2998 "`linker_flavor` must be `darwin` if and only if `is_like_darwin` is set"
2999 );
3000 check_eq!(
3001 self.is_like_msvc,
3002 matches!(self.linker_flavor, LinkerFlavor::Msvc(..)),
3003 "`linker_flavor` must be `msvc` if and only if `is_like_msvc` is set"
3004 );
3005 check_eq!(
3006 self.is_like_wasm && self.os != "emscripten",
3007 matches!(self.linker_flavor, LinkerFlavor::WasmLld(..)),
3008 "`linker_flavor` must be `wasm-lld` if and only if `is_like_wasm` is set and the `os` is not `emscripten`",
3009 );
3010 check_eq!(
3011 self.os == "emscripten",
3012 matches!(self.linker_flavor, LinkerFlavor::EmCc),
3013 "`linker_flavor` must be `em-cc` if and only if `os` is `emscripten`"
3014 );
3015 check_eq!(
3016 self.arch == "bpf",
3017 matches!(self.linker_flavor, LinkerFlavor::Bpf),
3018 "`linker_flavor` must be `bpf` if and only if `arch` is `bpf`"
3019 );
3020 check_eq!(
3021 self.arch == "nvptx64",
3022 matches!(self.linker_flavor, LinkerFlavor::Ptx),
3023 "`linker_flavor` must be `ptc` if and only if `arch` is `nvptx64`"
3024 );
3025
3026 for args in [
3027 &self.pre_link_args,
3028 &self.late_link_args,
3029 &self.late_link_args_dynamic,
3030 &self.late_link_args_static,
3031 &self.post_link_args,
3032 ] {
3033 for (&flavor, flavor_args) in args {
3034 check!(
3035 !flavor_args.is_empty() || self.arch == "avr",
3036 "linker flavor args must not be empty"
3037 );
3038 match self.linker_flavor {
3040 LinkerFlavor::Gnu(..) => {
3041 check_matches!(
3042 flavor,
3043 LinkerFlavor::Gnu(..),
3044 "mixing GNU and non-GNU linker flavors"
3045 );
3046 }
3047 LinkerFlavor::Darwin(..) => {
3048 check_matches!(
3049 flavor,
3050 LinkerFlavor::Darwin(..),
3051 "mixing Darwin and non-Darwin linker flavors"
3052 )
3053 }
3054 LinkerFlavor::WasmLld(..) => {
3055 check_matches!(
3056 flavor,
3057 LinkerFlavor::WasmLld(..),
3058 "mixing wasm and non-wasm linker flavors"
3059 )
3060 }
3061 LinkerFlavor::Unix(..) => {
3062 check_matches!(
3063 flavor,
3064 LinkerFlavor::Unix(..),
3065 "mixing unix and non-unix linker flavors"
3066 );
3067 }
3068 LinkerFlavor::Msvc(..) => {
3069 check_matches!(
3070 flavor,
3071 LinkerFlavor::Msvc(..),
3072 "mixing MSVC and non-MSVC linker flavors"
3073 );
3074 }
3075 LinkerFlavor::EmCc
3076 | LinkerFlavor::Bpf
3077 | LinkerFlavor::Ptx
3078 | LinkerFlavor::Llbc => {
3079 check_eq!(flavor, self.linker_flavor, "mixing different linker flavors")
3080 }
3081 }
3082
3083 let check_noncc = |noncc_flavor| -> Result<(), String> {
3085 if let Some(noncc_args) = args.get(&noncc_flavor) {
3086 for arg in flavor_args {
3087 if let Some(suffix) = arg.strip_prefix("-Wl,") {
3088 check!(
3089 noncc_args.iter().any(|a| a == suffix),
3090 " link args for cc and non-cc versions of flavors are not consistent"
3091 );
3092 }
3093 }
3094 }
3095 Ok(())
3096 };
3097
3098 match self.linker_flavor {
3099 LinkerFlavor::Gnu(Cc::Yes, lld) => check_noncc(LinkerFlavor::Gnu(Cc::No, lld))?,
3100 LinkerFlavor::WasmLld(Cc::Yes) => check_noncc(LinkerFlavor::WasmLld(Cc::No))?,
3101 LinkerFlavor::Unix(Cc::Yes) => check_noncc(LinkerFlavor::Unix(Cc::No))?,
3102 _ => {}
3103 }
3104 }
3105
3106 for cc in [Cc::No, Cc::Yes] {
3108 check_eq!(
3109 args.get(&LinkerFlavor::Gnu(cc, Lld::No)),
3110 args.get(&LinkerFlavor::Gnu(cc, Lld::Yes)),
3111 "link args for lld and non-lld versions of flavors are not consistent",
3112 );
3113 check_eq!(
3114 args.get(&LinkerFlavor::Darwin(cc, Lld::No)),
3115 args.get(&LinkerFlavor::Darwin(cc, Lld::Yes)),
3116 "link args for lld and non-lld versions of flavors are not consistent",
3117 );
3118 }
3119 check_eq!(
3120 args.get(&LinkerFlavor::Msvc(Lld::No)),
3121 args.get(&LinkerFlavor::Msvc(Lld::Yes)),
3122 "link args for lld and non-lld versions of flavors are not consistent",
3123 );
3124 }
3125
3126 if self.link_self_contained.is_disabled() {
3127 check!(
3128 self.pre_link_objects_self_contained.is_empty()
3129 && self.post_link_objects_self_contained.is_empty(),
3130 "if `link_self_contained` is disabled, then `pre_link_objects_self_contained` and `post_link_objects_self_contained` must be empty",
3131 );
3132 }
3133
3134 check_ne!(self.vendor, "", "`vendor` cannot be empty");
3138 check_ne!(self.os, "", "`os` cannot be empty");
3139 if !self.can_use_os_unknown() {
3140 check_ne!(
3142 self.os,
3143 "unknown",
3144 "`unknown` os can only be used on particular targets; use `none` for bare-metal targets"
3145 );
3146 }
3147
3148 if kind == TargetKind::Builtin {
3154 if self.os == "none"
3158 && (self.arch != "bpf"
3159 && self.arch != "hexagon"
3160 && self.arch != "wasm32"
3161 && self.arch != "wasm64")
3162 {
3163 check!(
3164 !self.dynamic_linking,
3165 "dynamic linking is not supported on this OS/architecture"
3166 );
3167 }
3168 if self.only_cdylib
3169 || self.crt_static_allows_dylibs
3170 || !self.late_link_args_dynamic.is_empty()
3171 {
3172 check!(
3173 self.dynamic_linking,
3174 "dynamic linking must be allowed when `only_cdylib` or `crt_static_allows_dylibs` or `late_link_args_dynamic` are set"
3175 );
3176 }
3177 if self.dynamic_linking && !self.is_like_wasm {
3179 check_eq!(
3180 self.relocation_model,
3181 RelocModel::Pic,
3182 "targets that support dynamic linking must use the `pic` relocation model"
3183 );
3184 }
3185 if self.position_independent_executables {
3186 check_eq!(
3187 self.relocation_model,
3188 RelocModel::Pic,
3189 "targets that support position-independent executables must use the `pic` relocation model"
3190 );
3191 }
3192 if self.relocation_model == RelocModel::Pic && (self.os != "uefi") {
3194 check!(
3195 self.dynamic_linking || self.position_independent_executables,
3196 "when the relocation model is `pic`, the target must support dynamic linking or use position-independent executables. \
3197 Set the relocation model to `static` to avoid this requirement"
3198 );
3199 }
3200 if self.static_position_independent_executables {
3201 check!(
3202 self.position_independent_executables,
3203 "if `static_position_independent_executables` is set, then `position_independent_executables` must be set"
3204 );
3205 }
3206 if self.position_independent_executables {
3207 check!(
3208 self.executables,
3209 "if `position_independent_executables` is set then `executables` must be set"
3210 );
3211 }
3212 }
3213
3214 if self.crt_static_default || self.crt_static_allows_dylibs {
3216 check!(
3217 self.crt_static_respected,
3218 "static CRT can be enabled but `crt_static_respected` is not set"
3219 );
3220 }
3221
3222 match &*self.arch {
3225 "riscv32" => {
3226 check_matches!(
3227 &*self.llvm_abiname,
3228 "ilp32" | "ilp32f" | "ilp32d" | "ilp32e",
3229 "invalid RISC-V ABI name: {}",
3230 self.llvm_abiname,
3231 );
3232 }
3233 "riscv64" => {
3234 check_matches!(
3236 &*self.llvm_abiname,
3237 "lp64" | "lp64f" | "lp64d" | "lp64e",
3238 "invalid RISC-V ABI name: {}",
3239 self.llvm_abiname,
3240 );
3241 }
3242 "arm" => {
3243 check!(
3244 self.llvm_floatabi.is_some(),
3245 "ARM targets must set `llvm-floatabi` to `hard` or `soft`",
3246 )
3247 }
3248 _ => {}
3249 }
3250
3251 if let Some(rust_abi) = self.rustc_abi {
3253 match rust_abi {
3254 RustcAbi::X86Sse2 => check_matches!(
3255 &*self.arch,
3256 "x86",
3257 "`x86-sse2` ABI is only valid for x86-32 targets"
3258 ),
3259 RustcAbi::X86Softfloat => check_matches!(
3260 &*self.arch,
3261 "x86" | "x86_64",
3262 "`x86-softfloat` ABI is only valid for x86 targets"
3263 ),
3264 }
3265 }
3266
3267 if !self.features.is_empty() {
3269 let mut features_enabled = FxHashSet::default();
3270 let mut features_disabled = FxHashSet::default();
3271 for feat in self.features.split(',') {
3272 if let Some(feat) = feat.strip_prefix("+") {
3273 features_enabled.insert(feat);
3274 if features_disabled.contains(feat) {
3275 return Err(format!(
3276 "target feature `{feat}` is both enabled and disabled"
3277 ));
3278 }
3279 } else if let Some(feat) = feat.strip_prefix("-") {
3280 features_disabled.insert(feat);
3281 if features_enabled.contains(feat) {
3282 return Err(format!(
3283 "target feature `{feat}` is both enabled and disabled"
3284 ));
3285 }
3286 } else {
3287 return Err(format!(
3288 "target feature `{feat}` is invalid, must start with `+` or `-`"
3289 ));
3290 }
3291 }
3292 let abi_feature_constraints = self.abi_required_features();
3294 for feat in abi_feature_constraints.required {
3295 if features_disabled.contains(feat) {
3298 return Err(format!(
3299 "target feature `{feat}` is required by the ABI but gets disabled in target spec"
3300 ));
3301 }
3302 }
3303 for feat in abi_feature_constraints.incompatible {
3304 if features_enabled.contains(feat) {
3307 return Err(format!(
3308 "target feature `{feat}` is incompatible with the ABI but gets enabled in target spec"
3309 ));
3310 }
3311 }
3312 }
3313
3314 Ok(())
3315 }
3316
3317 #[cfg(test)]
3319 fn test_target(mut self) {
3320 let recycled_target = Target::from_json(self.to_json()).map(|(j, _)| j);
3321 self.update_to_cli();
3322 self.check_consistency(TargetKind::Builtin).unwrap();
3323 assert_eq!(recycled_target, Ok(self));
3324 }
3325
3326 fn can_use_os_unknown(&self) -> bool {
3329 self.llvm_target == "wasm32-unknown-unknown"
3330 || self.llvm_target == "wasm64-unknown-unknown"
3331 || (self.env == "sgx" && self.vendor == "fortanix")
3332 }
3333
3334 pub fn expect_builtin(target_tuple: &TargetTuple) -> Target {
3336 match *target_tuple {
3337 TargetTuple::TargetTuple(ref target_tuple) => {
3338 load_builtin(target_tuple).expect("built-in target")
3339 }
3340 TargetTuple::TargetJson { .. } => {
3341 panic!("built-in targets doesn't support target-paths")
3342 }
3343 }
3344 }
3345
3346 pub fn builtins() -> impl Iterator<Item = Target> {
3348 load_all_builtins()
3349 }
3350
3351 pub fn search(
3361 target_tuple: &TargetTuple,
3362 sysroot: &Path,
3363 ) -> Result<(Target, TargetWarnings), String> {
3364 use std::{env, fs};
3365
3366 fn load_file(path: &Path) -> Result<(Target, TargetWarnings), String> {
3367 let contents = fs::read_to_string(path).map_err(|e| e.to_string())?;
3368 let obj = serde_json::from_str(&contents).map_err(|e| e.to_string())?;
3369 Target::from_json(obj)
3370 }
3371
3372 match *target_tuple {
3373 TargetTuple::TargetTuple(ref target_tuple) => {
3374 if let Some(t) = load_builtin(target_tuple) {
3376 return Ok((t, TargetWarnings::empty()));
3377 }
3378
3379 let path = {
3381 let mut target = target_tuple.to_string();
3382 target.push_str(".json");
3383 PathBuf::from(target)
3384 };
3385
3386 let target_path = env::var_os("RUST_TARGET_PATH").unwrap_or_default();
3387
3388 for dir in env::split_paths(&target_path) {
3389 let p = dir.join(&path);
3390 if p.is_file() {
3391 return load_file(&p);
3392 }
3393 }
3394
3395 let rustlib_path = crate::relative_target_rustlib_path(sysroot, target_tuple);
3398 let p = PathBuf::from_iter([
3399 Path::new(sysroot),
3400 Path::new(&rustlib_path),
3401 Path::new("target.json"),
3402 ]);
3403 if p.is_file() {
3404 return load_file(&p);
3405 }
3406
3407 if target_tuple == "i586-pc-windows-msvc" {
3411 Err("the `i586-pc-windows-msvc` target has been removed. Use the `i686-pc-windows-msvc` target instead.\n\
3412 Windows 10 (the minimum required OS version) requires a CPU baseline of at least i686 so you can safely switch".into())
3413 } else {
3414 Err(format!("could not find specification for target {target_tuple:?}"))
3415 }
3416 }
3417 TargetTuple::TargetJson { ref contents, .. } => {
3418 let obj = serde_json::from_str(contents).map_err(|e| e.to_string())?;
3419 Target::from_json(obj)
3420 }
3421 }
3422 }
3423
3424 pub fn small_data_threshold_support(&self) -> SmallDataThresholdSupport {
3427 match &self.options.small_data_threshold_support {
3428 SmallDataThresholdSupport::DefaultForArch => match self.arch.as_ref() {
3432 "mips" | "mips64" | "mips32r6" => {
3433 SmallDataThresholdSupport::LlvmArg("mips-ssection-threshold".into())
3434 }
3435 "hexagon" => {
3436 SmallDataThresholdSupport::LlvmArg("hexagon-small-data-threshold".into())
3437 }
3438 "m68k" => SmallDataThresholdSupport::LlvmArg("m68k-ssection-threshold".into()),
3439 "riscv32" | "riscv64" => {
3440 SmallDataThresholdSupport::LlvmModuleFlag("SmallDataLimit".into())
3441 }
3442 _ => SmallDataThresholdSupport::None,
3443 },
3444 s => s.clone(),
3445 }
3446 }
3447
3448 pub fn object_architecture(
3449 &self,
3450 unstable_target_features: &FxIndexSet<Symbol>,
3451 ) -> Option<(object::Architecture, Option<object::SubArchitecture>)> {
3452 use object::Architecture;
3453 Some(match self.arch.as_ref() {
3454 "arm" => (Architecture::Arm, None),
3455 "aarch64" => (
3456 if self.pointer_width == 32 {
3457 Architecture::Aarch64_Ilp32
3458 } else {
3459 Architecture::Aarch64
3460 },
3461 None,
3462 ),
3463 "x86" => (Architecture::I386, None),
3464 "s390x" => (Architecture::S390x, None),
3465 "mips" | "mips32r6" => (Architecture::Mips, None),
3466 "mips64" | "mips64r6" => (
3467 if self.options.llvm_abiname.as_ref() == "n32" {
3473 Architecture::Mips64_N32
3474 } else {
3475 Architecture::Mips64
3476 },
3477 None,
3478 ),
3479 "x86_64" => (
3480 if self.pointer_width == 32 {
3481 Architecture::X86_64_X32
3482 } else {
3483 Architecture::X86_64
3484 },
3485 None,
3486 ),
3487 "powerpc" => (Architecture::PowerPc, None),
3488 "powerpc64" => (Architecture::PowerPc64, None),
3489 "riscv32" => (Architecture::Riscv32, None),
3490 "riscv64" => (Architecture::Riscv64, None),
3491 "sparc" => {
3492 if unstable_target_features.contains(&sym::v8plus) {
3493 (Architecture::Sparc32Plus, None)
3495 } else {
3496 (Architecture::Sparc, None)
3498 }
3499 }
3500 "sparc64" => (Architecture::Sparc64, None),
3501 "avr" => (Architecture::Avr, None),
3502 "msp430" => (Architecture::Msp430, None),
3503 "hexagon" => (Architecture::Hexagon, None),
3504 "bpf" => (Architecture::Bpf, None),
3505 "loongarch64" => (Architecture::LoongArch64, None),
3506 "csky" => (Architecture::Csky, None),
3507 "arm64ec" => (Architecture::Aarch64, Some(object::SubArchitecture::Arm64EC)),
3508 _ => return None,
3510 })
3511 }
3512
3513 pub fn max_reliable_alignment(&self) -> Align {
3522 if self.is_like_windows && self.arch == "x86" {
3526 Align::from_bytes(4).unwrap()
3527 } else {
3528 Align::MAX
3529 }
3530 }
3531}
3532
3533#[derive(Clone, Debug)]
3535pub enum TargetTuple {
3536 TargetTuple(String),
3537 TargetJson {
3538 path_for_rustdoc: PathBuf,
3541 tuple: String,
3542 contents: String,
3543 },
3544}
3545
3546impl PartialEq for TargetTuple {
3548 fn eq(&self, other: &Self) -> bool {
3549 match (self, other) {
3550 (Self::TargetTuple(l0), Self::TargetTuple(r0)) => l0 == r0,
3551 (
3552 Self::TargetJson { path_for_rustdoc: _, tuple: l_tuple, contents: l_contents },
3553 Self::TargetJson { path_for_rustdoc: _, tuple: r_tuple, contents: r_contents },
3554 ) => l_tuple == r_tuple && l_contents == r_contents,
3555 _ => false,
3556 }
3557 }
3558}
3559
3560impl Hash for TargetTuple {
3562 fn hash<H: Hasher>(&self, state: &mut H) -> () {
3563 match self {
3564 TargetTuple::TargetTuple(tuple) => {
3565 0u8.hash(state);
3566 tuple.hash(state)
3567 }
3568 TargetTuple::TargetJson { path_for_rustdoc: _, tuple, contents } => {
3569 1u8.hash(state);
3570 tuple.hash(state);
3571 contents.hash(state)
3572 }
3573 }
3574 }
3575}
3576
3577impl<S: Encoder> Encodable<S> for TargetTuple {
3579 fn encode(&self, s: &mut S) {
3580 match self {
3581 TargetTuple::TargetTuple(tuple) => {
3582 s.emit_u8(0);
3583 s.emit_str(tuple);
3584 }
3585 TargetTuple::TargetJson { path_for_rustdoc: _, tuple, contents } => {
3586 s.emit_u8(1);
3587 s.emit_str(tuple);
3588 s.emit_str(contents);
3589 }
3590 }
3591 }
3592}
3593
3594impl<D: Decoder> Decodable<D> for TargetTuple {
3595 fn decode(d: &mut D) -> Self {
3596 match d.read_u8() {
3597 0 => TargetTuple::TargetTuple(d.read_str().to_owned()),
3598 1 => TargetTuple::TargetJson {
3599 path_for_rustdoc: PathBuf::new(),
3600 tuple: d.read_str().to_owned(),
3601 contents: d.read_str().to_owned(),
3602 },
3603 _ => {
3604 panic!("invalid enum variant tag while decoding `TargetTuple`, expected 0..2");
3605 }
3606 }
3607 }
3608}
3609
3610impl TargetTuple {
3611 pub fn from_tuple(tuple: &str) -> Self {
3613 TargetTuple::TargetTuple(tuple.into())
3614 }
3615
3616 pub fn from_path(path: &Path) -> Result<Self, io::Error> {
3618 let canonicalized_path = try_canonicalize(path)?;
3619 let contents = std::fs::read_to_string(&canonicalized_path).map_err(|err| {
3620 io::Error::new(
3621 io::ErrorKind::InvalidInput,
3622 format!("target path {canonicalized_path:?} is not a valid file: {err}"),
3623 )
3624 })?;
3625 let tuple = canonicalized_path
3626 .file_stem()
3627 .expect("target path must not be empty")
3628 .to_str()
3629 .expect("target path must be valid unicode")
3630 .to_owned();
3631 Ok(TargetTuple::TargetJson { path_for_rustdoc: canonicalized_path, tuple, contents })
3632 }
3633
3634 pub fn tuple(&self) -> &str {
3638 match *self {
3639 TargetTuple::TargetTuple(ref tuple) | TargetTuple::TargetJson { ref tuple, .. } => {
3640 tuple
3641 }
3642 }
3643 }
3644
3645 pub fn debug_tuple(&self) -> String {
3650 use std::hash::DefaultHasher;
3651
3652 match self {
3653 TargetTuple::TargetTuple(tuple) => tuple.to_owned(),
3654 TargetTuple::TargetJson { path_for_rustdoc: _, tuple, contents: content } => {
3655 let mut hasher = DefaultHasher::new();
3656 content.hash(&mut hasher);
3657 let hash = hasher.finish();
3658 format!("{tuple}-{hash}")
3659 }
3660 }
3661 }
3662}
3663
3664impl fmt::Display for TargetTuple {
3665 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3666 write!(f, "{}", self.debug_tuple())
3667 }
3668}