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
1494 ("mips-unknown-linux-uclibc", mips_unknown_linux_uclibc),
1495 ("mipsel-unknown-linux-uclibc", mipsel_unknown_linux_uclibc),
1496
1497 ("i686-linux-android", i686_linux_android),
1498 ("x86_64-linux-android", x86_64_linux_android),
1499 ("arm-linux-androideabi", arm_linux_androideabi),
1500 ("armv7-linux-androideabi", armv7_linux_androideabi),
1501 ("thumbv7neon-linux-androideabi", thumbv7neon_linux_androideabi),
1502 ("aarch64-linux-android", aarch64_linux_android),
1503 ("riscv64-linux-android", riscv64_linux_android),
1504
1505 ("aarch64-unknown-freebsd", aarch64_unknown_freebsd),
1506 ("armv6-unknown-freebsd", armv6_unknown_freebsd),
1507 ("armv7-unknown-freebsd", armv7_unknown_freebsd),
1508 ("i686-unknown-freebsd", i686_unknown_freebsd),
1509 ("powerpc-unknown-freebsd", powerpc_unknown_freebsd),
1510 ("powerpc64-unknown-freebsd", powerpc64_unknown_freebsd),
1511 ("powerpc64le-unknown-freebsd", powerpc64le_unknown_freebsd),
1512 ("riscv64gc-unknown-freebsd", riscv64gc_unknown_freebsd),
1513 ("x86_64-unknown-freebsd", x86_64_unknown_freebsd),
1514
1515 ("x86_64-unknown-dragonfly", x86_64_unknown_dragonfly),
1516
1517 ("aarch64-unknown-openbsd", aarch64_unknown_openbsd),
1518 ("i686-unknown-openbsd", i686_unknown_openbsd),
1519 ("powerpc-unknown-openbsd", powerpc_unknown_openbsd),
1520 ("powerpc64-unknown-openbsd", powerpc64_unknown_openbsd),
1521 ("riscv64gc-unknown-openbsd", riscv64gc_unknown_openbsd),
1522 ("sparc64-unknown-openbsd", sparc64_unknown_openbsd),
1523 ("x86_64-unknown-openbsd", x86_64_unknown_openbsd),
1524
1525 ("aarch64-unknown-netbsd", aarch64_unknown_netbsd),
1526 ("aarch64_be-unknown-netbsd", aarch64_be_unknown_netbsd),
1527 ("armv6-unknown-netbsd-eabihf", armv6_unknown_netbsd_eabihf),
1528 ("armv7-unknown-netbsd-eabihf", armv7_unknown_netbsd_eabihf),
1529 ("i586-unknown-netbsd", i586_unknown_netbsd),
1530 ("i686-unknown-netbsd", i686_unknown_netbsd),
1531 ("mipsel-unknown-netbsd", mipsel_unknown_netbsd),
1532 ("powerpc-unknown-netbsd", powerpc_unknown_netbsd),
1533 ("riscv64gc-unknown-netbsd", riscv64gc_unknown_netbsd),
1534 ("sparc64-unknown-netbsd", sparc64_unknown_netbsd),
1535 ("x86_64-unknown-netbsd", x86_64_unknown_netbsd),
1536
1537 ("i686-unknown-haiku", i686_unknown_haiku),
1538 ("x86_64-unknown-haiku", x86_64_unknown_haiku),
1539
1540 ("aarch64-unknown-helenos", aarch64_unknown_helenos),
1541 ("i686-unknown-helenos", i686_unknown_helenos),
1542 ("powerpc-unknown-helenos", powerpc_unknown_helenos),
1543 ("sparc64-unknown-helenos", sparc64_unknown_helenos),
1544 ("x86_64-unknown-helenos", x86_64_unknown_helenos),
1545
1546 ("i686-unknown-hurd-gnu", i686_unknown_hurd_gnu),
1547 ("x86_64-unknown-hurd-gnu", x86_64_unknown_hurd_gnu),
1548
1549 ("aarch64-apple-darwin", aarch64_apple_darwin),
1550 ("arm64e-apple-darwin", arm64e_apple_darwin),
1551 ("x86_64-apple-darwin", x86_64_apple_darwin),
1552 ("x86_64h-apple-darwin", x86_64h_apple_darwin),
1553 ("i686-apple-darwin", i686_apple_darwin),
1554
1555 ("aarch64-unknown-fuchsia", aarch64_unknown_fuchsia),
1556 ("riscv64gc-unknown-fuchsia", riscv64gc_unknown_fuchsia),
1557 ("x86_64-unknown-fuchsia", x86_64_unknown_fuchsia),
1558
1559 ("avr-none", avr_none),
1560
1561 ("x86_64-unknown-l4re-uclibc", x86_64_unknown_l4re_uclibc),
1562
1563 ("aarch64-unknown-redox", aarch64_unknown_redox),
1564 ("i586-unknown-redox", i586_unknown_redox),
1565 ("riscv64gc-unknown-redox", riscv64gc_unknown_redox),
1566 ("x86_64-unknown-redox", x86_64_unknown_redox),
1567
1568 ("x86_64-unknown-managarm-mlibc", x86_64_unknown_managarm_mlibc),
1569 ("aarch64-unknown-managarm-mlibc", aarch64_unknown_managarm_mlibc),
1570 ("riscv64gc-unknown-managarm-mlibc", riscv64gc_unknown_managarm_mlibc),
1571
1572 ("i386-apple-ios", i386_apple_ios),
1573 ("x86_64-apple-ios", x86_64_apple_ios),
1574 ("aarch64-apple-ios", aarch64_apple_ios),
1575 ("arm64e-apple-ios", arm64e_apple_ios),
1576 ("armv7s-apple-ios", armv7s_apple_ios),
1577 ("x86_64-apple-ios-macabi", x86_64_apple_ios_macabi),
1578 ("aarch64-apple-ios-macabi", aarch64_apple_ios_macabi),
1579 ("aarch64-apple-ios-sim", aarch64_apple_ios_sim),
1580
1581 ("aarch64-apple-tvos", aarch64_apple_tvos),
1582 ("aarch64-apple-tvos-sim", aarch64_apple_tvos_sim),
1583 ("arm64e-apple-tvos", arm64e_apple_tvos),
1584 ("x86_64-apple-tvos", x86_64_apple_tvos),
1585
1586 ("armv7k-apple-watchos", armv7k_apple_watchos),
1587 ("arm64_32-apple-watchos", arm64_32_apple_watchos),
1588 ("x86_64-apple-watchos-sim", x86_64_apple_watchos_sim),
1589 ("aarch64-apple-watchos", aarch64_apple_watchos),
1590 ("aarch64-apple-watchos-sim", aarch64_apple_watchos_sim),
1591
1592 ("aarch64-apple-visionos", aarch64_apple_visionos),
1593 ("aarch64-apple-visionos-sim", aarch64_apple_visionos_sim),
1594
1595 ("armebv7r-none-eabi", armebv7r_none_eabi),
1596 ("armebv7r-none-eabihf", armebv7r_none_eabihf),
1597 ("armv7r-none-eabi", armv7r_none_eabi),
1598 ("armv7r-none-eabihf", armv7r_none_eabihf),
1599 ("armv8r-none-eabihf", armv8r_none_eabihf),
1600
1601 ("armv7-rtems-eabihf", armv7_rtems_eabihf),
1602
1603 ("x86_64-pc-solaris", x86_64_pc_solaris),
1604 ("sparcv9-sun-solaris", sparcv9_sun_solaris),
1605
1606 ("x86_64-unknown-illumos", x86_64_unknown_illumos),
1607 ("aarch64-unknown-illumos", aarch64_unknown_illumos),
1608
1609 ("x86_64-pc-windows-gnu", x86_64_pc_windows_gnu),
1610 ("x86_64-uwp-windows-gnu", x86_64_uwp_windows_gnu),
1611 ("x86_64-win7-windows-gnu", x86_64_win7_windows_gnu),
1612 ("i686-pc-windows-gnu", i686_pc_windows_gnu),
1613 ("i686-uwp-windows-gnu", i686_uwp_windows_gnu),
1614 ("i686-win7-windows-gnu", i686_win7_windows_gnu),
1615
1616 ("aarch64-pc-windows-gnullvm", aarch64_pc_windows_gnullvm),
1617 ("i686-pc-windows-gnullvm", i686_pc_windows_gnullvm),
1618 ("x86_64-pc-windows-gnullvm", x86_64_pc_windows_gnullvm),
1619
1620 ("aarch64-pc-windows-msvc", aarch64_pc_windows_msvc),
1621 ("aarch64-uwp-windows-msvc", aarch64_uwp_windows_msvc),
1622 ("arm64ec-pc-windows-msvc", arm64ec_pc_windows_msvc),
1623 ("x86_64-pc-windows-msvc", x86_64_pc_windows_msvc),
1624 ("x86_64-uwp-windows-msvc", x86_64_uwp_windows_msvc),
1625 ("x86_64-win7-windows-msvc", x86_64_win7_windows_msvc),
1626 ("i686-pc-windows-msvc", i686_pc_windows_msvc),
1627 ("i686-uwp-windows-msvc", i686_uwp_windows_msvc),
1628 ("i686-win7-windows-msvc", i686_win7_windows_msvc),
1629 ("thumbv7a-pc-windows-msvc", thumbv7a_pc_windows_msvc),
1630 ("thumbv7a-uwp-windows-msvc", thumbv7a_uwp_windows_msvc),
1631
1632 ("wasm32-unknown-emscripten", wasm32_unknown_emscripten),
1633 ("wasm32-unknown-unknown", wasm32_unknown_unknown),
1634 ("wasm32v1-none", wasm32v1_none),
1635 ("wasm32-wasip1", wasm32_wasip1),
1636 ("wasm32-wasip2", wasm32_wasip2),
1637 ("wasm32-wasip3", wasm32_wasip3),
1638 ("wasm32-wasip1-threads", wasm32_wasip1_threads),
1639 ("wasm32-wali-linux-musl", wasm32_wali_linux_musl),
1640 ("wasm64-unknown-unknown", wasm64_unknown_unknown),
1641
1642 ("thumbv6m-none-eabi", thumbv6m_none_eabi),
1643 ("thumbv7m-none-eabi", thumbv7m_none_eabi),
1644 ("thumbv7em-none-eabi", thumbv7em_none_eabi),
1645 ("thumbv7em-none-eabihf", thumbv7em_none_eabihf),
1646 ("thumbv8m.base-none-eabi", thumbv8m_base_none_eabi),
1647 ("thumbv8m.main-none-eabi", thumbv8m_main_none_eabi),
1648 ("thumbv8m.main-none-eabihf", thumbv8m_main_none_eabihf),
1649
1650 ("armv7a-none-eabi", armv7a_none_eabi),
1651 ("armv7a-none-eabihf", armv7a_none_eabihf),
1652 ("armv7a-nuttx-eabi", armv7a_nuttx_eabi),
1653 ("armv7a-nuttx-eabihf", armv7a_nuttx_eabihf),
1654 ("armv7a-vex-v5", armv7a_vex_v5),
1655
1656 ("msp430-none-elf", msp430_none_elf),
1657
1658 ("aarch64_be-unknown-hermit", aarch64_be_unknown_hermit),
1659 ("aarch64-unknown-hermit", aarch64_unknown_hermit),
1660 ("riscv64gc-unknown-hermit", riscv64gc_unknown_hermit),
1661 ("x86_64-unknown-hermit", x86_64_unknown_hermit),
1662 ("x86_64-unknown-motor", x86_64_unknown_motor),
1663
1664 ("x86_64-unikraft-linux-musl", x86_64_unikraft_linux_musl),
1665
1666 ("armv7-unknown-trusty", armv7_unknown_trusty),
1667 ("aarch64-unknown-trusty", aarch64_unknown_trusty),
1668 ("x86_64-unknown-trusty", x86_64_unknown_trusty),
1669
1670 ("riscv32i-unknown-none-elf", riscv32i_unknown_none_elf),
1671 ("riscv32im-risc0-zkvm-elf", riscv32im_risc0_zkvm_elf),
1672 ("riscv32im-unknown-none-elf", riscv32im_unknown_none_elf),
1673 ("riscv32ima-unknown-none-elf", riscv32ima_unknown_none_elf),
1674 ("riscv32imc-unknown-none-elf", riscv32imc_unknown_none_elf),
1675 ("riscv32imc-esp-espidf", riscv32imc_esp_espidf),
1676 ("riscv32imac-esp-espidf", riscv32imac_esp_espidf),
1677 ("riscv32imafc-esp-espidf", riscv32imafc_esp_espidf),
1678
1679 ("riscv32e-unknown-none-elf", riscv32e_unknown_none_elf),
1680 ("riscv32em-unknown-none-elf", riscv32em_unknown_none_elf),
1681 ("riscv32emc-unknown-none-elf", riscv32emc_unknown_none_elf),
1682
1683 ("riscv32imac-unknown-none-elf", riscv32imac_unknown_none_elf),
1684 ("riscv32imafc-unknown-none-elf", riscv32imafc_unknown_none_elf),
1685 ("riscv32imac-unknown-xous-elf", riscv32imac_unknown_xous_elf),
1686 ("riscv32gc-unknown-linux-gnu", riscv32gc_unknown_linux_gnu),
1687 ("riscv32gc-unknown-linux-musl", riscv32gc_unknown_linux_musl),
1688 ("riscv64imac-unknown-none-elf", riscv64imac_unknown_none_elf),
1689 ("riscv64gc-unknown-none-elf", riscv64gc_unknown_none_elf),
1690 ("riscv64gc-unknown-linux-gnu", riscv64gc_unknown_linux_gnu),
1691 ("riscv64gc-unknown-linux-musl", riscv64gc_unknown_linux_musl),
1692 ("riscv64a23-unknown-linux-gnu", riscv64a23_unknown_linux_gnu),
1693
1694 ("sparc-unknown-none-elf", sparc_unknown_none_elf),
1695
1696 ("loongarch32-unknown-none", loongarch32_unknown_none),
1697 ("loongarch32-unknown-none-softfloat", loongarch32_unknown_none_softfloat),
1698 ("loongarch64-unknown-none", loongarch64_unknown_none),
1699 ("loongarch64-unknown-none-softfloat", loongarch64_unknown_none_softfloat),
1700
1701 ("aarch64-unknown-none", aarch64_unknown_none),
1702 ("aarch64-unknown-none-softfloat", aarch64_unknown_none_softfloat),
1703 ("aarch64_be-unknown-none-softfloat", aarch64_be_unknown_none_softfloat),
1704 ("aarch64-unknown-nuttx", aarch64_unknown_nuttx),
1705
1706 ("x86_64-fortanix-unknown-sgx", x86_64_fortanix_unknown_sgx),
1707
1708 ("x86_64-unknown-uefi", x86_64_unknown_uefi),
1709 ("i686-unknown-uefi", i686_unknown_uefi),
1710 ("aarch64-unknown-uefi", aarch64_unknown_uefi),
1711
1712 ("nvptx64-nvidia-cuda", nvptx64_nvidia_cuda),
1713
1714 ("amdgcn-amd-amdhsa", amdgcn_amd_amdhsa),
1715
1716 ("xtensa-esp32-none-elf", xtensa_esp32_none_elf),
1717 ("xtensa-esp32-espidf", xtensa_esp32_espidf),
1718 ("xtensa-esp32s2-none-elf", xtensa_esp32s2_none_elf),
1719 ("xtensa-esp32s2-espidf", xtensa_esp32s2_espidf),
1720 ("xtensa-esp32s3-none-elf", xtensa_esp32s3_none_elf),
1721 ("xtensa-esp32s3-espidf", xtensa_esp32s3_espidf),
1722
1723 ("i686-wrs-vxworks", i686_wrs_vxworks),
1724 ("x86_64-wrs-vxworks", x86_64_wrs_vxworks),
1725 ("armv7-wrs-vxworks-eabihf", armv7_wrs_vxworks_eabihf),
1726 ("aarch64-wrs-vxworks", aarch64_wrs_vxworks),
1727 ("powerpc-wrs-vxworks", powerpc_wrs_vxworks),
1728 ("powerpc-wrs-vxworks-spe", powerpc_wrs_vxworks_spe),
1729 ("powerpc64-wrs-vxworks", powerpc64_wrs_vxworks),
1730 ("riscv32-wrs-vxworks", riscv32_wrs_vxworks),
1731 ("riscv64-wrs-vxworks", riscv64_wrs_vxworks),
1732
1733 ("aarch64-kmc-solid_asp3", aarch64_kmc_solid_asp3),
1734 ("armv7a-kmc-solid_asp3-eabi", armv7a_kmc_solid_asp3_eabi),
1735 ("armv7a-kmc-solid_asp3-eabihf", armv7a_kmc_solid_asp3_eabihf),
1736
1737 ("mipsel-sony-psp", mipsel_sony_psp),
1738 ("mipsel-sony-psx", mipsel_sony_psx),
1739 ("mipsel-unknown-none", mipsel_unknown_none),
1740 ("mips-mti-none-elf", mips_mti_none_elf),
1741 ("mipsel-mti-none-elf", mipsel_mti_none_elf),
1742 ("thumbv4t-none-eabi", thumbv4t_none_eabi),
1743 ("armv4t-none-eabi", armv4t_none_eabi),
1744 ("thumbv5te-none-eabi", thumbv5te_none_eabi),
1745 ("armv5te-none-eabi", armv5te_none_eabi),
1746
1747 ("aarch64_be-unknown-linux-gnu", aarch64_be_unknown_linux_gnu),
1748 ("aarch64-unknown-linux-gnu_ilp32", aarch64_unknown_linux_gnu_ilp32),
1749 ("aarch64_be-unknown-linux-gnu_ilp32", aarch64_be_unknown_linux_gnu_ilp32),
1750
1751 ("bpfeb-unknown-none", bpfeb_unknown_none),
1752 ("bpfel-unknown-none", bpfel_unknown_none),
1753
1754 ("armv6k-nintendo-3ds", armv6k_nintendo_3ds),
1755
1756 ("aarch64-nintendo-switch-freestanding", aarch64_nintendo_switch_freestanding),
1757
1758 ("armv7-sony-vita-newlibeabihf", armv7_sony_vita_newlibeabihf),
1759
1760 ("armv7-unknown-linux-uclibceabi", armv7_unknown_linux_uclibceabi),
1761 ("armv7-unknown-linux-uclibceabihf", armv7_unknown_linux_uclibceabihf),
1762
1763 ("x86_64-unknown-none", x86_64_unknown_none),
1764
1765 ("aarch64-unknown-teeos", aarch64_unknown_teeos),
1766
1767 ("mips64-openwrt-linux-musl", mips64_openwrt_linux_musl),
1768
1769 ("aarch64-unknown-nto-qnx700", aarch64_unknown_nto_qnx700),
1770 ("aarch64-unknown-nto-qnx710", aarch64_unknown_nto_qnx710),
1771 ("aarch64-unknown-nto-qnx710_iosock", aarch64_unknown_nto_qnx710_iosock),
1772 ("aarch64-unknown-nto-qnx800", aarch64_unknown_nto_qnx800),
1773 ("x86_64-pc-nto-qnx710", x86_64_pc_nto_qnx710),
1774 ("x86_64-pc-nto-qnx710_iosock", x86_64_pc_nto_qnx710_iosock),
1775 ("x86_64-pc-nto-qnx800", x86_64_pc_nto_qnx800),
1776 ("i686-pc-nto-qnx700", i686_pc_nto_qnx700),
1777
1778 ("aarch64-unknown-linux-ohos", aarch64_unknown_linux_ohos),
1779 ("armv7-unknown-linux-ohos", armv7_unknown_linux_ohos),
1780 ("loongarch64-unknown-linux-ohos", loongarch64_unknown_linux_ohos),
1781 ("x86_64-unknown-linux-ohos", x86_64_unknown_linux_ohos),
1782
1783 ("x86_64-unknown-linux-none", x86_64_unknown_linux_none),
1784
1785 ("thumbv6m-nuttx-eabi", thumbv6m_nuttx_eabi),
1786 ("thumbv7a-nuttx-eabi", thumbv7a_nuttx_eabi),
1787 ("thumbv7a-nuttx-eabihf", thumbv7a_nuttx_eabihf),
1788 ("thumbv7m-nuttx-eabi", thumbv7m_nuttx_eabi),
1789 ("thumbv7em-nuttx-eabi", thumbv7em_nuttx_eabi),
1790 ("thumbv7em-nuttx-eabihf", thumbv7em_nuttx_eabihf),
1791 ("thumbv8m.base-nuttx-eabi", thumbv8m_base_nuttx_eabi),
1792 ("thumbv8m.main-nuttx-eabi", thumbv8m_main_nuttx_eabi),
1793 ("thumbv8m.main-nuttx-eabihf", thumbv8m_main_nuttx_eabihf),
1794 ("riscv32imc-unknown-nuttx-elf", riscv32imc_unknown_nuttx_elf),
1795 ("riscv32imac-unknown-nuttx-elf", riscv32imac_unknown_nuttx_elf),
1796 ("riscv32imafc-unknown-nuttx-elf", riscv32imafc_unknown_nuttx_elf),
1797 ("riscv64imac-unknown-nuttx-elf", riscv64imac_unknown_nuttx_elf),
1798 ("riscv64gc-unknown-nuttx-elf", riscv64gc_unknown_nuttx_elf),
1799 ("x86_64-lynx-lynxos178", x86_64_lynx_lynxos178),
1800
1801 ("x86_64-pc-cygwin", x86_64_pc_cygwin),
1802}
1803
1804macro_rules! cvs {
1806 () => {
1807 ::std::borrow::Cow::Borrowed(&[])
1808 };
1809 ($($x:expr),+ $(,)?) => {
1810 ::std::borrow::Cow::Borrowed(&[
1811 $(
1812 ::std::borrow::Cow::Borrowed($x),
1813 )*
1814 ])
1815 };
1816}
1817
1818pub(crate) use cvs;
1819
1820#[derive(Debug, PartialEq)]
1824pub struct TargetWarnings {
1825 unused_fields: Vec<String>,
1826}
1827
1828impl TargetWarnings {
1829 pub fn empty() -> Self {
1830 Self { unused_fields: Vec::new() }
1831 }
1832
1833 pub fn warning_messages(&self) -> Vec<String> {
1834 let mut warnings = vec![];
1835 if !self.unused_fields.is_empty() {
1836 warnings.push(format!(
1837 "target json file contains unused fields: {}",
1838 self.unused_fields.join(", ")
1839 ));
1840 }
1841 warnings
1842 }
1843}
1844
1845#[derive(Copy, Clone, Debug, PartialEq)]
1848enum TargetKind {
1849 Json,
1850 Builtin,
1851}
1852
1853crate::target_spec_enum! {
1854 pub enum Arch {
1855 AArch64 = "aarch64",
1856 AmdGpu = "amdgpu",
1857 Arm = "arm",
1858 Arm64EC = "arm64ec",
1859 Avr = "avr",
1860 Bpf = "bpf",
1861 CSky = "csky",
1862 Hexagon = "hexagon",
1863 LoongArch32 = "loongarch32",
1864 LoongArch64 = "loongarch64",
1865 M68k = "m68k",
1866 Mips = "mips",
1867 Mips32r6 = "mips32r6",
1868 Mips64 = "mips64",
1869 Mips64r6 = "mips64r6",
1870 Msp430 = "msp430",
1871 Nvptx64 = "nvptx64",
1872 PowerPC = "powerpc",
1873 PowerPC64 = "powerpc64",
1874 PowerPC64LE = "powerpc64le",
1875 RiscV32 = "riscv32",
1876 RiscV64 = "riscv64",
1877 S390x = "s390x",
1878 Sparc = "sparc",
1879 Sparc64 = "sparc64",
1880 SpirV = "spirv",
1881 Wasm32 = "wasm32",
1882 Wasm64 = "wasm64",
1883 X86 = "x86",
1884 X86_64 = "x86_64",
1885 Xtensa = "xtensa",
1886 }
1887 other_variant = Other;
1888}
1889
1890impl Arch {
1891 pub fn desc_symbol(&self) -> Symbol {
1892 match self {
1893 Self::AArch64 => sym::aarch64,
1894 Self::AmdGpu => sym::amdgpu,
1895 Self::Arm => sym::arm,
1896 Self::Arm64EC => sym::arm64ec,
1897 Self::Avr => sym::avr,
1898 Self::Bpf => sym::bpf,
1899 Self::CSky => sym::csky,
1900 Self::Hexagon => sym::hexagon,
1901 Self::LoongArch32 => sym::loongarch32,
1902 Self::LoongArch64 => sym::loongarch64,
1903 Self::M68k => sym::m68k,
1904 Self::Mips => sym::mips,
1905 Self::Mips32r6 => sym::mips32r6,
1906 Self::Mips64 => sym::mips64,
1907 Self::Mips64r6 => sym::mips64r6,
1908 Self::Msp430 => sym::msp430,
1909 Self::Nvptx64 => sym::nvptx64,
1910 Self::PowerPC => sym::powerpc,
1911 Self::PowerPC64 => sym::powerpc64,
1912 Self::PowerPC64LE => sym::powerpc64le,
1913 Self::RiscV32 => sym::riscv32,
1914 Self::RiscV64 => sym::riscv64,
1915 Self::S390x => sym::s390x,
1916 Self::Sparc => sym::sparc,
1917 Self::Sparc64 => sym::sparc64,
1918 Self::SpirV => sym::spirv,
1919 Self::Wasm32 => sym::wasm32,
1920 Self::Wasm64 => sym::wasm64,
1921 Self::X86 => sym::x86,
1922 Self::X86_64 => sym::x86_64,
1923 Self::Xtensa => sym::xtensa,
1924 Self::Other(name) => rustc_span::Symbol::intern(name),
1925 }
1926 }
1927}
1928
1929crate::target_spec_enum! {
1930 pub enum Os {
1931 Aix = "aix",
1932 AmdHsa = "amdhsa",
1933 Android = "android",
1934 Cuda = "cuda",
1935 Cygwin = "cygwin",
1936 Dragonfly = "dragonfly",
1937 Emscripten = "emscripten",
1938 EspIdf = "espidf",
1939 FreeBsd = "freebsd",
1940 Fuchsia = "fuchsia",
1941 Haiku = "haiku",
1942 HelenOs = "helenos",
1943 Hermit = "hermit",
1944 Horizon = "horizon",
1945 Hurd = "hurd",
1946 Illumos = "illumos",
1947 IOs = "ios",
1948 L4Re = "l4re",
1949 Linux = "linux",
1950 LynxOs178 = "lynxos178",
1951 MacOs = "macos",
1952 Managarm = "managarm",
1953 Motor = "motor",
1954 NetBsd = "netbsd",
1955 None = "none",
1956 Nto = "nto",
1957 NuttX = "nuttx",
1958 OpenBsd = "openbsd",
1959 Psp = "psp",
1960 Psx = "psx",
1961 Redox = "redox",
1962 Rtems = "rtems",
1963 Solaris = "solaris",
1964 SolidAsp3 = "solid_asp3",
1965 TeeOs = "teeos",
1966 Trusty = "trusty",
1967 TvOs = "tvos",
1968 Uefi = "uefi",
1969 VexOs = "vexos",
1970 VisionOs = "visionos",
1971 Vita = "vita",
1972 VxWorks = "vxworks",
1973 Wasi = "wasi",
1974 WatchOs = "watchos",
1975 Windows = "windows",
1976 Xous = "xous",
1977 Zkvm = "zkvm",
1978 Unknown = "unknown",
1979 }
1980 other_variant = Other;
1981}
1982
1983impl Os {
1984 pub fn desc_symbol(&self) -> Symbol {
1985 Symbol::intern(self.desc())
1986 }
1987}
1988
1989crate::target_spec_enum! {
1990 pub enum Env {
1991 Gnu = "gnu",
1992 MacAbi = "macabi",
1993 Mlibc = "mlibc",
1994 Msvc = "msvc",
1995 Musl = "musl",
1996 Newlib = "newlib",
1997 Nto70 = "nto70",
1998 Nto71 = "nto71",
1999 Nto71IoSock = "nto71_iosock",
2000 Nto80 = "nto80",
2001 Ohos = "ohos",
2002 Relibc = "relibc",
2003 Sgx = "sgx",
2004 Sim = "sim",
2005 P1 = "p1",
2006 P2 = "p2",
2007 P3 = "p3",
2008 Uclibc = "uclibc",
2009 V5 = "v5",
2010 Unspecified = "",
2011 }
2012 other_variant = Other;
2013}
2014
2015impl Env {
2016 pub fn desc_symbol(&self) -> Symbol {
2017 Symbol::intern(self.desc())
2018 }
2019}
2020
2021crate::target_spec_enum! {
2022 pub enum Abi {
2023 Abi64 = "abi64",
2024 AbiV2 = "abiv2",
2025 AbiV2Hf = "abiv2hf",
2026 Eabi = "eabi",
2027 EabiHf = "eabihf",
2028 ElfV1 = "elfv1",
2029 ElfV2 = "elfv2",
2030 Fortanix = "fortanix",
2031 Ilp32 = "ilp32",
2032 Ilp32e = "ilp32e",
2033 Llvm = "llvm",
2034 MacAbi = "macabi",
2035 Sim = "sim",
2036 SoftFloat = "softfloat",
2037 Spe = "spe",
2038 Uwp = "uwp",
2039 VecDefault = "vec-default",
2040 VecExtAbi = "vec-extabi",
2041 X32 = "x32",
2042 Unspecified = "",
2043 }
2044 other_variant = Other;
2045}
2046
2047impl Abi {
2048 pub fn desc_symbol(&self) -> Symbol {
2049 Symbol::intern(self.desc())
2050 }
2051}
2052
2053#[derive(PartialEq, Clone, Debug)]
2057pub struct Target {
2058 pub llvm_target: StaticCow<str>,
2065 pub metadata: TargetMetadata,
2068 pub pointer_width: u16,
2070 pub arch: Arch,
2073 pub data_layout: StaticCow<str>,
2075 pub options: TargetOptions,
2077}
2078
2079#[derive(Default, PartialEq, Clone, Debug)]
2083pub struct TargetMetadata {
2084 pub description: Option<StaticCow<str>>,
2087 pub tier: Option<u64>,
2089 pub host_tools: Option<bool>,
2091 pub std: Option<bool>,
2094}
2095
2096impl Target {
2097 pub fn parse_data_layout(&self) -> Result<TargetDataLayout, TargetDataLayoutErrors<'_>> {
2098 let mut dl = TargetDataLayout::parse_from_llvm_datalayout_string(
2099 &self.data_layout,
2100 self.options.default_address_space,
2101 )?;
2102
2103 if dl.endian != self.endian {
2105 return Err(TargetDataLayoutErrors::InconsistentTargetArchitecture {
2106 dl: dl.endian.as_str(),
2107 target: self.endian.as_str(),
2108 });
2109 }
2110
2111 let target_pointer_width: u64 = self.pointer_width.into();
2112 let dl_pointer_size: u64 = dl.pointer_size().bits();
2113 if dl_pointer_size != target_pointer_width {
2114 return Err(TargetDataLayoutErrors::InconsistentTargetPointerWidth {
2115 pointer_size: dl_pointer_size,
2116 target: self.pointer_width,
2117 });
2118 }
2119
2120 dl.c_enum_min_size = Integer::from_size(Size::from_bits(
2121 self.c_enum_min_bits.unwrap_or(self.c_int_width as _),
2122 ))
2123 .map_err(|err| TargetDataLayoutErrors::InvalidBitsSize { err })?;
2124
2125 Ok(dl)
2126 }
2127}
2128
2129pub trait HasTargetSpec {
2130 fn target_spec(&self) -> &Target;
2131}
2132
2133impl HasTargetSpec for Target {
2134 #[inline]
2135 fn target_spec(&self) -> &Target {
2136 self
2137 }
2138}
2139
2140#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
2142pub struct X86Abi {
2143 pub regparm: Option<u32>,
2146 pub reg_struct_return: bool,
2148}
2149
2150pub trait HasX86AbiOpt {
2151 fn x86_abi_opt(&self) -> X86Abi;
2152}
2153
2154type StaticCow<T> = Cow<'static, T>;
2155
2156#[derive(PartialEq, Clone, Debug)]
2165#[rustc_lint_opt_ty]
2166pub struct TargetOptions {
2167 pub endian: Endian,
2169 pub c_int_width: u16,
2171 pub os: Os,
2176 pub env: Env,
2178 pub abi: Abi,
2183 #[rustc_lint_opt_deny_field_access(
2185 "use `Target::is_like_*` instead of this field; see https://github.com/rust-lang/rust/issues/100343 for rationale"
2186 )]
2187 vendor: StaticCow<str>,
2188
2189 pub linker: Option<StaticCow<str>>,
2191 pub linker_flavor: LinkerFlavor,
2194 linker_flavor_json: LinkerFlavorCli,
2195 lld_flavor_json: LldFlavor,
2196 linker_is_gnu_json: bool,
2197
2198 pub pre_link_objects: CrtObjects,
2200 pub post_link_objects: CrtObjects,
2201 pub pre_link_objects_self_contained: CrtObjects,
2203 pub post_link_objects_self_contained: CrtObjects,
2204 pub link_self_contained: LinkSelfContainedDefault,
2207
2208 pub pre_link_args: LinkArgs,
2210 pre_link_args_json: LinkArgsCli,
2211 pub late_link_args: LinkArgs,
2215 late_link_args_json: LinkArgsCli,
2216 pub late_link_args_dynamic: LinkArgs,
2219 late_link_args_dynamic_json: LinkArgsCli,
2220 pub late_link_args_static: LinkArgs,
2223 late_link_args_static_json: LinkArgsCli,
2224 pub post_link_args: LinkArgs,
2227 post_link_args_json: LinkArgsCli,
2228
2229 pub link_script: Option<StaticCow<str>>,
2233 pub link_env: StaticCow<[(StaticCow<str>, StaticCow<str>)]>,
2235 pub link_env_remove: StaticCow<[StaticCow<str>]>,
2237
2238 pub asm_args: StaticCow<[StaticCow<str>]>,
2240
2241 pub cpu: StaticCow<str>,
2244 pub need_explicit_cpu: bool,
2247 pub features: StaticCow<str>,
2256 pub direct_access_external_data: Option<bool>,
2258 pub dynamic_linking: bool,
2260 pub dll_tls_export: bool,
2262 pub only_cdylib: bool,
2264 pub executables: bool,
2266 pub relocation_model: RelocModel,
2269 pub code_model: Option<CodeModel>,
2272 pub tls_model: TlsModel,
2275 pub disable_redzone: bool,
2277 pub frame_pointer: FramePointer,
2279 pub function_sections: bool,
2281 pub dll_prefix: StaticCow<str>,
2283 pub dll_suffix: StaticCow<str>,
2285 pub exe_suffix: StaticCow<str>,
2287 pub staticlib_prefix: StaticCow<str>,
2289 pub staticlib_suffix: StaticCow<str>,
2291 pub families: StaticCow<[StaticCow<str>]>,
2297 pub abi_return_struct_as_int: bool,
2299 pub is_like_aix: bool,
2302 pub is_like_darwin: bool,
2307 pub is_like_gpu: bool,
2309 pub is_like_solaris: bool,
2313 pub is_like_windows: bool,
2321 pub is_like_msvc: bool,
2331 pub is_like_wasm: bool,
2333 pub is_like_android: bool,
2335 pub is_like_vexos: bool,
2337 pub binary_format: BinaryFormat,
2339 pub default_dwarf_version: u32,
2342 pub allows_weak_linkage: bool,
2349 pub has_rpath: bool,
2351 pub no_default_libraries: bool,
2354 pub position_independent_executables: bool,
2360 pub static_position_independent_executables: bool,
2362 pub plt_by_default: bool,
2365 pub relro_level: RelroLevel,
2369 pub archive_format: StaticCow<str>,
2374 pub allow_asm: bool,
2376 pub main_needs_argc_argv: bool,
2379
2380 pub has_thread_local: bool,
2382 pub obj_is_bitcode: bool,
2386
2387 pub min_atomic_width: Option<u64>,
2389
2390 pub max_atomic_width: Option<u64>,
2392
2393 pub atomic_cas: bool,
2395
2396 pub panic_strategy: PanicStrategy,
2398
2399 pub crt_static_allows_dylibs: bool,
2401 pub crt_static_default: bool,
2403 pub crt_static_respected: bool,
2405
2406 pub stack_probes: StackProbeType,
2408
2409 pub min_global_align: Option<Align>,
2411
2412 pub default_codegen_units: Option<u64>,
2414
2415 pub default_codegen_backend: Option<StaticCow<str>>,
2425
2426 pub trap_unreachable: bool,
2429
2430 pub requires_lto: bool,
2433
2434 pub singlethread: bool,
2436
2437 pub no_builtins: bool,
2440
2441 pub default_visibility: Option<SymbolVisibility>,
2447
2448 pub emit_debug_gdb_scripts: bool,
2450
2451 pub requires_uwtable: bool,
2455
2456 pub default_uwtable: bool,
2459
2460 pub simd_types_indirect: bool,
2465
2466 pub limit_rdylib_exports: bool,
2468
2469 pub override_export_symbols: Option<StaticCow<[StaticCow<str>]>>,
2472
2473 pub merge_functions: MergeFunctions,
2480
2481 pub mcount: StaticCow<str>,
2483
2484 pub llvm_mcount_intrinsic: Option<StaticCow<str>>,
2486
2487 pub llvm_abiname: StaticCow<str>,
2490
2491 pub llvm_floatabi: Option<FloatAbi>,
2498
2499 pub rustc_abi: Option<RustcAbi>,
2504
2505 pub relax_elf_relocations: bool,
2507
2508 pub llvm_args: StaticCow<[StaticCow<str>]>,
2510
2511 pub use_ctors_section: bool,
2514
2515 pub eh_frame_header: bool,
2519
2520 pub has_thumb_interworking: bool,
2523
2524 pub debuginfo_kind: DebuginfoKind,
2526 pub split_debuginfo: SplitDebuginfo,
2529 pub supported_split_debuginfo: StaticCow<[SplitDebuginfo]>,
2531
2532 pub supported_sanitizers: SanitizerSet,
2538
2539 pub default_sanitizers: SanitizerSet,
2545
2546 pub c_enum_min_bits: Option<u64>,
2548
2549 pub generate_arange_section: bool,
2551
2552 pub supports_stack_protector: bool,
2555
2556 pub entry_name: StaticCow<str>,
2559
2560 pub entry_abi: CanonAbi,
2563
2564 pub supports_xray: bool,
2566
2567 pub default_address_space: rustc_abi::AddressSpace,
2571
2572 small_data_threshold_support: SmallDataThresholdSupport,
2574}
2575
2576fn add_link_args_iter(
2579 link_args: &mut LinkArgs,
2580 flavor: LinkerFlavor,
2581 args: impl Iterator<Item = StaticCow<str>> + Clone,
2582) {
2583 let mut insert = |flavor| link_args.entry(flavor).or_default().extend(args.clone());
2584 insert(flavor);
2585 match flavor {
2586 LinkerFlavor::Gnu(cc, lld) => {
2587 assert_eq!(lld, Lld::No);
2588 insert(LinkerFlavor::Gnu(cc, Lld::Yes));
2589 }
2590 LinkerFlavor::Darwin(cc, lld) => {
2591 assert_eq!(lld, Lld::No);
2592 insert(LinkerFlavor::Darwin(cc, Lld::Yes));
2593 }
2594 LinkerFlavor::Msvc(lld) => {
2595 assert_eq!(lld, Lld::No);
2596 insert(LinkerFlavor::Msvc(Lld::Yes));
2597 }
2598 LinkerFlavor::WasmLld(..)
2599 | LinkerFlavor::Unix(..)
2600 | LinkerFlavor::EmCc
2601 | LinkerFlavor::Bpf
2602 | LinkerFlavor::Llbc
2603 | LinkerFlavor::Ptx => {}
2604 }
2605}
2606
2607fn add_link_args(link_args: &mut LinkArgs, flavor: LinkerFlavor, args: &[&'static str]) {
2608 add_link_args_iter(link_args, flavor, args.iter().copied().map(Cow::Borrowed))
2609}
2610
2611impl TargetOptions {
2612 pub fn supports_comdat(&self) -> bool {
2613 !self.is_like_aix && !self.is_like_darwin
2615 }
2616}
2617
2618impl TargetOptions {
2619 fn link_args(flavor: LinkerFlavor, args: &[&'static str]) -> LinkArgs {
2620 let mut link_args = LinkArgs::new();
2621 add_link_args(&mut link_args, flavor, args);
2622 link_args
2623 }
2624
2625 fn add_pre_link_args(&mut self, flavor: LinkerFlavor, args: &[&'static str]) {
2626 add_link_args(&mut self.pre_link_args, flavor, args);
2627 }
2628
2629 fn update_from_cli(&mut self) {
2630 self.linker_flavor = LinkerFlavor::from_cli_json(
2631 self.linker_flavor_json,
2632 self.lld_flavor_json,
2633 self.linker_is_gnu_json,
2634 );
2635 for (args, args_json) in [
2636 (&mut self.pre_link_args, &self.pre_link_args_json),
2637 (&mut self.late_link_args, &self.late_link_args_json),
2638 (&mut self.late_link_args_dynamic, &self.late_link_args_dynamic_json),
2639 (&mut self.late_link_args_static, &self.late_link_args_static_json),
2640 (&mut self.post_link_args, &self.post_link_args_json),
2641 ] {
2642 args.clear();
2643 for (flavor, args_json) in args_json {
2644 let linker_flavor = self.linker_flavor.with_cli_hints(*flavor);
2645 let linker_flavor = match linker_flavor {
2647 LinkerFlavor::Gnu(cc, _) => LinkerFlavor::Gnu(cc, Lld::No),
2648 LinkerFlavor::Darwin(cc, _) => LinkerFlavor::Darwin(cc, Lld::No),
2649 LinkerFlavor::Msvc(_) => LinkerFlavor::Msvc(Lld::No),
2650 _ => linker_flavor,
2651 };
2652 if !args.contains_key(&linker_flavor) {
2653 add_link_args_iter(args, linker_flavor, args_json.iter().cloned());
2654 }
2655 }
2656 }
2657 }
2658
2659 fn update_to_cli(&mut self) {
2660 self.linker_flavor_json = self.linker_flavor.to_cli_counterpart();
2661 self.lld_flavor_json = self.linker_flavor.lld_flavor();
2662 self.linker_is_gnu_json = self.linker_flavor.is_gnu();
2663 for (args, args_json) in [
2664 (&self.pre_link_args, &mut self.pre_link_args_json),
2665 (&self.late_link_args, &mut self.late_link_args_json),
2666 (&self.late_link_args_dynamic, &mut self.late_link_args_dynamic_json),
2667 (&self.late_link_args_static, &mut self.late_link_args_static_json),
2668 (&self.post_link_args, &mut self.post_link_args_json),
2669 ] {
2670 *args_json = args
2671 .iter()
2672 .map(|(flavor, args)| (flavor.to_cli_counterpart(), args.clone()))
2673 .collect();
2674 }
2675 }
2676}
2677
2678impl Default for TargetOptions {
2679 fn default() -> TargetOptions {
2682 TargetOptions {
2683 endian: Endian::Little,
2684 c_int_width: 32,
2685 os: Os::None,
2686 env: Env::Unspecified,
2687 abi: Abi::Unspecified,
2688 vendor: "unknown".into(),
2689 linker: option_env!("CFG_DEFAULT_LINKER").map(|s| s.into()),
2690 linker_flavor: LinkerFlavor::Gnu(Cc::Yes, Lld::No),
2691 linker_flavor_json: LinkerFlavorCli::Gcc,
2692 lld_flavor_json: LldFlavor::Ld,
2693 linker_is_gnu_json: true,
2694 link_script: None,
2695 asm_args: cvs![],
2696 cpu: "generic".into(),
2697 need_explicit_cpu: false,
2698 features: "".into(),
2699 direct_access_external_data: None,
2700 dynamic_linking: false,
2701 dll_tls_export: true,
2702 only_cdylib: false,
2703 executables: true,
2704 relocation_model: RelocModel::Pic,
2705 code_model: None,
2706 tls_model: TlsModel::GeneralDynamic,
2707 disable_redzone: false,
2708 frame_pointer: FramePointer::MayOmit,
2709 function_sections: true,
2710 dll_prefix: "lib".into(),
2711 dll_suffix: ".so".into(),
2712 exe_suffix: "".into(),
2713 staticlib_prefix: "lib".into(),
2714 staticlib_suffix: ".a".into(),
2715 families: cvs![],
2716 abi_return_struct_as_int: false,
2717 is_like_aix: false,
2718 is_like_darwin: false,
2719 is_like_gpu: false,
2720 is_like_solaris: false,
2721 is_like_windows: false,
2722 is_like_msvc: false,
2723 is_like_wasm: false,
2724 is_like_android: false,
2725 is_like_vexos: false,
2726 binary_format: BinaryFormat::Elf,
2727 default_dwarf_version: 4,
2728 allows_weak_linkage: true,
2729 has_rpath: false,
2730 no_default_libraries: true,
2731 position_independent_executables: false,
2732 static_position_independent_executables: false,
2733 plt_by_default: true,
2734 relro_level: RelroLevel::None,
2735 pre_link_objects: Default::default(),
2736 post_link_objects: Default::default(),
2737 pre_link_objects_self_contained: Default::default(),
2738 post_link_objects_self_contained: Default::default(),
2739 link_self_contained: LinkSelfContainedDefault::False,
2740 pre_link_args: LinkArgs::new(),
2741 pre_link_args_json: LinkArgsCli::new(),
2742 late_link_args: LinkArgs::new(),
2743 late_link_args_json: LinkArgsCli::new(),
2744 late_link_args_dynamic: LinkArgs::new(),
2745 late_link_args_dynamic_json: LinkArgsCli::new(),
2746 late_link_args_static: LinkArgs::new(),
2747 late_link_args_static_json: LinkArgsCli::new(),
2748 post_link_args: LinkArgs::new(),
2749 post_link_args_json: LinkArgsCli::new(),
2750 link_env: cvs![],
2751 link_env_remove: cvs![],
2752 archive_format: "gnu".into(),
2753 main_needs_argc_argv: true,
2754 allow_asm: true,
2755 has_thread_local: false,
2756 obj_is_bitcode: false,
2757 min_atomic_width: None,
2758 max_atomic_width: None,
2759 atomic_cas: true,
2760 panic_strategy: PanicStrategy::Unwind,
2761 crt_static_allows_dylibs: false,
2762 crt_static_default: false,
2763 crt_static_respected: false,
2764 stack_probes: StackProbeType::None,
2765 min_global_align: None,
2766 default_codegen_units: None,
2767 default_codegen_backend: None,
2768 trap_unreachable: true,
2769 requires_lto: false,
2770 singlethread: false,
2771 no_builtins: false,
2772 default_visibility: None,
2773 emit_debug_gdb_scripts: true,
2774 requires_uwtable: false,
2775 default_uwtable: false,
2776 simd_types_indirect: true,
2777 limit_rdylib_exports: true,
2778 override_export_symbols: None,
2779 merge_functions: MergeFunctions::Aliases,
2780 mcount: "mcount".into(),
2781 llvm_mcount_intrinsic: None,
2782 llvm_abiname: "".into(),
2783 llvm_floatabi: None,
2784 rustc_abi: None,
2785 relax_elf_relocations: false,
2786 llvm_args: cvs![],
2787 use_ctors_section: false,
2788 eh_frame_header: true,
2789 has_thumb_interworking: false,
2790 debuginfo_kind: Default::default(),
2791 split_debuginfo: Default::default(),
2792 supported_split_debuginfo: Cow::Borrowed(&[SplitDebuginfo::Off]),
2794 supported_sanitizers: SanitizerSet::empty(),
2795 default_sanitizers: SanitizerSet::empty(),
2796 c_enum_min_bits: None,
2797 generate_arange_section: true,
2798 supports_stack_protector: true,
2799 entry_name: "main".into(),
2800 entry_abi: CanonAbi::C,
2801 supports_xray: false,
2802 default_address_space: rustc_abi::AddressSpace::ZERO,
2803 small_data_threshold_support: SmallDataThresholdSupport::DefaultForArch,
2804 }
2805 }
2806}
2807
2808impl Deref for Target {
2812 type Target = TargetOptions;
2813
2814 #[inline]
2815 fn deref(&self) -> &Self::Target {
2816 &self.options
2817 }
2818}
2819impl DerefMut for Target {
2820 #[inline]
2821 fn deref_mut(&mut self) -> &mut Self::Target {
2822 &mut self.options
2823 }
2824}
2825
2826impl Target {
2827 pub fn is_abi_supported(&self, abi: ExternAbi) -> bool {
2828 let abi_map = AbiMap::from_target(self);
2829 abi_map.canonize_abi(abi, false).is_mapped()
2830 }
2831
2832 pub fn min_atomic_width(&self) -> u64 {
2835 self.min_atomic_width.unwrap_or(8)
2836 }
2837
2838 pub fn max_atomic_width(&self) -> u64 {
2841 self.max_atomic_width.unwrap_or_else(|| self.pointer_width.into())
2842 }
2843
2844 fn check_consistency(&self, kind: TargetKind) -> Result<(), String> {
2847 macro_rules! check {
2848 ($b:expr, $($msg:tt)*) => {
2849 if !$b {
2850 return Err(format!($($msg)*));
2851 }
2852 }
2853 }
2854 macro_rules! check_eq {
2855 ($left:expr, $right:expr, $($msg:tt)*) => {
2856 if ($left) != ($right) {
2857 return Err(format!($($msg)*));
2858 }
2859 }
2860 }
2861 macro_rules! check_ne {
2862 ($left:expr, $right:expr, $($msg:tt)*) => {
2863 if ($left) == ($right) {
2864 return Err(format!($($msg)*));
2865 }
2866 }
2867 }
2868 macro_rules! check_matches {
2869 ($left:expr, $right:pat, $($msg:tt)*) => {
2870 if !matches!($left, $right) {
2871 return Err(format!($($msg)*));
2872 }
2873 }
2874 }
2875
2876 check_eq!(
2877 self.is_like_darwin,
2878 self.vendor == "apple",
2879 "`is_like_darwin` must be set if and only if `vendor` is `apple`"
2880 );
2881 check_eq!(
2882 self.is_like_solaris,
2883 matches!(self.os, Os::Solaris | Os::Illumos),
2884 "`is_like_solaris` must be set if and only if `os` is `solaris` or `illumos`"
2885 );
2886 check_eq!(
2887 self.is_like_gpu,
2888 self.arch == Arch::Nvptx64 || self.arch == Arch::AmdGpu,
2889 "`is_like_gpu` must be set if and only if `target` is `nvptx64` or `amdgcn`"
2890 );
2891 check_eq!(
2892 self.is_like_windows,
2893 matches!(self.os, Os::Windows | Os::Uefi | Os::Cygwin),
2894 "`is_like_windows` must be set if and only if `os` is `windows`, `uefi` or `cygwin`"
2895 );
2896 check_eq!(
2897 self.is_like_wasm,
2898 matches!(self.arch, Arch::Wasm32 | Arch::Wasm64),
2899 "`is_like_wasm` must be set if and only if `arch` is `wasm32` or `wasm64`"
2900 );
2901 if self.is_like_msvc {
2902 check!(self.is_like_windows, "if `is_like_msvc` is set, `is_like_windows` must be set");
2903 }
2904 if self.os == Os::Emscripten {
2905 check!(self.is_like_wasm, "the `emcscripten` os only makes sense on wasm-like targets");
2906 }
2907
2908 check_eq!(
2910 self.is_like_darwin,
2911 matches!(self.linker_flavor, LinkerFlavor::Darwin(..)),
2912 "`linker_flavor` must be `darwin` if and only if `is_like_darwin` is set"
2913 );
2914 check_eq!(
2915 self.is_like_msvc,
2916 matches!(self.linker_flavor, LinkerFlavor::Msvc(..)),
2917 "`linker_flavor` must be `msvc` if and only if `is_like_msvc` is set"
2918 );
2919 check_eq!(
2920 self.is_like_wasm && self.os != Os::Emscripten,
2921 matches!(self.linker_flavor, LinkerFlavor::WasmLld(..)),
2922 "`linker_flavor` must be `wasm-lld` if and only if `is_like_wasm` is set and the `os` is not `emscripten`",
2923 );
2924 check_eq!(
2925 self.os == Os::Emscripten,
2926 matches!(self.linker_flavor, LinkerFlavor::EmCc),
2927 "`linker_flavor` must be `em-cc` if and only if `os` is `emscripten`"
2928 );
2929 check_eq!(
2930 self.arch == Arch::Bpf,
2931 matches!(self.linker_flavor, LinkerFlavor::Bpf),
2932 "`linker_flavor` must be `bpf` if and only if `arch` is `bpf`"
2933 );
2934 check_eq!(
2935 self.arch == Arch::Nvptx64,
2936 matches!(self.linker_flavor, LinkerFlavor::Ptx),
2937 "`linker_flavor` must be `ptc` if and only if `arch` is `nvptx64`"
2938 );
2939
2940 for args in [
2941 &self.pre_link_args,
2942 &self.late_link_args,
2943 &self.late_link_args_dynamic,
2944 &self.late_link_args_static,
2945 &self.post_link_args,
2946 ] {
2947 for (&flavor, flavor_args) in args {
2948 check!(
2949 !flavor_args.is_empty() || self.arch == Arch::Avr,
2950 "linker flavor args must not be empty"
2951 );
2952 match self.linker_flavor {
2954 LinkerFlavor::Gnu(..) => {
2955 check_matches!(
2956 flavor,
2957 LinkerFlavor::Gnu(..),
2958 "mixing GNU and non-GNU linker flavors"
2959 );
2960 }
2961 LinkerFlavor::Darwin(..) => {
2962 check_matches!(
2963 flavor,
2964 LinkerFlavor::Darwin(..),
2965 "mixing Darwin and non-Darwin linker flavors"
2966 )
2967 }
2968 LinkerFlavor::WasmLld(..) => {
2969 check_matches!(
2970 flavor,
2971 LinkerFlavor::WasmLld(..),
2972 "mixing wasm and non-wasm linker flavors"
2973 )
2974 }
2975 LinkerFlavor::Unix(..) => {
2976 check_matches!(
2977 flavor,
2978 LinkerFlavor::Unix(..),
2979 "mixing unix and non-unix linker flavors"
2980 );
2981 }
2982 LinkerFlavor::Msvc(..) => {
2983 check_matches!(
2984 flavor,
2985 LinkerFlavor::Msvc(..),
2986 "mixing MSVC and non-MSVC linker flavors"
2987 );
2988 }
2989 LinkerFlavor::EmCc
2990 | LinkerFlavor::Bpf
2991 | LinkerFlavor::Ptx
2992 | LinkerFlavor::Llbc => {
2993 check_eq!(flavor, self.linker_flavor, "mixing different linker flavors")
2994 }
2995 }
2996
2997 let check_noncc = |noncc_flavor| -> Result<(), String> {
2999 if let Some(noncc_args) = args.get(&noncc_flavor) {
3000 for arg in flavor_args {
3001 if let Some(suffix) = arg.strip_prefix("-Wl,") {
3002 check!(
3003 noncc_args.iter().any(|a| a == suffix),
3004 " link args for cc and non-cc versions of flavors are not consistent"
3005 );
3006 }
3007 }
3008 }
3009 Ok(())
3010 };
3011
3012 match self.linker_flavor {
3013 LinkerFlavor::Gnu(Cc::Yes, lld) => check_noncc(LinkerFlavor::Gnu(Cc::No, lld))?,
3014 LinkerFlavor::WasmLld(Cc::Yes) => check_noncc(LinkerFlavor::WasmLld(Cc::No))?,
3015 LinkerFlavor::Unix(Cc::Yes) => check_noncc(LinkerFlavor::Unix(Cc::No))?,
3016 _ => {}
3017 }
3018 }
3019
3020 for cc in [Cc::No, Cc::Yes] {
3022 check_eq!(
3023 args.get(&LinkerFlavor::Gnu(cc, Lld::No)),
3024 args.get(&LinkerFlavor::Gnu(cc, Lld::Yes)),
3025 "link args for lld and non-lld versions of flavors are not consistent",
3026 );
3027 check_eq!(
3028 args.get(&LinkerFlavor::Darwin(cc, Lld::No)),
3029 args.get(&LinkerFlavor::Darwin(cc, Lld::Yes)),
3030 "link args for lld and non-lld versions of flavors are not consistent",
3031 );
3032 }
3033 check_eq!(
3034 args.get(&LinkerFlavor::Msvc(Lld::No)),
3035 args.get(&LinkerFlavor::Msvc(Lld::Yes)),
3036 "link args for lld and non-lld versions of flavors are not consistent",
3037 );
3038 }
3039
3040 if self.link_self_contained.is_disabled() {
3041 check!(
3042 self.pre_link_objects_self_contained.is_empty()
3043 && self.post_link_objects_self_contained.is_empty(),
3044 "if `link_self_contained` is disabled, then `pre_link_objects_self_contained` and `post_link_objects_self_contained` must be empty",
3045 );
3046 }
3047
3048 check_ne!(self.vendor, "", "`vendor` cannot be empty");
3052 if let Os::Other(s) = &self.os {
3053 check!(!s.is_empty(), "`os` cannot be empty");
3054 }
3055 if !self.can_use_os_unknown() {
3056 check_ne!(
3058 self.os,
3059 Os::Unknown,
3060 "`unknown` os can only be used on particular targets; use `none` for bare-metal targets"
3061 );
3062 }
3063
3064 if kind == TargetKind::Builtin {
3070 if self.os == Os::None
3074 && !matches!(self.arch, Arch::Bpf | Arch::Hexagon | Arch::Wasm32 | Arch::Wasm64)
3075 {
3076 check!(
3077 !self.dynamic_linking,
3078 "dynamic linking is not supported on this OS/architecture"
3079 );
3080 }
3081 if self.only_cdylib
3082 || self.crt_static_allows_dylibs
3083 || !self.late_link_args_dynamic.is_empty()
3084 {
3085 check!(
3086 self.dynamic_linking,
3087 "dynamic linking must be allowed when `only_cdylib` or `crt_static_allows_dylibs` or `late_link_args_dynamic` are set"
3088 );
3089 }
3090 if self.dynamic_linking && !self.is_like_wasm {
3092 check_eq!(
3093 self.relocation_model,
3094 RelocModel::Pic,
3095 "targets that support dynamic linking must use the `pic` relocation model"
3096 );
3097 }
3098 if self.position_independent_executables {
3099 check_eq!(
3100 self.relocation_model,
3101 RelocModel::Pic,
3102 "targets that support position-independent executables must use the `pic` relocation model"
3103 );
3104 }
3105 if self.relocation_model == RelocModel::Pic && self.os != Os::Uefi {
3107 check!(
3108 self.dynamic_linking || self.position_independent_executables,
3109 "when the relocation model is `pic`, the target must support dynamic linking or use position-independent executables. \
3110 Set the relocation model to `static` to avoid this requirement"
3111 );
3112 }
3113 if self.static_position_independent_executables {
3114 check!(
3115 self.position_independent_executables,
3116 "if `static_position_independent_executables` is set, then `position_independent_executables` must be set"
3117 );
3118 }
3119 if self.position_independent_executables {
3120 check!(
3121 self.executables,
3122 "if `position_independent_executables` is set then `executables` must be set"
3123 );
3124 }
3125 }
3126
3127 if self.crt_static_default || self.crt_static_allows_dylibs {
3129 check!(
3130 self.crt_static_respected,
3131 "static CRT can be enabled but `crt_static_respected` is not set"
3132 );
3133 }
3134
3135 match self.arch {
3138 Arch::RiscV32 => {
3139 check_matches!(
3140 &*self.llvm_abiname,
3141 "ilp32" | "ilp32f" | "ilp32d" | "ilp32e",
3142 "invalid RISC-V ABI name: {}",
3143 self.llvm_abiname,
3144 );
3145 }
3146 Arch::RiscV64 => {
3147 check_matches!(
3149 &*self.llvm_abiname,
3150 "lp64" | "lp64f" | "lp64d" | "lp64e",
3151 "invalid RISC-V ABI name: {}",
3152 self.llvm_abiname,
3153 );
3154 }
3155 Arch::Arm => {
3156 check!(
3157 self.llvm_floatabi.is_some(),
3158 "ARM targets must set `llvm-floatabi` to `hard` or `soft`",
3159 )
3160 }
3161 _ => {}
3162 }
3163
3164 if let Some(rust_abi) = self.rustc_abi {
3166 match rust_abi {
3167 RustcAbi::X86Sse2 => check_matches!(
3168 self.arch,
3169 Arch::X86,
3170 "`x86-sse2` ABI is only valid for x86-32 targets"
3171 ),
3172 RustcAbi::X86Softfloat => check_matches!(
3173 self.arch,
3174 Arch::X86 | Arch::X86_64,
3175 "`x86-softfloat` ABI is only valid for x86 targets"
3176 ),
3177 }
3178 }
3179
3180 if !self.features.is_empty() {
3182 let mut features_enabled = FxHashSet::default();
3183 let mut features_disabled = FxHashSet::default();
3184 for feat in self.features.split(',') {
3185 if let Some(feat) = feat.strip_prefix("+") {
3186 features_enabled.insert(feat);
3187 if features_disabled.contains(feat) {
3188 return Err(format!(
3189 "target feature `{feat}` is both enabled and disabled"
3190 ));
3191 }
3192 } else if let Some(feat) = feat.strip_prefix("-") {
3193 features_disabled.insert(feat);
3194 if features_enabled.contains(feat) {
3195 return Err(format!(
3196 "target feature `{feat}` is both enabled and disabled"
3197 ));
3198 }
3199 } else {
3200 return Err(format!(
3201 "target feature `{feat}` is invalid, must start with `+` or `-`"
3202 ));
3203 }
3204 }
3205 let abi_feature_constraints = self.abi_required_features();
3207 for feat in abi_feature_constraints.required {
3208 if features_disabled.contains(feat) {
3211 return Err(format!(
3212 "target feature `{feat}` is required by the ABI but gets disabled in target spec"
3213 ));
3214 }
3215 }
3216 for feat in abi_feature_constraints.incompatible {
3217 if features_enabled.contains(feat) {
3220 return Err(format!(
3221 "target feature `{feat}` is incompatible with the ABI but gets enabled in target spec"
3222 ));
3223 }
3224 }
3225 }
3226
3227 Ok(())
3228 }
3229
3230 #[cfg(test)]
3232 fn test_target(mut self) {
3233 let recycled_target =
3234 Target::from_json(&serde_json::to_string(&self.to_json()).unwrap()).map(|(j, _)| j);
3235 self.update_to_cli();
3236 self.check_consistency(TargetKind::Builtin).unwrap();
3237 assert_eq!(recycled_target, Ok(self));
3238 }
3239
3240 fn can_use_os_unknown(&self) -> bool {
3243 self.llvm_target == "wasm32-unknown-unknown"
3244 || self.llvm_target == "wasm64-unknown-unknown"
3245 || (self.env == Env::Sgx && self.vendor == "fortanix")
3246 }
3247
3248 pub fn expect_builtin(target_tuple: &TargetTuple) -> Target {
3250 match *target_tuple {
3251 TargetTuple::TargetTuple(ref target_tuple) => {
3252 load_builtin(target_tuple).expect("built-in target")
3253 }
3254 TargetTuple::TargetJson { .. } => {
3255 panic!("built-in targets doesn't support target-paths")
3256 }
3257 }
3258 }
3259
3260 pub fn builtins() -> impl Iterator<Item = Target> {
3262 load_all_builtins()
3263 }
3264
3265 pub fn search(
3275 target_tuple: &TargetTuple,
3276 sysroot: &Path,
3277 ) -> Result<(Target, TargetWarnings), String> {
3278 use std::{env, fs};
3279
3280 fn load_file(path: &Path) -> Result<(Target, TargetWarnings), String> {
3281 let contents = fs::read_to_string(path).map_err(|e| e.to_string())?;
3282 Target::from_json(&contents)
3283 }
3284
3285 match *target_tuple {
3286 TargetTuple::TargetTuple(ref target_tuple) => {
3287 if let Some(t) = load_builtin(target_tuple) {
3289 return Ok((t, TargetWarnings::empty()));
3290 }
3291
3292 let path = {
3294 let mut target = target_tuple.to_string();
3295 target.push_str(".json");
3296 PathBuf::from(target)
3297 };
3298
3299 let target_path = env::var_os("RUST_TARGET_PATH").unwrap_or_default();
3300
3301 for dir in env::split_paths(&target_path) {
3302 let p = dir.join(&path);
3303 if p.is_file() {
3304 return load_file(&p);
3305 }
3306 }
3307
3308 let rustlib_path = crate::relative_target_rustlib_path(sysroot, target_tuple);
3311 let p = PathBuf::from_iter([
3312 Path::new(sysroot),
3313 Path::new(&rustlib_path),
3314 Path::new("target.json"),
3315 ]);
3316 if p.is_file() {
3317 return load_file(&p);
3318 }
3319
3320 Err(format!("could not find specification for target {target_tuple:?}"))
3321 }
3322 TargetTuple::TargetJson { ref contents, .. } => Target::from_json(contents),
3323 }
3324 }
3325
3326 pub fn small_data_threshold_support(&self) -> SmallDataThresholdSupport {
3329 match &self.options.small_data_threshold_support {
3330 SmallDataThresholdSupport::DefaultForArch => match self.arch {
3334 Arch::Mips | Arch::Mips64 | Arch::Mips32r6 => {
3335 SmallDataThresholdSupport::LlvmArg("mips-ssection-threshold".into())
3336 }
3337 Arch::Hexagon => {
3338 SmallDataThresholdSupport::LlvmArg("hexagon-small-data-threshold".into())
3339 }
3340 Arch::M68k => SmallDataThresholdSupport::LlvmArg("m68k-ssection-threshold".into()),
3341 Arch::RiscV32 | Arch::RiscV64 => {
3342 SmallDataThresholdSupport::LlvmModuleFlag("SmallDataLimit".into())
3343 }
3344 _ => SmallDataThresholdSupport::None,
3345 },
3346 s => s.clone(),
3347 }
3348 }
3349
3350 pub fn object_architecture(
3351 &self,
3352 unstable_target_features: &FxIndexSet<Symbol>,
3353 ) -> Option<(object::Architecture, Option<object::SubArchitecture>)> {
3354 use object::Architecture;
3355 Some(match self.arch {
3356 Arch::Arm => (Architecture::Arm, None),
3357 Arch::AArch64 => (
3358 if self.pointer_width == 32 {
3359 Architecture::Aarch64_Ilp32
3360 } else {
3361 Architecture::Aarch64
3362 },
3363 None,
3364 ),
3365 Arch::X86 => (Architecture::I386, None),
3366 Arch::S390x => (Architecture::S390x, None),
3367 Arch::M68k => (Architecture::M68k, None),
3368 Arch::Mips | Arch::Mips32r6 => (Architecture::Mips, None),
3369 Arch::Mips64 | Arch::Mips64r6 => (
3370 if self.options.llvm_abiname.as_ref() == "n32" {
3376 Architecture::Mips64_N32
3377 } else {
3378 Architecture::Mips64
3379 },
3380 None,
3381 ),
3382 Arch::X86_64 => (
3383 if self.pointer_width == 32 {
3384 Architecture::X86_64_X32
3385 } else {
3386 Architecture::X86_64
3387 },
3388 None,
3389 ),
3390 Arch::PowerPC => (Architecture::PowerPc, None),
3391 Arch::PowerPC64 => (Architecture::PowerPc64, None),
3392 Arch::RiscV32 => (Architecture::Riscv32, None),
3393 Arch::RiscV64 => (Architecture::Riscv64, None),
3394 Arch::Sparc => {
3395 if unstable_target_features.contains(&sym::v8plus) {
3396 (Architecture::Sparc32Plus, None)
3398 } else {
3399 (Architecture::Sparc, None)
3401 }
3402 }
3403 Arch::Sparc64 => (Architecture::Sparc64, None),
3404 Arch::Avr => (Architecture::Avr, None),
3405 Arch::Msp430 => (Architecture::Msp430, None),
3406 Arch::Hexagon => (Architecture::Hexagon, None),
3407 Arch::Xtensa => (Architecture::Xtensa, None),
3408 Arch::Bpf => (Architecture::Bpf, None),
3409 Arch::LoongArch32 => (Architecture::LoongArch32, None),
3410 Arch::LoongArch64 => (Architecture::LoongArch64, None),
3411 Arch::CSky => (Architecture::Csky, None),
3412 Arch::Arm64EC => (Architecture::Aarch64, Some(object::SubArchitecture::Arm64EC)),
3413 Arch::AmdGpu
3414 | Arch::Nvptx64
3415 | Arch::PowerPC64LE
3416 | Arch::SpirV
3417 | Arch::Wasm32
3418 | Arch::Wasm64
3419 | Arch::Other(_) => return None,
3420 })
3421 }
3422
3423 pub fn max_reliable_alignment(&self) -> Align {
3432 if self.is_like_windows && self.arch == Arch::X86 {
3436 Align::from_bytes(4).unwrap()
3437 } else {
3438 Align::MAX
3439 }
3440 }
3441
3442 pub fn vendor_symbol(&self) -> Symbol {
3443 Symbol::intern(&self.vendor)
3444 }
3445}
3446
3447#[derive(Clone, Debug)]
3449pub enum TargetTuple {
3450 TargetTuple(String),
3451 TargetJson {
3452 path_for_rustdoc: PathBuf,
3455 tuple: String,
3456 contents: String,
3457 },
3458}
3459
3460impl PartialEq for TargetTuple {
3462 fn eq(&self, other: &Self) -> bool {
3463 match (self, other) {
3464 (Self::TargetTuple(l0), Self::TargetTuple(r0)) => l0 == r0,
3465 (
3466 Self::TargetJson { path_for_rustdoc: _, tuple: l_tuple, contents: l_contents },
3467 Self::TargetJson { path_for_rustdoc: _, tuple: r_tuple, contents: r_contents },
3468 ) => l_tuple == r_tuple && l_contents == r_contents,
3469 _ => false,
3470 }
3471 }
3472}
3473
3474impl Hash for TargetTuple {
3476 fn hash<H: Hasher>(&self, state: &mut H) -> () {
3477 match self {
3478 TargetTuple::TargetTuple(tuple) => {
3479 0u8.hash(state);
3480 tuple.hash(state)
3481 }
3482 TargetTuple::TargetJson { path_for_rustdoc: _, tuple, contents } => {
3483 1u8.hash(state);
3484 tuple.hash(state);
3485 contents.hash(state)
3486 }
3487 }
3488 }
3489}
3490
3491impl<S: Encoder> Encodable<S> for TargetTuple {
3493 fn encode(&self, s: &mut S) {
3494 match self {
3495 TargetTuple::TargetTuple(tuple) => {
3496 s.emit_u8(0);
3497 s.emit_str(tuple);
3498 }
3499 TargetTuple::TargetJson { path_for_rustdoc: _, tuple, contents } => {
3500 s.emit_u8(1);
3501 s.emit_str(tuple);
3502 s.emit_str(contents);
3503 }
3504 }
3505 }
3506}
3507
3508impl<D: Decoder> Decodable<D> for TargetTuple {
3509 fn decode(d: &mut D) -> Self {
3510 match d.read_u8() {
3511 0 => TargetTuple::TargetTuple(d.read_str().to_owned()),
3512 1 => TargetTuple::TargetJson {
3513 path_for_rustdoc: PathBuf::new(),
3514 tuple: d.read_str().to_owned(),
3515 contents: d.read_str().to_owned(),
3516 },
3517 _ => {
3518 panic!("invalid enum variant tag while decoding `TargetTuple`, expected 0..2");
3519 }
3520 }
3521 }
3522}
3523
3524impl TargetTuple {
3525 pub fn from_tuple(tuple: &str) -> Self {
3527 TargetTuple::TargetTuple(tuple.into())
3528 }
3529
3530 pub fn from_path(path: &Path) -> Result<Self, io::Error> {
3532 let canonicalized_path = try_canonicalize(path)?;
3533 let contents = std::fs::read_to_string(&canonicalized_path).map_err(|err| {
3534 io::Error::new(
3535 io::ErrorKind::InvalidInput,
3536 format!("target path {canonicalized_path:?} is not a valid file: {err}"),
3537 )
3538 })?;
3539 let tuple = canonicalized_path
3540 .file_stem()
3541 .expect("target path must not be empty")
3542 .to_str()
3543 .expect("target path must be valid unicode")
3544 .to_owned();
3545 Ok(TargetTuple::TargetJson { path_for_rustdoc: canonicalized_path, tuple, contents })
3546 }
3547
3548 pub fn tuple(&self) -> &str {
3552 match *self {
3553 TargetTuple::TargetTuple(ref tuple) | TargetTuple::TargetJson { ref tuple, .. } => {
3554 tuple
3555 }
3556 }
3557 }
3558
3559 pub fn debug_tuple(&self) -> String {
3564 use std::hash::DefaultHasher;
3565
3566 match self {
3567 TargetTuple::TargetTuple(tuple) => tuple.to_owned(),
3568 TargetTuple::TargetJson { path_for_rustdoc: _, tuple, contents: content } => {
3569 let mut hasher = DefaultHasher::new();
3570 content.hash(&mut hasher);
3571 let hash = hasher.finish();
3572 format!("{tuple}-{hash}")
3573 }
3574 }
3575 }
3576}
3577
3578impl fmt::Display for TargetTuple {
3579 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3580 write!(f, "{}", self.debug_tuple())
3581 }
3582}
3583
3584into_diag_arg_using_display!(&TargetTuple);