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::{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, Decodable, 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, Decodable, HashStable_Generic)]
844pub enum OnBrokenPipe {
845 Default,
846 Kill,
847 Error,
848 Inherit,
849}
850
851impl PanicStrategy {
852 pub const fn desc_symbol(&self) -> Symbol {
853 match *self {
854 PanicStrategy::Unwind => sym::unwind,
855 PanicStrategy::Abort => sym::abort,
856 PanicStrategy::ImmediateAbort => sym::immediate_abort,
857 }
858 }
859
860 pub fn unwinds(self) -> bool {
861 matches!(self, PanicStrategy::Unwind)
862 }
863}
864
865crate::target_spec_enum! {
866 pub enum RelroLevel {
867 Full = "full",
868 Partial = "partial",
869 Off = "off",
870 None = "none",
871 }
872
873 parse_error_type = "relro level";
874}
875
876impl IntoDiagArg for PanicStrategy {
877 fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
878 DiagArgValue::Str(Cow::Owned(self.desc().to_string()))
879 }
880}
881
882crate::target_spec_enum! {
883 pub enum SymbolVisibility {
884 Hidden = "hidden",
885 Protected = "protected",
886 Interposable = "interposable",
887 }
888
889 parse_error_type = "symbol visibility";
890}
891
892#[derive(Clone, Debug, PartialEq, Hash)]
893pub enum SmallDataThresholdSupport {
894 None,
895 DefaultForArch,
896 LlvmModuleFlag(StaticCow<str>),
897 LlvmArg(StaticCow<str>),
898}
899
900impl FromStr for SmallDataThresholdSupport {
901 type Err = String;
902
903 fn from_str(s: &str) -> Result<Self, Self::Err> {
904 if s == "none" {
905 Ok(Self::None)
906 } else if s == "default-for-arch" {
907 Ok(Self::DefaultForArch)
908 } else if let Some(flag) = s.strip_prefix("llvm-module-flag=") {
909 Ok(Self::LlvmModuleFlag(flag.to_string().into()))
910 } else if let Some(arg) = s.strip_prefix("llvm-arg=") {
911 Ok(Self::LlvmArg(arg.to_string().into()))
912 } else {
913 Err(format!("'{s}' is not a valid value for small-data-threshold-support."))
914 }
915 }
916}
917
918crate::json::serde_deserialize_from_str!(SmallDataThresholdSupport);
919impl schemars::JsonSchema for SmallDataThresholdSupport {
920 fn schema_name() -> std::borrow::Cow<'static, str> {
921 "SmallDataThresholdSupport".into()
922 }
923 fn json_schema(_: &mut schemars::SchemaGenerator) -> schemars::Schema {
924 schemars::json_schema! ({
925 "type": "string",
926 "pattern": r#"^none|default-for-arch|llvm-module-flag=.+|llvm-arg=.+$"#,
927 })
928 .into()
929 }
930}
931
932impl ToJson for SmallDataThresholdSupport {
933 fn to_json(&self) -> Value {
934 match self {
935 Self::None => "none".to_json(),
936 Self::DefaultForArch => "default-for-arch".to_json(),
937 Self::LlvmModuleFlag(flag) => format!("llvm-module-flag={flag}").to_json(),
938 Self::LlvmArg(arg) => format!("llvm-arg={arg}").to_json(),
939 }
940 }
941}
942
943crate::target_spec_enum! {
944 pub enum MergeFunctions {
945 Disabled = "disabled",
946 Trampolines = "trampolines",
947 Aliases = "aliases",
948 }
949
950 parse_error_type = "value for merge-functions";
951}
952
953crate::target_spec_enum! {
954 pub enum RelocModel {
955 Static = "static",
956 Pic = "pic",
957 Pie = "pie",
958 DynamicNoPic = "dynamic-no-pic",
959 Ropi = "ropi",
960 Rwpi = "rwpi",
961 RopiRwpi = "ropi-rwpi",
962 }
963
964 parse_error_type = "relocation model";
965}
966
967impl RelocModel {
968 pub const fn desc_symbol(&self) -> Symbol {
969 match *self {
970 RelocModel::Static => kw::Static,
971 RelocModel::Pic => sym::pic,
972 RelocModel::Pie => sym::pie,
973 RelocModel::DynamicNoPic => sym::dynamic_no_pic,
974 RelocModel::Ropi => sym::ropi,
975 RelocModel::Rwpi => sym::rwpi,
976 RelocModel::RopiRwpi => sym::ropi_rwpi,
977 }
978 }
979}
980
981crate::target_spec_enum! {
982 pub enum CodeModel {
983 Tiny = "tiny",
984 Small = "small",
985 Kernel = "kernel",
986 Medium = "medium",
987 Large = "large",
988 }
989
990 parse_error_type = "code model";
991}
992
993crate::target_spec_enum! {
994 pub enum FloatAbi {
996 Soft = "soft",
997 Hard = "hard",
998 }
999
1000 parse_error_type = "float abi";
1001}
1002
1003crate::target_spec_enum! {
1004 pub enum RustcAbi {
1006 X86Sse2 = "x86-sse2",
1008 X86Softfloat = "x86-softfloat",
1010 }
1011
1012 parse_error_type = "rustc abi";
1013}
1014
1015crate::target_spec_enum! {
1016 pub enum TlsModel {
1017 GeneralDynamic = "global-dynamic",
1018 LocalDynamic = "local-dynamic",
1019 InitialExec = "initial-exec",
1020 LocalExec = "local-exec",
1021 Emulated = "emulated",
1022 }
1023
1024 parse_error_type = "TLS model";
1025}
1026
1027crate::target_spec_enum! {
1028 pub enum LinkOutputKind {
1030 DynamicNoPicExe = "dynamic-nopic-exe",
1032 DynamicPicExe = "dynamic-pic-exe",
1034 StaticNoPicExe = "static-nopic-exe",
1036 StaticPicExe = "static-pic-exe",
1038 DynamicDylib = "dynamic-dylib",
1040 StaticDylib = "static-dylib",
1042 WasiReactorExe = "wasi-reactor-exe",
1044 }
1045
1046 parse_error_type = "CRT object kind";
1047}
1048
1049impl LinkOutputKind {
1050 pub fn can_link_dylib(self) -> bool {
1051 match self {
1052 LinkOutputKind::StaticNoPicExe | LinkOutputKind::StaticPicExe => false,
1053 LinkOutputKind::DynamicNoPicExe
1054 | LinkOutputKind::DynamicPicExe
1055 | LinkOutputKind::DynamicDylib
1056 | LinkOutputKind::StaticDylib
1057 | LinkOutputKind::WasiReactorExe => true,
1058 }
1059 }
1060}
1061
1062pub type LinkArgs = BTreeMap<LinkerFlavor, Vec<StaticCow<str>>>;
1063pub type LinkArgsCli = BTreeMap<LinkerFlavorCli, Vec<StaticCow<str>>>;
1064
1065crate::target_spec_enum! {
1066 #[derive(Default)]
1071 pub enum DebuginfoKind {
1072 #[default]
1074 Dwarf = "dwarf",
1075 DwarfDsym = "dwarf-dsym",
1077 Pdb = "pdb",
1079 }
1080
1081 parse_error_type = "debuginfo kind";
1082}
1083
1084crate::target_spec_enum! {
1085 #[derive(Default)]
1086 pub enum SplitDebuginfo {
1087 #[default]
1095 Off = "off",
1096
1097 Packed = "packed",
1104
1105 Unpacked = "unpacked",
1112 }
1113
1114 parse_error_type = "split debuginfo";
1115}
1116
1117into_diag_arg_using_display!(SplitDebuginfo);
1118
1119#[derive(Clone, Debug, PartialEq, Eq, serde_derive::Deserialize, schemars::JsonSchema)]
1120#[serde(tag = "kind")]
1121#[serde(rename_all = "kebab-case")]
1122pub enum StackProbeType {
1123 None,
1125 Inline,
1129 Call,
1131 InlineOrCall {
1134 #[serde(rename = "min-llvm-version-for-inline")]
1135 min_llvm_version_for_inline: (u32, u32, u32),
1136 },
1137}
1138
1139impl ToJson for StackProbeType {
1140 fn to_json(&self) -> Json {
1141 Json::Object(match self {
1142 StackProbeType::None => {
1143 [(String::from("kind"), "none".to_json())].into_iter().collect()
1144 }
1145 StackProbeType::Inline => {
1146 [(String::from("kind"), "inline".to_json())].into_iter().collect()
1147 }
1148 StackProbeType::Call => {
1149 [(String::from("kind"), "call".to_json())].into_iter().collect()
1150 }
1151 StackProbeType::InlineOrCall { min_llvm_version_for_inline: (maj, min, patch) } => [
1152 (String::from("kind"), "inline-or-call".to_json()),
1153 (
1154 String::from("min-llvm-version-for-inline"),
1155 Json::Array(vec![maj.to_json(), min.to_json(), patch.to_json()]),
1156 ),
1157 ]
1158 .into_iter()
1159 .collect(),
1160 })
1161 }
1162}
1163
1164#[derive(Default, Clone, Copy, PartialEq, Eq, Hash, Encodable, Decodable, HashStable_Generic)]
1165pub struct SanitizerSet(u16);
1166bitflags::bitflags! {
1167 impl SanitizerSet: u16 {
1168 const ADDRESS = 1 << 0;
1169 const LEAK = 1 << 1;
1170 const MEMORY = 1 << 2;
1171 const THREAD = 1 << 3;
1172 const HWADDRESS = 1 << 4;
1173 const CFI = 1 << 5;
1174 const MEMTAG = 1 << 6;
1175 const SHADOWCALLSTACK = 1 << 7;
1176 const KCFI = 1 << 8;
1177 const KERNELADDRESS = 1 << 9;
1178 const SAFESTACK = 1 << 10;
1179 const DATAFLOW = 1 << 11;
1180 const REALTIME = 1 << 12;
1181 }
1182}
1183rustc_data_structures::external_bitflags_debug! { SanitizerSet }
1184
1185impl SanitizerSet {
1186 const MUTUALLY_EXCLUSIVE: &'static [(SanitizerSet, SanitizerSet)] = &[
1189 (SanitizerSet::ADDRESS, SanitizerSet::MEMORY),
1190 (SanitizerSet::ADDRESS, SanitizerSet::THREAD),
1191 (SanitizerSet::ADDRESS, SanitizerSet::HWADDRESS),
1192 (SanitizerSet::ADDRESS, SanitizerSet::MEMTAG),
1193 (SanitizerSet::ADDRESS, SanitizerSet::KERNELADDRESS),
1194 (SanitizerSet::ADDRESS, SanitizerSet::SAFESTACK),
1195 (SanitizerSet::LEAK, SanitizerSet::MEMORY),
1196 (SanitizerSet::LEAK, SanitizerSet::THREAD),
1197 (SanitizerSet::LEAK, SanitizerSet::KERNELADDRESS),
1198 (SanitizerSet::LEAK, SanitizerSet::SAFESTACK),
1199 (SanitizerSet::MEMORY, SanitizerSet::THREAD),
1200 (SanitizerSet::MEMORY, SanitizerSet::HWADDRESS),
1201 (SanitizerSet::MEMORY, SanitizerSet::KERNELADDRESS),
1202 (SanitizerSet::MEMORY, SanitizerSet::SAFESTACK),
1203 (SanitizerSet::THREAD, SanitizerSet::HWADDRESS),
1204 (SanitizerSet::THREAD, SanitizerSet::KERNELADDRESS),
1205 (SanitizerSet::THREAD, SanitizerSet::SAFESTACK),
1206 (SanitizerSet::HWADDRESS, SanitizerSet::MEMTAG),
1207 (SanitizerSet::HWADDRESS, SanitizerSet::KERNELADDRESS),
1208 (SanitizerSet::HWADDRESS, SanitizerSet::SAFESTACK),
1209 (SanitizerSet::CFI, SanitizerSet::KCFI),
1210 (SanitizerSet::MEMTAG, SanitizerSet::KERNELADDRESS),
1211 (SanitizerSet::KERNELADDRESS, SanitizerSet::SAFESTACK),
1212 ];
1213
1214 pub fn as_str(self) -> Option<&'static str> {
1218 Some(match self {
1219 SanitizerSet::ADDRESS => "address",
1220 SanitizerSet::CFI => "cfi",
1221 SanitizerSet::DATAFLOW => "dataflow",
1222 SanitizerSet::KCFI => "kcfi",
1223 SanitizerSet::KERNELADDRESS => "kernel-address",
1224 SanitizerSet::LEAK => "leak",
1225 SanitizerSet::MEMORY => "memory",
1226 SanitizerSet::MEMTAG => "memtag",
1227 SanitizerSet::SAFESTACK => "safestack",
1228 SanitizerSet::SHADOWCALLSTACK => "shadow-call-stack",
1229 SanitizerSet::THREAD => "thread",
1230 SanitizerSet::HWADDRESS => "hwaddress",
1231 SanitizerSet::REALTIME => "realtime",
1232 _ => return None,
1233 })
1234 }
1235
1236 pub fn mutually_exclusive(self) -> Option<(SanitizerSet, SanitizerSet)> {
1237 Self::MUTUALLY_EXCLUSIVE
1238 .into_iter()
1239 .find(|&(a, b)| self.contains(*a) && self.contains(*b))
1240 .copied()
1241 }
1242}
1243
1244impl fmt::Display for SanitizerSet {
1246 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1247 let mut first = true;
1248 for s in *self {
1249 let name = s.as_str().unwrap_or_else(|| panic!("unrecognized sanitizer {s:?}"));
1250 if !first {
1251 f.write_str(", ")?;
1252 }
1253 f.write_str(name)?;
1254 first = false;
1255 }
1256 Ok(())
1257 }
1258}
1259
1260impl FromStr for SanitizerSet {
1261 type Err = String;
1262 fn from_str(s: &str) -> Result<Self, Self::Err> {
1263 Ok(match s {
1264 "address" => SanitizerSet::ADDRESS,
1265 "cfi" => SanitizerSet::CFI,
1266 "dataflow" => SanitizerSet::DATAFLOW,
1267 "kcfi" => SanitizerSet::KCFI,
1268 "kernel-address" => SanitizerSet::KERNELADDRESS,
1269 "leak" => SanitizerSet::LEAK,
1270 "memory" => SanitizerSet::MEMORY,
1271 "memtag" => SanitizerSet::MEMTAG,
1272 "safestack" => SanitizerSet::SAFESTACK,
1273 "shadow-call-stack" => SanitizerSet::SHADOWCALLSTACK,
1274 "thread" => SanitizerSet::THREAD,
1275 "hwaddress" => SanitizerSet::HWADDRESS,
1276 "realtime" => SanitizerSet::REALTIME,
1277 s => return Err(format!("unknown sanitizer {s}")),
1278 })
1279 }
1280}
1281
1282crate::json::serde_deserialize_from_str!(SanitizerSet);
1283impl schemars::JsonSchema for SanitizerSet {
1284 fn schema_name() -> std::borrow::Cow<'static, str> {
1285 "SanitizerSet".into()
1286 }
1287 fn json_schema(_: &mut schemars::SchemaGenerator) -> schemars::Schema {
1288 let all = Self::all().iter().map(|sanitizer| sanitizer.as_str()).collect::<Vec<_>>();
1289 schemars::json_schema! ({
1290 "type": "string",
1291 "enum": all,
1292 })
1293 .into()
1294 }
1295}
1296
1297impl ToJson for SanitizerSet {
1298 fn to_json(&self) -> Json {
1299 self.into_iter()
1300 .map(|v| Some(v.as_str()?.to_json()))
1301 .collect::<Option<Vec<_>>>()
1302 .unwrap_or_default()
1303 .to_json()
1304 }
1305}
1306
1307crate::target_spec_enum! {
1308 pub enum FramePointer {
1309 Always = "always",
1311 NonLeaf = "non-leaf",
1314 MayOmit = "may-omit",
1318 }
1319
1320 parse_error_type = "frame pointer";
1321}
1322
1323impl FramePointer {
1324 #[inline]
1327 pub fn ratchet(&mut self, rhs: FramePointer) -> FramePointer {
1328 *self = match (*self, rhs) {
1329 (FramePointer::Always, _) | (_, FramePointer::Always) => FramePointer::Always,
1330 (FramePointer::NonLeaf, _) | (_, FramePointer::NonLeaf) => FramePointer::NonLeaf,
1331 _ => FramePointer::MayOmit,
1332 };
1333 *self
1334 }
1335}
1336
1337crate::target_spec_enum! {
1338 pub enum StackProtector {
1340 None = "none",
1342
1343 Basic = "basic",
1348
1349 Strong = "strong",
1354
1355 All = "all",
1357 }
1358
1359 parse_error_type = "stack protector";
1360}
1361
1362into_diag_arg_using_display!(StackProtector);
1363
1364crate::target_spec_enum! {
1365 pub enum BinaryFormat {
1366 Coff = "coff",
1367 Elf = "elf",
1368 MachO = "mach-o",
1369 Wasm = "wasm",
1370 Xcoff = "xcoff",
1371 }
1372
1373 parse_error_type = "binary format";
1374}
1375
1376impl BinaryFormat {
1377 pub fn to_object(&self) -> object::BinaryFormat {
1379 match self {
1380 Self::Coff => object::BinaryFormat::Coff,
1381 Self::Elf => object::BinaryFormat::Elf,
1382 Self::MachO => object::BinaryFormat::MachO,
1383 Self::Wasm => object::BinaryFormat::Wasm,
1384 Self::Xcoff => object::BinaryFormat::Xcoff,
1385 }
1386 }
1387}
1388
1389impl ToJson for Align {
1390 fn to_json(&self) -> Json {
1391 self.bits().to_json()
1392 }
1393}
1394
1395macro_rules! supported_targets {
1396 ( $(($tuple:literal, $module:ident),)+ ) => {
1397 mod targets {
1398 $(pub(crate) mod $module;)+
1399 }
1400
1401 pub static TARGETS: &[&str] = &[$($tuple),+];
1403
1404 fn load_builtin(target: &str) -> Option<Target> {
1405 let t = match target {
1406 $( $tuple => targets::$module::target(), )+
1407 _ => return None,
1408 };
1409 debug!("got builtin target: {:?}", t);
1410 Some(t)
1411 }
1412
1413 fn load_all_builtins() -> impl Iterator<Item = Target> {
1414 [
1415 $( targets::$module::target, )+
1416 ]
1417 .into_iter()
1418 .map(|f| f())
1419 }
1420
1421 #[cfg(test)]
1422 mod tests {
1423 $(
1425 #[test] fn $module() {
1427 crate::spec::targets::$module::target().test_target()
1428 }
1429 )+
1430 }
1431 };
1432}
1433
1434supported_targets! {
1435 ("x86_64-unknown-linux-gnu", x86_64_unknown_linux_gnu),
1436 ("x86_64-unknown-linux-gnux32", x86_64_unknown_linux_gnux32),
1437 ("i686-unknown-linux-gnu", i686_unknown_linux_gnu),
1438 ("i586-unknown-linux-gnu", i586_unknown_linux_gnu),
1439 ("loongarch64-unknown-linux-gnu", loongarch64_unknown_linux_gnu),
1440 ("loongarch64-unknown-linux-musl", loongarch64_unknown_linux_musl),
1441 ("m68k-unknown-linux-gnu", m68k_unknown_linux_gnu),
1442 ("m68k-unknown-none-elf", m68k_unknown_none_elf),
1443 ("csky-unknown-linux-gnuabiv2", csky_unknown_linux_gnuabiv2),
1444 ("csky-unknown-linux-gnuabiv2hf", csky_unknown_linux_gnuabiv2hf),
1445 ("mips-unknown-linux-gnu", mips_unknown_linux_gnu),
1446 ("mips64-unknown-linux-gnuabi64", mips64_unknown_linux_gnuabi64),
1447 ("mips64el-unknown-linux-gnuabi64", mips64el_unknown_linux_gnuabi64),
1448 ("mipsisa32r6-unknown-linux-gnu", mipsisa32r6_unknown_linux_gnu),
1449 ("mipsisa32r6el-unknown-linux-gnu", mipsisa32r6el_unknown_linux_gnu),
1450 ("mipsisa64r6-unknown-linux-gnuabi64", mipsisa64r6_unknown_linux_gnuabi64),
1451 ("mipsisa64r6el-unknown-linux-gnuabi64", mipsisa64r6el_unknown_linux_gnuabi64),
1452 ("mipsel-unknown-linux-gnu", mipsel_unknown_linux_gnu),
1453 ("powerpc-unknown-linux-gnu", powerpc_unknown_linux_gnu),
1454 ("powerpc-unknown-linux-gnuspe", powerpc_unknown_linux_gnuspe),
1455 ("powerpc-unknown-linux-musl", powerpc_unknown_linux_musl),
1456 ("powerpc-unknown-linux-muslspe", powerpc_unknown_linux_muslspe),
1457 ("powerpc64-ibm-aix", powerpc64_ibm_aix),
1458 ("powerpc64-unknown-linux-gnu", powerpc64_unknown_linux_gnu),
1459 ("powerpc64-unknown-linux-musl", powerpc64_unknown_linux_musl),
1460 ("powerpc64le-unknown-linux-gnu", powerpc64le_unknown_linux_gnu),
1461 ("powerpc64le-unknown-linux-musl", powerpc64le_unknown_linux_musl),
1462 ("s390x-unknown-linux-gnu", s390x_unknown_linux_gnu),
1463 ("s390x-unknown-linux-musl", s390x_unknown_linux_musl),
1464 ("sparc-unknown-linux-gnu", sparc_unknown_linux_gnu),
1465 ("sparc64-unknown-linux-gnu", sparc64_unknown_linux_gnu),
1466 ("arm-unknown-linux-gnueabi", arm_unknown_linux_gnueabi),
1467 ("arm-unknown-linux-gnueabihf", arm_unknown_linux_gnueabihf),
1468 ("armeb-unknown-linux-gnueabi", armeb_unknown_linux_gnueabi),
1469 ("arm-unknown-linux-musleabi", arm_unknown_linux_musleabi),
1470 ("arm-unknown-linux-musleabihf", arm_unknown_linux_musleabihf),
1471 ("armv4t-unknown-linux-gnueabi", armv4t_unknown_linux_gnueabi),
1472 ("armv5te-unknown-linux-gnueabi", armv5te_unknown_linux_gnueabi),
1473 ("armv5te-unknown-linux-musleabi", armv5te_unknown_linux_musleabi),
1474 ("armv5te-unknown-linux-uclibceabi", armv5te_unknown_linux_uclibceabi),
1475 ("armv7-unknown-linux-gnueabi", armv7_unknown_linux_gnueabi),
1476 ("armv7-unknown-linux-gnueabihf", armv7_unknown_linux_gnueabihf),
1477 ("thumbv7neon-unknown-linux-gnueabihf", thumbv7neon_unknown_linux_gnueabihf),
1478 ("thumbv7neon-unknown-linux-musleabihf", thumbv7neon_unknown_linux_musleabihf),
1479 ("armv7-unknown-linux-musleabi", armv7_unknown_linux_musleabi),
1480 ("armv7-unknown-linux-musleabihf", armv7_unknown_linux_musleabihf),
1481 ("aarch64-unknown-linux-gnu", aarch64_unknown_linux_gnu),
1482 ("aarch64-unknown-linux-musl", aarch64_unknown_linux_musl),
1483 ("aarch64_be-unknown-linux-musl", aarch64_be_unknown_linux_musl),
1484 ("x86_64-unknown-linux-musl", x86_64_unknown_linux_musl),
1485 ("i686-unknown-linux-musl", i686_unknown_linux_musl),
1486 ("i586-unknown-linux-musl", i586_unknown_linux_musl),
1487 ("mips-unknown-linux-musl", mips_unknown_linux_musl),
1488 ("mipsel-unknown-linux-musl", mipsel_unknown_linux_musl),
1489 ("mips64-unknown-linux-muslabi64", mips64_unknown_linux_muslabi64),
1490 ("mips64el-unknown-linux-muslabi64", mips64el_unknown_linux_muslabi64),
1491 ("hexagon-unknown-linux-musl", hexagon_unknown_linux_musl),
1492 ("hexagon-unknown-none-elf", hexagon_unknown_none_elf),
1493 ("hexagon-unknown-qurt", hexagon_unknown_qurt),
1494
1495 ("mips-unknown-linux-uclibc", mips_unknown_linux_uclibc),
1496 ("mipsel-unknown-linux-uclibc", mipsel_unknown_linux_uclibc),
1497
1498 ("i686-linux-android", i686_linux_android),
1499 ("x86_64-linux-android", x86_64_linux_android),
1500 ("arm-linux-androideabi", arm_linux_androideabi),
1501 ("armv7-linux-androideabi", armv7_linux_androideabi),
1502 ("thumbv7neon-linux-androideabi", thumbv7neon_linux_androideabi),
1503 ("aarch64-linux-android", aarch64_linux_android),
1504 ("riscv64-linux-android", riscv64_linux_android),
1505
1506 ("aarch64-unknown-freebsd", aarch64_unknown_freebsd),
1507 ("armv6-unknown-freebsd", armv6_unknown_freebsd),
1508 ("armv7-unknown-freebsd", armv7_unknown_freebsd),
1509 ("i686-unknown-freebsd", i686_unknown_freebsd),
1510 ("powerpc-unknown-freebsd", powerpc_unknown_freebsd),
1511 ("powerpc64-unknown-freebsd", powerpc64_unknown_freebsd),
1512 ("powerpc64le-unknown-freebsd", powerpc64le_unknown_freebsd),
1513 ("riscv64gc-unknown-freebsd", riscv64gc_unknown_freebsd),
1514 ("x86_64-unknown-freebsd", x86_64_unknown_freebsd),
1515
1516 ("x86_64-unknown-dragonfly", x86_64_unknown_dragonfly),
1517
1518 ("aarch64-unknown-openbsd", aarch64_unknown_openbsd),
1519 ("i686-unknown-openbsd", i686_unknown_openbsd),
1520 ("powerpc-unknown-openbsd", powerpc_unknown_openbsd),
1521 ("powerpc64-unknown-openbsd", powerpc64_unknown_openbsd),
1522 ("riscv64gc-unknown-openbsd", riscv64gc_unknown_openbsd),
1523 ("sparc64-unknown-openbsd", sparc64_unknown_openbsd),
1524 ("x86_64-unknown-openbsd", x86_64_unknown_openbsd),
1525
1526 ("aarch64-unknown-netbsd", aarch64_unknown_netbsd),
1527 ("aarch64_be-unknown-netbsd", aarch64_be_unknown_netbsd),
1528 ("armv6-unknown-netbsd-eabihf", armv6_unknown_netbsd_eabihf),
1529 ("armv7-unknown-netbsd-eabihf", armv7_unknown_netbsd_eabihf),
1530 ("i586-unknown-netbsd", i586_unknown_netbsd),
1531 ("i686-unknown-netbsd", i686_unknown_netbsd),
1532 ("mipsel-unknown-netbsd", mipsel_unknown_netbsd),
1533 ("powerpc-unknown-netbsd", powerpc_unknown_netbsd),
1534 ("riscv64gc-unknown-netbsd", riscv64gc_unknown_netbsd),
1535 ("sparc64-unknown-netbsd", sparc64_unknown_netbsd),
1536 ("x86_64-unknown-netbsd", x86_64_unknown_netbsd),
1537
1538 ("i686-unknown-haiku", i686_unknown_haiku),
1539 ("x86_64-unknown-haiku", x86_64_unknown_haiku),
1540
1541 ("aarch64-unknown-helenos", aarch64_unknown_helenos),
1542 ("i686-unknown-helenos", i686_unknown_helenos),
1543 ("powerpc-unknown-helenos", powerpc_unknown_helenos),
1544 ("sparc64-unknown-helenos", sparc64_unknown_helenos),
1545 ("x86_64-unknown-helenos", x86_64_unknown_helenos),
1546
1547 ("i686-unknown-hurd-gnu", i686_unknown_hurd_gnu),
1548 ("x86_64-unknown-hurd-gnu", x86_64_unknown_hurd_gnu),
1549
1550 ("aarch64-apple-darwin", aarch64_apple_darwin),
1551 ("arm64e-apple-darwin", arm64e_apple_darwin),
1552 ("x86_64-apple-darwin", x86_64_apple_darwin),
1553 ("x86_64h-apple-darwin", x86_64h_apple_darwin),
1554 ("i686-apple-darwin", i686_apple_darwin),
1555
1556 ("aarch64-unknown-fuchsia", aarch64_unknown_fuchsia),
1557 ("riscv64gc-unknown-fuchsia", riscv64gc_unknown_fuchsia),
1558 ("x86_64-unknown-fuchsia", x86_64_unknown_fuchsia),
1559
1560 ("avr-none", avr_none),
1561
1562 ("x86_64-unknown-l4re-uclibc", x86_64_unknown_l4re_uclibc),
1563
1564 ("aarch64-unknown-redox", aarch64_unknown_redox),
1565 ("i586-unknown-redox", i586_unknown_redox),
1566 ("riscv64gc-unknown-redox", riscv64gc_unknown_redox),
1567 ("x86_64-unknown-redox", x86_64_unknown_redox),
1568
1569 ("x86_64-unknown-managarm-mlibc", x86_64_unknown_managarm_mlibc),
1570 ("aarch64-unknown-managarm-mlibc", aarch64_unknown_managarm_mlibc),
1571 ("riscv64gc-unknown-managarm-mlibc", riscv64gc_unknown_managarm_mlibc),
1572
1573 ("i386-apple-ios", i386_apple_ios),
1574 ("x86_64-apple-ios", x86_64_apple_ios),
1575 ("aarch64-apple-ios", aarch64_apple_ios),
1576 ("arm64e-apple-ios", arm64e_apple_ios),
1577 ("armv7s-apple-ios", armv7s_apple_ios),
1578 ("x86_64-apple-ios-macabi", x86_64_apple_ios_macabi),
1579 ("aarch64-apple-ios-macabi", aarch64_apple_ios_macabi),
1580 ("aarch64-apple-ios-sim", aarch64_apple_ios_sim),
1581
1582 ("aarch64-apple-tvos", aarch64_apple_tvos),
1583 ("aarch64-apple-tvos-sim", aarch64_apple_tvos_sim),
1584 ("arm64e-apple-tvos", arm64e_apple_tvos),
1585 ("x86_64-apple-tvos", x86_64_apple_tvos),
1586
1587 ("armv7k-apple-watchos", armv7k_apple_watchos),
1588 ("arm64_32-apple-watchos", arm64_32_apple_watchos),
1589 ("x86_64-apple-watchos-sim", x86_64_apple_watchos_sim),
1590 ("aarch64-apple-watchos", aarch64_apple_watchos),
1591 ("aarch64-apple-watchos-sim", aarch64_apple_watchos_sim),
1592
1593 ("aarch64-apple-visionos", aarch64_apple_visionos),
1594 ("aarch64-apple-visionos-sim", aarch64_apple_visionos_sim),
1595
1596 ("armebv7r-none-eabi", armebv7r_none_eabi),
1597 ("armebv7r-none-eabihf", armebv7r_none_eabihf),
1598 ("armv7r-none-eabi", armv7r_none_eabi),
1599 ("armv7r-none-eabihf", armv7r_none_eabihf),
1600 ("armv8r-none-eabihf", armv8r_none_eabihf),
1601
1602 ("armv7-rtems-eabihf", armv7_rtems_eabihf),
1603
1604 ("x86_64-pc-solaris", x86_64_pc_solaris),
1605 ("sparcv9-sun-solaris", sparcv9_sun_solaris),
1606
1607 ("x86_64-unknown-illumos", x86_64_unknown_illumos),
1608 ("aarch64-unknown-illumos", aarch64_unknown_illumos),
1609
1610 ("x86_64-pc-windows-gnu", x86_64_pc_windows_gnu),
1611 ("x86_64-uwp-windows-gnu", x86_64_uwp_windows_gnu),
1612 ("x86_64-win7-windows-gnu", x86_64_win7_windows_gnu),
1613 ("i686-pc-windows-gnu", i686_pc_windows_gnu),
1614 ("i686-uwp-windows-gnu", i686_uwp_windows_gnu),
1615 ("i686-win7-windows-gnu", i686_win7_windows_gnu),
1616
1617 ("aarch64-pc-windows-gnullvm", aarch64_pc_windows_gnullvm),
1618 ("i686-pc-windows-gnullvm", i686_pc_windows_gnullvm),
1619 ("x86_64-pc-windows-gnullvm", x86_64_pc_windows_gnullvm),
1620
1621 ("aarch64-pc-windows-msvc", aarch64_pc_windows_msvc),
1622 ("aarch64-uwp-windows-msvc", aarch64_uwp_windows_msvc),
1623 ("arm64ec-pc-windows-msvc", arm64ec_pc_windows_msvc),
1624 ("x86_64-pc-windows-msvc", x86_64_pc_windows_msvc),
1625 ("x86_64-uwp-windows-msvc", x86_64_uwp_windows_msvc),
1626 ("x86_64-win7-windows-msvc", x86_64_win7_windows_msvc),
1627 ("i686-pc-windows-msvc", i686_pc_windows_msvc),
1628 ("i686-uwp-windows-msvc", i686_uwp_windows_msvc),
1629 ("i686-win7-windows-msvc", i686_win7_windows_msvc),
1630 ("thumbv7a-pc-windows-msvc", thumbv7a_pc_windows_msvc),
1631 ("thumbv7a-uwp-windows-msvc", thumbv7a_uwp_windows_msvc),
1632
1633 ("wasm32-unknown-emscripten", wasm32_unknown_emscripten),
1634 ("wasm32-unknown-unknown", wasm32_unknown_unknown),
1635 ("wasm32v1-none", wasm32v1_none),
1636 ("wasm32-wasip1", wasm32_wasip1),
1637 ("wasm32-wasip2", wasm32_wasip2),
1638 ("wasm32-wasip3", wasm32_wasip3),
1639 ("wasm32-wasip1-threads", wasm32_wasip1_threads),
1640 ("wasm32-wali-linux-musl", wasm32_wali_linux_musl),
1641 ("wasm64-unknown-unknown", wasm64_unknown_unknown),
1642
1643 ("thumbv6m-none-eabi", thumbv6m_none_eabi),
1644 ("thumbv7m-none-eabi", thumbv7m_none_eabi),
1645 ("thumbv7em-none-eabi", thumbv7em_none_eabi),
1646 ("thumbv7em-none-eabihf", thumbv7em_none_eabihf),
1647 ("thumbv8m.base-none-eabi", thumbv8m_base_none_eabi),
1648 ("thumbv8m.main-none-eabi", thumbv8m_main_none_eabi),
1649 ("thumbv8m.main-none-eabihf", thumbv8m_main_none_eabihf),
1650
1651 ("armv7a-none-eabi", armv7a_none_eabi),
1652 ("armv7a-none-eabihf", armv7a_none_eabihf),
1653 ("armv7a-nuttx-eabi", armv7a_nuttx_eabi),
1654 ("armv7a-nuttx-eabihf", armv7a_nuttx_eabihf),
1655 ("armv7a-vex-v5", armv7a_vex_v5),
1656
1657 ("msp430-none-elf", msp430_none_elf),
1658
1659 ("aarch64_be-unknown-hermit", aarch64_be_unknown_hermit),
1660 ("aarch64-unknown-hermit", aarch64_unknown_hermit),
1661 ("riscv64gc-unknown-hermit", riscv64gc_unknown_hermit),
1662 ("x86_64-unknown-hermit", x86_64_unknown_hermit),
1663 ("x86_64-unknown-motor", x86_64_unknown_motor),
1664
1665 ("x86_64-unikraft-linux-musl", x86_64_unikraft_linux_musl),
1666
1667 ("armv7-unknown-trusty", armv7_unknown_trusty),
1668 ("aarch64-unknown-trusty", aarch64_unknown_trusty),
1669 ("x86_64-unknown-trusty", x86_64_unknown_trusty),
1670
1671 ("riscv32i-unknown-none-elf", riscv32i_unknown_none_elf),
1672 ("riscv32im-risc0-zkvm-elf", riscv32im_risc0_zkvm_elf),
1673 ("riscv32im-unknown-none-elf", riscv32im_unknown_none_elf),
1674 ("riscv32ima-unknown-none-elf", riscv32ima_unknown_none_elf),
1675 ("riscv32imc-unknown-none-elf", riscv32imc_unknown_none_elf),
1676 ("riscv32imc-esp-espidf", riscv32imc_esp_espidf),
1677 ("riscv32imac-esp-espidf", riscv32imac_esp_espidf),
1678 ("riscv32imafc-esp-espidf", riscv32imafc_esp_espidf),
1679
1680 ("riscv32e-unknown-none-elf", riscv32e_unknown_none_elf),
1681 ("riscv32em-unknown-none-elf", riscv32em_unknown_none_elf),
1682 ("riscv32emc-unknown-none-elf", riscv32emc_unknown_none_elf),
1683
1684 ("riscv32imac-unknown-none-elf", riscv32imac_unknown_none_elf),
1685 ("riscv32imafc-unknown-none-elf", riscv32imafc_unknown_none_elf),
1686 ("riscv32imac-unknown-xous-elf", riscv32imac_unknown_xous_elf),
1687 ("riscv32gc-unknown-linux-gnu", riscv32gc_unknown_linux_gnu),
1688 ("riscv32gc-unknown-linux-musl", riscv32gc_unknown_linux_musl),
1689 ("riscv64imac-unknown-none-elf", riscv64imac_unknown_none_elf),
1690 ("riscv64gc-unknown-none-elf", riscv64gc_unknown_none_elf),
1691 ("riscv64gc-unknown-linux-gnu", riscv64gc_unknown_linux_gnu),
1692 ("riscv64gc-unknown-linux-musl", riscv64gc_unknown_linux_musl),
1693 ("riscv64a23-unknown-linux-gnu", riscv64a23_unknown_linux_gnu),
1694
1695 ("sparc-unknown-none-elf", sparc_unknown_none_elf),
1696
1697 ("loongarch32-unknown-none", loongarch32_unknown_none),
1698 ("loongarch32-unknown-none-softfloat", loongarch32_unknown_none_softfloat),
1699 ("loongarch64-unknown-none", loongarch64_unknown_none),
1700 ("loongarch64-unknown-none-softfloat", loongarch64_unknown_none_softfloat),
1701
1702 ("aarch64-unknown-none", aarch64_unknown_none),
1703 ("aarch64-unknown-none-softfloat", aarch64_unknown_none_softfloat),
1704 ("aarch64_be-unknown-none-softfloat", aarch64_be_unknown_none_softfloat),
1705 ("aarch64-unknown-nuttx", aarch64_unknown_nuttx),
1706
1707 ("x86_64-fortanix-unknown-sgx", x86_64_fortanix_unknown_sgx),
1708
1709 ("x86_64-unknown-uefi", x86_64_unknown_uefi),
1710 ("i686-unknown-uefi", i686_unknown_uefi),
1711 ("aarch64-unknown-uefi", aarch64_unknown_uefi),
1712
1713 ("nvptx64-nvidia-cuda", nvptx64_nvidia_cuda),
1714
1715 ("amdgcn-amd-amdhsa", amdgcn_amd_amdhsa),
1716
1717 ("xtensa-esp32-none-elf", xtensa_esp32_none_elf),
1718 ("xtensa-esp32-espidf", xtensa_esp32_espidf),
1719 ("xtensa-esp32s2-none-elf", xtensa_esp32s2_none_elf),
1720 ("xtensa-esp32s2-espidf", xtensa_esp32s2_espidf),
1721 ("xtensa-esp32s3-none-elf", xtensa_esp32s3_none_elf),
1722 ("xtensa-esp32s3-espidf", xtensa_esp32s3_espidf),
1723
1724 ("i686-wrs-vxworks", i686_wrs_vxworks),
1725 ("x86_64-wrs-vxworks", x86_64_wrs_vxworks),
1726 ("armv7-wrs-vxworks-eabihf", armv7_wrs_vxworks_eabihf),
1727 ("aarch64-wrs-vxworks", aarch64_wrs_vxworks),
1728 ("powerpc-wrs-vxworks", powerpc_wrs_vxworks),
1729 ("powerpc-wrs-vxworks-spe", powerpc_wrs_vxworks_spe),
1730 ("powerpc64-wrs-vxworks", powerpc64_wrs_vxworks),
1731 ("riscv32-wrs-vxworks", riscv32_wrs_vxworks),
1732 ("riscv64-wrs-vxworks", riscv64_wrs_vxworks),
1733
1734 ("aarch64-kmc-solid_asp3", aarch64_kmc_solid_asp3),
1735 ("armv7a-kmc-solid_asp3-eabi", armv7a_kmc_solid_asp3_eabi),
1736 ("armv7a-kmc-solid_asp3-eabihf", armv7a_kmc_solid_asp3_eabihf),
1737
1738 ("mipsel-sony-psp", mipsel_sony_psp),
1739 ("mipsel-sony-psx", mipsel_sony_psx),
1740 ("mipsel-unknown-none", mipsel_unknown_none),
1741 ("mips-mti-none-elf", mips_mti_none_elf),
1742 ("mipsel-mti-none-elf", mipsel_mti_none_elf),
1743 ("thumbv4t-none-eabi", thumbv4t_none_eabi),
1744 ("armv4t-none-eabi", armv4t_none_eabi),
1745 ("thumbv5te-none-eabi", thumbv5te_none_eabi),
1746 ("armv5te-none-eabi", armv5te_none_eabi),
1747
1748 ("aarch64_be-unknown-linux-gnu", aarch64_be_unknown_linux_gnu),
1749 ("aarch64-unknown-linux-gnu_ilp32", aarch64_unknown_linux_gnu_ilp32),
1750 ("aarch64_be-unknown-linux-gnu_ilp32", aarch64_be_unknown_linux_gnu_ilp32),
1751
1752 ("bpfeb-unknown-none", bpfeb_unknown_none),
1753 ("bpfel-unknown-none", bpfel_unknown_none),
1754
1755 ("armv6k-nintendo-3ds", armv6k_nintendo_3ds),
1756
1757 ("aarch64-nintendo-switch-freestanding", aarch64_nintendo_switch_freestanding),
1758
1759 ("armv7-sony-vita-newlibeabihf", armv7_sony_vita_newlibeabihf),
1760
1761 ("armv7-unknown-linux-uclibceabi", armv7_unknown_linux_uclibceabi),
1762 ("armv7-unknown-linux-uclibceabihf", armv7_unknown_linux_uclibceabihf),
1763
1764 ("x86_64-unknown-none", x86_64_unknown_none),
1765
1766 ("aarch64-unknown-teeos", aarch64_unknown_teeos),
1767
1768 ("mips64-openwrt-linux-musl", mips64_openwrt_linux_musl),
1769
1770 ("aarch64-unknown-nto-qnx700", aarch64_unknown_nto_qnx700),
1771 ("aarch64-unknown-nto-qnx710", aarch64_unknown_nto_qnx710),
1772 ("aarch64-unknown-nto-qnx710_iosock", aarch64_unknown_nto_qnx710_iosock),
1773 ("aarch64-unknown-nto-qnx800", aarch64_unknown_nto_qnx800),
1774 ("x86_64-pc-nto-qnx710", x86_64_pc_nto_qnx710),
1775 ("x86_64-pc-nto-qnx710_iosock", x86_64_pc_nto_qnx710_iosock),
1776 ("x86_64-pc-nto-qnx800", x86_64_pc_nto_qnx800),
1777 ("i686-pc-nto-qnx700", i686_pc_nto_qnx700),
1778
1779 ("aarch64-unknown-linux-ohos", aarch64_unknown_linux_ohos),
1780 ("armv7-unknown-linux-ohos", armv7_unknown_linux_ohos),
1781 ("loongarch64-unknown-linux-ohos", loongarch64_unknown_linux_ohos),
1782 ("x86_64-unknown-linux-ohos", x86_64_unknown_linux_ohos),
1783
1784 ("x86_64-unknown-linux-none", x86_64_unknown_linux_none),
1785
1786 ("thumbv6m-nuttx-eabi", thumbv6m_nuttx_eabi),
1787 ("thumbv7a-nuttx-eabi", thumbv7a_nuttx_eabi),
1788 ("thumbv7a-nuttx-eabihf", thumbv7a_nuttx_eabihf),
1789 ("thumbv7m-nuttx-eabi", thumbv7m_nuttx_eabi),
1790 ("thumbv7em-nuttx-eabi", thumbv7em_nuttx_eabi),
1791 ("thumbv7em-nuttx-eabihf", thumbv7em_nuttx_eabihf),
1792 ("thumbv8m.base-nuttx-eabi", thumbv8m_base_nuttx_eabi),
1793 ("thumbv8m.main-nuttx-eabi", thumbv8m_main_nuttx_eabi),
1794 ("thumbv8m.main-nuttx-eabihf", thumbv8m_main_nuttx_eabihf),
1795 ("riscv32imc-unknown-nuttx-elf", riscv32imc_unknown_nuttx_elf),
1796 ("riscv32imac-unknown-nuttx-elf", riscv32imac_unknown_nuttx_elf),
1797 ("riscv32imafc-unknown-nuttx-elf", riscv32imafc_unknown_nuttx_elf),
1798 ("riscv64imac-unknown-nuttx-elf", riscv64imac_unknown_nuttx_elf),
1799 ("riscv64gc-unknown-nuttx-elf", riscv64gc_unknown_nuttx_elf),
1800 ("x86_64-lynx-lynxos178", x86_64_lynx_lynxos178),
1801
1802 ("x86_64-pc-cygwin", x86_64_pc_cygwin),
1803}
1804
1805macro_rules! cvs {
1807 () => {
1808 ::std::borrow::Cow::Borrowed(&[])
1809 };
1810 ($($x:expr),+ $(,)?) => {
1811 ::std::borrow::Cow::Borrowed(&[
1812 $(
1813 ::std::borrow::Cow::Borrowed($x),
1814 )*
1815 ])
1816 };
1817}
1818
1819pub(crate) use cvs;
1820
1821#[derive(Debug, PartialEq)]
1825pub struct TargetWarnings {
1826 unused_fields: Vec<String>,
1827}
1828
1829impl TargetWarnings {
1830 pub fn empty() -> Self {
1831 Self { unused_fields: Vec::new() }
1832 }
1833
1834 pub fn warning_messages(&self) -> Vec<String> {
1835 let mut warnings = vec![];
1836 if !self.unused_fields.is_empty() {
1837 warnings.push(format!(
1838 "target json file contains unused fields: {}",
1839 self.unused_fields.join(", ")
1840 ));
1841 }
1842 warnings
1843 }
1844}
1845
1846#[derive(Copy, Clone, Debug, PartialEq)]
1849enum TargetKind {
1850 Json,
1851 Builtin,
1852}
1853
1854crate::target_spec_enum! {
1855 pub enum Arch {
1856 AArch64 = "aarch64",
1857 AmdGpu = "amdgpu",
1858 Arm = "arm",
1859 Arm64EC = "arm64ec",
1860 Avr = "avr",
1861 Bpf = "bpf",
1862 CSky = "csky",
1863 Hexagon = "hexagon",
1864 LoongArch32 = "loongarch32",
1865 LoongArch64 = "loongarch64",
1866 M68k = "m68k",
1867 Mips = "mips",
1868 Mips32r6 = "mips32r6",
1869 Mips64 = "mips64",
1870 Mips64r6 = "mips64r6",
1871 Msp430 = "msp430",
1872 Nvptx64 = "nvptx64",
1873 PowerPC = "powerpc",
1874 PowerPC64 = "powerpc64",
1875 PowerPC64LE = "powerpc64le",
1876 RiscV32 = "riscv32",
1877 RiscV64 = "riscv64",
1878 S390x = "s390x",
1879 Sparc = "sparc",
1880 Sparc64 = "sparc64",
1881 SpirV = "spirv",
1882 Wasm32 = "wasm32",
1883 Wasm64 = "wasm64",
1884 X86 = "x86",
1885 X86_64 = "x86_64",
1886 Xtensa = "xtensa",
1887 }
1888 other_variant = Other;
1889}
1890
1891impl Arch {
1892 pub fn desc_symbol(&self) -> Symbol {
1893 match self {
1894 Self::AArch64 => sym::aarch64,
1895 Self::AmdGpu => sym::amdgpu,
1896 Self::Arm => sym::arm,
1897 Self::Arm64EC => sym::arm64ec,
1898 Self::Avr => sym::avr,
1899 Self::Bpf => sym::bpf,
1900 Self::CSky => sym::csky,
1901 Self::Hexagon => sym::hexagon,
1902 Self::LoongArch32 => sym::loongarch32,
1903 Self::LoongArch64 => sym::loongarch64,
1904 Self::M68k => sym::m68k,
1905 Self::Mips => sym::mips,
1906 Self::Mips32r6 => sym::mips32r6,
1907 Self::Mips64 => sym::mips64,
1908 Self::Mips64r6 => sym::mips64r6,
1909 Self::Msp430 => sym::msp430,
1910 Self::Nvptx64 => sym::nvptx64,
1911 Self::PowerPC => sym::powerpc,
1912 Self::PowerPC64 => sym::powerpc64,
1913 Self::PowerPC64LE => sym::powerpc64le,
1914 Self::RiscV32 => sym::riscv32,
1915 Self::RiscV64 => sym::riscv64,
1916 Self::S390x => sym::s390x,
1917 Self::Sparc => sym::sparc,
1918 Self::Sparc64 => sym::sparc64,
1919 Self::SpirV => sym::spirv,
1920 Self::Wasm32 => sym::wasm32,
1921 Self::Wasm64 => sym::wasm64,
1922 Self::X86 => sym::x86,
1923 Self::X86_64 => sym::x86_64,
1924 Self::Xtensa => sym::xtensa,
1925 Self::Other(name) => rustc_span::Symbol::intern(name),
1926 }
1927 }
1928}
1929
1930crate::target_spec_enum! {
1931 pub enum Os {
1932 Aix = "aix",
1933 AmdHsa = "amdhsa",
1934 Android = "android",
1935 Cuda = "cuda",
1936 Cygwin = "cygwin",
1937 Dragonfly = "dragonfly",
1938 Emscripten = "emscripten",
1939 EspIdf = "espidf",
1940 FreeBsd = "freebsd",
1941 Fuchsia = "fuchsia",
1942 Haiku = "haiku",
1943 HelenOs = "helenos",
1944 Hermit = "hermit",
1945 Horizon = "horizon",
1946 Hurd = "hurd",
1947 Illumos = "illumos",
1948 IOs = "ios",
1949 L4Re = "l4re",
1950 Linux = "linux",
1951 LynxOs178 = "lynxos178",
1952 MacOs = "macos",
1953 Managarm = "managarm",
1954 Motor = "motor",
1955 NetBsd = "netbsd",
1956 None = "none",
1957 Nto = "nto",
1958 NuttX = "nuttx",
1959 OpenBsd = "openbsd",
1960 Psp = "psp",
1961 Psx = "psx",
1962 Qurt = "qurt",
1963 Redox = "redox",
1964 Rtems = "rtems",
1965 Solaris = "solaris",
1966 SolidAsp3 = "solid_asp3",
1967 TeeOs = "teeos",
1968 Trusty = "trusty",
1969 TvOs = "tvos",
1970 Uefi = "uefi",
1971 VexOs = "vexos",
1972 VisionOs = "visionos",
1973 Vita = "vita",
1974 VxWorks = "vxworks",
1975 Wasi = "wasi",
1976 WatchOs = "watchos",
1977 Windows = "windows",
1978 Xous = "xous",
1979 Zkvm = "zkvm",
1980 Unknown = "unknown",
1981 }
1982 other_variant = Other;
1983}
1984
1985impl Os {
1986 pub fn desc_symbol(&self) -> Symbol {
1987 Symbol::intern(self.desc())
1988 }
1989}
1990
1991crate::target_spec_enum! {
1992 pub enum Env {
1993 Gnu = "gnu",
1994 MacAbi = "macabi",
1995 Mlibc = "mlibc",
1996 Msvc = "msvc",
1997 Musl = "musl",
1998 Newlib = "newlib",
1999 Nto70 = "nto70",
2000 Nto71 = "nto71",
2001 Nto71IoSock = "nto71_iosock",
2002 Nto80 = "nto80",
2003 Ohos = "ohos",
2004 Relibc = "relibc",
2005 Sgx = "sgx",
2006 Sim = "sim",
2007 P1 = "p1",
2008 P2 = "p2",
2009 P3 = "p3",
2010 Uclibc = "uclibc",
2011 V5 = "v5",
2012 Unspecified = "",
2013 }
2014 other_variant = Other;
2015}
2016
2017impl Env {
2018 pub fn desc_symbol(&self) -> Symbol {
2019 Symbol::intern(self.desc())
2020 }
2021}
2022
2023crate::target_spec_enum! {
2024 pub enum Abi {
2025 Abi64 = "abi64",
2026 AbiV2 = "abiv2",
2027 AbiV2Hf = "abiv2hf",
2028 Eabi = "eabi",
2029 EabiHf = "eabihf",
2030 ElfV1 = "elfv1",
2031 ElfV2 = "elfv2",
2032 Fortanix = "fortanix",
2033 Ilp32 = "ilp32",
2034 Ilp32e = "ilp32e",
2035 Llvm = "llvm",
2036 MacAbi = "macabi",
2037 Sim = "sim",
2038 SoftFloat = "softfloat",
2039 Spe = "spe",
2040 Uwp = "uwp",
2041 VecDefault = "vec-default",
2042 VecExtAbi = "vec-extabi",
2043 X32 = "x32",
2044 Unspecified = "",
2045 }
2046 other_variant = Other;
2047}
2048
2049impl Abi {
2050 pub fn desc_symbol(&self) -> Symbol {
2051 Symbol::intern(self.desc())
2052 }
2053}
2054
2055#[derive(PartialEq, Clone, Debug)]
2059pub struct Target {
2060 pub llvm_target: StaticCow<str>,
2067 pub metadata: TargetMetadata,
2070 pub pointer_width: u16,
2072 pub arch: Arch,
2075 pub data_layout: StaticCow<str>,
2077 pub options: TargetOptions,
2079}
2080
2081#[derive(Default, PartialEq, Clone, Debug)]
2085pub struct TargetMetadata {
2086 pub description: Option<StaticCow<str>>,
2089 pub tier: Option<u64>,
2091 pub host_tools: Option<bool>,
2093 pub std: Option<bool>,
2096}
2097
2098impl Target {
2099 pub fn parse_data_layout(&self) -> Result<TargetDataLayout, TargetDataLayoutErrors<'_>> {
2100 let mut dl = TargetDataLayout::parse_from_llvm_datalayout_string(
2101 &self.data_layout,
2102 self.options.default_address_space,
2103 )?;
2104
2105 if dl.endian != self.endian {
2107 return Err(TargetDataLayoutErrors::InconsistentTargetArchitecture {
2108 dl: dl.endian.as_str(),
2109 target: self.endian.as_str(),
2110 });
2111 }
2112
2113 let target_pointer_width: u64 = self.pointer_width.into();
2114 let dl_pointer_size: u64 = dl.pointer_size().bits();
2115 if dl_pointer_size != target_pointer_width {
2116 return Err(TargetDataLayoutErrors::InconsistentTargetPointerWidth {
2117 pointer_size: dl_pointer_size,
2118 target: self.pointer_width,
2119 });
2120 }
2121
2122 dl.c_enum_min_size = Integer::from_size(Size::from_bits(
2123 self.c_enum_min_bits.unwrap_or(self.c_int_width as _),
2124 ))
2125 .map_err(|err| TargetDataLayoutErrors::InvalidBitsSize { err })?;
2126
2127 Ok(dl)
2128 }
2129}
2130
2131pub trait HasTargetSpec {
2132 fn target_spec(&self) -> &Target;
2133}
2134
2135impl HasTargetSpec for Target {
2136 #[inline]
2137 fn target_spec(&self) -> &Target {
2138 self
2139 }
2140}
2141
2142#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
2144pub struct X86Abi {
2145 pub regparm: Option<u32>,
2148 pub reg_struct_return: bool,
2150}
2151
2152pub trait HasX86AbiOpt {
2153 fn x86_abi_opt(&self) -> X86Abi;
2154}
2155
2156type StaticCow<T> = Cow<'static, T>;
2157
2158#[derive(PartialEq, Clone, Debug)]
2167#[rustc_lint_opt_ty]
2168pub struct TargetOptions {
2169 pub endian: Endian,
2171 pub c_int_width: u16,
2173 pub os: Os,
2178 pub env: Env,
2180 pub abi: Abi,
2185 #[rustc_lint_opt_deny_field_access(
2187 "use `Target::is_like_*` instead of this field; see https://github.com/rust-lang/rust/issues/100343 for rationale"
2188 )]
2189 vendor: StaticCow<str>,
2190
2191 pub linker: Option<StaticCow<str>>,
2193 pub linker_flavor: LinkerFlavor,
2196 linker_flavor_json: LinkerFlavorCli,
2197 lld_flavor_json: LldFlavor,
2198 linker_is_gnu_json: bool,
2199
2200 pub pre_link_objects: CrtObjects,
2202 pub post_link_objects: CrtObjects,
2203 pub pre_link_objects_self_contained: CrtObjects,
2205 pub post_link_objects_self_contained: CrtObjects,
2206 pub link_self_contained: LinkSelfContainedDefault,
2209
2210 pub pre_link_args: LinkArgs,
2212 pre_link_args_json: LinkArgsCli,
2213 pub late_link_args: LinkArgs,
2217 late_link_args_json: LinkArgsCli,
2218 pub late_link_args_dynamic: LinkArgs,
2221 late_link_args_dynamic_json: LinkArgsCli,
2222 pub late_link_args_static: LinkArgs,
2225 late_link_args_static_json: LinkArgsCli,
2226 pub post_link_args: LinkArgs,
2229 post_link_args_json: LinkArgsCli,
2230
2231 pub link_script: Option<StaticCow<str>>,
2235 pub link_env: StaticCow<[(StaticCow<str>, StaticCow<str>)]>,
2237 pub link_env_remove: StaticCow<[StaticCow<str>]>,
2239
2240 pub asm_args: StaticCow<[StaticCow<str>]>,
2242
2243 pub cpu: StaticCow<str>,
2246 pub need_explicit_cpu: bool,
2249 pub features: StaticCow<str>,
2258 pub direct_access_external_data: Option<bool>,
2260 pub dynamic_linking: bool,
2262 pub dll_tls_export: bool,
2264 pub only_cdylib: bool,
2266 pub executables: bool,
2268 pub relocation_model: RelocModel,
2271 pub code_model: Option<CodeModel>,
2274 pub tls_model: TlsModel,
2277 pub disable_redzone: bool,
2279 pub frame_pointer: FramePointer,
2281 pub function_sections: bool,
2283 pub dll_prefix: StaticCow<str>,
2285 pub dll_suffix: StaticCow<str>,
2287 pub exe_suffix: StaticCow<str>,
2289 pub staticlib_prefix: StaticCow<str>,
2291 pub staticlib_suffix: StaticCow<str>,
2293 pub families: StaticCow<[StaticCow<str>]>,
2299 pub abi_return_struct_as_int: bool,
2301 pub is_like_aix: bool,
2304 pub is_like_darwin: bool,
2309 pub is_like_gpu: bool,
2311 pub is_like_solaris: bool,
2315 pub is_like_windows: bool,
2323 pub is_like_msvc: bool,
2333 pub is_like_wasm: bool,
2335 pub is_like_android: bool,
2337 pub is_like_vexos: bool,
2339 pub binary_format: BinaryFormat,
2341 pub default_dwarf_version: u32,
2344 pub allows_weak_linkage: bool,
2351 pub has_rpath: bool,
2353 pub no_default_libraries: bool,
2356 pub position_independent_executables: bool,
2362 pub static_position_independent_executables: bool,
2364 pub plt_by_default: bool,
2367 pub relro_level: RelroLevel,
2371 pub archive_format: StaticCow<str>,
2376 pub allow_asm: bool,
2378 pub main_needs_argc_argv: bool,
2381
2382 pub has_thread_local: bool,
2384 pub obj_is_bitcode: bool,
2388
2389 pub min_atomic_width: Option<u64>,
2391
2392 pub max_atomic_width: Option<u64>,
2394
2395 pub atomic_cas: bool,
2397
2398 pub panic_strategy: PanicStrategy,
2400
2401 pub crt_static_allows_dylibs: bool,
2403 pub crt_static_default: bool,
2405 pub crt_static_respected: bool,
2407
2408 pub stack_probes: StackProbeType,
2410
2411 pub min_global_align: Option<Align>,
2413
2414 pub default_codegen_units: Option<u64>,
2416
2417 pub default_codegen_backend: Option<StaticCow<str>>,
2427
2428 pub trap_unreachable: bool,
2431
2432 pub requires_lto: bool,
2435
2436 pub singlethread: bool,
2438
2439 pub no_builtins: bool,
2442
2443 pub default_visibility: Option<SymbolVisibility>,
2449
2450 pub emit_debug_gdb_scripts: bool,
2452
2453 pub requires_uwtable: bool,
2457
2458 pub default_uwtable: bool,
2461
2462 pub simd_types_indirect: bool,
2467
2468 pub limit_rdylib_exports: bool,
2470
2471 pub override_export_symbols: Option<StaticCow<[StaticCow<str>]>>,
2474
2475 pub merge_functions: MergeFunctions,
2482
2483 pub mcount: StaticCow<str>,
2485
2486 pub llvm_mcount_intrinsic: Option<StaticCow<str>>,
2488
2489 pub llvm_abiname: StaticCow<str>,
2492
2493 pub llvm_floatabi: Option<FloatAbi>,
2500
2501 pub rustc_abi: Option<RustcAbi>,
2506
2507 pub relax_elf_relocations: bool,
2509
2510 pub llvm_args: StaticCow<[StaticCow<str>]>,
2512
2513 pub use_ctors_section: bool,
2516
2517 pub eh_frame_header: bool,
2521
2522 pub has_thumb_interworking: bool,
2525
2526 pub debuginfo_kind: DebuginfoKind,
2528 pub split_debuginfo: SplitDebuginfo,
2531 pub supported_split_debuginfo: StaticCow<[SplitDebuginfo]>,
2533
2534 pub supported_sanitizers: SanitizerSet,
2540
2541 pub default_sanitizers: SanitizerSet,
2547
2548 pub c_enum_min_bits: Option<u64>,
2550
2551 pub generate_arange_section: bool,
2553
2554 pub supports_stack_protector: bool,
2557
2558 pub entry_name: StaticCow<str>,
2561
2562 pub entry_abi: CanonAbi,
2565
2566 pub supports_xray: bool,
2568
2569 pub default_address_space: rustc_abi::AddressSpace,
2573
2574 small_data_threshold_support: SmallDataThresholdSupport,
2576}
2577
2578fn add_link_args_iter(
2581 link_args: &mut LinkArgs,
2582 flavor: LinkerFlavor,
2583 args: impl Iterator<Item = StaticCow<str>> + Clone,
2584) {
2585 let mut insert = |flavor| link_args.entry(flavor).or_default().extend(args.clone());
2586 insert(flavor);
2587 match flavor {
2588 LinkerFlavor::Gnu(cc, lld) => {
2589 assert_eq!(lld, Lld::No);
2590 insert(LinkerFlavor::Gnu(cc, Lld::Yes));
2591 }
2592 LinkerFlavor::Darwin(cc, lld) => {
2593 assert_eq!(lld, Lld::No);
2594 insert(LinkerFlavor::Darwin(cc, Lld::Yes));
2595 }
2596 LinkerFlavor::Msvc(lld) => {
2597 assert_eq!(lld, Lld::No);
2598 insert(LinkerFlavor::Msvc(Lld::Yes));
2599 }
2600 LinkerFlavor::WasmLld(..)
2601 | LinkerFlavor::Unix(..)
2602 | LinkerFlavor::EmCc
2603 | LinkerFlavor::Bpf
2604 | LinkerFlavor::Llbc
2605 | LinkerFlavor::Ptx => {}
2606 }
2607}
2608
2609fn add_link_args(link_args: &mut LinkArgs, flavor: LinkerFlavor, args: &[&'static str]) {
2610 add_link_args_iter(link_args, flavor, args.iter().copied().map(Cow::Borrowed))
2611}
2612
2613impl TargetOptions {
2614 pub fn supports_comdat(&self) -> bool {
2615 !self.is_like_aix && !self.is_like_darwin
2617 }
2618}
2619
2620impl TargetOptions {
2621 fn link_args(flavor: LinkerFlavor, args: &[&'static str]) -> LinkArgs {
2622 let mut link_args = LinkArgs::new();
2623 add_link_args(&mut link_args, flavor, args);
2624 link_args
2625 }
2626
2627 fn add_pre_link_args(&mut self, flavor: LinkerFlavor, args: &[&'static str]) {
2628 add_link_args(&mut self.pre_link_args, flavor, args);
2629 }
2630
2631 fn update_from_cli(&mut self) {
2632 self.linker_flavor = LinkerFlavor::from_cli_json(
2633 self.linker_flavor_json,
2634 self.lld_flavor_json,
2635 self.linker_is_gnu_json,
2636 );
2637 for (args, args_json) in [
2638 (&mut self.pre_link_args, &self.pre_link_args_json),
2639 (&mut self.late_link_args, &self.late_link_args_json),
2640 (&mut self.late_link_args_dynamic, &self.late_link_args_dynamic_json),
2641 (&mut self.late_link_args_static, &self.late_link_args_static_json),
2642 (&mut self.post_link_args, &self.post_link_args_json),
2643 ] {
2644 args.clear();
2645 for (flavor, args_json) in args_json {
2646 let linker_flavor = self.linker_flavor.with_cli_hints(*flavor);
2647 let linker_flavor = match linker_flavor {
2649 LinkerFlavor::Gnu(cc, _) => LinkerFlavor::Gnu(cc, Lld::No),
2650 LinkerFlavor::Darwin(cc, _) => LinkerFlavor::Darwin(cc, Lld::No),
2651 LinkerFlavor::Msvc(_) => LinkerFlavor::Msvc(Lld::No),
2652 _ => linker_flavor,
2653 };
2654 if !args.contains_key(&linker_flavor) {
2655 add_link_args_iter(args, linker_flavor, args_json.iter().cloned());
2656 }
2657 }
2658 }
2659 }
2660
2661 fn update_to_cli(&mut self) {
2662 self.linker_flavor_json = self.linker_flavor.to_cli_counterpart();
2663 self.lld_flavor_json = self.linker_flavor.lld_flavor();
2664 self.linker_is_gnu_json = self.linker_flavor.is_gnu();
2665 for (args, args_json) in [
2666 (&self.pre_link_args, &mut self.pre_link_args_json),
2667 (&self.late_link_args, &mut self.late_link_args_json),
2668 (&self.late_link_args_dynamic, &mut self.late_link_args_dynamic_json),
2669 (&self.late_link_args_static, &mut self.late_link_args_static_json),
2670 (&self.post_link_args, &mut self.post_link_args_json),
2671 ] {
2672 *args_json = args
2673 .iter()
2674 .map(|(flavor, args)| (flavor.to_cli_counterpart(), args.clone()))
2675 .collect();
2676 }
2677 }
2678}
2679
2680impl Default for TargetOptions {
2681 fn default() -> TargetOptions {
2684 TargetOptions {
2685 endian: Endian::Little,
2686 c_int_width: 32,
2687 os: Os::None,
2688 env: Env::Unspecified,
2689 abi: Abi::Unspecified,
2690 vendor: "unknown".into(),
2691 linker: option_env!("CFG_DEFAULT_LINKER").map(|s| s.into()),
2692 linker_flavor: LinkerFlavor::Gnu(Cc::Yes, Lld::No),
2693 linker_flavor_json: LinkerFlavorCli::Gcc,
2694 lld_flavor_json: LldFlavor::Ld,
2695 linker_is_gnu_json: true,
2696 link_script: None,
2697 asm_args: cvs![],
2698 cpu: "generic".into(),
2699 need_explicit_cpu: false,
2700 features: "".into(),
2701 direct_access_external_data: None,
2702 dynamic_linking: false,
2703 dll_tls_export: true,
2704 only_cdylib: false,
2705 executables: true,
2706 relocation_model: RelocModel::Pic,
2707 code_model: None,
2708 tls_model: TlsModel::GeneralDynamic,
2709 disable_redzone: false,
2710 frame_pointer: FramePointer::MayOmit,
2711 function_sections: true,
2712 dll_prefix: "lib".into(),
2713 dll_suffix: ".so".into(),
2714 exe_suffix: "".into(),
2715 staticlib_prefix: "lib".into(),
2716 staticlib_suffix: ".a".into(),
2717 families: cvs![],
2718 abi_return_struct_as_int: false,
2719 is_like_aix: false,
2720 is_like_darwin: false,
2721 is_like_gpu: false,
2722 is_like_solaris: false,
2723 is_like_windows: false,
2724 is_like_msvc: false,
2725 is_like_wasm: false,
2726 is_like_android: false,
2727 is_like_vexos: false,
2728 binary_format: BinaryFormat::Elf,
2729 default_dwarf_version: 4,
2730 allows_weak_linkage: true,
2731 has_rpath: false,
2732 no_default_libraries: true,
2733 position_independent_executables: false,
2734 static_position_independent_executables: false,
2735 plt_by_default: true,
2736 relro_level: RelroLevel::None,
2737 pre_link_objects: Default::default(),
2738 post_link_objects: Default::default(),
2739 pre_link_objects_self_contained: Default::default(),
2740 post_link_objects_self_contained: Default::default(),
2741 link_self_contained: LinkSelfContainedDefault::False,
2742 pre_link_args: LinkArgs::new(),
2743 pre_link_args_json: LinkArgsCli::new(),
2744 late_link_args: LinkArgs::new(),
2745 late_link_args_json: LinkArgsCli::new(),
2746 late_link_args_dynamic: LinkArgs::new(),
2747 late_link_args_dynamic_json: LinkArgsCli::new(),
2748 late_link_args_static: LinkArgs::new(),
2749 late_link_args_static_json: LinkArgsCli::new(),
2750 post_link_args: LinkArgs::new(),
2751 post_link_args_json: LinkArgsCli::new(),
2752 link_env: cvs![],
2753 link_env_remove: cvs![],
2754 archive_format: "gnu".into(),
2755 main_needs_argc_argv: true,
2756 allow_asm: true,
2757 has_thread_local: false,
2758 obj_is_bitcode: false,
2759 min_atomic_width: None,
2760 max_atomic_width: None,
2761 atomic_cas: true,
2762 panic_strategy: PanicStrategy::Unwind,
2763 crt_static_allows_dylibs: false,
2764 crt_static_default: false,
2765 crt_static_respected: false,
2766 stack_probes: StackProbeType::None,
2767 min_global_align: None,
2768 default_codegen_units: None,
2769 default_codegen_backend: None,
2770 trap_unreachable: true,
2771 requires_lto: false,
2772 singlethread: false,
2773 no_builtins: false,
2774 default_visibility: None,
2775 emit_debug_gdb_scripts: true,
2776 requires_uwtable: false,
2777 default_uwtable: false,
2778 simd_types_indirect: true,
2779 limit_rdylib_exports: true,
2780 override_export_symbols: None,
2781 merge_functions: MergeFunctions::Aliases,
2782 mcount: "mcount".into(),
2783 llvm_mcount_intrinsic: None,
2784 llvm_abiname: "".into(),
2785 llvm_floatabi: None,
2786 rustc_abi: None,
2787 relax_elf_relocations: false,
2788 llvm_args: cvs![],
2789 use_ctors_section: false,
2790 eh_frame_header: true,
2791 has_thumb_interworking: false,
2792 debuginfo_kind: Default::default(),
2793 split_debuginfo: Default::default(),
2794 supported_split_debuginfo: Cow::Borrowed(&[SplitDebuginfo::Off]),
2796 supported_sanitizers: SanitizerSet::empty(),
2797 default_sanitizers: SanitizerSet::empty(),
2798 c_enum_min_bits: None,
2799 generate_arange_section: true,
2800 supports_stack_protector: true,
2801 entry_name: "main".into(),
2802 entry_abi: CanonAbi::C,
2803 supports_xray: false,
2804 default_address_space: rustc_abi::AddressSpace::ZERO,
2805 small_data_threshold_support: SmallDataThresholdSupport::DefaultForArch,
2806 }
2807 }
2808}
2809
2810impl Deref for Target {
2814 type Target = TargetOptions;
2815
2816 #[inline]
2817 fn deref(&self) -> &Self::Target {
2818 &self.options
2819 }
2820}
2821impl DerefMut for Target {
2822 #[inline]
2823 fn deref_mut(&mut self) -> &mut Self::Target {
2824 &mut self.options
2825 }
2826}
2827
2828impl Target {
2829 pub fn is_abi_supported(&self, abi: ExternAbi) -> bool {
2830 let abi_map = AbiMap::from_target(self);
2831 abi_map.canonize_abi(abi, false).is_mapped()
2832 }
2833
2834 pub fn min_atomic_width(&self) -> u64 {
2837 self.min_atomic_width.unwrap_or(8)
2838 }
2839
2840 pub fn max_atomic_width(&self) -> u64 {
2843 self.max_atomic_width.unwrap_or_else(|| self.pointer_width.into())
2844 }
2845
2846 fn check_consistency(&self, kind: TargetKind) -> Result<(), String> {
2849 macro_rules! check {
2850 ($b:expr, $($msg:tt)*) => {
2851 if !$b {
2852 return Err(format!($($msg)*));
2853 }
2854 }
2855 }
2856 macro_rules! check_eq {
2857 ($left:expr, $right:expr, $($msg:tt)*) => {
2858 if ($left) != ($right) {
2859 return Err(format!($($msg)*));
2860 }
2861 }
2862 }
2863 macro_rules! check_ne {
2864 ($left:expr, $right:expr, $($msg:tt)*) => {
2865 if ($left) == ($right) {
2866 return Err(format!($($msg)*));
2867 }
2868 }
2869 }
2870 macro_rules! check_matches {
2871 ($left:expr, $right:pat, $($msg:tt)*) => {
2872 if !matches!($left, $right) {
2873 return Err(format!($($msg)*));
2874 }
2875 }
2876 }
2877
2878 check_eq!(
2879 self.is_like_darwin,
2880 self.vendor == "apple",
2881 "`is_like_darwin` must be set if and only if `vendor` is `apple`"
2882 );
2883 check_eq!(
2884 self.is_like_solaris,
2885 matches!(self.os, Os::Solaris | Os::Illumos),
2886 "`is_like_solaris` must be set if and only if `os` is `solaris` or `illumos`"
2887 );
2888 check_eq!(
2889 self.is_like_gpu,
2890 self.arch == Arch::Nvptx64 || self.arch == Arch::AmdGpu,
2891 "`is_like_gpu` must be set if and only if `target` is `nvptx64` or `amdgcn`"
2892 );
2893 check_eq!(
2894 self.is_like_windows,
2895 matches!(self.os, Os::Windows | Os::Uefi | Os::Cygwin),
2896 "`is_like_windows` must be set if and only if `os` is `windows`, `uefi` or `cygwin`"
2897 );
2898 check_eq!(
2899 self.is_like_wasm,
2900 matches!(self.arch, Arch::Wasm32 | Arch::Wasm64),
2901 "`is_like_wasm` must be set if and only if `arch` is `wasm32` or `wasm64`"
2902 );
2903 if self.is_like_msvc {
2904 check!(self.is_like_windows, "if `is_like_msvc` is set, `is_like_windows` must be set");
2905 }
2906 if self.os == Os::Emscripten {
2907 check!(self.is_like_wasm, "the `emcscripten` os only makes sense on wasm-like targets");
2908 }
2909
2910 check_eq!(
2912 self.is_like_darwin,
2913 matches!(self.linker_flavor, LinkerFlavor::Darwin(..)),
2914 "`linker_flavor` must be `darwin` if and only if `is_like_darwin` is set"
2915 );
2916 check_eq!(
2917 self.is_like_msvc,
2918 matches!(self.linker_flavor, LinkerFlavor::Msvc(..)),
2919 "`linker_flavor` must be `msvc` if and only if `is_like_msvc` is set"
2920 );
2921 check_eq!(
2922 self.is_like_wasm && self.os != Os::Emscripten,
2923 matches!(self.linker_flavor, LinkerFlavor::WasmLld(..)),
2924 "`linker_flavor` must be `wasm-lld` if and only if `is_like_wasm` is set and the `os` is not `emscripten`",
2925 );
2926 check_eq!(
2927 self.os == Os::Emscripten,
2928 matches!(self.linker_flavor, LinkerFlavor::EmCc),
2929 "`linker_flavor` must be `em-cc` if and only if `os` is `emscripten`"
2930 );
2931 check_eq!(
2932 self.arch == Arch::Bpf,
2933 matches!(self.linker_flavor, LinkerFlavor::Bpf),
2934 "`linker_flavor` must be `bpf` if and only if `arch` is `bpf`"
2935 );
2936 check_eq!(
2937 self.arch == Arch::Nvptx64,
2938 matches!(self.linker_flavor, LinkerFlavor::Ptx),
2939 "`linker_flavor` must be `ptc` if and only if `arch` is `nvptx64`"
2940 );
2941
2942 for args in [
2943 &self.pre_link_args,
2944 &self.late_link_args,
2945 &self.late_link_args_dynamic,
2946 &self.late_link_args_static,
2947 &self.post_link_args,
2948 ] {
2949 for (&flavor, flavor_args) in args {
2950 check!(
2951 !flavor_args.is_empty() || self.arch == Arch::Avr,
2952 "linker flavor args must not be empty"
2953 );
2954 match self.linker_flavor {
2956 LinkerFlavor::Gnu(..) => {
2957 check_matches!(
2958 flavor,
2959 LinkerFlavor::Gnu(..),
2960 "mixing GNU and non-GNU linker flavors"
2961 );
2962 }
2963 LinkerFlavor::Darwin(..) => {
2964 check_matches!(
2965 flavor,
2966 LinkerFlavor::Darwin(..),
2967 "mixing Darwin and non-Darwin linker flavors"
2968 )
2969 }
2970 LinkerFlavor::WasmLld(..) => {
2971 check_matches!(
2972 flavor,
2973 LinkerFlavor::WasmLld(..),
2974 "mixing wasm and non-wasm linker flavors"
2975 )
2976 }
2977 LinkerFlavor::Unix(..) => {
2978 check_matches!(
2979 flavor,
2980 LinkerFlavor::Unix(..),
2981 "mixing unix and non-unix linker flavors"
2982 );
2983 }
2984 LinkerFlavor::Msvc(..) => {
2985 check_matches!(
2986 flavor,
2987 LinkerFlavor::Msvc(..),
2988 "mixing MSVC and non-MSVC linker flavors"
2989 );
2990 }
2991 LinkerFlavor::EmCc
2992 | LinkerFlavor::Bpf
2993 | LinkerFlavor::Ptx
2994 | LinkerFlavor::Llbc => {
2995 check_eq!(flavor, self.linker_flavor, "mixing different linker flavors")
2996 }
2997 }
2998
2999 let check_noncc = |noncc_flavor| -> Result<(), String> {
3001 if let Some(noncc_args) = args.get(&noncc_flavor) {
3002 for arg in flavor_args {
3003 if let Some(suffix) = arg.strip_prefix("-Wl,") {
3004 check!(
3005 noncc_args.iter().any(|a| a == suffix),
3006 " link args for cc and non-cc versions of flavors are not consistent"
3007 );
3008 }
3009 }
3010 }
3011 Ok(())
3012 };
3013
3014 match self.linker_flavor {
3015 LinkerFlavor::Gnu(Cc::Yes, lld) => check_noncc(LinkerFlavor::Gnu(Cc::No, lld))?,
3016 LinkerFlavor::WasmLld(Cc::Yes) => check_noncc(LinkerFlavor::WasmLld(Cc::No))?,
3017 LinkerFlavor::Unix(Cc::Yes) => check_noncc(LinkerFlavor::Unix(Cc::No))?,
3018 _ => {}
3019 }
3020 }
3021
3022 for cc in [Cc::No, Cc::Yes] {
3024 check_eq!(
3025 args.get(&LinkerFlavor::Gnu(cc, Lld::No)),
3026 args.get(&LinkerFlavor::Gnu(cc, Lld::Yes)),
3027 "link args for lld and non-lld versions of flavors are not consistent",
3028 );
3029 check_eq!(
3030 args.get(&LinkerFlavor::Darwin(cc, Lld::No)),
3031 args.get(&LinkerFlavor::Darwin(cc, Lld::Yes)),
3032 "link args for lld and non-lld versions of flavors are not consistent",
3033 );
3034 }
3035 check_eq!(
3036 args.get(&LinkerFlavor::Msvc(Lld::No)),
3037 args.get(&LinkerFlavor::Msvc(Lld::Yes)),
3038 "link args for lld and non-lld versions of flavors are not consistent",
3039 );
3040 }
3041
3042 if self.link_self_contained.is_disabled() {
3043 check!(
3044 self.pre_link_objects_self_contained.is_empty()
3045 && self.post_link_objects_self_contained.is_empty(),
3046 "if `link_self_contained` is disabled, then `pre_link_objects_self_contained` and `post_link_objects_self_contained` must be empty",
3047 );
3048 }
3049
3050 check_ne!(self.vendor, "", "`vendor` cannot be empty");
3054 if let Os::Other(s) = &self.os {
3055 check!(!s.is_empty(), "`os` cannot be empty");
3056 }
3057 if !self.can_use_os_unknown() {
3058 check_ne!(
3060 self.os,
3061 Os::Unknown,
3062 "`unknown` os can only be used on particular targets; use `none` for bare-metal targets"
3063 );
3064 }
3065
3066 if kind == TargetKind::Builtin {
3072 if self.os == Os::None
3076 && !matches!(self.arch, Arch::Bpf | Arch::Hexagon | Arch::Wasm32 | Arch::Wasm64)
3077 {
3078 check!(
3079 !self.dynamic_linking,
3080 "dynamic linking is not supported on this OS/architecture"
3081 );
3082 }
3083 if self.only_cdylib
3084 || self.crt_static_allows_dylibs
3085 || !self.late_link_args_dynamic.is_empty()
3086 {
3087 check!(
3088 self.dynamic_linking,
3089 "dynamic linking must be allowed when `only_cdylib` or `crt_static_allows_dylibs` or `late_link_args_dynamic` are set"
3090 );
3091 }
3092 if self.dynamic_linking && !self.is_like_wasm {
3094 check_eq!(
3095 self.relocation_model,
3096 RelocModel::Pic,
3097 "targets that support dynamic linking must use the `pic` relocation model"
3098 );
3099 }
3100 if self.position_independent_executables {
3101 check_eq!(
3102 self.relocation_model,
3103 RelocModel::Pic,
3104 "targets that support position-independent executables must use the `pic` relocation model"
3105 );
3106 }
3107 if self.relocation_model == RelocModel::Pic && self.os != Os::Uefi {
3109 check!(
3110 self.dynamic_linking || self.position_independent_executables,
3111 "when the relocation model is `pic`, the target must support dynamic linking or use position-independent executables. \
3112 Set the relocation model to `static` to avoid this requirement"
3113 );
3114 }
3115 if self.static_position_independent_executables {
3116 check!(
3117 self.position_independent_executables,
3118 "if `static_position_independent_executables` is set, then `position_independent_executables` must be set"
3119 );
3120 }
3121 if self.position_independent_executables {
3122 check!(
3123 self.executables,
3124 "if `position_independent_executables` is set then `executables` must be set"
3125 );
3126 }
3127 }
3128
3129 if self.crt_static_default || self.crt_static_allows_dylibs {
3131 check!(
3132 self.crt_static_respected,
3133 "static CRT can be enabled but `crt_static_respected` is not set"
3134 );
3135 }
3136
3137 match self.arch {
3140 Arch::RiscV32 => {
3141 check_matches!(
3142 &*self.llvm_abiname,
3143 "ilp32" | "ilp32f" | "ilp32d" | "ilp32e",
3144 "invalid RISC-V ABI name: {}",
3145 self.llvm_abiname,
3146 );
3147 }
3148 Arch::RiscV64 => {
3149 check_matches!(
3151 &*self.llvm_abiname,
3152 "lp64" | "lp64f" | "lp64d" | "lp64e",
3153 "invalid RISC-V ABI name: {}",
3154 self.llvm_abiname,
3155 );
3156 }
3157 Arch::Arm => {
3158 check!(
3159 self.llvm_floatabi.is_some(),
3160 "ARM targets must set `llvm-floatabi` to `hard` or `soft`",
3161 )
3162 }
3163 _ => {}
3164 }
3165
3166 if let Some(rust_abi) = self.rustc_abi {
3168 match rust_abi {
3169 RustcAbi::X86Sse2 => check_matches!(
3170 self.arch,
3171 Arch::X86,
3172 "`x86-sse2` ABI is only valid for x86-32 targets"
3173 ),
3174 RustcAbi::X86Softfloat => check_matches!(
3175 self.arch,
3176 Arch::X86 | Arch::X86_64,
3177 "`x86-softfloat` ABI is only valid for x86 targets"
3178 ),
3179 }
3180 }
3181
3182 if !self.features.is_empty() {
3184 let mut features_enabled = FxHashSet::default();
3185 let mut features_disabled = FxHashSet::default();
3186 for feat in self.features.split(',') {
3187 if let Some(feat) = feat.strip_prefix("+") {
3188 features_enabled.insert(feat);
3189 if features_disabled.contains(feat) {
3190 return Err(format!(
3191 "target feature `{feat}` is both enabled and disabled"
3192 ));
3193 }
3194 } else if let Some(feat) = feat.strip_prefix("-") {
3195 features_disabled.insert(feat);
3196 if features_enabled.contains(feat) {
3197 return Err(format!(
3198 "target feature `{feat}` is both enabled and disabled"
3199 ));
3200 }
3201 } else {
3202 return Err(format!(
3203 "target feature `{feat}` is invalid, must start with `+` or `-`"
3204 ));
3205 }
3206 }
3207 let abi_feature_constraints = self.abi_required_features();
3209 for feat in abi_feature_constraints.required {
3210 if features_disabled.contains(feat) {
3213 return Err(format!(
3214 "target feature `{feat}` is required by the ABI but gets disabled in target spec"
3215 ));
3216 }
3217 }
3218 for feat in abi_feature_constraints.incompatible {
3219 if features_enabled.contains(feat) {
3222 return Err(format!(
3223 "target feature `{feat}` is incompatible with the ABI but gets enabled in target spec"
3224 ));
3225 }
3226 }
3227 }
3228
3229 Ok(())
3230 }
3231
3232 #[cfg(test)]
3234 fn test_target(mut self) {
3235 let recycled_target =
3236 Target::from_json(&serde_json::to_string(&self.to_json()).unwrap()).map(|(j, _)| j);
3237 self.update_to_cli();
3238 self.check_consistency(TargetKind::Builtin).unwrap();
3239 assert_eq!(recycled_target, Ok(self));
3240 }
3241
3242 fn can_use_os_unknown(&self) -> bool {
3245 self.llvm_target == "wasm32-unknown-unknown"
3246 || self.llvm_target == "wasm64-unknown-unknown"
3247 || (self.env == Env::Sgx && self.vendor == "fortanix")
3248 }
3249
3250 pub fn expect_builtin(target_tuple: &TargetTuple) -> Target {
3252 match *target_tuple {
3253 TargetTuple::TargetTuple(ref target_tuple) => {
3254 load_builtin(target_tuple).expect("built-in target")
3255 }
3256 TargetTuple::TargetJson { .. } => {
3257 panic!("built-in targets doesn't support target-paths")
3258 }
3259 }
3260 }
3261
3262 pub fn builtins() -> impl Iterator<Item = Target> {
3264 load_all_builtins()
3265 }
3266
3267 pub fn search(
3277 target_tuple: &TargetTuple,
3278 sysroot: &Path,
3279 ) -> Result<(Target, TargetWarnings), String> {
3280 use std::{env, fs};
3281
3282 fn load_file(path: &Path) -> Result<(Target, TargetWarnings), String> {
3283 let contents = fs::read_to_string(path).map_err(|e| e.to_string())?;
3284 Target::from_json(&contents)
3285 }
3286
3287 match *target_tuple {
3288 TargetTuple::TargetTuple(ref target_tuple) => {
3289 if let Some(t) = load_builtin(target_tuple) {
3291 return Ok((t, TargetWarnings::empty()));
3292 }
3293
3294 let path = {
3296 let mut target = target_tuple.to_string();
3297 target.push_str(".json");
3298 PathBuf::from(target)
3299 };
3300
3301 let target_path = env::var_os("RUST_TARGET_PATH").unwrap_or_default();
3302
3303 for dir in env::split_paths(&target_path) {
3304 let p = dir.join(&path);
3305 if p.is_file() {
3306 return load_file(&p);
3307 }
3308 }
3309
3310 let rustlib_path = crate::relative_target_rustlib_path(sysroot, target_tuple);
3313 let p = PathBuf::from_iter([
3314 Path::new(sysroot),
3315 Path::new(&rustlib_path),
3316 Path::new("target.json"),
3317 ]);
3318 if p.is_file() {
3319 return load_file(&p);
3320 }
3321
3322 Err(format!("could not find specification for target {target_tuple:?}"))
3323 }
3324 TargetTuple::TargetJson { ref contents, .. } => Target::from_json(contents),
3325 }
3326 }
3327
3328 pub fn small_data_threshold_support(&self) -> SmallDataThresholdSupport {
3331 match &self.options.small_data_threshold_support {
3332 SmallDataThresholdSupport::DefaultForArch => match self.arch {
3336 Arch::Mips | Arch::Mips64 | Arch::Mips32r6 => {
3337 SmallDataThresholdSupport::LlvmArg("mips-ssection-threshold".into())
3338 }
3339 Arch::Hexagon => {
3340 SmallDataThresholdSupport::LlvmArg("hexagon-small-data-threshold".into())
3341 }
3342 Arch::M68k => SmallDataThresholdSupport::LlvmArg("m68k-ssection-threshold".into()),
3343 Arch::RiscV32 | Arch::RiscV64 => {
3344 SmallDataThresholdSupport::LlvmModuleFlag("SmallDataLimit".into())
3345 }
3346 _ => SmallDataThresholdSupport::None,
3347 },
3348 s => s.clone(),
3349 }
3350 }
3351
3352 pub fn object_architecture(
3353 &self,
3354 unstable_target_features: &FxIndexSet<Symbol>,
3355 ) -> Option<(object::Architecture, Option<object::SubArchitecture>)> {
3356 use object::Architecture;
3357 Some(match self.arch {
3358 Arch::Arm => (Architecture::Arm, None),
3359 Arch::AArch64 => (
3360 if self.pointer_width == 32 {
3361 Architecture::Aarch64_Ilp32
3362 } else {
3363 Architecture::Aarch64
3364 },
3365 None,
3366 ),
3367 Arch::X86 => (Architecture::I386, None),
3368 Arch::S390x => (Architecture::S390x, None),
3369 Arch::M68k => (Architecture::M68k, None),
3370 Arch::Mips | Arch::Mips32r6 => (Architecture::Mips, None),
3371 Arch::Mips64 | Arch::Mips64r6 => (
3372 if self.options.llvm_abiname.as_ref() == "n32" {
3378 Architecture::Mips64_N32
3379 } else {
3380 Architecture::Mips64
3381 },
3382 None,
3383 ),
3384 Arch::X86_64 => (
3385 if self.pointer_width == 32 {
3386 Architecture::X86_64_X32
3387 } else {
3388 Architecture::X86_64
3389 },
3390 None,
3391 ),
3392 Arch::PowerPC => (Architecture::PowerPc, None),
3393 Arch::PowerPC64 => (Architecture::PowerPc64, None),
3394 Arch::RiscV32 => (Architecture::Riscv32, None),
3395 Arch::RiscV64 => (Architecture::Riscv64, None),
3396 Arch::Sparc => {
3397 if unstable_target_features.contains(&sym::v8plus) {
3398 (Architecture::Sparc32Plus, None)
3400 } else {
3401 (Architecture::Sparc, None)
3403 }
3404 }
3405 Arch::Sparc64 => (Architecture::Sparc64, None),
3406 Arch::Avr => (Architecture::Avr, None),
3407 Arch::Msp430 => (Architecture::Msp430, None),
3408 Arch::Hexagon => (Architecture::Hexagon, None),
3409 Arch::Xtensa => (Architecture::Xtensa, None),
3410 Arch::Bpf => (Architecture::Bpf, None),
3411 Arch::LoongArch32 => (Architecture::LoongArch32, None),
3412 Arch::LoongArch64 => (Architecture::LoongArch64, None),
3413 Arch::CSky => (Architecture::Csky, None),
3414 Arch::Arm64EC => (Architecture::Aarch64, Some(object::SubArchitecture::Arm64EC)),
3415 Arch::AmdGpu
3416 | Arch::Nvptx64
3417 | Arch::PowerPC64LE
3418 | Arch::SpirV
3419 | Arch::Wasm32
3420 | Arch::Wasm64
3421 | Arch::Other(_) => return None,
3422 })
3423 }
3424
3425 pub fn max_reliable_alignment(&self) -> Align {
3434 if self.is_like_windows && self.arch == Arch::X86 {
3438 Align::from_bytes(4).unwrap()
3439 } else {
3440 Align::MAX
3441 }
3442 }
3443
3444 pub fn vendor_symbol(&self) -> Symbol {
3445 Symbol::intern(&self.vendor)
3446 }
3447}
3448
3449#[derive(Clone, Debug)]
3451pub enum TargetTuple {
3452 TargetTuple(String),
3453 TargetJson {
3454 path_for_rustdoc: PathBuf,
3457 tuple: String,
3458 contents: String,
3459 },
3460}
3461
3462impl PartialEq for TargetTuple {
3464 fn eq(&self, other: &Self) -> bool {
3465 match (self, other) {
3466 (Self::TargetTuple(l0), Self::TargetTuple(r0)) => l0 == r0,
3467 (
3468 Self::TargetJson { path_for_rustdoc: _, tuple: l_tuple, contents: l_contents },
3469 Self::TargetJson { path_for_rustdoc: _, tuple: r_tuple, contents: r_contents },
3470 ) => l_tuple == r_tuple && l_contents == r_contents,
3471 _ => false,
3472 }
3473 }
3474}
3475
3476impl Hash for TargetTuple {
3478 fn hash<H: Hasher>(&self, state: &mut H) -> () {
3479 match self {
3480 TargetTuple::TargetTuple(tuple) => {
3481 0u8.hash(state);
3482 tuple.hash(state)
3483 }
3484 TargetTuple::TargetJson { path_for_rustdoc: _, tuple, contents } => {
3485 1u8.hash(state);
3486 tuple.hash(state);
3487 contents.hash(state)
3488 }
3489 }
3490 }
3491}
3492
3493impl<S: Encoder> Encodable<S> for TargetTuple {
3495 fn encode(&self, s: &mut S) {
3496 match self {
3497 TargetTuple::TargetTuple(tuple) => {
3498 s.emit_u8(0);
3499 s.emit_str(tuple);
3500 }
3501 TargetTuple::TargetJson { path_for_rustdoc: _, tuple, contents } => {
3502 s.emit_u8(1);
3503 s.emit_str(tuple);
3504 s.emit_str(contents);
3505 }
3506 }
3507 }
3508}
3509
3510impl<D: Decoder> Decodable<D> for TargetTuple {
3511 fn decode(d: &mut D) -> Self {
3512 match d.read_u8() {
3513 0 => TargetTuple::TargetTuple(d.read_str().to_owned()),
3514 1 => TargetTuple::TargetJson {
3515 path_for_rustdoc: PathBuf::new(),
3516 tuple: d.read_str().to_owned(),
3517 contents: d.read_str().to_owned(),
3518 },
3519 _ => {
3520 panic!("invalid enum variant tag while decoding `TargetTuple`, expected 0..2");
3521 }
3522 }
3523 }
3524}
3525
3526impl TargetTuple {
3527 pub fn from_tuple(tuple: &str) -> Self {
3529 TargetTuple::TargetTuple(tuple.into())
3530 }
3531
3532 pub fn from_path(path: &Path) -> Result<Self, io::Error> {
3534 let canonicalized_path = try_canonicalize(path)?;
3535 let contents = std::fs::read_to_string(&canonicalized_path).map_err(|err| {
3536 io::Error::new(
3537 io::ErrorKind::InvalidInput,
3538 format!("target path {canonicalized_path:?} is not a valid file: {err}"),
3539 )
3540 })?;
3541 let tuple = canonicalized_path
3542 .file_stem()
3543 .expect("target path must not be empty")
3544 .to_str()
3545 .expect("target path must be valid unicode")
3546 .to_owned();
3547 Ok(TargetTuple::TargetJson { path_for_rustdoc: canonicalized_path, tuple, contents })
3548 }
3549
3550 pub fn tuple(&self) -> &str {
3554 match *self {
3555 TargetTuple::TargetTuple(ref tuple) | TargetTuple::TargetJson { ref tuple, .. } => {
3556 tuple
3557 }
3558 }
3559 }
3560
3561 pub fn debug_tuple(&self) -> String {
3566 use std::hash::DefaultHasher;
3567
3568 match self {
3569 TargetTuple::TargetTuple(tuple) => tuple.to_owned(),
3570 TargetTuple::TargetJson { path_for_rustdoc: _, tuple, contents: content } => {
3571 let mut hasher = DefaultHasher::new();
3572 content.hash(&mut hasher);
3573 let hash = hasher.finish();
3574 format!("{tuple}-{hash}")
3575 }
3576 }
3577 }
3578}
3579
3580impl fmt::Display for TargetTuple {
3581 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3582 write!(f, "{}", self.debug_tuple())
3583 }
3584}
3585
3586into_diag_arg_using_display!(&TargetTuple);