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 is_lld_enabled(self) -> bool {
770 self.contains(LinkerFeatures::LLD)
771 }
772
773 pub fn is_cc_enabled(self) -> bool {
775 self.contains(LinkerFeatures::CC)
776 }
777}
778
779#[derive(Clone, Copy, Debug, PartialEq, Hash, Encodable, Decodable, HashStable_Generic)]
780pub enum PanicStrategy {
781 Unwind,
782 Abort,
783}
784
785#[derive(Clone, Copy, Debug, PartialEq, Hash, Encodable, Decodable, HashStable_Generic)]
786pub enum OnBrokenPipe {
787 Default,
788 Kill,
789 Error,
790 Inherit,
791}
792
793impl PanicStrategy {
794 pub fn desc(&self) -> &str {
795 match *self {
796 PanicStrategy::Unwind => "unwind",
797 PanicStrategy::Abort => "abort",
798 }
799 }
800
801 pub const fn desc_symbol(&self) -> Symbol {
802 match *self {
803 PanicStrategy::Unwind => sym::unwind,
804 PanicStrategy::Abort => sym::abort,
805 }
806 }
807
808 pub const fn all() -> [Symbol; 2] {
809 [Self::Abort.desc_symbol(), Self::Unwind.desc_symbol()]
810 }
811}
812
813impl ToJson for PanicStrategy {
814 fn to_json(&self) -> Json {
815 match *self {
816 PanicStrategy::Abort => "abort".to_json(),
817 PanicStrategy::Unwind => "unwind".to_json(),
818 }
819 }
820}
821
822#[derive(Clone, Copy, Debug, PartialEq, Hash)]
823pub enum RelroLevel {
824 Full,
825 Partial,
826 Off,
827 None,
828}
829
830impl RelroLevel {
831 pub fn desc(&self) -> &str {
832 match *self {
833 RelroLevel::Full => "full",
834 RelroLevel::Partial => "partial",
835 RelroLevel::Off => "off",
836 RelroLevel::None => "none",
837 }
838 }
839}
840
841#[derive(Clone, Copy, Debug, PartialEq, Hash)]
842pub enum SymbolVisibility {
843 Hidden,
844 Protected,
845 Interposable,
846}
847
848impl SymbolVisibility {
849 pub fn desc(&self) -> &str {
850 match *self {
851 SymbolVisibility::Hidden => "hidden",
852 SymbolVisibility::Protected => "protected",
853 SymbolVisibility::Interposable => "interposable",
854 }
855 }
856}
857
858impl FromStr for SymbolVisibility {
859 type Err = ();
860
861 fn from_str(s: &str) -> Result<SymbolVisibility, ()> {
862 match s {
863 "hidden" => Ok(SymbolVisibility::Hidden),
864 "protected" => Ok(SymbolVisibility::Protected),
865 "interposable" => Ok(SymbolVisibility::Interposable),
866 _ => Err(()),
867 }
868 }
869}
870
871impl ToJson for SymbolVisibility {
872 fn to_json(&self) -> Json {
873 match *self {
874 SymbolVisibility::Hidden => "hidden".to_json(),
875 SymbolVisibility::Protected => "protected".to_json(),
876 SymbolVisibility::Interposable => "interposable".to_json(),
877 }
878 }
879}
880
881impl FromStr for RelroLevel {
882 type Err = ();
883
884 fn from_str(s: &str) -> Result<RelroLevel, ()> {
885 match s {
886 "full" => Ok(RelroLevel::Full),
887 "partial" => Ok(RelroLevel::Partial),
888 "off" => Ok(RelroLevel::Off),
889 "none" => Ok(RelroLevel::None),
890 _ => Err(()),
891 }
892 }
893}
894
895impl ToJson for RelroLevel {
896 fn to_json(&self) -> Json {
897 match *self {
898 RelroLevel::Full => "full".to_json(),
899 RelroLevel::Partial => "partial".to_json(),
900 RelroLevel::Off => "off".to_json(),
901 RelroLevel::None => "None".to_json(),
902 }
903 }
904}
905
906#[derive(Clone, Debug, PartialEq, Hash)]
907pub enum SmallDataThresholdSupport {
908 None,
909 DefaultForArch,
910 LlvmModuleFlag(StaticCow<str>),
911 LlvmArg(StaticCow<str>),
912}
913
914impl FromStr for SmallDataThresholdSupport {
915 type Err = ();
916
917 fn from_str(s: &str) -> Result<Self, Self::Err> {
918 if s == "none" {
919 Ok(Self::None)
920 } else if s == "default-for-arch" {
921 Ok(Self::DefaultForArch)
922 } else if let Some(flag) = s.strip_prefix("llvm-module-flag=") {
923 Ok(Self::LlvmModuleFlag(flag.to_string().into()))
924 } else if let Some(arg) = s.strip_prefix("llvm-arg=") {
925 Ok(Self::LlvmArg(arg.to_string().into()))
926 } else {
927 Err(())
928 }
929 }
930}
931
932impl ToJson for SmallDataThresholdSupport {
933 fn to_json(&self) -> Value {
934 match self {
935 Self::None => "none".to_json(),
936 Self::DefaultForArch => "default-for-arch".to_json(),
937 Self::LlvmModuleFlag(flag) => format!("llvm-module-flag={flag}").to_json(),
938 Self::LlvmArg(arg) => format!("llvm-arg={arg}").to_json(),
939 }
940 }
941}
942
943#[derive(Clone, Copy, Debug, PartialEq, Hash)]
944pub enum MergeFunctions {
945 Disabled,
946 Trampolines,
947 Aliases,
948}
949
950impl MergeFunctions {
951 pub fn desc(&self) -> &str {
952 match *self {
953 MergeFunctions::Disabled => "disabled",
954 MergeFunctions::Trampolines => "trampolines",
955 MergeFunctions::Aliases => "aliases",
956 }
957 }
958}
959
960impl FromStr for MergeFunctions {
961 type Err = ();
962
963 fn from_str(s: &str) -> Result<MergeFunctions, ()> {
964 match s {
965 "disabled" => Ok(MergeFunctions::Disabled),
966 "trampolines" => Ok(MergeFunctions::Trampolines),
967 "aliases" => Ok(MergeFunctions::Aliases),
968 _ => Err(()),
969 }
970 }
971}
972
973impl ToJson for MergeFunctions {
974 fn to_json(&self) -> Json {
975 match *self {
976 MergeFunctions::Disabled => "disabled".to_json(),
977 MergeFunctions::Trampolines => "trampolines".to_json(),
978 MergeFunctions::Aliases => "aliases".to_json(),
979 }
980 }
981}
982
983#[derive(Clone, Copy, PartialEq, Hash, Debug)]
984pub enum RelocModel {
985 Static,
986 Pic,
987 Pie,
988 DynamicNoPic,
989 Ropi,
990 Rwpi,
991 RopiRwpi,
992}
993
994impl RelocModel {
995 pub fn desc(&self) -> &str {
996 match *self {
997 RelocModel::Static => "static",
998 RelocModel::Pic => "pic",
999 RelocModel::Pie => "pie",
1000 RelocModel::DynamicNoPic => "dynamic-no-pic",
1001 RelocModel::Ropi => "ropi",
1002 RelocModel::Rwpi => "rwpi",
1003 RelocModel::RopiRwpi => "ropi-rwpi",
1004 }
1005 }
1006 pub const fn desc_symbol(&self) -> Symbol {
1007 match *self {
1008 RelocModel::Static => kw::Static,
1009 RelocModel::Pic => sym::pic,
1010 RelocModel::Pie => sym::pie,
1011 RelocModel::DynamicNoPic => sym::dynamic_no_pic,
1012 RelocModel::Ropi => sym::ropi,
1013 RelocModel::Rwpi => sym::rwpi,
1014 RelocModel::RopiRwpi => sym::ropi_rwpi,
1015 }
1016 }
1017
1018 pub const fn all() -> [Symbol; 7] {
1019 [
1020 RelocModel::Static.desc_symbol(),
1021 RelocModel::Pic.desc_symbol(),
1022 RelocModel::Pie.desc_symbol(),
1023 RelocModel::DynamicNoPic.desc_symbol(),
1024 RelocModel::Ropi.desc_symbol(),
1025 RelocModel::Rwpi.desc_symbol(),
1026 RelocModel::RopiRwpi.desc_symbol(),
1027 ]
1028 }
1029}
1030
1031impl FromStr for RelocModel {
1032 type Err = ();
1033
1034 fn from_str(s: &str) -> Result<RelocModel, ()> {
1035 Ok(match s {
1036 "static" => RelocModel::Static,
1037 "pic" => RelocModel::Pic,
1038 "pie" => RelocModel::Pie,
1039 "dynamic-no-pic" => RelocModel::DynamicNoPic,
1040 "ropi" => RelocModel::Ropi,
1041 "rwpi" => RelocModel::Rwpi,
1042 "ropi-rwpi" => RelocModel::RopiRwpi,
1043 _ => return Err(()),
1044 })
1045 }
1046}
1047
1048impl ToJson for RelocModel {
1049 fn to_json(&self) -> Json {
1050 self.desc().to_json()
1051 }
1052}
1053
1054#[derive(Clone, Copy, PartialEq, Hash, Debug)]
1055pub enum CodeModel {
1056 Tiny,
1057 Small,
1058 Kernel,
1059 Medium,
1060 Large,
1061}
1062
1063impl FromStr for CodeModel {
1064 type Err = ();
1065
1066 fn from_str(s: &str) -> Result<CodeModel, ()> {
1067 Ok(match s {
1068 "tiny" => CodeModel::Tiny,
1069 "small" => CodeModel::Small,
1070 "kernel" => CodeModel::Kernel,
1071 "medium" => CodeModel::Medium,
1072 "large" => CodeModel::Large,
1073 _ => return Err(()),
1074 })
1075 }
1076}
1077
1078impl ToJson for CodeModel {
1079 fn to_json(&self) -> Json {
1080 match *self {
1081 CodeModel::Tiny => "tiny",
1082 CodeModel::Small => "small",
1083 CodeModel::Kernel => "kernel",
1084 CodeModel::Medium => "medium",
1085 CodeModel::Large => "large",
1086 }
1087 .to_json()
1088 }
1089}
1090
1091#[derive(Clone, Copy, PartialEq, Hash, Debug)]
1093pub enum FloatAbi {
1094 Soft,
1095 Hard,
1096}
1097
1098impl FromStr for FloatAbi {
1099 type Err = ();
1100
1101 fn from_str(s: &str) -> Result<FloatAbi, ()> {
1102 Ok(match s {
1103 "soft" => FloatAbi::Soft,
1104 "hard" => FloatAbi::Hard,
1105 _ => return Err(()),
1106 })
1107 }
1108}
1109
1110impl ToJson for FloatAbi {
1111 fn to_json(&self) -> Json {
1112 match *self {
1113 FloatAbi::Soft => "soft",
1114 FloatAbi::Hard => "hard",
1115 }
1116 .to_json()
1117 }
1118}
1119
1120#[derive(Clone, Copy, PartialEq, Hash, Debug)]
1122pub enum RustcAbi {
1123 X86Sse2,
1125 X86Softfloat,
1127}
1128
1129impl FromStr for RustcAbi {
1130 type Err = ();
1131
1132 fn from_str(s: &str) -> Result<RustcAbi, ()> {
1133 Ok(match s {
1134 "x86-sse2" => RustcAbi::X86Sse2,
1135 "x86-softfloat" => RustcAbi::X86Softfloat,
1136 _ => return Err(()),
1137 })
1138 }
1139}
1140
1141impl ToJson for RustcAbi {
1142 fn to_json(&self) -> Json {
1143 match *self {
1144 RustcAbi::X86Sse2 => "x86-sse2",
1145 RustcAbi::X86Softfloat => "x86-softfloat",
1146 }
1147 .to_json()
1148 }
1149}
1150
1151#[derive(Clone, Copy, PartialEq, Hash, Debug)]
1152pub enum TlsModel {
1153 GeneralDynamic,
1154 LocalDynamic,
1155 InitialExec,
1156 LocalExec,
1157 Emulated,
1158}
1159
1160impl FromStr for TlsModel {
1161 type Err = ();
1162
1163 fn from_str(s: &str) -> Result<TlsModel, ()> {
1164 Ok(match s {
1165 "global-dynamic" => TlsModel::GeneralDynamic,
1168 "local-dynamic" => TlsModel::LocalDynamic,
1169 "initial-exec" => TlsModel::InitialExec,
1170 "local-exec" => TlsModel::LocalExec,
1171 "emulated" => TlsModel::Emulated,
1172 _ => return Err(()),
1173 })
1174 }
1175}
1176
1177impl ToJson for TlsModel {
1178 fn to_json(&self) -> Json {
1179 match *self {
1180 TlsModel::GeneralDynamic => "global-dynamic",
1181 TlsModel::LocalDynamic => "local-dynamic",
1182 TlsModel::InitialExec => "initial-exec",
1183 TlsModel::LocalExec => "local-exec",
1184 TlsModel::Emulated => "emulated",
1185 }
1186 .to_json()
1187 }
1188}
1189
1190#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug)]
1192pub enum LinkOutputKind {
1193 DynamicNoPicExe,
1195 DynamicPicExe,
1197 StaticNoPicExe,
1199 StaticPicExe,
1201 DynamicDylib,
1203 StaticDylib,
1205 WasiReactorExe,
1207}
1208
1209impl LinkOutputKind {
1210 fn as_str(&self) -> &'static str {
1211 match self {
1212 LinkOutputKind::DynamicNoPicExe => "dynamic-nopic-exe",
1213 LinkOutputKind::DynamicPicExe => "dynamic-pic-exe",
1214 LinkOutputKind::StaticNoPicExe => "static-nopic-exe",
1215 LinkOutputKind::StaticPicExe => "static-pic-exe",
1216 LinkOutputKind::DynamicDylib => "dynamic-dylib",
1217 LinkOutputKind::StaticDylib => "static-dylib",
1218 LinkOutputKind::WasiReactorExe => "wasi-reactor-exe",
1219 }
1220 }
1221
1222 pub(super) fn from_str(s: &str) -> Option<LinkOutputKind> {
1223 Some(match s {
1224 "dynamic-nopic-exe" => LinkOutputKind::DynamicNoPicExe,
1225 "dynamic-pic-exe" => LinkOutputKind::DynamicPicExe,
1226 "static-nopic-exe" => LinkOutputKind::StaticNoPicExe,
1227 "static-pic-exe" => LinkOutputKind::StaticPicExe,
1228 "dynamic-dylib" => LinkOutputKind::DynamicDylib,
1229 "static-dylib" => LinkOutputKind::StaticDylib,
1230 "wasi-reactor-exe" => LinkOutputKind::WasiReactorExe,
1231 _ => return None,
1232 })
1233 }
1234
1235 pub fn can_link_dylib(self) -> bool {
1236 match self {
1237 LinkOutputKind::StaticNoPicExe | LinkOutputKind::StaticPicExe => false,
1238 LinkOutputKind::DynamicNoPicExe
1239 | LinkOutputKind::DynamicPicExe
1240 | LinkOutputKind::DynamicDylib
1241 | LinkOutputKind::StaticDylib
1242 | LinkOutputKind::WasiReactorExe => true,
1243 }
1244 }
1245}
1246
1247impl fmt::Display for LinkOutputKind {
1248 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1249 f.write_str(self.as_str())
1250 }
1251}
1252
1253pub type LinkArgs = BTreeMap<LinkerFlavor, Vec<StaticCow<str>>>;
1254pub type LinkArgsCli = BTreeMap<LinkerFlavorCli, Vec<StaticCow<str>>>;
1255
1256#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
1261pub enum DebuginfoKind {
1262 #[default]
1264 Dwarf,
1265 DwarfDsym,
1267 Pdb,
1269}
1270
1271impl DebuginfoKind {
1272 fn as_str(&self) -> &'static str {
1273 match self {
1274 DebuginfoKind::Dwarf => "dwarf",
1275 DebuginfoKind::DwarfDsym => "dwarf-dsym",
1276 DebuginfoKind::Pdb => "pdb",
1277 }
1278 }
1279}
1280
1281impl FromStr for DebuginfoKind {
1282 type Err = ();
1283
1284 fn from_str(s: &str) -> Result<Self, ()> {
1285 Ok(match s {
1286 "dwarf" => DebuginfoKind::Dwarf,
1287 "dwarf-dsym" => DebuginfoKind::DwarfDsym,
1288 "pdb" => DebuginfoKind::Pdb,
1289 _ => return Err(()),
1290 })
1291 }
1292}
1293
1294impl ToJson for DebuginfoKind {
1295 fn to_json(&self) -> Json {
1296 self.as_str().to_json()
1297 }
1298}
1299
1300impl fmt::Display for DebuginfoKind {
1301 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1302 f.write_str(self.as_str())
1303 }
1304}
1305
1306#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
1307pub enum SplitDebuginfo {
1308 #[default]
1316 Off,
1317
1318 Packed,
1325
1326 Unpacked,
1333}
1334
1335impl SplitDebuginfo {
1336 fn as_str(&self) -> &'static str {
1337 match self {
1338 SplitDebuginfo::Off => "off",
1339 SplitDebuginfo::Packed => "packed",
1340 SplitDebuginfo::Unpacked => "unpacked",
1341 }
1342 }
1343}
1344
1345impl FromStr for SplitDebuginfo {
1346 type Err = ();
1347
1348 fn from_str(s: &str) -> Result<Self, ()> {
1349 Ok(match s {
1350 "off" => SplitDebuginfo::Off,
1351 "unpacked" => SplitDebuginfo::Unpacked,
1352 "packed" => SplitDebuginfo::Packed,
1353 _ => return Err(()),
1354 })
1355 }
1356}
1357
1358impl ToJson for SplitDebuginfo {
1359 fn to_json(&self) -> Json {
1360 self.as_str().to_json()
1361 }
1362}
1363
1364impl fmt::Display for SplitDebuginfo {
1365 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1366 f.write_str(self.as_str())
1367 }
1368}
1369
1370#[derive(Clone, Debug, PartialEq, Eq)]
1371pub enum StackProbeType {
1372 None,
1374 Inline,
1378 Call,
1380 InlineOrCall { min_llvm_version_for_inline: (u32, u32, u32) },
1383}
1384
1385impl StackProbeType {
1386 fn from_json(json: &Json) -> Result<Self, String> {
1387 let object = json.as_object().ok_or_else(|| "expected a JSON object")?;
1388 let kind = object
1389 .get("kind")
1390 .and_then(|o| o.as_str())
1391 .ok_or_else(|| "expected `kind` to be a string")?;
1392 match kind {
1393 "none" => Ok(StackProbeType::None),
1394 "inline" => Ok(StackProbeType::Inline),
1395 "call" => Ok(StackProbeType::Call),
1396 "inline-or-call" => {
1397 let min_version = object
1398 .get("min-llvm-version-for-inline")
1399 .and_then(|o| o.as_array())
1400 .ok_or_else(|| "expected `min-llvm-version-for-inline` to be an array")?;
1401 let mut iter = min_version.into_iter().map(|v| {
1402 let int = v.as_u64().ok_or_else(
1403 || "expected `min-llvm-version-for-inline` values to be integers",
1404 )?;
1405 u32::try_from(int)
1406 .map_err(|_| "`min-llvm-version-for-inline` values don't convert to u32")
1407 });
1408 let min_llvm_version_for_inline = (
1409 iter.next().unwrap_or(Ok(11))?,
1410 iter.next().unwrap_or(Ok(0))?,
1411 iter.next().unwrap_or(Ok(0))?,
1412 );
1413 Ok(StackProbeType::InlineOrCall { min_llvm_version_for_inline })
1414 }
1415 _ => Err(String::from(
1416 "`kind` expected to be one of `none`, `inline`, `call` or `inline-or-call`",
1417 )),
1418 }
1419 }
1420}
1421
1422impl ToJson for StackProbeType {
1423 fn to_json(&self) -> Json {
1424 Json::Object(match self {
1425 StackProbeType::None => {
1426 [(String::from("kind"), "none".to_json())].into_iter().collect()
1427 }
1428 StackProbeType::Inline => {
1429 [(String::from("kind"), "inline".to_json())].into_iter().collect()
1430 }
1431 StackProbeType::Call => {
1432 [(String::from("kind"), "call".to_json())].into_iter().collect()
1433 }
1434 StackProbeType::InlineOrCall { min_llvm_version_for_inline: (maj, min, patch) } => [
1435 (String::from("kind"), "inline-or-call".to_json()),
1436 (
1437 String::from("min-llvm-version-for-inline"),
1438 Json::Array(vec![maj.to_json(), min.to_json(), patch.to_json()]),
1439 ),
1440 ]
1441 .into_iter()
1442 .collect(),
1443 })
1444 }
1445}
1446
1447#[derive(Default, Clone, Copy, PartialEq, Eq, Hash, Encodable, Decodable, HashStable_Generic)]
1448pub struct SanitizerSet(u16);
1449bitflags::bitflags! {
1450 impl SanitizerSet: u16 {
1451 const ADDRESS = 1 << 0;
1452 const LEAK = 1 << 1;
1453 const MEMORY = 1 << 2;
1454 const THREAD = 1 << 3;
1455 const HWADDRESS = 1 << 4;
1456 const CFI = 1 << 5;
1457 const MEMTAG = 1 << 6;
1458 const SHADOWCALLSTACK = 1 << 7;
1459 const KCFI = 1 << 8;
1460 const KERNELADDRESS = 1 << 9;
1461 const SAFESTACK = 1 << 10;
1462 const DATAFLOW = 1 << 11;
1463 }
1464}
1465rustc_data_structures::external_bitflags_debug! { SanitizerSet }
1466
1467impl SanitizerSet {
1468 const MUTUALLY_EXCLUSIVE: &'static [(SanitizerSet, SanitizerSet)] = &[
1471 (SanitizerSet::ADDRESS, SanitizerSet::MEMORY),
1472 (SanitizerSet::ADDRESS, SanitizerSet::THREAD),
1473 (SanitizerSet::ADDRESS, SanitizerSet::HWADDRESS),
1474 (SanitizerSet::ADDRESS, SanitizerSet::MEMTAG),
1475 (SanitizerSet::ADDRESS, SanitizerSet::KERNELADDRESS),
1476 (SanitizerSet::ADDRESS, SanitizerSet::SAFESTACK),
1477 (SanitizerSet::LEAK, SanitizerSet::MEMORY),
1478 (SanitizerSet::LEAK, SanitizerSet::THREAD),
1479 (SanitizerSet::LEAK, SanitizerSet::KERNELADDRESS),
1480 (SanitizerSet::LEAK, SanitizerSet::SAFESTACK),
1481 (SanitizerSet::MEMORY, SanitizerSet::THREAD),
1482 (SanitizerSet::MEMORY, SanitizerSet::HWADDRESS),
1483 (SanitizerSet::MEMORY, SanitizerSet::KERNELADDRESS),
1484 (SanitizerSet::MEMORY, SanitizerSet::SAFESTACK),
1485 (SanitizerSet::THREAD, SanitizerSet::HWADDRESS),
1486 (SanitizerSet::THREAD, SanitizerSet::KERNELADDRESS),
1487 (SanitizerSet::THREAD, SanitizerSet::SAFESTACK),
1488 (SanitizerSet::HWADDRESS, SanitizerSet::MEMTAG),
1489 (SanitizerSet::HWADDRESS, SanitizerSet::KERNELADDRESS),
1490 (SanitizerSet::HWADDRESS, SanitizerSet::SAFESTACK),
1491 (SanitizerSet::CFI, SanitizerSet::KCFI),
1492 (SanitizerSet::MEMTAG, SanitizerSet::KERNELADDRESS),
1493 (SanitizerSet::KERNELADDRESS, SanitizerSet::SAFESTACK),
1494 ];
1495
1496 pub fn as_str(self) -> Option<&'static str> {
1500 Some(match self {
1501 SanitizerSet::ADDRESS => "address",
1502 SanitizerSet::CFI => "cfi",
1503 SanitizerSet::DATAFLOW => "dataflow",
1504 SanitizerSet::KCFI => "kcfi",
1505 SanitizerSet::KERNELADDRESS => "kernel-address",
1506 SanitizerSet::LEAK => "leak",
1507 SanitizerSet::MEMORY => "memory",
1508 SanitizerSet::MEMTAG => "memtag",
1509 SanitizerSet::SAFESTACK => "safestack",
1510 SanitizerSet::SHADOWCALLSTACK => "shadow-call-stack",
1511 SanitizerSet::THREAD => "thread",
1512 SanitizerSet::HWADDRESS => "hwaddress",
1513 _ => return None,
1514 })
1515 }
1516
1517 pub fn mutually_exclusive(self) -> Option<(SanitizerSet, SanitizerSet)> {
1518 Self::MUTUALLY_EXCLUSIVE
1519 .into_iter()
1520 .find(|&(a, b)| self.contains(*a) && self.contains(*b))
1521 .copied()
1522 }
1523}
1524
1525impl fmt::Display for SanitizerSet {
1527 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1528 let mut first = true;
1529 for s in *self {
1530 let name = s.as_str().unwrap_or_else(|| panic!("unrecognized sanitizer {s:?}"));
1531 if !first {
1532 f.write_str(", ")?;
1533 }
1534 f.write_str(name)?;
1535 first = false;
1536 }
1537 Ok(())
1538 }
1539}
1540
1541impl ToJson for SanitizerSet {
1542 fn to_json(&self) -> Json {
1543 self.into_iter()
1544 .map(|v| Some(v.as_str()?.to_json()))
1545 .collect::<Option<Vec<_>>>()
1546 .unwrap_or_default()
1547 .to_json()
1548 }
1549}
1550
1551#[derive(Clone, Copy, PartialEq, Hash, Debug)]
1552pub enum FramePointer {
1553 Always,
1555 NonLeaf,
1558 MayOmit,
1562}
1563
1564impl FramePointer {
1565 #[inline]
1568 pub fn ratchet(&mut self, rhs: FramePointer) -> FramePointer {
1569 *self = match (*self, rhs) {
1570 (FramePointer::Always, _) | (_, FramePointer::Always) => FramePointer::Always,
1571 (FramePointer::NonLeaf, _) | (_, FramePointer::NonLeaf) => FramePointer::NonLeaf,
1572 _ => FramePointer::MayOmit,
1573 };
1574 *self
1575 }
1576}
1577
1578impl FromStr for FramePointer {
1579 type Err = ();
1580 fn from_str(s: &str) -> Result<Self, ()> {
1581 Ok(match s {
1582 "always" => Self::Always,
1583 "non-leaf" => Self::NonLeaf,
1584 "may-omit" => Self::MayOmit,
1585 _ => return Err(()),
1586 })
1587 }
1588}
1589
1590impl ToJson for FramePointer {
1591 fn to_json(&self) -> Json {
1592 match *self {
1593 Self::Always => "always",
1594 Self::NonLeaf => "non-leaf",
1595 Self::MayOmit => "may-omit",
1596 }
1597 .to_json()
1598 }
1599}
1600
1601#[derive(Clone, Copy, Debug, PartialEq, Hash, Eq)]
1603pub enum StackProtector {
1604 None,
1606
1607 Basic,
1612
1613 Strong,
1618
1619 All,
1621}
1622
1623impl StackProtector {
1624 fn as_str(&self) -> &'static str {
1625 match self {
1626 StackProtector::None => "none",
1627 StackProtector::Basic => "basic",
1628 StackProtector::Strong => "strong",
1629 StackProtector::All => "all",
1630 }
1631 }
1632}
1633
1634impl FromStr for StackProtector {
1635 type Err = ();
1636
1637 fn from_str(s: &str) -> Result<StackProtector, ()> {
1638 Ok(match s {
1639 "none" => StackProtector::None,
1640 "basic" => StackProtector::Basic,
1641 "strong" => StackProtector::Strong,
1642 "all" => StackProtector::All,
1643 _ => return Err(()),
1644 })
1645 }
1646}
1647
1648impl fmt::Display for StackProtector {
1649 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1650 f.write_str(self.as_str())
1651 }
1652}
1653
1654#[derive(PartialEq, Clone, Debug)]
1655pub enum BinaryFormat {
1656 Coff,
1657 Elf,
1658 MachO,
1659 Wasm,
1660 Xcoff,
1661}
1662
1663impl BinaryFormat {
1664 pub fn to_object(&self) -> object::BinaryFormat {
1666 match self {
1667 Self::Coff => object::BinaryFormat::Coff,
1668 Self::Elf => object::BinaryFormat::Elf,
1669 Self::MachO => object::BinaryFormat::MachO,
1670 Self::Wasm => object::BinaryFormat::Wasm,
1671 Self::Xcoff => object::BinaryFormat::Xcoff,
1672 }
1673 }
1674}
1675
1676impl FromStr for BinaryFormat {
1677 type Err = ();
1678 fn from_str(s: &str) -> Result<Self, Self::Err> {
1679 match s {
1680 "coff" => Ok(Self::Coff),
1681 "elf" => Ok(Self::Elf),
1682 "mach-o" => Ok(Self::MachO),
1683 "wasm" => Ok(Self::Wasm),
1684 "xcoff" => Ok(Self::Xcoff),
1685 _ => Err(()),
1686 }
1687 }
1688}
1689
1690impl ToJson for BinaryFormat {
1691 fn to_json(&self) -> Json {
1692 match self {
1693 Self::Coff => "coff",
1694 Self::Elf => "elf",
1695 Self::MachO => "mach-o",
1696 Self::Wasm => "wasm",
1697 Self::Xcoff => "xcoff",
1698 }
1699 .to_json()
1700 }
1701}
1702
1703impl ToJson for Align {
1704 fn to_json(&self) -> Json {
1705 self.bits().to_json()
1706 }
1707}
1708
1709macro_rules! supported_targets {
1710 ( $(($tuple:literal, $module:ident),)+ ) => {
1711 mod targets {
1712 $(pub(crate) mod $module;)+
1713 }
1714
1715 pub static TARGETS: &[&str] = &[$($tuple),+];
1717
1718 fn load_builtin(target: &str) -> Option<Target> {
1719 let t = match target {
1720 $( $tuple => targets::$module::target(), )+
1721 _ => return None,
1722 };
1723 debug!("got builtin target: {:?}", t);
1724 Some(t)
1725 }
1726
1727 fn load_all_builtins() -> impl Iterator<Item = Target> {
1728 [
1729 $( targets::$module::target, )+
1730 ]
1731 .into_iter()
1732 .map(|f| f())
1733 }
1734
1735 #[cfg(test)]
1736 mod tests {
1737 $(
1739 #[test] fn $module() {
1741 crate::spec::targets::$module::target().test_target()
1742 }
1743 )+
1744 }
1745 };
1746}
1747
1748supported_targets! {
1749 ("x86_64-unknown-linux-gnu", x86_64_unknown_linux_gnu),
1750 ("x86_64-unknown-linux-gnux32", x86_64_unknown_linux_gnux32),
1751 ("i686-unknown-linux-gnu", i686_unknown_linux_gnu),
1752 ("i586-unknown-linux-gnu", i586_unknown_linux_gnu),
1753 ("loongarch64-unknown-linux-gnu", loongarch64_unknown_linux_gnu),
1754 ("loongarch64-unknown-linux-musl", loongarch64_unknown_linux_musl),
1755 ("m68k-unknown-linux-gnu", m68k_unknown_linux_gnu),
1756 ("m68k-unknown-none-elf", m68k_unknown_none_elf),
1757 ("csky-unknown-linux-gnuabiv2", csky_unknown_linux_gnuabiv2),
1758 ("csky-unknown-linux-gnuabiv2hf", csky_unknown_linux_gnuabiv2hf),
1759 ("mips-unknown-linux-gnu", mips_unknown_linux_gnu),
1760 ("mips64-unknown-linux-gnuabi64", mips64_unknown_linux_gnuabi64),
1761 ("mips64el-unknown-linux-gnuabi64", mips64el_unknown_linux_gnuabi64),
1762 ("mipsisa32r6-unknown-linux-gnu", mipsisa32r6_unknown_linux_gnu),
1763 ("mipsisa32r6el-unknown-linux-gnu", mipsisa32r6el_unknown_linux_gnu),
1764 ("mipsisa64r6-unknown-linux-gnuabi64", mipsisa64r6_unknown_linux_gnuabi64),
1765 ("mipsisa64r6el-unknown-linux-gnuabi64", mipsisa64r6el_unknown_linux_gnuabi64),
1766 ("mipsel-unknown-linux-gnu", mipsel_unknown_linux_gnu),
1767 ("powerpc-unknown-linux-gnu", powerpc_unknown_linux_gnu),
1768 ("powerpc-unknown-linux-gnuspe", powerpc_unknown_linux_gnuspe),
1769 ("powerpc-unknown-linux-musl", powerpc_unknown_linux_musl),
1770 ("powerpc-unknown-linux-muslspe", powerpc_unknown_linux_muslspe),
1771 ("powerpc64-ibm-aix", powerpc64_ibm_aix),
1772 ("powerpc64-unknown-linux-gnu", powerpc64_unknown_linux_gnu),
1773 ("powerpc64-unknown-linux-musl", powerpc64_unknown_linux_musl),
1774 ("powerpc64le-unknown-linux-gnu", powerpc64le_unknown_linux_gnu),
1775 ("powerpc64le-unknown-linux-musl", powerpc64le_unknown_linux_musl),
1776 ("s390x-unknown-linux-gnu", s390x_unknown_linux_gnu),
1777 ("s390x-unknown-linux-musl", s390x_unknown_linux_musl),
1778 ("sparc-unknown-linux-gnu", sparc_unknown_linux_gnu),
1779 ("sparc64-unknown-linux-gnu", sparc64_unknown_linux_gnu),
1780 ("arm-unknown-linux-gnueabi", arm_unknown_linux_gnueabi),
1781 ("arm-unknown-linux-gnueabihf", arm_unknown_linux_gnueabihf),
1782 ("armeb-unknown-linux-gnueabi", armeb_unknown_linux_gnueabi),
1783 ("arm-unknown-linux-musleabi", arm_unknown_linux_musleabi),
1784 ("arm-unknown-linux-musleabihf", arm_unknown_linux_musleabihf),
1785 ("armv4t-unknown-linux-gnueabi", armv4t_unknown_linux_gnueabi),
1786 ("armv5te-unknown-linux-gnueabi", armv5te_unknown_linux_gnueabi),
1787 ("armv5te-unknown-linux-musleabi", armv5te_unknown_linux_musleabi),
1788 ("armv5te-unknown-linux-uclibceabi", armv5te_unknown_linux_uclibceabi),
1789 ("armv7-unknown-linux-gnueabi", armv7_unknown_linux_gnueabi),
1790 ("armv7-unknown-linux-gnueabihf", armv7_unknown_linux_gnueabihf),
1791 ("thumbv7neon-unknown-linux-gnueabihf", thumbv7neon_unknown_linux_gnueabihf),
1792 ("thumbv7neon-unknown-linux-musleabihf", thumbv7neon_unknown_linux_musleabihf),
1793 ("armv7-unknown-linux-musleabi", armv7_unknown_linux_musleabi),
1794 ("armv7-unknown-linux-musleabihf", armv7_unknown_linux_musleabihf),
1795 ("aarch64-unknown-linux-gnu", aarch64_unknown_linux_gnu),
1796 ("aarch64-unknown-linux-musl", aarch64_unknown_linux_musl),
1797 ("x86_64-unknown-linux-musl", x86_64_unknown_linux_musl),
1798 ("i686-unknown-linux-musl", i686_unknown_linux_musl),
1799 ("i586-unknown-linux-musl", i586_unknown_linux_musl),
1800 ("mips-unknown-linux-musl", mips_unknown_linux_musl),
1801 ("mipsel-unknown-linux-musl", mipsel_unknown_linux_musl),
1802 ("mips64-unknown-linux-muslabi64", mips64_unknown_linux_muslabi64),
1803 ("mips64el-unknown-linux-muslabi64", mips64el_unknown_linux_muslabi64),
1804 ("hexagon-unknown-linux-musl", hexagon_unknown_linux_musl),
1805 ("hexagon-unknown-none-elf", hexagon_unknown_none_elf),
1806
1807 ("mips-unknown-linux-uclibc", mips_unknown_linux_uclibc),
1808 ("mipsel-unknown-linux-uclibc", mipsel_unknown_linux_uclibc),
1809
1810 ("i686-linux-android", i686_linux_android),
1811 ("x86_64-linux-android", x86_64_linux_android),
1812 ("arm-linux-androideabi", arm_linux_androideabi),
1813 ("armv7-linux-androideabi", armv7_linux_androideabi),
1814 ("thumbv7neon-linux-androideabi", thumbv7neon_linux_androideabi),
1815 ("aarch64-linux-android", aarch64_linux_android),
1816 ("riscv64-linux-android", riscv64_linux_android),
1817
1818 ("aarch64-unknown-freebsd", aarch64_unknown_freebsd),
1819 ("armv6-unknown-freebsd", armv6_unknown_freebsd),
1820 ("armv7-unknown-freebsd", armv7_unknown_freebsd),
1821 ("i686-unknown-freebsd", i686_unknown_freebsd),
1822 ("powerpc-unknown-freebsd", powerpc_unknown_freebsd),
1823 ("powerpc64-unknown-freebsd", powerpc64_unknown_freebsd),
1824 ("powerpc64le-unknown-freebsd", powerpc64le_unknown_freebsd),
1825 ("riscv64gc-unknown-freebsd", riscv64gc_unknown_freebsd),
1826 ("x86_64-unknown-freebsd", x86_64_unknown_freebsd),
1827
1828 ("x86_64-unknown-dragonfly", x86_64_unknown_dragonfly),
1829
1830 ("aarch64-unknown-openbsd", aarch64_unknown_openbsd),
1831 ("i686-unknown-openbsd", i686_unknown_openbsd),
1832 ("powerpc-unknown-openbsd", powerpc_unknown_openbsd),
1833 ("powerpc64-unknown-openbsd", powerpc64_unknown_openbsd),
1834 ("riscv64gc-unknown-openbsd", riscv64gc_unknown_openbsd),
1835 ("sparc64-unknown-openbsd", sparc64_unknown_openbsd),
1836 ("x86_64-unknown-openbsd", x86_64_unknown_openbsd),
1837
1838 ("aarch64-unknown-netbsd", aarch64_unknown_netbsd),
1839 ("aarch64_be-unknown-netbsd", aarch64_be_unknown_netbsd),
1840 ("armv6-unknown-netbsd-eabihf", armv6_unknown_netbsd_eabihf),
1841 ("armv7-unknown-netbsd-eabihf", armv7_unknown_netbsd_eabihf),
1842 ("i586-unknown-netbsd", i586_unknown_netbsd),
1843 ("i686-unknown-netbsd", i686_unknown_netbsd),
1844 ("mipsel-unknown-netbsd", mipsel_unknown_netbsd),
1845 ("powerpc-unknown-netbsd", powerpc_unknown_netbsd),
1846 ("riscv64gc-unknown-netbsd", riscv64gc_unknown_netbsd),
1847 ("sparc64-unknown-netbsd", sparc64_unknown_netbsd),
1848 ("x86_64-unknown-netbsd", x86_64_unknown_netbsd),
1849
1850 ("i686-unknown-haiku", i686_unknown_haiku),
1851 ("x86_64-unknown-haiku", x86_64_unknown_haiku),
1852
1853 ("i686-unknown-hurd-gnu", i686_unknown_hurd_gnu),
1854 ("x86_64-unknown-hurd-gnu", x86_64_unknown_hurd_gnu),
1855
1856 ("aarch64-apple-darwin", aarch64_apple_darwin),
1857 ("arm64e-apple-darwin", arm64e_apple_darwin),
1858 ("x86_64-apple-darwin", x86_64_apple_darwin),
1859 ("x86_64h-apple-darwin", x86_64h_apple_darwin),
1860 ("i686-apple-darwin", i686_apple_darwin),
1861
1862 ("aarch64-unknown-fuchsia", aarch64_unknown_fuchsia),
1863 ("riscv64gc-unknown-fuchsia", riscv64gc_unknown_fuchsia),
1864 ("x86_64-unknown-fuchsia", x86_64_unknown_fuchsia),
1865
1866 ("avr-none", avr_none),
1867
1868 ("x86_64-unknown-l4re-uclibc", x86_64_unknown_l4re_uclibc),
1869
1870 ("aarch64-unknown-redox", aarch64_unknown_redox),
1871 ("i586-unknown-redox", i586_unknown_redox),
1872 ("x86_64-unknown-redox", x86_64_unknown_redox),
1873
1874 ("i386-apple-ios", i386_apple_ios),
1875 ("x86_64-apple-ios", x86_64_apple_ios),
1876 ("aarch64-apple-ios", aarch64_apple_ios),
1877 ("arm64e-apple-ios", arm64e_apple_ios),
1878 ("armv7s-apple-ios", armv7s_apple_ios),
1879 ("x86_64-apple-ios-macabi", x86_64_apple_ios_macabi),
1880 ("aarch64-apple-ios-macabi", aarch64_apple_ios_macabi),
1881 ("aarch64-apple-ios-sim", aarch64_apple_ios_sim),
1882
1883 ("aarch64-apple-tvos", aarch64_apple_tvos),
1884 ("aarch64-apple-tvos-sim", aarch64_apple_tvos_sim),
1885 ("arm64e-apple-tvos", arm64e_apple_tvos),
1886 ("x86_64-apple-tvos", x86_64_apple_tvos),
1887
1888 ("armv7k-apple-watchos", armv7k_apple_watchos),
1889 ("arm64_32-apple-watchos", arm64_32_apple_watchos),
1890 ("x86_64-apple-watchos-sim", x86_64_apple_watchos_sim),
1891 ("aarch64-apple-watchos", aarch64_apple_watchos),
1892 ("aarch64-apple-watchos-sim", aarch64_apple_watchos_sim),
1893
1894 ("aarch64-apple-visionos", aarch64_apple_visionos),
1895 ("aarch64-apple-visionos-sim", aarch64_apple_visionos_sim),
1896
1897 ("armebv7r-none-eabi", armebv7r_none_eabi),
1898 ("armebv7r-none-eabihf", armebv7r_none_eabihf),
1899 ("armv7r-none-eabi", armv7r_none_eabi),
1900 ("armv7r-none-eabihf", armv7r_none_eabihf),
1901 ("armv8r-none-eabihf", armv8r_none_eabihf),
1902
1903 ("armv7-rtems-eabihf", armv7_rtems_eabihf),
1904
1905 ("x86_64-pc-solaris", x86_64_pc_solaris),
1906 ("sparcv9-sun-solaris", sparcv9_sun_solaris),
1907
1908 ("x86_64-unknown-illumos", x86_64_unknown_illumos),
1909 ("aarch64-unknown-illumos", aarch64_unknown_illumos),
1910
1911 ("x86_64-pc-windows-gnu", x86_64_pc_windows_gnu),
1912 ("x86_64-uwp-windows-gnu", x86_64_uwp_windows_gnu),
1913 ("x86_64-win7-windows-gnu", x86_64_win7_windows_gnu),
1914 ("i686-pc-windows-gnu", i686_pc_windows_gnu),
1915 ("i686-uwp-windows-gnu", i686_uwp_windows_gnu),
1916 ("i686-win7-windows-gnu", i686_win7_windows_gnu),
1917
1918 ("aarch64-pc-windows-gnullvm", aarch64_pc_windows_gnullvm),
1919 ("i686-pc-windows-gnullvm", i686_pc_windows_gnullvm),
1920 ("x86_64-pc-windows-gnullvm", x86_64_pc_windows_gnullvm),
1921
1922 ("aarch64-pc-windows-msvc", aarch64_pc_windows_msvc),
1923 ("aarch64-uwp-windows-msvc", aarch64_uwp_windows_msvc),
1924 ("arm64ec-pc-windows-msvc", arm64ec_pc_windows_msvc),
1925 ("x86_64-pc-windows-msvc", x86_64_pc_windows_msvc),
1926 ("x86_64-uwp-windows-msvc", x86_64_uwp_windows_msvc),
1927 ("x86_64-win7-windows-msvc", x86_64_win7_windows_msvc),
1928 ("i686-pc-windows-msvc", i686_pc_windows_msvc),
1929 ("i686-uwp-windows-msvc", i686_uwp_windows_msvc),
1930 ("i686-win7-windows-msvc", i686_win7_windows_msvc),
1931 ("thumbv7a-pc-windows-msvc", thumbv7a_pc_windows_msvc),
1932 ("thumbv7a-uwp-windows-msvc", thumbv7a_uwp_windows_msvc),
1933
1934 ("wasm32-unknown-emscripten", wasm32_unknown_emscripten),
1935 ("wasm32-unknown-unknown", wasm32_unknown_unknown),
1936 ("wasm32v1-none", wasm32v1_none),
1937 ("wasm32-wasip1", wasm32_wasip1),
1938 ("wasm32-wasip2", wasm32_wasip2),
1939 ("wasm32-wasip1-threads", wasm32_wasip1_threads),
1940 ("wasm32-wali-linux-musl", wasm32_wali_linux_musl),
1941 ("wasm64-unknown-unknown", wasm64_unknown_unknown),
1942
1943 ("thumbv6m-none-eabi", thumbv6m_none_eabi),
1944 ("thumbv7m-none-eabi", thumbv7m_none_eabi),
1945 ("thumbv7em-none-eabi", thumbv7em_none_eabi),
1946 ("thumbv7em-none-eabihf", thumbv7em_none_eabihf),
1947 ("thumbv8m.base-none-eabi", thumbv8m_base_none_eabi),
1948 ("thumbv8m.main-none-eabi", thumbv8m_main_none_eabi),
1949 ("thumbv8m.main-none-eabihf", thumbv8m_main_none_eabihf),
1950
1951 ("armv7a-none-eabi", armv7a_none_eabi),
1952 ("armv7a-none-eabihf", armv7a_none_eabihf),
1953 ("armv7a-nuttx-eabi", armv7a_nuttx_eabi),
1954 ("armv7a-nuttx-eabihf", armv7a_nuttx_eabihf),
1955
1956 ("msp430-none-elf", msp430_none_elf),
1957
1958 ("aarch64-unknown-hermit", aarch64_unknown_hermit),
1959 ("riscv64gc-unknown-hermit", riscv64gc_unknown_hermit),
1960 ("x86_64-unknown-hermit", x86_64_unknown_hermit),
1961
1962 ("x86_64-unikraft-linux-musl", x86_64_unikraft_linux_musl),
1963
1964 ("armv7-unknown-trusty", armv7_unknown_trusty),
1965 ("aarch64-unknown-trusty", aarch64_unknown_trusty),
1966 ("x86_64-unknown-trusty", x86_64_unknown_trusty),
1967
1968 ("riscv32i-unknown-none-elf", riscv32i_unknown_none_elf),
1969 ("riscv32im-risc0-zkvm-elf", riscv32im_risc0_zkvm_elf),
1970 ("riscv32im-unknown-none-elf", riscv32im_unknown_none_elf),
1971 ("riscv32ima-unknown-none-elf", riscv32ima_unknown_none_elf),
1972 ("riscv32imc-unknown-none-elf", riscv32imc_unknown_none_elf),
1973 ("riscv32imc-esp-espidf", riscv32imc_esp_espidf),
1974 ("riscv32imac-esp-espidf", riscv32imac_esp_espidf),
1975 ("riscv32imafc-esp-espidf", riscv32imafc_esp_espidf),
1976
1977 ("riscv32e-unknown-none-elf", riscv32e_unknown_none_elf),
1978 ("riscv32em-unknown-none-elf", riscv32em_unknown_none_elf),
1979 ("riscv32emc-unknown-none-elf", riscv32emc_unknown_none_elf),
1980
1981 ("riscv32imac-unknown-none-elf", riscv32imac_unknown_none_elf),
1982 ("riscv32imafc-unknown-none-elf", riscv32imafc_unknown_none_elf),
1983 ("riscv32imac-unknown-xous-elf", riscv32imac_unknown_xous_elf),
1984 ("riscv32gc-unknown-linux-gnu", riscv32gc_unknown_linux_gnu),
1985 ("riscv32gc-unknown-linux-musl", riscv32gc_unknown_linux_musl),
1986 ("riscv64imac-unknown-none-elf", riscv64imac_unknown_none_elf),
1987 ("riscv64gc-unknown-none-elf", riscv64gc_unknown_none_elf),
1988 ("riscv64gc-unknown-linux-gnu", riscv64gc_unknown_linux_gnu),
1989 ("riscv64gc-unknown-linux-musl", riscv64gc_unknown_linux_musl),
1990
1991 ("sparc-unknown-none-elf", sparc_unknown_none_elf),
1992
1993 ("loongarch32-unknown-none", loongarch32_unknown_none),
1994 ("loongarch32-unknown-none-softfloat", loongarch32_unknown_none_softfloat),
1995 ("loongarch64-unknown-none", loongarch64_unknown_none),
1996 ("loongarch64-unknown-none-softfloat", loongarch64_unknown_none_softfloat),
1997
1998 ("aarch64-unknown-none", aarch64_unknown_none),
1999 ("aarch64-unknown-none-softfloat", aarch64_unknown_none_softfloat),
2000 ("aarch64-unknown-nuttx", aarch64_unknown_nuttx),
2001
2002 ("x86_64-fortanix-unknown-sgx", x86_64_fortanix_unknown_sgx),
2003
2004 ("x86_64-unknown-uefi", x86_64_unknown_uefi),
2005 ("i686-unknown-uefi", i686_unknown_uefi),
2006 ("aarch64-unknown-uefi", aarch64_unknown_uefi),
2007
2008 ("nvptx64-nvidia-cuda", nvptx64_nvidia_cuda),
2009
2010 ("amdgcn-amd-amdhsa", amdgcn_amd_amdhsa),
2011
2012 ("xtensa-esp32-none-elf", xtensa_esp32_none_elf),
2013 ("xtensa-esp32-espidf", xtensa_esp32_espidf),
2014 ("xtensa-esp32s2-none-elf", xtensa_esp32s2_none_elf),
2015 ("xtensa-esp32s2-espidf", xtensa_esp32s2_espidf),
2016 ("xtensa-esp32s3-none-elf", xtensa_esp32s3_none_elf),
2017 ("xtensa-esp32s3-espidf", xtensa_esp32s3_espidf),
2018
2019 ("i686-wrs-vxworks", i686_wrs_vxworks),
2020 ("x86_64-wrs-vxworks", x86_64_wrs_vxworks),
2021 ("armv7-wrs-vxworks-eabihf", armv7_wrs_vxworks_eabihf),
2022 ("aarch64-wrs-vxworks", aarch64_wrs_vxworks),
2023 ("powerpc-wrs-vxworks", powerpc_wrs_vxworks),
2024 ("powerpc-wrs-vxworks-spe", powerpc_wrs_vxworks_spe),
2025 ("powerpc64-wrs-vxworks", powerpc64_wrs_vxworks),
2026 ("riscv32-wrs-vxworks", riscv32_wrs_vxworks),
2027 ("riscv64-wrs-vxworks", riscv64_wrs_vxworks),
2028
2029 ("aarch64-kmc-solid_asp3", aarch64_kmc_solid_asp3),
2030 ("armv7a-kmc-solid_asp3-eabi", armv7a_kmc_solid_asp3_eabi),
2031 ("armv7a-kmc-solid_asp3-eabihf", armv7a_kmc_solid_asp3_eabihf),
2032
2033 ("mipsel-sony-psp", mipsel_sony_psp),
2034 ("mipsel-sony-psx", mipsel_sony_psx),
2035 ("mipsel-unknown-none", mipsel_unknown_none),
2036 ("mips-mti-none-elf", mips_mti_none_elf),
2037 ("mipsel-mti-none-elf", mipsel_mti_none_elf),
2038 ("thumbv4t-none-eabi", thumbv4t_none_eabi),
2039 ("armv4t-none-eabi", armv4t_none_eabi),
2040 ("thumbv5te-none-eabi", thumbv5te_none_eabi),
2041 ("armv5te-none-eabi", armv5te_none_eabi),
2042
2043 ("aarch64_be-unknown-linux-gnu", aarch64_be_unknown_linux_gnu),
2044 ("aarch64-unknown-linux-gnu_ilp32", aarch64_unknown_linux_gnu_ilp32),
2045 ("aarch64_be-unknown-linux-gnu_ilp32", aarch64_be_unknown_linux_gnu_ilp32),
2046
2047 ("bpfeb-unknown-none", bpfeb_unknown_none),
2048 ("bpfel-unknown-none", bpfel_unknown_none),
2049
2050 ("armv6k-nintendo-3ds", armv6k_nintendo_3ds),
2051
2052 ("aarch64-nintendo-switch-freestanding", aarch64_nintendo_switch_freestanding),
2053
2054 ("armv7-sony-vita-newlibeabihf", armv7_sony_vita_newlibeabihf),
2055
2056 ("armv7-unknown-linux-uclibceabi", armv7_unknown_linux_uclibceabi),
2057 ("armv7-unknown-linux-uclibceabihf", armv7_unknown_linux_uclibceabihf),
2058
2059 ("x86_64-unknown-none", x86_64_unknown_none),
2060
2061 ("aarch64-unknown-teeos", aarch64_unknown_teeos),
2062
2063 ("mips64-openwrt-linux-musl", mips64_openwrt_linux_musl),
2064
2065 ("aarch64-unknown-nto-qnx700", aarch64_unknown_nto_qnx700),
2066 ("aarch64-unknown-nto-qnx710", aarch64_unknown_nto_qnx710),
2067 ("aarch64-unknown-nto-qnx710_iosock", aarch64_unknown_nto_qnx710_iosock),
2068 ("aarch64-unknown-nto-qnx800", aarch64_unknown_nto_qnx800),
2069 ("x86_64-pc-nto-qnx710", x86_64_pc_nto_qnx710),
2070 ("x86_64-pc-nto-qnx710_iosock", x86_64_pc_nto_qnx710_iosock),
2071 ("x86_64-pc-nto-qnx800", x86_64_pc_nto_qnx800),
2072 ("i686-pc-nto-qnx700", i686_pc_nto_qnx700),
2073
2074 ("aarch64-unknown-linux-ohos", aarch64_unknown_linux_ohos),
2075 ("armv7-unknown-linux-ohos", armv7_unknown_linux_ohos),
2076 ("loongarch64-unknown-linux-ohos", loongarch64_unknown_linux_ohos),
2077 ("x86_64-unknown-linux-ohos", x86_64_unknown_linux_ohos),
2078
2079 ("x86_64-unknown-linux-none", x86_64_unknown_linux_none),
2080
2081 ("thumbv6m-nuttx-eabi", thumbv6m_nuttx_eabi),
2082 ("thumbv7a-nuttx-eabi", thumbv7a_nuttx_eabi),
2083 ("thumbv7a-nuttx-eabihf", thumbv7a_nuttx_eabihf),
2084 ("thumbv7m-nuttx-eabi", thumbv7m_nuttx_eabi),
2085 ("thumbv7em-nuttx-eabi", thumbv7em_nuttx_eabi),
2086 ("thumbv7em-nuttx-eabihf", thumbv7em_nuttx_eabihf),
2087 ("thumbv8m.base-nuttx-eabi", thumbv8m_base_nuttx_eabi),
2088 ("thumbv8m.main-nuttx-eabi", thumbv8m_main_nuttx_eabi),
2089 ("thumbv8m.main-nuttx-eabihf", thumbv8m_main_nuttx_eabihf),
2090 ("riscv32imc-unknown-nuttx-elf", riscv32imc_unknown_nuttx_elf),
2091 ("riscv32imac-unknown-nuttx-elf", riscv32imac_unknown_nuttx_elf),
2092 ("riscv32imafc-unknown-nuttx-elf", riscv32imafc_unknown_nuttx_elf),
2093 ("riscv64imac-unknown-nuttx-elf", riscv64imac_unknown_nuttx_elf),
2094 ("riscv64gc-unknown-nuttx-elf", riscv64gc_unknown_nuttx_elf),
2095 ("x86_64-lynx-lynxos178", x86_64_lynx_lynxos178),
2096
2097 ("x86_64-pc-cygwin", x86_64_pc_cygwin),
2098}
2099
2100macro_rules! cvs {
2102 () => {
2103 ::std::borrow::Cow::Borrowed(&[])
2104 };
2105 ($($x:expr),+ $(,)?) => {
2106 ::std::borrow::Cow::Borrowed(&[
2107 $(
2108 ::std::borrow::Cow::Borrowed($x),
2109 )*
2110 ])
2111 };
2112}
2113
2114pub(crate) use cvs;
2115
2116#[derive(Debug, PartialEq)]
2120pub struct TargetWarnings {
2121 unused_fields: Vec<String>,
2122 incorrect_type: Vec<String>,
2123}
2124
2125impl TargetWarnings {
2126 pub fn empty() -> Self {
2127 Self { unused_fields: Vec::new(), incorrect_type: Vec::new() }
2128 }
2129
2130 pub fn warning_messages(&self) -> Vec<String> {
2131 let mut warnings = vec![];
2132 if !self.unused_fields.is_empty() {
2133 warnings.push(format!(
2134 "target json file contains unused fields: {}",
2135 self.unused_fields.join(", ")
2136 ));
2137 }
2138 if !self.incorrect_type.is_empty() {
2139 warnings.push(format!(
2140 "target json file contains fields whose value doesn't have the correct json type: {}",
2141 self.incorrect_type.join(", ")
2142 ));
2143 }
2144 warnings
2145 }
2146}
2147
2148#[derive(Copy, Clone, Debug, PartialEq)]
2151enum TargetKind {
2152 Json,
2153 Builtin,
2154}
2155
2156#[derive(PartialEq, Clone, Debug)]
2160pub struct Target {
2161 pub llvm_target: StaticCow<str>,
2168 pub metadata: TargetMetadata,
2171 pub pointer_width: u32,
2173 pub arch: StaticCow<str>,
2176 pub data_layout: StaticCow<str>,
2178 pub options: TargetOptions,
2180}
2181
2182#[derive(Default, PartialEq, Clone, Debug)]
2186pub struct TargetMetadata {
2187 pub description: Option<StaticCow<str>>,
2190 pub tier: Option<u64>,
2192 pub host_tools: Option<bool>,
2194 pub std: Option<bool>,
2197}
2198
2199impl Target {
2200 pub fn parse_data_layout(&self) -> Result<TargetDataLayout, TargetDataLayoutErrors<'_>> {
2201 let mut dl = TargetDataLayout::parse_from_llvm_datalayout_string(
2202 &self.data_layout,
2203 self.options.default_address_space,
2204 )?;
2205
2206 if dl.endian != self.endian {
2208 return Err(TargetDataLayoutErrors::InconsistentTargetArchitecture {
2209 dl: dl.endian.as_str(),
2210 target: self.endian.as_str(),
2211 });
2212 }
2213
2214 let target_pointer_width: u64 = self.pointer_width.into();
2215 let dl_pointer_size: u64 = dl.pointer_size().bits();
2216 if dl_pointer_size != target_pointer_width {
2217 return Err(TargetDataLayoutErrors::InconsistentTargetPointerWidth {
2218 pointer_size: dl_pointer_size,
2219 target: self.pointer_width,
2220 });
2221 }
2222
2223 dl.c_enum_min_size = Integer::from_size(Size::from_bits(
2224 self.c_enum_min_bits.unwrap_or(self.c_int_width as _),
2225 ))
2226 .map_err(|err| TargetDataLayoutErrors::InvalidBitsSize { err })?;
2227
2228 Ok(dl)
2229 }
2230}
2231
2232pub trait HasTargetSpec {
2233 fn target_spec(&self) -> &Target;
2234}
2235
2236impl HasTargetSpec for Target {
2237 #[inline]
2238 fn target_spec(&self) -> &Target {
2239 self
2240 }
2241}
2242
2243#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
2245pub struct X86Abi {
2246 pub regparm: Option<u32>,
2249 pub reg_struct_return: bool,
2251}
2252
2253pub trait HasX86AbiOpt {
2254 fn x86_abi_opt(&self) -> X86Abi;
2255}
2256
2257type StaticCow<T> = Cow<'static, T>;
2258
2259#[derive(PartialEq, Clone, Debug)]
2268pub struct TargetOptions {
2269 pub endian: Endian,
2271 pub c_int_width: u16,
2273 pub os: StaticCow<str>,
2278 pub env: StaticCow<str>,
2280 pub abi: StaticCow<str>,
2285 pub vendor: StaticCow<str>,
2287
2288 pub linker: Option<StaticCow<str>>,
2290 pub linker_flavor: LinkerFlavor,
2293 linker_flavor_json: LinkerFlavorCli,
2294 lld_flavor_json: LldFlavor,
2295 linker_is_gnu_json: bool,
2296
2297 pub pre_link_objects: CrtObjects,
2299 pub post_link_objects: CrtObjects,
2300 pub pre_link_objects_self_contained: CrtObjects,
2302 pub post_link_objects_self_contained: CrtObjects,
2303 pub link_self_contained: LinkSelfContainedDefault,
2306
2307 pub pre_link_args: LinkArgs,
2309 pre_link_args_json: LinkArgsCli,
2310 pub late_link_args: LinkArgs,
2314 late_link_args_json: LinkArgsCli,
2315 pub late_link_args_dynamic: LinkArgs,
2318 late_link_args_dynamic_json: LinkArgsCli,
2319 pub late_link_args_static: LinkArgs,
2322 late_link_args_static_json: LinkArgsCli,
2323 pub post_link_args: LinkArgs,
2326 post_link_args_json: LinkArgsCli,
2327
2328 pub link_script: Option<StaticCow<str>>,
2332 pub link_env: StaticCow<[(StaticCow<str>, StaticCow<str>)]>,
2334 pub link_env_remove: StaticCow<[StaticCow<str>]>,
2336
2337 pub asm_args: StaticCow<[StaticCow<str>]>,
2339
2340 pub cpu: StaticCow<str>,
2343 pub need_explicit_cpu: bool,
2346 pub features: StaticCow<str>,
2355 pub direct_access_external_data: Option<bool>,
2357 pub dynamic_linking: bool,
2359 pub dll_tls_export: bool,
2361 pub only_cdylib: bool,
2363 pub executables: bool,
2365 pub relocation_model: RelocModel,
2368 pub code_model: Option<CodeModel>,
2371 pub tls_model: TlsModel,
2374 pub disable_redzone: bool,
2376 pub frame_pointer: FramePointer,
2378 pub function_sections: bool,
2380 pub dll_prefix: StaticCow<str>,
2382 pub dll_suffix: StaticCow<str>,
2384 pub exe_suffix: StaticCow<str>,
2386 pub staticlib_prefix: StaticCow<str>,
2388 pub staticlib_suffix: StaticCow<str>,
2390 pub families: StaticCow<[StaticCow<str>]>,
2396 pub abi_return_struct_as_int: bool,
2398 pub is_like_aix: bool,
2401 pub is_like_darwin: bool,
2406 pub is_like_solaris: bool,
2410 pub is_like_windows: bool,
2418 pub is_like_msvc: bool,
2428 pub is_like_wasm: bool,
2430 pub is_like_android: bool,
2432 pub binary_format: BinaryFormat,
2434 pub default_dwarf_version: u32,
2437 pub allows_weak_linkage: bool,
2444 pub has_rpath: bool,
2446 pub no_default_libraries: bool,
2449 pub position_independent_executables: bool,
2455 pub static_position_independent_executables: bool,
2457 pub plt_by_default: bool,
2460 pub relro_level: RelroLevel,
2464 pub archive_format: StaticCow<str>,
2469 pub allow_asm: bool,
2471 pub main_needs_argc_argv: bool,
2474
2475 pub has_thread_local: bool,
2477 pub obj_is_bitcode: bool,
2481 pub bitcode_llvm_cmdline: StaticCow<str>,
2483
2484 pub min_atomic_width: Option<u64>,
2486
2487 pub max_atomic_width: Option<u64>,
2489
2490 pub atomic_cas: bool,
2492
2493 pub panic_strategy: PanicStrategy,
2495
2496 pub crt_static_allows_dylibs: bool,
2498 pub crt_static_default: bool,
2500 pub crt_static_respected: bool,
2502
2503 pub stack_probes: StackProbeType,
2505
2506 pub min_global_align: Option<Align>,
2508
2509 pub default_codegen_units: Option<u64>,
2511
2512 pub default_codegen_backend: Option<StaticCow<str>>,
2522
2523 pub trap_unreachable: bool,
2526
2527 pub requires_lto: bool,
2530
2531 pub singlethread: bool,
2533
2534 pub no_builtins: bool,
2537
2538 pub default_visibility: Option<SymbolVisibility>,
2544
2545 pub emit_debug_gdb_scripts: bool,
2547
2548 pub requires_uwtable: bool,
2552
2553 pub default_uwtable: bool,
2556
2557 pub simd_types_indirect: bool,
2562
2563 pub limit_rdylib_exports: bool,
2565
2566 pub override_export_symbols: Option<StaticCow<[StaticCow<str>]>>,
2569
2570 pub merge_functions: MergeFunctions,
2577
2578 pub mcount: StaticCow<str>,
2580
2581 pub llvm_mcount_intrinsic: Option<StaticCow<str>>,
2583
2584 pub llvm_abiname: StaticCow<str>,
2587
2588 pub llvm_floatabi: Option<FloatAbi>,
2595
2596 pub rustc_abi: Option<RustcAbi>,
2601
2602 pub relax_elf_relocations: bool,
2604
2605 pub llvm_args: StaticCow<[StaticCow<str>]>,
2607
2608 pub use_ctors_section: bool,
2611
2612 pub eh_frame_header: bool,
2616
2617 pub has_thumb_interworking: bool,
2620
2621 pub debuginfo_kind: DebuginfoKind,
2623 pub split_debuginfo: SplitDebuginfo,
2626 pub supported_split_debuginfo: StaticCow<[SplitDebuginfo]>,
2628
2629 pub supported_sanitizers: SanitizerSet,
2635
2636 pub c_enum_min_bits: Option<u64>,
2638
2639 pub generate_arange_section: bool,
2641
2642 pub supports_stack_protector: bool,
2645
2646 pub entry_name: StaticCow<str>,
2649
2650 pub entry_abi: CanonAbi,
2653
2654 pub supports_xray: bool,
2656
2657 pub default_address_space: rustc_abi::AddressSpace,
2661
2662 small_data_threshold_support: SmallDataThresholdSupport,
2664}
2665
2666fn add_link_args_iter(
2669 link_args: &mut LinkArgs,
2670 flavor: LinkerFlavor,
2671 args: impl Iterator<Item = StaticCow<str>> + Clone,
2672) {
2673 let mut insert = |flavor| link_args.entry(flavor).or_default().extend(args.clone());
2674 insert(flavor);
2675 match flavor {
2676 LinkerFlavor::Gnu(cc, lld) => {
2677 assert_eq!(lld, Lld::No);
2678 insert(LinkerFlavor::Gnu(cc, Lld::Yes));
2679 }
2680 LinkerFlavor::Darwin(cc, lld) => {
2681 assert_eq!(lld, Lld::No);
2682 insert(LinkerFlavor::Darwin(cc, Lld::Yes));
2683 }
2684 LinkerFlavor::Msvc(lld) => {
2685 assert_eq!(lld, Lld::No);
2686 insert(LinkerFlavor::Msvc(Lld::Yes));
2687 }
2688 LinkerFlavor::WasmLld(..)
2689 | LinkerFlavor::Unix(..)
2690 | LinkerFlavor::EmCc
2691 | LinkerFlavor::Bpf
2692 | LinkerFlavor::Llbc
2693 | LinkerFlavor::Ptx => {}
2694 }
2695}
2696
2697fn add_link_args(link_args: &mut LinkArgs, flavor: LinkerFlavor, args: &[&'static str]) {
2698 add_link_args_iter(link_args, flavor, args.iter().copied().map(Cow::Borrowed))
2699}
2700
2701impl TargetOptions {
2702 pub fn supports_comdat(&self) -> bool {
2703 !self.is_like_aix && !self.is_like_darwin
2705 }
2706}
2707
2708impl TargetOptions {
2709 fn link_args(flavor: LinkerFlavor, args: &[&'static str]) -> LinkArgs {
2710 let mut link_args = LinkArgs::new();
2711 add_link_args(&mut link_args, flavor, args);
2712 link_args
2713 }
2714
2715 fn add_pre_link_args(&mut self, flavor: LinkerFlavor, args: &[&'static str]) {
2716 add_link_args(&mut self.pre_link_args, flavor, args);
2717 }
2718
2719 fn update_from_cli(&mut self) {
2720 self.linker_flavor = LinkerFlavor::from_cli_json(
2721 self.linker_flavor_json,
2722 self.lld_flavor_json,
2723 self.linker_is_gnu_json,
2724 );
2725 for (args, args_json) in [
2726 (&mut self.pre_link_args, &self.pre_link_args_json),
2727 (&mut self.late_link_args, &self.late_link_args_json),
2728 (&mut self.late_link_args_dynamic, &self.late_link_args_dynamic_json),
2729 (&mut self.late_link_args_static, &self.late_link_args_static_json),
2730 (&mut self.post_link_args, &self.post_link_args_json),
2731 ] {
2732 args.clear();
2733 for (flavor, args_json) in args_json {
2734 let linker_flavor = self.linker_flavor.with_cli_hints(*flavor);
2735 let linker_flavor = match linker_flavor {
2737 LinkerFlavor::Gnu(cc, _) => LinkerFlavor::Gnu(cc, Lld::No),
2738 LinkerFlavor::Darwin(cc, _) => LinkerFlavor::Darwin(cc, Lld::No),
2739 LinkerFlavor::Msvc(_) => LinkerFlavor::Msvc(Lld::No),
2740 _ => linker_flavor,
2741 };
2742 if !args.contains_key(&linker_flavor) {
2743 add_link_args_iter(args, linker_flavor, args_json.iter().cloned());
2744 }
2745 }
2746 }
2747 }
2748
2749 fn update_to_cli(&mut self) {
2750 self.linker_flavor_json = self.linker_flavor.to_cli_counterpart();
2751 self.lld_flavor_json = self.linker_flavor.lld_flavor();
2752 self.linker_is_gnu_json = self.linker_flavor.is_gnu();
2753 for (args, args_json) in [
2754 (&self.pre_link_args, &mut self.pre_link_args_json),
2755 (&self.late_link_args, &mut self.late_link_args_json),
2756 (&self.late_link_args_dynamic, &mut self.late_link_args_dynamic_json),
2757 (&self.late_link_args_static, &mut self.late_link_args_static_json),
2758 (&self.post_link_args, &mut self.post_link_args_json),
2759 ] {
2760 *args_json = args
2761 .iter()
2762 .map(|(flavor, args)| (flavor.to_cli_counterpart(), args.clone()))
2763 .collect();
2764 }
2765 }
2766}
2767
2768impl Default for TargetOptions {
2769 fn default() -> TargetOptions {
2772 TargetOptions {
2773 endian: Endian::Little,
2774 c_int_width: 32,
2775 os: "none".into(),
2776 env: "".into(),
2777 abi: "".into(),
2778 vendor: "unknown".into(),
2779 linker: option_env!("CFG_DEFAULT_LINKER").map(|s| s.into()),
2780 linker_flavor: LinkerFlavor::Gnu(Cc::Yes, Lld::No),
2781 linker_flavor_json: LinkerFlavorCli::Gcc,
2782 lld_flavor_json: LldFlavor::Ld,
2783 linker_is_gnu_json: true,
2784 link_script: None,
2785 asm_args: cvs![],
2786 cpu: "generic".into(),
2787 need_explicit_cpu: false,
2788 features: "".into(),
2789 direct_access_external_data: None,
2790 dynamic_linking: false,
2791 dll_tls_export: true,
2792 only_cdylib: false,
2793 executables: true,
2794 relocation_model: RelocModel::Pic,
2795 code_model: None,
2796 tls_model: TlsModel::GeneralDynamic,
2797 disable_redzone: false,
2798 frame_pointer: FramePointer::MayOmit,
2799 function_sections: true,
2800 dll_prefix: "lib".into(),
2801 dll_suffix: ".so".into(),
2802 exe_suffix: "".into(),
2803 staticlib_prefix: "lib".into(),
2804 staticlib_suffix: ".a".into(),
2805 families: cvs![],
2806 abi_return_struct_as_int: false,
2807 is_like_aix: false,
2808 is_like_darwin: false,
2809 is_like_solaris: false,
2810 is_like_windows: false,
2811 is_like_msvc: false,
2812 is_like_wasm: false,
2813 is_like_android: false,
2814 binary_format: BinaryFormat::Elf,
2815 default_dwarf_version: 4,
2816 allows_weak_linkage: true,
2817 has_rpath: false,
2818 no_default_libraries: true,
2819 position_independent_executables: false,
2820 static_position_independent_executables: false,
2821 plt_by_default: true,
2822 relro_level: RelroLevel::None,
2823 pre_link_objects: Default::default(),
2824 post_link_objects: Default::default(),
2825 pre_link_objects_self_contained: Default::default(),
2826 post_link_objects_self_contained: Default::default(),
2827 link_self_contained: LinkSelfContainedDefault::False,
2828 pre_link_args: LinkArgs::new(),
2829 pre_link_args_json: LinkArgsCli::new(),
2830 late_link_args: LinkArgs::new(),
2831 late_link_args_json: LinkArgsCli::new(),
2832 late_link_args_dynamic: LinkArgs::new(),
2833 late_link_args_dynamic_json: LinkArgsCli::new(),
2834 late_link_args_static: LinkArgs::new(),
2835 late_link_args_static_json: LinkArgsCli::new(),
2836 post_link_args: LinkArgs::new(),
2837 post_link_args_json: LinkArgsCli::new(),
2838 link_env: cvs![],
2839 link_env_remove: cvs![],
2840 archive_format: "gnu".into(),
2841 main_needs_argc_argv: true,
2842 allow_asm: true,
2843 has_thread_local: false,
2844 obj_is_bitcode: false,
2845 bitcode_llvm_cmdline: "".into(),
2846 min_atomic_width: None,
2847 max_atomic_width: None,
2848 atomic_cas: true,
2849 panic_strategy: PanicStrategy::Unwind,
2850 crt_static_allows_dylibs: false,
2851 crt_static_default: false,
2852 crt_static_respected: false,
2853 stack_probes: StackProbeType::None,
2854 min_global_align: None,
2855 default_codegen_units: None,
2856 default_codegen_backend: None,
2857 trap_unreachable: true,
2858 requires_lto: false,
2859 singlethread: false,
2860 no_builtins: false,
2861 default_visibility: None,
2862 emit_debug_gdb_scripts: true,
2863 requires_uwtable: false,
2864 default_uwtable: false,
2865 simd_types_indirect: true,
2866 limit_rdylib_exports: true,
2867 override_export_symbols: None,
2868 merge_functions: MergeFunctions::Aliases,
2869 mcount: "mcount".into(),
2870 llvm_mcount_intrinsic: None,
2871 llvm_abiname: "".into(),
2872 llvm_floatabi: None,
2873 rustc_abi: None,
2874 relax_elf_relocations: false,
2875 llvm_args: cvs![],
2876 use_ctors_section: false,
2877 eh_frame_header: true,
2878 has_thumb_interworking: false,
2879 debuginfo_kind: Default::default(),
2880 split_debuginfo: Default::default(),
2881 supported_split_debuginfo: Cow::Borrowed(&[SplitDebuginfo::Off]),
2883 supported_sanitizers: SanitizerSet::empty(),
2884 c_enum_min_bits: None,
2885 generate_arange_section: true,
2886 supports_stack_protector: true,
2887 entry_name: "main".into(),
2888 entry_abi: CanonAbi::C,
2889 supports_xray: false,
2890 default_address_space: rustc_abi::AddressSpace::ZERO,
2891 small_data_threshold_support: SmallDataThresholdSupport::DefaultForArch,
2892 }
2893 }
2894}
2895
2896impl Deref for Target {
2900 type Target = TargetOptions;
2901
2902 #[inline]
2903 fn deref(&self) -> &Self::Target {
2904 &self.options
2905 }
2906}
2907impl DerefMut for Target {
2908 #[inline]
2909 fn deref_mut(&mut self) -> &mut Self::Target {
2910 &mut self.options
2911 }
2912}
2913
2914impl Target {
2915 pub fn is_abi_supported(&self, abi: ExternAbi) -> bool {
2916 let abi_map = AbiMap::from_target(self);
2917 abi_map.canonize_abi(abi, false).is_mapped()
2918 }
2919
2920 pub fn min_atomic_width(&self) -> u64 {
2923 self.min_atomic_width.unwrap_or(8)
2924 }
2925
2926 pub fn max_atomic_width(&self) -> u64 {
2929 self.max_atomic_width.unwrap_or_else(|| self.pointer_width.into())
2930 }
2931
2932 fn check_consistency(&self, kind: TargetKind) -> Result<(), String> {
2935 macro_rules! check {
2936 ($b:expr, $($msg:tt)*) => {
2937 if !$b {
2938 return Err(format!($($msg)*));
2939 }
2940 }
2941 }
2942 macro_rules! check_eq {
2943 ($left:expr, $right:expr, $($msg:tt)*) => {
2944 if ($left) != ($right) {
2945 return Err(format!($($msg)*));
2946 }
2947 }
2948 }
2949 macro_rules! check_ne {
2950 ($left:expr, $right:expr, $($msg:tt)*) => {
2951 if ($left) == ($right) {
2952 return Err(format!($($msg)*));
2953 }
2954 }
2955 }
2956 macro_rules! check_matches {
2957 ($left:expr, $right:pat, $($msg:tt)*) => {
2958 if !matches!($left, $right) {
2959 return Err(format!($($msg)*));
2960 }
2961 }
2962 }
2963
2964 check_eq!(
2965 self.is_like_darwin,
2966 self.vendor == "apple",
2967 "`is_like_darwin` must be set if and only if `vendor` is `apple`"
2968 );
2969 check_eq!(
2970 self.is_like_solaris,
2971 self.os == "solaris" || self.os == "illumos",
2972 "`is_like_solaris` must be set if and only if `os` is `solaris` or `illumos`"
2973 );
2974 check_eq!(
2975 self.is_like_windows,
2976 self.os == "windows" || self.os == "uefi" || self.os == "cygwin",
2977 "`is_like_windows` must be set if and only if `os` is `windows`, `uefi` or `cygwin`"
2978 );
2979 check_eq!(
2980 self.is_like_wasm,
2981 self.arch == "wasm32" || self.arch == "wasm64",
2982 "`is_like_wasm` must be set if and only if `arch` is `wasm32` or `wasm64`"
2983 );
2984 if self.is_like_msvc {
2985 check!(self.is_like_windows, "if `is_like_msvc` is set, `is_like_windows` must be set");
2986 }
2987 if self.os == "emscripten" {
2988 check!(self.is_like_wasm, "the `emcscripten` os only makes sense on wasm-like targets");
2989 }
2990
2991 check_eq!(
2993 self.is_like_darwin,
2994 matches!(self.linker_flavor, LinkerFlavor::Darwin(..)),
2995 "`linker_flavor` must be `darwin` if and only if `is_like_darwin` is set"
2996 );
2997 check_eq!(
2998 self.is_like_msvc,
2999 matches!(self.linker_flavor, LinkerFlavor::Msvc(..)),
3000 "`linker_flavor` must be `msvc` if and only if `is_like_msvc` is set"
3001 );
3002 check_eq!(
3003 self.is_like_wasm && self.os != "emscripten",
3004 matches!(self.linker_flavor, LinkerFlavor::WasmLld(..)),
3005 "`linker_flavor` must be `wasm-lld` if and only if `is_like_wasm` is set and the `os` is not `emscripten`",
3006 );
3007 check_eq!(
3008 self.os == "emscripten",
3009 matches!(self.linker_flavor, LinkerFlavor::EmCc),
3010 "`linker_flavor` must be `em-cc` if and only if `os` is `emscripten`"
3011 );
3012 check_eq!(
3013 self.arch == "bpf",
3014 matches!(self.linker_flavor, LinkerFlavor::Bpf),
3015 "`linker_flavor` must be `bpf` if and only if `arch` is `bpf`"
3016 );
3017 check_eq!(
3018 self.arch == "nvptx64",
3019 matches!(self.linker_flavor, LinkerFlavor::Ptx),
3020 "`linker_flavor` must be `ptc` if and only if `arch` is `nvptx64`"
3021 );
3022
3023 for args in [
3024 &self.pre_link_args,
3025 &self.late_link_args,
3026 &self.late_link_args_dynamic,
3027 &self.late_link_args_static,
3028 &self.post_link_args,
3029 ] {
3030 for (&flavor, flavor_args) in args {
3031 check!(
3032 !flavor_args.is_empty() || self.arch == "avr",
3033 "linker flavor args must not be empty"
3034 );
3035 match self.linker_flavor {
3037 LinkerFlavor::Gnu(..) => {
3038 check_matches!(
3039 flavor,
3040 LinkerFlavor::Gnu(..),
3041 "mixing GNU and non-GNU linker flavors"
3042 );
3043 }
3044 LinkerFlavor::Darwin(..) => {
3045 check_matches!(
3046 flavor,
3047 LinkerFlavor::Darwin(..),
3048 "mixing Darwin and non-Darwin linker flavors"
3049 )
3050 }
3051 LinkerFlavor::WasmLld(..) => {
3052 check_matches!(
3053 flavor,
3054 LinkerFlavor::WasmLld(..),
3055 "mixing wasm and non-wasm linker flavors"
3056 )
3057 }
3058 LinkerFlavor::Unix(..) => {
3059 check_matches!(
3060 flavor,
3061 LinkerFlavor::Unix(..),
3062 "mixing unix and non-unix linker flavors"
3063 );
3064 }
3065 LinkerFlavor::Msvc(..) => {
3066 check_matches!(
3067 flavor,
3068 LinkerFlavor::Msvc(..),
3069 "mixing MSVC and non-MSVC linker flavors"
3070 );
3071 }
3072 LinkerFlavor::EmCc
3073 | LinkerFlavor::Bpf
3074 | LinkerFlavor::Ptx
3075 | LinkerFlavor::Llbc => {
3076 check_eq!(flavor, self.linker_flavor, "mixing different linker flavors")
3077 }
3078 }
3079
3080 let check_noncc = |noncc_flavor| -> Result<(), String> {
3082 if let Some(noncc_args) = args.get(&noncc_flavor) {
3083 for arg in flavor_args {
3084 if let Some(suffix) = arg.strip_prefix("-Wl,") {
3085 check!(
3086 noncc_args.iter().any(|a| a == suffix),
3087 " link args for cc and non-cc versions of flavors are not consistent"
3088 );
3089 }
3090 }
3091 }
3092 Ok(())
3093 };
3094
3095 match self.linker_flavor {
3096 LinkerFlavor::Gnu(Cc::Yes, lld) => check_noncc(LinkerFlavor::Gnu(Cc::No, lld))?,
3097 LinkerFlavor::WasmLld(Cc::Yes) => check_noncc(LinkerFlavor::WasmLld(Cc::No))?,
3098 LinkerFlavor::Unix(Cc::Yes) => check_noncc(LinkerFlavor::Unix(Cc::No))?,
3099 _ => {}
3100 }
3101 }
3102
3103 for cc in [Cc::No, Cc::Yes] {
3105 check_eq!(
3106 args.get(&LinkerFlavor::Gnu(cc, Lld::No)),
3107 args.get(&LinkerFlavor::Gnu(cc, Lld::Yes)),
3108 "link args for lld and non-lld versions of flavors are not consistent",
3109 );
3110 check_eq!(
3111 args.get(&LinkerFlavor::Darwin(cc, Lld::No)),
3112 args.get(&LinkerFlavor::Darwin(cc, Lld::Yes)),
3113 "link args for lld and non-lld versions of flavors are not consistent",
3114 );
3115 }
3116 check_eq!(
3117 args.get(&LinkerFlavor::Msvc(Lld::No)),
3118 args.get(&LinkerFlavor::Msvc(Lld::Yes)),
3119 "link args for lld and non-lld versions of flavors are not consistent",
3120 );
3121 }
3122
3123 if self.link_self_contained.is_disabled() {
3124 check!(
3125 self.pre_link_objects_self_contained.is_empty()
3126 && self.post_link_objects_self_contained.is_empty(),
3127 "if `link_self_contained` is disabled, then `pre_link_objects_self_contained` and `post_link_objects_self_contained` must be empty",
3128 );
3129 }
3130
3131 check_ne!(self.vendor, "", "`vendor` cannot be empty");
3135 check_ne!(self.os, "", "`os` cannot be empty");
3136 if !self.can_use_os_unknown() {
3137 check_ne!(
3139 self.os,
3140 "unknown",
3141 "`unknown` os can only be used on particular targets; use `none` for bare-metal targets"
3142 );
3143 }
3144
3145 if kind == TargetKind::Builtin {
3151 if self.os == "none"
3155 && (self.arch != "bpf"
3156 && self.arch != "hexagon"
3157 && self.arch != "wasm32"
3158 && self.arch != "wasm64")
3159 {
3160 check!(
3161 !self.dynamic_linking,
3162 "dynamic linking is not supported on this OS/architecture"
3163 );
3164 }
3165 if self.only_cdylib
3166 || self.crt_static_allows_dylibs
3167 || !self.late_link_args_dynamic.is_empty()
3168 {
3169 check!(
3170 self.dynamic_linking,
3171 "dynamic linking must be allowed when `only_cdylib` or `crt_static_allows_dylibs` or `late_link_args_dynamic` are set"
3172 );
3173 }
3174 if self.dynamic_linking && !self.is_like_wasm {
3176 check_eq!(
3177 self.relocation_model,
3178 RelocModel::Pic,
3179 "targets that support dynamic linking must use the `pic` relocation model"
3180 );
3181 }
3182 if self.position_independent_executables {
3183 check_eq!(
3184 self.relocation_model,
3185 RelocModel::Pic,
3186 "targets that support position-independent executables must use the `pic` relocation model"
3187 );
3188 }
3189 if self.relocation_model == RelocModel::Pic && (self.os != "uefi") {
3191 check!(
3192 self.dynamic_linking || self.position_independent_executables,
3193 "when the relocation model is `pic`, the target must support dynamic linking or use position-independent executables. \
3194 Set the relocation model to `static` to avoid this requirement"
3195 );
3196 }
3197 if self.static_position_independent_executables {
3198 check!(
3199 self.position_independent_executables,
3200 "if `static_position_independent_executables` is set, then `position_independent_executables` must be set"
3201 );
3202 }
3203 if self.position_independent_executables {
3204 check!(
3205 self.executables,
3206 "if `position_independent_executables` is set then `executables` must be set"
3207 );
3208 }
3209 }
3210
3211 if self.crt_static_default || self.crt_static_allows_dylibs {
3213 check!(
3214 self.crt_static_respected,
3215 "static CRT can be enabled but `crt_static_respected` is not set"
3216 );
3217 }
3218
3219 match &*self.arch {
3222 "riscv32" => {
3223 check_matches!(
3224 &*self.llvm_abiname,
3225 "ilp32" | "ilp32f" | "ilp32d" | "ilp32e",
3226 "invalid RISC-V ABI name: {}",
3227 self.llvm_abiname,
3228 );
3229 }
3230 "riscv64" => {
3231 check_matches!(
3233 &*self.llvm_abiname,
3234 "lp64" | "lp64f" | "lp64d" | "lp64e",
3235 "invalid RISC-V ABI name: {}",
3236 self.llvm_abiname,
3237 );
3238 }
3239 "arm" => {
3240 check!(
3241 self.llvm_floatabi.is_some(),
3242 "ARM targets must set `llvm-floatabi` to `hard` or `soft`",
3243 )
3244 }
3245 _ => {}
3246 }
3247
3248 if let Some(rust_abi) = self.rustc_abi {
3250 match rust_abi {
3251 RustcAbi::X86Sse2 => check_matches!(
3252 &*self.arch,
3253 "x86",
3254 "`x86-sse2` ABI is only valid for x86-32 targets"
3255 ),
3256 RustcAbi::X86Softfloat => check_matches!(
3257 &*self.arch,
3258 "x86" | "x86_64",
3259 "`x86-softfloat` ABI is only valid for x86 targets"
3260 ),
3261 }
3262 }
3263
3264 if !self.features.is_empty() {
3266 let mut features_enabled = FxHashSet::default();
3267 let mut features_disabled = FxHashSet::default();
3268 for feat in self.features.split(',') {
3269 if let Some(feat) = feat.strip_prefix("+") {
3270 features_enabled.insert(feat);
3271 if features_disabled.contains(feat) {
3272 return Err(format!(
3273 "target feature `{feat}` is both enabled and disabled"
3274 ));
3275 }
3276 } else if let Some(feat) = feat.strip_prefix("-") {
3277 features_disabled.insert(feat);
3278 if features_enabled.contains(feat) {
3279 return Err(format!(
3280 "target feature `{feat}` is both enabled and disabled"
3281 ));
3282 }
3283 } else {
3284 return Err(format!(
3285 "target feature `{feat}` is invalid, must start with `+` or `-`"
3286 ));
3287 }
3288 }
3289 let abi_feature_constraints = self.abi_required_features();
3291 for feat in abi_feature_constraints.required {
3292 if features_disabled.contains(feat) {
3295 return Err(format!(
3296 "target feature `{feat}` is required by the ABI but gets disabled in target spec"
3297 ));
3298 }
3299 }
3300 for feat in abi_feature_constraints.incompatible {
3301 if features_enabled.contains(feat) {
3304 return Err(format!(
3305 "target feature `{feat}` is incompatible with the ABI but gets enabled in target spec"
3306 ));
3307 }
3308 }
3309 }
3310
3311 Ok(())
3312 }
3313
3314 #[cfg(test)]
3316 fn test_target(mut self) {
3317 let recycled_target = Target::from_json(self.to_json()).map(|(j, _)| j);
3318 self.update_to_cli();
3319 self.check_consistency(TargetKind::Builtin).unwrap();
3320 assert_eq!(recycled_target, Ok(self));
3321 }
3322
3323 fn can_use_os_unknown(&self) -> bool {
3326 self.llvm_target == "wasm32-unknown-unknown"
3327 || self.llvm_target == "wasm64-unknown-unknown"
3328 || (self.env == "sgx" && self.vendor == "fortanix")
3329 }
3330
3331 pub fn expect_builtin(target_tuple: &TargetTuple) -> Target {
3333 match *target_tuple {
3334 TargetTuple::TargetTuple(ref target_tuple) => {
3335 load_builtin(target_tuple).expect("built-in target")
3336 }
3337 TargetTuple::TargetJson { .. } => {
3338 panic!("built-in targets doesn't support target-paths")
3339 }
3340 }
3341 }
3342
3343 pub fn builtins() -> impl Iterator<Item = Target> {
3345 load_all_builtins()
3346 }
3347
3348 pub fn search(
3358 target_tuple: &TargetTuple,
3359 sysroot: &Path,
3360 ) -> Result<(Target, TargetWarnings), String> {
3361 use std::{env, fs};
3362
3363 fn load_file(path: &Path) -> Result<(Target, TargetWarnings), String> {
3364 let contents = fs::read_to_string(path).map_err(|e| e.to_string())?;
3365 let obj = serde_json::from_str(&contents).map_err(|e| e.to_string())?;
3366 Target::from_json(obj)
3367 }
3368
3369 match *target_tuple {
3370 TargetTuple::TargetTuple(ref target_tuple) => {
3371 if let Some(t) = load_builtin(target_tuple) {
3373 return Ok((t, TargetWarnings::empty()));
3374 }
3375
3376 let path = {
3378 let mut target = target_tuple.to_string();
3379 target.push_str(".json");
3380 PathBuf::from(target)
3381 };
3382
3383 let target_path = env::var_os("RUST_TARGET_PATH").unwrap_or_default();
3384
3385 for dir in env::split_paths(&target_path) {
3386 let p = dir.join(&path);
3387 if p.is_file() {
3388 return load_file(&p);
3389 }
3390 }
3391
3392 let rustlib_path = crate::relative_target_rustlib_path(sysroot, target_tuple);
3395 let p = PathBuf::from_iter([
3396 Path::new(sysroot),
3397 Path::new(&rustlib_path),
3398 Path::new("target.json"),
3399 ]);
3400 if p.is_file() {
3401 return load_file(&p);
3402 }
3403
3404 if target_tuple == "i586-pc-windows-msvc" {
3408 Err("the `i586-pc-windows-msvc` target has been removed. Use the `i686-pc-windows-msvc` target instead.\n\
3409 Windows 10 (the minimum required OS version) requires a CPU baseline of at least i686 so you can safely switch".into())
3410 } else {
3411 Err(format!("could not find specification for target {target_tuple:?}"))
3412 }
3413 }
3414 TargetTuple::TargetJson { ref contents, .. } => {
3415 let obj = serde_json::from_str(contents).map_err(|e| e.to_string())?;
3416 Target::from_json(obj)
3417 }
3418 }
3419 }
3420
3421 pub fn small_data_threshold_support(&self) -> SmallDataThresholdSupport {
3424 match &self.options.small_data_threshold_support {
3425 SmallDataThresholdSupport::DefaultForArch => match self.arch.as_ref() {
3429 "mips" | "mips64" | "mips32r6" => {
3430 SmallDataThresholdSupport::LlvmArg("mips-ssection-threshold".into())
3431 }
3432 "hexagon" => {
3433 SmallDataThresholdSupport::LlvmArg("hexagon-small-data-threshold".into())
3434 }
3435 "m68k" => SmallDataThresholdSupport::LlvmArg("m68k-ssection-threshold".into()),
3436 "riscv32" | "riscv64" => {
3437 SmallDataThresholdSupport::LlvmModuleFlag("SmallDataLimit".into())
3438 }
3439 _ => SmallDataThresholdSupport::None,
3440 },
3441 s => s.clone(),
3442 }
3443 }
3444
3445 pub fn object_architecture(
3446 &self,
3447 unstable_target_features: &FxIndexSet<Symbol>,
3448 ) -> Option<(object::Architecture, Option<object::SubArchitecture>)> {
3449 use object::Architecture;
3450 Some(match self.arch.as_ref() {
3451 "arm" => (Architecture::Arm, None),
3452 "aarch64" => (
3453 if self.pointer_width == 32 {
3454 Architecture::Aarch64_Ilp32
3455 } else {
3456 Architecture::Aarch64
3457 },
3458 None,
3459 ),
3460 "x86" => (Architecture::I386, None),
3461 "s390x" => (Architecture::S390x, None),
3462 "mips" | "mips32r6" => (Architecture::Mips, None),
3463 "mips64" | "mips64r6" => (
3464 if self.options.llvm_abiname.as_ref() == "n32" {
3470 Architecture::Mips64_N32
3471 } else {
3472 Architecture::Mips64
3473 },
3474 None,
3475 ),
3476 "x86_64" => (
3477 if self.pointer_width == 32 {
3478 Architecture::X86_64_X32
3479 } else {
3480 Architecture::X86_64
3481 },
3482 None,
3483 ),
3484 "powerpc" => (Architecture::PowerPc, None),
3485 "powerpc64" => (Architecture::PowerPc64, None),
3486 "riscv32" => (Architecture::Riscv32, None),
3487 "riscv64" => (Architecture::Riscv64, None),
3488 "sparc" => {
3489 if unstable_target_features.contains(&sym::v8plus) {
3490 (Architecture::Sparc32Plus, None)
3492 } else {
3493 (Architecture::Sparc, None)
3495 }
3496 }
3497 "sparc64" => (Architecture::Sparc64, None),
3498 "avr" => (Architecture::Avr, None),
3499 "msp430" => (Architecture::Msp430, None),
3500 "hexagon" => (Architecture::Hexagon, None),
3501 "bpf" => (Architecture::Bpf, None),
3502 "loongarch32" => (Architecture::LoongArch32, None),
3503 "loongarch64" => (Architecture::LoongArch64, None),
3504 "csky" => (Architecture::Csky, None),
3505 "arm64ec" => (Architecture::Aarch64, Some(object::SubArchitecture::Arm64EC)),
3506 _ => return None,
3508 })
3509 }
3510
3511 pub fn max_reliable_alignment(&self) -> Align {
3520 if self.is_like_windows && self.arch == "x86" {
3524 Align::from_bytes(4).unwrap()
3525 } else {
3526 Align::MAX
3527 }
3528 }
3529}
3530
3531#[derive(Clone, Debug)]
3533pub enum TargetTuple {
3534 TargetTuple(String),
3535 TargetJson {
3536 path_for_rustdoc: PathBuf,
3539 tuple: String,
3540 contents: String,
3541 },
3542}
3543
3544impl PartialEq for TargetTuple {
3546 fn eq(&self, other: &Self) -> bool {
3547 match (self, other) {
3548 (Self::TargetTuple(l0), Self::TargetTuple(r0)) => l0 == r0,
3549 (
3550 Self::TargetJson { path_for_rustdoc: _, tuple: l_tuple, contents: l_contents },
3551 Self::TargetJson { path_for_rustdoc: _, tuple: r_tuple, contents: r_contents },
3552 ) => l_tuple == r_tuple && l_contents == r_contents,
3553 _ => false,
3554 }
3555 }
3556}
3557
3558impl Hash for TargetTuple {
3560 fn hash<H: Hasher>(&self, state: &mut H) -> () {
3561 match self {
3562 TargetTuple::TargetTuple(tuple) => {
3563 0u8.hash(state);
3564 tuple.hash(state)
3565 }
3566 TargetTuple::TargetJson { path_for_rustdoc: _, tuple, contents } => {
3567 1u8.hash(state);
3568 tuple.hash(state);
3569 contents.hash(state)
3570 }
3571 }
3572 }
3573}
3574
3575impl<S: Encoder> Encodable<S> for TargetTuple {
3577 fn encode(&self, s: &mut S) {
3578 match self {
3579 TargetTuple::TargetTuple(tuple) => {
3580 s.emit_u8(0);
3581 s.emit_str(tuple);
3582 }
3583 TargetTuple::TargetJson { path_for_rustdoc: _, tuple, contents } => {
3584 s.emit_u8(1);
3585 s.emit_str(tuple);
3586 s.emit_str(contents);
3587 }
3588 }
3589 }
3590}
3591
3592impl<D: Decoder> Decodable<D> for TargetTuple {
3593 fn decode(d: &mut D) -> Self {
3594 match d.read_u8() {
3595 0 => TargetTuple::TargetTuple(d.read_str().to_owned()),
3596 1 => TargetTuple::TargetJson {
3597 path_for_rustdoc: PathBuf::new(),
3598 tuple: d.read_str().to_owned(),
3599 contents: d.read_str().to_owned(),
3600 },
3601 _ => {
3602 panic!("invalid enum variant tag while decoding `TargetTuple`, expected 0..2");
3603 }
3604 }
3605 }
3606}
3607
3608impl TargetTuple {
3609 pub fn from_tuple(tuple: &str) -> Self {
3611 TargetTuple::TargetTuple(tuple.into())
3612 }
3613
3614 pub fn from_path(path: &Path) -> Result<Self, io::Error> {
3616 let canonicalized_path = try_canonicalize(path)?;
3617 let contents = std::fs::read_to_string(&canonicalized_path).map_err(|err| {
3618 io::Error::new(
3619 io::ErrorKind::InvalidInput,
3620 format!("target path {canonicalized_path:?} is not a valid file: {err}"),
3621 )
3622 })?;
3623 let tuple = canonicalized_path
3624 .file_stem()
3625 .expect("target path must not be empty")
3626 .to_str()
3627 .expect("target path must be valid unicode")
3628 .to_owned();
3629 Ok(TargetTuple::TargetJson { path_for_rustdoc: canonicalized_path, tuple, contents })
3630 }
3631
3632 pub fn tuple(&self) -> &str {
3636 match *self {
3637 TargetTuple::TargetTuple(ref tuple) | TargetTuple::TargetJson { ref tuple, .. } => {
3638 tuple
3639 }
3640 }
3641 }
3642
3643 pub fn debug_tuple(&self) -> String {
3648 use std::hash::DefaultHasher;
3649
3650 match self {
3651 TargetTuple::TargetTuple(tuple) => tuple.to_owned(),
3652 TargetTuple::TargetJson { path_for_rustdoc: _, tuple, contents: content } => {
3653 let mut hasher = DefaultHasher::new();
3654 content.hash(&mut hasher);
3655 let hash = hasher.finish();
3656 format!("{tuple}-{hash}")
3657 }
3658 }
3659 }
3660}
3661
3662impl fmt::Display for TargetTuple {
3663 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3664 write!(f, "{}", self.debug_tuple())
3665 }
3666}