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 }
1181}
1182rustc_data_structures::external_bitflags_debug! { SanitizerSet }
1183
1184impl SanitizerSet {
1185 const MUTUALLY_EXCLUSIVE: &'static [(SanitizerSet, SanitizerSet)] = &[
1188 (SanitizerSet::ADDRESS, SanitizerSet::MEMORY),
1189 (SanitizerSet::ADDRESS, SanitizerSet::THREAD),
1190 (SanitizerSet::ADDRESS, SanitizerSet::HWADDRESS),
1191 (SanitizerSet::ADDRESS, SanitizerSet::MEMTAG),
1192 (SanitizerSet::ADDRESS, SanitizerSet::KERNELADDRESS),
1193 (SanitizerSet::ADDRESS, SanitizerSet::SAFESTACK),
1194 (SanitizerSet::LEAK, SanitizerSet::MEMORY),
1195 (SanitizerSet::LEAK, SanitizerSet::THREAD),
1196 (SanitizerSet::LEAK, SanitizerSet::KERNELADDRESS),
1197 (SanitizerSet::LEAK, SanitizerSet::SAFESTACK),
1198 (SanitizerSet::MEMORY, SanitizerSet::THREAD),
1199 (SanitizerSet::MEMORY, SanitizerSet::HWADDRESS),
1200 (SanitizerSet::MEMORY, SanitizerSet::KERNELADDRESS),
1201 (SanitizerSet::MEMORY, SanitizerSet::SAFESTACK),
1202 (SanitizerSet::THREAD, SanitizerSet::HWADDRESS),
1203 (SanitizerSet::THREAD, SanitizerSet::KERNELADDRESS),
1204 (SanitizerSet::THREAD, SanitizerSet::SAFESTACK),
1205 (SanitizerSet::HWADDRESS, SanitizerSet::MEMTAG),
1206 (SanitizerSet::HWADDRESS, SanitizerSet::KERNELADDRESS),
1207 (SanitizerSet::HWADDRESS, SanitizerSet::SAFESTACK),
1208 (SanitizerSet::CFI, SanitizerSet::KCFI),
1209 (SanitizerSet::MEMTAG, SanitizerSet::KERNELADDRESS),
1210 (SanitizerSet::KERNELADDRESS, SanitizerSet::SAFESTACK),
1211 ];
1212
1213 pub fn as_str(self) -> Option<&'static str> {
1217 Some(match self {
1218 SanitizerSet::ADDRESS => "address",
1219 SanitizerSet::CFI => "cfi",
1220 SanitizerSet::DATAFLOW => "dataflow",
1221 SanitizerSet::KCFI => "kcfi",
1222 SanitizerSet::KERNELADDRESS => "kernel-address",
1223 SanitizerSet::LEAK => "leak",
1224 SanitizerSet::MEMORY => "memory",
1225 SanitizerSet::MEMTAG => "memtag",
1226 SanitizerSet::SAFESTACK => "safestack",
1227 SanitizerSet::SHADOWCALLSTACK => "shadow-call-stack",
1228 SanitizerSet::THREAD => "thread",
1229 SanitizerSet::HWADDRESS => "hwaddress",
1230 _ => return None,
1231 })
1232 }
1233
1234 pub fn mutually_exclusive(self) -> Option<(SanitizerSet, SanitizerSet)> {
1235 Self::MUTUALLY_EXCLUSIVE
1236 .into_iter()
1237 .find(|&(a, b)| self.contains(*a) && self.contains(*b))
1238 .copied()
1239 }
1240}
1241
1242impl fmt::Display for SanitizerSet {
1244 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1245 let mut first = true;
1246 for s in *self {
1247 let name = s.as_str().unwrap_or_else(|| panic!("unrecognized sanitizer {s:?}"));
1248 if !first {
1249 f.write_str(", ")?;
1250 }
1251 f.write_str(name)?;
1252 first = false;
1253 }
1254 Ok(())
1255 }
1256}
1257
1258impl FromStr for SanitizerSet {
1259 type Err = String;
1260 fn from_str(s: &str) -> Result<Self, Self::Err> {
1261 Ok(match s {
1262 "address" => SanitizerSet::ADDRESS,
1263 "cfi" => SanitizerSet::CFI,
1264 "dataflow" => SanitizerSet::DATAFLOW,
1265 "kcfi" => SanitizerSet::KCFI,
1266 "kernel-address" => SanitizerSet::KERNELADDRESS,
1267 "leak" => SanitizerSet::LEAK,
1268 "memory" => SanitizerSet::MEMORY,
1269 "memtag" => SanitizerSet::MEMTAG,
1270 "safestack" => SanitizerSet::SAFESTACK,
1271 "shadow-call-stack" => SanitizerSet::SHADOWCALLSTACK,
1272 "thread" => SanitizerSet::THREAD,
1273 "hwaddress" => SanitizerSet::HWADDRESS,
1274 s => return Err(format!("unknown sanitizer {s}")),
1275 })
1276 }
1277}
1278
1279crate::json::serde_deserialize_from_str!(SanitizerSet);
1280impl schemars::JsonSchema for SanitizerSet {
1281 fn schema_name() -> std::borrow::Cow<'static, str> {
1282 "SanitizerSet".into()
1283 }
1284 fn json_schema(_: &mut schemars::SchemaGenerator) -> schemars::Schema {
1285 let all = Self::all().iter().map(|sanitizer| sanitizer.as_str()).collect::<Vec<_>>();
1286 schemars::json_schema! ({
1287 "type": "string",
1288 "enum": all,
1289 })
1290 .into()
1291 }
1292}
1293
1294impl ToJson for SanitizerSet {
1295 fn to_json(&self) -> Json {
1296 self.into_iter()
1297 .map(|v| Some(v.as_str()?.to_json()))
1298 .collect::<Option<Vec<_>>>()
1299 .unwrap_or_default()
1300 .to_json()
1301 }
1302}
1303
1304crate::target_spec_enum! {
1305 pub enum FramePointer {
1306 Always = "always",
1308 NonLeaf = "non-leaf",
1311 MayOmit = "may-omit",
1315 }
1316
1317 parse_error_type = "frame pointer";
1318}
1319
1320impl FramePointer {
1321 #[inline]
1324 pub fn ratchet(&mut self, rhs: FramePointer) -> FramePointer {
1325 *self = match (*self, rhs) {
1326 (FramePointer::Always, _) | (_, FramePointer::Always) => FramePointer::Always,
1327 (FramePointer::NonLeaf, _) | (_, FramePointer::NonLeaf) => FramePointer::NonLeaf,
1328 _ => FramePointer::MayOmit,
1329 };
1330 *self
1331 }
1332}
1333
1334crate::target_spec_enum! {
1335 pub enum StackProtector {
1337 None = "none",
1339
1340 Basic = "basic",
1345
1346 Strong = "strong",
1351
1352 All = "all",
1354 }
1355
1356 parse_error_type = "stack protector";
1357}
1358
1359into_diag_arg_using_display!(StackProtector);
1360
1361crate::target_spec_enum! {
1362 pub enum BinaryFormat {
1363 Coff = "coff",
1364 Elf = "elf",
1365 MachO = "mach-o",
1366 Wasm = "wasm",
1367 Xcoff = "xcoff",
1368 }
1369
1370 parse_error_type = "binary format";
1371}
1372
1373impl BinaryFormat {
1374 pub fn to_object(&self) -> object::BinaryFormat {
1376 match self {
1377 Self::Coff => object::BinaryFormat::Coff,
1378 Self::Elf => object::BinaryFormat::Elf,
1379 Self::MachO => object::BinaryFormat::MachO,
1380 Self::Wasm => object::BinaryFormat::Wasm,
1381 Self::Xcoff => object::BinaryFormat::Xcoff,
1382 }
1383 }
1384}
1385
1386impl ToJson for Align {
1387 fn to_json(&self) -> Json {
1388 self.bits().to_json()
1389 }
1390}
1391
1392macro_rules! supported_targets {
1393 ( $(($tuple:literal, $module:ident),)+ ) => {
1394 mod targets {
1395 $(pub(crate) mod $module;)+
1396 }
1397
1398 pub static TARGETS: &[&str] = &[$($tuple),+];
1400
1401 fn load_builtin(target: &str) -> Option<Target> {
1402 let t = match target {
1403 $( $tuple => targets::$module::target(), )+
1404 _ => return None,
1405 };
1406 debug!("got builtin target: {:?}", t);
1407 Some(t)
1408 }
1409
1410 fn load_all_builtins() -> impl Iterator<Item = Target> {
1411 [
1412 $( targets::$module::target, )+
1413 ]
1414 .into_iter()
1415 .map(|f| f())
1416 }
1417
1418 #[cfg(test)]
1419 mod tests {
1420 $(
1422 #[test] fn $module() {
1424 crate::spec::targets::$module::target().test_target()
1425 }
1426 )+
1427 }
1428 };
1429}
1430
1431supported_targets! {
1432 ("x86_64-unknown-linux-gnu", x86_64_unknown_linux_gnu),
1433 ("x86_64-unknown-linux-gnux32", x86_64_unknown_linux_gnux32),
1434 ("i686-unknown-linux-gnu", i686_unknown_linux_gnu),
1435 ("i586-unknown-linux-gnu", i586_unknown_linux_gnu),
1436 ("loongarch64-unknown-linux-gnu", loongarch64_unknown_linux_gnu),
1437 ("loongarch64-unknown-linux-musl", loongarch64_unknown_linux_musl),
1438 ("m68k-unknown-linux-gnu", m68k_unknown_linux_gnu),
1439 ("m68k-unknown-none-elf", m68k_unknown_none_elf),
1440 ("csky-unknown-linux-gnuabiv2", csky_unknown_linux_gnuabiv2),
1441 ("csky-unknown-linux-gnuabiv2hf", csky_unknown_linux_gnuabiv2hf),
1442 ("mips-unknown-linux-gnu", mips_unknown_linux_gnu),
1443 ("mips64-unknown-linux-gnuabi64", mips64_unknown_linux_gnuabi64),
1444 ("mips64el-unknown-linux-gnuabi64", mips64el_unknown_linux_gnuabi64),
1445 ("mipsisa32r6-unknown-linux-gnu", mipsisa32r6_unknown_linux_gnu),
1446 ("mipsisa32r6el-unknown-linux-gnu", mipsisa32r6el_unknown_linux_gnu),
1447 ("mipsisa64r6-unknown-linux-gnuabi64", mipsisa64r6_unknown_linux_gnuabi64),
1448 ("mipsisa64r6el-unknown-linux-gnuabi64", mipsisa64r6el_unknown_linux_gnuabi64),
1449 ("mipsel-unknown-linux-gnu", mipsel_unknown_linux_gnu),
1450 ("powerpc-unknown-linux-gnu", powerpc_unknown_linux_gnu),
1451 ("powerpc-unknown-linux-gnuspe", powerpc_unknown_linux_gnuspe),
1452 ("powerpc-unknown-linux-musl", powerpc_unknown_linux_musl),
1453 ("powerpc-unknown-linux-muslspe", powerpc_unknown_linux_muslspe),
1454 ("powerpc64-ibm-aix", powerpc64_ibm_aix),
1455 ("powerpc64-unknown-linux-gnu", powerpc64_unknown_linux_gnu),
1456 ("powerpc64-unknown-linux-musl", powerpc64_unknown_linux_musl),
1457 ("powerpc64le-unknown-linux-gnu", powerpc64le_unknown_linux_gnu),
1458 ("powerpc64le-unknown-linux-musl", powerpc64le_unknown_linux_musl),
1459 ("s390x-unknown-linux-gnu", s390x_unknown_linux_gnu),
1460 ("s390x-unknown-linux-musl", s390x_unknown_linux_musl),
1461 ("sparc-unknown-linux-gnu", sparc_unknown_linux_gnu),
1462 ("sparc64-unknown-linux-gnu", sparc64_unknown_linux_gnu),
1463 ("arm-unknown-linux-gnueabi", arm_unknown_linux_gnueabi),
1464 ("arm-unknown-linux-gnueabihf", arm_unknown_linux_gnueabihf),
1465 ("armeb-unknown-linux-gnueabi", armeb_unknown_linux_gnueabi),
1466 ("arm-unknown-linux-musleabi", arm_unknown_linux_musleabi),
1467 ("arm-unknown-linux-musleabihf", arm_unknown_linux_musleabihf),
1468 ("armv4t-unknown-linux-gnueabi", armv4t_unknown_linux_gnueabi),
1469 ("armv5te-unknown-linux-gnueabi", armv5te_unknown_linux_gnueabi),
1470 ("armv5te-unknown-linux-musleabi", armv5te_unknown_linux_musleabi),
1471 ("armv5te-unknown-linux-uclibceabi", armv5te_unknown_linux_uclibceabi),
1472 ("armv7-unknown-linux-gnueabi", armv7_unknown_linux_gnueabi),
1473 ("armv7-unknown-linux-gnueabihf", armv7_unknown_linux_gnueabihf),
1474 ("thumbv7neon-unknown-linux-gnueabihf", thumbv7neon_unknown_linux_gnueabihf),
1475 ("thumbv7neon-unknown-linux-musleabihf", thumbv7neon_unknown_linux_musleabihf),
1476 ("armv7-unknown-linux-musleabi", armv7_unknown_linux_musleabi),
1477 ("armv7-unknown-linux-musleabihf", armv7_unknown_linux_musleabihf),
1478 ("aarch64-unknown-linux-gnu", aarch64_unknown_linux_gnu),
1479 ("aarch64-unknown-linux-musl", aarch64_unknown_linux_musl),
1480 ("aarch64_be-unknown-linux-musl", aarch64_be_unknown_linux_musl),
1481 ("x86_64-unknown-linux-musl", x86_64_unknown_linux_musl),
1482 ("i686-unknown-linux-musl", i686_unknown_linux_musl),
1483 ("i586-unknown-linux-musl", i586_unknown_linux_musl),
1484 ("mips-unknown-linux-musl", mips_unknown_linux_musl),
1485 ("mipsel-unknown-linux-musl", mipsel_unknown_linux_musl),
1486 ("mips64-unknown-linux-muslabi64", mips64_unknown_linux_muslabi64),
1487 ("mips64el-unknown-linux-muslabi64", mips64el_unknown_linux_muslabi64),
1488 ("hexagon-unknown-linux-musl", hexagon_unknown_linux_musl),
1489 ("hexagon-unknown-none-elf", hexagon_unknown_none_elf),
1490
1491 ("mips-unknown-linux-uclibc", mips_unknown_linux_uclibc),
1492 ("mipsel-unknown-linux-uclibc", mipsel_unknown_linux_uclibc),
1493
1494 ("i686-linux-android", i686_linux_android),
1495 ("x86_64-linux-android", x86_64_linux_android),
1496 ("arm-linux-androideabi", arm_linux_androideabi),
1497 ("armv7-linux-androideabi", armv7_linux_androideabi),
1498 ("thumbv7neon-linux-androideabi", thumbv7neon_linux_androideabi),
1499 ("aarch64-linux-android", aarch64_linux_android),
1500 ("riscv64-linux-android", riscv64_linux_android),
1501
1502 ("aarch64-unknown-freebsd", aarch64_unknown_freebsd),
1503 ("armv6-unknown-freebsd", armv6_unknown_freebsd),
1504 ("armv7-unknown-freebsd", armv7_unknown_freebsd),
1505 ("i686-unknown-freebsd", i686_unknown_freebsd),
1506 ("powerpc-unknown-freebsd", powerpc_unknown_freebsd),
1507 ("powerpc64-unknown-freebsd", powerpc64_unknown_freebsd),
1508 ("powerpc64le-unknown-freebsd", powerpc64le_unknown_freebsd),
1509 ("riscv64gc-unknown-freebsd", riscv64gc_unknown_freebsd),
1510 ("x86_64-unknown-freebsd", x86_64_unknown_freebsd),
1511
1512 ("x86_64-unknown-dragonfly", x86_64_unknown_dragonfly),
1513
1514 ("aarch64-unknown-openbsd", aarch64_unknown_openbsd),
1515 ("i686-unknown-openbsd", i686_unknown_openbsd),
1516 ("powerpc-unknown-openbsd", powerpc_unknown_openbsd),
1517 ("powerpc64-unknown-openbsd", powerpc64_unknown_openbsd),
1518 ("riscv64gc-unknown-openbsd", riscv64gc_unknown_openbsd),
1519 ("sparc64-unknown-openbsd", sparc64_unknown_openbsd),
1520 ("x86_64-unknown-openbsd", x86_64_unknown_openbsd),
1521
1522 ("aarch64-unknown-netbsd", aarch64_unknown_netbsd),
1523 ("aarch64_be-unknown-netbsd", aarch64_be_unknown_netbsd),
1524 ("armv6-unknown-netbsd-eabihf", armv6_unknown_netbsd_eabihf),
1525 ("armv7-unknown-netbsd-eabihf", armv7_unknown_netbsd_eabihf),
1526 ("i586-unknown-netbsd", i586_unknown_netbsd),
1527 ("i686-unknown-netbsd", i686_unknown_netbsd),
1528 ("mipsel-unknown-netbsd", mipsel_unknown_netbsd),
1529 ("powerpc-unknown-netbsd", powerpc_unknown_netbsd),
1530 ("riscv64gc-unknown-netbsd", riscv64gc_unknown_netbsd),
1531 ("sparc64-unknown-netbsd", sparc64_unknown_netbsd),
1532 ("x86_64-unknown-netbsd", x86_64_unknown_netbsd),
1533
1534 ("i686-unknown-haiku", i686_unknown_haiku),
1535 ("x86_64-unknown-haiku", x86_64_unknown_haiku),
1536
1537 ("i686-unknown-hurd-gnu", i686_unknown_hurd_gnu),
1538 ("x86_64-unknown-hurd-gnu", x86_64_unknown_hurd_gnu),
1539
1540 ("aarch64-apple-darwin", aarch64_apple_darwin),
1541 ("arm64e-apple-darwin", arm64e_apple_darwin),
1542 ("x86_64-apple-darwin", x86_64_apple_darwin),
1543 ("x86_64h-apple-darwin", x86_64h_apple_darwin),
1544 ("i686-apple-darwin", i686_apple_darwin),
1545
1546 ("aarch64-unknown-fuchsia", aarch64_unknown_fuchsia),
1547 ("riscv64gc-unknown-fuchsia", riscv64gc_unknown_fuchsia),
1548 ("x86_64-unknown-fuchsia", x86_64_unknown_fuchsia),
1549
1550 ("avr-none", avr_none),
1551
1552 ("x86_64-unknown-l4re-uclibc", x86_64_unknown_l4re_uclibc),
1553
1554 ("aarch64-unknown-redox", aarch64_unknown_redox),
1555 ("i586-unknown-redox", i586_unknown_redox),
1556 ("x86_64-unknown-redox", x86_64_unknown_redox),
1557
1558 ("x86_64-unknown-managarm-mlibc", x86_64_unknown_managarm_mlibc),
1559 ("aarch64-unknown-managarm-mlibc", aarch64_unknown_managarm_mlibc),
1560 ("riscv64gc-unknown-managarm-mlibc", riscv64gc_unknown_managarm_mlibc),
1561
1562 ("i386-apple-ios", i386_apple_ios),
1563 ("x86_64-apple-ios", x86_64_apple_ios),
1564 ("aarch64-apple-ios", aarch64_apple_ios),
1565 ("arm64e-apple-ios", arm64e_apple_ios),
1566 ("armv7s-apple-ios", armv7s_apple_ios),
1567 ("x86_64-apple-ios-macabi", x86_64_apple_ios_macabi),
1568 ("aarch64-apple-ios-macabi", aarch64_apple_ios_macabi),
1569 ("aarch64-apple-ios-sim", aarch64_apple_ios_sim),
1570
1571 ("aarch64-apple-tvos", aarch64_apple_tvos),
1572 ("aarch64-apple-tvos-sim", aarch64_apple_tvos_sim),
1573 ("arm64e-apple-tvos", arm64e_apple_tvos),
1574 ("x86_64-apple-tvos", x86_64_apple_tvos),
1575
1576 ("armv7k-apple-watchos", armv7k_apple_watchos),
1577 ("arm64_32-apple-watchos", arm64_32_apple_watchos),
1578 ("x86_64-apple-watchos-sim", x86_64_apple_watchos_sim),
1579 ("aarch64-apple-watchos", aarch64_apple_watchos),
1580 ("aarch64-apple-watchos-sim", aarch64_apple_watchos_sim),
1581
1582 ("aarch64-apple-visionos", aarch64_apple_visionos),
1583 ("aarch64-apple-visionos-sim", aarch64_apple_visionos_sim),
1584
1585 ("armebv7r-none-eabi", armebv7r_none_eabi),
1586 ("armebv7r-none-eabihf", armebv7r_none_eabihf),
1587 ("armv7r-none-eabi", armv7r_none_eabi),
1588 ("armv7r-none-eabihf", armv7r_none_eabihf),
1589 ("armv8r-none-eabihf", armv8r_none_eabihf),
1590
1591 ("armv7-rtems-eabihf", armv7_rtems_eabihf),
1592
1593 ("x86_64-pc-solaris", x86_64_pc_solaris),
1594 ("sparcv9-sun-solaris", sparcv9_sun_solaris),
1595
1596 ("x86_64-unknown-illumos", x86_64_unknown_illumos),
1597 ("aarch64-unknown-illumos", aarch64_unknown_illumos),
1598
1599 ("x86_64-pc-windows-gnu", x86_64_pc_windows_gnu),
1600 ("x86_64-uwp-windows-gnu", x86_64_uwp_windows_gnu),
1601 ("x86_64-win7-windows-gnu", x86_64_win7_windows_gnu),
1602 ("i686-pc-windows-gnu", i686_pc_windows_gnu),
1603 ("i686-uwp-windows-gnu", i686_uwp_windows_gnu),
1604 ("i686-win7-windows-gnu", i686_win7_windows_gnu),
1605
1606 ("aarch64-pc-windows-gnullvm", aarch64_pc_windows_gnullvm),
1607 ("i686-pc-windows-gnullvm", i686_pc_windows_gnullvm),
1608 ("x86_64-pc-windows-gnullvm", x86_64_pc_windows_gnullvm),
1609
1610 ("aarch64-pc-windows-msvc", aarch64_pc_windows_msvc),
1611 ("aarch64-uwp-windows-msvc", aarch64_uwp_windows_msvc),
1612 ("arm64ec-pc-windows-msvc", arm64ec_pc_windows_msvc),
1613 ("x86_64-pc-windows-msvc", x86_64_pc_windows_msvc),
1614 ("x86_64-uwp-windows-msvc", x86_64_uwp_windows_msvc),
1615 ("x86_64-win7-windows-msvc", x86_64_win7_windows_msvc),
1616 ("i686-pc-windows-msvc", i686_pc_windows_msvc),
1617 ("i686-uwp-windows-msvc", i686_uwp_windows_msvc),
1618 ("i686-win7-windows-msvc", i686_win7_windows_msvc),
1619 ("thumbv7a-pc-windows-msvc", thumbv7a_pc_windows_msvc),
1620 ("thumbv7a-uwp-windows-msvc", thumbv7a_uwp_windows_msvc),
1621
1622 ("wasm32-unknown-emscripten", wasm32_unknown_emscripten),
1623 ("wasm32-unknown-unknown", wasm32_unknown_unknown),
1624 ("wasm32v1-none", wasm32v1_none),
1625 ("wasm32-wasip1", wasm32_wasip1),
1626 ("wasm32-wasip2", wasm32_wasip2),
1627 ("wasm32-wasip3", wasm32_wasip3),
1628 ("wasm32-wasip1-threads", wasm32_wasip1_threads),
1629 ("wasm32-wali-linux-musl", wasm32_wali_linux_musl),
1630 ("wasm64-unknown-unknown", wasm64_unknown_unknown),
1631
1632 ("thumbv6m-none-eabi", thumbv6m_none_eabi),
1633 ("thumbv7m-none-eabi", thumbv7m_none_eabi),
1634 ("thumbv7em-none-eabi", thumbv7em_none_eabi),
1635 ("thumbv7em-none-eabihf", thumbv7em_none_eabihf),
1636 ("thumbv8m.base-none-eabi", thumbv8m_base_none_eabi),
1637 ("thumbv8m.main-none-eabi", thumbv8m_main_none_eabi),
1638 ("thumbv8m.main-none-eabihf", thumbv8m_main_none_eabihf),
1639
1640 ("armv7a-none-eabi", armv7a_none_eabi),
1641 ("armv7a-none-eabihf", armv7a_none_eabihf),
1642 ("armv7a-nuttx-eabi", armv7a_nuttx_eabi),
1643 ("armv7a-nuttx-eabihf", armv7a_nuttx_eabihf),
1644 ("armv7a-vex-v5", armv7a_vex_v5),
1645
1646 ("msp430-none-elf", msp430_none_elf),
1647
1648 ("aarch64_be-unknown-hermit", aarch64_be_unknown_hermit),
1649 ("aarch64-unknown-hermit", aarch64_unknown_hermit),
1650 ("riscv64gc-unknown-hermit", riscv64gc_unknown_hermit),
1651 ("x86_64-unknown-hermit", x86_64_unknown_hermit),
1652 ("x86_64-unknown-motor", x86_64_unknown_motor),
1653
1654 ("x86_64-unikraft-linux-musl", x86_64_unikraft_linux_musl),
1655
1656 ("armv7-unknown-trusty", armv7_unknown_trusty),
1657 ("aarch64-unknown-trusty", aarch64_unknown_trusty),
1658 ("x86_64-unknown-trusty", x86_64_unknown_trusty),
1659
1660 ("riscv32i-unknown-none-elf", riscv32i_unknown_none_elf),
1661 ("riscv32im-risc0-zkvm-elf", riscv32im_risc0_zkvm_elf),
1662 ("riscv32im-unknown-none-elf", riscv32im_unknown_none_elf),
1663 ("riscv32ima-unknown-none-elf", riscv32ima_unknown_none_elf),
1664 ("riscv32imc-unknown-none-elf", riscv32imc_unknown_none_elf),
1665 ("riscv32imc-esp-espidf", riscv32imc_esp_espidf),
1666 ("riscv32imac-esp-espidf", riscv32imac_esp_espidf),
1667 ("riscv32imafc-esp-espidf", riscv32imafc_esp_espidf),
1668
1669 ("riscv32e-unknown-none-elf", riscv32e_unknown_none_elf),
1670 ("riscv32em-unknown-none-elf", riscv32em_unknown_none_elf),
1671 ("riscv32emc-unknown-none-elf", riscv32emc_unknown_none_elf),
1672
1673 ("riscv32imac-unknown-none-elf", riscv32imac_unknown_none_elf),
1674 ("riscv32imafc-unknown-none-elf", riscv32imafc_unknown_none_elf),
1675 ("riscv32imac-unknown-xous-elf", riscv32imac_unknown_xous_elf),
1676 ("riscv32gc-unknown-linux-gnu", riscv32gc_unknown_linux_gnu),
1677 ("riscv32gc-unknown-linux-musl", riscv32gc_unknown_linux_musl),
1678 ("riscv64imac-unknown-none-elf", riscv64imac_unknown_none_elf),
1679 ("riscv64gc-unknown-none-elf", riscv64gc_unknown_none_elf),
1680 ("riscv64gc-unknown-linux-gnu", riscv64gc_unknown_linux_gnu),
1681 ("riscv64gc-unknown-linux-musl", riscv64gc_unknown_linux_musl),
1682 ("riscv64a23-unknown-linux-gnu", riscv64a23_unknown_linux_gnu),
1683
1684 ("sparc-unknown-none-elf", sparc_unknown_none_elf),
1685
1686 ("loongarch32-unknown-none", loongarch32_unknown_none),
1687 ("loongarch32-unknown-none-softfloat", loongarch32_unknown_none_softfloat),
1688 ("loongarch64-unknown-none", loongarch64_unknown_none),
1689 ("loongarch64-unknown-none-softfloat", loongarch64_unknown_none_softfloat),
1690
1691 ("aarch64-unknown-none", aarch64_unknown_none),
1692 ("aarch64-unknown-none-softfloat", aarch64_unknown_none_softfloat),
1693 ("aarch64_be-unknown-none-softfloat", aarch64_be_unknown_none_softfloat),
1694 ("aarch64-unknown-nuttx", aarch64_unknown_nuttx),
1695
1696 ("x86_64-fortanix-unknown-sgx", x86_64_fortanix_unknown_sgx),
1697
1698 ("x86_64-unknown-uefi", x86_64_unknown_uefi),
1699 ("i686-unknown-uefi", i686_unknown_uefi),
1700 ("aarch64-unknown-uefi", aarch64_unknown_uefi),
1701
1702 ("nvptx64-nvidia-cuda", nvptx64_nvidia_cuda),
1703
1704 ("amdgcn-amd-amdhsa", amdgcn_amd_amdhsa),
1705
1706 ("xtensa-esp32-none-elf", xtensa_esp32_none_elf),
1707 ("xtensa-esp32-espidf", xtensa_esp32_espidf),
1708 ("xtensa-esp32s2-none-elf", xtensa_esp32s2_none_elf),
1709 ("xtensa-esp32s2-espidf", xtensa_esp32s2_espidf),
1710 ("xtensa-esp32s3-none-elf", xtensa_esp32s3_none_elf),
1711 ("xtensa-esp32s3-espidf", xtensa_esp32s3_espidf),
1712
1713 ("i686-wrs-vxworks", i686_wrs_vxworks),
1714 ("x86_64-wrs-vxworks", x86_64_wrs_vxworks),
1715 ("armv7-wrs-vxworks-eabihf", armv7_wrs_vxworks_eabihf),
1716 ("aarch64-wrs-vxworks", aarch64_wrs_vxworks),
1717 ("powerpc-wrs-vxworks", powerpc_wrs_vxworks),
1718 ("powerpc-wrs-vxworks-spe", powerpc_wrs_vxworks_spe),
1719 ("powerpc64-wrs-vxworks", powerpc64_wrs_vxworks),
1720 ("riscv32-wrs-vxworks", riscv32_wrs_vxworks),
1721 ("riscv64-wrs-vxworks", riscv64_wrs_vxworks),
1722
1723 ("aarch64-kmc-solid_asp3", aarch64_kmc_solid_asp3),
1724 ("armv7a-kmc-solid_asp3-eabi", armv7a_kmc_solid_asp3_eabi),
1725 ("armv7a-kmc-solid_asp3-eabihf", armv7a_kmc_solid_asp3_eabihf),
1726
1727 ("mipsel-sony-psp", mipsel_sony_psp),
1728 ("mipsel-sony-psx", mipsel_sony_psx),
1729 ("mipsel-unknown-none", mipsel_unknown_none),
1730 ("mips-mti-none-elf", mips_mti_none_elf),
1731 ("mipsel-mti-none-elf", mipsel_mti_none_elf),
1732 ("thumbv4t-none-eabi", thumbv4t_none_eabi),
1733 ("armv4t-none-eabi", armv4t_none_eabi),
1734 ("thumbv5te-none-eabi", thumbv5te_none_eabi),
1735 ("armv5te-none-eabi", armv5te_none_eabi),
1736
1737 ("aarch64_be-unknown-linux-gnu", aarch64_be_unknown_linux_gnu),
1738 ("aarch64-unknown-linux-gnu_ilp32", aarch64_unknown_linux_gnu_ilp32),
1739 ("aarch64_be-unknown-linux-gnu_ilp32", aarch64_be_unknown_linux_gnu_ilp32),
1740
1741 ("bpfeb-unknown-none", bpfeb_unknown_none),
1742 ("bpfel-unknown-none", bpfel_unknown_none),
1743
1744 ("armv6k-nintendo-3ds", armv6k_nintendo_3ds),
1745
1746 ("aarch64-nintendo-switch-freestanding", aarch64_nintendo_switch_freestanding),
1747
1748 ("armv7-sony-vita-newlibeabihf", armv7_sony_vita_newlibeabihf),
1749
1750 ("armv7-unknown-linux-uclibceabi", armv7_unknown_linux_uclibceabi),
1751 ("armv7-unknown-linux-uclibceabihf", armv7_unknown_linux_uclibceabihf),
1752
1753 ("x86_64-unknown-none", x86_64_unknown_none),
1754
1755 ("aarch64-unknown-teeos", aarch64_unknown_teeos),
1756
1757 ("mips64-openwrt-linux-musl", mips64_openwrt_linux_musl),
1758
1759 ("aarch64-unknown-nto-qnx700", aarch64_unknown_nto_qnx700),
1760 ("aarch64-unknown-nto-qnx710", aarch64_unknown_nto_qnx710),
1761 ("aarch64-unknown-nto-qnx710_iosock", aarch64_unknown_nto_qnx710_iosock),
1762 ("aarch64-unknown-nto-qnx800", aarch64_unknown_nto_qnx800),
1763 ("x86_64-pc-nto-qnx710", x86_64_pc_nto_qnx710),
1764 ("x86_64-pc-nto-qnx710_iosock", x86_64_pc_nto_qnx710_iosock),
1765 ("x86_64-pc-nto-qnx800", x86_64_pc_nto_qnx800),
1766 ("i686-pc-nto-qnx700", i686_pc_nto_qnx700),
1767
1768 ("aarch64-unknown-linux-ohos", aarch64_unknown_linux_ohos),
1769 ("armv7-unknown-linux-ohos", armv7_unknown_linux_ohos),
1770 ("loongarch64-unknown-linux-ohos", loongarch64_unknown_linux_ohos),
1771 ("x86_64-unknown-linux-ohos", x86_64_unknown_linux_ohos),
1772
1773 ("x86_64-unknown-linux-none", x86_64_unknown_linux_none),
1774
1775 ("thumbv6m-nuttx-eabi", thumbv6m_nuttx_eabi),
1776 ("thumbv7a-nuttx-eabi", thumbv7a_nuttx_eabi),
1777 ("thumbv7a-nuttx-eabihf", thumbv7a_nuttx_eabihf),
1778 ("thumbv7m-nuttx-eabi", thumbv7m_nuttx_eabi),
1779 ("thumbv7em-nuttx-eabi", thumbv7em_nuttx_eabi),
1780 ("thumbv7em-nuttx-eabihf", thumbv7em_nuttx_eabihf),
1781 ("thumbv8m.base-nuttx-eabi", thumbv8m_base_nuttx_eabi),
1782 ("thumbv8m.main-nuttx-eabi", thumbv8m_main_nuttx_eabi),
1783 ("thumbv8m.main-nuttx-eabihf", thumbv8m_main_nuttx_eabihf),
1784 ("riscv32imc-unknown-nuttx-elf", riscv32imc_unknown_nuttx_elf),
1785 ("riscv32imac-unknown-nuttx-elf", riscv32imac_unknown_nuttx_elf),
1786 ("riscv32imafc-unknown-nuttx-elf", riscv32imafc_unknown_nuttx_elf),
1787 ("riscv64imac-unknown-nuttx-elf", riscv64imac_unknown_nuttx_elf),
1788 ("riscv64gc-unknown-nuttx-elf", riscv64gc_unknown_nuttx_elf),
1789 ("x86_64-lynx-lynxos178", x86_64_lynx_lynxos178),
1790
1791 ("x86_64-pc-cygwin", x86_64_pc_cygwin),
1792}
1793
1794macro_rules! cvs {
1796 () => {
1797 ::std::borrow::Cow::Borrowed(&[])
1798 };
1799 ($($x:expr),+ $(,)?) => {
1800 ::std::borrow::Cow::Borrowed(&[
1801 $(
1802 ::std::borrow::Cow::Borrowed($x),
1803 )*
1804 ])
1805 };
1806}
1807
1808pub(crate) use cvs;
1809
1810#[derive(Debug, PartialEq)]
1814pub struct TargetWarnings {
1815 unused_fields: Vec<String>,
1816}
1817
1818impl TargetWarnings {
1819 pub fn empty() -> Self {
1820 Self { unused_fields: Vec::new() }
1821 }
1822
1823 pub fn warning_messages(&self) -> Vec<String> {
1824 let mut warnings = vec![];
1825 if !self.unused_fields.is_empty() {
1826 warnings.push(format!(
1827 "target json file contains unused fields: {}",
1828 self.unused_fields.join(", ")
1829 ));
1830 }
1831 warnings
1832 }
1833}
1834
1835#[derive(Copy, Clone, Debug, PartialEq)]
1838enum TargetKind {
1839 Json,
1840 Builtin,
1841}
1842
1843#[derive(PartialEq, Clone, Debug)]
1847pub struct Target {
1848 pub llvm_target: StaticCow<str>,
1855 pub metadata: TargetMetadata,
1858 pub pointer_width: u16,
1860 pub arch: StaticCow<str>,
1863 pub data_layout: StaticCow<str>,
1865 pub options: TargetOptions,
1867}
1868
1869#[derive(Default, PartialEq, Clone, Debug)]
1873pub struct TargetMetadata {
1874 pub description: Option<StaticCow<str>>,
1877 pub tier: Option<u64>,
1879 pub host_tools: Option<bool>,
1881 pub std: Option<bool>,
1884}
1885
1886impl Target {
1887 pub fn parse_data_layout(&self) -> Result<TargetDataLayout, TargetDataLayoutErrors<'_>> {
1888 let mut dl = TargetDataLayout::parse_from_llvm_datalayout_string(
1889 &self.data_layout,
1890 self.options.default_address_space,
1891 )?;
1892
1893 if dl.endian != self.endian {
1895 return Err(TargetDataLayoutErrors::InconsistentTargetArchitecture {
1896 dl: dl.endian.as_str(),
1897 target: self.endian.as_str(),
1898 });
1899 }
1900
1901 let target_pointer_width: u64 = self.pointer_width.into();
1902 let dl_pointer_size: u64 = dl.pointer_size().bits();
1903 if dl_pointer_size != target_pointer_width {
1904 return Err(TargetDataLayoutErrors::InconsistentTargetPointerWidth {
1905 pointer_size: dl_pointer_size,
1906 target: self.pointer_width,
1907 });
1908 }
1909
1910 dl.c_enum_min_size = Integer::from_size(Size::from_bits(
1911 self.c_enum_min_bits.unwrap_or(self.c_int_width as _),
1912 ))
1913 .map_err(|err| TargetDataLayoutErrors::InvalidBitsSize { err })?;
1914
1915 Ok(dl)
1916 }
1917}
1918
1919pub trait HasTargetSpec {
1920 fn target_spec(&self) -> &Target;
1921}
1922
1923impl HasTargetSpec for Target {
1924 #[inline]
1925 fn target_spec(&self) -> &Target {
1926 self
1927 }
1928}
1929
1930#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
1932pub struct X86Abi {
1933 pub regparm: Option<u32>,
1936 pub reg_struct_return: bool,
1938}
1939
1940pub trait HasX86AbiOpt {
1941 fn x86_abi_opt(&self) -> X86Abi;
1942}
1943
1944type StaticCow<T> = Cow<'static, T>;
1945
1946#[derive(PartialEq, Clone, Debug)]
1955pub struct TargetOptions {
1956 pub endian: Endian,
1958 pub c_int_width: u16,
1960 pub os: StaticCow<str>,
1965 pub env: StaticCow<str>,
1967 pub abi: StaticCow<str>,
1972 pub vendor: StaticCow<str>,
1974
1975 pub linker: Option<StaticCow<str>>,
1977 pub linker_flavor: LinkerFlavor,
1980 linker_flavor_json: LinkerFlavorCli,
1981 lld_flavor_json: LldFlavor,
1982 linker_is_gnu_json: bool,
1983
1984 pub pre_link_objects: CrtObjects,
1986 pub post_link_objects: CrtObjects,
1987 pub pre_link_objects_self_contained: CrtObjects,
1989 pub post_link_objects_self_contained: CrtObjects,
1990 pub link_self_contained: LinkSelfContainedDefault,
1993
1994 pub pre_link_args: LinkArgs,
1996 pre_link_args_json: LinkArgsCli,
1997 pub late_link_args: LinkArgs,
2001 late_link_args_json: LinkArgsCli,
2002 pub late_link_args_dynamic: LinkArgs,
2005 late_link_args_dynamic_json: LinkArgsCli,
2006 pub late_link_args_static: LinkArgs,
2009 late_link_args_static_json: LinkArgsCli,
2010 pub post_link_args: LinkArgs,
2013 post_link_args_json: LinkArgsCli,
2014
2015 pub link_script: Option<StaticCow<str>>,
2019 pub link_env: StaticCow<[(StaticCow<str>, StaticCow<str>)]>,
2021 pub link_env_remove: StaticCow<[StaticCow<str>]>,
2023
2024 pub asm_args: StaticCow<[StaticCow<str>]>,
2026
2027 pub cpu: StaticCow<str>,
2030 pub need_explicit_cpu: bool,
2033 pub features: StaticCow<str>,
2042 pub direct_access_external_data: Option<bool>,
2044 pub dynamic_linking: bool,
2046 pub dll_tls_export: bool,
2048 pub only_cdylib: bool,
2050 pub executables: bool,
2052 pub relocation_model: RelocModel,
2055 pub code_model: Option<CodeModel>,
2058 pub tls_model: TlsModel,
2061 pub disable_redzone: bool,
2063 pub frame_pointer: FramePointer,
2065 pub function_sections: bool,
2067 pub dll_prefix: StaticCow<str>,
2069 pub dll_suffix: StaticCow<str>,
2071 pub exe_suffix: StaticCow<str>,
2073 pub staticlib_prefix: StaticCow<str>,
2075 pub staticlib_suffix: StaticCow<str>,
2077 pub families: StaticCow<[StaticCow<str>]>,
2083 pub abi_return_struct_as_int: bool,
2085 pub is_like_aix: bool,
2088 pub is_like_darwin: bool,
2093 pub is_like_solaris: bool,
2097 pub is_like_windows: bool,
2105 pub is_like_msvc: bool,
2115 pub is_like_wasm: bool,
2117 pub is_like_android: bool,
2119 pub is_like_vexos: bool,
2121 pub binary_format: BinaryFormat,
2123 pub default_dwarf_version: u32,
2126 pub allows_weak_linkage: bool,
2133 pub has_rpath: bool,
2135 pub no_default_libraries: bool,
2138 pub position_independent_executables: bool,
2144 pub static_position_independent_executables: bool,
2146 pub plt_by_default: bool,
2149 pub relro_level: RelroLevel,
2153 pub archive_format: StaticCow<str>,
2158 pub allow_asm: bool,
2160 pub main_needs_argc_argv: bool,
2163
2164 pub has_thread_local: bool,
2166 pub obj_is_bitcode: bool,
2170
2171 pub min_atomic_width: Option<u64>,
2173
2174 pub max_atomic_width: Option<u64>,
2176
2177 pub atomic_cas: bool,
2179
2180 pub panic_strategy: PanicStrategy,
2182
2183 pub crt_static_allows_dylibs: bool,
2185 pub crt_static_default: bool,
2187 pub crt_static_respected: bool,
2189
2190 pub stack_probes: StackProbeType,
2192
2193 pub min_global_align: Option<Align>,
2195
2196 pub default_codegen_units: Option<u64>,
2198
2199 pub default_codegen_backend: Option<StaticCow<str>>,
2209
2210 pub trap_unreachable: bool,
2213
2214 pub requires_lto: bool,
2217
2218 pub singlethread: bool,
2220
2221 pub no_builtins: bool,
2224
2225 pub default_visibility: Option<SymbolVisibility>,
2231
2232 pub emit_debug_gdb_scripts: bool,
2234
2235 pub requires_uwtable: bool,
2239
2240 pub default_uwtable: bool,
2243
2244 pub simd_types_indirect: bool,
2249
2250 pub limit_rdylib_exports: bool,
2252
2253 pub override_export_symbols: Option<StaticCow<[StaticCow<str>]>>,
2256
2257 pub merge_functions: MergeFunctions,
2264
2265 pub mcount: StaticCow<str>,
2267
2268 pub llvm_mcount_intrinsic: Option<StaticCow<str>>,
2270
2271 pub llvm_abiname: StaticCow<str>,
2274
2275 pub llvm_floatabi: Option<FloatAbi>,
2282
2283 pub rustc_abi: Option<RustcAbi>,
2288
2289 pub relax_elf_relocations: bool,
2291
2292 pub llvm_args: StaticCow<[StaticCow<str>]>,
2294
2295 pub use_ctors_section: bool,
2298
2299 pub eh_frame_header: bool,
2303
2304 pub has_thumb_interworking: bool,
2307
2308 pub debuginfo_kind: DebuginfoKind,
2310 pub split_debuginfo: SplitDebuginfo,
2313 pub supported_split_debuginfo: StaticCow<[SplitDebuginfo]>,
2315
2316 pub supported_sanitizers: SanitizerSet,
2322
2323 pub c_enum_min_bits: Option<u64>,
2325
2326 pub generate_arange_section: bool,
2328
2329 pub supports_stack_protector: bool,
2332
2333 pub entry_name: StaticCow<str>,
2336
2337 pub entry_abi: CanonAbi,
2340
2341 pub supports_xray: bool,
2343
2344 pub default_address_space: rustc_abi::AddressSpace,
2348
2349 small_data_threshold_support: SmallDataThresholdSupport,
2351}
2352
2353fn add_link_args_iter(
2356 link_args: &mut LinkArgs,
2357 flavor: LinkerFlavor,
2358 args: impl Iterator<Item = StaticCow<str>> + Clone,
2359) {
2360 let mut insert = |flavor| link_args.entry(flavor).or_default().extend(args.clone());
2361 insert(flavor);
2362 match flavor {
2363 LinkerFlavor::Gnu(cc, lld) => {
2364 assert_eq!(lld, Lld::No);
2365 insert(LinkerFlavor::Gnu(cc, Lld::Yes));
2366 }
2367 LinkerFlavor::Darwin(cc, lld) => {
2368 assert_eq!(lld, Lld::No);
2369 insert(LinkerFlavor::Darwin(cc, Lld::Yes));
2370 }
2371 LinkerFlavor::Msvc(lld) => {
2372 assert_eq!(lld, Lld::No);
2373 insert(LinkerFlavor::Msvc(Lld::Yes));
2374 }
2375 LinkerFlavor::WasmLld(..)
2376 | LinkerFlavor::Unix(..)
2377 | LinkerFlavor::EmCc
2378 | LinkerFlavor::Bpf
2379 | LinkerFlavor::Llbc
2380 | LinkerFlavor::Ptx => {}
2381 }
2382}
2383
2384fn add_link_args(link_args: &mut LinkArgs, flavor: LinkerFlavor, args: &[&'static str]) {
2385 add_link_args_iter(link_args, flavor, args.iter().copied().map(Cow::Borrowed))
2386}
2387
2388impl TargetOptions {
2389 pub fn supports_comdat(&self) -> bool {
2390 !self.is_like_aix && !self.is_like_darwin
2392 }
2393}
2394
2395impl TargetOptions {
2396 fn link_args(flavor: LinkerFlavor, args: &[&'static str]) -> LinkArgs {
2397 let mut link_args = LinkArgs::new();
2398 add_link_args(&mut link_args, flavor, args);
2399 link_args
2400 }
2401
2402 fn add_pre_link_args(&mut self, flavor: LinkerFlavor, args: &[&'static str]) {
2403 add_link_args(&mut self.pre_link_args, flavor, args);
2404 }
2405
2406 fn update_from_cli(&mut self) {
2407 self.linker_flavor = LinkerFlavor::from_cli_json(
2408 self.linker_flavor_json,
2409 self.lld_flavor_json,
2410 self.linker_is_gnu_json,
2411 );
2412 for (args, args_json) in [
2413 (&mut self.pre_link_args, &self.pre_link_args_json),
2414 (&mut self.late_link_args, &self.late_link_args_json),
2415 (&mut self.late_link_args_dynamic, &self.late_link_args_dynamic_json),
2416 (&mut self.late_link_args_static, &self.late_link_args_static_json),
2417 (&mut self.post_link_args, &self.post_link_args_json),
2418 ] {
2419 args.clear();
2420 for (flavor, args_json) in args_json {
2421 let linker_flavor = self.linker_flavor.with_cli_hints(*flavor);
2422 let linker_flavor = match linker_flavor {
2424 LinkerFlavor::Gnu(cc, _) => LinkerFlavor::Gnu(cc, Lld::No),
2425 LinkerFlavor::Darwin(cc, _) => LinkerFlavor::Darwin(cc, Lld::No),
2426 LinkerFlavor::Msvc(_) => LinkerFlavor::Msvc(Lld::No),
2427 _ => linker_flavor,
2428 };
2429 if !args.contains_key(&linker_flavor) {
2430 add_link_args_iter(args, linker_flavor, args_json.iter().cloned());
2431 }
2432 }
2433 }
2434 }
2435
2436 fn update_to_cli(&mut self) {
2437 self.linker_flavor_json = self.linker_flavor.to_cli_counterpart();
2438 self.lld_flavor_json = self.linker_flavor.lld_flavor();
2439 self.linker_is_gnu_json = self.linker_flavor.is_gnu();
2440 for (args, args_json) in [
2441 (&self.pre_link_args, &mut self.pre_link_args_json),
2442 (&self.late_link_args, &mut self.late_link_args_json),
2443 (&self.late_link_args_dynamic, &mut self.late_link_args_dynamic_json),
2444 (&self.late_link_args_static, &mut self.late_link_args_static_json),
2445 (&self.post_link_args, &mut self.post_link_args_json),
2446 ] {
2447 *args_json = args
2448 .iter()
2449 .map(|(flavor, args)| (flavor.to_cli_counterpart(), args.clone()))
2450 .collect();
2451 }
2452 }
2453}
2454
2455impl Default for TargetOptions {
2456 fn default() -> TargetOptions {
2459 TargetOptions {
2460 endian: Endian::Little,
2461 c_int_width: 32,
2462 os: "none".into(),
2463 env: "".into(),
2464 abi: "".into(),
2465 vendor: "unknown".into(),
2466 linker: option_env!("CFG_DEFAULT_LINKER").map(|s| s.into()),
2467 linker_flavor: LinkerFlavor::Gnu(Cc::Yes, Lld::No),
2468 linker_flavor_json: LinkerFlavorCli::Gcc,
2469 lld_flavor_json: LldFlavor::Ld,
2470 linker_is_gnu_json: true,
2471 link_script: None,
2472 asm_args: cvs![],
2473 cpu: "generic".into(),
2474 need_explicit_cpu: false,
2475 features: "".into(),
2476 direct_access_external_data: None,
2477 dynamic_linking: false,
2478 dll_tls_export: true,
2479 only_cdylib: false,
2480 executables: true,
2481 relocation_model: RelocModel::Pic,
2482 code_model: None,
2483 tls_model: TlsModel::GeneralDynamic,
2484 disable_redzone: false,
2485 frame_pointer: FramePointer::MayOmit,
2486 function_sections: true,
2487 dll_prefix: "lib".into(),
2488 dll_suffix: ".so".into(),
2489 exe_suffix: "".into(),
2490 staticlib_prefix: "lib".into(),
2491 staticlib_suffix: ".a".into(),
2492 families: cvs![],
2493 abi_return_struct_as_int: false,
2494 is_like_aix: false,
2495 is_like_darwin: false,
2496 is_like_solaris: false,
2497 is_like_windows: false,
2498 is_like_msvc: false,
2499 is_like_wasm: false,
2500 is_like_android: false,
2501 is_like_vexos: false,
2502 binary_format: BinaryFormat::Elf,
2503 default_dwarf_version: 4,
2504 allows_weak_linkage: true,
2505 has_rpath: false,
2506 no_default_libraries: true,
2507 position_independent_executables: false,
2508 static_position_independent_executables: false,
2509 plt_by_default: true,
2510 relro_level: RelroLevel::None,
2511 pre_link_objects: Default::default(),
2512 post_link_objects: Default::default(),
2513 pre_link_objects_self_contained: Default::default(),
2514 post_link_objects_self_contained: Default::default(),
2515 link_self_contained: LinkSelfContainedDefault::False,
2516 pre_link_args: LinkArgs::new(),
2517 pre_link_args_json: LinkArgsCli::new(),
2518 late_link_args: LinkArgs::new(),
2519 late_link_args_json: LinkArgsCli::new(),
2520 late_link_args_dynamic: LinkArgs::new(),
2521 late_link_args_dynamic_json: LinkArgsCli::new(),
2522 late_link_args_static: LinkArgs::new(),
2523 late_link_args_static_json: LinkArgsCli::new(),
2524 post_link_args: LinkArgs::new(),
2525 post_link_args_json: LinkArgsCli::new(),
2526 link_env: cvs![],
2527 link_env_remove: cvs![],
2528 archive_format: "gnu".into(),
2529 main_needs_argc_argv: true,
2530 allow_asm: true,
2531 has_thread_local: false,
2532 obj_is_bitcode: false,
2533 min_atomic_width: None,
2534 max_atomic_width: None,
2535 atomic_cas: true,
2536 panic_strategy: PanicStrategy::Unwind,
2537 crt_static_allows_dylibs: false,
2538 crt_static_default: false,
2539 crt_static_respected: false,
2540 stack_probes: StackProbeType::None,
2541 min_global_align: None,
2542 default_codegen_units: None,
2543 default_codegen_backend: None,
2544 trap_unreachable: true,
2545 requires_lto: false,
2546 singlethread: false,
2547 no_builtins: false,
2548 default_visibility: None,
2549 emit_debug_gdb_scripts: true,
2550 requires_uwtable: false,
2551 default_uwtable: false,
2552 simd_types_indirect: true,
2553 limit_rdylib_exports: true,
2554 override_export_symbols: None,
2555 merge_functions: MergeFunctions::Aliases,
2556 mcount: "mcount".into(),
2557 llvm_mcount_intrinsic: None,
2558 llvm_abiname: "".into(),
2559 llvm_floatabi: None,
2560 rustc_abi: None,
2561 relax_elf_relocations: false,
2562 llvm_args: cvs![],
2563 use_ctors_section: false,
2564 eh_frame_header: true,
2565 has_thumb_interworking: false,
2566 debuginfo_kind: Default::default(),
2567 split_debuginfo: Default::default(),
2568 supported_split_debuginfo: Cow::Borrowed(&[SplitDebuginfo::Off]),
2570 supported_sanitizers: SanitizerSet::empty(),
2571 c_enum_min_bits: None,
2572 generate_arange_section: true,
2573 supports_stack_protector: true,
2574 entry_name: "main".into(),
2575 entry_abi: CanonAbi::C,
2576 supports_xray: false,
2577 default_address_space: rustc_abi::AddressSpace::ZERO,
2578 small_data_threshold_support: SmallDataThresholdSupport::DefaultForArch,
2579 }
2580 }
2581}
2582
2583impl Deref for Target {
2587 type Target = TargetOptions;
2588
2589 #[inline]
2590 fn deref(&self) -> &Self::Target {
2591 &self.options
2592 }
2593}
2594impl DerefMut for Target {
2595 #[inline]
2596 fn deref_mut(&mut self) -> &mut Self::Target {
2597 &mut self.options
2598 }
2599}
2600
2601impl Target {
2602 pub fn is_abi_supported(&self, abi: ExternAbi) -> bool {
2603 let abi_map = AbiMap::from_target(self);
2604 abi_map.canonize_abi(abi, false).is_mapped()
2605 }
2606
2607 pub fn min_atomic_width(&self) -> u64 {
2610 self.min_atomic_width.unwrap_or(8)
2611 }
2612
2613 pub fn max_atomic_width(&self) -> u64 {
2616 self.max_atomic_width.unwrap_or_else(|| self.pointer_width.into())
2617 }
2618
2619 fn check_consistency(&self, kind: TargetKind) -> Result<(), String> {
2622 macro_rules! check {
2623 ($b:expr, $($msg:tt)*) => {
2624 if !$b {
2625 return Err(format!($($msg)*));
2626 }
2627 }
2628 }
2629 macro_rules! check_eq {
2630 ($left:expr, $right:expr, $($msg:tt)*) => {
2631 if ($left) != ($right) {
2632 return Err(format!($($msg)*));
2633 }
2634 }
2635 }
2636 macro_rules! check_ne {
2637 ($left:expr, $right:expr, $($msg:tt)*) => {
2638 if ($left) == ($right) {
2639 return Err(format!($($msg)*));
2640 }
2641 }
2642 }
2643 macro_rules! check_matches {
2644 ($left:expr, $right:pat, $($msg:tt)*) => {
2645 if !matches!($left, $right) {
2646 return Err(format!($($msg)*));
2647 }
2648 }
2649 }
2650
2651 check_eq!(
2652 self.is_like_darwin,
2653 self.vendor == "apple",
2654 "`is_like_darwin` must be set if and only if `vendor` is `apple`"
2655 );
2656 check_eq!(
2657 self.is_like_solaris,
2658 self.os == "solaris" || self.os == "illumos",
2659 "`is_like_solaris` must be set if and only if `os` is `solaris` or `illumos`"
2660 );
2661 check_eq!(
2662 self.is_like_windows,
2663 self.os == "windows" || self.os == "uefi" || self.os == "cygwin",
2664 "`is_like_windows` must be set if and only if `os` is `windows`, `uefi` or `cygwin`"
2665 );
2666 check_eq!(
2667 self.is_like_wasm,
2668 self.arch == "wasm32" || self.arch == "wasm64",
2669 "`is_like_wasm` must be set if and only if `arch` is `wasm32` or `wasm64`"
2670 );
2671 if self.is_like_msvc {
2672 check!(self.is_like_windows, "if `is_like_msvc` is set, `is_like_windows` must be set");
2673 }
2674 if self.os == "emscripten" {
2675 check!(self.is_like_wasm, "the `emcscripten` os only makes sense on wasm-like targets");
2676 }
2677
2678 check_eq!(
2680 self.is_like_darwin,
2681 matches!(self.linker_flavor, LinkerFlavor::Darwin(..)),
2682 "`linker_flavor` must be `darwin` if and only if `is_like_darwin` is set"
2683 );
2684 check_eq!(
2685 self.is_like_msvc,
2686 matches!(self.linker_flavor, LinkerFlavor::Msvc(..)),
2687 "`linker_flavor` must be `msvc` if and only if `is_like_msvc` is set"
2688 );
2689 check_eq!(
2690 self.is_like_wasm && self.os != "emscripten",
2691 matches!(self.linker_flavor, LinkerFlavor::WasmLld(..)),
2692 "`linker_flavor` must be `wasm-lld` if and only if `is_like_wasm` is set and the `os` is not `emscripten`",
2693 );
2694 check_eq!(
2695 self.os == "emscripten",
2696 matches!(self.linker_flavor, LinkerFlavor::EmCc),
2697 "`linker_flavor` must be `em-cc` if and only if `os` is `emscripten`"
2698 );
2699 check_eq!(
2700 self.arch == "bpf",
2701 matches!(self.linker_flavor, LinkerFlavor::Bpf),
2702 "`linker_flavor` must be `bpf` if and only if `arch` is `bpf`"
2703 );
2704 check_eq!(
2705 self.arch == "nvptx64",
2706 matches!(self.linker_flavor, LinkerFlavor::Ptx),
2707 "`linker_flavor` must be `ptc` if and only if `arch` is `nvptx64`"
2708 );
2709
2710 for args in [
2711 &self.pre_link_args,
2712 &self.late_link_args,
2713 &self.late_link_args_dynamic,
2714 &self.late_link_args_static,
2715 &self.post_link_args,
2716 ] {
2717 for (&flavor, flavor_args) in args {
2718 check!(
2719 !flavor_args.is_empty() || self.arch == "avr",
2720 "linker flavor args must not be empty"
2721 );
2722 match self.linker_flavor {
2724 LinkerFlavor::Gnu(..) => {
2725 check_matches!(
2726 flavor,
2727 LinkerFlavor::Gnu(..),
2728 "mixing GNU and non-GNU linker flavors"
2729 );
2730 }
2731 LinkerFlavor::Darwin(..) => {
2732 check_matches!(
2733 flavor,
2734 LinkerFlavor::Darwin(..),
2735 "mixing Darwin and non-Darwin linker flavors"
2736 )
2737 }
2738 LinkerFlavor::WasmLld(..) => {
2739 check_matches!(
2740 flavor,
2741 LinkerFlavor::WasmLld(..),
2742 "mixing wasm and non-wasm linker flavors"
2743 )
2744 }
2745 LinkerFlavor::Unix(..) => {
2746 check_matches!(
2747 flavor,
2748 LinkerFlavor::Unix(..),
2749 "mixing unix and non-unix linker flavors"
2750 );
2751 }
2752 LinkerFlavor::Msvc(..) => {
2753 check_matches!(
2754 flavor,
2755 LinkerFlavor::Msvc(..),
2756 "mixing MSVC and non-MSVC linker flavors"
2757 );
2758 }
2759 LinkerFlavor::EmCc
2760 | LinkerFlavor::Bpf
2761 | LinkerFlavor::Ptx
2762 | LinkerFlavor::Llbc => {
2763 check_eq!(flavor, self.linker_flavor, "mixing different linker flavors")
2764 }
2765 }
2766
2767 let check_noncc = |noncc_flavor| -> Result<(), String> {
2769 if let Some(noncc_args) = args.get(&noncc_flavor) {
2770 for arg in flavor_args {
2771 if let Some(suffix) = arg.strip_prefix("-Wl,") {
2772 check!(
2773 noncc_args.iter().any(|a| a == suffix),
2774 " link args for cc and non-cc versions of flavors are not consistent"
2775 );
2776 }
2777 }
2778 }
2779 Ok(())
2780 };
2781
2782 match self.linker_flavor {
2783 LinkerFlavor::Gnu(Cc::Yes, lld) => check_noncc(LinkerFlavor::Gnu(Cc::No, lld))?,
2784 LinkerFlavor::WasmLld(Cc::Yes) => check_noncc(LinkerFlavor::WasmLld(Cc::No))?,
2785 LinkerFlavor::Unix(Cc::Yes) => check_noncc(LinkerFlavor::Unix(Cc::No))?,
2786 _ => {}
2787 }
2788 }
2789
2790 for cc in [Cc::No, Cc::Yes] {
2792 check_eq!(
2793 args.get(&LinkerFlavor::Gnu(cc, Lld::No)),
2794 args.get(&LinkerFlavor::Gnu(cc, Lld::Yes)),
2795 "link args for lld and non-lld versions of flavors are not consistent",
2796 );
2797 check_eq!(
2798 args.get(&LinkerFlavor::Darwin(cc, Lld::No)),
2799 args.get(&LinkerFlavor::Darwin(cc, Lld::Yes)),
2800 "link args for lld and non-lld versions of flavors are not consistent",
2801 );
2802 }
2803 check_eq!(
2804 args.get(&LinkerFlavor::Msvc(Lld::No)),
2805 args.get(&LinkerFlavor::Msvc(Lld::Yes)),
2806 "link args for lld and non-lld versions of flavors are not consistent",
2807 );
2808 }
2809
2810 if self.link_self_contained.is_disabled() {
2811 check!(
2812 self.pre_link_objects_self_contained.is_empty()
2813 && self.post_link_objects_self_contained.is_empty(),
2814 "if `link_self_contained` is disabled, then `pre_link_objects_self_contained` and `post_link_objects_self_contained` must be empty",
2815 );
2816 }
2817
2818 check_ne!(self.vendor, "", "`vendor` cannot be empty");
2822 check_ne!(self.os, "", "`os` cannot be empty");
2823 if !self.can_use_os_unknown() {
2824 check_ne!(
2826 self.os,
2827 "unknown",
2828 "`unknown` os can only be used on particular targets; use `none` for bare-metal targets"
2829 );
2830 }
2831
2832 if kind == TargetKind::Builtin {
2838 if self.os == "none"
2842 && (self.arch != "bpf"
2843 && self.arch != "hexagon"
2844 && self.arch != "wasm32"
2845 && self.arch != "wasm64")
2846 {
2847 check!(
2848 !self.dynamic_linking,
2849 "dynamic linking is not supported on this OS/architecture"
2850 );
2851 }
2852 if self.only_cdylib
2853 || self.crt_static_allows_dylibs
2854 || !self.late_link_args_dynamic.is_empty()
2855 {
2856 check!(
2857 self.dynamic_linking,
2858 "dynamic linking must be allowed when `only_cdylib` or `crt_static_allows_dylibs` or `late_link_args_dynamic` are set"
2859 );
2860 }
2861 if self.dynamic_linking && !self.is_like_wasm {
2863 check_eq!(
2864 self.relocation_model,
2865 RelocModel::Pic,
2866 "targets that support dynamic linking must use the `pic` relocation model"
2867 );
2868 }
2869 if self.position_independent_executables {
2870 check_eq!(
2871 self.relocation_model,
2872 RelocModel::Pic,
2873 "targets that support position-independent executables must use the `pic` relocation model"
2874 );
2875 }
2876 if self.relocation_model == RelocModel::Pic && (self.os != "uefi") {
2878 check!(
2879 self.dynamic_linking || self.position_independent_executables,
2880 "when the relocation model is `pic`, the target must support dynamic linking or use position-independent executables. \
2881 Set the relocation model to `static` to avoid this requirement"
2882 );
2883 }
2884 if self.static_position_independent_executables {
2885 check!(
2886 self.position_independent_executables,
2887 "if `static_position_independent_executables` is set, then `position_independent_executables` must be set"
2888 );
2889 }
2890 if self.position_independent_executables {
2891 check!(
2892 self.executables,
2893 "if `position_independent_executables` is set then `executables` must be set"
2894 );
2895 }
2896 }
2897
2898 if self.crt_static_default || self.crt_static_allows_dylibs {
2900 check!(
2901 self.crt_static_respected,
2902 "static CRT can be enabled but `crt_static_respected` is not set"
2903 );
2904 }
2905
2906 match &*self.arch {
2909 "riscv32" => {
2910 check_matches!(
2911 &*self.llvm_abiname,
2912 "ilp32" | "ilp32f" | "ilp32d" | "ilp32e",
2913 "invalid RISC-V ABI name: {}",
2914 self.llvm_abiname,
2915 );
2916 }
2917 "riscv64" => {
2918 check_matches!(
2920 &*self.llvm_abiname,
2921 "lp64" | "lp64f" | "lp64d" | "lp64e",
2922 "invalid RISC-V ABI name: {}",
2923 self.llvm_abiname,
2924 );
2925 }
2926 "arm" => {
2927 check!(
2928 self.llvm_floatabi.is_some(),
2929 "ARM targets must set `llvm-floatabi` to `hard` or `soft`",
2930 )
2931 }
2932 _ => {}
2933 }
2934
2935 if let Some(rust_abi) = self.rustc_abi {
2937 match rust_abi {
2938 RustcAbi::X86Sse2 => check_matches!(
2939 &*self.arch,
2940 "x86",
2941 "`x86-sse2` ABI is only valid for x86-32 targets"
2942 ),
2943 RustcAbi::X86Softfloat => check_matches!(
2944 &*self.arch,
2945 "x86" | "x86_64",
2946 "`x86-softfloat` ABI is only valid for x86 targets"
2947 ),
2948 }
2949 }
2950
2951 if !self.features.is_empty() {
2953 let mut features_enabled = FxHashSet::default();
2954 let mut features_disabled = FxHashSet::default();
2955 for feat in self.features.split(',') {
2956 if let Some(feat) = feat.strip_prefix("+") {
2957 features_enabled.insert(feat);
2958 if features_disabled.contains(feat) {
2959 return Err(format!(
2960 "target feature `{feat}` is both enabled and disabled"
2961 ));
2962 }
2963 } else if let Some(feat) = feat.strip_prefix("-") {
2964 features_disabled.insert(feat);
2965 if features_enabled.contains(feat) {
2966 return Err(format!(
2967 "target feature `{feat}` is both enabled and disabled"
2968 ));
2969 }
2970 } else {
2971 return Err(format!(
2972 "target feature `{feat}` is invalid, must start with `+` or `-`"
2973 ));
2974 }
2975 }
2976 let abi_feature_constraints = self.abi_required_features();
2978 for feat in abi_feature_constraints.required {
2979 if features_disabled.contains(feat) {
2982 return Err(format!(
2983 "target feature `{feat}` is required by the ABI but gets disabled in target spec"
2984 ));
2985 }
2986 }
2987 for feat in abi_feature_constraints.incompatible {
2988 if features_enabled.contains(feat) {
2991 return Err(format!(
2992 "target feature `{feat}` is incompatible with the ABI but gets enabled in target spec"
2993 ));
2994 }
2995 }
2996 }
2997
2998 Ok(())
2999 }
3000
3001 #[cfg(test)]
3003 fn test_target(mut self) {
3004 let recycled_target =
3005 Target::from_json(&serde_json::to_string(&self.to_json()).unwrap()).map(|(j, _)| j);
3006 self.update_to_cli();
3007 self.check_consistency(TargetKind::Builtin).unwrap();
3008 assert_eq!(recycled_target, Ok(self));
3009 }
3010
3011 fn can_use_os_unknown(&self) -> bool {
3014 self.llvm_target == "wasm32-unknown-unknown"
3015 || self.llvm_target == "wasm64-unknown-unknown"
3016 || (self.env == "sgx" && self.vendor == "fortanix")
3017 }
3018
3019 pub fn expect_builtin(target_tuple: &TargetTuple) -> Target {
3021 match *target_tuple {
3022 TargetTuple::TargetTuple(ref target_tuple) => {
3023 load_builtin(target_tuple).expect("built-in target")
3024 }
3025 TargetTuple::TargetJson { .. } => {
3026 panic!("built-in targets doesn't support target-paths")
3027 }
3028 }
3029 }
3030
3031 pub fn builtins() -> impl Iterator<Item = Target> {
3033 load_all_builtins()
3034 }
3035
3036 pub fn search(
3046 target_tuple: &TargetTuple,
3047 sysroot: &Path,
3048 ) -> Result<(Target, TargetWarnings), String> {
3049 use std::{env, fs};
3050
3051 fn load_file(path: &Path) -> Result<(Target, TargetWarnings), String> {
3052 let contents = fs::read_to_string(path).map_err(|e| e.to_string())?;
3053 Target::from_json(&contents)
3054 }
3055
3056 match *target_tuple {
3057 TargetTuple::TargetTuple(ref target_tuple) => {
3058 if let Some(t) = load_builtin(target_tuple) {
3060 return Ok((t, TargetWarnings::empty()));
3061 }
3062
3063 let path = {
3065 let mut target = target_tuple.to_string();
3066 target.push_str(".json");
3067 PathBuf::from(target)
3068 };
3069
3070 let target_path = env::var_os("RUST_TARGET_PATH").unwrap_or_default();
3071
3072 for dir in env::split_paths(&target_path) {
3073 let p = dir.join(&path);
3074 if p.is_file() {
3075 return load_file(&p);
3076 }
3077 }
3078
3079 let rustlib_path = crate::relative_target_rustlib_path(sysroot, target_tuple);
3082 let p = PathBuf::from_iter([
3083 Path::new(sysroot),
3084 Path::new(&rustlib_path),
3085 Path::new("target.json"),
3086 ]);
3087 if p.is_file() {
3088 return load_file(&p);
3089 }
3090
3091 if target_tuple == "i586-pc-windows-msvc" {
3095 Err("the `i586-pc-windows-msvc` target has been removed. Use the `i686-pc-windows-msvc` target instead.\n\
3096 Windows 10 (the minimum required OS version) requires a CPU baseline of at least i686 so you can safely switch".into())
3097 } else {
3098 Err(format!("could not find specification for target {target_tuple:?}"))
3099 }
3100 }
3101 TargetTuple::TargetJson { ref contents, .. } => Target::from_json(contents),
3102 }
3103 }
3104
3105 pub fn small_data_threshold_support(&self) -> SmallDataThresholdSupport {
3108 match &self.options.small_data_threshold_support {
3109 SmallDataThresholdSupport::DefaultForArch => match self.arch.as_ref() {
3113 "mips" | "mips64" | "mips32r6" => {
3114 SmallDataThresholdSupport::LlvmArg("mips-ssection-threshold".into())
3115 }
3116 "hexagon" => {
3117 SmallDataThresholdSupport::LlvmArg("hexagon-small-data-threshold".into())
3118 }
3119 "m68k" => SmallDataThresholdSupport::LlvmArg("m68k-ssection-threshold".into()),
3120 "riscv32" | "riscv64" => {
3121 SmallDataThresholdSupport::LlvmModuleFlag("SmallDataLimit".into())
3122 }
3123 _ => SmallDataThresholdSupport::None,
3124 },
3125 s => s.clone(),
3126 }
3127 }
3128
3129 pub fn object_architecture(
3130 &self,
3131 unstable_target_features: &FxIndexSet<Symbol>,
3132 ) -> Option<(object::Architecture, Option<object::SubArchitecture>)> {
3133 use object::Architecture;
3134 Some(match self.arch.as_ref() {
3135 "arm" => (Architecture::Arm, None),
3136 "aarch64" => (
3137 if self.pointer_width == 32 {
3138 Architecture::Aarch64_Ilp32
3139 } else {
3140 Architecture::Aarch64
3141 },
3142 None,
3143 ),
3144 "x86" => (Architecture::I386, None),
3145 "s390x" => (Architecture::S390x, None),
3146 "m68k" => (Architecture::M68k, None),
3147 "mips" | "mips32r6" => (Architecture::Mips, None),
3148 "mips64" | "mips64r6" => (
3149 if self.options.llvm_abiname.as_ref() == "n32" {
3155 Architecture::Mips64_N32
3156 } else {
3157 Architecture::Mips64
3158 },
3159 None,
3160 ),
3161 "x86_64" => (
3162 if self.pointer_width == 32 {
3163 Architecture::X86_64_X32
3164 } else {
3165 Architecture::X86_64
3166 },
3167 None,
3168 ),
3169 "powerpc" => (Architecture::PowerPc, None),
3170 "powerpc64" => (Architecture::PowerPc64, None),
3171 "riscv32" => (Architecture::Riscv32, None),
3172 "riscv64" => (Architecture::Riscv64, None),
3173 "sparc" => {
3174 if unstable_target_features.contains(&sym::v8plus) {
3175 (Architecture::Sparc32Plus, None)
3177 } else {
3178 (Architecture::Sparc, None)
3180 }
3181 }
3182 "sparc64" => (Architecture::Sparc64, None),
3183 "avr" => (Architecture::Avr, None),
3184 "msp430" => (Architecture::Msp430, None),
3185 "hexagon" => (Architecture::Hexagon, None),
3186 "xtensa" => (Architecture::Xtensa, None),
3187 "bpf" => (Architecture::Bpf, None),
3188 "loongarch32" => (Architecture::LoongArch32, None),
3189 "loongarch64" => (Architecture::LoongArch64, None),
3190 "csky" => (Architecture::Csky, None),
3191 "arm64ec" => (Architecture::Aarch64, Some(object::SubArchitecture::Arm64EC)),
3192 _ => return None,
3194 })
3195 }
3196
3197 pub fn max_reliable_alignment(&self) -> Align {
3206 if self.is_like_windows && self.arch == "x86" {
3210 Align::from_bytes(4).unwrap()
3211 } else {
3212 Align::MAX
3213 }
3214 }
3215}
3216
3217#[derive(Clone, Debug)]
3219pub enum TargetTuple {
3220 TargetTuple(String),
3221 TargetJson {
3222 path_for_rustdoc: PathBuf,
3225 tuple: String,
3226 contents: String,
3227 },
3228}
3229
3230impl PartialEq for TargetTuple {
3232 fn eq(&self, other: &Self) -> bool {
3233 match (self, other) {
3234 (Self::TargetTuple(l0), Self::TargetTuple(r0)) => l0 == r0,
3235 (
3236 Self::TargetJson { path_for_rustdoc: _, tuple: l_tuple, contents: l_contents },
3237 Self::TargetJson { path_for_rustdoc: _, tuple: r_tuple, contents: r_contents },
3238 ) => l_tuple == r_tuple && l_contents == r_contents,
3239 _ => false,
3240 }
3241 }
3242}
3243
3244impl Hash for TargetTuple {
3246 fn hash<H: Hasher>(&self, state: &mut H) -> () {
3247 match self {
3248 TargetTuple::TargetTuple(tuple) => {
3249 0u8.hash(state);
3250 tuple.hash(state)
3251 }
3252 TargetTuple::TargetJson { path_for_rustdoc: _, tuple, contents } => {
3253 1u8.hash(state);
3254 tuple.hash(state);
3255 contents.hash(state)
3256 }
3257 }
3258 }
3259}
3260
3261impl<S: Encoder> Encodable<S> for TargetTuple {
3263 fn encode(&self, s: &mut S) {
3264 match self {
3265 TargetTuple::TargetTuple(tuple) => {
3266 s.emit_u8(0);
3267 s.emit_str(tuple);
3268 }
3269 TargetTuple::TargetJson { path_for_rustdoc: _, tuple, contents } => {
3270 s.emit_u8(1);
3271 s.emit_str(tuple);
3272 s.emit_str(contents);
3273 }
3274 }
3275 }
3276}
3277
3278impl<D: Decoder> Decodable<D> for TargetTuple {
3279 fn decode(d: &mut D) -> Self {
3280 match d.read_u8() {
3281 0 => TargetTuple::TargetTuple(d.read_str().to_owned()),
3282 1 => TargetTuple::TargetJson {
3283 path_for_rustdoc: PathBuf::new(),
3284 tuple: d.read_str().to_owned(),
3285 contents: d.read_str().to_owned(),
3286 },
3287 _ => {
3288 panic!("invalid enum variant tag while decoding `TargetTuple`, expected 0..2");
3289 }
3290 }
3291 }
3292}
3293
3294impl TargetTuple {
3295 pub fn from_tuple(tuple: &str) -> Self {
3297 TargetTuple::TargetTuple(tuple.into())
3298 }
3299
3300 pub fn from_path(path: &Path) -> Result<Self, io::Error> {
3302 let canonicalized_path = try_canonicalize(path)?;
3303 let contents = std::fs::read_to_string(&canonicalized_path).map_err(|err| {
3304 io::Error::new(
3305 io::ErrorKind::InvalidInput,
3306 format!("target path {canonicalized_path:?} is not a valid file: {err}"),
3307 )
3308 })?;
3309 let tuple = canonicalized_path
3310 .file_stem()
3311 .expect("target path must not be empty")
3312 .to_str()
3313 .expect("target path must be valid unicode")
3314 .to_owned();
3315 Ok(TargetTuple::TargetJson { path_for_rustdoc: canonicalized_path, tuple, contents })
3316 }
3317
3318 pub fn tuple(&self) -> &str {
3322 match *self {
3323 TargetTuple::TargetTuple(ref tuple) | TargetTuple::TargetJson { ref tuple, .. } => {
3324 tuple
3325 }
3326 }
3327 }
3328
3329 pub fn debug_tuple(&self) -> String {
3334 use std::hash::DefaultHasher;
3335
3336 match self {
3337 TargetTuple::TargetTuple(tuple) => tuple.to_owned(),
3338 TargetTuple::TargetJson { path_for_rustdoc: _, tuple, contents: content } => {
3339 let mut hasher = DefaultHasher::new();
3340 content.hash(&mut hasher);
3341 let hash = hasher.finish();
3342 format!("{tuple}-{hash}")
3343 }
3344 }
3345 }
3346}
3347
3348impl fmt::Display for TargetTuple {
3349 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3350 write!(f, "{}", self.debug_tuple())
3351 }
3352}
3353
3354into_diag_arg_using_display!(&TargetTuple);