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 ("riscv64im-unknown-none-elf", riscv64im_unknown_none_elf),
1690 ("riscv64imac-unknown-none-elf", riscv64imac_unknown_none_elf),
1691 ("riscv64gc-unknown-none-elf", riscv64gc_unknown_none_elf),
1692 ("riscv64gc-unknown-linux-gnu", riscv64gc_unknown_linux_gnu),
1693 ("riscv64gc-unknown-linux-musl", riscv64gc_unknown_linux_musl),
1694 ("riscv64a23-unknown-linux-gnu", riscv64a23_unknown_linux_gnu),
1695
1696 ("sparc-unknown-none-elf", sparc_unknown_none_elf),
1697
1698 ("loongarch32-unknown-none", loongarch32_unknown_none),
1699 ("loongarch32-unknown-none-softfloat", loongarch32_unknown_none_softfloat),
1700 ("loongarch64-unknown-none", loongarch64_unknown_none),
1701 ("loongarch64-unknown-none-softfloat", loongarch64_unknown_none_softfloat),
1702
1703 ("aarch64-unknown-none", aarch64_unknown_none),
1704 ("aarch64-unknown-none-softfloat", aarch64_unknown_none_softfloat),
1705 ("aarch64_be-unknown-none-softfloat", aarch64_be_unknown_none_softfloat),
1706 ("aarch64-unknown-nuttx", aarch64_unknown_nuttx),
1707
1708 ("x86_64-fortanix-unknown-sgx", x86_64_fortanix_unknown_sgx),
1709
1710 ("x86_64-unknown-uefi", x86_64_unknown_uefi),
1711 ("i686-unknown-uefi", i686_unknown_uefi),
1712 ("aarch64-unknown-uefi", aarch64_unknown_uefi),
1713
1714 ("nvptx64-nvidia-cuda", nvptx64_nvidia_cuda),
1715
1716 ("amdgcn-amd-amdhsa", amdgcn_amd_amdhsa),
1717
1718 ("xtensa-esp32-none-elf", xtensa_esp32_none_elf),
1719 ("xtensa-esp32-espidf", xtensa_esp32_espidf),
1720 ("xtensa-esp32s2-none-elf", xtensa_esp32s2_none_elf),
1721 ("xtensa-esp32s2-espidf", xtensa_esp32s2_espidf),
1722 ("xtensa-esp32s3-none-elf", xtensa_esp32s3_none_elf),
1723 ("xtensa-esp32s3-espidf", xtensa_esp32s3_espidf),
1724
1725 ("i686-wrs-vxworks", i686_wrs_vxworks),
1726 ("x86_64-wrs-vxworks", x86_64_wrs_vxworks),
1727 ("armv7-wrs-vxworks-eabihf", armv7_wrs_vxworks_eabihf),
1728 ("aarch64-wrs-vxworks", aarch64_wrs_vxworks),
1729 ("powerpc-wrs-vxworks", powerpc_wrs_vxworks),
1730 ("powerpc-wrs-vxworks-spe", powerpc_wrs_vxworks_spe),
1731 ("powerpc64-wrs-vxworks", powerpc64_wrs_vxworks),
1732 ("riscv32-wrs-vxworks", riscv32_wrs_vxworks),
1733 ("riscv64-wrs-vxworks", riscv64_wrs_vxworks),
1734
1735 ("aarch64-kmc-solid_asp3", aarch64_kmc_solid_asp3),
1736 ("armv7a-kmc-solid_asp3-eabi", armv7a_kmc_solid_asp3_eabi),
1737 ("armv7a-kmc-solid_asp3-eabihf", armv7a_kmc_solid_asp3_eabihf),
1738
1739 ("mipsel-sony-psp", mipsel_sony_psp),
1740 ("mipsel-sony-psx", mipsel_sony_psx),
1741 ("mipsel-unknown-none", mipsel_unknown_none),
1742 ("mips-mti-none-elf", mips_mti_none_elf),
1743 ("mipsel-mti-none-elf", mipsel_mti_none_elf),
1744 ("thumbv4t-none-eabi", thumbv4t_none_eabi),
1745 ("armv4t-none-eabi", armv4t_none_eabi),
1746 ("thumbv5te-none-eabi", thumbv5te_none_eabi),
1747 ("armv5te-none-eabi", armv5te_none_eabi),
1748
1749 ("aarch64_be-unknown-linux-gnu", aarch64_be_unknown_linux_gnu),
1750 ("aarch64-unknown-linux-gnu_ilp32", aarch64_unknown_linux_gnu_ilp32),
1751 ("aarch64_be-unknown-linux-gnu_ilp32", aarch64_be_unknown_linux_gnu_ilp32),
1752
1753 ("bpfeb-unknown-none", bpfeb_unknown_none),
1754 ("bpfel-unknown-none", bpfel_unknown_none),
1755
1756 ("armv6k-nintendo-3ds", armv6k_nintendo_3ds),
1757
1758 ("aarch64-nintendo-switch-freestanding", aarch64_nintendo_switch_freestanding),
1759
1760 ("armv7-sony-vita-newlibeabihf", armv7_sony_vita_newlibeabihf),
1761
1762 ("armv7-unknown-linux-uclibceabi", armv7_unknown_linux_uclibceabi),
1763 ("armv7-unknown-linux-uclibceabihf", armv7_unknown_linux_uclibceabihf),
1764
1765 ("x86_64-unknown-none", x86_64_unknown_none),
1766
1767 ("aarch64-unknown-teeos", aarch64_unknown_teeos),
1768
1769 ("mips64-openwrt-linux-musl", mips64_openwrt_linux_musl),
1770
1771 ("aarch64-unknown-nto-qnx700", aarch64_unknown_nto_qnx700),
1772 ("aarch64-unknown-nto-qnx710", aarch64_unknown_nto_qnx710),
1773 ("aarch64-unknown-nto-qnx710_iosock", aarch64_unknown_nto_qnx710_iosock),
1774 ("aarch64-unknown-nto-qnx800", aarch64_unknown_nto_qnx800),
1775 ("x86_64-pc-nto-qnx710", x86_64_pc_nto_qnx710),
1776 ("x86_64-pc-nto-qnx710_iosock", x86_64_pc_nto_qnx710_iosock),
1777 ("x86_64-pc-nto-qnx800", x86_64_pc_nto_qnx800),
1778 ("i686-pc-nto-qnx700", i686_pc_nto_qnx700),
1779
1780 ("aarch64-unknown-linux-ohos", aarch64_unknown_linux_ohos),
1781 ("armv7-unknown-linux-ohos", armv7_unknown_linux_ohos),
1782 ("loongarch64-unknown-linux-ohos", loongarch64_unknown_linux_ohos),
1783 ("x86_64-unknown-linux-ohos", x86_64_unknown_linux_ohos),
1784
1785 ("x86_64-unknown-linux-none", x86_64_unknown_linux_none),
1786
1787 ("thumbv6m-nuttx-eabi", thumbv6m_nuttx_eabi),
1788 ("thumbv7a-nuttx-eabi", thumbv7a_nuttx_eabi),
1789 ("thumbv7a-nuttx-eabihf", thumbv7a_nuttx_eabihf),
1790 ("thumbv7m-nuttx-eabi", thumbv7m_nuttx_eabi),
1791 ("thumbv7em-nuttx-eabi", thumbv7em_nuttx_eabi),
1792 ("thumbv7em-nuttx-eabihf", thumbv7em_nuttx_eabihf),
1793 ("thumbv8m.base-nuttx-eabi", thumbv8m_base_nuttx_eabi),
1794 ("thumbv8m.main-nuttx-eabi", thumbv8m_main_nuttx_eabi),
1795 ("thumbv8m.main-nuttx-eabihf", thumbv8m_main_nuttx_eabihf),
1796 ("riscv32imc-unknown-nuttx-elf", riscv32imc_unknown_nuttx_elf),
1797 ("riscv32imac-unknown-nuttx-elf", riscv32imac_unknown_nuttx_elf),
1798 ("riscv32imafc-unknown-nuttx-elf", riscv32imafc_unknown_nuttx_elf),
1799 ("riscv64imac-unknown-nuttx-elf", riscv64imac_unknown_nuttx_elf),
1800 ("riscv64gc-unknown-nuttx-elf", riscv64gc_unknown_nuttx_elf),
1801 ("x86_64-lynx-lynxos178", x86_64_lynx_lynxos178),
1802
1803 ("x86_64-pc-cygwin", x86_64_pc_cygwin),
1804}
1805
1806macro_rules! cvs {
1808 () => {
1809 ::std::borrow::Cow::Borrowed(&[])
1810 };
1811 ($($x:expr),+ $(,)?) => {
1812 ::std::borrow::Cow::Borrowed(&[
1813 $(
1814 ::std::borrow::Cow::Borrowed($x),
1815 )*
1816 ])
1817 };
1818}
1819
1820pub(crate) use cvs;
1821
1822#[derive(Debug, PartialEq)]
1826pub struct TargetWarnings {
1827 unused_fields: Vec<String>,
1828}
1829
1830impl TargetWarnings {
1831 pub fn empty() -> Self {
1832 Self { unused_fields: Vec::new() }
1833 }
1834
1835 pub fn warning_messages(&self) -> Vec<String> {
1836 let mut warnings = vec![];
1837 if !self.unused_fields.is_empty() {
1838 warnings.push(format!(
1839 "target json file contains unused fields: {}",
1840 self.unused_fields.join(", ")
1841 ));
1842 }
1843 warnings
1844 }
1845}
1846
1847#[derive(Copy, Clone, Debug, PartialEq)]
1850enum TargetKind {
1851 Json,
1852 Builtin,
1853}
1854
1855crate::target_spec_enum! {
1856 pub enum Arch {
1857 AArch64 = "aarch64",
1858 AmdGpu = "amdgpu",
1859 Arm = "arm",
1860 Arm64EC = "arm64ec",
1861 Avr = "avr",
1862 Bpf = "bpf",
1863 CSky = "csky",
1864 Hexagon = "hexagon",
1865 LoongArch32 = "loongarch32",
1866 LoongArch64 = "loongarch64",
1867 M68k = "m68k",
1868 Mips = "mips",
1869 Mips32r6 = "mips32r6",
1870 Mips64 = "mips64",
1871 Mips64r6 = "mips64r6",
1872 Msp430 = "msp430",
1873 Nvptx64 = "nvptx64",
1874 PowerPC = "powerpc",
1875 PowerPC64 = "powerpc64",
1876 PowerPC64LE = "powerpc64le",
1877 RiscV32 = "riscv32",
1878 RiscV64 = "riscv64",
1879 S390x = "s390x",
1880 Sparc = "sparc",
1881 Sparc64 = "sparc64",
1882 SpirV = "spirv",
1883 Wasm32 = "wasm32",
1884 Wasm64 = "wasm64",
1885 X86 = "x86",
1886 X86_64 = "x86_64",
1887 Xtensa = "xtensa",
1888 }
1889 other_variant = Other;
1890}
1891
1892impl Arch {
1893 pub fn desc_symbol(&self) -> Symbol {
1894 match self {
1895 Self::AArch64 => sym::aarch64,
1896 Self::AmdGpu => sym::amdgpu,
1897 Self::Arm => sym::arm,
1898 Self::Arm64EC => sym::arm64ec,
1899 Self::Avr => sym::avr,
1900 Self::Bpf => sym::bpf,
1901 Self::CSky => sym::csky,
1902 Self::Hexagon => sym::hexagon,
1903 Self::LoongArch32 => sym::loongarch32,
1904 Self::LoongArch64 => sym::loongarch64,
1905 Self::M68k => sym::m68k,
1906 Self::Mips => sym::mips,
1907 Self::Mips32r6 => sym::mips32r6,
1908 Self::Mips64 => sym::mips64,
1909 Self::Mips64r6 => sym::mips64r6,
1910 Self::Msp430 => sym::msp430,
1911 Self::Nvptx64 => sym::nvptx64,
1912 Self::PowerPC => sym::powerpc,
1913 Self::PowerPC64 => sym::powerpc64,
1914 Self::PowerPC64LE => sym::powerpc64le,
1915 Self::RiscV32 => sym::riscv32,
1916 Self::RiscV64 => sym::riscv64,
1917 Self::S390x => sym::s390x,
1918 Self::Sparc => sym::sparc,
1919 Self::Sparc64 => sym::sparc64,
1920 Self::SpirV => sym::spirv,
1921 Self::Wasm32 => sym::wasm32,
1922 Self::Wasm64 => sym::wasm64,
1923 Self::X86 => sym::x86,
1924 Self::X86_64 => sym::x86_64,
1925 Self::Xtensa => sym::xtensa,
1926 Self::Other(name) => rustc_span::Symbol::intern(name),
1927 }
1928 }
1929
1930 pub fn supports_c_variadic_definitions(&self) -> bool {
1931 use Arch::*;
1932
1933 match self {
1934 Bpf | SpirV => false,
1936
1937 Other(_) => true,
1940
1941 AArch64 | AmdGpu | Arm | Arm64EC | Avr | CSky | Hexagon | LoongArch32 | LoongArch64
1942 | M68k | Mips | Mips32r6 | Mips64 | Mips64r6 | Msp430 | Nvptx64 | PowerPC
1943 | PowerPC64 | PowerPC64LE | RiscV32 | RiscV64 | S390x | Sparc | Sparc64 | Wasm32
1944 | Wasm64 | X86 | X86_64 | Xtensa => true,
1945 }
1946 }
1947}
1948
1949crate::target_spec_enum! {
1950 pub enum Os {
1951 Aix = "aix",
1952 AmdHsa = "amdhsa",
1953 Android = "android",
1954 Cuda = "cuda",
1955 Cygwin = "cygwin",
1956 Dragonfly = "dragonfly",
1957 Emscripten = "emscripten",
1958 EspIdf = "espidf",
1959 FreeBsd = "freebsd",
1960 Fuchsia = "fuchsia",
1961 Haiku = "haiku",
1962 HelenOs = "helenos",
1963 Hermit = "hermit",
1964 Horizon = "horizon",
1965 Hurd = "hurd",
1966 Illumos = "illumos",
1967 IOs = "ios",
1968 L4Re = "l4re",
1969 Linux = "linux",
1970 LynxOs178 = "lynxos178",
1971 MacOs = "macos",
1972 Managarm = "managarm",
1973 Motor = "motor",
1974 NetBsd = "netbsd",
1975 None = "none",
1976 Nto = "nto",
1977 NuttX = "nuttx",
1978 OpenBsd = "openbsd",
1979 Psp = "psp",
1980 Psx = "psx",
1981 Qurt = "qurt",
1982 Redox = "redox",
1983 Rtems = "rtems",
1984 Solaris = "solaris",
1985 SolidAsp3 = "solid_asp3",
1986 TeeOs = "teeos",
1987 Trusty = "trusty",
1988 TvOs = "tvos",
1989 Uefi = "uefi",
1990 VexOs = "vexos",
1991 VisionOs = "visionos",
1992 Vita = "vita",
1993 VxWorks = "vxworks",
1994 Wasi = "wasi",
1995 WatchOs = "watchos",
1996 Windows = "windows",
1997 Xous = "xous",
1998 Zkvm = "zkvm",
1999 Unknown = "unknown",
2000 }
2001 other_variant = Other;
2002}
2003
2004impl Os {
2005 pub fn desc_symbol(&self) -> Symbol {
2006 Symbol::intern(self.desc())
2007 }
2008}
2009
2010crate::target_spec_enum! {
2011 pub enum Env {
2012 Gnu = "gnu",
2013 MacAbi = "macabi",
2014 Mlibc = "mlibc",
2015 Msvc = "msvc",
2016 Musl = "musl",
2017 Newlib = "newlib",
2018 Nto70 = "nto70",
2019 Nto71 = "nto71",
2020 Nto71IoSock = "nto71_iosock",
2021 Nto80 = "nto80",
2022 Ohos = "ohos",
2023 Relibc = "relibc",
2024 Sgx = "sgx",
2025 Sim = "sim",
2026 P1 = "p1",
2027 P2 = "p2",
2028 P3 = "p3",
2029 Uclibc = "uclibc",
2030 V5 = "v5",
2031 Unspecified = "",
2032 }
2033 other_variant = Other;
2034}
2035
2036impl Env {
2037 pub fn desc_symbol(&self) -> Symbol {
2038 Symbol::intern(self.desc())
2039 }
2040}
2041
2042crate::target_spec_enum! {
2043 pub enum Abi {
2044 Abi64 = "abi64",
2045 AbiV2 = "abiv2",
2046 AbiV2Hf = "abiv2hf",
2047 Eabi = "eabi",
2048 EabiHf = "eabihf",
2049 ElfV1 = "elfv1",
2050 ElfV2 = "elfv2",
2051 Fortanix = "fortanix",
2052 Ilp32 = "ilp32",
2053 Ilp32e = "ilp32e",
2054 Llvm = "llvm",
2055 MacAbi = "macabi",
2056 Sim = "sim",
2057 SoftFloat = "softfloat",
2058 Spe = "spe",
2059 Uwp = "uwp",
2060 VecDefault = "vec-default",
2061 VecExtAbi = "vec-extabi",
2062 X32 = "x32",
2063 Unspecified = "",
2064 }
2065 other_variant = Other;
2066}
2067
2068impl Abi {
2069 pub fn desc_symbol(&self) -> Symbol {
2070 Symbol::intern(self.desc())
2071 }
2072}
2073
2074#[derive(PartialEq, Clone, Debug)]
2078pub struct Target {
2079 pub llvm_target: StaticCow<str>,
2086 pub metadata: TargetMetadata,
2089 pub pointer_width: u16,
2091 pub arch: Arch,
2094 pub data_layout: StaticCow<str>,
2096 pub options: TargetOptions,
2098}
2099
2100#[derive(Default, PartialEq, Clone, Debug)]
2104pub struct TargetMetadata {
2105 pub description: Option<StaticCow<str>>,
2108 pub tier: Option<u64>,
2110 pub host_tools: Option<bool>,
2112 pub std: Option<bool>,
2115}
2116
2117impl Target {
2118 pub fn parse_data_layout(&self) -> Result<TargetDataLayout, TargetDataLayoutErrors<'_>> {
2119 let mut dl = TargetDataLayout::parse_from_llvm_datalayout_string(
2120 &self.data_layout,
2121 self.options.default_address_space,
2122 )?;
2123
2124 if dl.endian != self.endian {
2126 return Err(TargetDataLayoutErrors::InconsistentTargetArchitecture {
2127 dl: dl.endian.as_str(),
2128 target: self.endian.as_str(),
2129 });
2130 }
2131
2132 let target_pointer_width: u64 = self.pointer_width.into();
2133 let dl_pointer_size: u64 = dl.pointer_size().bits();
2134 if dl_pointer_size != target_pointer_width {
2135 return Err(TargetDataLayoutErrors::InconsistentTargetPointerWidth {
2136 pointer_size: dl_pointer_size,
2137 target: self.pointer_width,
2138 });
2139 }
2140
2141 dl.c_enum_min_size = Integer::from_size(Size::from_bits(
2142 self.c_enum_min_bits.unwrap_or(self.c_int_width as _),
2143 ))
2144 .map_err(|err| TargetDataLayoutErrors::InvalidBitsSize { err })?;
2145
2146 Ok(dl)
2147 }
2148}
2149
2150pub trait HasTargetSpec {
2151 fn target_spec(&self) -> &Target;
2152}
2153
2154impl HasTargetSpec for Target {
2155 #[inline]
2156 fn target_spec(&self) -> &Target {
2157 self
2158 }
2159}
2160
2161#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
2163pub struct X86Abi {
2164 pub regparm: Option<u32>,
2167 pub reg_struct_return: bool,
2169}
2170
2171pub trait HasX86AbiOpt {
2172 fn x86_abi_opt(&self) -> X86Abi;
2173}
2174
2175type StaticCow<T> = Cow<'static, T>;
2176
2177#[derive(PartialEq, Clone, Debug)]
2186#[rustc_lint_opt_ty]
2187pub struct TargetOptions {
2188 pub endian: Endian,
2190 pub c_int_width: u16,
2192 pub os: Os,
2197 pub env: Env,
2199 pub abi: Abi,
2204 #[rustc_lint_opt_deny_field_access(
2206 "use `Target::is_like_*` instead of this field; see https://github.com/rust-lang/rust/issues/100343 for rationale"
2207 )]
2208 vendor: StaticCow<str>,
2209
2210 pub linker: Option<StaticCow<str>>,
2212 pub linker_flavor: LinkerFlavor,
2215 linker_flavor_json: LinkerFlavorCli,
2216 lld_flavor_json: LldFlavor,
2217 linker_is_gnu_json: bool,
2218
2219 pub pre_link_objects: CrtObjects,
2221 pub post_link_objects: CrtObjects,
2222 pub pre_link_objects_self_contained: CrtObjects,
2224 pub post_link_objects_self_contained: CrtObjects,
2225 pub link_self_contained: LinkSelfContainedDefault,
2228
2229 pub pre_link_args: LinkArgs,
2231 pre_link_args_json: LinkArgsCli,
2232 pub late_link_args: LinkArgs,
2236 late_link_args_json: LinkArgsCli,
2237 pub late_link_args_dynamic: LinkArgs,
2240 late_link_args_dynamic_json: LinkArgsCli,
2241 pub late_link_args_static: LinkArgs,
2244 late_link_args_static_json: LinkArgsCli,
2245 pub post_link_args: LinkArgs,
2248 post_link_args_json: LinkArgsCli,
2249
2250 pub link_script: Option<StaticCow<str>>,
2254 pub link_env: StaticCow<[(StaticCow<str>, StaticCow<str>)]>,
2256 pub link_env_remove: StaticCow<[StaticCow<str>]>,
2258
2259 pub asm_args: StaticCow<[StaticCow<str>]>,
2261
2262 pub cpu: StaticCow<str>,
2265 pub need_explicit_cpu: bool,
2268 pub features: StaticCow<str>,
2277 pub direct_access_external_data: Option<bool>,
2279 pub dynamic_linking: bool,
2281 pub dll_tls_export: bool,
2283 pub only_cdylib: bool,
2285 pub executables: bool,
2287 pub relocation_model: RelocModel,
2290 pub code_model: Option<CodeModel>,
2293 pub tls_model: TlsModel,
2296 pub disable_redzone: bool,
2298 pub frame_pointer: FramePointer,
2300 pub function_sections: bool,
2302 pub dll_prefix: StaticCow<str>,
2304 pub dll_suffix: StaticCow<str>,
2306 pub exe_suffix: StaticCow<str>,
2308 pub staticlib_prefix: StaticCow<str>,
2310 pub staticlib_suffix: StaticCow<str>,
2312 pub families: StaticCow<[StaticCow<str>]>,
2318 pub abi_return_struct_as_int: bool,
2320 pub is_like_aix: bool,
2323 pub is_like_darwin: bool,
2328 pub is_like_gpu: bool,
2330 pub is_like_solaris: bool,
2334 pub is_like_windows: bool,
2342 pub is_like_msvc: bool,
2352 pub is_like_wasm: bool,
2354 pub is_like_android: bool,
2356 pub is_like_vexos: bool,
2358 pub binary_format: BinaryFormat,
2360 pub default_dwarf_version: u32,
2363 pub allows_weak_linkage: bool,
2370 pub has_rpath: bool,
2372 pub no_default_libraries: bool,
2375 pub position_independent_executables: bool,
2381 pub static_position_independent_executables: bool,
2383 pub plt_by_default: bool,
2386 pub relro_level: RelroLevel,
2390 pub archive_format: StaticCow<str>,
2395 pub allow_asm: bool,
2397 pub main_needs_argc_argv: bool,
2400
2401 pub has_thread_local: bool,
2403 pub obj_is_bitcode: bool,
2407
2408 pub min_atomic_width: Option<u64>,
2410
2411 pub max_atomic_width: Option<u64>,
2413
2414 pub atomic_cas: bool,
2416
2417 pub panic_strategy: PanicStrategy,
2419
2420 pub crt_static_allows_dylibs: bool,
2422 pub crt_static_default: bool,
2424 pub crt_static_respected: bool,
2426
2427 pub stack_probes: StackProbeType,
2429
2430 pub min_global_align: Option<Align>,
2432
2433 pub default_codegen_units: Option<u64>,
2435
2436 pub default_codegen_backend: Option<StaticCow<str>>,
2446
2447 pub trap_unreachable: bool,
2450
2451 pub requires_lto: bool,
2454
2455 pub singlethread: bool,
2457
2458 pub no_builtins: bool,
2461
2462 pub default_visibility: Option<SymbolVisibility>,
2468
2469 pub emit_debug_gdb_scripts: bool,
2471
2472 pub requires_uwtable: bool,
2476
2477 pub default_uwtable: bool,
2480
2481 pub simd_types_indirect: bool,
2486
2487 pub limit_rdylib_exports: bool,
2489
2490 pub override_export_symbols: Option<StaticCow<[StaticCow<str>]>>,
2493
2494 pub merge_functions: MergeFunctions,
2501
2502 pub mcount: StaticCow<str>,
2504
2505 pub llvm_mcount_intrinsic: Option<StaticCow<str>>,
2507
2508 pub llvm_abiname: StaticCow<str>,
2511
2512 pub llvm_floatabi: Option<FloatAbi>,
2519
2520 pub rustc_abi: Option<RustcAbi>,
2525
2526 pub relax_elf_relocations: bool,
2528
2529 pub llvm_args: StaticCow<[StaticCow<str>]>,
2531
2532 pub use_ctors_section: bool,
2535
2536 pub eh_frame_header: bool,
2540
2541 pub has_thumb_interworking: bool,
2544
2545 pub debuginfo_kind: DebuginfoKind,
2547 pub split_debuginfo: SplitDebuginfo,
2550 pub supported_split_debuginfo: StaticCow<[SplitDebuginfo]>,
2552
2553 pub supported_sanitizers: SanitizerSet,
2559
2560 pub default_sanitizers: SanitizerSet,
2566
2567 pub c_enum_min_bits: Option<u64>,
2569
2570 pub generate_arange_section: bool,
2572
2573 pub supports_stack_protector: bool,
2576
2577 pub entry_name: StaticCow<str>,
2580
2581 pub entry_abi: CanonAbi,
2584
2585 pub supports_xray: bool,
2587
2588 pub default_address_space: rustc_abi::AddressSpace,
2592
2593 small_data_threshold_support: SmallDataThresholdSupport,
2595}
2596
2597fn add_link_args_iter(
2600 link_args: &mut LinkArgs,
2601 flavor: LinkerFlavor,
2602 args: impl Iterator<Item = StaticCow<str>> + Clone,
2603) {
2604 let mut insert = |flavor| link_args.entry(flavor).or_default().extend(args.clone());
2605 insert(flavor);
2606 match flavor {
2607 LinkerFlavor::Gnu(cc, lld) => {
2608 assert_eq!(lld, Lld::No);
2609 insert(LinkerFlavor::Gnu(cc, Lld::Yes));
2610 }
2611 LinkerFlavor::Darwin(cc, lld) => {
2612 assert_eq!(lld, Lld::No);
2613 insert(LinkerFlavor::Darwin(cc, Lld::Yes));
2614 }
2615 LinkerFlavor::Msvc(lld) => {
2616 assert_eq!(lld, Lld::No);
2617 insert(LinkerFlavor::Msvc(Lld::Yes));
2618 }
2619 LinkerFlavor::WasmLld(..)
2620 | LinkerFlavor::Unix(..)
2621 | LinkerFlavor::EmCc
2622 | LinkerFlavor::Bpf
2623 | LinkerFlavor::Llbc
2624 | LinkerFlavor::Ptx => {}
2625 }
2626}
2627
2628fn add_link_args(link_args: &mut LinkArgs, flavor: LinkerFlavor, args: &[&'static str]) {
2629 add_link_args_iter(link_args, flavor, args.iter().copied().map(Cow::Borrowed))
2630}
2631
2632impl TargetOptions {
2633 pub fn supports_comdat(&self) -> bool {
2634 !self.is_like_aix && !self.is_like_darwin
2636 }
2637
2638 pub fn uses_pdb_debuginfo(&self) -> bool {
2639 self.debuginfo_kind == DebuginfoKind::Pdb
2640 }
2641}
2642
2643impl TargetOptions {
2644 fn link_args(flavor: LinkerFlavor, args: &[&'static str]) -> LinkArgs {
2645 let mut link_args = LinkArgs::new();
2646 add_link_args(&mut link_args, flavor, args);
2647 link_args
2648 }
2649
2650 fn add_pre_link_args(&mut self, flavor: LinkerFlavor, args: &[&'static str]) {
2651 add_link_args(&mut self.pre_link_args, flavor, args);
2652 }
2653
2654 fn update_from_cli(&mut self) {
2655 self.linker_flavor = LinkerFlavor::from_cli_json(
2656 self.linker_flavor_json,
2657 self.lld_flavor_json,
2658 self.linker_is_gnu_json,
2659 );
2660 for (args, args_json) in [
2661 (&mut self.pre_link_args, &self.pre_link_args_json),
2662 (&mut self.late_link_args, &self.late_link_args_json),
2663 (&mut self.late_link_args_dynamic, &self.late_link_args_dynamic_json),
2664 (&mut self.late_link_args_static, &self.late_link_args_static_json),
2665 (&mut self.post_link_args, &self.post_link_args_json),
2666 ] {
2667 args.clear();
2668 for (flavor, args_json) in args_json {
2669 let linker_flavor = self.linker_flavor.with_cli_hints(*flavor);
2670 let linker_flavor = match linker_flavor {
2672 LinkerFlavor::Gnu(cc, _) => LinkerFlavor::Gnu(cc, Lld::No),
2673 LinkerFlavor::Darwin(cc, _) => LinkerFlavor::Darwin(cc, Lld::No),
2674 LinkerFlavor::Msvc(_) => LinkerFlavor::Msvc(Lld::No),
2675 _ => linker_flavor,
2676 };
2677 if !args.contains_key(&linker_flavor) {
2678 add_link_args_iter(args, linker_flavor, args_json.iter().cloned());
2679 }
2680 }
2681 }
2682 }
2683
2684 fn update_to_cli(&mut self) {
2685 self.linker_flavor_json = self.linker_flavor.to_cli_counterpart();
2686 self.lld_flavor_json = self.linker_flavor.lld_flavor();
2687 self.linker_is_gnu_json = self.linker_flavor.is_gnu();
2688 for (args, args_json) in [
2689 (&self.pre_link_args, &mut self.pre_link_args_json),
2690 (&self.late_link_args, &mut self.late_link_args_json),
2691 (&self.late_link_args_dynamic, &mut self.late_link_args_dynamic_json),
2692 (&self.late_link_args_static, &mut self.late_link_args_static_json),
2693 (&self.post_link_args, &mut self.post_link_args_json),
2694 ] {
2695 *args_json = args
2696 .iter()
2697 .map(|(flavor, args)| (flavor.to_cli_counterpart(), args.clone()))
2698 .collect();
2699 }
2700 }
2701}
2702
2703impl Default for TargetOptions {
2704 fn default() -> TargetOptions {
2707 TargetOptions {
2708 endian: Endian::Little,
2709 c_int_width: 32,
2710 os: Os::None,
2711 env: Env::Unspecified,
2712 abi: Abi::Unspecified,
2713 vendor: "unknown".into(),
2714 linker: option_env!("CFG_DEFAULT_LINKER").map(|s| s.into()),
2715 linker_flavor: LinkerFlavor::Gnu(Cc::Yes, Lld::No),
2716 linker_flavor_json: LinkerFlavorCli::Gcc,
2717 lld_flavor_json: LldFlavor::Ld,
2718 linker_is_gnu_json: true,
2719 link_script: None,
2720 asm_args: cvs![],
2721 cpu: "generic".into(),
2722 need_explicit_cpu: false,
2723 features: "".into(),
2724 direct_access_external_data: None,
2725 dynamic_linking: false,
2726 dll_tls_export: true,
2727 only_cdylib: false,
2728 executables: true,
2729 relocation_model: RelocModel::Pic,
2730 code_model: None,
2731 tls_model: TlsModel::GeneralDynamic,
2732 disable_redzone: false,
2733 frame_pointer: FramePointer::MayOmit,
2734 function_sections: true,
2735 dll_prefix: "lib".into(),
2736 dll_suffix: ".so".into(),
2737 exe_suffix: "".into(),
2738 staticlib_prefix: "lib".into(),
2739 staticlib_suffix: ".a".into(),
2740 families: cvs![],
2741 abi_return_struct_as_int: false,
2742 is_like_aix: false,
2743 is_like_darwin: false,
2744 is_like_gpu: false,
2745 is_like_solaris: false,
2746 is_like_windows: false,
2747 is_like_msvc: false,
2748 is_like_wasm: false,
2749 is_like_android: false,
2750 is_like_vexos: false,
2751 binary_format: BinaryFormat::Elf,
2752 default_dwarf_version: 4,
2753 allows_weak_linkage: true,
2754 has_rpath: false,
2755 no_default_libraries: true,
2756 position_independent_executables: false,
2757 static_position_independent_executables: false,
2758 plt_by_default: true,
2759 relro_level: RelroLevel::None,
2760 pre_link_objects: Default::default(),
2761 post_link_objects: Default::default(),
2762 pre_link_objects_self_contained: Default::default(),
2763 post_link_objects_self_contained: Default::default(),
2764 link_self_contained: LinkSelfContainedDefault::False,
2765 pre_link_args: LinkArgs::new(),
2766 pre_link_args_json: LinkArgsCli::new(),
2767 late_link_args: LinkArgs::new(),
2768 late_link_args_json: LinkArgsCli::new(),
2769 late_link_args_dynamic: LinkArgs::new(),
2770 late_link_args_dynamic_json: LinkArgsCli::new(),
2771 late_link_args_static: LinkArgs::new(),
2772 late_link_args_static_json: LinkArgsCli::new(),
2773 post_link_args: LinkArgs::new(),
2774 post_link_args_json: LinkArgsCli::new(),
2775 link_env: cvs![],
2776 link_env_remove: cvs![],
2777 archive_format: "gnu".into(),
2778 main_needs_argc_argv: true,
2779 allow_asm: true,
2780 has_thread_local: false,
2781 obj_is_bitcode: false,
2782 min_atomic_width: None,
2783 max_atomic_width: None,
2784 atomic_cas: true,
2785 panic_strategy: PanicStrategy::Unwind,
2786 crt_static_allows_dylibs: false,
2787 crt_static_default: false,
2788 crt_static_respected: false,
2789 stack_probes: StackProbeType::None,
2790 min_global_align: None,
2791 default_codegen_units: None,
2792 default_codegen_backend: None,
2793 trap_unreachable: true,
2794 requires_lto: false,
2795 singlethread: false,
2796 no_builtins: false,
2797 default_visibility: None,
2798 emit_debug_gdb_scripts: true,
2799 requires_uwtable: false,
2800 default_uwtable: false,
2801 simd_types_indirect: true,
2802 limit_rdylib_exports: true,
2803 override_export_symbols: None,
2804 merge_functions: MergeFunctions::Aliases,
2805 mcount: "mcount".into(),
2806 llvm_mcount_intrinsic: None,
2807 llvm_abiname: "".into(),
2808 llvm_floatabi: None,
2809 rustc_abi: None,
2810 relax_elf_relocations: false,
2811 llvm_args: cvs![],
2812 use_ctors_section: false,
2813 eh_frame_header: true,
2814 has_thumb_interworking: false,
2815 debuginfo_kind: Default::default(),
2816 split_debuginfo: Default::default(),
2817 supported_split_debuginfo: Cow::Borrowed(&[SplitDebuginfo::Off]),
2819 supported_sanitizers: SanitizerSet::empty(),
2820 default_sanitizers: SanitizerSet::empty(),
2821 c_enum_min_bits: None,
2822 generate_arange_section: true,
2823 supports_stack_protector: true,
2824 entry_name: "main".into(),
2825 entry_abi: CanonAbi::C,
2826 supports_xray: false,
2827 default_address_space: rustc_abi::AddressSpace::ZERO,
2828 small_data_threshold_support: SmallDataThresholdSupport::DefaultForArch,
2829 }
2830 }
2831}
2832
2833impl Deref for Target {
2837 type Target = TargetOptions;
2838
2839 #[inline]
2840 fn deref(&self) -> &Self::Target {
2841 &self.options
2842 }
2843}
2844impl DerefMut for Target {
2845 #[inline]
2846 fn deref_mut(&mut self) -> &mut Self::Target {
2847 &mut self.options
2848 }
2849}
2850
2851impl Target {
2852 pub fn is_abi_supported(&self, abi: ExternAbi) -> bool {
2853 let abi_map = AbiMap::from_target(self);
2854 abi_map.canonize_abi(abi, false).is_mapped()
2855 }
2856
2857 pub fn min_atomic_width(&self) -> u64 {
2860 self.min_atomic_width.unwrap_or(8)
2861 }
2862
2863 pub fn max_atomic_width(&self) -> u64 {
2866 self.max_atomic_width.unwrap_or_else(|| self.pointer_width.into())
2867 }
2868
2869 fn check_consistency(&self, kind: TargetKind) -> Result<(), String> {
2872 macro_rules! check {
2873 ($b:expr, $($msg:tt)*) => {
2874 if !$b {
2875 return Err(format!($($msg)*));
2876 }
2877 }
2878 }
2879 macro_rules! check_eq {
2880 ($left:expr, $right:expr, $($msg:tt)*) => {
2881 if ($left) != ($right) {
2882 return Err(format!($($msg)*));
2883 }
2884 }
2885 }
2886 macro_rules! check_ne {
2887 ($left:expr, $right:expr, $($msg:tt)*) => {
2888 if ($left) == ($right) {
2889 return Err(format!($($msg)*));
2890 }
2891 }
2892 }
2893 macro_rules! check_matches {
2894 ($left:expr, $right:pat, $($msg:tt)*) => {
2895 if !matches!($left, $right) {
2896 return Err(format!($($msg)*));
2897 }
2898 }
2899 }
2900
2901 check_eq!(
2902 self.is_like_darwin,
2903 self.vendor == "apple",
2904 "`is_like_darwin` must be set if and only if `vendor` is `apple`"
2905 );
2906 check_eq!(
2907 self.is_like_solaris,
2908 matches!(self.os, Os::Solaris | Os::Illumos),
2909 "`is_like_solaris` must be set if and only if `os` is `solaris` or `illumos`"
2910 );
2911 check_eq!(
2912 self.is_like_gpu,
2913 self.arch == Arch::Nvptx64 || self.arch == Arch::AmdGpu,
2914 "`is_like_gpu` must be set if and only if `target` is `nvptx64` or `amdgcn`"
2915 );
2916 check_eq!(
2917 self.is_like_windows,
2918 matches!(self.os, Os::Windows | Os::Uefi | Os::Cygwin),
2919 "`is_like_windows` must be set if and only if `os` is `windows`, `uefi` or `cygwin`"
2920 );
2921 check_eq!(
2922 self.is_like_wasm,
2923 matches!(self.arch, Arch::Wasm32 | Arch::Wasm64),
2924 "`is_like_wasm` must be set if and only if `arch` is `wasm32` or `wasm64`"
2925 );
2926 if self.is_like_msvc {
2927 check!(self.is_like_windows, "if `is_like_msvc` is set, `is_like_windows` must be set");
2928 }
2929 if self.os == Os::Emscripten {
2930 check!(self.is_like_wasm, "the `emcscripten` os only makes sense on wasm-like targets");
2931 }
2932
2933 check_eq!(
2935 self.is_like_darwin,
2936 matches!(self.linker_flavor, LinkerFlavor::Darwin(..)),
2937 "`linker_flavor` must be `darwin` if and only if `is_like_darwin` is set"
2938 );
2939 check_eq!(
2940 self.is_like_msvc,
2941 matches!(self.linker_flavor, LinkerFlavor::Msvc(..)),
2942 "`linker_flavor` must be `msvc` if and only if `is_like_msvc` is set"
2943 );
2944 check_eq!(
2945 self.is_like_wasm && self.os != Os::Emscripten,
2946 matches!(self.linker_flavor, LinkerFlavor::WasmLld(..)),
2947 "`linker_flavor` must be `wasm-lld` if and only if `is_like_wasm` is set and the `os` is not `emscripten`",
2948 );
2949 check_eq!(
2950 self.os == Os::Emscripten,
2951 matches!(self.linker_flavor, LinkerFlavor::EmCc),
2952 "`linker_flavor` must be `em-cc` if and only if `os` is `emscripten`"
2953 );
2954 check_eq!(
2955 self.arch == Arch::Bpf,
2956 matches!(self.linker_flavor, LinkerFlavor::Bpf),
2957 "`linker_flavor` must be `bpf` if and only if `arch` is `bpf`"
2958 );
2959
2960 for args in [
2961 &self.pre_link_args,
2962 &self.late_link_args,
2963 &self.late_link_args_dynamic,
2964 &self.late_link_args_static,
2965 &self.post_link_args,
2966 ] {
2967 for (&flavor, flavor_args) in args {
2968 check!(
2969 !flavor_args.is_empty() || self.arch == Arch::Avr,
2970 "linker flavor args must not be empty"
2971 );
2972 match self.linker_flavor {
2974 LinkerFlavor::Gnu(..) => {
2975 check_matches!(
2976 flavor,
2977 LinkerFlavor::Gnu(..),
2978 "mixing GNU and non-GNU linker flavors"
2979 );
2980 }
2981 LinkerFlavor::Darwin(..) => {
2982 check_matches!(
2983 flavor,
2984 LinkerFlavor::Darwin(..),
2985 "mixing Darwin and non-Darwin linker flavors"
2986 )
2987 }
2988 LinkerFlavor::WasmLld(..) => {
2989 check_matches!(
2990 flavor,
2991 LinkerFlavor::WasmLld(..),
2992 "mixing wasm and non-wasm linker flavors"
2993 )
2994 }
2995 LinkerFlavor::Unix(..) => {
2996 check_matches!(
2997 flavor,
2998 LinkerFlavor::Unix(..),
2999 "mixing unix and non-unix linker flavors"
3000 );
3001 }
3002 LinkerFlavor::Msvc(..) => {
3003 check_matches!(
3004 flavor,
3005 LinkerFlavor::Msvc(..),
3006 "mixing MSVC and non-MSVC linker flavors"
3007 );
3008 }
3009 LinkerFlavor::EmCc
3010 | LinkerFlavor::Bpf
3011 | LinkerFlavor::Ptx
3012 | LinkerFlavor::Llbc => {
3013 check_eq!(flavor, self.linker_flavor, "mixing different linker flavors")
3014 }
3015 }
3016
3017 let check_noncc = |noncc_flavor| -> Result<(), String> {
3019 if let Some(noncc_args) = args.get(&noncc_flavor) {
3020 for arg in flavor_args {
3021 if let Some(suffix) = arg.strip_prefix("-Wl,") {
3022 check!(
3023 noncc_args.iter().any(|a| a == suffix),
3024 " link args for cc and non-cc versions of flavors are not consistent"
3025 );
3026 }
3027 }
3028 }
3029 Ok(())
3030 };
3031
3032 match self.linker_flavor {
3033 LinkerFlavor::Gnu(Cc::Yes, lld) => check_noncc(LinkerFlavor::Gnu(Cc::No, lld))?,
3034 LinkerFlavor::WasmLld(Cc::Yes) => check_noncc(LinkerFlavor::WasmLld(Cc::No))?,
3035 LinkerFlavor::Unix(Cc::Yes) => check_noncc(LinkerFlavor::Unix(Cc::No))?,
3036 _ => {}
3037 }
3038 }
3039
3040 for cc in [Cc::No, Cc::Yes] {
3042 check_eq!(
3043 args.get(&LinkerFlavor::Gnu(cc, Lld::No)),
3044 args.get(&LinkerFlavor::Gnu(cc, Lld::Yes)),
3045 "link args for lld and non-lld versions of flavors are not consistent",
3046 );
3047 check_eq!(
3048 args.get(&LinkerFlavor::Darwin(cc, Lld::No)),
3049 args.get(&LinkerFlavor::Darwin(cc, Lld::Yes)),
3050 "link args for lld and non-lld versions of flavors are not consistent",
3051 );
3052 }
3053 check_eq!(
3054 args.get(&LinkerFlavor::Msvc(Lld::No)),
3055 args.get(&LinkerFlavor::Msvc(Lld::Yes)),
3056 "link args for lld and non-lld versions of flavors are not consistent",
3057 );
3058 }
3059
3060 if self.link_self_contained.is_disabled() {
3061 check!(
3062 self.pre_link_objects_self_contained.is_empty()
3063 && self.post_link_objects_self_contained.is_empty(),
3064 "if `link_self_contained` is disabled, then `pre_link_objects_self_contained` and `post_link_objects_self_contained` must be empty",
3065 );
3066 }
3067
3068 check_ne!(self.vendor, "", "`vendor` cannot be empty");
3072 if let Os::Other(s) = &self.os {
3073 check!(!s.is_empty(), "`os` cannot be empty");
3074 }
3075 if !self.can_use_os_unknown() {
3076 check_ne!(
3078 self.os,
3079 Os::Unknown,
3080 "`unknown` os can only be used on particular targets; use `none` for bare-metal targets"
3081 );
3082 }
3083
3084 if kind == TargetKind::Builtin {
3090 if self.os == Os::None
3094 && !matches!(self.arch, Arch::Bpf | Arch::Hexagon | Arch::Wasm32 | Arch::Wasm64)
3095 {
3096 check!(
3097 !self.dynamic_linking,
3098 "dynamic linking is not supported on this OS/architecture"
3099 );
3100 }
3101 if self.only_cdylib
3102 || self.crt_static_allows_dylibs
3103 || !self.late_link_args_dynamic.is_empty()
3104 {
3105 check!(
3106 self.dynamic_linking,
3107 "dynamic linking must be allowed when `only_cdylib` or `crt_static_allows_dylibs` or `late_link_args_dynamic` are set"
3108 );
3109 }
3110 if self.dynamic_linking && !self.is_like_wasm {
3112 check_eq!(
3113 self.relocation_model,
3114 RelocModel::Pic,
3115 "targets that support dynamic linking must use the `pic` relocation model"
3116 );
3117 }
3118 if self.position_independent_executables {
3119 check_eq!(
3120 self.relocation_model,
3121 RelocModel::Pic,
3122 "targets that support position-independent executables must use the `pic` relocation model"
3123 );
3124 }
3125 if self.relocation_model == RelocModel::Pic && self.os != Os::Uefi {
3127 check!(
3128 self.dynamic_linking || self.position_independent_executables,
3129 "when the relocation model is `pic`, the target must support dynamic linking or use position-independent executables. \
3130 Set the relocation model to `static` to avoid this requirement"
3131 );
3132 }
3133 if self.static_position_independent_executables {
3134 check!(
3135 self.position_independent_executables,
3136 "if `static_position_independent_executables` is set, then `position_independent_executables` must be set"
3137 );
3138 }
3139 if self.position_independent_executables {
3140 check!(
3141 self.executables,
3142 "if `position_independent_executables` is set then `executables` must be set"
3143 );
3144 }
3145 }
3146
3147 if self.crt_static_default || self.crt_static_allows_dylibs {
3149 check!(
3150 self.crt_static_respected,
3151 "static CRT can be enabled but `crt_static_respected` is not set"
3152 );
3153 }
3154
3155 match self.arch {
3158 Arch::RiscV32 => {
3159 check_matches!(
3160 &*self.llvm_abiname,
3161 "ilp32" | "ilp32f" | "ilp32d" | "ilp32e",
3162 "invalid RISC-V ABI name: {}",
3163 self.llvm_abiname,
3164 );
3165 }
3166 Arch::RiscV64 => {
3167 check_matches!(
3169 &*self.llvm_abiname,
3170 "lp64" | "lp64f" | "lp64d" | "lp64e",
3171 "invalid RISC-V ABI name: {}",
3172 self.llvm_abiname,
3173 );
3174 }
3175 Arch::Arm => {
3176 check!(
3177 self.llvm_floatabi.is_some(),
3178 "ARM targets must set `llvm-floatabi` to `hard` or `soft`",
3179 )
3180 }
3181 _ => {}
3182 }
3183
3184 if let Some(rust_abi) = self.rustc_abi {
3186 match rust_abi {
3187 RustcAbi::X86Sse2 => check_matches!(
3188 self.arch,
3189 Arch::X86,
3190 "`x86-sse2` ABI is only valid for x86-32 targets"
3191 ),
3192 RustcAbi::X86Softfloat => check_matches!(
3193 self.arch,
3194 Arch::X86 | Arch::X86_64,
3195 "`x86-softfloat` ABI is only valid for x86 targets"
3196 ),
3197 }
3198 }
3199
3200 if !self.features.is_empty() {
3202 let mut features_enabled = FxHashSet::default();
3203 let mut features_disabled = FxHashSet::default();
3204 for feat in self.features.split(',') {
3205 if let Some(feat) = feat.strip_prefix("+") {
3206 features_enabled.insert(feat);
3207 if features_disabled.contains(feat) {
3208 return Err(format!(
3209 "target feature `{feat}` is both enabled and disabled"
3210 ));
3211 }
3212 } else if let Some(feat) = feat.strip_prefix("-") {
3213 features_disabled.insert(feat);
3214 if features_enabled.contains(feat) {
3215 return Err(format!(
3216 "target feature `{feat}` is both enabled and disabled"
3217 ));
3218 }
3219 } else {
3220 return Err(format!(
3221 "target feature `{feat}` is invalid, must start with `+` or `-`"
3222 ));
3223 }
3224 }
3225 let abi_feature_constraints = self.abi_required_features();
3227 for feat in abi_feature_constraints.required {
3228 if features_disabled.contains(feat) {
3231 return Err(format!(
3232 "target feature `{feat}` is required by the ABI but gets disabled in target spec"
3233 ));
3234 }
3235 }
3236 for feat in abi_feature_constraints.incompatible {
3237 if features_enabled.contains(feat) {
3240 return Err(format!(
3241 "target feature `{feat}` is incompatible with the ABI but gets enabled in target spec"
3242 ));
3243 }
3244 }
3245 }
3246
3247 Ok(())
3248 }
3249
3250 #[cfg(test)]
3252 fn test_target(mut self) {
3253 let recycled_target =
3254 Target::from_json(&serde_json::to_string(&self.to_json()).unwrap()).map(|(j, _)| j);
3255 self.update_to_cli();
3256 self.check_consistency(TargetKind::Builtin).unwrap();
3257 assert_eq!(recycled_target, Ok(self));
3258 }
3259
3260 fn can_use_os_unknown(&self) -> bool {
3263 self.llvm_target == "wasm32-unknown-unknown"
3264 || self.llvm_target == "wasm64-unknown-unknown"
3265 || (self.env == Env::Sgx && self.vendor == "fortanix")
3266 }
3267
3268 pub fn expect_builtin(target_tuple: &TargetTuple) -> Target {
3270 match *target_tuple {
3271 TargetTuple::TargetTuple(ref target_tuple) => {
3272 load_builtin(target_tuple).expect("built-in target")
3273 }
3274 TargetTuple::TargetJson { .. } => {
3275 panic!("built-in targets doesn't support target-paths")
3276 }
3277 }
3278 }
3279
3280 pub fn builtins() -> impl Iterator<Item = Target> {
3282 load_all_builtins()
3283 }
3284
3285 pub fn search(
3295 target_tuple: &TargetTuple,
3296 sysroot: &Path,
3297 ) -> Result<(Target, TargetWarnings), String> {
3298 use std::{env, fs};
3299
3300 fn load_file(path: &Path) -> Result<(Target, TargetWarnings), String> {
3301 let contents = fs::read_to_string(path).map_err(|e| e.to_string())?;
3302 Target::from_json(&contents)
3303 }
3304
3305 match *target_tuple {
3306 TargetTuple::TargetTuple(ref target_tuple) => {
3307 if let Some(t) = load_builtin(target_tuple) {
3309 return Ok((t, TargetWarnings::empty()));
3310 }
3311
3312 let path = {
3314 let mut target = target_tuple.to_string();
3315 target.push_str(".json");
3316 PathBuf::from(target)
3317 };
3318
3319 let target_path = env::var_os("RUST_TARGET_PATH").unwrap_or_default();
3320
3321 for dir in env::split_paths(&target_path) {
3322 let p = dir.join(&path);
3323 if p.is_file() {
3324 return load_file(&p);
3325 }
3326 }
3327
3328 let rustlib_path = crate::relative_target_rustlib_path(sysroot, target_tuple);
3331 let p = PathBuf::from_iter([
3332 Path::new(sysroot),
3333 Path::new(&rustlib_path),
3334 Path::new("target.json"),
3335 ]);
3336 if p.is_file() {
3337 return load_file(&p);
3338 }
3339
3340 Err(format!("could not find specification for target {target_tuple:?}"))
3341 }
3342 TargetTuple::TargetJson { ref contents, .. } => Target::from_json(contents),
3343 }
3344 }
3345
3346 pub fn small_data_threshold_support(&self) -> SmallDataThresholdSupport {
3349 match &self.options.small_data_threshold_support {
3350 SmallDataThresholdSupport::DefaultForArch => match self.arch {
3354 Arch::Mips | Arch::Mips64 | Arch::Mips32r6 => {
3355 SmallDataThresholdSupport::LlvmArg("mips-ssection-threshold".into())
3356 }
3357 Arch::Hexagon => {
3358 SmallDataThresholdSupport::LlvmArg("hexagon-small-data-threshold".into())
3359 }
3360 Arch::M68k => SmallDataThresholdSupport::LlvmArg("m68k-ssection-threshold".into()),
3361 Arch::RiscV32 | Arch::RiscV64 => {
3362 SmallDataThresholdSupport::LlvmModuleFlag("SmallDataLimit".into())
3363 }
3364 _ => SmallDataThresholdSupport::None,
3365 },
3366 s => s.clone(),
3367 }
3368 }
3369
3370 pub fn object_architecture(
3371 &self,
3372 unstable_target_features: &FxIndexSet<Symbol>,
3373 ) -> Option<(object::Architecture, Option<object::SubArchitecture>)> {
3374 use object::Architecture;
3375 Some(match self.arch {
3376 Arch::Arm => (Architecture::Arm, None),
3377 Arch::AArch64 => (
3378 if self.pointer_width == 32 {
3379 Architecture::Aarch64_Ilp32
3380 } else {
3381 Architecture::Aarch64
3382 },
3383 None,
3384 ),
3385 Arch::X86 => (Architecture::I386, None),
3386 Arch::S390x => (Architecture::S390x, None),
3387 Arch::M68k => (Architecture::M68k, None),
3388 Arch::Mips | Arch::Mips32r6 => (Architecture::Mips, None),
3389 Arch::Mips64 | Arch::Mips64r6 => (
3390 if self.options.llvm_abiname.as_ref() == "n32" {
3396 Architecture::Mips64_N32
3397 } else {
3398 Architecture::Mips64
3399 },
3400 None,
3401 ),
3402 Arch::X86_64 => (
3403 if self.pointer_width == 32 {
3404 Architecture::X86_64_X32
3405 } else {
3406 Architecture::X86_64
3407 },
3408 None,
3409 ),
3410 Arch::PowerPC => (Architecture::PowerPc, None),
3411 Arch::PowerPC64 => (Architecture::PowerPc64, None),
3412 Arch::RiscV32 => (Architecture::Riscv32, None),
3413 Arch::RiscV64 => (Architecture::Riscv64, None),
3414 Arch::Sparc => {
3415 if unstable_target_features.contains(&sym::v8plus) {
3416 (Architecture::Sparc32Plus, None)
3418 } else {
3419 (Architecture::Sparc, None)
3421 }
3422 }
3423 Arch::Sparc64 => (Architecture::Sparc64, None),
3424 Arch::Avr => (Architecture::Avr, None),
3425 Arch::Msp430 => (Architecture::Msp430, None),
3426 Arch::Hexagon => (Architecture::Hexagon, None),
3427 Arch::Xtensa => (Architecture::Xtensa, None),
3428 Arch::Bpf => (Architecture::Bpf, None),
3429 Arch::LoongArch32 => (Architecture::LoongArch32, None),
3430 Arch::LoongArch64 => (Architecture::LoongArch64, None),
3431 Arch::CSky => (Architecture::Csky, None),
3432 Arch::Arm64EC => (Architecture::Aarch64, Some(object::SubArchitecture::Arm64EC)),
3433 Arch::AmdGpu
3434 | Arch::Nvptx64
3435 | Arch::PowerPC64LE
3436 | Arch::SpirV
3437 | Arch::Wasm32
3438 | Arch::Wasm64
3439 | Arch::Other(_) => return None,
3440 })
3441 }
3442
3443 pub fn max_reliable_alignment(&self) -> Align {
3452 if self.is_like_windows && self.arch == Arch::X86 {
3456 Align::from_bytes(4).unwrap()
3457 } else {
3458 Align::MAX
3459 }
3460 }
3461
3462 pub fn vendor_symbol(&self) -> Symbol {
3463 Symbol::intern(&self.vendor)
3464 }
3465}
3466
3467#[derive(Clone, Debug)]
3469pub enum TargetTuple {
3470 TargetTuple(String),
3471 TargetJson {
3472 path_for_rustdoc: PathBuf,
3475 tuple: String,
3476 contents: String,
3477 },
3478}
3479
3480impl PartialEq for TargetTuple {
3482 fn eq(&self, other: &Self) -> bool {
3483 match (self, other) {
3484 (Self::TargetTuple(l0), Self::TargetTuple(r0)) => l0 == r0,
3485 (
3486 Self::TargetJson { path_for_rustdoc: _, tuple: l_tuple, contents: l_contents },
3487 Self::TargetJson { path_for_rustdoc: _, tuple: r_tuple, contents: r_contents },
3488 ) => l_tuple == r_tuple && l_contents == r_contents,
3489 _ => false,
3490 }
3491 }
3492}
3493
3494impl Hash for TargetTuple {
3496 fn hash<H: Hasher>(&self, state: &mut H) -> () {
3497 match self {
3498 TargetTuple::TargetTuple(tuple) => {
3499 0u8.hash(state);
3500 tuple.hash(state)
3501 }
3502 TargetTuple::TargetJson { path_for_rustdoc: _, tuple, contents } => {
3503 1u8.hash(state);
3504 tuple.hash(state);
3505 contents.hash(state)
3506 }
3507 }
3508 }
3509}
3510
3511impl<S: Encoder> Encodable<S> for TargetTuple {
3513 fn encode(&self, s: &mut S) {
3514 match self {
3515 TargetTuple::TargetTuple(tuple) => {
3516 s.emit_u8(0);
3517 s.emit_str(tuple);
3518 }
3519 TargetTuple::TargetJson { path_for_rustdoc: _, tuple, contents } => {
3520 s.emit_u8(1);
3521 s.emit_str(tuple);
3522 s.emit_str(contents);
3523 }
3524 }
3525 }
3526}
3527
3528impl<D: Decoder> Decodable<D> for TargetTuple {
3529 fn decode(d: &mut D) -> Self {
3530 match d.read_u8() {
3531 0 => TargetTuple::TargetTuple(d.read_str().to_owned()),
3532 1 => TargetTuple::TargetJson {
3533 path_for_rustdoc: PathBuf::new(),
3534 tuple: d.read_str().to_owned(),
3535 contents: d.read_str().to_owned(),
3536 },
3537 _ => {
3538 panic!("invalid enum variant tag while decoding `TargetTuple`, expected 0..2");
3539 }
3540 }
3541 }
3542}
3543
3544impl TargetTuple {
3545 pub fn from_tuple(tuple: &str) -> Self {
3547 TargetTuple::TargetTuple(tuple.into())
3548 }
3549
3550 pub fn from_path(path: &Path) -> Result<Self, io::Error> {
3552 let canonicalized_path = try_canonicalize(path)?;
3553 let contents = std::fs::read_to_string(&canonicalized_path).map_err(|err| {
3554 io::Error::new(
3555 io::ErrorKind::InvalidInput,
3556 format!("target path {canonicalized_path:?} is not a valid file: {err}"),
3557 )
3558 })?;
3559 let tuple = canonicalized_path
3560 .file_stem()
3561 .expect("target path must not be empty")
3562 .to_str()
3563 .expect("target path must be valid unicode")
3564 .to_owned();
3565 Ok(TargetTuple::TargetJson { path_for_rustdoc: canonicalized_path, tuple, contents })
3566 }
3567
3568 pub fn tuple(&self) -> &str {
3572 match *self {
3573 TargetTuple::TargetTuple(ref tuple) | TargetTuple::TargetJson { ref tuple, .. } => {
3574 tuple
3575 }
3576 }
3577 }
3578
3579 pub fn debug_tuple(&self) -> String {
3584 use std::hash::DefaultHasher;
3585
3586 match self {
3587 TargetTuple::TargetTuple(tuple) => tuple.to_owned(),
3588 TargetTuple::TargetJson { path_for_rustdoc: _, tuple, contents: content } => {
3589 let mut hasher = DefaultHasher::new();
3590 content.hash(&mut hasher);
3591 let hash = hasher.finish();
3592 format!("{tuple}-{hash}")
3593 }
3594 }
3595 }
3596}
3597
3598impl fmt::Display for TargetTuple {
3599 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3600 write!(f, "{}", self.debug_tuple())
3601 }
3602}
3603
3604into_diag_arg_using_display!(&TargetTuple);