1use core::result::Result;
41use std::borrow::Cow;
42use std::collections::BTreeMap;
43use std::hash::{Hash, Hasher};
44use std::ops::{Deref, DerefMut};
45use std::path::{Path, PathBuf};
46use std::str::FromStr;
47use std::{fmt, io};
48
49use rustc_abi::{
50 Align, CanonAbi, Endian, ExternAbi, Integer, Size, TargetDataLayout, TargetDataLayoutErrors,
51};
52use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
53use rustc_error_messages::{DiagArgValue, IntoDiagArg, into_diag_arg_using_display};
54use rustc_fs_util::try_canonicalize;
55use rustc_macros::{BlobDecodable, Decodable, Encodable, HashStable_Generic};
56use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
57use rustc_span::{Symbol, kw, sym};
58use serde_json::Value;
59use tracing::debug;
60
61use crate::json::{Json, ToJson};
62use crate::spec::crt_objects::CrtObjects;
63
64pub mod crt_objects;
65
66mod abi_map;
67mod base;
68mod json;
69
70pub use abi_map::{AbiMap, AbiMapping};
71pub use base::apple;
72pub use base::avr::ef_avr_arch;
73pub use json::json_schema;
74
75#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
77pub enum Cc {
78 Yes,
79 No,
80}
81
82#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
84pub enum Lld {
85 Yes,
86 No,
87}
88
89#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
110pub enum LinkerFlavor {
111 Gnu(Cc, Lld),
115 Darwin(Cc, Lld),
118 WasmLld(Cc),
122 Unix(Cc),
126 Msvc(Lld),
128 EmCc,
131 Bpf,
134 Ptx,
136 Llbc,
138}
139
140#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
145pub enum LinkerFlavorCli {
146 Gnu(Cc, Lld),
148 Darwin(Cc, Lld),
149 WasmLld(Cc),
150 Unix(Cc),
151 Msvc(Lld),
153 EmCc,
154 Bpf,
155 Ptx,
156 Llbc,
157
158 Gcc,
160 Ld,
161 Lld(LldFlavor),
162 Em,
163}
164
165impl LinkerFlavorCli {
166 pub fn is_unstable(&self) -> bool {
168 match self {
169 LinkerFlavorCli::Gnu(..)
170 | LinkerFlavorCli::Darwin(..)
171 | LinkerFlavorCli::WasmLld(..)
172 | LinkerFlavorCli::Unix(..)
173 | LinkerFlavorCli::Msvc(Lld::Yes)
174 | LinkerFlavorCli::EmCc
175 | LinkerFlavorCli::Bpf
176 | LinkerFlavorCli::Llbc
177 | LinkerFlavorCli::Ptx => true,
178 LinkerFlavorCli::Gcc
179 | LinkerFlavorCli::Ld
180 | LinkerFlavorCli::Lld(..)
181 | LinkerFlavorCli::Msvc(Lld::No)
182 | LinkerFlavorCli::Em => false,
183 }
184 }
185}
186
187crate::target_spec_enum! {
188 pub enum LldFlavor {
189 Wasm = "wasm",
190 Ld64 = "darwin",
191 Ld = "gnu",
192 Link = "link",
193 }
194
195 parse_error_type = "LLD flavor";
196}
197
198impl LinkerFlavor {
199 fn from_cli_json(cli: LinkerFlavorCli, lld_flavor: LldFlavor, is_gnu: bool) -> LinkerFlavor {
204 match cli {
205 LinkerFlavorCli::Gnu(cc, lld) => LinkerFlavor::Gnu(cc, lld),
206 LinkerFlavorCli::Darwin(cc, lld) => LinkerFlavor::Darwin(cc, lld),
207 LinkerFlavorCli::WasmLld(cc) => LinkerFlavor::WasmLld(cc),
208 LinkerFlavorCli::Unix(cc) => LinkerFlavor::Unix(cc),
209 LinkerFlavorCli::Msvc(lld) => LinkerFlavor::Msvc(lld),
210 LinkerFlavorCli::EmCc => LinkerFlavor::EmCc,
211 LinkerFlavorCli::Bpf => LinkerFlavor::Bpf,
212 LinkerFlavorCli::Llbc => LinkerFlavor::Llbc,
213 LinkerFlavorCli::Ptx => LinkerFlavor::Ptx,
214
215 LinkerFlavorCli::Gcc => match lld_flavor {
217 LldFlavor::Ld if is_gnu => LinkerFlavor::Gnu(Cc::Yes, Lld::No),
218 LldFlavor::Ld64 => LinkerFlavor::Darwin(Cc::Yes, Lld::No),
219 LldFlavor::Wasm => LinkerFlavor::WasmLld(Cc::Yes),
220 LldFlavor::Ld | LldFlavor::Link => LinkerFlavor::Unix(Cc::Yes),
221 },
222 LinkerFlavorCli::Ld => match lld_flavor {
223 LldFlavor::Ld if is_gnu => LinkerFlavor::Gnu(Cc::No, Lld::No),
224 LldFlavor::Ld64 => LinkerFlavor::Darwin(Cc::No, Lld::No),
225 LldFlavor::Ld | LldFlavor::Wasm | LldFlavor::Link => LinkerFlavor::Unix(Cc::No),
226 },
227 LinkerFlavorCli::Lld(LldFlavor::Ld) => LinkerFlavor::Gnu(Cc::No, Lld::Yes),
228 LinkerFlavorCli::Lld(LldFlavor::Ld64) => LinkerFlavor::Darwin(Cc::No, Lld::Yes),
229 LinkerFlavorCli::Lld(LldFlavor::Wasm) => LinkerFlavor::WasmLld(Cc::No),
230 LinkerFlavorCli::Lld(LldFlavor::Link) => LinkerFlavor::Msvc(Lld::Yes),
231 LinkerFlavorCli::Em => LinkerFlavor::EmCc,
232 }
233 }
234
235 fn to_cli(self) -> LinkerFlavorCli {
237 match self {
238 LinkerFlavor::Gnu(Cc::Yes, _)
239 | LinkerFlavor::Darwin(Cc::Yes, _)
240 | LinkerFlavor::WasmLld(Cc::Yes)
241 | LinkerFlavor::Unix(Cc::Yes) => LinkerFlavorCli::Gcc,
242 LinkerFlavor::Gnu(_, Lld::Yes) => LinkerFlavorCli::Lld(LldFlavor::Ld),
243 LinkerFlavor::Darwin(_, Lld::Yes) => LinkerFlavorCli::Lld(LldFlavor::Ld64),
244 LinkerFlavor::WasmLld(..) => LinkerFlavorCli::Lld(LldFlavor::Wasm),
245 LinkerFlavor::Gnu(..) | LinkerFlavor::Darwin(..) | LinkerFlavor::Unix(..) => {
246 LinkerFlavorCli::Ld
247 }
248 LinkerFlavor::Msvc(Lld::Yes) => LinkerFlavorCli::Lld(LldFlavor::Link),
249 LinkerFlavor::Msvc(..) => LinkerFlavorCli::Msvc(Lld::No),
250 LinkerFlavor::EmCc => LinkerFlavorCli::Em,
251 LinkerFlavor::Bpf => LinkerFlavorCli::Bpf,
252 LinkerFlavor::Llbc => LinkerFlavorCli::Llbc,
253 LinkerFlavor::Ptx => LinkerFlavorCli::Ptx,
254 }
255 }
256
257 fn to_cli_counterpart(self) -> LinkerFlavorCli {
259 match self {
260 LinkerFlavor::Gnu(cc, lld) => LinkerFlavorCli::Gnu(cc, lld),
261 LinkerFlavor::Darwin(cc, lld) => LinkerFlavorCli::Darwin(cc, lld),
262 LinkerFlavor::WasmLld(cc) => LinkerFlavorCli::WasmLld(cc),
263 LinkerFlavor::Unix(cc) => LinkerFlavorCli::Unix(cc),
264 LinkerFlavor::Msvc(lld) => LinkerFlavorCli::Msvc(lld),
265 LinkerFlavor::EmCc => LinkerFlavorCli::EmCc,
266 LinkerFlavor::Bpf => LinkerFlavorCli::Bpf,
267 LinkerFlavor::Llbc => LinkerFlavorCli::Llbc,
268 LinkerFlavor::Ptx => LinkerFlavorCli::Ptx,
269 }
270 }
271
272 fn infer_cli_hints(cli: LinkerFlavorCli) -> (Option<Cc>, Option<Lld>) {
273 match cli {
274 LinkerFlavorCli::Gnu(cc, lld) | LinkerFlavorCli::Darwin(cc, lld) => {
275 (Some(cc), Some(lld))
276 }
277 LinkerFlavorCli::WasmLld(cc) => (Some(cc), Some(Lld::Yes)),
278 LinkerFlavorCli::Unix(cc) => (Some(cc), None),
279 LinkerFlavorCli::Msvc(lld) => (Some(Cc::No), Some(lld)),
280 LinkerFlavorCli::EmCc => (Some(Cc::Yes), Some(Lld::Yes)),
281 LinkerFlavorCli::Bpf | LinkerFlavorCli::Ptx => (None, None),
282 LinkerFlavorCli::Llbc => (None, None),
283
284 LinkerFlavorCli::Gcc => (Some(Cc::Yes), None),
286 LinkerFlavorCli::Ld => (Some(Cc::No), Some(Lld::No)),
287 LinkerFlavorCli::Lld(_) => (Some(Cc::No), Some(Lld::Yes)),
288 LinkerFlavorCli::Em => (Some(Cc::Yes), Some(Lld::Yes)),
289 }
290 }
291
292 fn infer_linker_hints(linker_stem: &str) -> Result<Self, (Option<Cc>, Option<Lld>)> {
293 let stem = linker_stem
295 .rsplit_once('-')
296 .and_then(|(lhs, rhs)| rhs.chars().all(char::is_numeric).then_some(lhs))
297 .unwrap_or(linker_stem);
298
299 if stem == "llvm-bitcode-linker" {
300 Ok(Self::Llbc)
301 } else if stem == "emcc" || stem == "gcc"
303 || stem.ends_with("-gcc")
304 || stem == "g++"
305 || stem.ends_with("-g++")
306 || stem == "clang"
307 || stem.ends_with("-clang")
308 || stem == "clang++"
309 || stem.ends_with("-clang++")
310 {
311 Err((Some(Cc::Yes), Some(Lld::No)))
312 } else if stem == "wasm-ld"
313 || stem.ends_with("-wasm-ld")
314 || stem == "ld.lld"
315 || stem == "lld"
316 || stem == "rust-lld"
317 || stem == "lld-link"
318 {
319 Err((Some(Cc::No), Some(Lld::Yes)))
320 } else if stem == "ld" || stem.ends_with("-ld") || stem == "link" {
321 Err((Some(Cc::No), Some(Lld::No)))
322 } else {
323 Err((None, None))
324 }
325 }
326
327 fn with_hints(self, (cc_hint, lld_hint): (Option<Cc>, Option<Lld>)) -> LinkerFlavor {
328 match self {
329 LinkerFlavor::Gnu(cc, lld) => {
330 LinkerFlavor::Gnu(cc_hint.unwrap_or(cc), lld_hint.unwrap_or(lld))
331 }
332 LinkerFlavor::Darwin(cc, lld) => {
333 LinkerFlavor::Darwin(cc_hint.unwrap_or(cc), lld_hint.unwrap_or(lld))
334 }
335 LinkerFlavor::WasmLld(cc) => LinkerFlavor::WasmLld(cc_hint.unwrap_or(cc)),
336 LinkerFlavor::Unix(cc) => LinkerFlavor::Unix(cc_hint.unwrap_or(cc)),
337 LinkerFlavor::Msvc(lld) => LinkerFlavor::Msvc(lld_hint.unwrap_or(lld)),
338 LinkerFlavor::EmCc | LinkerFlavor::Bpf | LinkerFlavor::Llbc | LinkerFlavor::Ptx => self,
339 }
340 }
341
342 pub fn with_cli_hints(self, cli: LinkerFlavorCli) -> LinkerFlavor {
343 self.with_hints(LinkerFlavor::infer_cli_hints(cli))
344 }
345
346 pub fn with_linker_hints(self, linker_stem: &str) -> LinkerFlavor {
347 match LinkerFlavor::infer_linker_hints(linker_stem) {
348 Ok(linker_flavor) => linker_flavor,
349 Err(hints) => self.with_hints(hints),
350 }
351 }
352
353 pub fn check_compatibility(self, cli: LinkerFlavorCli) -> Option<String> {
354 let compatible = |cli| {
355 match (self, cli) {
357 (LinkerFlavor::Gnu(..), LinkerFlavorCli::Gnu(..))
359 | (LinkerFlavor::Darwin(..), LinkerFlavorCli::Darwin(..))
360 | (LinkerFlavor::WasmLld(..), LinkerFlavorCli::WasmLld(..))
361 | (LinkerFlavor::Unix(..), LinkerFlavorCli::Unix(..))
362 | (LinkerFlavor::Msvc(..), LinkerFlavorCli::Msvc(..))
363 | (LinkerFlavor::EmCc, LinkerFlavorCli::EmCc)
364 | (LinkerFlavor::Bpf, LinkerFlavorCli::Bpf)
365 | (LinkerFlavor::Llbc, LinkerFlavorCli::Llbc)
366 | (LinkerFlavor::Ptx, LinkerFlavorCli::Ptx) => return true,
367 (LinkerFlavor::Ptx, LinkerFlavorCli::Llbc) => return true,
369 _ => {}
370 }
371
372 cli == self.with_cli_hints(cli).to_cli()
374 };
375 (!compatible(cli)).then(|| {
376 LinkerFlavorCli::all()
377 .iter()
378 .filter(|cli| compatible(**cli))
379 .map(|cli| cli.desc())
380 .intersperse(", ")
381 .collect()
382 })
383 }
384
385 pub fn lld_flavor(self) -> LldFlavor {
386 match self {
387 LinkerFlavor::Gnu(..)
388 | LinkerFlavor::Unix(..)
389 | LinkerFlavor::EmCc
390 | LinkerFlavor::Bpf
391 | LinkerFlavor::Llbc
392 | LinkerFlavor::Ptx => LldFlavor::Ld,
393 LinkerFlavor::Darwin(..) => LldFlavor::Ld64,
394 LinkerFlavor::WasmLld(..) => LldFlavor::Wasm,
395 LinkerFlavor::Msvc(..) => LldFlavor::Link,
396 }
397 }
398
399 pub fn is_gnu(self) -> bool {
400 matches!(self, LinkerFlavor::Gnu(..))
401 }
402
403 pub fn uses_lld(self) -> bool {
405 match self {
407 LinkerFlavor::Gnu(_, Lld::Yes)
408 | LinkerFlavor::Darwin(_, Lld::Yes)
409 | LinkerFlavor::WasmLld(..)
410 | LinkerFlavor::EmCc
411 | LinkerFlavor::Msvc(Lld::Yes) => true,
412 LinkerFlavor::Gnu(..)
413 | LinkerFlavor::Darwin(..)
414 | LinkerFlavor::Msvc(_)
415 | LinkerFlavor::Unix(_)
416 | LinkerFlavor::Bpf
417 | LinkerFlavor::Llbc
418 | LinkerFlavor::Ptx => false,
419 }
420 }
421
422 pub fn uses_cc(self) -> bool {
424 match self {
426 LinkerFlavor::Gnu(Cc::Yes, _)
427 | LinkerFlavor::Darwin(Cc::Yes, _)
428 | LinkerFlavor::WasmLld(Cc::Yes)
429 | LinkerFlavor::Unix(Cc::Yes)
430 | LinkerFlavor::EmCc => true,
431 LinkerFlavor::Gnu(..)
432 | LinkerFlavor::Darwin(..)
433 | LinkerFlavor::WasmLld(_)
434 | LinkerFlavor::Msvc(_)
435 | LinkerFlavor::Unix(_)
436 | LinkerFlavor::Bpf
437 | LinkerFlavor::Llbc
438 | LinkerFlavor::Ptx => false,
439 }
440 }
441
442 pub fn with_lld_enabled(self) -> LinkerFlavor {
445 match self {
446 LinkerFlavor::Gnu(cc, Lld::No) => LinkerFlavor::Gnu(cc, Lld::Yes),
447 LinkerFlavor::Darwin(cc, Lld::No) => LinkerFlavor::Darwin(cc, Lld::Yes),
448 LinkerFlavor::Msvc(Lld::No) => LinkerFlavor::Msvc(Lld::Yes),
449 _ => self,
450 }
451 }
452
453 pub fn with_lld_disabled(self) -> LinkerFlavor {
456 match self {
457 LinkerFlavor::Gnu(cc, Lld::Yes) => LinkerFlavor::Gnu(cc, Lld::No),
458 LinkerFlavor::Darwin(cc, Lld::Yes) => LinkerFlavor::Darwin(cc, Lld::No),
459 LinkerFlavor::Msvc(Lld::Yes) => LinkerFlavor::Msvc(Lld::No),
460 _ => self,
461 }
462 }
463}
464
465macro_rules! linker_flavor_cli_impls {
466 ($(($($flavor:tt)*) $string:literal)*) => (
467 impl LinkerFlavorCli {
468 const fn all() -> &'static [LinkerFlavorCli] {
469 &[$($($flavor)*,)*]
470 }
471
472 pub const fn one_of() -> &'static str {
473 concat!("one of: ", $($string, " ",)*)
474 }
475
476 pub fn desc(self) -> &'static str {
477 match self {
478 $($($flavor)* => $string,)*
479 }
480 }
481 }
482
483 impl FromStr for LinkerFlavorCli {
484 type Err = String;
485
486 fn from_str(s: &str) -> Result<LinkerFlavorCli, Self::Err> {
487 Ok(match s {
488 $($string => $($flavor)*,)*
489 _ => return Err(format!("invalid linker flavor, allowed values: {}", Self::one_of())),
490 })
491 }
492 }
493 )
494}
495
496linker_flavor_cli_impls! {
497 (LinkerFlavorCli::Gnu(Cc::No, Lld::No)) "gnu"
498 (LinkerFlavorCli::Gnu(Cc::No, Lld::Yes)) "gnu-lld"
499 (LinkerFlavorCli::Gnu(Cc::Yes, Lld::No)) "gnu-cc"
500 (LinkerFlavorCli::Gnu(Cc::Yes, Lld::Yes)) "gnu-lld-cc"
501 (LinkerFlavorCli::Darwin(Cc::No, Lld::No)) "darwin"
502 (LinkerFlavorCli::Darwin(Cc::No, Lld::Yes)) "darwin-lld"
503 (LinkerFlavorCli::Darwin(Cc::Yes, Lld::No)) "darwin-cc"
504 (LinkerFlavorCli::Darwin(Cc::Yes, Lld::Yes)) "darwin-lld-cc"
505 (LinkerFlavorCli::WasmLld(Cc::No)) "wasm-lld"
506 (LinkerFlavorCli::WasmLld(Cc::Yes)) "wasm-lld-cc"
507 (LinkerFlavorCli::Unix(Cc::No)) "unix"
508 (LinkerFlavorCli::Unix(Cc::Yes)) "unix-cc"
509 (LinkerFlavorCli::Msvc(Lld::Yes)) "msvc-lld"
510 (LinkerFlavorCli::Msvc(Lld::No)) "msvc"
511 (LinkerFlavorCli::EmCc) "em-cc"
512 (LinkerFlavorCli::Bpf) "bpf"
513 (LinkerFlavorCli::Llbc) "llbc"
514 (LinkerFlavorCli::Ptx) "ptx"
515
516 (LinkerFlavorCli::Gcc) "gcc"
518 (LinkerFlavorCli::Ld) "ld"
519 (LinkerFlavorCli::Lld(LldFlavor::Ld)) "ld.lld"
520 (LinkerFlavorCli::Lld(LldFlavor::Ld64)) "ld64.lld"
521 (LinkerFlavorCli::Lld(LldFlavor::Link)) "lld-link"
522 (LinkerFlavorCli::Lld(LldFlavor::Wasm)) "wasm-ld"
523 (LinkerFlavorCli::Em) "em"
524}
525
526crate::json::serde_deserialize_from_str!(LinkerFlavorCli);
527impl schemars::JsonSchema for LinkerFlavorCli {
528 fn schema_name() -> std::borrow::Cow<'static, str> {
529 "LinkerFlavor".into()
530 }
531 fn json_schema(_: &mut schemars::SchemaGenerator) -> schemars::Schema {
532 let all: Vec<&'static str> =
533 Self::all().iter().map(|flavor| flavor.desc()).collect::<Vec<_>>();
534 schemars::json_schema! ({
535 "type": "string",
536 "enum": all
537 })
538 .into()
539 }
540}
541
542impl ToJson for LinkerFlavorCli {
543 fn to_json(&self) -> Json {
544 self.desc().to_json()
545 }
546}
547
548#[derive(Clone, Copy, PartialEq, Debug)]
555pub enum LinkSelfContainedDefault {
556 True,
558
559 False,
561
562 InferredForMusl,
564
565 InferredForMingw,
567
568 WithComponents(LinkSelfContainedComponents),
571}
572
573impl FromStr for LinkSelfContainedDefault {
575 type Err = String;
576
577 fn from_str(s: &str) -> Result<LinkSelfContainedDefault, Self::Err> {
578 Ok(match s {
579 "false" => LinkSelfContainedDefault::False,
580 "true" | "wasm" => LinkSelfContainedDefault::True,
581 "musl" => LinkSelfContainedDefault::InferredForMusl,
582 "mingw" => LinkSelfContainedDefault::InferredForMingw,
583 _ => {
584 return Err(format!(
585 "'{s}' is not a valid `-Clink-self-contained` default. \
586 Use 'false', 'true', 'wasm', 'musl' or 'mingw'",
587 ));
588 }
589 })
590 }
591}
592
593crate::json::serde_deserialize_from_str!(LinkSelfContainedDefault);
594impl schemars::JsonSchema for LinkSelfContainedDefault {
595 fn schema_name() -> std::borrow::Cow<'static, str> {
596 "LinkSelfContainedDefault".into()
597 }
598 fn json_schema(_: &mut schemars::SchemaGenerator) -> schemars::Schema {
599 schemars::json_schema! ({
600 "type": "string",
601 "enum": ["false", "true", "wasm", "musl", "mingw"]
602 })
603 .into()
604 }
605}
606
607impl ToJson for LinkSelfContainedDefault {
608 fn to_json(&self) -> Json {
609 match *self {
610 LinkSelfContainedDefault::WithComponents(components) => {
611 let mut map = BTreeMap::new();
615 map.insert("components", components);
616 map.to_json()
617 }
618
619 LinkSelfContainedDefault::True => "true".to_json(),
621 LinkSelfContainedDefault::False => "false".to_json(),
622 LinkSelfContainedDefault::InferredForMusl => "musl".to_json(),
623 LinkSelfContainedDefault::InferredForMingw => "mingw".to_json(),
624 }
625 }
626}
627
628impl LinkSelfContainedDefault {
629 pub fn is_disabled(self) -> bool {
632 self == LinkSelfContainedDefault::False
633 }
634
635 fn json_key(self) -> &'static str {
639 match self {
640 LinkSelfContainedDefault::WithComponents(_) => "link-self-contained",
641 _ => "crt-objects-fallback",
642 }
643 }
644
645 pub fn with_linker() -> LinkSelfContainedDefault {
648 LinkSelfContainedDefault::WithComponents(LinkSelfContainedComponents::LINKER)
649 }
650}
651
652bitflags::bitflags! {
653 #[derive(Clone, Copy, PartialEq, Eq, Default)]
654 pub struct LinkSelfContainedComponents: u8 {
656 const CRT_OBJECTS = 1 << 0;
658 const LIBC = 1 << 1;
660 const UNWIND = 1 << 2;
662 const LINKER = 1 << 3;
664 const SANITIZERS = 1 << 4;
666 const MINGW = 1 << 5;
668 }
669}
670rustc_data_structures::external_bitflags_debug! { LinkSelfContainedComponents }
671
672impl LinkSelfContainedComponents {
673 pub fn as_str(self) -> Option<&'static str> {
677 Some(match self {
678 LinkSelfContainedComponents::CRT_OBJECTS => "crto",
679 LinkSelfContainedComponents::LIBC => "libc",
680 LinkSelfContainedComponents::UNWIND => "unwind",
681 LinkSelfContainedComponents::LINKER => "linker",
682 LinkSelfContainedComponents::SANITIZERS => "sanitizers",
683 LinkSelfContainedComponents::MINGW => "mingw",
684 _ => return None,
685 })
686 }
687
688 fn all_components() -> [LinkSelfContainedComponents; 6] {
690 [
691 LinkSelfContainedComponents::CRT_OBJECTS,
692 LinkSelfContainedComponents::LIBC,
693 LinkSelfContainedComponents::UNWIND,
694 LinkSelfContainedComponents::LINKER,
695 LinkSelfContainedComponents::SANITIZERS,
696 LinkSelfContainedComponents::MINGW,
697 ]
698 }
699
700 pub fn are_any_components_enabled(self) -> bool {
702 !self.is_empty()
703 }
704
705 pub fn is_linker_enabled(self) -> bool {
707 self.contains(LinkSelfContainedComponents::LINKER)
708 }
709
710 pub fn is_crt_objects_enabled(self) -> bool {
712 self.contains(LinkSelfContainedComponents::CRT_OBJECTS)
713 }
714}
715
716impl FromStr for LinkSelfContainedComponents {
717 type Err = String;
718
719 fn from_str(s: &str) -> Result<Self, Self::Err> {
721 Ok(match s {
722 "crto" => LinkSelfContainedComponents::CRT_OBJECTS,
723 "libc" => LinkSelfContainedComponents::LIBC,
724 "unwind" => LinkSelfContainedComponents::UNWIND,
725 "linker" => LinkSelfContainedComponents::LINKER,
726 "sanitizers" => LinkSelfContainedComponents::SANITIZERS,
727 "mingw" => LinkSelfContainedComponents::MINGW,
728 _ => {
729 return Err(format!(
730 "'{s}' is not a valid link-self-contained component, expected 'crto', 'libc', 'unwind', 'linker', 'sanitizers', 'mingw'"
731 ));
732 }
733 })
734 }
735}
736
737crate::json::serde_deserialize_from_str!(LinkSelfContainedComponents);
738impl schemars::JsonSchema for LinkSelfContainedComponents {
739 fn schema_name() -> std::borrow::Cow<'static, str> {
740 "LinkSelfContainedComponents".into()
741 }
742 fn json_schema(_: &mut schemars::SchemaGenerator) -> schemars::Schema {
743 let all =
744 Self::all_components().iter().map(|component| component.as_str()).collect::<Vec<_>>();
745 schemars::json_schema! ({
746 "type": "string",
747 "enum": all,
748 })
749 .into()
750 }
751}
752
753impl ToJson for LinkSelfContainedComponents {
754 fn to_json(&self) -> Json {
755 let components: Vec<_> = Self::all_components()
756 .into_iter()
757 .filter(|c| self.contains(*c))
758 .map(|c| {
759 c.as_str().unwrap().to_owned()
762 })
763 .collect();
764
765 components.to_json()
766 }
767}
768
769bitflags::bitflags! {
770 #[derive(Clone, Copy, PartialEq, Eq, Default)]
791 pub struct LinkerFeatures: u8 {
792 const CC = 1 << 0;
794 const LLD = 1 << 1;
796 }
797}
798rustc_data_structures::external_bitflags_debug! { LinkerFeatures }
799
800impl LinkerFeatures {
801 pub fn from_str(s: &str) -> Option<LinkerFeatures> {
803 Some(match s {
804 "cc" => LinkerFeatures::CC,
805 "lld" => LinkerFeatures::LLD,
806 _ => return None,
807 })
808 }
809
810 pub fn as_str(self) -> Option<&'static str> {
814 Some(match self {
815 LinkerFeatures::CC => "cc",
816 LinkerFeatures::LLD => "lld",
817 _ => return None,
818 })
819 }
820
821 pub fn is_lld_enabled(self) -> bool {
823 self.contains(LinkerFeatures::LLD)
824 }
825
826 pub fn is_cc_enabled(self) -> bool {
828 self.contains(LinkerFeatures::CC)
829 }
830}
831
832crate::target_spec_enum! {
833 #[derive(Encodable, BlobDecodable, HashStable_Generic)]
834 pub enum PanicStrategy {
835 Unwind = "unwind",
836 Abort = "abort",
837 ImmediateAbort = "immediate-abort",
838 }
839
840 parse_error_type = "panic strategy";
841}
842
843#[derive(Clone, Copy, Debug, PartialEq, Hash, Encodable, BlobDecodable, HashStable_Generic)]
844pub enum OnBrokenPipe {
845 Default,
846 Kill,
847 Error,
848 Inherit,
849}
850
851impl PanicStrategy {
852 pub const fn desc_symbol(&self) -> Symbol {
853 match *self {
854 PanicStrategy::Unwind => sym::unwind,
855 PanicStrategy::Abort => sym::abort,
856 PanicStrategy::ImmediateAbort => sym::immediate_abort,
857 }
858 }
859
860 pub fn unwinds(self) -> bool {
861 matches!(self, PanicStrategy::Unwind)
862 }
863}
864
865crate::target_spec_enum! {
866 pub enum RelroLevel {
867 Full = "full",
868 Partial = "partial",
869 Off = "off",
870 None = "none",
871 }
872
873 parse_error_type = "relro level";
874}
875
876impl IntoDiagArg for PanicStrategy {
877 fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
878 DiagArgValue::Str(Cow::Owned(self.desc().to_string()))
879 }
880}
881
882crate::target_spec_enum! {
883 pub enum SymbolVisibility {
884 Hidden = "hidden",
885 Protected = "protected",
886 Interposable = "interposable",
887 }
888
889 parse_error_type = "symbol visibility";
890}
891
892#[derive(Clone, Debug, PartialEq, Hash)]
893pub enum SmallDataThresholdSupport {
894 None,
895 DefaultForArch,
896 LlvmModuleFlag(StaticCow<str>),
897 LlvmArg(StaticCow<str>),
898}
899
900impl FromStr for SmallDataThresholdSupport {
901 type Err = String;
902
903 fn from_str(s: &str) -> Result<Self, Self::Err> {
904 if s == "none" {
905 Ok(Self::None)
906 } else if s == "default-for-arch" {
907 Ok(Self::DefaultForArch)
908 } else if let Some(flag) = s.strip_prefix("llvm-module-flag=") {
909 Ok(Self::LlvmModuleFlag(flag.to_string().into()))
910 } else if let Some(arg) = s.strip_prefix("llvm-arg=") {
911 Ok(Self::LlvmArg(arg.to_string().into()))
912 } else {
913 Err(format!("'{s}' is not a valid value for small-data-threshold-support."))
914 }
915 }
916}
917
918crate::json::serde_deserialize_from_str!(SmallDataThresholdSupport);
919impl schemars::JsonSchema for SmallDataThresholdSupport {
920 fn schema_name() -> std::borrow::Cow<'static, str> {
921 "SmallDataThresholdSupport".into()
922 }
923 fn json_schema(_: &mut schemars::SchemaGenerator) -> schemars::Schema {
924 schemars::json_schema! ({
925 "type": "string",
926 "pattern": r#"^none|default-for-arch|llvm-module-flag=.+|llvm-arg=.+$"#,
927 })
928 .into()
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
943crate::target_spec_enum! {
944 pub enum MergeFunctions {
945 Disabled = "disabled",
946 Trampolines = "trampolines",
947 Aliases = "aliases",
948 }
949
950 parse_error_type = "value for merge-functions";
951}
952
953crate::target_spec_enum! {
954 pub enum RelocModel {
955 Static = "static",
956 Pic = "pic",
957 Pie = "pie",
958 DynamicNoPic = "dynamic-no-pic",
959 Ropi = "ropi",
960 Rwpi = "rwpi",
961 RopiRwpi = "ropi-rwpi",
962 }
963
964 parse_error_type = "relocation model";
965}
966
967impl RelocModel {
968 pub const fn desc_symbol(&self) -> Symbol {
969 match *self {
970 RelocModel::Static => kw::Static,
971 RelocModel::Pic => sym::pic,
972 RelocModel::Pie => sym::pie,
973 RelocModel::DynamicNoPic => sym::dynamic_no_pic,
974 RelocModel::Ropi => sym::ropi,
975 RelocModel::Rwpi => sym::rwpi,
976 RelocModel::RopiRwpi => sym::ropi_rwpi,
977 }
978 }
979}
980
981crate::target_spec_enum! {
982 pub enum CodeModel {
983 Tiny = "tiny",
984 Small = "small",
985 Kernel = "kernel",
986 Medium = "medium",
987 Large = "large",
988 }
989
990 parse_error_type = "code model";
991}
992
993crate::target_spec_enum! {
994 pub enum FloatAbi {
996 Soft = "soft",
997 Hard = "hard",
998 }
999
1000 parse_error_type = "float abi";
1001}
1002
1003crate::target_spec_enum! {
1004 pub enum RustcAbi {
1006 X86Sse2 = "x86-sse2",
1008 X86Softfloat = "x86-softfloat",
1010 }
1011
1012 parse_error_type = "rustc abi";
1013}
1014
1015crate::target_spec_enum! {
1016 pub enum TlsModel {
1017 GeneralDynamic = "global-dynamic",
1018 LocalDynamic = "local-dynamic",
1019 InitialExec = "initial-exec",
1020 LocalExec = "local-exec",
1021 Emulated = "emulated",
1022 }
1023
1024 parse_error_type = "TLS model";
1025}
1026
1027crate::target_spec_enum! {
1028 pub enum LinkOutputKind {
1030 DynamicNoPicExe = "dynamic-nopic-exe",
1032 DynamicPicExe = "dynamic-pic-exe",
1034 StaticNoPicExe = "static-nopic-exe",
1036 StaticPicExe = "static-pic-exe",
1038 DynamicDylib = "dynamic-dylib",
1040 StaticDylib = "static-dylib",
1042 WasiReactorExe = "wasi-reactor-exe",
1044 }
1045
1046 parse_error_type = "CRT object kind";
1047}
1048
1049impl LinkOutputKind {
1050 pub fn can_link_dylib(self) -> bool {
1051 match self {
1052 LinkOutputKind::StaticNoPicExe | LinkOutputKind::StaticPicExe => false,
1053 LinkOutputKind::DynamicNoPicExe
1054 | LinkOutputKind::DynamicPicExe
1055 | LinkOutputKind::DynamicDylib
1056 | LinkOutputKind::StaticDylib
1057 | LinkOutputKind::WasiReactorExe => true,
1058 }
1059 }
1060}
1061
1062pub type LinkArgs = BTreeMap<LinkerFlavor, Vec<StaticCow<str>>>;
1063pub type LinkArgsCli = BTreeMap<LinkerFlavorCli, Vec<StaticCow<str>>>;
1064
1065crate::target_spec_enum! {
1066 #[derive(Default)]
1071 pub enum DebuginfoKind {
1072 #[default]
1074 Dwarf = "dwarf",
1075 DwarfDsym = "dwarf-dsym",
1077 Pdb = "pdb",
1079 }
1080
1081 parse_error_type = "debuginfo kind";
1082}
1083
1084crate::target_spec_enum! {
1085 #[derive(Default)]
1086 pub enum SplitDebuginfo {
1087 #[default]
1095 Off = "off",
1096
1097 Packed = "packed",
1104
1105 Unpacked = "unpacked",
1112 }
1113
1114 parse_error_type = "split debuginfo";
1115}
1116
1117into_diag_arg_using_display!(SplitDebuginfo);
1118
1119#[derive(Clone, Debug, PartialEq, Eq, serde_derive::Deserialize, schemars::JsonSchema)]
1120#[serde(tag = "kind")]
1121#[serde(rename_all = "kebab-case")]
1122pub enum StackProbeType {
1123 None,
1125 Inline,
1129 Call,
1131 InlineOrCall {
1134 #[serde(rename = "min-llvm-version-for-inline")]
1135 min_llvm_version_for_inline: (u32, u32, u32),
1136 },
1137}
1138
1139impl ToJson for StackProbeType {
1140 fn to_json(&self) -> Json {
1141 Json::Object(match self {
1142 StackProbeType::None => {
1143 [(String::from("kind"), "none".to_json())].into_iter().collect()
1144 }
1145 StackProbeType::Inline => {
1146 [(String::from("kind"), "inline".to_json())].into_iter().collect()
1147 }
1148 StackProbeType::Call => {
1149 [(String::from("kind"), "call".to_json())].into_iter().collect()
1150 }
1151 StackProbeType::InlineOrCall { min_llvm_version_for_inline: (maj, min, patch) } => [
1152 (String::from("kind"), "inline-or-call".to_json()),
1153 (
1154 String::from("min-llvm-version-for-inline"),
1155 Json::Array(vec![maj.to_json(), min.to_json(), patch.to_json()]),
1156 ),
1157 ]
1158 .into_iter()
1159 .collect(),
1160 })
1161 }
1162}
1163
1164#[derive(Default, Clone, Copy, PartialEq, Eq, Hash, Encodable, Decodable, HashStable_Generic)]
1165pub struct SanitizerSet(u16);
1166bitflags::bitflags! {
1167 impl SanitizerSet: u16 {
1168 const ADDRESS = 1 << 0;
1169 const LEAK = 1 << 1;
1170 const MEMORY = 1 << 2;
1171 const THREAD = 1 << 3;
1172 const HWADDRESS = 1 << 4;
1173 const CFI = 1 << 5;
1174 const MEMTAG = 1 << 6;
1175 const SHADOWCALLSTACK = 1 << 7;
1176 const KCFI = 1 << 8;
1177 const KERNELADDRESS = 1 << 9;
1178 const SAFESTACK = 1 << 10;
1179 const DATAFLOW = 1 << 11;
1180 const REALTIME = 1 << 12;
1181 }
1182}
1183rustc_data_structures::external_bitflags_debug! { SanitizerSet }
1184
1185impl SanitizerSet {
1186 const MUTUALLY_EXCLUSIVE: &'static [(SanitizerSet, SanitizerSet)] = &[
1189 (SanitizerSet::ADDRESS, SanitizerSet::MEMORY),
1190 (SanitizerSet::ADDRESS, SanitizerSet::THREAD),
1191 (SanitizerSet::ADDRESS, SanitizerSet::HWADDRESS),
1192 (SanitizerSet::ADDRESS, SanitizerSet::MEMTAG),
1193 (SanitizerSet::ADDRESS, SanitizerSet::KERNELADDRESS),
1194 (SanitizerSet::ADDRESS, SanitizerSet::SAFESTACK),
1195 (SanitizerSet::LEAK, SanitizerSet::MEMORY),
1196 (SanitizerSet::LEAK, SanitizerSet::THREAD),
1197 (SanitizerSet::LEAK, SanitizerSet::KERNELADDRESS),
1198 (SanitizerSet::LEAK, SanitizerSet::SAFESTACK),
1199 (SanitizerSet::MEMORY, SanitizerSet::THREAD),
1200 (SanitizerSet::MEMORY, SanitizerSet::HWADDRESS),
1201 (SanitizerSet::MEMORY, SanitizerSet::KERNELADDRESS),
1202 (SanitizerSet::MEMORY, SanitizerSet::SAFESTACK),
1203 (SanitizerSet::THREAD, SanitizerSet::HWADDRESS),
1204 (SanitizerSet::THREAD, SanitizerSet::KERNELADDRESS),
1205 (SanitizerSet::THREAD, SanitizerSet::SAFESTACK),
1206 (SanitizerSet::HWADDRESS, SanitizerSet::MEMTAG),
1207 (SanitizerSet::HWADDRESS, SanitizerSet::KERNELADDRESS),
1208 (SanitizerSet::HWADDRESS, SanitizerSet::SAFESTACK),
1209 (SanitizerSet::CFI, SanitizerSet::KCFI),
1210 (SanitizerSet::MEMTAG, SanitizerSet::KERNELADDRESS),
1211 (SanitizerSet::KERNELADDRESS, SanitizerSet::SAFESTACK),
1212 ];
1213
1214 pub fn as_str(self) -> Option<&'static str> {
1218 Some(match self {
1219 SanitizerSet::ADDRESS => "address",
1220 SanitizerSet::CFI => "cfi",
1221 SanitizerSet::DATAFLOW => "dataflow",
1222 SanitizerSet::KCFI => "kcfi",
1223 SanitizerSet::KERNELADDRESS => "kernel-address",
1224 SanitizerSet::LEAK => "leak",
1225 SanitizerSet::MEMORY => "memory",
1226 SanitizerSet::MEMTAG => "memtag",
1227 SanitizerSet::SAFESTACK => "safestack",
1228 SanitizerSet::SHADOWCALLSTACK => "shadow-call-stack",
1229 SanitizerSet::THREAD => "thread",
1230 SanitizerSet::HWADDRESS => "hwaddress",
1231 SanitizerSet::REALTIME => "realtime",
1232 _ => return None,
1233 })
1234 }
1235
1236 pub fn mutually_exclusive(self) -> Option<(SanitizerSet, SanitizerSet)> {
1237 Self::MUTUALLY_EXCLUSIVE
1238 .into_iter()
1239 .find(|&(a, b)| self.contains(*a) && self.contains(*b))
1240 .copied()
1241 }
1242}
1243
1244impl fmt::Display for SanitizerSet {
1246 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1247 let mut first = true;
1248 for s in *self {
1249 let name = s.as_str().unwrap_or_else(|| panic!("unrecognized sanitizer {s:?}"));
1250 if !first {
1251 f.write_str(", ")?;
1252 }
1253 f.write_str(name)?;
1254 first = false;
1255 }
1256 Ok(())
1257 }
1258}
1259
1260impl FromStr for SanitizerSet {
1261 type Err = String;
1262 fn from_str(s: &str) -> Result<Self, Self::Err> {
1263 Ok(match s {
1264 "address" => SanitizerSet::ADDRESS,
1265 "cfi" => SanitizerSet::CFI,
1266 "dataflow" => SanitizerSet::DATAFLOW,
1267 "kcfi" => SanitizerSet::KCFI,
1268 "kernel-address" => SanitizerSet::KERNELADDRESS,
1269 "leak" => SanitizerSet::LEAK,
1270 "memory" => SanitizerSet::MEMORY,
1271 "memtag" => SanitizerSet::MEMTAG,
1272 "safestack" => SanitizerSet::SAFESTACK,
1273 "shadow-call-stack" => SanitizerSet::SHADOWCALLSTACK,
1274 "thread" => SanitizerSet::THREAD,
1275 "hwaddress" => SanitizerSet::HWADDRESS,
1276 "realtime" => SanitizerSet::REALTIME,
1277 s => return Err(format!("unknown sanitizer {s}")),
1278 })
1279 }
1280}
1281
1282crate::json::serde_deserialize_from_str!(SanitizerSet);
1283impl schemars::JsonSchema for SanitizerSet {
1284 fn schema_name() -> std::borrow::Cow<'static, str> {
1285 "SanitizerSet".into()
1286 }
1287 fn json_schema(_: &mut schemars::SchemaGenerator) -> schemars::Schema {
1288 let all = Self::all().iter().map(|sanitizer| sanitizer.as_str()).collect::<Vec<_>>();
1289 schemars::json_schema! ({
1290 "type": "string",
1291 "enum": all,
1292 })
1293 .into()
1294 }
1295}
1296
1297impl ToJson for SanitizerSet {
1298 fn to_json(&self) -> Json {
1299 self.into_iter()
1300 .map(|v| Some(v.as_str()?.to_json()))
1301 .collect::<Option<Vec<_>>>()
1302 .unwrap_or_default()
1303 .to_json()
1304 }
1305}
1306
1307crate::target_spec_enum! {
1308 pub enum FramePointer {
1309 Always = "always",
1311 NonLeaf = "non-leaf",
1314 MayOmit = "may-omit",
1318 }
1319
1320 parse_error_type = "frame pointer";
1321}
1322
1323impl FramePointer {
1324 #[inline]
1327 pub fn ratchet(&mut self, rhs: FramePointer) -> FramePointer {
1328 *self = match (*self, rhs) {
1329 (FramePointer::Always, _) | (_, FramePointer::Always) => FramePointer::Always,
1330 (FramePointer::NonLeaf, _) | (_, FramePointer::NonLeaf) => FramePointer::NonLeaf,
1331 _ => FramePointer::MayOmit,
1332 };
1333 *self
1334 }
1335}
1336
1337crate::target_spec_enum! {
1338 pub enum StackProtector {
1340 None = "none",
1342
1343 Basic = "basic",
1348
1349 Strong = "strong",
1354
1355 All = "all",
1357 }
1358
1359 parse_error_type = "stack protector";
1360}
1361
1362into_diag_arg_using_display!(StackProtector);
1363
1364crate::target_spec_enum! {
1365 pub enum BinaryFormat {
1366 Coff = "coff",
1367 Elf = "elf",
1368 MachO = "mach-o",
1369 Wasm = "wasm",
1370 Xcoff = "xcoff",
1371 }
1372
1373 parse_error_type = "binary format";
1374}
1375
1376impl BinaryFormat {
1377 pub fn to_object(&self) -> object::BinaryFormat {
1379 match self {
1380 Self::Coff => object::BinaryFormat::Coff,
1381 Self::Elf => object::BinaryFormat::Elf,
1382 Self::MachO => object::BinaryFormat::MachO,
1383 Self::Wasm => object::BinaryFormat::Wasm,
1384 Self::Xcoff => object::BinaryFormat::Xcoff,
1385 }
1386 }
1387}
1388
1389impl ToJson for Align {
1390 fn to_json(&self) -> Json {
1391 self.bits().to_json()
1392 }
1393}
1394
1395macro_rules! supported_targets {
1396 ( $(($tuple:literal, $module:ident),)+ ) => {
1397 mod targets {
1398 $(pub(crate) mod $module;)+
1399 }
1400
1401 pub static TARGETS: &[&str] = &[$($tuple),+];
1403
1404 fn load_builtin(target: &str) -> Option<Target> {
1405 let t = match target {
1406 $( $tuple => targets::$module::target(), )+
1407 _ => return None,
1408 };
1409 debug!("got builtin target: {:?}", t);
1410 Some(t)
1411 }
1412
1413 fn load_all_builtins() -> impl Iterator<Item = Target> {
1414 [
1415 $( targets::$module::target, )+
1416 ]
1417 .into_iter()
1418 .map(|f| f())
1419 }
1420
1421 #[cfg(test)]
1422 mod tests {
1423 $(
1425 #[test] fn $module() {
1427 crate::spec::targets::$module::target().test_target()
1428 }
1429 )+
1430 }
1431 };
1432}
1433
1434supported_targets! {
1435 ("x86_64-unknown-linux-gnu", x86_64_unknown_linux_gnu),
1436 ("x86_64-unknown-linux-gnux32", x86_64_unknown_linux_gnux32),
1437 ("i686-unknown-linux-gnu", i686_unknown_linux_gnu),
1438 ("i586-unknown-linux-gnu", i586_unknown_linux_gnu),
1439 ("loongarch64-unknown-linux-gnu", loongarch64_unknown_linux_gnu),
1440 ("loongarch64-unknown-linux-musl", loongarch64_unknown_linux_musl),
1441 ("m68k-unknown-linux-gnu", m68k_unknown_linux_gnu),
1442 ("m68k-unknown-none-elf", m68k_unknown_none_elf),
1443 ("csky-unknown-linux-gnuabiv2", csky_unknown_linux_gnuabiv2),
1444 ("csky-unknown-linux-gnuabiv2hf", csky_unknown_linux_gnuabiv2hf),
1445 ("mips-unknown-linux-gnu", mips_unknown_linux_gnu),
1446 ("mips64-unknown-linux-gnuabi64", mips64_unknown_linux_gnuabi64),
1447 ("mips64el-unknown-linux-gnuabi64", mips64el_unknown_linux_gnuabi64),
1448 ("mipsisa32r6-unknown-linux-gnu", mipsisa32r6_unknown_linux_gnu),
1449 ("mipsisa32r6el-unknown-linux-gnu", mipsisa32r6el_unknown_linux_gnu),
1450 ("mipsisa64r6-unknown-linux-gnuabi64", mipsisa64r6_unknown_linux_gnuabi64),
1451 ("mipsisa64r6el-unknown-linux-gnuabi64", mipsisa64r6el_unknown_linux_gnuabi64),
1452 ("mipsel-unknown-linux-gnu", mipsel_unknown_linux_gnu),
1453 ("powerpc-unknown-linux-gnu", powerpc_unknown_linux_gnu),
1454 ("powerpc-unknown-linux-gnuspe", powerpc_unknown_linux_gnuspe),
1455 ("powerpc-unknown-linux-musl", powerpc_unknown_linux_musl),
1456 ("powerpc-unknown-linux-muslspe", powerpc_unknown_linux_muslspe),
1457 ("powerpc64-ibm-aix", powerpc64_ibm_aix),
1458 ("powerpc64-unknown-linux-gnu", powerpc64_unknown_linux_gnu),
1459 ("powerpc64-unknown-linux-musl", powerpc64_unknown_linux_musl),
1460 ("powerpc64le-unknown-linux-gnu", powerpc64le_unknown_linux_gnu),
1461 ("powerpc64le-unknown-linux-musl", powerpc64le_unknown_linux_musl),
1462 ("s390x-unknown-linux-gnu", s390x_unknown_linux_gnu),
1463 ("s390x-unknown-linux-musl", s390x_unknown_linux_musl),
1464 ("sparc-unknown-linux-gnu", sparc_unknown_linux_gnu),
1465 ("sparc64-unknown-linux-gnu", sparc64_unknown_linux_gnu),
1466 ("arm-unknown-linux-gnueabi", arm_unknown_linux_gnueabi),
1467 ("arm-unknown-linux-gnueabihf", arm_unknown_linux_gnueabihf),
1468 ("armeb-unknown-linux-gnueabi", armeb_unknown_linux_gnueabi),
1469 ("arm-unknown-linux-musleabi", arm_unknown_linux_musleabi),
1470 ("arm-unknown-linux-musleabihf", arm_unknown_linux_musleabihf),
1471 ("armv4t-unknown-linux-gnueabi", armv4t_unknown_linux_gnueabi),
1472 ("armv5te-unknown-linux-gnueabi", armv5te_unknown_linux_gnueabi),
1473 ("armv5te-unknown-linux-musleabi", armv5te_unknown_linux_musleabi),
1474 ("armv5te-unknown-linux-uclibceabi", armv5te_unknown_linux_uclibceabi),
1475 ("armv7-unknown-linux-gnueabi", armv7_unknown_linux_gnueabi),
1476 ("armv7-unknown-linux-gnueabihf", armv7_unknown_linux_gnueabihf),
1477 ("thumbv7neon-unknown-linux-gnueabihf", thumbv7neon_unknown_linux_gnueabihf),
1478 ("thumbv7neon-unknown-linux-musleabihf", thumbv7neon_unknown_linux_musleabihf),
1479 ("armv7-unknown-linux-musleabi", armv7_unknown_linux_musleabi),
1480 ("armv7-unknown-linux-musleabihf", armv7_unknown_linux_musleabihf),
1481 ("aarch64-unknown-linux-gnu", aarch64_unknown_linux_gnu),
1482 ("aarch64-unknown-linux-musl", aarch64_unknown_linux_musl),
1483 ("aarch64_be-unknown-linux-musl", aarch64_be_unknown_linux_musl),
1484 ("x86_64-unknown-linux-musl", x86_64_unknown_linux_musl),
1485 ("i686-unknown-linux-musl", i686_unknown_linux_musl),
1486 ("i586-unknown-linux-musl", i586_unknown_linux_musl),
1487 ("mips-unknown-linux-musl", mips_unknown_linux_musl),
1488 ("mipsel-unknown-linux-musl", mipsel_unknown_linux_musl),
1489 ("mips64-unknown-linux-muslabi64", mips64_unknown_linux_muslabi64),
1490 ("mips64el-unknown-linux-muslabi64", mips64el_unknown_linux_muslabi64),
1491 ("hexagon-unknown-linux-musl", hexagon_unknown_linux_musl),
1492 ("hexagon-unknown-none-elf", hexagon_unknown_none_elf),
1493 ("hexagon-unknown-qurt", hexagon_unknown_qurt),
1494
1495 ("mips-unknown-linux-uclibc", mips_unknown_linux_uclibc),
1496 ("mipsel-unknown-linux-uclibc", mipsel_unknown_linux_uclibc),
1497
1498 ("i686-linux-android", i686_linux_android),
1499 ("x86_64-linux-android", x86_64_linux_android),
1500 ("arm-linux-androideabi", arm_linux_androideabi),
1501 ("armv7-linux-androideabi", armv7_linux_androideabi),
1502 ("thumbv7neon-linux-androideabi", thumbv7neon_linux_androideabi),
1503 ("aarch64-linux-android", aarch64_linux_android),
1504 ("riscv64-linux-android", riscv64_linux_android),
1505
1506 ("aarch64-unknown-freebsd", aarch64_unknown_freebsd),
1507 ("armv6-unknown-freebsd", armv6_unknown_freebsd),
1508 ("armv7-unknown-freebsd", armv7_unknown_freebsd),
1509 ("i686-unknown-freebsd", i686_unknown_freebsd),
1510 ("powerpc-unknown-freebsd", powerpc_unknown_freebsd),
1511 ("powerpc64-unknown-freebsd", powerpc64_unknown_freebsd),
1512 ("powerpc64le-unknown-freebsd", powerpc64le_unknown_freebsd),
1513 ("riscv64gc-unknown-freebsd", riscv64gc_unknown_freebsd),
1514 ("x86_64-unknown-freebsd", x86_64_unknown_freebsd),
1515
1516 ("x86_64-unknown-dragonfly", x86_64_unknown_dragonfly),
1517
1518 ("aarch64-unknown-openbsd", aarch64_unknown_openbsd),
1519 ("i686-unknown-openbsd", i686_unknown_openbsd),
1520 ("powerpc-unknown-openbsd", powerpc_unknown_openbsd),
1521 ("powerpc64-unknown-openbsd", powerpc64_unknown_openbsd),
1522 ("riscv64gc-unknown-openbsd", riscv64gc_unknown_openbsd),
1523 ("sparc64-unknown-openbsd", sparc64_unknown_openbsd),
1524 ("x86_64-unknown-openbsd", x86_64_unknown_openbsd),
1525
1526 ("aarch64-unknown-netbsd", aarch64_unknown_netbsd),
1527 ("aarch64_be-unknown-netbsd", aarch64_be_unknown_netbsd),
1528 ("armv6-unknown-netbsd-eabihf", armv6_unknown_netbsd_eabihf),
1529 ("armv7-unknown-netbsd-eabihf", armv7_unknown_netbsd_eabihf),
1530 ("i586-unknown-netbsd", i586_unknown_netbsd),
1531 ("i686-unknown-netbsd", i686_unknown_netbsd),
1532 ("mipsel-unknown-netbsd", mipsel_unknown_netbsd),
1533 ("powerpc-unknown-netbsd", powerpc_unknown_netbsd),
1534 ("riscv64gc-unknown-netbsd", riscv64gc_unknown_netbsd),
1535 ("sparc64-unknown-netbsd", sparc64_unknown_netbsd),
1536 ("x86_64-unknown-netbsd", x86_64_unknown_netbsd),
1537
1538 ("i686-unknown-haiku", i686_unknown_haiku),
1539 ("x86_64-unknown-haiku", x86_64_unknown_haiku),
1540
1541 ("aarch64-unknown-helenos", aarch64_unknown_helenos),
1542 ("i686-unknown-helenos", i686_unknown_helenos),
1543 ("powerpc-unknown-helenos", powerpc_unknown_helenos),
1544 ("sparc64-unknown-helenos", sparc64_unknown_helenos),
1545 ("x86_64-unknown-helenos", x86_64_unknown_helenos),
1546
1547 ("i686-unknown-hurd-gnu", i686_unknown_hurd_gnu),
1548 ("x86_64-unknown-hurd-gnu", x86_64_unknown_hurd_gnu),
1549
1550 ("aarch64-apple-darwin", aarch64_apple_darwin),
1551 ("arm64e-apple-darwin", arm64e_apple_darwin),
1552 ("x86_64-apple-darwin", x86_64_apple_darwin),
1553 ("x86_64h-apple-darwin", x86_64h_apple_darwin),
1554 ("i686-apple-darwin", i686_apple_darwin),
1555
1556 ("aarch64-unknown-fuchsia", aarch64_unknown_fuchsia),
1557 ("riscv64gc-unknown-fuchsia", riscv64gc_unknown_fuchsia),
1558 ("x86_64-unknown-fuchsia", x86_64_unknown_fuchsia),
1559
1560 ("avr-none", avr_none),
1561
1562 ("x86_64-unknown-l4re-uclibc", x86_64_unknown_l4re_uclibc),
1563
1564 ("aarch64-unknown-redox", aarch64_unknown_redox),
1565 ("i586-unknown-redox", i586_unknown_redox),
1566 ("riscv64gc-unknown-redox", riscv64gc_unknown_redox),
1567 ("x86_64-unknown-redox", x86_64_unknown_redox),
1568
1569 ("x86_64-unknown-managarm-mlibc", x86_64_unknown_managarm_mlibc),
1570 ("aarch64-unknown-managarm-mlibc", aarch64_unknown_managarm_mlibc),
1571 ("riscv64gc-unknown-managarm-mlibc", riscv64gc_unknown_managarm_mlibc),
1572
1573 ("i386-apple-ios", i386_apple_ios),
1574 ("x86_64-apple-ios", x86_64_apple_ios),
1575 ("aarch64-apple-ios", aarch64_apple_ios),
1576 ("arm64e-apple-ios", arm64e_apple_ios),
1577 ("armv7s-apple-ios", armv7s_apple_ios),
1578 ("x86_64-apple-ios-macabi", x86_64_apple_ios_macabi),
1579 ("aarch64-apple-ios-macabi", aarch64_apple_ios_macabi),
1580 ("aarch64-apple-ios-sim", aarch64_apple_ios_sim),
1581
1582 ("aarch64-apple-tvos", aarch64_apple_tvos),
1583 ("aarch64-apple-tvos-sim", aarch64_apple_tvos_sim),
1584 ("arm64e-apple-tvos", arm64e_apple_tvos),
1585 ("x86_64-apple-tvos", x86_64_apple_tvos),
1586
1587 ("armv7k-apple-watchos", armv7k_apple_watchos),
1588 ("arm64_32-apple-watchos", arm64_32_apple_watchos),
1589 ("x86_64-apple-watchos-sim", x86_64_apple_watchos_sim),
1590 ("aarch64-apple-watchos", aarch64_apple_watchos),
1591 ("aarch64-apple-watchos-sim", aarch64_apple_watchos_sim),
1592
1593 ("aarch64-apple-visionos", aarch64_apple_visionos),
1594 ("aarch64-apple-visionos-sim", aarch64_apple_visionos_sim),
1595
1596 ("armebv7r-none-eabi", armebv7r_none_eabi),
1597 ("armebv7r-none-eabihf", armebv7r_none_eabihf),
1598 ("armv7r-none-eabi", armv7r_none_eabi),
1599 ("armv7r-none-eabihf", armv7r_none_eabihf),
1600 ("armv8r-none-eabihf", armv8r_none_eabihf),
1601
1602 ("armv7-rtems-eabihf", armv7_rtems_eabihf),
1603
1604 ("x86_64-pc-solaris", x86_64_pc_solaris),
1605 ("sparcv9-sun-solaris", sparcv9_sun_solaris),
1606
1607 ("x86_64-unknown-illumos", x86_64_unknown_illumos),
1608 ("aarch64-unknown-illumos", aarch64_unknown_illumos),
1609
1610 ("x86_64-pc-windows-gnu", x86_64_pc_windows_gnu),
1611 ("x86_64-uwp-windows-gnu", x86_64_uwp_windows_gnu),
1612 ("x86_64-win7-windows-gnu", x86_64_win7_windows_gnu),
1613 ("i686-pc-windows-gnu", i686_pc_windows_gnu),
1614 ("i686-uwp-windows-gnu", i686_uwp_windows_gnu),
1615 ("i686-win7-windows-gnu", i686_win7_windows_gnu),
1616
1617 ("aarch64-pc-windows-gnullvm", aarch64_pc_windows_gnullvm),
1618 ("i686-pc-windows-gnullvm", i686_pc_windows_gnullvm),
1619 ("x86_64-pc-windows-gnullvm", x86_64_pc_windows_gnullvm),
1620
1621 ("aarch64-pc-windows-msvc", aarch64_pc_windows_msvc),
1622 ("aarch64-uwp-windows-msvc", aarch64_uwp_windows_msvc),
1623 ("arm64ec-pc-windows-msvc", arm64ec_pc_windows_msvc),
1624 ("x86_64-pc-windows-msvc", x86_64_pc_windows_msvc),
1625 ("x86_64-uwp-windows-msvc", x86_64_uwp_windows_msvc),
1626 ("x86_64-win7-windows-msvc", x86_64_win7_windows_msvc),
1627 ("i686-pc-windows-msvc", i686_pc_windows_msvc),
1628 ("i686-uwp-windows-msvc", i686_uwp_windows_msvc),
1629 ("i686-win7-windows-msvc", i686_win7_windows_msvc),
1630 ("thumbv7a-pc-windows-msvc", thumbv7a_pc_windows_msvc),
1631 ("thumbv7a-uwp-windows-msvc", thumbv7a_uwp_windows_msvc),
1632
1633 ("wasm32-unknown-emscripten", wasm32_unknown_emscripten),
1634 ("wasm32-unknown-unknown", wasm32_unknown_unknown),
1635 ("wasm32v1-none", wasm32v1_none),
1636 ("wasm32-wasip1", wasm32_wasip1),
1637 ("wasm32-wasip2", wasm32_wasip2),
1638 ("wasm32-wasip3", wasm32_wasip3),
1639 ("wasm32-wasip1-threads", wasm32_wasip1_threads),
1640 ("wasm32-wali-linux-musl", wasm32_wali_linux_musl),
1641 ("wasm64-unknown-unknown", wasm64_unknown_unknown),
1642
1643 ("thumbv6m-none-eabi", thumbv6m_none_eabi),
1644 ("thumbv7m-none-eabi", thumbv7m_none_eabi),
1645 ("thumbv7em-none-eabi", thumbv7em_none_eabi),
1646 ("thumbv7em-none-eabihf", thumbv7em_none_eabihf),
1647 ("thumbv8m.base-none-eabi", thumbv8m_base_none_eabi),
1648 ("thumbv8m.main-none-eabi", thumbv8m_main_none_eabi),
1649 ("thumbv8m.main-none-eabihf", thumbv8m_main_none_eabihf),
1650
1651 ("armv7a-none-eabi", armv7a_none_eabi),
1652 ("armv7a-none-eabihf", armv7a_none_eabihf),
1653 ("armv7a-nuttx-eabi", armv7a_nuttx_eabi),
1654 ("armv7a-nuttx-eabihf", armv7a_nuttx_eabihf),
1655 ("armv7a-vex-v5", armv7a_vex_v5),
1656
1657 ("msp430-none-elf", msp430_none_elf),
1658
1659 ("aarch64_be-unknown-hermit", aarch64_be_unknown_hermit),
1660 ("aarch64-unknown-hermit", aarch64_unknown_hermit),
1661 ("riscv64gc-unknown-hermit", riscv64gc_unknown_hermit),
1662 ("x86_64-unknown-hermit", x86_64_unknown_hermit),
1663 ("x86_64-unknown-motor", x86_64_unknown_motor),
1664
1665 ("x86_64-unikraft-linux-musl", x86_64_unikraft_linux_musl),
1666
1667 ("armv7-unknown-trusty", armv7_unknown_trusty),
1668 ("aarch64-unknown-trusty", aarch64_unknown_trusty),
1669 ("x86_64-unknown-trusty", x86_64_unknown_trusty),
1670
1671 ("riscv32i-unknown-none-elf", riscv32i_unknown_none_elf),
1672 ("riscv32im-risc0-zkvm-elf", riscv32im_risc0_zkvm_elf),
1673 ("riscv32im-unknown-none-elf", riscv32im_unknown_none_elf),
1674 ("riscv32ima-unknown-none-elf", riscv32ima_unknown_none_elf),
1675 ("riscv32imc-unknown-none-elf", riscv32imc_unknown_none_elf),
1676 ("riscv32imc-esp-espidf", riscv32imc_esp_espidf),
1677 ("riscv32imac-esp-espidf", riscv32imac_esp_espidf),
1678 ("riscv32imafc-esp-espidf", riscv32imafc_esp_espidf),
1679
1680 ("riscv32e-unknown-none-elf", riscv32e_unknown_none_elf),
1681 ("riscv32em-unknown-none-elf", riscv32em_unknown_none_elf),
1682 ("riscv32emc-unknown-none-elf", riscv32emc_unknown_none_elf),
1683
1684 ("riscv32imac-unknown-none-elf", riscv32imac_unknown_none_elf),
1685 ("riscv32imafc-unknown-none-elf", riscv32imafc_unknown_none_elf),
1686 ("riscv32imac-unknown-xous-elf", riscv32imac_unknown_xous_elf),
1687 ("riscv32gc-unknown-linux-gnu", riscv32gc_unknown_linux_gnu),
1688 ("riscv32gc-unknown-linux-musl", riscv32gc_unknown_linux_musl),
1689 ("riscv64imac-unknown-none-elf", riscv64imac_unknown_none_elf),
1690 ("riscv64gc-unknown-none-elf", riscv64gc_unknown_none_elf),
1691 ("riscv64gc-unknown-linux-gnu", riscv64gc_unknown_linux_gnu),
1692 ("riscv64gc-unknown-linux-musl", riscv64gc_unknown_linux_musl),
1693 ("riscv64a23-unknown-linux-gnu", riscv64a23_unknown_linux_gnu),
1694
1695 ("sparc-unknown-none-elf", sparc_unknown_none_elf),
1696
1697 ("loongarch32-unknown-none", loongarch32_unknown_none),
1698 ("loongarch32-unknown-none-softfloat", loongarch32_unknown_none_softfloat),
1699 ("loongarch64-unknown-none", loongarch64_unknown_none),
1700 ("loongarch64-unknown-none-softfloat", loongarch64_unknown_none_softfloat),
1701
1702 ("aarch64-unknown-none", aarch64_unknown_none),
1703 ("aarch64-unknown-none-softfloat", aarch64_unknown_none_softfloat),
1704 ("aarch64_be-unknown-none-softfloat", aarch64_be_unknown_none_softfloat),
1705 ("aarch64-unknown-nuttx", aarch64_unknown_nuttx),
1706
1707 ("x86_64-fortanix-unknown-sgx", x86_64_fortanix_unknown_sgx),
1708
1709 ("x86_64-unknown-uefi", x86_64_unknown_uefi),
1710 ("i686-unknown-uefi", i686_unknown_uefi),
1711 ("aarch64-unknown-uefi", aarch64_unknown_uefi),
1712
1713 ("nvptx64-nvidia-cuda", nvptx64_nvidia_cuda),
1714
1715 ("amdgcn-amd-amdhsa", amdgcn_amd_amdhsa),
1716
1717 ("xtensa-esp32-none-elf", xtensa_esp32_none_elf),
1718 ("xtensa-esp32-espidf", xtensa_esp32_espidf),
1719 ("xtensa-esp32s2-none-elf", xtensa_esp32s2_none_elf),
1720 ("xtensa-esp32s2-espidf", xtensa_esp32s2_espidf),
1721 ("xtensa-esp32s3-none-elf", xtensa_esp32s3_none_elf),
1722 ("xtensa-esp32s3-espidf", xtensa_esp32s3_espidf),
1723
1724 ("i686-wrs-vxworks", i686_wrs_vxworks),
1725 ("x86_64-wrs-vxworks", x86_64_wrs_vxworks),
1726 ("armv7-wrs-vxworks-eabihf", armv7_wrs_vxworks_eabihf),
1727 ("aarch64-wrs-vxworks", aarch64_wrs_vxworks),
1728 ("powerpc-wrs-vxworks", powerpc_wrs_vxworks),
1729 ("powerpc-wrs-vxworks-spe", powerpc_wrs_vxworks_spe),
1730 ("powerpc64-wrs-vxworks", powerpc64_wrs_vxworks),
1731 ("riscv32-wrs-vxworks", riscv32_wrs_vxworks),
1732 ("riscv64-wrs-vxworks", riscv64_wrs_vxworks),
1733
1734 ("aarch64-kmc-solid_asp3", aarch64_kmc_solid_asp3),
1735 ("armv7a-kmc-solid_asp3-eabi", armv7a_kmc_solid_asp3_eabi),
1736 ("armv7a-kmc-solid_asp3-eabihf", armv7a_kmc_solid_asp3_eabihf),
1737
1738 ("mipsel-sony-psp", mipsel_sony_psp),
1739 ("mipsel-sony-psx", mipsel_sony_psx),
1740 ("mipsel-unknown-none", mipsel_unknown_none),
1741 ("mips-mti-none-elf", mips_mti_none_elf),
1742 ("mipsel-mti-none-elf", mipsel_mti_none_elf),
1743 ("thumbv4t-none-eabi", thumbv4t_none_eabi),
1744 ("armv4t-none-eabi", armv4t_none_eabi),
1745 ("thumbv5te-none-eabi", thumbv5te_none_eabi),
1746 ("armv5te-none-eabi", armv5te_none_eabi),
1747
1748 ("aarch64_be-unknown-linux-gnu", aarch64_be_unknown_linux_gnu),
1749 ("aarch64-unknown-linux-gnu_ilp32", aarch64_unknown_linux_gnu_ilp32),
1750 ("aarch64_be-unknown-linux-gnu_ilp32", aarch64_be_unknown_linux_gnu_ilp32),
1751
1752 ("bpfeb-unknown-none", bpfeb_unknown_none),
1753 ("bpfel-unknown-none", bpfel_unknown_none),
1754
1755 ("armv6k-nintendo-3ds", armv6k_nintendo_3ds),
1756
1757 ("aarch64-nintendo-switch-freestanding", aarch64_nintendo_switch_freestanding),
1758
1759 ("armv7-sony-vita-newlibeabihf", armv7_sony_vita_newlibeabihf),
1760
1761 ("armv7-unknown-linux-uclibceabi", armv7_unknown_linux_uclibceabi),
1762 ("armv7-unknown-linux-uclibceabihf", armv7_unknown_linux_uclibceabihf),
1763
1764 ("x86_64-unknown-none", x86_64_unknown_none),
1765
1766 ("aarch64-unknown-teeos", aarch64_unknown_teeos),
1767
1768 ("mips64-openwrt-linux-musl", mips64_openwrt_linux_musl),
1769
1770 ("aarch64-unknown-nto-qnx700", aarch64_unknown_nto_qnx700),
1771 ("aarch64-unknown-nto-qnx710", aarch64_unknown_nto_qnx710),
1772 ("aarch64-unknown-nto-qnx710_iosock", aarch64_unknown_nto_qnx710_iosock),
1773 ("aarch64-unknown-nto-qnx800", aarch64_unknown_nto_qnx800),
1774 ("x86_64-pc-nto-qnx710", x86_64_pc_nto_qnx710),
1775 ("x86_64-pc-nto-qnx710_iosock", x86_64_pc_nto_qnx710_iosock),
1776 ("x86_64-pc-nto-qnx800", x86_64_pc_nto_qnx800),
1777 ("i686-pc-nto-qnx700", i686_pc_nto_qnx700),
1778
1779 ("aarch64-unknown-linux-ohos", aarch64_unknown_linux_ohos),
1780 ("armv7-unknown-linux-ohos", armv7_unknown_linux_ohos),
1781 ("loongarch64-unknown-linux-ohos", loongarch64_unknown_linux_ohos),
1782 ("x86_64-unknown-linux-ohos", x86_64_unknown_linux_ohos),
1783
1784 ("x86_64-unknown-linux-none", x86_64_unknown_linux_none),
1785
1786 ("thumbv6m-nuttx-eabi", thumbv6m_nuttx_eabi),
1787 ("thumbv7a-nuttx-eabi", thumbv7a_nuttx_eabi),
1788 ("thumbv7a-nuttx-eabihf", thumbv7a_nuttx_eabihf),
1789 ("thumbv7m-nuttx-eabi", thumbv7m_nuttx_eabi),
1790 ("thumbv7em-nuttx-eabi", thumbv7em_nuttx_eabi),
1791 ("thumbv7em-nuttx-eabihf", thumbv7em_nuttx_eabihf),
1792 ("thumbv8m.base-nuttx-eabi", thumbv8m_base_nuttx_eabi),
1793 ("thumbv8m.main-nuttx-eabi", thumbv8m_main_nuttx_eabi),
1794 ("thumbv8m.main-nuttx-eabihf", thumbv8m_main_nuttx_eabihf),
1795 ("riscv32imc-unknown-nuttx-elf", riscv32imc_unknown_nuttx_elf),
1796 ("riscv32imac-unknown-nuttx-elf", riscv32imac_unknown_nuttx_elf),
1797 ("riscv32imafc-unknown-nuttx-elf", riscv32imafc_unknown_nuttx_elf),
1798 ("riscv64imac-unknown-nuttx-elf", riscv64imac_unknown_nuttx_elf),
1799 ("riscv64gc-unknown-nuttx-elf", riscv64gc_unknown_nuttx_elf),
1800 ("x86_64-lynx-lynxos178", x86_64_lynx_lynxos178),
1801
1802 ("x86_64-pc-cygwin", x86_64_pc_cygwin),
1803}
1804
1805macro_rules! cvs {
1807 () => {
1808 ::std::borrow::Cow::Borrowed(&[])
1809 };
1810 ($($x:expr),+ $(,)?) => {
1811 ::std::borrow::Cow::Borrowed(&[
1812 $(
1813 ::std::borrow::Cow::Borrowed($x),
1814 )*
1815 ])
1816 };
1817}
1818
1819pub(crate) use cvs;
1820
1821#[derive(Debug, PartialEq)]
1825pub struct TargetWarnings {
1826 unused_fields: Vec<String>,
1827}
1828
1829impl TargetWarnings {
1830 pub fn empty() -> Self {
1831 Self { unused_fields: Vec::new() }
1832 }
1833
1834 pub fn warning_messages(&self) -> Vec<String> {
1835 let mut warnings = vec![];
1836 if !self.unused_fields.is_empty() {
1837 warnings.push(format!(
1838 "target json file contains unused fields: {}",
1839 self.unused_fields.join(", ")
1840 ));
1841 }
1842 warnings
1843 }
1844}
1845
1846#[derive(Copy, Clone, Debug, PartialEq)]
1849enum TargetKind {
1850 Json,
1851 Builtin,
1852}
1853
1854crate::target_spec_enum! {
1855 pub enum Arch {
1856 AArch64 = "aarch64",
1857 AmdGpu = "amdgpu",
1858 Arm = "arm",
1859 Arm64EC = "arm64ec",
1860 Avr = "avr",
1861 Bpf = "bpf",
1862 CSky = "csky",
1863 Hexagon = "hexagon",
1864 LoongArch32 = "loongarch32",
1865 LoongArch64 = "loongarch64",
1866 M68k = "m68k",
1867 Mips = "mips",
1868 Mips32r6 = "mips32r6",
1869 Mips64 = "mips64",
1870 Mips64r6 = "mips64r6",
1871 Msp430 = "msp430",
1872 Nvptx64 = "nvptx64",
1873 PowerPC = "powerpc",
1874 PowerPC64 = "powerpc64",
1875 PowerPC64LE = "powerpc64le",
1876 RiscV32 = "riscv32",
1877 RiscV64 = "riscv64",
1878 S390x = "s390x",
1879 Sparc = "sparc",
1880 Sparc64 = "sparc64",
1881 SpirV = "spirv",
1882 Wasm32 = "wasm32",
1883 Wasm64 = "wasm64",
1884 X86 = "x86",
1885 X86_64 = "x86_64",
1886 Xtensa = "xtensa",
1887 }
1888 other_variant = Other;
1889}
1890
1891impl Arch {
1892 pub fn desc_symbol(&self) -> Symbol {
1893 match self {
1894 Self::AArch64 => sym::aarch64,
1895 Self::AmdGpu => sym::amdgpu,
1896 Self::Arm => sym::arm,
1897 Self::Arm64EC => sym::arm64ec,
1898 Self::Avr => sym::avr,
1899 Self::Bpf => sym::bpf,
1900 Self::CSky => sym::csky,
1901 Self::Hexagon => sym::hexagon,
1902 Self::LoongArch32 => sym::loongarch32,
1903 Self::LoongArch64 => sym::loongarch64,
1904 Self::M68k => sym::m68k,
1905 Self::Mips => sym::mips,
1906 Self::Mips32r6 => sym::mips32r6,
1907 Self::Mips64 => sym::mips64,
1908 Self::Mips64r6 => sym::mips64r6,
1909 Self::Msp430 => sym::msp430,
1910 Self::Nvptx64 => sym::nvptx64,
1911 Self::PowerPC => sym::powerpc,
1912 Self::PowerPC64 => sym::powerpc64,
1913 Self::PowerPC64LE => sym::powerpc64le,
1914 Self::RiscV32 => sym::riscv32,
1915 Self::RiscV64 => sym::riscv64,
1916 Self::S390x => sym::s390x,
1917 Self::Sparc => sym::sparc,
1918 Self::Sparc64 => sym::sparc64,
1919 Self::SpirV => sym::spirv,
1920 Self::Wasm32 => sym::wasm32,
1921 Self::Wasm64 => sym::wasm64,
1922 Self::X86 => sym::x86,
1923 Self::X86_64 => sym::x86_64,
1924 Self::Xtensa => sym::xtensa,
1925 Self::Other(name) => rustc_span::Symbol::intern(name),
1926 }
1927 }
1928
1929 pub fn supports_c_variadic_definitions(&self) -> bool {
1930 use Arch::*;
1931
1932 match self {
1933 Bpf | SpirV => false,
1935
1936 Other(_) => true,
1939
1940 AArch64 | AmdGpu | Arm | Arm64EC | Avr | CSky | Hexagon | LoongArch32 | LoongArch64
1941 | M68k | Mips | Mips32r6 | Mips64 | Mips64r6 | Msp430 | Nvptx64 | PowerPC
1942 | PowerPC64 | PowerPC64LE | RiscV32 | RiscV64 | S390x | Sparc | Sparc64 | Wasm32
1943 | Wasm64 | X86 | X86_64 | Xtensa => true,
1944 }
1945 }
1946}
1947
1948crate::target_spec_enum! {
1949 pub enum Os {
1950 Aix = "aix",
1951 AmdHsa = "amdhsa",
1952 Android = "android",
1953 Cuda = "cuda",
1954 Cygwin = "cygwin",
1955 Dragonfly = "dragonfly",
1956 Emscripten = "emscripten",
1957 EspIdf = "espidf",
1958 FreeBsd = "freebsd",
1959 Fuchsia = "fuchsia",
1960 Haiku = "haiku",
1961 HelenOs = "helenos",
1962 Hermit = "hermit",
1963 Horizon = "horizon",
1964 Hurd = "hurd",
1965 Illumos = "illumos",
1966 IOs = "ios",
1967 L4Re = "l4re",
1968 Linux = "linux",
1969 LynxOs178 = "lynxos178",
1970 MacOs = "macos",
1971 Managarm = "managarm",
1972 Motor = "motor",
1973 NetBsd = "netbsd",
1974 None = "none",
1975 Nto = "nto",
1976 NuttX = "nuttx",
1977 OpenBsd = "openbsd",
1978 Psp = "psp",
1979 Psx = "psx",
1980 Qurt = "qurt",
1981 Redox = "redox",
1982 Rtems = "rtems",
1983 Solaris = "solaris",
1984 SolidAsp3 = "solid_asp3",
1985 TeeOs = "teeos",
1986 Trusty = "trusty",
1987 TvOs = "tvos",
1988 Uefi = "uefi",
1989 VexOs = "vexos",
1990 VisionOs = "visionos",
1991 Vita = "vita",
1992 VxWorks = "vxworks",
1993 Wasi = "wasi",
1994 WatchOs = "watchos",
1995 Windows = "windows",
1996 Xous = "xous",
1997 Zkvm = "zkvm",
1998 Unknown = "unknown",
1999 }
2000 other_variant = Other;
2001}
2002
2003impl Os {
2004 pub fn desc_symbol(&self) -> Symbol {
2005 Symbol::intern(self.desc())
2006 }
2007}
2008
2009crate::target_spec_enum! {
2010 pub enum Env {
2011 Gnu = "gnu",
2012 MacAbi = "macabi",
2013 Mlibc = "mlibc",
2014 Msvc = "msvc",
2015 Musl = "musl",
2016 Newlib = "newlib",
2017 Nto70 = "nto70",
2018 Nto71 = "nto71",
2019 Nto71IoSock = "nto71_iosock",
2020 Nto80 = "nto80",
2021 Ohos = "ohos",
2022 Relibc = "relibc",
2023 Sgx = "sgx",
2024 Sim = "sim",
2025 P1 = "p1",
2026 P2 = "p2",
2027 P3 = "p3",
2028 Uclibc = "uclibc",
2029 V5 = "v5",
2030 Unspecified = "",
2031 }
2032 other_variant = Other;
2033}
2034
2035impl Env {
2036 pub fn desc_symbol(&self) -> Symbol {
2037 Symbol::intern(self.desc())
2038 }
2039}
2040
2041crate::target_spec_enum! {
2042 pub enum Abi {
2043 Abi64 = "abi64",
2044 AbiV2 = "abiv2",
2045 AbiV2Hf = "abiv2hf",
2046 Eabi = "eabi",
2047 EabiHf = "eabihf",
2048 ElfV1 = "elfv1",
2049 ElfV2 = "elfv2",
2050 Fortanix = "fortanix",
2051 Ilp32 = "ilp32",
2052 Ilp32e = "ilp32e",
2053 Llvm = "llvm",
2054 MacAbi = "macabi",
2055 Sim = "sim",
2056 SoftFloat = "softfloat",
2057 Spe = "spe",
2058 Uwp = "uwp",
2059 VecDefault = "vec-default",
2060 VecExtAbi = "vec-extabi",
2061 X32 = "x32",
2062 Unspecified = "",
2063 }
2064 other_variant = Other;
2065}
2066
2067impl Abi {
2068 pub fn desc_symbol(&self) -> Symbol {
2069 Symbol::intern(self.desc())
2070 }
2071}
2072
2073#[derive(PartialEq, Clone, Debug)]
2077pub struct Target {
2078 pub llvm_target: StaticCow<str>,
2085 pub metadata: TargetMetadata,
2088 pub pointer_width: u16,
2090 pub arch: Arch,
2093 pub data_layout: StaticCow<str>,
2095 pub options: TargetOptions,
2097}
2098
2099#[derive(Default, PartialEq, Clone, Debug)]
2103pub struct TargetMetadata {
2104 pub description: Option<StaticCow<str>>,
2107 pub tier: Option<u64>,
2109 pub host_tools: Option<bool>,
2111 pub std: Option<bool>,
2114}
2115
2116impl Target {
2117 pub fn parse_data_layout(&self) -> Result<TargetDataLayout, TargetDataLayoutErrors<'_>> {
2118 let mut dl = TargetDataLayout::parse_from_llvm_datalayout_string(
2119 &self.data_layout,
2120 self.options.default_address_space,
2121 )?;
2122
2123 if dl.endian != self.endian {
2125 return Err(TargetDataLayoutErrors::InconsistentTargetArchitecture {
2126 dl: dl.endian.as_str(),
2127 target: self.endian.as_str(),
2128 });
2129 }
2130
2131 let target_pointer_width: u64 = self.pointer_width.into();
2132 let dl_pointer_size: u64 = dl.pointer_size().bits();
2133 if dl_pointer_size != target_pointer_width {
2134 return Err(TargetDataLayoutErrors::InconsistentTargetPointerWidth {
2135 pointer_size: dl_pointer_size,
2136 target: self.pointer_width,
2137 });
2138 }
2139
2140 dl.c_enum_min_size = Integer::from_size(Size::from_bits(
2141 self.c_enum_min_bits.unwrap_or(self.c_int_width as _),
2142 ))
2143 .map_err(|err| TargetDataLayoutErrors::InvalidBitsSize { err })?;
2144
2145 Ok(dl)
2146 }
2147}
2148
2149pub trait HasTargetSpec {
2150 fn target_spec(&self) -> &Target;
2151}
2152
2153impl HasTargetSpec for Target {
2154 #[inline]
2155 fn target_spec(&self) -> &Target {
2156 self
2157 }
2158}
2159
2160#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
2162pub struct X86Abi {
2163 pub regparm: Option<u32>,
2166 pub reg_struct_return: bool,
2168}
2169
2170pub trait HasX86AbiOpt {
2171 fn x86_abi_opt(&self) -> X86Abi;
2172}
2173
2174type StaticCow<T> = Cow<'static, T>;
2175
2176#[derive(PartialEq, Clone, Debug)]
2185#[rustc_lint_opt_ty]
2186pub struct TargetOptions {
2187 pub endian: Endian,
2189 pub c_int_width: u16,
2191 pub os: Os,
2196 pub env: Env,
2198 pub abi: Abi,
2203 #[rustc_lint_opt_deny_field_access(
2205 "use `Target::is_like_*` instead of this field; see https://github.com/rust-lang/rust/issues/100343 for rationale"
2206 )]
2207 vendor: StaticCow<str>,
2208
2209 pub linker: Option<StaticCow<str>>,
2211 pub linker_flavor: LinkerFlavor,
2214 linker_flavor_json: LinkerFlavorCli,
2215 lld_flavor_json: LldFlavor,
2216 linker_is_gnu_json: bool,
2217
2218 pub pre_link_objects: CrtObjects,
2220 pub post_link_objects: CrtObjects,
2221 pub pre_link_objects_self_contained: CrtObjects,
2223 pub post_link_objects_self_contained: CrtObjects,
2224 pub link_self_contained: LinkSelfContainedDefault,
2227
2228 pub pre_link_args: LinkArgs,
2230 pre_link_args_json: LinkArgsCli,
2231 pub late_link_args: LinkArgs,
2235 late_link_args_json: LinkArgsCli,
2236 pub late_link_args_dynamic: LinkArgs,
2239 late_link_args_dynamic_json: LinkArgsCli,
2240 pub late_link_args_static: LinkArgs,
2243 late_link_args_static_json: LinkArgsCli,
2244 pub post_link_args: LinkArgs,
2247 post_link_args_json: LinkArgsCli,
2248
2249 pub link_script: Option<StaticCow<str>>,
2253 pub link_env: StaticCow<[(StaticCow<str>, StaticCow<str>)]>,
2255 pub link_env_remove: StaticCow<[StaticCow<str>]>,
2257
2258 pub asm_args: StaticCow<[StaticCow<str>]>,
2260
2261 pub cpu: StaticCow<str>,
2264 pub need_explicit_cpu: bool,
2267 pub features: StaticCow<str>,
2276 pub direct_access_external_data: Option<bool>,
2278 pub dynamic_linking: bool,
2280 pub dll_tls_export: bool,
2282 pub only_cdylib: bool,
2284 pub executables: bool,
2286 pub relocation_model: RelocModel,
2289 pub code_model: Option<CodeModel>,
2292 pub tls_model: TlsModel,
2295 pub disable_redzone: bool,
2297 pub frame_pointer: FramePointer,
2299 pub function_sections: bool,
2301 pub dll_prefix: StaticCow<str>,
2303 pub dll_suffix: StaticCow<str>,
2305 pub exe_suffix: StaticCow<str>,
2307 pub staticlib_prefix: StaticCow<str>,
2309 pub staticlib_suffix: StaticCow<str>,
2311 pub families: StaticCow<[StaticCow<str>]>,
2317 pub abi_return_struct_as_int: bool,
2319 pub is_like_aix: bool,
2322 pub is_like_darwin: bool,
2327 pub is_like_gpu: bool,
2329 pub is_like_solaris: bool,
2333 pub is_like_windows: bool,
2341 pub is_like_msvc: bool,
2351 pub is_like_wasm: bool,
2353 pub is_like_android: bool,
2355 pub is_like_vexos: bool,
2357 pub binary_format: BinaryFormat,
2359 pub default_dwarf_version: u32,
2362 pub allows_weak_linkage: bool,
2369 pub has_rpath: bool,
2371 pub no_default_libraries: bool,
2374 pub position_independent_executables: bool,
2380 pub static_position_independent_executables: bool,
2382 pub plt_by_default: bool,
2385 pub relro_level: RelroLevel,
2389 pub archive_format: StaticCow<str>,
2394 pub allow_asm: bool,
2396 pub main_needs_argc_argv: bool,
2399
2400 pub has_thread_local: bool,
2402 pub obj_is_bitcode: bool,
2406
2407 pub min_atomic_width: Option<u64>,
2409
2410 pub max_atomic_width: Option<u64>,
2412
2413 pub atomic_cas: bool,
2415
2416 pub panic_strategy: PanicStrategy,
2418
2419 pub crt_static_allows_dylibs: bool,
2421 pub crt_static_default: bool,
2423 pub crt_static_respected: bool,
2425
2426 pub stack_probes: StackProbeType,
2428
2429 pub min_global_align: Option<Align>,
2431
2432 pub default_codegen_units: Option<u64>,
2434
2435 pub default_codegen_backend: Option<StaticCow<str>>,
2445
2446 pub trap_unreachable: bool,
2449
2450 pub requires_lto: bool,
2453
2454 pub singlethread: bool,
2456
2457 pub no_builtins: bool,
2460
2461 pub default_visibility: Option<SymbolVisibility>,
2467
2468 pub emit_debug_gdb_scripts: bool,
2470
2471 pub requires_uwtable: bool,
2475
2476 pub default_uwtable: bool,
2479
2480 pub simd_types_indirect: bool,
2485
2486 pub limit_rdylib_exports: bool,
2488
2489 pub override_export_symbols: Option<StaticCow<[StaticCow<str>]>>,
2492
2493 pub merge_functions: MergeFunctions,
2500
2501 pub mcount: StaticCow<str>,
2503
2504 pub llvm_mcount_intrinsic: Option<StaticCow<str>>,
2506
2507 pub llvm_abiname: StaticCow<str>,
2510
2511 pub llvm_floatabi: Option<FloatAbi>,
2518
2519 pub rustc_abi: Option<RustcAbi>,
2524
2525 pub relax_elf_relocations: bool,
2527
2528 pub llvm_args: StaticCow<[StaticCow<str>]>,
2530
2531 pub use_ctors_section: bool,
2534
2535 pub eh_frame_header: bool,
2539
2540 pub has_thumb_interworking: bool,
2543
2544 pub debuginfo_kind: DebuginfoKind,
2546 pub split_debuginfo: SplitDebuginfo,
2549 pub supported_split_debuginfo: StaticCow<[SplitDebuginfo]>,
2551
2552 pub supported_sanitizers: SanitizerSet,
2558
2559 pub default_sanitizers: SanitizerSet,
2565
2566 pub c_enum_min_bits: Option<u64>,
2568
2569 pub generate_arange_section: bool,
2571
2572 pub supports_stack_protector: bool,
2575
2576 pub entry_name: StaticCow<str>,
2579
2580 pub entry_abi: CanonAbi,
2583
2584 pub supports_xray: bool,
2586
2587 pub default_address_space: rustc_abi::AddressSpace,
2591
2592 small_data_threshold_support: SmallDataThresholdSupport,
2594}
2595
2596fn add_link_args_iter(
2599 link_args: &mut LinkArgs,
2600 flavor: LinkerFlavor,
2601 args: impl Iterator<Item = StaticCow<str>> + Clone,
2602) {
2603 let mut insert = |flavor| link_args.entry(flavor).or_default().extend(args.clone());
2604 insert(flavor);
2605 match flavor {
2606 LinkerFlavor::Gnu(cc, lld) => {
2607 assert_eq!(lld, Lld::No);
2608 insert(LinkerFlavor::Gnu(cc, Lld::Yes));
2609 }
2610 LinkerFlavor::Darwin(cc, lld) => {
2611 assert_eq!(lld, Lld::No);
2612 insert(LinkerFlavor::Darwin(cc, Lld::Yes));
2613 }
2614 LinkerFlavor::Msvc(lld) => {
2615 assert_eq!(lld, Lld::No);
2616 insert(LinkerFlavor::Msvc(Lld::Yes));
2617 }
2618 LinkerFlavor::WasmLld(..)
2619 | LinkerFlavor::Unix(..)
2620 | LinkerFlavor::EmCc
2621 | LinkerFlavor::Bpf
2622 | LinkerFlavor::Llbc
2623 | LinkerFlavor::Ptx => {}
2624 }
2625}
2626
2627fn add_link_args(link_args: &mut LinkArgs, flavor: LinkerFlavor, args: &[&'static str]) {
2628 add_link_args_iter(link_args, flavor, args.iter().copied().map(Cow::Borrowed))
2629}
2630
2631impl TargetOptions {
2632 pub fn supports_comdat(&self) -> bool {
2633 !self.is_like_aix && !self.is_like_darwin
2635 }
2636
2637 pub fn uses_pdb_debuginfo(&self) -> bool {
2638 self.debuginfo_kind == DebuginfoKind::Pdb
2639 }
2640}
2641
2642impl TargetOptions {
2643 fn link_args(flavor: LinkerFlavor, args: &[&'static str]) -> LinkArgs {
2644 let mut link_args = LinkArgs::new();
2645 add_link_args(&mut link_args, flavor, args);
2646 link_args
2647 }
2648
2649 fn add_pre_link_args(&mut self, flavor: LinkerFlavor, args: &[&'static str]) {
2650 add_link_args(&mut self.pre_link_args, flavor, args);
2651 }
2652
2653 fn update_from_cli(&mut self) {
2654 self.linker_flavor = LinkerFlavor::from_cli_json(
2655 self.linker_flavor_json,
2656 self.lld_flavor_json,
2657 self.linker_is_gnu_json,
2658 );
2659 for (args, args_json) in [
2660 (&mut self.pre_link_args, &self.pre_link_args_json),
2661 (&mut self.late_link_args, &self.late_link_args_json),
2662 (&mut self.late_link_args_dynamic, &self.late_link_args_dynamic_json),
2663 (&mut self.late_link_args_static, &self.late_link_args_static_json),
2664 (&mut self.post_link_args, &self.post_link_args_json),
2665 ] {
2666 args.clear();
2667 for (flavor, args_json) in args_json {
2668 let linker_flavor = self.linker_flavor.with_cli_hints(*flavor);
2669 let linker_flavor = match linker_flavor {
2671 LinkerFlavor::Gnu(cc, _) => LinkerFlavor::Gnu(cc, Lld::No),
2672 LinkerFlavor::Darwin(cc, _) => LinkerFlavor::Darwin(cc, Lld::No),
2673 LinkerFlavor::Msvc(_) => LinkerFlavor::Msvc(Lld::No),
2674 _ => linker_flavor,
2675 };
2676 if !args.contains_key(&linker_flavor) {
2677 add_link_args_iter(args, linker_flavor, args_json.iter().cloned());
2678 }
2679 }
2680 }
2681 }
2682
2683 fn update_to_cli(&mut self) {
2684 self.linker_flavor_json = self.linker_flavor.to_cli_counterpart();
2685 self.lld_flavor_json = self.linker_flavor.lld_flavor();
2686 self.linker_is_gnu_json = self.linker_flavor.is_gnu();
2687 for (args, args_json) in [
2688 (&self.pre_link_args, &mut self.pre_link_args_json),
2689 (&self.late_link_args, &mut self.late_link_args_json),
2690 (&self.late_link_args_dynamic, &mut self.late_link_args_dynamic_json),
2691 (&self.late_link_args_static, &mut self.late_link_args_static_json),
2692 (&self.post_link_args, &mut self.post_link_args_json),
2693 ] {
2694 *args_json = args
2695 .iter()
2696 .map(|(flavor, args)| (flavor.to_cli_counterpart(), args.clone()))
2697 .collect();
2698 }
2699 }
2700}
2701
2702impl Default for TargetOptions {
2703 fn default() -> TargetOptions {
2706 TargetOptions {
2707 endian: Endian::Little,
2708 c_int_width: 32,
2709 os: Os::None,
2710 env: Env::Unspecified,
2711 abi: Abi::Unspecified,
2712 vendor: "unknown".into(),
2713 linker: option_env!("CFG_DEFAULT_LINKER").map(|s| s.into()),
2714 linker_flavor: LinkerFlavor::Gnu(Cc::Yes, Lld::No),
2715 linker_flavor_json: LinkerFlavorCli::Gcc,
2716 lld_flavor_json: LldFlavor::Ld,
2717 linker_is_gnu_json: true,
2718 link_script: None,
2719 asm_args: cvs![],
2720 cpu: "generic".into(),
2721 need_explicit_cpu: false,
2722 features: "".into(),
2723 direct_access_external_data: None,
2724 dynamic_linking: false,
2725 dll_tls_export: true,
2726 only_cdylib: false,
2727 executables: true,
2728 relocation_model: RelocModel::Pic,
2729 code_model: None,
2730 tls_model: TlsModel::GeneralDynamic,
2731 disable_redzone: false,
2732 frame_pointer: FramePointer::MayOmit,
2733 function_sections: true,
2734 dll_prefix: "lib".into(),
2735 dll_suffix: ".so".into(),
2736 exe_suffix: "".into(),
2737 staticlib_prefix: "lib".into(),
2738 staticlib_suffix: ".a".into(),
2739 families: cvs![],
2740 abi_return_struct_as_int: false,
2741 is_like_aix: false,
2742 is_like_darwin: false,
2743 is_like_gpu: false,
2744 is_like_solaris: false,
2745 is_like_windows: false,
2746 is_like_msvc: false,
2747 is_like_wasm: false,
2748 is_like_android: false,
2749 is_like_vexos: false,
2750 binary_format: BinaryFormat::Elf,
2751 default_dwarf_version: 4,
2752 allows_weak_linkage: true,
2753 has_rpath: false,
2754 no_default_libraries: true,
2755 position_independent_executables: false,
2756 static_position_independent_executables: false,
2757 plt_by_default: true,
2758 relro_level: RelroLevel::None,
2759 pre_link_objects: Default::default(),
2760 post_link_objects: Default::default(),
2761 pre_link_objects_self_contained: Default::default(),
2762 post_link_objects_self_contained: Default::default(),
2763 link_self_contained: LinkSelfContainedDefault::False,
2764 pre_link_args: LinkArgs::new(),
2765 pre_link_args_json: LinkArgsCli::new(),
2766 late_link_args: LinkArgs::new(),
2767 late_link_args_json: LinkArgsCli::new(),
2768 late_link_args_dynamic: LinkArgs::new(),
2769 late_link_args_dynamic_json: LinkArgsCli::new(),
2770 late_link_args_static: LinkArgs::new(),
2771 late_link_args_static_json: LinkArgsCli::new(),
2772 post_link_args: LinkArgs::new(),
2773 post_link_args_json: LinkArgsCli::new(),
2774 link_env: cvs![],
2775 link_env_remove: cvs![],
2776 archive_format: "gnu".into(),
2777 main_needs_argc_argv: true,
2778 allow_asm: true,
2779 has_thread_local: false,
2780 obj_is_bitcode: false,
2781 min_atomic_width: None,
2782 max_atomic_width: None,
2783 atomic_cas: true,
2784 panic_strategy: PanicStrategy::Unwind,
2785 crt_static_allows_dylibs: false,
2786 crt_static_default: false,
2787 crt_static_respected: false,
2788 stack_probes: StackProbeType::None,
2789 min_global_align: None,
2790 default_codegen_units: None,
2791 default_codegen_backend: None,
2792 trap_unreachable: true,
2793 requires_lto: false,
2794 singlethread: false,
2795 no_builtins: false,
2796 default_visibility: None,
2797 emit_debug_gdb_scripts: true,
2798 requires_uwtable: false,
2799 default_uwtable: false,
2800 simd_types_indirect: true,
2801 limit_rdylib_exports: true,
2802 override_export_symbols: None,
2803 merge_functions: MergeFunctions::Aliases,
2804 mcount: "mcount".into(),
2805 llvm_mcount_intrinsic: None,
2806 llvm_abiname: "".into(),
2807 llvm_floatabi: None,
2808 rustc_abi: None,
2809 relax_elf_relocations: false,
2810 llvm_args: cvs![],
2811 use_ctors_section: false,
2812 eh_frame_header: true,
2813 has_thumb_interworking: false,
2814 debuginfo_kind: Default::default(),
2815 split_debuginfo: Default::default(),
2816 supported_split_debuginfo: Cow::Borrowed(&[SplitDebuginfo::Off]),
2818 supported_sanitizers: SanitizerSet::empty(),
2819 default_sanitizers: SanitizerSet::empty(),
2820 c_enum_min_bits: None,
2821 generate_arange_section: true,
2822 supports_stack_protector: true,
2823 entry_name: "main".into(),
2824 entry_abi: CanonAbi::C,
2825 supports_xray: false,
2826 default_address_space: rustc_abi::AddressSpace::ZERO,
2827 small_data_threshold_support: SmallDataThresholdSupport::DefaultForArch,
2828 }
2829 }
2830}
2831
2832impl Deref for Target {
2836 type Target = TargetOptions;
2837
2838 #[inline]
2839 fn deref(&self) -> &Self::Target {
2840 &self.options
2841 }
2842}
2843impl DerefMut for Target {
2844 #[inline]
2845 fn deref_mut(&mut self) -> &mut Self::Target {
2846 &mut self.options
2847 }
2848}
2849
2850impl Target {
2851 pub fn is_abi_supported(&self, abi: ExternAbi) -> bool {
2852 let abi_map = AbiMap::from_target(self);
2853 abi_map.canonize_abi(abi, false).is_mapped()
2854 }
2855
2856 pub fn min_atomic_width(&self) -> u64 {
2859 self.min_atomic_width.unwrap_or(8)
2860 }
2861
2862 pub fn max_atomic_width(&self) -> u64 {
2865 self.max_atomic_width.unwrap_or_else(|| self.pointer_width.into())
2866 }
2867
2868 fn check_consistency(&self, kind: TargetKind) -> Result<(), String> {
2871 macro_rules! check {
2872 ($b:expr, $($msg:tt)*) => {
2873 if !$b {
2874 return Err(format!($($msg)*));
2875 }
2876 }
2877 }
2878 macro_rules! check_eq {
2879 ($left:expr, $right:expr, $($msg:tt)*) => {
2880 if ($left) != ($right) {
2881 return Err(format!($($msg)*));
2882 }
2883 }
2884 }
2885 macro_rules! check_ne {
2886 ($left:expr, $right:expr, $($msg:tt)*) => {
2887 if ($left) == ($right) {
2888 return Err(format!($($msg)*));
2889 }
2890 }
2891 }
2892 macro_rules! check_matches {
2893 ($left:expr, $right:pat, $($msg:tt)*) => {
2894 if !matches!($left, $right) {
2895 return Err(format!($($msg)*));
2896 }
2897 }
2898 }
2899
2900 check_eq!(
2901 self.is_like_darwin,
2902 self.vendor == "apple",
2903 "`is_like_darwin` must be set if and only if `vendor` is `apple`"
2904 );
2905 check_eq!(
2906 self.is_like_solaris,
2907 matches!(self.os, Os::Solaris | Os::Illumos),
2908 "`is_like_solaris` must be set if and only if `os` is `solaris` or `illumos`"
2909 );
2910 check_eq!(
2911 self.is_like_gpu,
2912 self.arch == Arch::Nvptx64 || self.arch == Arch::AmdGpu,
2913 "`is_like_gpu` must be set if and only if `target` is `nvptx64` or `amdgcn`"
2914 );
2915 check_eq!(
2916 self.is_like_windows,
2917 matches!(self.os, Os::Windows | Os::Uefi | Os::Cygwin),
2918 "`is_like_windows` must be set if and only if `os` is `windows`, `uefi` or `cygwin`"
2919 );
2920 check_eq!(
2921 self.is_like_wasm,
2922 matches!(self.arch, Arch::Wasm32 | Arch::Wasm64),
2923 "`is_like_wasm` must be set if and only if `arch` is `wasm32` or `wasm64`"
2924 );
2925 if self.is_like_msvc {
2926 check!(self.is_like_windows, "if `is_like_msvc` is set, `is_like_windows` must be set");
2927 }
2928 if self.os == Os::Emscripten {
2929 check!(self.is_like_wasm, "the `emcscripten` os only makes sense on wasm-like targets");
2930 }
2931
2932 check_eq!(
2934 self.is_like_darwin,
2935 matches!(self.linker_flavor, LinkerFlavor::Darwin(..)),
2936 "`linker_flavor` must be `darwin` if and only if `is_like_darwin` is set"
2937 );
2938 check_eq!(
2939 self.is_like_msvc,
2940 matches!(self.linker_flavor, LinkerFlavor::Msvc(..)),
2941 "`linker_flavor` must be `msvc` if and only if `is_like_msvc` is set"
2942 );
2943 check_eq!(
2944 self.is_like_wasm && self.os != Os::Emscripten,
2945 matches!(self.linker_flavor, LinkerFlavor::WasmLld(..)),
2946 "`linker_flavor` must be `wasm-lld` if and only if `is_like_wasm` is set and the `os` is not `emscripten`",
2947 );
2948 check_eq!(
2949 self.os == Os::Emscripten,
2950 matches!(self.linker_flavor, LinkerFlavor::EmCc),
2951 "`linker_flavor` must be `em-cc` if and only if `os` is `emscripten`"
2952 );
2953 check_eq!(
2954 self.arch == Arch::Bpf,
2955 matches!(self.linker_flavor, LinkerFlavor::Bpf),
2956 "`linker_flavor` must be `bpf` if and only if `arch` is `bpf`"
2957 );
2958 check_eq!(
2959 self.arch == Arch::Nvptx64,
2960 matches!(self.linker_flavor, LinkerFlavor::Ptx),
2961 "`linker_flavor` must be `ptc` if and only if `arch` is `nvptx64`"
2962 );
2963
2964 for args in [
2965 &self.pre_link_args,
2966 &self.late_link_args,
2967 &self.late_link_args_dynamic,
2968 &self.late_link_args_static,
2969 &self.post_link_args,
2970 ] {
2971 for (&flavor, flavor_args) in args {
2972 check!(
2973 !flavor_args.is_empty() || self.arch == Arch::Avr,
2974 "linker flavor args must not be empty"
2975 );
2976 match self.linker_flavor {
2978 LinkerFlavor::Gnu(..) => {
2979 check_matches!(
2980 flavor,
2981 LinkerFlavor::Gnu(..),
2982 "mixing GNU and non-GNU linker flavors"
2983 );
2984 }
2985 LinkerFlavor::Darwin(..) => {
2986 check_matches!(
2987 flavor,
2988 LinkerFlavor::Darwin(..),
2989 "mixing Darwin and non-Darwin linker flavors"
2990 )
2991 }
2992 LinkerFlavor::WasmLld(..) => {
2993 check_matches!(
2994 flavor,
2995 LinkerFlavor::WasmLld(..),
2996 "mixing wasm and non-wasm linker flavors"
2997 )
2998 }
2999 LinkerFlavor::Unix(..) => {
3000 check_matches!(
3001 flavor,
3002 LinkerFlavor::Unix(..),
3003 "mixing unix and non-unix linker flavors"
3004 );
3005 }
3006 LinkerFlavor::Msvc(..) => {
3007 check_matches!(
3008 flavor,
3009 LinkerFlavor::Msvc(..),
3010 "mixing MSVC and non-MSVC linker flavors"
3011 );
3012 }
3013 LinkerFlavor::EmCc
3014 | LinkerFlavor::Bpf
3015 | LinkerFlavor::Ptx
3016 | LinkerFlavor::Llbc => {
3017 check_eq!(flavor, self.linker_flavor, "mixing different linker flavors")
3018 }
3019 }
3020
3021 let check_noncc = |noncc_flavor| -> Result<(), String> {
3023 if let Some(noncc_args) = args.get(&noncc_flavor) {
3024 for arg in flavor_args {
3025 if let Some(suffix) = arg.strip_prefix("-Wl,") {
3026 check!(
3027 noncc_args.iter().any(|a| a == suffix),
3028 " link args for cc and non-cc versions of flavors are not consistent"
3029 );
3030 }
3031 }
3032 }
3033 Ok(())
3034 };
3035
3036 match self.linker_flavor {
3037 LinkerFlavor::Gnu(Cc::Yes, lld) => check_noncc(LinkerFlavor::Gnu(Cc::No, lld))?,
3038 LinkerFlavor::WasmLld(Cc::Yes) => check_noncc(LinkerFlavor::WasmLld(Cc::No))?,
3039 LinkerFlavor::Unix(Cc::Yes) => check_noncc(LinkerFlavor::Unix(Cc::No))?,
3040 _ => {}
3041 }
3042 }
3043
3044 for cc in [Cc::No, Cc::Yes] {
3046 check_eq!(
3047 args.get(&LinkerFlavor::Gnu(cc, Lld::No)),
3048 args.get(&LinkerFlavor::Gnu(cc, Lld::Yes)),
3049 "link args for lld and non-lld versions of flavors are not consistent",
3050 );
3051 check_eq!(
3052 args.get(&LinkerFlavor::Darwin(cc, Lld::No)),
3053 args.get(&LinkerFlavor::Darwin(cc, Lld::Yes)),
3054 "link args for lld and non-lld versions of flavors are not consistent",
3055 );
3056 }
3057 check_eq!(
3058 args.get(&LinkerFlavor::Msvc(Lld::No)),
3059 args.get(&LinkerFlavor::Msvc(Lld::Yes)),
3060 "link args for lld and non-lld versions of flavors are not consistent",
3061 );
3062 }
3063
3064 if self.link_self_contained.is_disabled() {
3065 check!(
3066 self.pre_link_objects_self_contained.is_empty()
3067 && self.post_link_objects_self_contained.is_empty(),
3068 "if `link_self_contained` is disabled, then `pre_link_objects_self_contained` and `post_link_objects_self_contained` must be empty",
3069 );
3070 }
3071
3072 check_ne!(self.vendor, "", "`vendor` cannot be empty");
3076 if let Os::Other(s) = &self.os {
3077 check!(!s.is_empty(), "`os` cannot be empty");
3078 }
3079 if !self.can_use_os_unknown() {
3080 check_ne!(
3082 self.os,
3083 Os::Unknown,
3084 "`unknown` os can only be used on particular targets; use `none` for bare-metal targets"
3085 );
3086 }
3087
3088 if kind == TargetKind::Builtin {
3094 if self.os == Os::None
3098 && !matches!(self.arch, Arch::Bpf | Arch::Hexagon | Arch::Wasm32 | Arch::Wasm64)
3099 {
3100 check!(
3101 !self.dynamic_linking,
3102 "dynamic linking is not supported on this OS/architecture"
3103 );
3104 }
3105 if self.only_cdylib
3106 || self.crt_static_allows_dylibs
3107 || !self.late_link_args_dynamic.is_empty()
3108 {
3109 check!(
3110 self.dynamic_linking,
3111 "dynamic linking must be allowed when `only_cdylib` or `crt_static_allows_dylibs` or `late_link_args_dynamic` are set"
3112 );
3113 }
3114 if self.dynamic_linking && !self.is_like_wasm {
3116 check_eq!(
3117 self.relocation_model,
3118 RelocModel::Pic,
3119 "targets that support dynamic linking must use the `pic` relocation model"
3120 );
3121 }
3122 if self.position_independent_executables {
3123 check_eq!(
3124 self.relocation_model,
3125 RelocModel::Pic,
3126 "targets that support position-independent executables must use the `pic` relocation model"
3127 );
3128 }
3129 if self.relocation_model == RelocModel::Pic && self.os != Os::Uefi {
3131 check!(
3132 self.dynamic_linking || self.position_independent_executables,
3133 "when the relocation model is `pic`, the target must support dynamic linking or use position-independent executables. \
3134 Set the relocation model to `static` to avoid this requirement"
3135 );
3136 }
3137 if self.static_position_independent_executables {
3138 check!(
3139 self.position_independent_executables,
3140 "if `static_position_independent_executables` is set, then `position_independent_executables` must be set"
3141 );
3142 }
3143 if self.position_independent_executables {
3144 check!(
3145 self.executables,
3146 "if `position_independent_executables` is set then `executables` must be set"
3147 );
3148 }
3149 }
3150
3151 if self.crt_static_default || self.crt_static_allows_dylibs {
3153 check!(
3154 self.crt_static_respected,
3155 "static CRT can be enabled but `crt_static_respected` is not set"
3156 );
3157 }
3158
3159 match self.arch {
3162 Arch::RiscV32 => {
3163 check_matches!(
3164 &*self.llvm_abiname,
3165 "ilp32" | "ilp32f" | "ilp32d" | "ilp32e",
3166 "invalid RISC-V ABI name: {}",
3167 self.llvm_abiname,
3168 );
3169 }
3170 Arch::RiscV64 => {
3171 check_matches!(
3173 &*self.llvm_abiname,
3174 "lp64" | "lp64f" | "lp64d" | "lp64e",
3175 "invalid RISC-V ABI name: {}",
3176 self.llvm_abiname,
3177 );
3178 }
3179 Arch::Arm => {
3180 check!(
3181 self.llvm_floatabi.is_some(),
3182 "ARM targets must set `llvm-floatabi` to `hard` or `soft`",
3183 )
3184 }
3185 _ => {}
3186 }
3187
3188 if let Some(rust_abi) = self.rustc_abi {
3190 match rust_abi {
3191 RustcAbi::X86Sse2 => check_matches!(
3192 self.arch,
3193 Arch::X86,
3194 "`x86-sse2` ABI is only valid for x86-32 targets"
3195 ),
3196 RustcAbi::X86Softfloat => check_matches!(
3197 self.arch,
3198 Arch::X86 | Arch::X86_64,
3199 "`x86-softfloat` ABI is only valid for x86 targets"
3200 ),
3201 }
3202 }
3203
3204 if !self.features.is_empty() {
3206 let mut features_enabled = FxHashSet::default();
3207 let mut features_disabled = FxHashSet::default();
3208 for feat in self.features.split(',') {
3209 if let Some(feat) = feat.strip_prefix("+") {
3210 features_enabled.insert(feat);
3211 if features_disabled.contains(feat) {
3212 return Err(format!(
3213 "target feature `{feat}` is both enabled and disabled"
3214 ));
3215 }
3216 } else if let Some(feat) = feat.strip_prefix("-") {
3217 features_disabled.insert(feat);
3218 if features_enabled.contains(feat) {
3219 return Err(format!(
3220 "target feature `{feat}` is both enabled and disabled"
3221 ));
3222 }
3223 } else {
3224 return Err(format!(
3225 "target feature `{feat}` is invalid, must start with `+` or `-`"
3226 ));
3227 }
3228 }
3229 let abi_feature_constraints = self.abi_required_features();
3231 for feat in abi_feature_constraints.required {
3232 if features_disabled.contains(feat) {
3235 return Err(format!(
3236 "target feature `{feat}` is required by the ABI but gets disabled in target spec"
3237 ));
3238 }
3239 }
3240 for feat in abi_feature_constraints.incompatible {
3241 if features_enabled.contains(feat) {
3244 return Err(format!(
3245 "target feature `{feat}` is incompatible with the ABI but gets enabled in target spec"
3246 ));
3247 }
3248 }
3249 }
3250
3251 Ok(())
3252 }
3253
3254 #[cfg(test)]
3256 fn test_target(mut self) {
3257 let recycled_target =
3258 Target::from_json(&serde_json::to_string(&self.to_json()).unwrap()).map(|(j, _)| j);
3259 self.update_to_cli();
3260 self.check_consistency(TargetKind::Builtin).unwrap();
3261 assert_eq!(recycled_target, Ok(self));
3262 }
3263
3264 fn can_use_os_unknown(&self) -> bool {
3267 self.llvm_target == "wasm32-unknown-unknown"
3268 || self.llvm_target == "wasm64-unknown-unknown"
3269 || (self.env == Env::Sgx && self.vendor == "fortanix")
3270 }
3271
3272 pub fn expect_builtin(target_tuple: &TargetTuple) -> Target {
3274 match *target_tuple {
3275 TargetTuple::TargetTuple(ref target_tuple) => {
3276 load_builtin(target_tuple).expect("built-in target")
3277 }
3278 TargetTuple::TargetJson { .. } => {
3279 panic!("built-in targets doesn't support target-paths")
3280 }
3281 }
3282 }
3283
3284 pub fn builtins() -> impl Iterator<Item = Target> {
3286 load_all_builtins()
3287 }
3288
3289 pub fn search(
3299 target_tuple: &TargetTuple,
3300 sysroot: &Path,
3301 ) -> Result<(Target, TargetWarnings), String> {
3302 use std::{env, fs};
3303
3304 fn load_file(path: &Path) -> Result<(Target, TargetWarnings), String> {
3305 let contents = fs::read_to_string(path).map_err(|e| e.to_string())?;
3306 Target::from_json(&contents)
3307 }
3308
3309 match *target_tuple {
3310 TargetTuple::TargetTuple(ref target_tuple) => {
3311 if let Some(t) = load_builtin(target_tuple) {
3313 return Ok((t, TargetWarnings::empty()));
3314 }
3315
3316 let path = {
3318 let mut target = target_tuple.to_string();
3319 target.push_str(".json");
3320 PathBuf::from(target)
3321 };
3322
3323 let target_path = env::var_os("RUST_TARGET_PATH").unwrap_or_default();
3324
3325 for dir in env::split_paths(&target_path) {
3326 let p = dir.join(&path);
3327 if p.is_file() {
3328 return load_file(&p);
3329 }
3330 }
3331
3332 let rustlib_path = crate::relative_target_rustlib_path(sysroot, target_tuple);
3335 let p = PathBuf::from_iter([
3336 Path::new(sysroot),
3337 Path::new(&rustlib_path),
3338 Path::new("target.json"),
3339 ]);
3340 if p.is_file() {
3341 return load_file(&p);
3342 }
3343
3344 Err(format!("could not find specification for target {target_tuple:?}"))
3345 }
3346 TargetTuple::TargetJson { ref contents, .. } => Target::from_json(contents),
3347 }
3348 }
3349
3350 pub fn small_data_threshold_support(&self) -> SmallDataThresholdSupport {
3353 match &self.options.small_data_threshold_support {
3354 SmallDataThresholdSupport::DefaultForArch => match self.arch {
3358 Arch::Mips | Arch::Mips64 | Arch::Mips32r6 => {
3359 SmallDataThresholdSupport::LlvmArg("mips-ssection-threshold".into())
3360 }
3361 Arch::Hexagon => {
3362 SmallDataThresholdSupport::LlvmArg("hexagon-small-data-threshold".into())
3363 }
3364 Arch::M68k => SmallDataThresholdSupport::LlvmArg("m68k-ssection-threshold".into()),
3365 Arch::RiscV32 | Arch::RiscV64 => {
3366 SmallDataThresholdSupport::LlvmModuleFlag("SmallDataLimit".into())
3367 }
3368 _ => SmallDataThresholdSupport::None,
3369 },
3370 s => s.clone(),
3371 }
3372 }
3373
3374 pub fn object_architecture(
3375 &self,
3376 unstable_target_features: &FxIndexSet<Symbol>,
3377 ) -> Option<(object::Architecture, Option<object::SubArchitecture>)> {
3378 use object::Architecture;
3379 Some(match self.arch {
3380 Arch::Arm => (Architecture::Arm, None),
3381 Arch::AArch64 => (
3382 if self.pointer_width == 32 {
3383 Architecture::Aarch64_Ilp32
3384 } else {
3385 Architecture::Aarch64
3386 },
3387 None,
3388 ),
3389 Arch::X86 => (Architecture::I386, None),
3390 Arch::S390x => (Architecture::S390x, None),
3391 Arch::M68k => (Architecture::M68k, None),
3392 Arch::Mips | Arch::Mips32r6 => (Architecture::Mips, None),
3393 Arch::Mips64 | Arch::Mips64r6 => (
3394 if self.options.llvm_abiname.as_ref() == "n32" {
3400 Architecture::Mips64_N32
3401 } else {
3402 Architecture::Mips64
3403 },
3404 None,
3405 ),
3406 Arch::X86_64 => (
3407 if self.pointer_width == 32 {
3408 Architecture::X86_64_X32
3409 } else {
3410 Architecture::X86_64
3411 },
3412 None,
3413 ),
3414 Arch::PowerPC => (Architecture::PowerPc, None),
3415 Arch::PowerPC64 => (Architecture::PowerPc64, None),
3416 Arch::RiscV32 => (Architecture::Riscv32, None),
3417 Arch::RiscV64 => (Architecture::Riscv64, None),
3418 Arch::Sparc => {
3419 if unstable_target_features.contains(&sym::v8plus) {
3420 (Architecture::Sparc32Plus, None)
3422 } else {
3423 (Architecture::Sparc, None)
3425 }
3426 }
3427 Arch::Sparc64 => (Architecture::Sparc64, None),
3428 Arch::Avr => (Architecture::Avr, None),
3429 Arch::Msp430 => (Architecture::Msp430, None),
3430 Arch::Hexagon => (Architecture::Hexagon, None),
3431 Arch::Xtensa => (Architecture::Xtensa, None),
3432 Arch::Bpf => (Architecture::Bpf, None),
3433 Arch::LoongArch32 => (Architecture::LoongArch32, None),
3434 Arch::LoongArch64 => (Architecture::LoongArch64, None),
3435 Arch::CSky => (Architecture::Csky, None),
3436 Arch::Arm64EC => (Architecture::Aarch64, Some(object::SubArchitecture::Arm64EC)),
3437 Arch::AmdGpu
3438 | Arch::Nvptx64
3439 | Arch::PowerPC64LE
3440 | Arch::SpirV
3441 | Arch::Wasm32
3442 | Arch::Wasm64
3443 | Arch::Other(_) => return None,
3444 })
3445 }
3446
3447 pub fn max_reliable_alignment(&self) -> Align {
3456 if self.is_like_windows && self.arch == Arch::X86 {
3460 Align::from_bytes(4).unwrap()
3461 } else {
3462 Align::MAX
3463 }
3464 }
3465
3466 pub fn vendor_symbol(&self) -> Symbol {
3467 Symbol::intern(&self.vendor)
3468 }
3469}
3470
3471#[derive(Clone, Debug)]
3473pub enum TargetTuple {
3474 TargetTuple(String),
3475 TargetJson {
3476 path_for_rustdoc: PathBuf,
3479 tuple: String,
3480 contents: String,
3481 },
3482}
3483
3484impl PartialEq for TargetTuple {
3486 fn eq(&self, other: &Self) -> bool {
3487 match (self, other) {
3488 (Self::TargetTuple(l0), Self::TargetTuple(r0)) => l0 == r0,
3489 (
3490 Self::TargetJson { path_for_rustdoc: _, tuple: l_tuple, contents: l_contents },
3491 Self::TargetJson { path_for_rustdoc: _, tuple: r_tuple, contents: r_contents },
3492 ) => l_tuple == r_tuple && l_contents == r_contents,
3493 _ => false,
3494 }
3495 }
3496}
3497
3498impl Hash for TargetTuple {
3500 fn hash<H: Hasher>(&self, state: &mut H) -> () {
3501 match self {
3502 TargetTuple::TargetTuple(tuple) => {
3503 0u8.hash(state);
3504 tuple.hash(state)
3505 }
3506 TargetTuple::TargetJson { path_for_rustdoc: _, tuple, contents } => {
3507 1u8.hash(state);
3508 tuple.hash(state);
3509 contents.hash(state)
3510 }
3511 }
3512 }
3513}
3514
3515impl<S: Encoder> Encodable<S> for TargetTuple {
3517 fn encode(&self, s: &mut S) {
3518 match self {
3519 TargetTuple::TargetTuple(tuple) => {
3520 s.emit_u8(0);
3521 s.emit_str(tuple);
3522 }
3523 TargetTuple::TargetJson { path_for_rustdoc: _, tuple, contents } => {
3524 s.emit_u8(1);
3525 s.emit_str(tuple);
3526 s.emit_str(contents);
3527 }
3528 }
3529 }
3530}
3531
3532impl<D: Decoder> Decodable<D> for TargetTuple {
3533 fn decode(d: &mut D) -> Self {
3534 match d.read_u8() {
3535 0 => TargetTuple::TargetTuple(d.read_str().to_owned()),
3536 1 => TargetTuple::TargetJson {
3537 path_for_rustdoc: PathBuf::new(),
3538 tuple: d.read_str().to_owned(),
3539 contents: d.read_str().to_owned(),
3540 },
3541 _ => {
3542 panic!("invalid enum variant tag while decoding `TargetTuple`, expected 0..2");
3543 }
3544 }
3545 }
3546}
3547
3548impl TargetTuple {
3549 pub fn from_tuple(tuple: &str) -> Self {
3551 TargetTuple::TargetTuple(tuple.into())
3552 }
3553
3554 pub fn from_path(path: &Path) -> Result<Self, io::Error> {
3556 let canonicalized_path = try_canonicalize(path)?;
3557 let contents = std::fs::read_to_string(&canonicalized_path).map_err(|err| {
3558 io::Error::new(
3559 io::ErrorKind::InvalidInput,
3560 format!("target path {canonicalized_path:?} is not a valid file: {err}"),
3561 )
3562 })?;
3563 let tuple = canonicalized_path
3564 .file_stem()
3565 .expect("target path must not be empty")
3566 .to_str()
3567 .expect("target path must be valid unicode")
3568 .to_owned();
3569 Ok(TargetTuple::TargetJson { path_for_rustdoc: canonicalized_path, tuple, contents })
3570 }
3571
3572 pub fn tuple(&self) -> &str {
3576 match *self {
3577 TargetTuple::TargetTuple(ref tuple) | TargetTuple::TargetJson { ref tuple, .. } => {
3578 tuple
3579 }
3580 }
3581 }
3582
3583 pub fn debug_tuple(&self) -> String {
3588 use std::hash::DefaultHasher;
3589
3590 match self {
3591 TargetTuple::TargetTuple(tuple) => tuple.to_owned(),
3592 TargetTuple::TargetJson { path_for_rustdoc: _, tuple, contents: content } => {
3593 let mut hasher = DefaultHasher::new();
3594 content.hash(&mut hasher);
3595 let hash = hasher.finish();
3596 format!("{tuple}-{hash}")
3597 }
3598 }
3599 }
3600}
3601
3602impl fmt::Display for TargetTuple {
3603 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3604 write!(f, "{}", self.debug_tuple())
3605 }
3606}
3607
3608into_diag_arg_using_display!(&TargetTuple);