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