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 }
838
839 parse_error_type = "panic strategy";
840}
841
842#[derive(Clone, Copy, Debug, PartialEq, Hash, Encodable, Decodable, HashStable_Generic)]
843pub enum OnBrokenPipe {
844 Default,
845 Kill,
846 Error,
847 Inherit,
848}
849
850impl PanicStrategy {
851 pub const fn desc_symbol(&self) -> Symbol {
852 match *self {
853 PanicStrategy::Unwind => sym::unwind,
854 PanicStrategy::Abort => sym::abort,
855 }
856 }
857
858 pub const fn all() -> [Symbol; 2] {
859 [Self::Abort.desc_symbol(), Self::Unwind.desc_symbol()]
860 }
861}
862
863crate::target_spec_enum! {
864 pub enum RelroLevel {
865 Full = "full",
866 Partial = "partial",
867 Off = "off",
868 None = "none",
869 }
870
871 parse_error_type = "relro level";
872}
873
874impl IntoDiagArg for PanicStrategy {
875 fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
876 DiagArgValue::Str(Cow::Owned(self.desc().to_string()))
877 }
878}
879
880crate::target_spec_enum! {
881 pub enum SymbolVisibility {
882 Hidden = "hidden",
883 Protected = "protected",
884 Interposable = "interposable",
885 }
886
887 parse_error_type = "symbol visibility";
888}
889
890#[derive(Clone, Debug, PartialEq, Hash)]
891pub enum SmallDataThresholdSupport {
892 None,
893 DefaultForArch,
894 LlvmModuleFlag(StaticCow<str>),
895 LlvmArg(StaticCow<str>),
896}
897
898impl FromStr for SmallDataThresholdSupport {
899 type Err = String;
900
901 fn from_str(s: &str) -> Result<Self, Self::Err> {
902 if s == "none" {
903 Ok(Self::None)
904 } else if s == "default-for-arch" {
905 Ok(Self::DefaultForArch)
906 } else if let Some(flag) = s.strip_prefix("llvm-module-flag=") {
907 Ok(Self::LlvmModuleFlag(flag.to_string().into()))
908 } else if let Some(arg) = s.strip_prefix("llvm-arg=") {
909 Ok(Self::LlvmArg(arg.to_string().into()))
910 } else {
911 Err(format!("'{s}' is not a valid value for small-data-threshold-support."))
912 }
913 }
914}
915
916crate::json::serde_deserialize_from_str!(SmallDataThresholdSupport);
917impl schemars::JsonSchema for SmallDataThresholdSupport {
918 fn schema_name() -> std::borrow::Cow<'static, str> {
919 "SmallDataThresholdSupport".into()
920 }
921 fn json_schema(_: &mut schemars::SchemaGenerator) -> schemars::Schema {
922 schemars::json_schema! ({
923 "type": "string",
924 "pattern": r#"^none|default-for-arch|llvm-module-flag=.+|llvm-arg=.+$"#,
925 })
926 .into()
927 }
928}
929
930impl ToJson for SmallDataThresholdSupport {
931 fn to_json(&self) -> Value {
932 match self {
933 Self::None => "none".to_json(),
934 Self::DefaultForArch => "default-for-arch".to_json(),
935 Self::LlvmModuleFlag(flag) => format!("llvm-module-flag={flag}").to_json(),
936 Self::LlvmArg(arg) => format!("llvm-arg={arg}").to_json(),
937 }
938 }
939}
940
941crate::target_spec_enum! {
942 pub enum MergeFunctions {
943 Disabled = "disabled",
944 Trampolines = "trampolines",
945 Aliases = "aliases",
946 }
947
948 parse_error_type = "value for merge-functions";
949}
950
951crate::target_spec_enum! {
952 pub enum RelocModel {
953 Static = "static",
954 Pic = "pic",
955 Pie = "pie",
956 DynamicNoPic = "dynamic-no-pic",
957 Ropi = "ropi",
958 Rwpi = "rwpi",
959 RopiRwpi = "ropi-rwpi",
960 }
961
962 parse_error_type = "relocation model";
963}
964
965impl RelocModel {
966 pub const fn desc_symbol(&self) -> Symbol {
967 match *self {
968 RelocModel::Static => kw::Static,
969 RelocModel::Pic => sym::pic,
970 RelocModel::Pie => sym::pie,
971 RelocModel::DynamicNoPic => sym::dynamic_no_pic,
972 RelocModel::Ropi => sym::ropi,
973 RelocModel::Rwpi => sym::rwpi,
974 RelocModel::RopiRwpi => sym::ropi_rwpi,
975 }
976 }
977
978 pub const fn all() -> [Symbol; 7] {
979 [
980 RelocModel::Static.desc_symbol(),
981 RelocModel::Pic.desc_symbol(),
982 RelocModel::Pie.desc_symbol(),
983 RelocModel::DynamicNoPic.desc_symbol(),
984 RelocModel::Ropi.desc_symbol(),
985 RelocModel::Rwpi.desc_symbol(),
986 RelocModel::RopiRwpi.desc_symbol(),
987 ]
988 }
989}
990
991crate::target_spec_enum! {
992 pub enum CodeModel {
993 Tiny = "tiny",
994 Small = "small",
995 Kernel = "kernel",
996 Medium = "medium",
997 Large = "large",
998 }
999
1000 parse_error_type = "code model";
1001}
1002
1003crate::target_spec_enum! {
1004 pub enum FloatAbi {
1006 Soft = "soft",
1007 Hard = "hard",
1008 }
1009
1010 parse_error_type = "float abi";
1011}
1012
1013crate::target_spec_enum! {
1014 pub enum RustcAbi {
1016 X86Sse2 = "x86-sse2",
1018 X86Softfloat = "x86-softfloat",
1020 }
1021
1022 parse_error_type = "rustc abi";
1023}
1024
1025crate::target_spec_enum! {
1026 pub enum TlsModel {
1027 GeneralDynamic = "global-dynamic",
1028 LocalDynamic = "local-dynamic",
1029 InitialExec = "initial-exec",
1030 LocalExec = "local-exec",
1031 Emulated = "emulated",
1032 }
1033
1034 parse_error_type = "TLS model";
1035}
1036
1037crate::target_spec_enum! {
1038 pub enum LinkOutputKind {
1040 DynamicNoPicExe = "dynamic-nopic-exe",
1042 DynamicPicExe = "dynamic-pic-exe",
1044 StaticNoPicExe = "static-nopic-exe",
1046 StaticPicExe = "static-pic-exe",
1048 DynamicDylib = "dynamic-dylib",
1050 StaticDylib = "static-dylib",
1052 WasiReactorExe = "wasi-reactor-exe",
1054 }
1055
1056 parse_error_type = "CRT object kind";
1057}
1058
1059impl LinkOutputKind {
1060 pub fn can_link_dylib(self) -> bool {
1061 match self {
1062 LinkOutputKind::StaticNoPicExe | LinkOutputKind::StaticPicExe => false,
1063 LinkOutputKind::DynamicNoPicExe
1064 | LinkOutputKind::DynamicPicExe
1065 | LinkOutputKind::DynamicDylib
1066 | LinkOutputKind::StaticDylib
1067 | LinkOutputKind::WasiReactorExe => true,
1068 }
1069 }
1070}
1071
1072pub type LinkArgs = BTreeMap<LinkerFlavor, Vec<StaticCow<str>>>;
1073pub type LinkArgsCli = BTreeMap<LinkerFlavorCli, Vec<StaticCow<str>>>;
1074
1075crate::target_spec_enum! {
1076 #[derive(Default)]
1081 pub enum DebuginfoKind {
1082 #[default]
1084 Dwarf = "dwarf",
1085 DwarfDsym = "dwarf-dsym",
1087 Pdb = "pdb",
1089 }
1090
1091 parse_error_type = "debuginfo kind";
1092}
1093
1094crate::target_spec_enum! {
1095 #[derive(Default)]
1096 pub enum SplitDebuginfo {
1097 #[default]
1105 Off = "off",
1106
1107 Packed = "packed",
1114
1115 Unpacked = "unpacked",
1122 }
1123
1124 parse_error_type = "split debuginfo";
1125}
1126
1127into_diag_arg_using_display!(SplitDebuginfo);
1128
1129#[derive(Clone, Debug, PartialEq, Eq, serde_derive::Deserialize, schemars::JsonSchema)]
1130#[serde(tag = "kind")]
1131#[serde(rename_all = "kebab-case")]
1132pub enum StackProbeType {
1133 None,
1135 Inline,
1139 Call,
1141 InlineOrCall {
1144 #[serde(rename = "min-llvm-version-for-inline")]
1145 min_llvm_version_for_inline: (u32, u32, u32),
1146 },
1147}
1148
1149impl ToJson for StackProbeType {
1150 fn to_json(&self) -> Json {
1151 Json::Object(match self {
1152 StackProbeType::None => {
1153 [(String::from("kind"), "none".to_json())].into_iter().collect()
1154 }
1155 StackProbeType::Inline => {
1156 [(String::from("kind"), "inline".to_json())].into_iter().collect()
1157 }
1158 StackProbeType::Call => {
1159 [(String::from("kind"), "call".to_json())].into_iter().collect()
1160 }
1161 StackProbeType::InlineOrCall { min_llvm_version_for_inline: (maj, min, patch) } => [
1162 (String::from("kind"), "inline-or-call".to_json()),
1163 (
1164 String::from("min-llvm-version-for-inline"),
1165 Json::Array(vec![maj.to_json(), min.to_json(), patch.to_json()]),
1166 ),
1167 ]
1168 .into_iter()
1169 .collect(),
1170 })
1171 }
1172}
1173
1174#[derive(Default, Clone, Copy, PartialEq, Eq, Hash, Encodable, Decodable, HashStable_Generic)]
1175pub struct SanitizerSet(u16);
1176bitflags::bitflags! {
1177 impl SanitizerSet: u16 {
1178 const ADDRESS = 1 << 0;
1179 const LEAK = 1 << 1;
1180 const MEMORY = 1 << 2;
1181 const THREAD = 1 << 3;
1182 const HWADDRESS = 1 << 4;
1183 const CFI = 1 << 5;
1184 const MEMTAG = 1 << 6;
1185 const SHADOWCALLSTACK = 1 << 7;
1186 const KCFI = 1 << 8;
1187 const KERNELADDRESS = 1 << 9;
1188 const SAFESTACK = 1 << 10;
1189 const DATAFLOW = 1 << 11;
1190 }
1191}
1192rustc_data_structures::external_bitflags_debug! { SanitizerSet }
1193
1194impl SanitizerSet {
1195 const MUTUALLY_EXCLUSIVE: &'static [(SanitizerSet, SanitizerSet)] = &[
1198 (SanitizerSet::ADDRESS, SanitizerSet::MEMORY),
1199 (SanitizerSet::ADDRESS, SanitizerSet::THREAD),
1200 (SanitizerSet::ADDRESS, SanitizerSet::HWADDRESS),
1201 (SanitizerSet::ADDRESS, SanitizerSet::MEMTAG),
1202 (SanitizerSet::ADDRESS, SanitizerSet::KERNELADDRESS),
1203 (SanitizerSet::ADDRESS, SanitizerSet::SAFESTACK),
1204 (SanitizerSet::LEAK, SanitizerSet::MEMORY),
1205 (SanitizerSet::LEAK, SanitizerSet::THREAD),
1206 (SanitizerSet::LEAK, SanitizerSet::KERNELADDRESS),
1207 (SanitizerSet::LEAK, SanitizerSet::SAFESTACK),
1208 (SanitizerSet::MEMORY, SanitizerSet::THREAD),
1209 (SanitizerSet::MEMORY, SanitizerSet::HWADDRESS),
1210 (SanitizerSet::MEMORY, SanitizerSet::KERNELADDRESS),
1211 (SanitizerSet::MEMORY, SanitizerSet::SAFESTACK),
1212 (SanitizerSet::THREAD, SanitizerSet::HWADDRESS),
1213 (SanitizerSet::THREAD, SanitizerSet::KERNELADDRESS),
1214 (SanitizerSet::THREAD, SanitizerSet::SAFESTACK),
1215 (SanitizerSet::HWADDRESS, SanitizerSet::MEMTAG),
1216 (SanitizerSet::HWADDRESS, SanitizerSet::KERNELADDRESS),
1217 (SanitizerSet::HWADDRESS, SanitizerSet::SAFESTACK),
1218 (SanitizerSet::CFI, SanitizerSet::KCFI),
1219 (SanitizerSet::MEMTAG, SanitizerSet::KERNELADDRESS),
1220 (SanitizerSet::KERNELADDRESS, SanitizerSet::SAFESTACK),
1221 ];
1222
1223 pub fn as_str(self) -> Option<&'static str> {
1227 Some(match self {
1228 SanitizerSet::ADDRESS => "address",
1229 SanitizerSet::CFI => "cfi",
1230 SanitizerSet::DATAFLOW => "dataflow",
1231 SanitizerSet::KCFI => "kcfi",
1232 SanitizerSet::KERNELADDRESS => "kernel-address",
1233 SanitizerSet::LEAK => "leak",
1234 SanitizerSet::MEMORY => "memory",
1235 SanitizerSet::MEMTAG => "memtag",
1236 SanitizerSet::SAFESTACK => "safestack",
1237 SanitizerSet::SHADOWCALLSTACK => "shadow-call-stack",
1238 SanitizerSet::THREAD => "thread",
1239 SanitizerSet::HWADDRESS => "hwaddress",
1240 _ => return None,
1241 })
1242 }
1243
1244 pub fn mutually_exclusive(self) -> Option<(SanitizerSet, SanitizerSet)> {
1245 Self::MUTUALLY_EXCLUSIVE
1246 .into_iter()
1247 .find(|&(a, b)| self.contains(*a) && self.contains(*b))
1248 .copied()
1249 }
1250}
1251
1252impl fmt::Display for SanitizerSet {
1254 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1255 let mut first = true;
1256 for s in *self {
1257 let name = s.as_str().unwrap_or_else(|| panic!("unrecognized sanitizer {s:?}"));
1258 if !first {
1259 f.write_str(", ")?;
1260 }
1261 f.write_str(name)?;
1262 first = false;
1263 }
1264 Ok(())
1265 }
1266}
1267
1268impl FromStr for SanitizerSet {
1269 type Err = String;
1270 fn from_str(s: &str) -> Result<Self, Self::Err> {
1271 Ok(match s {
1272 "address" => SanitizerSet::ADDRESS,
1273 "cfi" => SanitizerSet::CFI,
1274 "dataflow" => SanitizerSet::DATAFLOW,
1275 "kcfi" => SanitizerSet::KCFI,
1276 "kernel-address" => SanitizerSet::KERNELADDRESS,
1277 "leak" => SanitizerSet::LEAK,
1278 "memory" => SanitizerSet::MEMORY,
1279 "memtag" => SanitizerSet::MEMTAG,
1280 "safestack" => SanitizerSet::SAFESTACK,
1281 "shadow-call-stack" => SanitizerSet::SHADOWCALLSTACK,
1282 "thread" => SanitizerSet::THREAD,
1283 "hwaddress" => SanitizerSet::HWADDRESS,
1284 s => return Err(format!("unknown sanitizer {s}")),
1285 })
1286 }
1287}
1288
1289crate::json::serde_deserialize_from_str!(SanitizerSet);
1290impl schemars::JsonSchema for SanitizerSet {
1291 fn schema_name() -> std::borrow::Cow<'static, str> {
1292 "SanitizerSet".into()
1293 }
1294 fn json_schema(_: &mut schemars::SchemaGenerator) -> schemars::Schema {
1295 let all = Self::all().iter().map(|sanitizer| sanitizer.as_str()).collect::<Vec<_>>();
1296 schemars::json_schema! ({
1297 "type": "string",
1298 "enum": all,
1299 })
1300 .into()
1301 }
1302}
1303
1304impl ToJson for SanitizerSet {
1305 fn to_json(&self) -> Json {
1306 self.into_iter()
1307 .map(|v| Some(v.as_str()?.to_json()))
1308 .collect::<Option<Vec<_>>>()
1309 .unwrap_or_default()
1310 .to_json()
1311 }
1312}
1313
1314crate::target_spec_enum! {
1315 pub enum FramePointer {
1316 Always = "always",
1318 NonLeaf = "non-leaf",
1321 MayOmit = "may-omit",
1325 }
1326
1327 parse_error_type = "frame pointer";
1328}
1329
1330impl FramePointer {
1331 #[inline]
1334 pub fn ratchet(&mut self, rhs: FramePointer) -> FramePointer {
1335 *self = match (*self, rhs) {
1336 (FramePointer::Always, _) | (_, FramePointer::Always) => FramePointer::Always,
1337 (FramePointer::NonLeaf, _) | (_, FramePointer::NonLeaf) => FramePointer::NonLeaf,
1338 _ => FramePointer::MayOmit,
1339 };
1340 *self
1341 }
1342}
1343
1344crate::target_spec_enum! {
1345 pub enum StackProtector {
1347 None = "none",
1349
1350 Basic = "basic",
1355
1356 Strong = "strong",
1361
1362 All = "all",
1364 }
1365
1366 parse_error_type = "stack protector";
1367}
1368
1369into_diag_arg_using_display!(StackProtector);
1370
1371crate::target_spec_enum! {
1372 pub enum BinaryFormat {
1373 Coff = "coff",
1374 Elf = "elf",
1375 MachO = "mach-o",
1376 Wasm = "wasm",
1377 Xcoff = "xcoff",
1378 }
1379
1380 parse_error_type = "binary format";
1381}
1382
1383impl BinaryFormat {
1384 pub fn to_object(&self) -> object::BinaryFormat {
1386 match self {
1387 Self::Coff => object::BinaryFormat::Coff,
1388 Self::Elf => object::BinaryFormat::Elf,
1389 Self::MachO => object::BinaryFormat::MachO,
1390 Self::Wasm => object::BinaryFormat::Wasm,
1391 Self::Xcoff => object::BinaryFormat::Xcoff,
1392 }
1393 }
1394}
1395
1396impl ToJson for Align {
1397 fn to_json(&self) -> Json {
1398 self.bits().to_json()
1399 }
1400}
1401
1402macro_rules! supported_targets {
1403 ( $(($tuple:literal, $module:ident),)+ ) => {
1404 mod targets {
1405 $(pub(crate) mod $module;)+
1406 }
1407
1408 pub static TARGETS: &[&str] = &[$($tuple),+];
1410
1411 fn load_builtin(target: &str) -> Option<Target> {
1412 let t = match target {
1413 $( $tuple => targets::$module::target(), )+
1414 _ => return None,
1415 };
1416 debug!("got builtin target: {:?}", t);
1417 Some(t)
1418 }
1419
1420 fn load_all_builtins() -> impl Iterator<Item = Target> {
1421 [
1422 $( targets::$module::target, )+
1423 ]
1424 .into_iter()
1425 .map(|f| f())
1426 }
1427
1428 #[cfg(test)]
1429 mod tests {
1430 $(
1432 #[test] fn $module() {
1434 crate::spec::targets::$module::target().test_target()
1435 }
1436 )+
1437 }
1438 };
1439}
1440
1441supported_targets! {
1442 ("x86_64-unknown-linux-gnu", x86_64_unknown_linux_gnu),
1443 ("x86_64-unknown-linux-gnux32", x86_64_unknown_linux_gnux32),
1444 ("i686-unknown-linux-gnu", i686_unknown_linux_gnu),
1445 ("i586-unknown-linux-gnu", i586_unknown_linux_gnu),
1446 ("loongarch64-unknown-linux-gnu", loongarch64_unknown_linux_gnu),
1447 ("loongarch64-unknown-linux-musl", loongarch64_unknown_linux_musl),
1448 ("m68k-unknown-linux-gnu", m68k_unknown_linux_gnu),
1449 ("m68k-unknown-none-elf", m68k_unknown_none_elf),
1450 ("csky-unknown-linux-gnuabiv2", csky_unknown_linux_gnuabiv2),
1451 ("csky-unknown-linux-gnuabiv2hf", csky_unknown_linux_gnuabiv2hf),
1452 ("mips-unknown-linux-gnu", mips_unknown_linux_gnu),
1453 ("mips64-unknown-linux-gnuabi64", mips64_unknown_linux_gnuabi64),
1454 ("mips64el-unknown-linux-gnuabi64", mips64el_unknown_linux_gnuabi64),
1455 ("mipsisa32r6-unknown-linux-gnu", mipsisa32r6_unknown_linux_gnu),
1456 ("mipsisa32r6el-unknown-linux-gnu", mipsisa32r6el_unknown_linux_gnu),
1457 ("mipsisa64r6-unknown-linux-gnuabi64", mipsisa64r6_unknown_linux_gnuabi64),
1458 ("mipsisa64r6el-unknown-linux-gnuabi64", mipsisa64r6el_unknown_linux_gnuabi64),
1459 ("mipsel-unknown-linux-gnu", mipsel_unknown_linux_gnu),
1460 ("powerpc-unknown-linux-gnu", powerpc_unknown_linux_gnu),
1461 ("powerpc-unknown-linux-gnuspe", powerpc_unknown_linux_gnuspe),
1462 ("powerpc-unknown-linux-musl", powerpc_unknown_linux_musl),
1463 ("powerpc-unknown-linux-muslspe", powerpc_unknown_linux_muslspe),
1464 ("powerpc64-ibm-aix", powerpc64_ibm_aix),
1465 ("powerpc64-unknown-linux-gnu", powerpc64_unknown_linux_gnu),
1466 ("powerpc64-unknown-linux-musl", powerpc64_unknown_linux_musl),
1467 ("powerpc64le-unknown-linux-gnu", powerpc64le_unknown_linux_gnu),
1468 ("powerpc64le-unknown-linux-musl", powerpc64le_unknown_linux_musl),
1469 ("s390x-unknown-linux-gnu", s390x_unknown_linux_gnu),
1470 ("s390x-unknown-linux-musl", s390x_unknown_linux_musl),
1471 ("sparc-unknown-linux-gnu", sparc_unknown_linux_gnu),
1472 ("sparc64-unknown-linux-gnu", sparc64_unknown_linux_gnu),
1473 ("arm-unknown-linux-gnueabi", arm_unknown_linux_gnueabi),
1474 ("arm-unknown-linux-gnueabihf", arm_unknown_linux_gnueabihf),
1475 ("armeb-unknown-linux-gnueabi", armeb_unknown_linux_gnueabi),
1476 ("arm-unknown-linux-musleabi", arm_unknown_linux_musleabi),
1477 ("arm-unknown-linux-musleabihf", arm_unknown_linux_musleabihf),
1478 ("armv4t-unknown-linux-gnueabi", armv4t_unknown_linux_gnueabi),
1479 ("armv5te-unknown-linux-gnueabi", armv5te_unknown_linux_gnueabi),
1480 ("armv5te-unknown-linux-musleabi", armv5te_unknown_linux_musleabi),
1481 ("armv5te-unknown-linux-uclibceabi", armv5te_unknown_linux_uclibceabi),
1482 ("armv7-unknown-linux-gnueabi", armv7_unknown_linux_gnueabi),
1483 ("armv7-unknown-linux-gnueabihf", armv7_unknown_linux_gnueabihf),
1484 ("thumbv7neon-unknown-linux-gnueabihf", thumbv7neon_unknown_linux_gnueabihf),
1485 ("thumbv7neon-unknown-linux-musleabihf", thumbv7neon_unknown_linux_musleabihf),
1486 ("armv7-unknown-linux-musleabi", armv7_unknown_linux_musleabi),
1487 ("armv7-unknown-linux-musleabihf", armv7_unknown_linux_musleabihf),
1488 ("aarch64-unknown-linux-gnu", aarch64_unknown_linux_gnu),
1489 ("aarch64-unknown-linux-musl", aarch64_unknown_linux_musl),
1490 ("aarch64_be-unknown-linux-musl", aarch64_be_unknown_linux_musl),
1491 ("x86_64-unknown-linux-musl", x86_64_unknown_linux_musl),
1492 ("i686-unknown-linux-musl", i686_unknown_linux_musl),
1493 ("i586-unknown-linux-musl", i586_unknown_linux_musl),
1494 ("mips-unknown-linux-musl", mips_unknown_linux_musl),
1495 ("mipsel-unknown-linux-musl", mipsel_unknown_linux_musl),
1496 ("mips64-unknown-linux-muslabi64", mips64_unknown_linux_muslabi64),
1497 ("mips64el-unknown-linux-muslabi64", mips64el_unknown_linux_muslabi64),
1498 ("hexagon-unknown-linux-musl", hexagon_unknown_linux_musl),
1499 ("hexagon-unknown-none-elf", hexagon_unknown_none_elf),
1500
1501 ("mips-unknown-linux-uclibc", mips_unknown_linux_uclibc),
1502 ("mipsel-unknown-linux-uclibc", mipsel_unknown_linux_uclibc),
1503
1504 ("i686-linux-android", i686_linux_android),
1505 ("x86_64-linux-android", x86_64_linux_android),
1506 ("arm-linux-androideabi", arm_linux_androideabi),
1507 ("armv7-linux-androideabi", armv7_linux_androideabi),
1508 ("thumbv7neon-linux-androideabi", thumbv7neon_linux_androideabi),
1509 ("aarch64-linux-android", aarch64_linux_android),
1510 ("riscv64-linux-android", riscv64_linux_android),
1511
1512 ("aarch64-unknown-freebsd", aarch64_unknown_freebsd),
1513 ("armv6-unknown-freebsd", armv6_unknown_freebsd),
1514 ("armv7-unknown-freebsd", armv7_unknown_freebsd),
1515 ("i686-unknown-freebsd", i686_unknown_freebsd),
1516 ("powerpc-unknown-freebsd", powerpc_unknown_freebsd),
1517 ("powerpc64-unknown-freebsd", powerpc64_unknown_freebsd),
1518 ("powerpc64le-unknown-freebsd", powerpc64le_unknown_freebsd),
1519 ("riscv64gc-unknown-freebsd", riscv64gc_unknown_freebsd),
1520 ("x86_64-unknown-freebsd", x86_64_unknown_freebsd),
1521
1522 ("x86_64-unknown-dragonfly", x86_64_unknown_dragonfly),
1523
1524 ("aarch64-unknown-openbsd", aarch64_unknown_openbsd),
1525 ("i686-unknown-openbsd", i686_unknown_openbsd),
1526 ("powerpc-unknown-openbsd", powerpc_unknown_openbsd),
1527 ("powerpc64-unknown-openbsd", powerpc64_unknown_openbsd),
1528 ("riscv64gc-unknown-openbsd", riscv64gc_unknown_openbsd),
1529 ("sparc64-unknown-openbsd", sparc64_unknown_openbsd),
1530 ("x86_64-unknown-openbsd", x86_64_unknown_openbsd),
1531
1532 ("aarch64-unknown-netbsd", aarch64_unknown_netbsd),
1533 ("aarch64_be-unknown-netbsd", aarch64_be_unknown_netbsd),
1534 ("armv6-unknown-netbsd-eabihf", armv6_unknown_netbsd_eabihf),
1535 ("armv7-unknown-netbsd-eabihf", armv7_unknown_netbsd_eabihf),
1536 ("i586-unknown-netbsd", i586_unknown_netbsd),
1537 ("i686-unknown-netbsd", i686_unknown_netbsd),
1538 ("mipsel-unknown-netbsd", mipsel_unknown_netbsd),
1539 ("powerpc-unknown-netbsd", powerpc_unknown_netbsd),
1540 ("riscv64gc-unknown-netbsd", riscv64gc_unknown_netbsd),
1541 ("sparc64-unknown-netbsd", sparc64_unknown_netbsd),
1542 ("x86_64-unknown-netbsd", x86_64_unknown_netbsd),
1543
1544 ("i686-unknown-haiku", i686_unknown_haiku),
1545 ("x86_64-unknown-haiku", x86_64_unknown_haiku),
1546
1547 ("i686-unknown-hurd-gnu", i686_unknown_hurd_gnu),
1548 ("x86_64-unknown-hurd-gnu", x86_64_unknown_hurd_gnu),
1549
1550 ("aarch64-apple-darwin", aarch64_apple_darwin),
1551 ("arm64e-apple-darwin", arm64e_apple_darwin),
1552 ("x86_64-apple-darwin", x86_64_apple_darwin),
1553 ("x86_64h-apple-darwin", x86_64h_apple_darwin),
1554 ("i686-apple-darwin", i686_apple_darwin),
1555
1556 ("aarch64-unknown-fuchsia", aarch64_unknown_fuchsia),
1557 ("riscv64gc-unknown-fuchsia", riscv64gc_unknown_fuchsia),
1558 ("x86_64-unknown-fuchsia", x86_64_unknown_fuchsia),
1559
1560 ("avr-none", avr_none),
1561
1562 ("x86_64-unknown-l4re-uclibc", x86_64_unknown_l4re_uclibc),
1563
1564 ("aarch64-unknown-redox", aarch64_unknown_redox),
1565 ("i586-unknown-redox", i586_unknown_redox),
1566 ("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-wasip1-threads", wasm32_wasip1_threads),
1638 ("wasm32-wali-linux-musl", wasm32_wali_linux_musl),
1639 ("wasm64-unknown-unknown", wasm64_unknown_unknown),
1640
1641 ("thumbv6m-none-eabi", thumbv6m_none_eabi),
1642 ("thumbv7m-none-eabi", thumbv7m_none_eabi),
1643 ("thumbv7em-none-eabi", thumbv7em_none_eabi),
1644 ("thumbv7em-none-eabihf", thumbv7em_none_eabihf),
1645 ("thumbv8m.base-none-eabi", thumbv8m_base_none_eabi),
1646 ("thumbv8m.main-none-eabi", thumbv8m_main_none_eabi),
1647 ("thumbv8m.main-none-eabihf", thumbv8m_main_none_eabihf),
1648
1649 ("armv7a-none-eabi", armv7a_none_eabi),
1650 ("armv7a-none-eabihf", armv7a_none_eabihf),
1651 ("armv7a-nuttx-eabi", armv7a_nuttx_eabi),
1652 ("armv7a-nuttx-eabihf", armv7a_nuttx_eabihf),
1653 ("armv7a-vex-v5", armv7a_vex_v5),
1654
1655 ("msp430-none-elf", msp430_none_elf),
1656
1657 ("aarch64_be-unknown-hermit", aarch64_be_unknown_hermit),
1658 ("aarch64-unknown-hermit", aarch64_unknown_hermit),
1659 ("riscv64gc-unknown-hermit", riscv64gc_unknown_hermit),
1660 ("x86_64-unknown-hermit", x86_64_unknown_hermit),
1661
1662 ("x86_64-unikraft-linux-musl", x86_64_unikraft_linux_musl),
1663
1664 ("armv7-unknown-trusty", armv7_unknown_trusty),
1665 ("aarch64-unknown-trusty", aarch64_unknown_trusty),
1666 ("x86_64-unknown-trusty", x86_64_unknown_trusty),
1667
1668 ("riscv32i-unknown-none-elf", riscv32i_unknown_none_elf),
1669 ("riscv32im-risc0-zkvm-elf", riscv32im_risc0_zkvm_elf),
1670 ("riscv32im-unknown-none-elf", riscv32im_unknown_none_elf),
1671 ("riscv32ima-unknown-none-elf", riscv32ima_unknown_none_elf),
1672 ("riscv32imc-unknown-none-elf", riscv32imc_unknown_none_elf),
1673 ("riscv32imc-esp-espidf", riscv32imc_esp_espidf),
1674 ("riscv32imac-esp-espidf", riscv32imac_esp_espidf),
1675 ("riscv32imafc-esp-espidf", riscv32imafc_esp_espidf),
1676
1677 ("riscv32e-unknown-none-elf", riscv32e_unknown_none_elf),
1678 ("riscv32em-unknown-none-elf", riscv32em_unknown_none_elf),
1679 ("riscv32emc-unknown-none-elf", riscv32emc_unknown_none_elf),
1680
1681 ("riscv32imac-unknown-none-elf", riscv32imac_unknown_none_elf),
1682 ("riscv32imafc-unknown-none-elf", riscv32imafc_unknown_none_elf),
1683 ("riscv32imac-unknown-xous-elf", riscv32imac_unknown_xous_elf),
1684 ("riscv32gc-unknown-linux-gnu", riscv32gc_unknown_linux_gnu),
1685 ("riscv32gc-unknown-linux-musl", riscv32gc_unknown_linux_musl),
1686 ("riscv64imac-unknown-none-elf", riscv64imac_unknown_none_elf),
1687 ("riscv64gc-unknown-none-elf", riscv64gc_unknown_none_elf),
1688 ("riscv64gc-unknown-linux-gnu", riscv64gc_unknown_linux_gnu),
1689 ("riscv64gc-unknown-linux-musl", riscv64gc_unknown_linux_musl),
1690 ("riscv64a23-unknown-linux-gnu", riscv64a23_unknown_linux_gnu),
1691
1692 ("sparc-unknown-none-elf", sparc_unknown_none_elf),
1693
1694 ("loongarch32-unknown-none", loongarch32_unknown_none),
1695 ("loongarch32-unknown-none-softfloat", loongarch32_unknown_none_softfloat),
1696 ("loongarch64-unknown-none", loongarch64_unknown_none),
1697 ("loongarch64-unknown-none-softfloat", loongarch64_unknown_none_softfloat),
1698
1699 ("aarch64-unknown-none", aarch64_unknown_none),
1700 ("aarch64-unknown-none-softfloat", aarch64_unknown_none_softfloat),
1701 ("aarch64_be-unknown-none-softfloat", aarch64_be_unknown_none_softfloat),
1702 ("aarch64-unknown-nuttx", aarch64_unknown_nuttx),
1703
1704 ("x86_64-fortanix-unknown-sgx", x86_64_fortanix_unknown_sgx),
1705
1706 ("x86_64-unknown-uefi", x86_64_unknown_uefi),
1707 ("i686-unknown-uefi", i686_unknown_uefi),
1708 ("aarch64-unknown-uefi", aarch64_unknown_uefi),
1709
1710 ("nvptx64-nvidia-cuda", nvptx64_nvidia_cuda),
1711
1712 ("amdgcn-amd-amdhsa", amdgcn_amd_amdhsa),
1713
1714 ("xtensa-esp32-none-elf", xtensa_esp32_none_elf),
1715 ("xtensa-esp32-espidf", xtensa_esp32_espidf),
1716 ("xtensa-esp32s2-none-elf", xtensa_esp32s2_none_elf),
1717 ("xtensa-esp32s2-espidf", xtensa_esp32s2_espidf),
1718 ("xtensa-esp32s3-none-elf", xtensa_esp32s3_none_elf),
1719 ("xtensa-esp32s3-espidf", xtensa_esp32s3_espidf),
1720
1721 ("i686-wrs-vxworks", i686_wrs_vxworks),
1722 ("x86_64-wrs-vxworks", x86_64_wrs_vxworks),
1723 ("armv7-wrs-vxworks-eabihf", armv7_wrs_vxworks_eabihf),
1724 ("aarch64-wrs-vxworks", aarch64_wrs_vxworks),
1725 ("powerpc-wrs-vxworks", powerpc_wrs_vxworks),
1726 ("powerpc-wrs-vxworks-spe", powerpc_wrs_vxworks_spe),
1727 ("powerpc64-wrs-vxworks", powerpc64_wrs_vxworks),
1728 ("riscv32-wrs-vxworks", riscv32_wrs_vxworks),
1729 ("riscv64-wrs-vxworks", riscv64_wrs_vxworks),
1730
1731 ("aarch64-kmc-solid_asp3", aarch64_kmc_solid_asp3),
1732 ("armv7a-kmc-solid_asp3-eabi", armv7a_kmc_solid_asp3_eabi),
1733 ("armv7a-kmc-solid_asp3-eabihf", armv7a_kmc_solid_asp3_eabihf),
1734
1735 ("mipsel-sony-psp", mipsel_sony_psp),
1736 ("mipsel-sony-psx", mipsel_sony_psx),
1737 ("mipsel-unknown-none", mipsel_unknown_none),
1738 ("mips-mti-none-elf", mips_mti_none_elf),
1739 ("mipsel-mti-none-elf", mipsel_mti_none_elf),
1740 ("thumbv4t-none-eabi", thumbv4t_none_eabi),
1741 ("armv4t-none-eabi", armv4t_none_eabi),
1742 ("thumbv5te-none-eabi", thumbv5te_none_eabi),
1743 ("armv5te-none-eabi", armv5te_none_eabi),
1744
1745 ("aarch64_be-unknown-linux-gnu", aarch64_be_unknown_linux_gnu),
1746 ("aarch64-unknown-linux-gnu_ilp32", aarch64_unknown_linux_gnu_ilp32),
1747 ("aarch64_be-unknown-linux-gnu_ilp32", aarch64_be_unknown_linux_gnu_ilp32),
1748
1749 ("bpfeb-unknown-none", bpfeb_unknown_none),
1750 ("bpfel-unknown-none", bpfel_unknown_none),
1751
1752 ("armv6k-nintendo-3ds", armv6k_nintendo_3ds),
1753
1754 ("aarch64-nintendo-switch-freestanding", aarch64_nintendo_switch_freestanding),
1755
1756 ("armv7-sony-vita-newlibeabihf", armv7_sony_vita_newlibeabihf),
1757
1758 ("armv7-unknown-linux-uclibceabi", armv7_unknown_linux_uclibceabi),
1759 ("armv7-unknown-linux-uclibceabihf", armv7_unknown_linux_uclibceabihf),
1760
1761 ("x86_64-unknown-none", x86_64_unknown_none),
1762
1763 ("aarch64-unknown-teeos", aarch64_unknown_teeos),
1764
1765 ("mips64-openwrt-linux-musl", mips64_openwrt_linux_musl),
1766
1767 ("aarch64-unknown-nto-qnx700", aarch64_unknown_nto_qnx700),
1768 ("aarch64-unknown-nto-qnx710", aarch64_unknown_nto_qnx710),
1769 ("aarch64-unknown-nto-qnx710_iosock", aarch64_unknown_nto_qnx710_iosock),
1770 ("aarch64-unknown-nto-qnx800", aarch64_unknown_nto_qnx800),
1771 ("x86_64-pc-nto-qnx710", x86_64_pc_nto_qnx710),
1772 ("x86_64-pc-nto-qnx710_iosock", x86_64_pc_nto_qnx710_iosock),
1773 ("x86_64-pc-nto-qnx800", x86_64_pc_nto_qnx800),
1774 ("i686-pc-nto-qnx700", i686_pc_nto_qnx700),
1775
1776 ("aarch64-unknown-linux-ohos", aarch64_unknown_linux_ohos),
1777 ("armv7-unknown-linux-ohos", armv7_unknown_linux_ohos),
1778 ("loongarch64-unknown-linux-ohos", loongarch64_unknown_linux_ohos),
1779 ("x86_64-unknown-linux-ohos", x86_64_unknown_linux_ohos),
1780
1781 ("x86_64-unknown-linux-none", x86_64_unknown_linux_none),
1782
1783 ("thumbv6m-nuttx-eabi", thumbv6m_nuttx_eabi),
1784 ("thumbv7a-nuttx-eabi", thumbv7a_nuttx_eabi),
1785 ("thumbv7a-nuttx-eabihf", thumbv7a_nuttx_eabihf),
1786 ("thumbv7m-nuttx-eabi", thumbv7m_nuttx_eabi),
1787 ("thumbv7em-nuttx-eabi", thumbv7em_nuttx_eabi),
1788 ("thumbv7em-nuttx-eabihf", thumbv7em_nuttx_eabihf),
1789 ("thumbv8m.base-nuttx-eabi", thumbv8m_base_nuttx_eabi),
1790 ("thumbv8m.main-nuttx-eabi", thumbv8m_main_nuttx_eabi),
1791 ("thumbv8m.main-nuttx-eabihf", thumbv8m_main_nuttx_eabihf),
1792 ("riscv32imc-unknown-nuttx-elf", riscv32imc_unknown_nuttx_elf),
1793 ("riscv32imac-unknown-nuttx-elf", riscv32imac_unknown_nuttx_elf),
1794 ("riscv32imafc-unknown-nuttx-elf", riscv32imafc_unknown_nuttx_elf),
1795 ("riscv64imac-unknown-nuttx-elf", riscv64imac_unknown_nuttx_elf),
1796 ("riscv64gc-unknown-nuttx-elf", riscv64gc_unknown_nuttx_elf),
1797 ("x86_64-lynx-lynxos178", x86_64_lynx_lynxos178),
1798
1799 ("x86_64-pc-cygwin", x86_64_pc_cygwin),
1800}
1801
1802macro_rules! cvs {
1804 () => {
1805 ::std::borrow::Cow::Borrowed(&[])
1806 };
1807 ($($x:expr),+ $(,)?) => {
1808 ::std::borrow::Cow::Borrowed(&[
1809 $(
1810 ::std::borrow::Cow::Borrowed($x),
1811 )*
1812 ])
1813 };
1814}
1815
1816pub(crate) use cvs;
1817
1818#[derive(Debug, PartialEq)]
1822pub struct TargetWarnings {
1823 unused_fields: Vec<String>,
1824}
1825
1826impl TargetWarnings {
1827 pub fn empty() -> Self {
1828 Self { unused_fields: Vec::new() }
1829 }
1830
1831 pub fn warning_messages(&self) -> Vec<String> {
1832 let mut warnings = vec![];
1833 if !self.unused_fields.is_empty() {
1834 warnings.push(format!(
1835 "target json file contains unused fields: {}",
1836 self.unused_fields.join(", ")
1837 ));
1838 }
1839 warnings
1840 }
1841}
1842
1843#[derive(Copy, Clone, Debug, PartialEq)]
1846enum TargetKind {
1847 Json,
1848 Builtin,
1849}
1850
1851#[derive(PartialEq, Clone, Debug)]
1855pub struct Target {
1856 pub llvm_target: StaticCow<str>,
1863 pub metadata: TargetMetadata,
1866 pub pointer_width: u16,
1868 pub arch: StaticCow<str>,
1871 pub data_layout: StaticCow<str>,
1873 pub options: TargetOptions,
1875}
1876
1877#[derive(Default, PartialEq, Clone, Debug)]
1881pub struct TargetMetadata {
1882 pub description: Option<StaticCow<str>>,
1885 pub tier: Option<u64>,
1887 pub host_tools: Option<bool>,
1889 pub std: Option<bool>,
1892}
1893
1894impl Target {
1895 pub fn parse_data_layout(&self) -> Result<TargetDataLayout, TargetDataLayoutErrors<'_>> {
1896 let mut dl = TargetDataLayout::parse_from_llvm_datalayout_string(
1897 &self.data_layout,
1898 self.options.default_address_space,
1899 )?;
1900
1901 if dl.endian != self.endian {
1903 return Err(TargetDataLayoutErrors::InconsistentTargetArchitecture {
1904 dl: dl.endian.as_str(),
1905 target: self.endian.as_str(),
1906 });
1907 }
1908
1909 let target_pointer_width: u64 = self.pointer_width.into();
1910 let dl_pointer_size: u64 = dl.pointer_size().bits();
1911 if dl_pointer_size != target_pointer_width {
1912 return Err(TargetDataLayoutErrors::InconsistentTargetPointerWidth {
1913 pointer_size: dl_pointer_size,
1914 target: self.pointer_width,
1915 });
1916 }
1917
1918 dl.c_enum_min_size = Integer::from_size(Size::from_bits(
1919 self.c_enum_min_bits.unwrap_or(self.c_int_width as _),
1920 ))
1921 .map_err(|err| TargetDataLayoutErrors::InvalidBitsSize { err })?;
1922
1923 Ok(dl)
1924 }
1925}
1926
1927pub trait HasTargetSpec {
1928 fn target_spec(&self) -> &Target;
1929}
1930
1931impl HasTargetSpec for Target {
1932 #[inline]
1933 fn target_spec(&self) -> &Target {
1934 self
1935 }
1936}
1937
1938#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
1940pub struct X86Abi {
1941 pub regparm: Option<u32>,
1944 pub reg_struct_return: bool,
1946}
1947
1948pub trait HasX86AbiOpt {
1949 fn x86_abi_opt(&self) -> X86Abi;
1950}
1951
1952type StaticCow<T> = Cow<'static, T>;
1953
1954#[derive(PartialEq, Clone, Debug)]
1963pub struct TargetOptions {
1964 pub endian: Endian,
1966 pub c_int_width: u16,
1968 pub os: StaticCow<str>,
1973 pub env: StaticCow<str>,
1975 pub abi: StaticCow<str>,
1980 pub vendor: StaticCow<str>,
1982
1983 pub linker: Option<StaticCow<str>>,
1985 pub linker_flavor: LinkerFlavor,
1988 linker_flavor_json: LinkerFlavorCli,
1989 lld_flavor_json: LldFlavor,
1990 linker_is_gnu_json: bool,
1991
1992 pub pre_link_objects: CrtObjects,
1994 pub post_link_objects: CrtObjects,
1995 pub pre_link_objects_self_contained: CrtObjects,
1997 pub post_link_objects_self_contained: CrtObjects,
1998 pub link_self_contained: LinkSelfContainedDefault,
2001
2002 pub pre_link_args: LinkArgs,
2004 pre_link_args_json: LinkArgsCli,
2005 pub late_link_args: LinkArgs,
2009 late_link_args_json: LinkArgsCli,
2010 pub late_link_args_dynamic: LinkArgs,
2013 late_link_args_dynamic_json: LinkArgsCli,
2014 pub late_link_args_static: LinkArgs,
2017 late_link_args_static_json: LinkArgsCli,
2018 pub post_link_args: LinkArgs,
2021 post_link_args_json: LinkArgsCli,
2022
2023 pub link_script: Option<StaticCow<str>>,
2027 pub link_env: StaticCow<[(StaticCow<str>, StaticCow<str>)]>,
2029 pub link_env_remove: StaticCow<[StaticCow<str>]>,
2031
2032 pub asm_args: StaticCow<[StaticCow<str>]>,
2034
2035 pub cpu: StaticCow<str>,
2038 pub need_explicit_cpu: bool,
2041 pub features: StaticCow<str>,
2050 pub direct_access_external_data: Option<bool>,
2052 pub dynamic_linking: bool,
2054 pub dll_tls_export: bool,
2056 pub only_cdylib: bool,
2058 pub executables: bool,
2060 pub relocation_model: RelocModel,
2063 pub code_model: Option<CodeModel>,
2066 pub tls_model: TlsModel,
2069 pub disable_redzone: bool,
2071 pub frame_pointer: FramePointer,
2073 pub function_sections: bool,
2075 pub dll_prefix: StaticCow<str>,
2077 pub dll_suffix: StaticCow<str>,
2079 pub exe_suffix: StaticCow<str>,
2081 pub staticlib_prefix: StaticCow<str>,
2083 pub staticlib_suffix: StaticCow<str>,
2085 pub families: StaticCow<[StaticCow<str>]>,
2091 pub abi_return_struct_as_int: bool,
2093 pub is_like_aix: bool,
2096 pub is_like_darwin: bool,
2101 pub is_like_solaris: bool,
2105 pub is_like_windows: bool,
2113 pub is_like_msvc: bool,
2123 pub is_like_wasm: bool,
2125 pub is_like_android: bool,
2127 pub is_like_vexos: bool,
2129 pub binary_format: BinaryFormat,
2131 pub default_dwarf_version: u32,
2134 pub allows_weak_linkage: bool,
2141 pub has_rpath: bool,
2143 pub no_default_libraries: bool,
2146 pub position_independent_executables: bool,
2152 pub static_position_independent_executables: bool,
2154 pub plt_by_default: bool,
2157 pub relro_level: RelroLevel,
2161 pub archive_format: StaticCow<str>,
2166 pub allow_asm: bool,
2168 pub main_needs_argc_argv: bool,
2171
2172 pub has_thread_local: bool,
2174 pub obj_is_bitcode: bool,
2178
2179 pub min_atomic_width: Option<u64>,
2181
2182 pub max_atomic_width: Option<u64>,
2184
2185 pub atomic_cas: bool,
2187
2188 pub panic_strategy: PanicStrategy,
2190
2191 pub crt_static_allows_dylibs: bool,
2193 pub crt_static_default: bool,
2195 pub crt_static_respected: bool,
2197
2198 pub stack_probes: StackProbeType,
2200
2201 pub min_global_align: Option<Align>,
2203
2204 pub default_codegen_units: Option<u64>,
2206
2207 pub default_codegen_backend: Option<StaticCow<str>>,
2217
2218 pub trap_unreachable: bool,
2221
2222 pub requires_lto: bool,
2225
2226 pub singlethread: bool,
2228
2229 pub no_builtins: bool,
2232
2233 pub default_visibility: Option<SymbolVisibility>,
2239
2240 pub emit_debug_gdb_scripts: bool,
2242
2243 pub requires_uwtable: bool,
2247
2248 pub default_uwtable: bool,
2251
2252 pub simd_types_indirect: bool,
2257
2258 pub limit_rdylib_exports: bool,
2260
2261 pub override_export_symbols: Option<StaticCow<[StaticCow<str>]>>,
2264
2265 pub merge_functions: MergeFunctions,
2272
2273 pub mcount: StaticCow<str>,
2275
2276 pub llvm_mcount_intrinsic: Option<StaticCow<str>>,
2278
2279 pub llvm_abiname: StaticCow<str>,
2282
2283 pub llvm_floatabi: Option<FloatAbi>,
2290
2291 pub rustc_abi: Option<RustcAbi>,
2296
2297 pub relax_elf_relocations: bool,
2299
2300 pub llvm_args: StaticCow<[StaticCow<str>]>,
2302
2303 pub use_ctors_section: bool,
2306
2307 pub eh_frame_header: bool,
2311
2312 pub has_thumb_interworking: bool,
2315
2316 pub debuginfo_kind: DebuginfoKind,
2318 pub split_debuginfo: SplitDebuginfo,
2321 pub supported_split_debuginfo: StaticCow<[SplitDebuginfo]>,
2323
2324 pub supported_sanitizers: SanitizerSet,
2330
2331 pub c_enum_min_bits: Option<u64>,
2333
2334 pub generate_arange_section: bool,
2336
2337 pub supports_stack_protector: bool,
2340
2341 pub entry_name: StaticCow<str>,
2344
2345 pub entry_abi: CanonAbi,
2348
2349 pub supports_xray: bool,
2351
2352 pub default_address_space: rustc_abi::AddressSpace,
2356
2357 small_data_threshold_support: SmallDataThresholdSupport,
2359}
2360
2361fn add_link_args_iter(
2364 link_args: &mut LinkArgs,
2365 flavor: LinkerFlavor,
2366 args: impl Iterator<Item = StaticCow<str>> + Clone,
2367) {
2368 let mut insert = |flavor| link_args.entry(flavor).or_default().extend(args.clone());
2369 insert(flavor);
2370 match flavor {
2371 LinkerFlavor::Gnu(cc, lld) => {
2372 assert_eq!(lld, Lld::No);
2373 insert(LinkerFlavor::Gnu(cc, Lld::Yes));
2374 }
2375 LinkerFlavor::Darwin(cc, lld) => {
2376 assert_eq!(lld, Lld::No);
2377 insert(LinkerFlavor::Darwin(cc, Lld::Yes));
2378 }
2379 LinkerFlavor::Msvc(lld) => {
2380 assert_eq!(lld, Lld::No);
2381 insert(LinkerFlavor::Msvc(Lld::Yes));
2382 }
2383 LinkerFlavor::WasmLld(..)
2384 | LinkerFlavor::Unix(..)
2385 | LinkerFlavor::EmCc
2386 | LinkerFlavor::Bpf
2387 | LinkerFlavor::Llbc
2388 | LinkerFlavor::Ptx => {}
2389 }
2390}
2391
2392fn add_link_args(link_args: &mut LinkArgs, flavor: LinkerFlavor, args: &[&'static str]) {
2393 add_link_args_iter(link_args, flavor, args.iter().copied().map(Cow::Borrowed))
2394}
2395
2396impl TargetOptions {
2397 pub fn supports_comdat(&self) -> bool {
2398 !self.is_like_aix && !self.is_like_darwin
2400 }
2401}
2402
2403impl TargetOptions {
2404 fn link_args(flavor: LinkerFlavor, args: &[&'static str]) -> LinkArgs {
2405 let mut link_args = LinkArgs::new();
2406 add_link_args(&mut link_args, flavor, args);
2407 link_args
2408 }
2409
2410 fn add_pre_link_args(&mut self, flavor: LinkerFlavor, args: &[&'static str]) {
2411 add_link_args(&mut self.pre_link_args, flavor, args);
2412 }
2413
2414 fn update_from_cli(&mut self) {
2415 self.linker_flavor = LinkerFlavor::from_cli_json(
2416 self.linker_flavor_json,
2417 self.lld_flavor_json,
2418 self.linker_is_gnu_json,
2419 );
2420 for (args, args_json) in [
2421 (&mut self.pre_link_args, &self.pre_link_args_json),
2422 (&mut self.late_link_args, &self.late_link_args_json),
2423 (&mut self.late_link_args_dynamic, &self.late_link_args_dynamic_json),
2424 (&mut self.late_link_args_static, &self.late_link_args_static_json),
2425 (&mut self.post_link_args, &self.post_link_args_json),
2426 ] {
2427 args.clear();
2428 for (flavor, args_json) in args_json {
2429 let linker_flavor = self.linker_flavor.with_cli_hints(*flavor);
2430 let linker_flavor = match linker_flavor {
2432 LinkerFlavor::Gnu(cc, _) => LinkerFlavor::Gnu(cc, Lld::No),
2433 LinkerFlavor::Darwin(cc, _) => LinkerFlavor::Darwin(cc, Lld::No),
2434 LinkerFlavor::Msvc(_) => LinkerFlavor::Msvc(Lld::No),
2435 _ => linker_flavor,
2436 };
2437 if !args.contains_key(&linker_flavor) {
2438 add_link_args_iter(args, linker_flavor, args_json.iter().cloned());
2439 }
2440 }
2441 }
2442 }
2443
2444 fn update_to_cli(&mut self) {
2445 self.linker_flavor_json = self.linker_flavor.to_cli_counterpart();
2446 self.lld_flavor_json = self.linker_flavor.lld_flavor();
2447 self.linker_is_gnu_json = self.linker_flavor.is_gnu();
2448 for (args, args_json) in [
2449 (&self.pre_link_args, &mut self.pre_link_args_json),
2450 (&self.late_link_args, &mut self.late_link_args_json),
2451 (&self.late_link_args_dynamic, &mut self.late_link_args_dynamic_json),
2452 (&self.late_link_args_static, &mut self.late_link_args_static_json),
2453 (&self.post_link_args, &mut self.post_link_args_json),
2454 ] {
2455 *args_json = args
2456 .iter()
2457 .map(|(flavor, args)| (flavor.to_cli_counterpart(), args.clone()))
2458 .collect();
2459 }
2460 }
2461}
2462
2463impl Default for TargetOptions {
2464 fn default() -> TargetOptions {
2467 TargetOptions {
2468 endian: Endian::Little,
2469 c_int_width: 32,
2470 os: "none".into(),
2471 env: "".into(),
2472 abi: "".into(),
2473 vendor: "unknown".into(),
2474 linker: option_env!("CFG_DEFAULT_LINKER").map(|s| s.into()),
2475 linker_flavor: LinkerFlavor::Gnu(Cc::Yes, Lld::No),
2476 linker_flavor_json: LinkerFlavorCli::Gcc,
2477 lld_flavor_json: LldFlavor::Ld,
2478 linker_is_gnu_json: true,
2479 link_script: None,
2480 asm_args: cvs![],
2481 cpu: "generic".into(),
2482 need_explicit_cpu: false,
2483 features: "".into(),
2484 direct_access_external_data: None,
2485 dynamic_linking: false,
2486 dll_tls_export: true,
2487 only_cdylib: false,
2488 executables: true,
2489 relocation_model: RelocModel::Pic,
2490 code_model: None,
2491 tls_model: TlsModel::GeneralDynamic,
2492 disable_redzone: false,
2493 frame_pointer: FramePointer::MayOmit,
2494 function_sections: true,
2495 dll_prefix: "lib".into(),
2496 dll_suffix: ".so".into(),
2497 exe_suffix: "".into(),
2498 staticlib_prefix: "lib".into(),
2499 staticlib_suffix: ".a".into(),
2500 families: cvs![],
2501 abi_return_struct_as_int: false,
2502 is_like_aix: false,
2503 is_like_darwin: false,
2504 is_like_solaris: false,
2505 is_like_windows: false,
2506 is_like_msvc: false,
2507 is_like_wasm: false,
2508 is_like_android: false,
2509 is_like_vexos: false,
2510 binary_format: BinaryFormat::Elf,
2511 default_dwarf_version: 4,
2512 allows_weak_linkage: true,
2513 has_rpath: false,
2514 no_default_libraries: true,
2515 position_independent_executables: false,
2516 static_position_independent_executables: false,
2517 plt_by_default: true,
2518 relro_level: RelroLevel::None,
2519 pre_link_objects: Default::default(),
2520 post_link_objects: Default::default(),
2521 pre_link_objects_self_contained: Default::default(),
2522 post_link_objects_self_contained: Default::default(),
2523 link_self_contained: LinkSelfContainedDefault::False,
2524 pre_link_args: LinkArgs::new(),
2525 pre_link_args_json: LinkArgsCli::new(),
2526 late_link_args: LinkArgs::new(),
2527 late_link_args_json: LinkArgsCli::new(),
2528 late_link_args_dynamic: LinkArgs::new(),
2529 late_link_args_dynamic_json: LinkArgsCli::new(),
2530 late_link_args_static: LinkArgs::new(),
2531 late_link_args_static_json: LinkArgsCli::new(),
2532 post_link_args: LinkArgs::new(),
2533 post_link_args_json: LinkArgsCli::new(),
2534 link_env: cvs![],
2535 link_env_remove: cvs![],
2536 archive_format: "gnu".into(),
2537 main_needs_argc_argv: true,
2538 allow_asm: true,
2539 has_thread_local: false,
2540 obj_is_bitcode: false,
2541 min_atomic_width: None,
2542 max_atomic_width: None,
2543 atomic_cas: true,
2544 panic_strategy: PanicStrategy::Unwind,
2545 crt_static_allows_dylibs: false,
2546 crt_static_default: false,
2547 crt_static_respected: false,
2548 stack_probes: StackProbeType::None,
2549 min_global_align: None,
2550 default_codegen_units: None,
2551 default_codegen_backend: None,
2552 trap_unreachable: true,
2553 requires_lto: false,
2554 singlethread: false,
2555 no_builtins: false,
2556 default_visibility: None,
2557 emit_debug_gdb_scripts: true,
2558 requires_uwtable: false,
2559 default_uwtable: false,
2560 simd_types_indirect: true,
2561 limit_rdylib_exports: true,
2562 override_export_symbols: None,
2563 merge_functions: MergeFunctions::Aliases,
2564 mcount: "mcount".into(),
2565 llvm_mcount_intrinsic: None,
2566 llvm_abiname: "".into(),
2567 llvm_floatabi: None,
2568 rustc_abi: None,
2569 relax_elf_relocations: false,
2570 llvm_args: cvs![],
2571 use_ctors_section: false,
2572 eh_frame_header: true,
2573 has_thumb_interworking: false,
2574 debuginfo_kind: Default::default(),
2575 split_debuginfo: Default::default(),
2576 supported_split_debuginfo: Cow::Borrowed(&[SplitDebuginfo::Off]),
2578 supported_sanitizers: SanitizerSet::empty(),
2579 c_enum_min_bits: None,
2580 generate_arange_section: true,
2581 supports_stack_protector: true,
2582 entry_name: "main".into(),
2583 entry_abi: CanonAbi::C,
2584 supports_xray: false,
2585 default_address_space: rustc_abi::AddressSpace::ZERO,
2586 small_data_threshold_support: SmallDataThresholdSupport::DefaultForArch,
2587 }
2588 }
2589}
2590
2591impl Deref for Target {
2595 type Target = TargetOptions;
2596
2597 #[inline]
2598 fn deref(&self) -> &Self::Target {
2599 &self.options
2600 }
2601}
2602impl DerefMut for Target {
2603 #[inline]
2604 fn deref_mut(&mut self) -> &mut Self::Target {
2605 &mut self.options
2606 }
2607}
2608
2609impl Target {
2610 pub fn is_abi_supported(&self, abi: ExternAbi) -> bool {
2611 let abi_map = AbiMap::from_target(self);
2612 abi_map.canonize_abi(abi, false).is_mapped()
2613 }
2614
2615 pub fn min_atomic_width(&self) -> u64 {
2618 self.min_atomic_width.unwrap_or(8)
2619 }
2620
2621 pub fn max_atomic_width(&self) -> u64 {
2624 self.max_atomic_width.unwrap_or_else(|| self.pointer_width.into())
2625 }
2626
2627 fn check_consistency(&self, kind: TargetKind) -> Result<(), String> {
2630 macro_rules! check {
2631 ($b:expr, $($msg:tt)*) => {
2632 if !$b {
2633 return Err(format!($($msg)*));
2634 }
2635 }
2636 }
2637 macro_rules! check_eq {
2638 ($left:expr, $right:expr, $($msg:tt)*) => {
2639 if ($left) != ($right) {
2640 return Err(format!($($msg)*));
2641 }
2642 }
2643 }
2644 macro_rules! check_ne {
2645 ($left:expr, $right:expr, $($msg:tt)*) => {
2646 if ($left) == ($right) {
2647 return Err(format!($($msg)*));
2648 }
2649 }
2650 }
2651 macro_rules! check_matches {
2652 ($left:expr, $right:pat, $($msg:tt)*) => {
2653 if !matches!($left, $right) {
2654 return Err(format!($($msg)*));
2655 }
2656 }
2657 }
2658
2659 check_eq!(
2660 self.is_like_darwin,
2661 self.vendor == "apple",
2662 "`is_like_darwin` must be set if and only if `vendor` is `apple`"
2663 );
2664 check_eq!(
2665 self.is_like_solaris,
2666 self.os == "solaris" || self.os == "illumos",
2667 "`is_like_solaris` must be set if and only if `os` is `solaris` or `illumos`"
2668 );
2669 check_eq!(
2670 self.is_like_windows,
2671 self.os == "windows" || self.os == "uefi" || self.os == "cygwin",
2672 "`is_like_windows` must be set if and only if `os` is `windows`, `uefi` or `cygwin`"
2673 );
2674 check_eq!(
2675 self.is_like_wasm,
2676 self.arch == "wasm32" || self.arch == "wasm64",
2677 "`is_like_wasm` must be set if and only if `arch` is `wasm32` or `wasm64`"
2678 );
2679 if self.is_like_msvc {
2680 check!(self.is_like_windows, "if `is_like_msvc` is set, `is_like_windows` must be set");
2681 }
2682 if self.os == "emscripten" {
2683 check!(self.is_like_wasm, "the `emcscripten` os only makes sense on wasm-like targets");
2684 }
2685
2686 check_eq!(
2688 self.is_like_darwin,
2689 matches!(self.linker_flavor, LinkerFlavor::Darwin(..)),
2690 "`linker_flavor` must be `darwin` if and only if `is_like_darwin` is set"
2691 );
2692 check_eq!(
2693 self.is_like_msvc,
2694 matches!(self.linker_flavor, LinkerFlavor::Msvc(..)),
2695 "`linker_flavor` must be `msvc` if and only if `is_like_msvc` is set"
2696 );
2697 check_eq!(
2698 self.is_like_wasm && self.os != "emscripten",
2699 matches!(self.linker_flavor, LinkerFlavor::WasmLld(..)),
2700 "`linker_flavor` must be `wasm-lld` if and only if `is_like_wasm` is set and the `os` is not `emscripten`",
2701 );
2702 check_eq!(
2703 self.os == "emscripten",
2704 matches!(self.linker_flavor, LinkerFlavor::EmCc),
2705 "`linker_flavor` must be `em-cc` if and only if `os` is `emscripten`"
2706 );
2707 check_eq!(
2708 self.arch == "bpf",
2709 matches!(self.linker_flavor, LinkerFlavor::Bpf),
2710 "`linker_flavor` must be `bpf` if and only if `arch` is `bpf`"
2711 );
2712 check_eq!(
2713 self.arch == "nvptx64",
2714 matches!(self.linker_flavor, LinkerFlavor::Ptx),
2715 "`linker_flavor` must be `ptc` if and only if `arch` is `nvptx64`"
2716 );
2717
2718 for args in [
2719 &self.pre_link_args,
2720 &self.late_link_args,
2721 &self.late_link_args_dynamic,
2722 &self.late_link_args_static,
2723 &self.post_link_args,
2724 ] {
2725 for (&flavor, flavor_args) in args {
2726 check!(
2727 !flavor_args.is_empty() || self.arch == "avr",
2728 "linker flavor args must not be empty"
2729 );
2730 match self.linker_flavor {
2732 LinkerFlavor::Gnu(..) => {
2733 check_matches!(
2734 flavor,
2735 LinkerFlavor::Gnu(..),
2736 "mixing GNU and non-GNU linker flavors"
2737 );
2738 }
2739 LinkerFlavor::Darwin(..) => {
2740 check_matches!(
2741 flavor,
2742 LinkerFlavor::Darwin(..),
2743 "mixing Darwin and non-Darwin linker flavors"
2744 )
2745 }
2746 LinkerFlavor::WasmLld(..) => {
2747 check_matches!(
2748 flavor,
2749 LinkerFlavor::WasmLld(..),
2750 "mixing wasm and non-wasm linker flavors"
2751 )
2752 }
2753 LinkerFlavor::Unix(..) => {
2754 check_matches!(
2755 flavor,
2756 LinkerFlavor::Unix(..),
2757 "mixing unix and non-unix linker flavors"
2758 );
2759 }
2760 LinkerFlavor::Msvc(..) => {
2761 check_matches!(
2762 flavor,
2763 LinkerFlavor::Msvc(..),
2764 "mixing MSVC and non-MSVC linker flavors"
2765 );
2766 }
2767 LinkerFlavor::EmCc
2768 | LinkerFlavor::Bpf
2769 | LinkerFlavor::Ptx
2770 | LinkerFlavor::Llbc => {
2771 check_eq!(flavor, self.linker_flavor, "mixing different linker flavors")
2772 }
2773 }
2774
2775 let check_noncc = |noncc_flavor| -> Result<(), String> {
2777 if let Some(noncc_args) = args.get(&noncc_flavor) {
2778 for arg in flavor_args {
2779 if let Some(suffix) = arg.strip_prefix("-Wl,") {
2780 check!(
2781 noncc_args.iter().any(|a| a == suffix),
2782 " link args for cc and non-cc versions of flavors are not consistent"
2783 );
2784 }
2785 }
2786 }
2787 Ok(())
2788 };
2789
2790 match self.linker_flavor {
2791 LinkerFlavor::Gnu(Cc::Yes, lld) => check_noncc(LinkerFlavor::Gnu(Cc::No, lld))?,
2792 LinkerFlavor::WasmLld(Cc::Yes) => check_noncc(LinkerFlavor::WasmLld(Cc::No))?,
2793 LinkerFlavor::Unix(Cc::Yes) => check_noncc(LinkerFlavor::Unix(Cc::No))?,
2794 _ => {}
2795 }
2796 }
2797
2798 for cc in [Cc::No, Cc::Yes] {
2800 check_eq!(
2801 args.get(&LinkerFlavor::Gnu(cc, Lld::No)),
2802 args.get(&LinkerFlavor::Gnu(cc, Lld::Yes)),
2803 "link args for lld and non-lld versions of flavors are not consistent",
2804 );
2805 check_eq!(
2806 args.get(&LinkerFlavor::Darwin(cc, Lld::No)),
2807 args.get(&LinkerFlavor::Darwin(cc, Lld::Yes)),
2808 "link args for lld and non-lld versions of flavors are not consistent",
2809 );
2810 }
2811 check_eq!(
2812 args.get(&LinkerFlavor::Msvc(Lld::No)),
2813 args.get(&LinkerFlavor::Msvc(Lld::Yes)),
2814 "link args for lld and non-lld versions of flavors are not consistent",
2815 );
2816 }
2817
2818 if self.link_self_contained.is_disabled() {
2819 check!(
2820 self.pre_link_objects_self_contained.is_empty()
2821 && self.post_link_objects_self_contained.is_empty(),
2822 "if `link_self_contained` is disabled, then `pre_link_objects_self_contained` and `post_link_objects_self_contained` must be empty",
2823 );
2824 }
2825
2826 check_ne!(self.vendor, "", "`vendor` cannot be empty");
2830 check_ne!(self.os, "", "`os` cannot be empty");
2831 if !self.can_use_os_unknown() {
2832 check_ne!(
2834 self.os,
2835 "unknown",
2836 "`unknown` os can only be used on particular targets; use `none` for bare-metal targets"
2837 );
2838 }
2839
2840 if kind == TargetKind::Builtin {
2846 if self.os == "none"
2850 && (self.arch != "bpf"
2851 && self.arch != "hexagon"
2852 && self.arch != "wasm32"
2853 && self.arch != "wasm64")
2854 {
2855 check!(
2856 !self.dynamic_linking,
2857 "dynamic linking is not supported on this OS/architecture"
2858 );
2859 }
2860 if self.only_cdylib
2861 || self.crt_static_allows_dylibs
2862 || !self.late_link_args_dynamic.is_empty()
2863 {
2864 check!(
2865 self.dynamic_linking,
2866 "dynamic linking must be allowed when `only_cdylib` or `crt_static_allows_dylibs` or `late_link_args_dynamic` are set"
2867 );
2868 }
2869 if self.dynamic_linking && !self.is_like_wasm {
2871 check_eq!(
2872 self.relocation_model,
2873 RelocModel::Pic,
2874 "targets that support dynamic linking must use the `pic` relocation model"
2875 );
2876 }
2877 if self.position_independent_executables {
2878 check_eq!(
2879 self.relocation_model,
2880 RelocModel::Pic,
2881 "targets that support position-independent executables must use the `pic` relocation model"
2882 );
2883 }
2884 if self.relocation_model == RelocModel::Pic && (self.os != "uefi") {
2886 check!(
2887 self.dynamic_linking || self.position_independent_executables,
2888 "when the relocation model is `pic`, the target must support dynamic linking or use position-independent executables. \
2889 Set the relocation model to `static` to avoid this requirement"
2890 );
2891 }
2892 if self.static_position_independent_executables {
2893 check!(
2894 self.position_independent_executables,
2895 "if `static_position_independent_executables` is set, then `position_independent_executables` must be set"
2896 );
2897 }
2898 if self.position_independent_executables {
2899 check!(
2900 self.executables,
2901 "if `position_independent_executables` is set then `executables` must be set"
2902 );
2903 }
2904 }
2905
2906 if self.crt_static_default || self.crt_static_allows_dylibs {
2908 check!(
2909 self.crt_static_respected,
2910 "static CRT can be enabled but `crt_static_respected` is not set"
2911 );
2912 }
2913
2914 match &*self.arch {
2917 "riscv32" => {
2918 check_matches!(
2919 &*self.llvm_abiname,
2920 "ilp32" | "ilp32f" | "ilp32d" | "ilp32e",
2921 "invalid RISC-V ABI name: {}",
2922 self.llvm_abiname,
2923 );
2924 }
2925 "riscv64" => {
2926 check_matches!(
2928 &*self.llvm_abiname,
2929 "lp64" | "lp64f" | "lp64d" | "lp64e",
2930 "invalid RISC-V ABI name: {}",
2931 self.llvm_abiname,
2932 );
2933 }
2934 "arm" => {
2935 check!(
2936 self.llvm_floatabi.is_some(),
2937 "ARM targets must set `llvm-floatabi` to `hard` or `soft`",
2938 )
2939 }
2940 _ => {}
2941 }
2942
2943 if let Some(rust_abi) = self.rustc_abi {
2945 match rust_abi {
2946 RustcAbi::X86Sse2 => check_matches!(
2947 &*self.arch,
2948 "x86",
2949 "`x86-sse2` ABI is only valid for x86-32 targets"
2950 ),
2951 RustcAbi::X86Softfloat => check_matches!(
2952 &*self.arch,
2953 "x86" | "x86_64",
2954 "`x86-softfloat` ABI is only valid for x86 targets"
2955 ),
2956 }
2957 }
2958
2959 if !self.features.is_empty() {
2961 let mut features_enabled = FxHashSet::default();
2962 let mut features_disabled = FxHashSet::default();
2963 for feat in self.features.split(',') {
2964 if let Some(feat) = feat.strip_prefix("+") {
2965 features_enabled.insert(feat);
2966 if features_disabled.contains(feat) {
2967 return Err(format!(
2968 "target feature `{feat}` is both enabled and disabled"
2969 ));
2970 }
2971 } else if let Some(feat) = feat.strip_prefix("-") {
2972 features_disabled.insert(feat);
2973 if features_enabled.contains(feat) {
2974 return Err(format!(
2975 "target feature `{feat}` is both enabled and disabled"
2976 ));
2977 }
2978 } else {
2979 return Err(format!(
2980 "target feature `{feat}` is invalid, must start with `+` or `-`"
2981 ));
2982 }
2983 }
2984 let abi_feature_constraints = self.abi_required_features();
2986 for feat in abi_feature_constraints.required {
2987 if features_disabled.contains(feat) {
2990 return Err(format!(
2991 "target feature `{feat}` is required by the ABI but gets disabled in target spec"
2992 ));
2993 }
2994 }
2995 for feat in abi_feature_constraints.incompatible {
2996 if features_enabled.contains(feat) {
2999 return Err(format!(
3000 "target feature `{feat}` is incompatible with the ABI but gets enabled in target spec"
3001 ));
3002 }
3003 }
3004 }
3005
3006 Ok(())
3007 }
3008
3009 #[cfg(test)]
3011 fn test_target(mut self) {
3012 let recycled_target =
3013 Target::from_json(&serde_json::to_string(&self.to_json()).unwrap()).map(|(j, _)| j);
3014 self.update_to_cli();
3015 self.check_consistency(TargetKind::Builtin).unwrap();
3016 assert_eq!(recycled_target, Ok(self));
3017 }
3018
3019 fn can_use_os_unknown(&self) -> bool {
3022 self.llvm_target == "wasm32-unknown-unknown"
3023 || self.llvm_target == "wasm64-unknown-unknown"
3024 || (self.env == "sgx" && self.vendor == "fortanix")
3025 }
3026
3027 pub fn expect_builtin(target_tuple: &TargetTuple) -> Target {
3029 match *target_tuple {
3030 TargetTuple::TargetTuple(ref target_tuple) => {
3031 load_builtin(target_tuple).expect("built-in target")
3032 }
3033 TargetTuple::TargetJson { .. } => {
3034 panic!("built-in targets doesn't support target-paths")
3035 }
3036 }
3037 }
3038
3039 pub fn builtins() -> impl Iterator<Item = Target> {
3041 load_all_builtins()
3042 }
3043
3044 pub fn search(
3054 target_tuple: &TargetTuple,
3055 sysroot: &Path,
3056 ) -> Result<(Target, TargetWarnings), String> {
3057 use std::{env, fs};
3058
3059 fn load_file(path: &Path) -> Result<(Target, TargetWarnings), String> {
3060 let contents = fs::read_to_string(path).map_err(|e| e.to_string())?;
3061 Target::from_json(&contents)
3062 }
3063
3064 match *target_tuple {
3065 TargetTuple::TargetTuple(ref target_tuple) => {
3066 if let Some(t) = load_builtin(target_tuple) {
3068 return Ok((t, TargetWarnings::empty()));
3069 }
3070
3071 let path = {
3073 let mut target = target_tuple.to_string();
3074 target.push_str(".json");
3075 PathBuf::from(target)
3076 };
3077
3078 let target_path = env::var_os("RUST_TARGET_PATH").unwrap_or_default();
3079
3080 for dir in env::split_paths(&target_path) {
3081 let p = dir.join(&path);
3082 if p.is_file() {
3083 return load_file(&p);
3084 }
3085 }
3086
3087 let rustlib_path = crate::relative_target_rustlib_path(sysroot, target_tuple);
3090 let p = PathBuf::from_iter([
3091 Path::new(sysroot),
3092 Path::new(&rustlib_path),
3093 Path::new("target.json"),
3094 ]);
3095 if p.is_file() {
3096 return load_file(&p);
3097 }
3098
3099 if target_tuple == "i586-pc-windows-msvc" {
3103 Err("the `i586-pc-windows-msvc` target has been removed. Use the `i686-pc-windows-msvc` target instead.\n\
3104 Windows 10 (the minimum required OS version) requires a CPU baseline of at least i686 so you can safely switch".into())
3105 } else {
3106 Err(format!("could not find specification for target {target_tuple:?}"))
3107 }
3108 }
3109 TargetTuple::TargetJson { ref contents, .. } => Target::from_json(contents),
3110 }
3111 }
3112
3113 pub fn small_data_threshold_support(&self) -> SmallDataThresholdSupport {
3116 match &self.options.small_data_threshold_support {
3117 SmallDataThresholdSupport::DefaultForArch => match self.arch.as_ref() {
3121 "mips" | "mips64" | "mips32r6" => {
3122 SmallDataThresholdSupport::LlvmArg("mips-ssection-threshold".into())
3123 }
3124 "hexagon" => {
3125 SmallDataThresholdSupport::LlvmArg("hexagon-small-data-threshold".into())
3126 }
3127 "m68k" => SmallDataThresholdSupport::LlvmArg("m68k-ssection-threshold".into()),
3128 "riscv32" | "riscv64" => {
3129 SmallDataThresholdSupport::LlvmModuleFlag("SmallDataLimit".into())
3130 }
3131 _ => SmallDataThresholdSupport::None,
3132 },
3133 s => s.clone(),
3134 }
3135 }
3136
3137 pub fn object_architecture(
3138 &self,
3139 unstable_target_features: &FxIndexSet<Symbol>,
3140 ) -> Option<(object::Architecture, Option<object::SubArchitecture>)> {
3141 use object::Architecture;
3142 Some(match self.arch.as_ref() {
3143 "arm" => (Architecture::Arm, None),
3144 "aarch64" => (
3145 if self.pointer_width == 32 {
3146 Architecture::Aarch64_Ilp32
3147 } else {
3148 Architecture::Aarch64
3149 },
3150 None,
3151 ),
3152 "x86" => (Architecture::I386, None),
3153 "s390x" => (Architecture::S390x, None),
3154 "m68k" => (Architecture::M68k, None),
3155 "mips" | "mips32r6" => (Architecture::Mips, None),
3156 "mips64" | "mips64r6" => (
3157 if self.options.llvm_abiname.as_ref() == "n32" {
3163 Architecture::Mips64_N32
3164 } else {
3165 Architecture::Mips64
3166 },
3167 None,
3168 ),
3169 "x86_64" => (
3170 if self.pointer_width == 32 {
3171 Architecture::X86_64_X32
3172 } else {
3173 Architecture::X86_64
3174 },
3175 None,
3176 ),
3177 "powerpc" => (Architecture::PowerPc, None),
3178 "powerpc64" => (Architecture::PowerPc64, None),
3179 "riscv32" => (Architecture::Riscv32, None),
3180 "riscv64" => (Architecture::Riscv64, None),
3181 "sparc" => {
3182 if unstable_target_features.contains(&sym::v8plus) {
3183 (Architecture::Sparc32Plus, None)
3185 } else {
3186 (Architecture::Sparc, None)
3188 }
3189 }
3190 "sparc64" => (Architecture::Sparc64, None),
3191 "avr" => (Architecture::Avr, None),
3192 "msp430" => (Architecture::Msp430, None),
3193 "hexagon" => (Architecture::Hexagon, None),
3194 "bpf" => (Architecture::Bpf, None),
3195 "loongarch32" => (Architecture::LoongArch32, None),
3196 "loongarch64" => (Architecture::LoongArch64, None),
3197 "csky" => (Architecture::Csky, None),
3198 "arm64ec" => (Architecture::Aarch64, Some(object::SubArchitecture::Arm64EC)),
3199 _ => return None,
3201 })
3202 }
3203
3204 pub fn max_reliable_alignment(&self) -> Align {
3213 if self.is_like_windows && self.arch == "x86" {
3217 Align::from_bytes(4).unwrap()
3218 } else {
3219 Align::MAX
3220 }
3221 }
3222}
3223
3224#[derive(Clone, Debug)]
3226pub enum TargetTuple {
3227 TargetTuple(String),
3228 TargetJson {
3229 path_for_rustdoc: PathBuf,
3232 tuple: String,
3233 contents: String,
3234 },
3235}
3236
3237impl PartialEq for TargetTuple {
3239 fn eq(&self, other: &Self) -> bool {
3240 match (self, other) {
3241 (Self::TargetTuple(l0), Self::TargetTuple(r0)) => l0 == r0,
3242 (
3243 Self::TargetJson { path_for_rustdoc: _, tuple: l_tuple, contents: l_contents },
3244 Self::TargetJson { path_for_rustdoc: _, tuple: r_tuple, contents: r_contents },
3245 ) => l_tuple == r_tuple && l_contents == r_contents,
3246 _ => false,
3247 }
3248 }
3249}
3250
3251impl Hash for TargetTuple {
3253 fn hash<H: Hasher>(&self, state: &mut H) -> () {
3254 match self {
3255 TargetTuple::TargetTuple(tuple) => {
3256 0u8.hash(state);
3257 tuple.hash(state)
3258 }
3259 TargetTuple::TargetJson { path_for_rustdoc: _, tuple, contents } => {
3260 1u8.hash(state);
3261 tuple.hash(state);
3262 contents.hash(state)
3263 }
3264 }
3265 }
3266}
3267
3268impl<S: Encoder> Encodable<S> for TargetTuple {
3270 fn encode(&self, s: &mut S) {
3271 match self {
3272 TargetTuple::TargetTuple(tuple) => {
3273 s.emit_u8(0);
3274 s.emit_str(tuple);
3275 }
3276 TargetTuple::TargetJson { path_for_rustdoc: _, tuple, contents } => {
3277 s.emit_u8(1);
3278 s.emit_str(tuple);
3279 s.emit_str(contents);
3280 }
3281 }
3282 }
3283}
3284
3285impl<D: Decoder> Decodable<D> for TargetTuple {
3286 fn decode(d: &mut D) -> Self {
3287 match d.read_u8() {
3288 0 => TargetTuple::TargetTuple(d.read_str().to_owned()),
3289 1 => TargetTuple::TargetJson {
3290 path_for_rustdoc: PathBuf::new(),
3291 tuple: d.read_str().to_owned(),
3292 contents: d.read_str().to_owned(),
3293 },
3294 _ => {
3295 panic!("invalid enum variant tag while decoding `TargetTuple`, expected 0..2");
3296 }
3297 }
3298 }
3299}
3300
3301impl TargetTuple {
3302 pub fn from_tuple(tuple: &str) -> Self {
3304 TargetTuple::TargetTuple(tuple.into())
3305 }
3306
3307 pub fn from_path(path: &Path) -> Result<Self, io::Error> {
3309 let canonicalized_path = try_canonicalize(path)?;
3310 let contents = std::fs::read_to_string(&canonicalized_path).map_err(|err| {
3311 io::Error::new(
3312 io::ErrorKind::InvalidInput,
3313 format!("target path {canonicalized_path:?} is not a valid file: {err}"),
3314 )
3315 })?;
3316 let tuple = canonicalized_path
3317 .file_stem()
3318 .expect("target path must not be empty")
3319 .to_str()
3320 .expect("target path must be valid unicode")
3321 .to_owned();
3322 Ok(TargetTuple::TargetJson { path_for_rustdoc: canonicalized_path, tuple, contents })
3323 }
3324
3325 pub fn tuple(&self) -> &str {
3329 match *self {
3330 TargetTuple::TargetTuple(ref tuple) | TargetTuple::TargetJson { ref tuple, .. } => {
3331 tuple
3332 }
3333 }
3334 }
3335
3336 pub fn debug_tuple(&self) -> String {
3341 use std::hash::DefaultHasher;
3342
3343 match self {
3344 TargetTuple::TargetTuple(tuple) => tuple.to_owned(),
3345 TargetTuple::TargetJson { path_for_rustdoc: _, tuple, contents: content } => {
3346 let mut hasher = DefaultHasher::new();
3347 content.hash(&mut hasher);
3348 let hash = hasher.finish();
3349 format!("{tuple}-{hash}")
3350 }
3351 }
3352 }
3353}
3354
3355impl fmt::Display for TargetTuple {
3356 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3357 write!(f, "{}", self.debug_tuple())
3358 }
3359}
3360
3361into_diag_arg_using_display!(&TargetTuple);