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_fs_util::try_canonicalize;
54use rustc_macros::{Decodable, Encodable, HashStable_Generic};
55use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
56use rustc_span::{Symbol, kw, sym};
57use serde_json::Value;
58use tracing::debug;
59
60use crate::json::{Json, ToJson};
61use crate::spec::crt_objects::CrtObjects;
62
63pub mod crt_objects;
64
65mod abi_map;
66mod base;
67mod json;
68
69pub use abi_map::{AbiMap, AbiMapping};
70pub use base::apple;
71pub use base::avr::ef_avr_arch;
72
73#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
75pub enum Cc {
76 Yes,
77 No,
78}
79
80#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
82pub enum Lld {
83 Yes,
84 No,
85}
86
87#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
108pub enum LinkerFlavor {
109 Gnu(Cc, Lld),
113 Darwin(Cc, Lld),
116 WasmLld(Cc),
120 Unix(Cc),
124 Msvc(Lld),
126 EmCc,
129 Bpf,
132 Ptx,
134 Llbc,
136}
137
138#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
143pub enum LinkerFlavorCli {
144 Gnu(Cc, Lld),
146 Darwin(Cc, Lld),
147 WasmLld(Cc),
148 Unix(Cc),
149 Msvc(Lld),
151 EmCc,
152 Bpf,
153 Ptx,
154 Llbc,
155
156 Gcc,
158 Ld,
159 Lld(LldFlavor),
160 Em,
161}
162
163impl LinkerFlavorCli {
164 pub fn is_unstable(&self) -> bool {
166 match self {
167 LinkerFlavorCli::Gnu(..)
168 | LinkerFlavorCli::Darwin(..)
169 | LinkerFlavorCli::WasmLld(..)
170 | LinkerFlavorCli::Unix(..)
171 | LinkerFlavorCli::Msvc(Lld::Yes)
172 | LinkerFlavorCli::EmCc
173 | LinkerFlavorCli::Bpf
174 | LinkerFlavorCli::Llbc
175 | LinkerFlavorCli::Ptx => true,
176 LinkerFlavorCli::Gcc
177 | LinkerFlavorCli::Ld
178 | LinkerFlavorCli::Lld(..)
179 | LinkerFlavorCli::Msvc(Lld::No)
180 | LinkerFlavorCli::Em => false,
181 }
182 }
183}
184
185#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
186pub enum LldFlavor {
187 Wasm,
188 Ld64,
189 Ld,
190 Link,
191}
192
193impl LldFlavor {
194 pub fn as_str(&self) -> &'static str {
195 match self {
196 LldFlavor::Wasm => "wasm",
197 LldFlavor::Ld64 => "darwin",
198 LldFlavor::Ld => "gnu",
199 LldFlavor::Link => "link",
200 }
201 }
202}
203
204impl FromStr for LldFlavor {
205 type Err = String;
206
207 fn from_str(s: &str) -> Result<Self, Self::Err> {
208 Ok(match s {
209 "darwin" => LldFlavor::Ld64,
210 "gnu" => LldFlavor::Ld,
211 "link" => LldFlavor::Link,
212 "wasm" => LldFlavor::Wasm,
213 _ => {
214 return Err(
215 "invalid value for lld flavor: '{s}', expected one of 'darwin', 'gnu', 'link', 'wasm'"
216 .into(),
217 );
218 }
219 })
220 }
221}
222
223crate::json::serde_deserialize_from_str!(LldFlavor);
224
225impl ToJson for LldFlavor {
226 fn to_json(&self) -> Json {
227 self.as_str().to_json()
228 }
229}
230
231impl LinkerFlavor {
232 fn from_cli_json(cli: LinkerFlavorCli, lld_flavor: LldFlavor, is_gnu: bool) -> LinkerFlavor {
237 match cli {
238 LinkerFlavorCli::Gnu(cc, lld) => LinkerFlavor::Gnu(cc, lld),
239 LinkerFlavorCli::Darwin(cc, lld) => LinkerFlavor::Darwin(cc, lld),
240 LinkerFlavorCli::WasmLld(cc) => LinkerFlavor::WasmLld(cc),
241 LinkerFlavorCli::Unix(cc) => LinkerFlavor::Unix(cc),
242 LinkerFlavorCli::Msvc(lld) => LinkerFlavor::Msvc(lld),
243 LinkerFlavorCli::EmCc => LinkerFlavor::EmCc,
244 LinkerFlavorCli::Bpf => LinkerFlavor::Bpf,
245 LinkerFlavorCli::Llbc => LinkerFlavor::Llbc,
246 LinkerFlavorCli::Ptx => LinkerFlavor::Ptx,
247
248 LinkerFlavorCli::Gcc => match lld_flavor {
250 LldFlavor::Ld if is_gnu => LinkerFlavor::Gnu(Cc::Yes, Lld::No),
251 LldFlavor::Ld64 => LinkerFlavor::Darwin(Cc::Yes, Lld::No),
252 LldFlavor::Wasm => LinkerFlavor::WasmLld(Cc::Yes),
253 LldFlavor::Ld | LldFlavor::Link => LinkerFlavor::Unix(Cc::Yes),
254 },
255 LinkerFlavorCli::Ld => match lld_flavor {
256 LldFlavor::Ld if is_gnu => LinkerFlavor::Gnu(Cc::No, Lld::No),
257 LldFlavor::Ld64 => LinkerFlavor::Darwin(Cc::No, Lld::No),
258 LldFlavor::Ld | LldFlavor::Wasm | LldFlavor::Link => LinkerFlavor::Unix(Cc::No),
259 },
260 LinkerFlavorCli::Lld(LldFlavor::Ld) => LinkerFlavor::Gnu(Cc::No, Lld::Yes),
261 LinkerFlavorCli::Lld(LldFlavor::Ld64) => LinkerFlavor::Darwin(Cc::No, Lld::Yes),
262 LinkerFlavorCli::Lld(LldFlavor::Wasm) => LinkerFlavor::WasmLld(Cc::No),
263 LinkerFlavorCli::Lld(LldFlavor::Link) => LinkerFlavor::Msvc(Lld::Yes),
264 LinkerFlavorCli::Em => LinkerFlavor::EmCc,
265 }
266 }
267
268 fn to_cli(self) -> LinkerFlavorCli {
270 match self {
271 LinkerFlavor::Gnu(Cc::Yes, _)
272 | LinkerFlavor::Darwin(Cc::Yes, _)
273 | LinkerFlavor::WasmLld(Cc::Yes)
274 | LinkerFlavor::Unix(Cc::Yes) => LinkerFlavorCli::Gcc,
275 LinkerFlavor::Gnu(_, Lld::Yes) => LinkerFlavorCli::Lld(LldFlavor::Ld),
276 LinkerFlavor::Darwin(_, Lld::Yes) => LinkerFlavorCli::Lld(LldFlavor::Ld64),
277 LinkerFlavor::WasmLld(..) => LinkerFlavorCli::Lld(LldFlavor::Wasm),
278 LinkerFlavor::Gnu(..) | LinkerFlavor::Darwin(..) | LinkerFlavor::Unix(..) => {
279 LinkerFlavorCli::Ld
280 }
281 LinkerFlavor::Msvc(Lld::Yes) => LinkerFlavorCli::Lld(LldFlavor::Link),
282 LinkerFlavor::Msvc(..) => LinkerFlavorCli::Msvc(Lld::No),
283 LinkerFlavor::EmCc => LinkerFlavorCli::Em,
284 LinkerFlavor::Bpf => LinkerFlavorCli::Bpf,
285 LinkerFlavor::Llbc => LinkerFlavorCli::Llbc,
286 LinkerFlavor::Ptx => LinkerFlavorCli::Ptx,
287 }
288 }
289
290 fn to_cli_counterpart(self) -> LinkerFlavorCli {
292 match self {
293 LinkerFlavor::Gnu(cc, lld) => LinkerFlavorCli::Gnu(cc, lld),
294 LinkerFlavor::Darwin(cc, lld) => LinkerFlavorCli::Darwin(cc, lld),
295 LinkerFlavor::WasmLld(cc) => LinkerFlavorCli::WasmLld(cc),
296 LinkerFlavor::Unix(cc) => LinkerFlavorCli::Unix(cc),
297 LinkerFlavor::Msvc(lld) => LinkerFlavorCli::Msvc(lld),
298 LinkerFlavor::EmCc => LinkerFlavorCli::EmCc,
299 LinkerFlavor::Bpf => LinkerFlavorCli::Bpf,
300 LinkerFlavor::Llbc => LinkerFlavorCli::Llbc,
301 LinkerFlavor::Ptx => LinkerFlavorCli::Ptx,
302 }
303 }
304
305 fn infer_cli_hints(cli: LinkerFlavorCli) -> (Option<Cc>, Option<Lld>) {
306 match cli {
307 LinkerFlavorCli::Gnu(cc, lld) | LinkerFlavorCli::Darwin(cc, lld) => {
308 (Some(cc), Some(lld))
309 }
310 LinkerFlavorCli::WasmLld(cc) => (Some(cc), Some(Lld::Yes)),
311 LinkerFlavorCli::Unix(cc) => (Some(cc), None),
312 LinkerFlavorCli::Msvc(lld) => (Some(Cc::No), Some(lld)),
313 LinkerFlavorCli::EmCc => (Some(Cc::Yes), Some(Lld::Yes)),
314 LinkerFlavorCli::Bpf | LinkerFlavorCli::Ptx => (None, None),
315 LinkerFlavorCli::Llbc => (None, None),
316
317 LinkerFlavorCli::Gcc => (Some(Cc::Yes), None),
319 LinkerFlavorCli::Ld => (Some(Cc::No), Some(Lld::No)),
320 LinkerFlavorCli::Lld(_) => (Some(Cc::No), Some(Lld::Yes)),
321 LinkerFlavorCli::Em => (Some(Cc::Yes), Some(Lld::Yes)),
322 }
323 }
324
325 fn infer_linker_hints(linker_stem: &str) -> Result<Self, (Option<Cc>, Option<Lld>)> {
326 let stem = linker_stem
328 .rsplit_once('-')
329 .and_then(|(lhs, rhs)| rhs.chars().all(char::is_numeric).then_some(lhs))
330 .unwrap_or(linker_stem);
331
332 if stem == "llvm-bitcode-linker" {
333 Ok(Self::Llbc)
334 } else if stem == "emcc" || stem == "gcc"
336 || stem.ends_with("-gcc")
337 || stem == "g++"
338 || stem.ends_with("-g++")
339 || stem == "clang"
340 || stem.ends_with("-clang")
341 || stem == "clang++"
342 || stem.ends_with("-clang++")
343 {
344 Err((Some(Cc::Yes), Some(Lld::No)))
345 } else if stem == "wasm-ld"
346 || stem.ends_with("-wasm-ld")
347 || stem == "ld.lld"
348 || stem == "lld"
349 || stem == "rust-lld"
350 || stem == "lld-link"
351 {
352 Err((Some(Cc::No), Some(Lld::Yes)))
353 } else if stem == "ld" || stem.ends_with("-ld") || stem == "link" {
354 Err((Some(Cc::No), Some(Lld::No)))
355 } else {
356 Err((None, None))
357 }
358 }
359
360 fn with_hints(self, (cc_hint, lld_hint): (Option<Cc>, Option<Lld>)) -> LinkerFlavor {
361 match self {
362 LinkerFlavor::Gnu(cc, lld) => {
363 LinkerFlavor::Gnu(cc_hint.unwrap_or(cc), lld_hint.unwrap_or(lld))
364 }
365 LinkerFlavor::Darwin(cc, lld) => {
366 LinkerFlavor::Darwin(cc_hint.unwrap_or(cc), lld_hint.unwrap_or(lld))
367 }
368 LinkerFlavor::WasmLld(cc) => LinkerFlavor::WasmLld(cc_hint.unwrap_or(cc)),
369 LinkerFlavor::Unix(cc) => LinkerFlavor::Unix(cc_hint.unwrap_or(cc)),
370 LinkerFlavor::Msvc(lld) => LinkerFlavor::Msvc(lld_hint.unwrap_or(lld)),
371 LinkerFlavor::EmCc | LinkerFlavor::Bpf | LinkerFlavor::Llbc | LinkerFlavor::Ptx => self,
372 }
373 }
374
375 pub fn with_cli_hints(self, cli: LinkerFlavorCli) -> LinkerFlavor {
376 self.with_hints(LinkerFlavor::infer_cli_hints(cli))
377 }
378
379 pub fn with_linker_hints(self, linker_stem: &str) -> LinkerFlavor {
380 match LinkerFlavor::infer_linker_hints(linker_stem) {
381 Ok(linker_flavor) => linker_flavor,
382 Err(hints) => self.with_hints(hints),
383 }
384 }
385
386 pub fn check_compatibility(self, cli: LinkerFlavorCli) -> Option<String> {
387 let compatible = |cli| {
388 match (self, cli) {
390 (LinkerFlavor::Gnu(..), LinkerFlavorCli::Gnu(..))
392 | (LinkerFlavor::Darwin(..), LinkerFlavorCli::Darwin(..))
393 | (LinkerFlavor::WasmLld(..), LinkerFlavorCli::WasmLld(..))
394 | (LinkerFlavor::Unix(..), LinkerFlavorCli::Unix(..))
395 | (LinkerFlavor::Msvc(..), LinkerFlavorCli::Msvc(..))
396 | (LinkerFlavor::EmCc, LinkerFlavorCli::EmCc)
397 | (LinkerFlavor::Bpf, LinkerFlavorCli::Bpf)
398 | (LinkerFlavor::Llbc, LinkerFlavorCli::Llbc)
399 | (LinkerFlavor::Ptx, LinkerFlavorCli::Ptx) => return true,
400 (LinkerFlavor::Ptx, LinkerFlavorCli::Llbc) => return true,
402 _ => {}
403 }
404
405 cli == self.with_cli_hints(cli).to_cli()
407 };
408 (!compatible(cli)).then(|| {
409 LinkerFlavorCli::all()
410 .iter()
411 .filter(|cli| compatible(**cli))
412 .map(|cli| cli.desc())
413 .intersperse(", ")
414 .collect()
415 })
416 }
417
418 pub fn lld_flavor(self) -> LldFlavor {
419 match self {
420 LinkerFlavor::Gnu(..)
421 | LinkerFlavor::Unix(..)
422 | LinkerFlavor::EmCc
423 | LinkerFlavor::Bpf
424 | LinkerFlavor::Llbc
425 | LinkerFlavor::Ptx => LldFlavor::Ld,
426 LinkerFlavor::Darwin(..) => LldFlavor::Ld64,
427 LinkerFlavor::WasmLld(..) => LldFlavor::Wasm,
428 LinkerFlavor::Msvc(..) => LldFlavor::Link,
429 }
430 }
431
432 pub fn is_gnu(self) -> bool {
433 matches!(self, LinkerFlavor::Gnu(..))
434 }
435
436 pub fn uses_lld(self) -> bool {
438 match self {
440 LinkerFlavor::Gnu(_, Lld::Yes)
441 | LinkerFlavor::Darwin(_, Lld::Yes)
442 | LinkerFlavor::WasmLld(..)
443 | LinkerFlavor::EmCc
444 | LinkerFlavor::Msvc(Lld::Yes) => true,
445 LinkerFlavor::Gnu(..)
446 | LinkerFlavor::Darwin(..)
447 | LinkerFlavor::Msvc(_)
448 | LinkerFlavor::Unix(_)
449 | LinkerFlavor::Bpf
450 | LinkerFlavor::Llbc
451 | LinkerFlavor::Ptx => false,
452 }
453 }
454
455 pub fn uses_cc(self) -> bool {
457 match self {
459 LinkerFlavor::Gnu(Cc::Yes, _)
460 | LinkerFlavor::Darwin(Cc::Yes, _)
461 | LinkerFlavor::WasmLld(Cc::Yes)
462 | LinkerFlavor::Unix(Cc::Yes)
463 | LinkerFlavor::EmCc => true,
464 LinkerFlavor::Gnu(..)
465 | LinkerFlavor::Darwin(..)
466 | LinkerFlavor::WasmLld(_)
467 | LinkerFlavor::Msvc(_)
468 | LinkerFlavor::Unix(_)
469 | LinkerFlavor::Bpf
470 | LinkerFlavor::Llbc
471 | LinkerFlavor::Ptx => false,
472 }
473 }
474
475 pub fn with_lld_enabled(self) -> LinkerFlavor {
478 match self {
479 LinkerFlavor::Gnu(cc, Lld::No) => LinkerFlavor::Gnu(cc, Lld::Yes),
480 LinkerFlavor::Darwin(cc, Lld::No) => LinkerFlavor::Darwin(cc, Lld::Yes),
481 LinkerFlavor::Msvc(Lld::No) => LinkerFlavor::Msvc(Lld::Yes),
482 _ => self,
483 }
484 }
485
486 pub fn with_lld_disabled(self) -> LinkerFlavor {
489 match self {
490 LinkerFlavor::Gnu(cc, Lld::Yes) => LinkerFlavor::Gnu(cc, Lld::No),
491 LinkerFlavor::Darwin(cc, Lld::Yes) => LinkerFlavor::Darwin(cc, Lld::No),
492 LinkerFlavor::Msvc(Lld::Yes) => LinkerFlavor::Msvc(Lld::No),
493 _ => self,
494 }
495 }
496}
497
498macro_rules! linker_flavor_cli_impls {
499 ($(($($flavor:tt)*) $string:literal)*) => (
500 impl LinkerFlavorCli {
501 const fn all() -> &'static [LinkerFlavorCli] {
502 &[$($($flavor)*,)*]
503 }
504
505 pub const fn one_of() -> &'static str {
506 concat!("one of: ", $($string, " ",)*)
507 }
508
509 pub fn desc(self) -> &'static str {
510 match self {
511 $($($flavor)* => $string,)*
512 }
513 }
514 }
515
516 impl FromStr for LinkerFlavorCli {
517 type Err = String;
518
519 fn from_str(s: &str) -> Result<LinkerFlavorCli, Self::Err> {
520 Ok(match s {
521 $($string => $($flavor)*,)*
522 _ => return Err(format!("invalid linker flavor, allowed values: {}", Self::one_of())),
523 })
524 }
525 }
526 )
527}
528
529linker_flavor_cli_impls! {
530 (LinkerFlavorCli::Gnu(Cc::No, Lld::No)) "gnu"
531 (LinkerFlavorCli::Gnu(Cc::No, Lld::Yes)) "gnu-lld"
532 (LinkerFlavorCli::Gnu(Cc::Yes, Lld::No)) "gnu-cc"
533 (LinkerFlavorCli::Gnu(Cc::Yes, Lld::Yes)) "gnu-lld-cc"
534 (LinkerFlavorCli::Darwin(Cc::No, Lld::No)) "darwin"
535 (LinkerFlavorCli::Darwin(Cc::No, Lld::Yes)) "darwin-lld"
536 (LinkerFlavorCli::Darwin(Cc::Yes, Lld::No)) "darwin-cc"
537 (LinkerFlavorCli::Darwin(Cc::Yes, Lld::Yes)) "darwin-lld-cc"
538 (LinkerFlavorCli::WasmLld(Cc::No)) "wasm-lld"
539 (LinkerFlavorCli::WasmLld(Cc::Yes)) "wasm-lld-cc"
540 (LinkerFlavorCli::Unix(Cc::No)) "unix"
541 (LinkerFlavorCli::Unix(Cc::Yes)) "unix-cc"
542 (LinkerFlavorCli::Msvc(Lld::Yes)) "msvc-lld"
543 (LinkerFlavorCli::Msvc(Lld::No)) "msvc"
544 (LinkerFlavorCli::EmCc) "em-cc"
545 (LinkerFlavorCli::Bpf) "bpf"
546 (LinkerFlavorCli::Llbc) "llbc"
547 (LinkerFlavorCli::Ptx) "ptx"
548
549 (LinkerFlavorCli::Gcc) "gcc"
551 (LinkerFlavorCli::Ld) "ld"
552 (LinkerFlavorCli::Lld(LldFlavor::Ld)) "ld.lld"
553 (LinkerFlavorCli::Lld(LldFlavor::Ld64)) "ld64.lld"
554 (LinkerFlavorCli::Lld(LldFlavor::Link)) "lld-link"
555 (LinkerFlavorCli::Lld(LldFlavor::Wasm)) "wasm-ld"
556 (LinkerFlavorCli::Em) "em"
557}
558
559crate::json::serde_deserialize_from_str!(LinkerFlavorCli);
560
561impl ToJson for LinkerFlavorCli {
562 fn to_json(&self) -> Json {
563 self.desc().to_json()
564 }
565}
566
567#[derive(Clone, Copy, PartialEq, Debug)]
574pub enum LinkSelfContainedDefault {
575 True,
577
578 False,
580
581 InferredForMusl,
583
584 InferredForMingw,
586
587 WithComponents(LinkSelfContainedComponents),
590}
591
592impl FromStr for LinkSelfContainedDefault {
594 type Err = String;
595
596 fn from_str(s: &str) -> Result<LinkSelfContainedDefault, Self::Err> {
597 Ok(match s {
598 "false" => LinkSelfContainedDefault::False,
599 "true" | "wasm" => LinkSelfContainedDefault::True,
600 "musl" => LinkSelfContainedDefault::InferredForMusl,
601 "mingw" => LinkSelfContainedDefault::InferredForMingw,
602 _ => {
603 return Err(format!(
604 "'{s}' is not a valid `-Clink-self-contained` default. \
605 Use 'false', 'true', 'wasm', 'musl' or 'mingw'",
606 ));
607 }
608 })
609 }
610}
611
612crate::json::serde_deserialize_from_str!(LinkSelfContainedDefault);
613
614impl ToJson for LinkSelfContainedDefault {
615 fn to_json(&self) -> Json {
616 match *self {
617 LinkSelfContainedDefault::WithComponents(components) => {
618 let mut map = BTreeMap::new();
622 map.insert("components", components);
623 map.to_json()
624 }
625
626 LinkSelfContainedDefault::True => "true".to_json(),
628 LinkSelfContainedDefault::False => "false".to_json(),
629 LinkSelfContainedDefault::InferredForMusl => "musl".to_json(),
630 LinkSelfContainedDefault::InferredForMingw => "mingw".to_json(),
631 }
632 }
633}
634
635impl LinkSelfContainedDefault {
636 pub fn is_disabled(self) -> bool {
639 self == LinkSelfContainedDefault::False
640 }
641
642 fn json_key(self) -> &'static str {
646 match self {
647 LinkSelfContainedDefault::WithComponents(_) => "link-self-contained",
648 _ => "crt-objects-fallback",
649 }
650 }
651
652 pub fn with_linker() -> LinkSelfContainedDefault {
655 LinkSelfContainedDefault::WithComponents(LinkSelfContainedComponents::LINKER)
656 }
657}
658
659bitflags::bitflags! {
660 #[derive(Clone, Copy, PartialEq, Eq, Default)]
661 pub struct LinkSelfContainedComponents: u8 {
663 const CRT_OBJECTS = 1 << 0;
665 const LIBC = 1 << 1;
667 const UNWIND = 1 << 2;
669 const LINKER = 1 << 3;
671 const SANITIZERS = 1 << 4;
673 const MINGW = 1 << 5;
675 }
676}
677rustc_data_structures::external_bitflags_debug! { LinkSelfContainedComponents }
678
679impl LinkSelfContainedComponents {
680 pub fn as_str(self) -> Option<&'static str> {
684 Some(match self {
685 LinkSelfContainedComponents::CRT_OBJECTS => "crto",
686 LinkSelfContainedComponents::LIBC => "libc",
687 LinkSelfContainedComponents::UNWIND => "unwind",
688 LinkSelfContainedComponents::LINKER => "linker",
689 LinkSelfContainedComponents::SANITIZERS => "sanitizers",
690 LinkSelfContainedComponents::MINGW => "mingw",
691 _ => return None,
692 })
693 }
694
695 fn all_components() -> [LinkSelfContainedComponents; 6] {
697 [
698 LinkSelfContainedComponents::CRT_OBJECTS,
699 LinkSelfContainedComponents::LIBC,
700 LinkSelfContainedComponents::UNWIND,
701 LinkSelfContainedComponents::LINKER,
702 LinkSelfContainedComponents::SANITIZERS,
703 LinkSelfContainedComponents::MINGW,
704 ]
705 }
706
707 pub fn are_any_components_enabled(self) -> bool {
709 !self.is_empty()
710 }
711
712 pub fn is_linker_enabled(self) -> bool {
714 self.contains(LinkSelfContainedComponents::LINKER)
715 }
716
717 pub fn is_crt_objects_enabled(self) -> bool {
719 self.contains(LinkSelfContainedComponents::CRT_OBJECTS)
720 }
721}
722
723impl FromStr for LinkSelfContainedComponents {
724 type Err = String;
725
726 fn from_str(s: &str) -> Result<Self, Self::Err> {
728 Ok(match s {
729 "crto" => LinkSelfContainedComponents::CRT_OBJECTS,
730 "libc" => LinkSelfContainedComponents::LIBC,
731 "unwind" => LinkSelfContainedComponents::UNWIND,
732 "linker" => LinkSelfContainedComponents::LINKER,
733 "sanitizers" => LinkSelfContainedComponents::SANITIZERS,
734 "mingw" => LinkSelfContainedComponents::MINGW,
735 _ => {
736 return Err(format!(
737 "'{s}' is not a valid link-self-contained component, expected 'crto', 'libc', 'unwind', 'linker', 'sanitizers', 'mingw'"
738 ));
739 }
740 })
741 }
742}
743
744crate::json::serde_deserialize_from_str!(LinkSelfContainedComponents);
745
746impl ToJson for LinkSelfContainedComponents {
747 fn to_json(&self) -> Json {
748 let components: Vec<_> = Self::all_components()
749 .into_iter()
750 .filter(|c| self.contains(*c))
751 .map(|c| {
752 c.as_str().unwrap().to_owned()
755 })
756 .collect();
757
758 components.to_json()
759 }
760}
761
762bitflags::bitflags! {
763 #[derive(Clone, Copy, PartialEq, Eq, Default)]
784 pub struct LinkerFeatures: u8 {
785 const CC = 1 << 0;
787 const LLD = 1 << 1;
789 }
790}
791rustc_data_structures::external_bitflags_debug! { LinkerFeatures }
792
793impl LinkerFeatures {
794 pub fn from_str(s: &str) -> Option<LinkerFeatures> {
796 Some(match s {
797 "cc" => LinkerFeatures::CC,
798 "lld" => LinkerFeatures::LLD,
799 _ => return None,
800 })
801 }
802
803 pub fn as_str(self) -> Option<&'static str> {
807 Some(match self {
808 LinkerFeatures::CC => "cc",
809 LinkerFeatures::LLD => "lld",
810 _ => return None,
811 })
812 }
813
814 pub fn is_lld_enabled(self) -> bool {
816 self.contains(LinkerFeatures::LLD)
817 }
818
819 pub fn is_cc_enabled(self) -> bool {
821 self.contains(LinkerFeatures::CC)
822 }
823}
824
825#[derive(Clone, Copy, Debug, PartialEq, Hash, Encodable, Decodable, HashStable_Generic)]
826pub enum PanicStrategy {
827 Unwind,
828 Abort,
829}
830
831#[derive(Clone, Copy, Debug, PartialEq, Hash, Encodable, Decodable, HashStable_Generic)]
832pub enum OnBrokenPipe {
833 Default,
834 Kill,
835 Error,
836 Inherit,
837}
838
839impl PanicStrategy {
840 pub fn desc(&self) -> &str {
841 match *self {
842 PanicStrategy::Unwind => "unwind",
843 PanicStrategy::Abort => "abort",
844 }
845 }
846
847 pub const fn desc_symbol(&self) -> Symbol {
848 match *self {
849 PanicStrategy::Unwind => sym::unwind,
850 PanicStrategy::Abort => sym::abort,
851 }
852 }
853
854 pub const fn all() -> [Symbol; 2] {
855 [Self::Abort.desc_symbol(), Self::Unwind.desc_symbol()]
856 }
857}
858
859impl FromStr for PanicStrategy {
860 type Err = String;
861 fn from_str(s: &str) -> Result<Self, Self::Err> {
862 Ok(match s {
863 "unwind" => PanicStrategy::Unwind,
864 "abort" => PanicStrategy::Abort,
865 _ => {
866 return Err(format!(
867 "'{}' is not a valid value for \
868 panic-strategy. Use 'unwind' or 'abort'.",
869 s
870 ));
871 }
872 })
873 }
874}
875
876crate::json::serde_deserialize_from_str!(PanicStrategy);
877
878impl ToJson for PanicStrategy {
879 fn to_json(&self) -> Json {
880 match *self {
881 PanicStrategy::Abort => "abort".to_json(),
882 PanicStrategy::Unwind => "unwind".to_json(),
883 }
884 }
885}
886
887#[derive(Clone, Copy, Debug, PartialEq, Hash)]
888pub enum RelroLevel {
889 Full,
890 Partial,
891 Off,
892 None,
893}
894
895impl RelroLevel {
896 pub fn desc(&self) -> &str {
897 match *self {
898 RelroLevel::Full => "full",
899 RelroLevel::Partial => "partial",
900 RelroLevel::Off => "off",
901 RelroLevel::None => "none",
902 }
903 }
904}
905
906#[derive(Clone, Copy, Debug, PartialEq, Hash)]
907pub enum SymbolVisibility {
908 Hidden,
909 Protected,
910 Interposable,
911}
912
913impl SymbolVisibility {
914 pub fn desc(&self) -> &str {
915 match *self {
916 SymbolVisibility::Hidden => "hidden",
917 SymbolVisibility::Protected => "protected",
918 SymbolVisibility::Interposable => "interposable",
919 }
920 }
921}
922
923impl FromStr for SymbolVisibility {
924 type Err = String;
925
926 fn from_str(s: &str) -> Result<SymbolVisibility, Self::Err> {
927 match s {
928 "hidden" => Ok(SymbolVisibility::Hidden),
929 "protected" => Ok(SymbolVisibility::Protected),
930 "interposable" => Ok(SymbolVisibility::Interposable),
931 _ => Err(format!(
932 "'{}' is not a valid value for \
933 symbol-visibility. Use 'hidden', 'protected, or 'interposable'.",
934 s
935 )),
936 }
937 }
938}
939
940crate::json::serde_deserialize_from_str!(SymbolVisibility);
941
942impl ToJson for SymbolVisibility {
943 fn to_json(&self) -> Json {
944 match *self {
945 SymbolVisibility::Hidden => "hidden".to_json(),
946 SymbolVisibility::Protected => "protected".to_json(),
947 SymbolVisibility::Interposable => "interposable".to_json(),
948 }
949 }
950}
951
952impl FromStr for RelroLevel {
953 type Err = String;
954
955 fn from_str(s: &str) -> Result<RelroLevel, Self::Err> {
956 match s {
957 "full" => Ok(RelroLevel::Full),
958 "partial" => Ok(RelroLevel::Partial),
959 "off" => Ok(RelroLevel::Off),
960 "none" => Ok(RelroLevel::None),
961 _ => Err(format!(
962 "'{}' is not a valid value for \
963 relro-level. Use 'full', 'partial, 'off', or 'none'.",
964 s
965 )),
966 }
967 }
968}
969
970crate::json::serde_deserialize_from_str!(RelroLevel);
971
972impl ToJson for RelroLevel {
973 fn to_json(&self) -> Json {
974 match *self {
975 RelroLevel::Full => "full".to_json(),
976 RelroLevel::Partial => "partial".to_json(),
977 RelroLevel::Off => "off".to_json(),
978 RelroLevel::None => "None".to_json(),
979 }
980 }
981}
982
983#[derive(Clone, Debug, PartialEq, Hash)]
984pub enum SmallDataThresholdSupport {
985 None,
986 DefaultForArch,
987 LlvmModuleFlag(StaticCow<str>),
988 LlvmArg(StaticCow<str>),
989}
990
991impl FromStr for SmallDataThresholdSupport {
992 type Err = String;
993
994 fn from_str(s: &str) -> Result<Self, Self::Err> {
995 if s == "none" {
996 Ok(Self::None)
997 } else if s == "default-for-arch" {
998 Ok(Self::DefaultForArch)
999 } else if let Some(flag) = s.strip_prefix("llvm-module-flag=") {
1000 Ok(Self::LlvmModuleFlag(flag.to_string().into()))
1001 } else if let Some(arg) = s.strip_prefix("llvm-arg=") {
1002 Ok(Self::LlvmArg(arg.to_string().into()))
1003 } else {
1004 Err(format!("'{s}' is not a valid value for small-data-threshold-support."))
1005 }
1006 }
1007}
1008
1009crate::json::serde_deserialize_from_str!(SmallDataThresholdSupport);
1010
1011impl ToJson for SmallDataThresholdSupport {
1012 fn to_json(&self) -> Value {
1013 match self {
1014 Self::None => "none".to_json(),
1015 Self::DefaultForArch => "default-for-arch".to_json(),
1016 Self::LlvmModuleFlag(flag) => format!("llvm-module-flag={flag}").to_json(),
1017 Self::LlvmArg(arg) => format!("llvm-arg={arg}").to_json(),
1018 }
1019 }
1020}
1021
1022#[derive(Clone, Copy, Debug, PartialEq, Hash)]
1023pub enum MergeFunctions {
1024 Disabled,
1025 Trampolines,
1026 Aliases,
1027}
1028
1029impl MergeFunctions {
1030 pub fn desc(&self) -> &str {
1031 match *self {
1032 MergeFunctions::Disabled => "disabled",
1033 MergeFunctions::Trampolines => "trampolines",
1034 MergeFunctions::Aliases => "aliases",
1035 }
1036 }
1037}
1038
1039impl FromStr for MergeFunctions {
1040 type Err = String;
1041
1042 fn from_str(s: &str) -> Result<MergeFunctions, Self::Err> {
1043 match s {
1044 "disabled" => Ok(MergeFunctions::Disabled),
1045 "trampolines" => Ok(MergeFunctions::Trampolines),
1046 "aliases" => Ok(MergeFunctions::Aliases),
1047 _ => Err(format!(
1048 "'{}' is not a valid value for \
1049 merge-functions. Use 'disabled', \
1050 'trampolines', or 'aliases'.",
1051 s
1052 )),
1053 }
1054 }
1055}
1056
1057crate::json::serde_deserialize_from_str!(MergeFunctions);
1058
1059impl ToJson for MergeFunctions {
1060 fn to_json(&self) -> Json {
1061 match *self {
1062 MergeFunctions::Disabled => "disabled".to_json(),
1063 MergeFunctions::Trampolines => "trampolines".to_json(),
1064 MergeFunctions::Aliases => "aliases".to_json(),
1065 }
1066 }
1067}
1068
1069#[derive(Clone, Copy, PartialEq, Hash, Debug)]
1070pub enum RelocModel {
1071 Static,
1072 Pic,
1073 Pie,
1074 DynamicNoPic,
1075 Ropi,
1076 Rwpi,
1077 RopiRwpi,
1078}
1079
1080impl RelocModel {
1081 pub fn desc(&self) -> &str {
1082 match *self {
1083 RelocModel::Static => "static",
1084 RelocModel::Pic => "pic",
1085 RelocModel::Pie => "pie",
1086 RelocModel::DynamicNoPic => "dynamic-no-pic",
1087 RelocModel::Ropi => "ropi",
1088 RelocModel::Rwpi => "rwpi",
1089 RelocModel::RopiRwpi => "ropi-rwpi",
1090 }
1091 }
1092 pub const fn desc_symbol(&self) -> Symbol {
1093 match *self {
1094 RelocModel::Static => kw::Static,
1095 RelocModel::Pic => sym::pic,
1096 RelocModel::Pie => sym::pie,
1097 RelocModel::DynamicNoPic => sym::dynamic_no_pic,
1098 RelocModel::Ropi => sym::ropi,
1099 RelocModel::Rwpi => sym::rwpi,
1100 RelocModel::RopiRwpi => sym::ropi_rwpi,
1101 }
1102 }
1103
1104 pub const fn all() -> [Symbol; 7] {
1105 [
1106 RelocModel::Static.desc_symbol(),
1107 RelocModel::Pic.desc_symbol(),
1108 RelocModel::Pie.desc_symbol(),
1109 RelocModel::DynamicNoPic.desc_symbol(),
1110 RelocModel::Ropi.desc_symbol(),
1111 RelocModel::Rwpi.desc_symbol(),
1112 RelocModel::RopiRwpi.desc_symbol(),
1113 ]
1114 }
1115}
1116
1117impl FromStr for RelocModel {
1118 type Err = String;
1119
1120 fn from_str(s: &str) -> Result<RelocModel, Self::Err> {
1121 Ok(match s {
1122 "static" => RelocModel::Static,
1123 "pic" => RelocModel::Pic,
1124 "pie" => RelocModel::Pie,
1125 "dynamic-no-pic" => RelocModel::DynamicNoPic,
1126 "ropi" => RelocModel::Ropi,
1127 "rwpi" => RelocModel::Rwpi,
1128 "ropi-rwpi" => RelocModel::RopiRwpi,
1129 _ => {
1130 return Err(format!(
1131 "invalid relocation model '{s}'.
1132 Run `rustc --print relocation-models` to \
1133 see the list of supported values.'"
1134 ));
1135 }
1136 })
1137 }
1138}
1139
1140crate::json::serde_deserialize_from_str!(RelocModel);
1141
1142impl ToJson for RelocModel {
1143 fn to_json(&self) -> Json {
1144 self.desc().to_json()
1145 }
1146}
1147
1148#[derive(Clone, Copy, PartialEq, Hash, Debug)]
1149pub enum CodeModel {
1150 Tiny,
1151 Small,
1152 Kernel,
1153 Medium,
1154 Large,
1155}
1156
1157impl FromStr for CodeModel {
1158 type Err = String;
1159
1160 fn from_str(s: &str) -> Result<CodeModel, Self::Err> {
1161 Ok(match s {
1162 "tiny" => CodeModel::Tiny,
1163 "small" => CodeModel::Small,
1164 "kernel" => CodeModel::Kernel,
1165 "medium" => CodeModel::Medium,
1166 "large" => CodeModel::Large,
1167 _ => {
1168 return Err(format!(
1169 "'{s}' is not a valid code model. \
1170 Run `rustc --print code-models` to \
1171 see the list of supported values."
1172 ));
1173 }
1174 })
1175 }
1176}
1177
1178crate::json::serde_deserialize_from_str!(CodeModel);
1179
1180impl ToJson for CodeModel {
1181 fn to_json(&self) -> Json {
1182 match *self {
1183 CodeModel::Tiny => "tiny",
1184 CodeModel::Small => "small",
1185 CodeModel::Kernel => "kernel",
1186 CodeModel::Medium => "medium",
1187 CodeModel::Large => "large",
1188 }
1189 .to_json()
1190 }
1191}
1192
1193#[derive(Clone, Copy, PartialEq, Hash, Debug)]
1195pub enum FloatAbi {
1196 Soft,
1197 Hard,
1198}
1199
1200impl FromStr for FloatAbi {
1201 type Err = String;
1202
1203 fn from_str(s: &str) -> Result<FloatAbi, Self::Err> {
1204 Ok(match s {
1205 "soft" => FloatAbi::Soft,
1206 "hard" => FloatAbi::Hard,
1207 _ => {
1208 return Err(format!(
1209 "'{}' is not a valid value for \
1210 llvm-floatabi. Use 'soft' or 'hard'.",
1211 s
1212 ));
1213 }
1214 })
1215 }
1216}
1217
1218crate::json::serde_deserialize_from_str!(FloatAbi);
1219
1220impl ToJson for FloatAbi {
1221 fn to_json(&self) -> Json {
1222 match *self {
1223 FloatAbi::Soft => "soft",
1224 FloatAbi::Hard => "hard",
1225 }
1226 .to_json()
1227 }
1228}
1229
1230#[derive(Clone, Copy, PartialEq, Hash, Debug)]
1232pub enum RustcAbi {
1233 X86Sse2,
1235 X86Softfloat,
1237}
1238
1239impl FromStr for RustcAbi {
1240 type Err = String;
1241
1242 fn from_str(s: &str) -> Result<RustcAbi, Self::Err> {
1243 Ok(match s {
1244 "x86-sse2" => RustcAbi::X86Sse2,
1245 "x86-softfloat" => RustcAbi::X86Softfloat,
1246 _ => {
1247 return Err(format!(
1248 "'{s}' is not a valid value for rustc-abi. \
1249 Use 'x86-softfloat' or leave the field unset."
1250 ));
1251 }
1252 })
1253 }
1254}
1255
1256crate::json::serde_deserialize_from_str!(RustcAbi);
1257
1258impl ToJson for RustcAbi {
1259 fn to_json(&self) -> Json {
1260 match *self {
1261 RustcAbi::X86Sse2 => "x86-sse2",
1262 RustcAbi::X86Softfloat => "x86-softfloat",
1263 }
1264 .to_json()
1265 }
1266}
1267
1268#[derive(Clone, Copy, PartialEq, Hash, Debug)]
1269pub enum TlsModel {
1270 GeneralDynamic,
1271 LocalDynamic,
1272 InitialExec,
1273 LocalExec,
1274 Emulated,
1275}
1276
1277impl FromStr for TlsModel {
1278 type Err = String;
1279
1280 fn from_str(s: &str) -> Result<TlsModel, Self::Err> {
1281 Ok(match s {
1282 "global-dynamic" => TlsModel::GeneralDynamic,
1285 "local-dynamic" => TlsModel::LocalDynamic,
1286 "initial-exec" => TlsModel::InitialExec,
1287 "local-exec" => TlsModel::LocalExec,
1288 "emulated" => TlsModel::Emulated,
1289 _ => {
1290 return Err(format!(
1291 "'{s}' is not a valid TLS model. \
1292 Run `rustc --print tls-models` to \
1293 see the list of supported values."
1294 ));
1295 }
1296 })
1297 }
1298}
1299
1300crate::json::serde_deserialize_from_str!(TlsModel);
1301
1302impl ToJson for TlsModel {
1303 fn to_json(&self) -> Json {
1304 match *self {
1305 TlsModel::GeneralDynamic => "global-dynamic",
1306 TlsModel::LocalDynamic => "local-dynamic",
1307 TlsModel::InitialExec => "initial-exec",
1308 TlsModel::LocalExec => "local-exec",
1309 TlsModel::Emulated => "emulated",
1310 }
1311 .to_json()
1312 }
1313}
1314
1315#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug)]
1317pub enum LinkOutputKind {
1318 DynamicNoPicExe,
1320 DynamicPicExe,
1322 StaticNoPicExe,
1324 StaticPicExe,
1326 DynamicDylib,
1328 StaticDylib,
1330 WasiReactorExe,
1332}
1333
1334impl LinkOutputKind {
1335 fn as_str(&self) -> &'static str {
1336 match self {
1337 LinkOutputKind::DynamicNoPicExe => "dynamic-nopic-exe",
1338 LinkOutputKind::DynamicPicExe => "dynamic-pic-exe",
1339 LinkOutputKind::StaticNoPicExe => "static-nopic-exe",
1340 LinkOutputKind::StaticPicExe => "static-pic-exe",
1341 LinkOutputKind::DynamicDylib => "dynamic-dylib",
1342 LinkOutputKind::StaticDylib => "static-dylib",
1343 LinkOutputKind::WasiReactorExe => "wasi-reactor-exe",
1344 }
1345 }
1346
1347 pub fn can_link_dylib(self) -> bool {
1348 match self {
1349 LinkOutputKind::StaticNoPicExe | LinkOutputKind::StaticPicExe => false,
1350 LinkOutputKind::DynamicNoPicExe
1351 | LinkOutputKind::DynamicPicExe
1352 | LinkOutputKind::DynamicDylib
1353 | LinkOutputKind::StaticDylib
1354 | LinkOutputKind::WasiReactorExe => true,
1355 }
1356 }
1357}
1358
1359impl FromStr for LinkOutputKind {
1360 type Err = String;
1361
1362 fn from_str(s: &str) -> Result<LinkOutputKind, Self::Err> {
1363 Ok(match s {
1364 "dynamic-nopic-exe" => LinkOutputKind::DynamicNoPicExe,
1365 "dynamic-pic-exe" => LinkOutputKind::DynamicPicExe,
1366 "static-nopic-exe" => LinkOutputKind::StaticNoPicExe,
1367 "static-pic-exe" => LinkOutputKind::StaticPicExe,
1368 "dynamic-dylib" => LinkOutputKind::DynamicDylib,
1369 "static-dylib" => LinkOutputKind::StaticDylib,
1370 "wasi-reactor-exe" => LinkOutputKind::WasiReactorExe,
1371 _ => {
1372 return Err(format!(
1373 "invalid value for CRT object kind. \
1374 Use '(dynamic,static)-(nopic,pic)-exe' or \
1375 '(dynamic,static)-dylib' or 'wasi-reactor-exe'"
1376 ));
1377 }
1378 })
1379 }
1380}
1381
1382crate::json::serde_deserialize_from_str!(LinkOutputKind);
1383
1384impl fmt::Display for LinkOutputKind {
1385 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1386 f.write_str(self.as_str())
1387 }
1388}
1389
1390pub type LinkArgs = BTreeMap<LinkerFlavor, Vec<StaticCow<str>>>;
1391pub type LinkArgsCli = BTreeMap<LinkerFlavorCli, Vec<StaticCow<str>>>;
1392
1393#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
1398pub enum DebuginfoKind {
1399 #[default]
1401 Dwarf,
1402 DwarfDsym,
1404 Pdb,
1406}
1407
1408impl DebuginfoKind {
1409 fn as_str(&self) -> &'static str {
1410 match self {
1411 DebuginfoKind::Dwarf => "dwarf",
1412 DebuginfoKind::DwarfDsym => "dwarf-dsym",
1413 DebuginfoKind::Pdb => "pdb",
1414 }
1415 }
1416}
1417
1418impl FromStr for DebuginfoKind {
1419 type Err = String;
1420
1421 fn from_str(s: &str) -> Result<Self, Self::Err> {
1422 Ok(match s {
1423 "dwarf" => DebuginfoKind::Dwarf,
1424 "dwarf-dsym" => DebuginfoKind::DwarfDsym,
1425 "pdb" => DebuginfoKind::Pdb,
1426 _ => {
1427 return Err(format!(
1428 "'{s}' is not a valid value for debuginfo-kind. Use 'dwarf', \
1429 'dwarf-dsym' or 'pdb'."
1430 ));
1431 }
1432 })
1433 }
1434}
1435
1436crate::json::serde_deserialize_from_str!(DebuginfoKind);
1437
1438impl ToJson for DebuginfoKind {
1439 fn to_json(&self) -> Json {
1440 self.as_str().to_json()
1441 }
1442}
1443
1444impl fmt::Display for DebuginfoKind {
1445 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1446 f.write_str(self.as_str())
1447 }
1448}
1449
1450#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
1451pub enum SplitDebuginfo {
1452 #[default]
1460 Off,
1461
1462 Packed,
1469
1470 Unpacked,
1477}
1478
1479impl SplitDebuginfo {
1480 fn as_str(&self) -> &'static str {
1481 match self {
1482 SplitDebuginfo::Off => "off",
1483 SplitDebuginfo::Packed => "packed",
1484 SplitDebuginfo::Unpacked => "unpacked",
1485 }
1486 }
1487}
1488
1489impl FromStr for SplitDebuginfo {
1490 type Err = String;
1491
1492 fn from_str(s: &str) -> Result<Self, Self::Err> {
1493 Ok(match s {
1494 "off" => SplitDebuginfo::Off,
1495 "unpacked" => SplitDebuginfo::Unpacked,
1496 "packed" => SplitDebuginfo::Packed,
1497 _ => {
1498 return Err(format!(
1499 "'{s}' is not a valid value for \
1500 split-debuginfo. Use 'off', 'unpacked', or 'packed'.",
1501 ));
1502 }
1503 })
1504 }
1505}
1506
1507crate::json::serde_deserialize_from_str!(SplitDebuginfo);
1508
1509impl ToJson for SplitDebuginfo {
1510 fn to_json(&self) -> Json {
1511 self.as_str().to_json()
1512 }
1513}
1514
1515impl fmt::Display for SplitDebuginfo {
1516 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1517 f.write_str(self.as_str())
1518 }
1519}
1520
1521#[derive(Clone, Debug, PartialEq, Eq, serde_derive::Deserialize)]
1522#[serde(tag = "kind")]
1523#[serde(rename_all = "kebab-case")]
1524pub enum StackProbeType {
1525 None,
1527 Inline,
1531 Call,
1533 InlineOrCall {
1536 #[serde(rename = "min-llvm-version-for-inline")]
1537 min_llvm_version_for_inline: (u32, u32, u32),
1538 },
1539}
1540
1541impl ToJson for StackProbeType {
1542 fn to_json(&self) -> Json {
1543 Json::Object(match self {
1544 StackProbeType::None => {
1545 [(String::from("kind"), "none".to_json())].into_iter().collect()
1546 }
1547 StackProbeType::Inline => {
1548 [(String::from("kind"), "inline".to_json())].into_iter().collect()
1549 }
1550 StackProbeType::Call => {
1551 [(String::from("kind"), "call".to_json())].into_iter().collect()
1552 }
1553 StackProbeType::InlineOrCall { min_llvm_version_for_inline: (maj, min, patch) } => [
1554 (String::from("kind"), "inline-or-call".to_json()),
1555 (
1556 String::from("min-llvm-version-for-inline"),
1557 Json::Array(vec![maj.to_json(), min.to_json(), patch.to_json()]),
1558 ),
1559 ]
1560 .into_iter()
1561 .collect(),
1562 })
1563 }
1564}
1565
1566#[derive(Default, Clone, Copy, PartialEq, Eq, Hash, Encodable, Decodable, HashStable_Generic)]
1567pub struct SanitizerSet(u16);
1568bitflags::bitflags! {
1569 impl SanitizerSet: u16 {
1570 const ADDRESS = 1 << 0;
1571 const LEAK = 1 << 1;
1572 const MEMORY = 1 << 2;
1573 const THREAD = 1 << 3;
1574 const HWADDRESS = 1 << 4;
1575 const CFI = 1 << 5;
1576 const MEMTAG = 1 << 6;
1577 const SHADOWCALLSTACK = 1 << 7;
1578 const KCFI = 1 << 8;
1579 const KERNELADDRESS = 1 << 9;
1580 const SAFESTACK = 1 << 10;
1581 const DATAFLOW = 1 << 11;
1582 }
1583}
1584rustc_data_structures::external_bitflags_debug! { SanitizerSet }
1585
1586impl SanitizerSet {
1587 const MUTUALLY_EXCLUSIVE: &'static [(SanitizerSet, SanitizerSet)] = &[
1590 (SanitizerSet::ADDRESS, SanitizerSet::MEMORY),
1591 (SanitizerSet::ADDRESS, SanitizerSet::THREAD),
1592 (SanitizerSet::ADDRESS, SanitizerSet::HWADDRESS),
1593 (SanitizerSet::ADDRESS, SanitizerSet::MEMTAG),
1594 (SanitizerSet::ADDRESS, SanitizerSet::KERNELADDRESS),
1595 (SanitizerSet::ADDRESS, SanitizerSet::SAFESTACK),
1596 (SanitizerSet::LEAK, SanitizerSet::MEMORY),
1597 (SanitizerSet::LEAK, SanitizerSet::THREAD),
1598 (SanitizerSet::LEAK, SanitizerSet::KERNELADDRESS),
1599 (SanitizerSet::LEAK, SanitizerSet::SAFESTACK),
1600 (SanitizerSet::MEMORY, SanitizerSet::THREAD),
1601 (SanitizerSet::MEMORY, SanitizerSet::HWADDRESS),
1602 (SanitizerSet::MEMORY, SanitizerSet::KERNELADDRESS),
1603 (SanitizerSet::MEMORY, SanitizerSet::SAFESTACK),
1604 (SanitizerSet::THREAD, SanitizerSet::HWADDRESS),
1605 (SanitizerSet::THREAD, SanitizerSet::KERNELADDRESS),
1606 (SanitizerSet::THREAD, SanitizerSet::SAFESTACK),
1607 (SanitizerSet::HWADDRESS, SanitizerSet::MEMTAG),
1608 (SanitizerSet::HWADDRESS, SanitizerSet::KERNELADDRESS),
1609 (SanitizerSet::HWADDRESS, SanitizerSet::SAFESTACK),
1610 (SanitizerSet::CFI, SanitizerSet::KCFI),
1611 (SanitizerSet::MEMTAG, SanitizerSet::KERNELADDRESS),
1612 (SanitizerSet::KERNELADDRESS, SanitizerSet::SAFESTACK),
1613 ];
1614
1615 pub fn as_str(self) -> Option<&'static str> {
1619 Some(match self {
1620 SanitizerSet::ADDRESS => "address",
1621 SanitizerSet::CFI => "cfi",
1622 SanitizerSet::DATAFLOW => "dataflow",
1623 SanitizerSet::KCFI => "kcfi",
1624 SanitizerSet::KERNELADDRESS => "kernel-address",
1625 SanitizerSet::LEAK => "leak",
1626 SanitizerSet::MEMORY => "memory",
1627 SanitizerSet::MEMTAG => "memtag",
1628 SanitizerSet::SAFESTACK => "safestack",
1629 SanitizerSet::SHADOWCALLSTACK => "shadow-call-stack",
1630 SanitizerSet::THREAD => "thread",
1631 SanitizerSet::HWADDRESS => "hwaddress",
1632 _ => return None,
1633 })
1634 }
1635
1636 pub fn mutually_exclusive(self) -> Option<(SanitizerSet, SanitizerSet)> {
1637 Self::MUTUALLY_EXCLUSIVE
1638 .into_iter()
1639 .find(|&(a, b)| self.contains(*a) && self.contains(*b))
1640 .copied()
1641 }
1642}
1643
1644impl fmt::Display for SanitizerSet {
1646 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1647 let mut first = true;
1648 for s in *self {
1649 let name = s.as_str().unwrap_or_else(|| panic!("unrecognized sanitizer {s:?}"));
1650 if !first {
1651 f.write_str(", ")?;
1652 }
1653 f.write_str(name)?;
1654 first = false;
1655 }
1656 Ok(())
1657 }
1658}
1659
1660impl FromStr for SanitizerSet {
1661 type Err = String;
1662 fn from_str(s: &str) -> Result<Self, Self::Err> {
1663 Ok(match s {
1664 "address" => SanitizerSet::ADDRESS,
1665 "cfi" => SanitizerSet::CFI,
1666 "dataflow" => SanitizerSet::DATAFLOW,
1667 "kcfi" => SanitizerSet::KCFI,
1668 "kernel-address" => SanitizerSet::KERNELADDRESS,
1669 "leak" => SanitizerSet::LEAK,
1670 "memory" => SanitizerSet::MEMORY,
1671 "memtag" => SanitizerSet::MEMTAG,
1672 "safestack" => SanitizerSet::SAFESTACK,
1673 "shadow-call-stack" => SanitizerSet::SHADOWCALLSTACK,
1674 "thread" => SanitizerSet::THREAD,
1675 "hwaddress" => SanitizerSet::HWADDRESS,
1676 s => return Err(format!("unknown sanitizer {s}")),
1677 })
1678 }
1679}
1680
1681crate::json::serde_deserialize_from_str!(SanitizerSet);
1682
1683impl ToJson for SanitizerSet {
1684 fn to_json(&self) -> Json {
1685 self.into_iter()
1686 .map(|v| Some(v.as_str()?.to_json()))
1687 .collect::<Option<Vec<_>>>()
1688 .unwrap_or_default()
1689 .to_json()
1690 }
1691}
1692
1693#[derive(Clone, Copy, PartialEq, Hash, Debug)]
1694pub enum FramePointer {
1695 Always,
1697 NonLeaf,
1700 MayOmit,
1704}
1705
1706impl FramePointer {
1707 #[inline]
1710 pub fn ratchet(&mut self, rhs: FramePointer) -> FramePointer {
1711 *self = match (*self, rhs) {
1712 (FramePointer::Always, _) | (_, FramePointer::Always) => FramePointer::Always,
1713 (FramePointer::NonLeaf, _) | (_, FramePointer::NonLeaf) => FramePointer::NonLeaf,
1714 _ => FramePointer::MayOmit,
1715 };
1716 *self
1717 }
1718}
1719
1720impl FromStr for FramePointer {
1721 type Err = String;
1722 fn from_str(s: &str) -> Result<Self, Self::Err> {
1723 Ok(match s {
1724 "always" => Self::Always,
1725 "non-leaf" => Self::NonLeaf,
1726 "may-omit" => Self::MayOmit,
1727 _ => return Err(format!("'{s}' is not a valid value for frame-pointer")),
1728 })
1729 }
1730}
1731
1732crate::json::serde_deserialize_from_str!(FramePointer);
1733
1734impl ToJson for FramePointer {
1735 fn to_json(&self) -> Json {
1736 match *self {
1737 Self::Always => "always",
1738 Self::NonLeaf => "non-leaf",
1739 Self::MayOmit => "may-omit",
1740 }
1741 .to_json()
1742 }
1743}
1744
1745#[derive(Clone, Copy, Debug, PartialEq, Hash, Eq)]
1747pub enum StackProtector {
1748 None,
1750
1751 Basic,
1756
1757 Strong,
1762
1763 All,
1765}
1766
1767impl StackProtector {
1768 fn as_str(&self) -> &'static str {
1769 match self {
1770 StackProtector::None => "none",
1771 StackProtector::Basic => "basic",
1772 StackProtector::Strong => "strong",
1773 StackProtector::All => "all",
1774 }
1775 }
1776}
1777
1778impl FromStr for StackProtector {
1779 type Err = ();
1780
1781 fn from_str(s: &str) -> Result<StackProtector, ()> {
1782 Ok(match s {
1783 "none" => StackProtector::None,
1784 "basic" => StackProtector::Basic,
1785 "strong" => StackProtector::Strong,
1786 "all" => StackProtector::All,
1787 _ => return Err(()),
1788 })
1789 }
1790}
1791
1792impl fmt::Display for StackProtector {
1793 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1794 f.write_str(self.as_str())
1795 }
1796}
1797
1798#[derive(PartialEq, Clone, Debug)]
1799pub enum BinaryFormat {
1800 Coff,
1801 Elf,
1802 MachO,
1803 Wasm,
1804 Xcoff,
1805}
1806
1807impl BinaryFormat {
1808 pub fn to_object(&self) -> object::BinaryFormat {
1810 match self {
1811 Self::Coff => object::BinaryFormat::Coff,
1812 Self::Elf => object::BinaryFormat::Elf,
1813 Self::MachO => object::BinaryFormat::MachO,
1814 Self::Wasm => object::BinaryFormat::Wasm,
1815 Self::Xcoff => object::BinaryFormat::Xcoff,
1816 }
1817 }
1818}
1819
1820impl FromStr for BinaryFormat {
1821 type Err = String;
1822 fn from_str(s: &str) -> Result<Self, Self::Err> {
1823 match s {
1824 "coff" => Ok(Self::Coff),
1825 "elf" => Ok(Self::Elf),
1826 "mach-o" => Ok(Self::MachO),
1827 "wasm" => Ok(Self::Wasm),
1828 "xcoff" => Ok(Self::Xcoff),
1829 _ => Err(format!(
1830 "'{s}' is not a valid value for binary_format. \
1831 Use 'coff', 'elf', 'mach-o', 'wasm' or 'xcoff' "
1832 )),
1833 }
1834 }
1835}
1836
1837crate::json::serde_deserialize_from_str!(BinaryFormat);
1838
1839impl ToJson for BinaryFormat {
1840 fn to_json(&self) -> Json {
1841 match self {
1842 Self::Coff => "coff",
1843 Self::Elf => "elf",
1844 Self::MachO => "mach-o",
1845 Self::Wasm => "wasm",
1846 Self::Xcoff => "xcoff",
1847 }
1848 .to_json()
1849 }
1850}
1851
1852impl ToJson for Align {
1853 fn to_json(&self) -> Json {
1854 self.bits().to_json()
1855 }
1856}
1857
1858macro_rules! supported_targets {
1859 ( $(($tuple:literal, $module:ident),)+ ) => {
1860 mod targets {
1861 $(pub(crate) mod $module;)+
1862 }
1863
1864 pub static TARGETS: &[&str] = &[$($tuple),+];
1866
1867 fn load_builtin(target: &str) -> Option<Target> {
1868 let t = match target {
1869 $( $tuple => targets::$module::target(), )+
1870 _ => return None,
1871 };
1872 debug!("got builtin target: {:?}", t);
1873 Some(t)
1874 }
1875
1876 fn load_all_builtins() -> impl Iterator<Item = Target> {
1877 [
1878 $( targets::$module::target, )+
1879 ]
1880 .into_iter()
1881 .map(|f| f())
1882 }
1883
1884 #[cfg(test)]
1885 mod tests {
1886 $(
1888 #[test] fn $module() {
1890 crate::spec::targets::$module::target().test_target()
1891 }
1892 )+
1893 }
1894 };
1895}
1896
1897supported_targets! {
1898 ("x86_64-unknown-linux-gnu", x86_64_unknown_linux_gnu),
1899 ("x86_64-unknown-linux-gnux32", x86_64_unknown_linux_gnux32),
1900 ("i686-unknown-linux-gnu", i686_unknown_linux_gnu),
1901 ("i586-unknown-linux-gnu", i586_unknown_linux_gnu),
1902 ("loongarch64-unknown-linux-gnu", loongarch64_unknown_linux_gnu),
1903 ("loongarch64-unknown-linux-musl", loongarch64_unknown_linux_musl),
1904 ("m68k-unknown-linux-gnu", m68k_unknown_linux_gnu),
1905 ("m68k-unknown-none-elf", m68k_unknown_none_elf),
1906 ("csky-unknown-linux-gnuabiv2", csky_unknown_linux_gnuabiv2),
1907 ("csky-unknown-linux-gnuabiv2hf", csky_unknown_linux_gnuabiv2hf),
1908 ("mips-unknown-linux-gnu", mips_unknown_linux_gnu),
1909 ("mips64-unknown-linux-gnuabi64", mips64_unknown_linux_gnuabi64),
1910 ("mips64el-unknown-linux-gnuabi64", mips64el_unknown_linux_gnuabi64),
1911 ("mipsisa32r6-unknown-linux-gnu", mipsisa32r6_unknown_linux_gnu),
1912 ("mipsisa32r6el-unknown-linux-gnu", mipsisa32r6el_unknown_linux_gnu),
1913 ("mipsisa64r6-unknown-linux-gnuabi64", mipsisa64r6_unknown_linux_gnuabi64),
1914 ("mipsisa64r6el-unknown-linux-gnuabi64", mipsisa64r6el_unknown_linux_gnuabi64),
1915 ("mipsel-unknown-linux-gnu", mipsel_unknown_linux_gnu),
1916 ("powerpc-unknown-linux-gnu", powerpc_unknown_linux_gnu),
1917 ("powerpc-unknown-linux-gnuspe", powerpc_unknown_linux_gnuspe),
1918 ("powerpc-unknown-linux-musl", powerpc_unknown_linux_musl),
1919 ("powerpc-unknown-linux-muslspe", powerpc_unknown_linux_muslspe),
1920 ("powerpc64-ibm-aix", powerpc64_ibm_aix),
1921 ("powerpc64-unknown-linux-gnu", powerpc64_unknown_linux_gnu),
1922 ("powerpc64-unknown-linux-musl", powerpc64_unknown_linux_musl),
1923 ("powerpc64le-unknown-linux-gnu", powerpc64le_unknown_linux_gnu),
1924 ("powerpc64le-unknown-linux-musl", powerpc64le_unknown_linux_musl),
1925 ("s390x-unknown-linux-gnu", s390x_unknown_linux_gnu),
1926 ("s390x-unknown-linux-musl", s390x_unknown_linux_musl),
1927 ("sparc-unknown-linux-gnu", sparc_unknown_linux_gnu),
1928 ("sparc64-unknown-linux-gnu", sparc64_unknown_linux_gnu),
1929 ("arm-unknown-linux-gnueabi", arm_unknown_linux_gnueabi),
1930 ("arm-unknown-linux-gnueabihf", arm_unknown_linux_gnueabihf),
1931 ("armeb-unknown-linux-gnueabi", armeb_unknown_linux_gnueabi),
1932 ("arm-unknown-linux-musleabi", arm_unknown_linux_musleabi),
1933 ("arm-unknown-linux-musleabihf", arm_unknown_linux_musleabihf),
1934 ("armv4t-unknown-linux-gnueabi", armv4t_unknown_linux_gnueabi),
1935 ("armv5te-unknown-linux-gnueabi", armv5te_unknown_linux_gnueabi),
1936 ("armv5te-unknown-linux-musleabi", armv5te_unknown_linux_musleabi),
1937 ("armv5te-unknown-linux-uclibceabi", armv5te_unknown_linux_uclibceabi),
1938 ("armv7-unknown-linux-gnueabi", armv7_unknown_linux_gnueabi),
1939 ("armv7-unknown-linux-gnueabihf", armv7_unknown_linux_gnueabihf),
1940 ("thumbv7neon-unknown-linux-gnueabihf", thumbv7neon_unknown_linux_gnueabihf),
1941 ("thumbv7neon-unknown-linux-musleabihf", thumbv7neon_unknown_linux_musleabihf),
1942 ("armv7-unknown-linux-musleabi", armv7_unknown_linux_musleabi),
1943 ("armv7-unknown-linux-musleabihf", armv7_unknown_linux_musleabihf),
1944 ("aarch64-unknown-linux-gnu", aarch64_unknown_linux_gnu),
1945 ("aarch64-unknown-linux-musl", aarch64_unknown_linux_musl),
1946 ("x86_64-unknown-linux-musl", x86_64_unknown_linux_musl),
1947 ("i686-unknown-linux-musl", i686_unknown_linux_musl),
1948 ("i586-unknown-linux-musl", i586_unknown_linux_musl),
1949 ("mips-unknown-linux-musl", mips_unknown_linux_musl),
1950 ("mipsel-unknown-linux-musl", mipsel_unknown_linux_musl),
1951 ("mips64-unknown-linux-muslabi64", mips64_unknown_linux_muslabi64),
1952 ("mips64el-unknown-linux-muslabi64", mips64el_unknown_linux_muslabi64),
1953 ("hexagon-unknown-linux-musl", hexagon_unknown_linux_musl),
1954 ("hexagon-unknown-none-elf", hexagon_unknown_none_elf),
1955
1956 ("mips-unknown-linux-uclibc", mips_unknown_linux_uclibc),
1957 ("mipsel-unknown-linux-uclibc", mipsel_unknown_linux_uclibc),
1958
1959 ("i686-linux-android", i686_linux_android),
1960 ("x86_64-linux-android", x86_64_linux_android),
1961 ("arm-linux-androideabi", arm_linux_androideabi),
1962 ("armv7-linux-androideabi", armv7_linux_androideabi),
1963 ("thumbv7neon-linux-androideabi", thumbv7neon_linux_androideabi),
1964 ("aarch64-linux-android", aarch64_linux_android),
1965 ("riscv64-linux-android", riscv64_linux_android),
1966
1967 ("aarch64-unknown-freebsd", aarch64_unknown_freebsd),
1968 ("armv6-unknown-freebsd", armv6_unknown_freebsd),
1969 ("armv7-unknown-freebsd", armv7_unknown_freebsd),
1970 ("i686-unknown-freebsd", i686_unknown_freebsd),
1971 ("powerpc-unknown-freebsd", powerpc_unknown_freebsd),
1972 ("powerpc64-unknown-freebsd", powerpc64_unknown_freebsd),
1973 ("powerpc64le-unknown-freebsd", powerpc64le_unknown_freebsd),
1974 ("riscv64gc-unknown-freebsd", riscv64gc_unknown_freebsd),
1975 ("x86_64-unknown-freebsd", x86_64_unknown_freebsd),
1976
1977 ("x86_64-unknown-dragonfly", x86_64_unknown_dragonfly),
1978
1979 ("aarch64-unknown-openbsd", aarch64_unknown_openbsd),
1980 ("i686-unknown-openbsd", i686_unknown_openbsd),
1981 ("powerpc-unknown-openbsd", powerpc_unknown_openbsd),
1982 ("powerpc64-unknown-openbsd", powerpc64_unknown_openbsd),
1983 ("riscv64gc-unknown-openbsd", riscv64gc_unknown_openbsd),
1984 ("sparc64-unknown-openbsd", sparc64_unknown_openbsd),
1985 ("x86_64-unknown-openbsd", x86_64_unknown_openbsd),
1986
1987 ("aarch64-unknown-netbsd", aarch64_unknown_netbsd),
1988 ("aarch64_be-unknown-netbsd", aarch64_be_unknown_netbsd),
1989 ("armv6-unknown-netbsd-eabihf", armv6_unknown_netbsd_eabihf),
1990 ("armv7-unknown-netbsd-eabihf", armv7_unknown_netbsd_eabihf),
1991 ("i586-unknown-netbsd", i586_unknown_netbsd),
1992 ("i686-unknown-netbsd", i686_unknown_netbsd),
1993 ("mipsel-unknown-netbsd", mipsel_unknown_netbsd),
1994 ("powerpc-unknown-netbsd", powerpc_unknown_netbsd),
1995 ("riscv64gc-unknown-netbsd", riscv64gc_unknown_netbsd),
1996 ("sparc64-unknown-netbsd", sparc64_unknown_netbsd),
1997 ("x86_64-unknown-netbsd", x86_64_unknown_netbsd),
1998
1999 ("i686-unknown-haiku", i686_unknown_haiku),
2000 ("x86_64-unknown-haiku", x86_64_unknown_haiku),
2001
2002 ("i686-unknown-hurd-gnu", i686_unknown_hurd_gnu),
2003 ("x86_64-unknown-hurd-gnu", x86_64_unknown_hurd_gnu),
2004
2005 ("aarch64-apple-darwin", aarch64_apple_darwin),
2006 ("arm64e-apple-darwin", arm64e_apple_darwin),
2007 ("x86_64-apple-darwin", x86_64_apple_darwin),
2008 ("x86_64h-apple-darwin", x86_64h_apple_darwin),
2009 ("i686-apple-darwin", i686_apple_darwin),
2010
2011 ("aarch64-unknown-fuchsia", aarch64_unknown_fuchsia),
2012 ("riscv64gc-unknown-fuchsia", riscv64gc_unknown_fuchsia),
2013 ("x86_64-unknown-fuchsia", x86_64_unknown_fuchsia),
2014
2015 ("avr-none", avr_none),
2016
2017 ("x86_64-unknown-l4re-uclibc", x86_64_unknown_l4re_uclibc),
2018
2019 ("aarch64-unknown-redox", aarch64_unknown_redox),
2020 ("i586-unknown-redox", i586_unknown_redox),
2021 ("x86_64-unknown-redox", x86_64_unknown_redox),
2022
2023 ("i386-apple-ios", i386_apple_ios),
2024 ("x86_64-apple-ios", x86_64_apple_ios),
2025 ("aarch64-apple-ios", aarch64_apple_ios),
2026 ("arm64e-apple-ios", arm64e_apple_ios),
2027 ("armv7s-apple-ios", armv7s_apple_ios),
2028 ("x86_64-apple-ios-macabi", x86_64_apple_ios_macabi),
2029 ("aarch64-apple-ios-macabi", aarch64_apple_ios_macabi),
2030 ("aarch64-apple-ios-sim", aarch64_apple_ios_sim),
2031
2032 ("aarch64-apple-tvos", aarch64_apple_tvos),
2033 ("aarch64-apple-tvos-sim", aarch64_apple_tvos_sim),
2034 ("arm64e-apple-tvos", arm64e_apple_tvos),
2035 ("x86_64-apple-tvos", x86_64_apple_tvos),
2036
2037 ("armv7k-apple-watchos", armv7k_apple_watchos),
2038 ("arm64_32-apple-watchos", arm64_32_apple_watchos),
2039 ("x86_64-apple-watchos-sim", x86_64_apple_watchos_sim),
2040 ("aarch64-apple-watchos", aarch64_apple_watchos),
2041 ("aarch64-apple-watchos-sim", aarch64_apple_watchos_sim),
2042
2043 ("aarch64-apple-visionos", aarch64_apple_visionos),
2044 ("aarch64-apple-visionos-sim", aarch64_apple_visionos_sim),
2045
2046 ("armebv7r-none-eabi", armebv7r_none_eabi),
2047 ("armebv7r-none-eabihf", armebv7r_none_eabihf),
2048 ("armv7r-none-eabi", armv7r_none_eabi),
2049 ("armv7r-none-eabihf", armv7r_none_eabihf),
2050 ("armv8r-none-eabihf", armv8r_none_eabihf),
2051
2052 ("armv7-rtems-eabihf", armv7_rtems_eabihf),
2053
2054 ("x86_64-pc-solaris", x86_64_pc_solaris),
2055 ("sparcv9-sun-solaris", sparcv9_sun_solaris),
2056
2057 ("x86_64-unknown-illumos", x86_64_unknown_illumos),
2058 ("aarch64-unknown-illumos", aarch64_unknown_illumos),
2059
2060 ("x86_64-pc-windows-gnu", x86_64_pc_windows_gnu),
2061 ("x86_64-uwp-windows-gnu", x86_64_uwp_windows_gnu),
2062 ("x86_64-win7-windows-gnu", x86_64_win7_windows_gnu),
2063 ("i686-pc-windows-gnu", i686_pc_windows_gnu),
2064 ("i686-uwp-windows-gnu", i686_uwp_windows_gnu),
2065 ("i686-win7-windows-gnu", i686_win7_windows_gnu),
2066
2067 ("aarch64-pc-windows-gnullvm", aarch64_pc_windows_gnullvm),
2068 ("i686-pc-windows-gnullvm", i686_pc_windows_gnullvm),
2069 ("x86_64-pc-windows-gnullvm", x86_64_pc_windows_gnullvm),
2070
2071 ("aarch64-pc-windows-msvc", aarch64_pc_windows_msvc),
2072 ("aarch64-uwp-windows-msvc", aarch64_uwp_windows_msvc),
2073 ("arm64ec-pc-windows-msvc", arm64ec_pc_windows_msvc),
2074 ("x86_64-pc-windows-msvc", x86_64_pc_windows_msvc),
2075 ("x86_64-uwp-windows-msvc", x86_64_uwp_windows_msvc),
2076 ("x86_64-win7-windows-msvc", x86_64_win7_windows_msvc),
2077 ("i686-pc-windows-msvc", i686_pc_windows_msvc),
2078 ("i686-uwp-windows-msvc", i686_uwp_windows_msvc),
2079 ("i686-win7-windows-msvc", i686_win7_windows_msvc),
2080 ("thumbv7a-pc-windows-msvc", thumbv7a_pc_windows_msvc),
2081 ("thumbv7a-uwp-windows-msvc", thumbv7a_uwp_windows_msvc),
2082
2083 ("wasm32-unknown-emscripten", wasm32_unknown_emscripten),
2084 ("wasm32-unknown-unknown", wasm32_unknown_unknown),
2085 ("wasm32v1-none", wasm32v1_none),
2086 ("wasm32-wasip1", wasm32_wasip1),
2087 ("wasm32-wasip2", wasm32_wasip2),
2088 ("wasm32-wasip1-threads", wasm32_wasip1_threads),
2089 ("wasm32-wali-linux-musl", wasm32_wali_linux_musl),
2090 ("wasm64-unknown-unknown", wasm64_unknown_unknown),
2091
2092 ("thumbv6m-none-eabi", thumbv6m_none_eabi),
2093 ("thumbv7m-none-eabi", thumbv7m_none_eabi),
2094 ("thumbv7em-none-eabi", thumbv7em_none_eabi),
2095 ("thumbv7em-none-eabihf", thumbv7em_none_eabihf),
2096 ("thumbv8m.base-none-eabi", thumbv8m_base_none_eabi),
2097 ("thumbv8m.main-none-eabi", thumbv8m_main_none_eabi),
2098 ("thumbv8m.main-none-eabihf", thumbv8m_main_none_eabihf),
2099
2100 ("armv7a-none-eabi", armv7a_none_eabi),
2101 ("armv7a-none-eabihf", armv7a_none_eabihf),
2102 ("armv7a-nuttx-eabi", armv7a_nuttx_eabi),
2103 ("armv7a-nuttx-eabihf", armv7a_nuttx_eabihf),
2104 ("armv7a-vex-v5", armv7a_vex_v5),
2105
2106 ("msp430-none-elf", msp430_none_elf),
2107
2108 ("aarch64-unknown-hermit", aarch64_unknown_hermit),
2109 ("riscv64gc-unknown-hermit", riscv64gc_unknown_hermit),
2110 ("x86_64-unknown-hermit", x86_64_unknown_hermit),
2111
2112 ("x86_64-unikraft-linux-musl", x86_64_unikraft_linux_musl),
2113
2114 ("armv7-unknown-trusty", armv7_unknown_trusty),
2115 ("aarch64-unknown-trusty", aarch64_unknown_trusty),
2116 ("x86_64-unknown-trusty", x86_64_unknown_trusty),
2117
2118 ("riscv32i-unknown-none-elf", riscv32i_unknown_none_elf),
2119 ("riscv32im-risc0-zkvm-elf", riscv32im_risc0_zkvm_elf),
2120 ("riscv32im-unknown-none-elf", riscv32im_unknown_none_elf),
2121 ("riscv32ima-unknown-none-elf", riscv32ima_unknown_none_elf),
2122 ("riscv32imc-unknown-none-elf", riscv32imc_unknown_none_elf),
2123 ("riscv32imc-esp-espidf", riscv32imc_esp_espidf),
2124 ("riscv32imac-esp-espidf", riscv32imac_esp_espidf),
2125 ("riscv32imafc-esp-espidf", riscv32imafc_esp_espidf),
2126
2127 ("riscv32e-unknown-none-elf", riscv32e_unknown_none_elf),
2128 ("riscv32em-unknown-none-elf", riscv32em_unknown_none_elf),
2129 ("riscv32emc-unknown-none-elf", riscv32emc_unknown_none_elf),
2130
2131 ("riscv32imac-unknown-none-elf", riscv32imac_unknown_none_elf),
2132 ("riscv32imafc-unknown-none-elf", riscv32imafc_unknown_none_elf),
2133 ("riscv32imac-unknown-xous-elf", riscv32imac_unknown_xous_elf),
2134 ("riscv32gc-unknown-linux-gnu", riscv32gc_unknown_linux_gnu),
2135 ("riscv32gc-unknown-linux-musl", riscv32gc_unknown_linux_musl),
2136 ("riscv64imac-unknown-none-elf", riscv64imac_unknown_none_elf),
2137 ("riscv64gc-unknown-none-elf", riscv64gc_unknown_none_elf),
2138 ("riscv64gc-unknown-linux-gnu", riscv64gc_unknown_linux_gnu),
2139 ("riscv64gc-unknown-linux-musl", riscv64gc_unknown_linux_musl),
2140
2141 ("sparc-unknown-none-elf", sparc_unknown_none_elf),
2142
2143 ("loongarch32-unknown-none", loongarch32_unknown_none),
2144 ("loongarch32-unknown-none-softfloat", loongarch32_unknown_none_softfloat),
2145 ("loongarch64-unknown-none", loongarch64_unknown_none),
2146 ("loongarch64-unknown-none-softfloat", loongarch64_unknown_none_softfloat),
2147
2148 ("aarch64-unknown-none", aarch64_unknown_none),
2149 ("aarch64-unknown-none-softfloat", aarch64_unknown_none_softfloat),
2150 ("aarch64_be-unknown-none-softfloat", aarch64_be_unknown_none_softfloat),
2151 ("aarch64-unknown-nuttx", aarch64_unknown_nuttx),
2152
2153 ("x86_64-fortanix-unknown-sgx", x86_64_fortanix_unknown_sgx),
2154
2155 ("x86_64-unknown-uefi", x86_64_unknown_uefi),
2156 ("i686-unknown-uefi", i686_unknown_uefi),
2157 ("aarch64-unknown-uefi", aarch64_unknown_uefi),
2158
2159 ("nvptx64-nvidia-cuda", nvptx64_nvidia_cuda),
2160
2161 ("amdgcn-amd-amdhsa", amdgcn_amd_amdhsa),
2162
2163 ("xtensa-esp32-none-elf", xtensa_esp32_none_elf),
2164 ("xtensa-esp32-espidf", xtensa_esp32_espidf),
2165 ("xtensa-esp32s2-none-elf", xtensa_esp32s2_none_elf),
2166 ("xtensa-esp32s2-espidf", xtensa_esp32s2_espidf),
2167 ("xtensa-esp32s3-none-elf", xtensa_esp32s3_none_elf),
2168 ("xtensa-esp32s3-espidf", xtensa_esp32s3_espidf),
2169
2170 ("i686-wrs-vxworks", i686_wrs_vxworks),
2171 ("x86_64-wrs-vxworks", x86_64_wrs_vxworks),
2172 ("armv7-wrs-vxworks-eabihf", armv7_wrs_vxworks_eabihf),
2173 ("aarch64-wrs-vxworks", aarch64_wrs_vxworks),
2174 ("powerpc-wrs-vxworks", powerpc_wrs_vxworks),
2175 ("powerpc-wrs-vxworks-spe", powerpc_wrs_vxworks_spe),
2176 ("powerpc64-wrs-vxworks", powerpc64_wrs_vxworks),
2177 ("riscv32-wrs-vxworks", riscv32_wrs_vxworks),
2178 ("riscv64-wrs-vxworks", riscv64_wrs_vxworks),
2179
2180 ("aarch64-kmc-solid_asp3", aarch64_kmc_solid_asp3),
2181 ("armv7a-kmc-solid_asp3-eabi", armv7a_kmc_solid_asp3_eabi),
2182 ("armv7a-kmc-solid_asp3-eabihf", armv7a_kmc_solid_asp3_eabihf),
2183
2184 ("mipsel-sony-psp", mipsel_sony_psp),
2185 ("mipsel-sony-psx", mipsel_sony_psx),
2186 ("mipsel-unknown-none", mipsel_unknown_none),
2187 ("mips-mti-none-elf", mips_mti_none_elf),
2188 ("mipsel-mti-none-elf", mipsel_mti_none_elf),
2189 ("thumbv4t-none-eabi", thumbv4t_none_eabi),
2190 ("armv4t-none-eabi", armv4t_none_eabi),
2191 ("thumbv5te-none-eabi", thumbv5te_none_eabi),
2192 ("armv5te-none-eabi", armv5te_none_eabi),
2193
2194 ("aarch64_be-unknown-linux-gnu", aarch64_be_unknown_linux_gnu),
2195 ("aarch64-unknown-linux-gnu_ilp32", aarch64_unknown_linux_gnu_ilp32),
2196 ("aarch64_be-unknown-linux-gnu_ilp32", aarch64_be_unknown_linux_gnu_ilp32),
2197
2198 ("bpfeb-unknown-none", bpfeb_unknown_none),
2199 ("bpfel-unknown-none", bpfel_unknown_none),
2200
2201 ("armv6k-nintendo-3ds", armv6k_nintendo_3ds),
2202
2203 ("aarch64-nintendo-switch-freestanding", aarch64_nintendo_switch_freestanding),
2204
2205 ("armv7-sony-vita-newlibeabihf", armv7_sony_vita_newlibeabihf),
2206
2207 ("armv7-unknown-linux-uclibceabi", armv7_unknown_linux_uclibceabi),
2208 ("armv7-unknown-linux-uclibceabihf", armv7_unknown_linux_uclibceabihf),
2209
2210 ("x86_64-unknown-none", x86_64_unknown_none),
2211
2212 ("aarch64-unknown-teeos", aarch64_unknown_teeos),
2213
2214 ("mips64-openwrt-linux-musl", mips64_openwrt_linux_musl),
2215
2216 ("aarch64-unknown-nto-qnx700", aarch64_unknown_nto_qnx700),
2217 ("aarch64-unknown-nto-qnx710", aarch64_unknown_nto_qnx710),
2218 ("aarch64-unknown-nto-qnx710_iosock", aarch64_unknown_nto_qnx710_iosock),
2219 ("aarch64-unknown-nto-qnx800", aarch64_unknown_nto_qnx800),
2220 ("x86_64-pc-nto-qnx710", x86_64_pc_nto_qnx710),
2221 ("x86_64-pc-nto-qnx710_iosock", x86_64_pc_nto_qnx710_iosock),
2222 ("x86_64-pc-nto-qnx800", x86_64_pc_nto_qnx800),
2223 ("i686-pc-nto-qnx700", i686_pc_nto_qnx700),
2224
2225 ("aarch64-unknown-linux-ohos", aarch64_unknown_linux_ohos),
2226 ("armv7-unknown-linux-ohos", armv7_unknown_linux_ohos),
2227 ("loongarch64-unknown-linux-ohos", loongarch64_unknown_linux_ohos),
2228 ("x86_64-unknown-linux-ohos", x86_64_unknown_linux_ohos),
2229
2230 ("x86_64-unknown-linux-none", x86_64_unknown_linux_none),
2231
2232 ("thumbv6m-nuttx-eabi", thumbv6m_nuttx_eabi),
2233 ("thumbv7a-nuttx-eabi", thumbv7a_nuttx_eabi),
2234 ("thumbv7a-nuttx-eabihf", thumbv7a_nuttx_eabihf),
2235 ("thumbv7m-nuttx-eabi", thumbv7m_nuttx_eabi),
2236 ("thumbv7em-nuttx-eabi", thumbv7em_nuttx_eabi),
2237 ("thumbv7em-nuttx-eabihf", thumbv7em_nuttx_eabihf),
2238 ("thumbv8m.base-nuttx-eabi", thumbv8m_base_nuttx_eabi),
2239 ("thumbv8m.main-nuttx-eabi", thumbv8m_main_nuttx_eabi),
2240 ("thumbv8m.main-nuttx-eabihf", thumbv8m_main_nuttx_eabihf),
2241 ("riscv32imc-unknown-nuttx-elf", riscv32imc_unknown_nuttx_elf),
2242 ("riscv32imac-unknown-nuttx-elf", riscv32imac_unknown_nuttx_elf),
2243 ("riscv32imafc-unknown-nuttx-elf", riscv32imafc_unknown_nuttx_elf),
2244 ("riscv64imac-unknown-nuttx-elf", riscv64imac_unknown_nuttx_elf),
2245 ("riscv64gc-unknown-nuttx-elf", riscv64gc_unknown_nuttx_elf),
2246 ("x86_64-lynx-lynxos178", x86_64_lynx_lynxos178),
2247
2248 ("x86_64-pc-cygwin", x86_64_pc_cygwin),
2249}
2250
2251macro_rules! cvs {
2253 () => {
2254 ::std::borrow::Cow::Borrowed(&[])
2255 };
2256 ($($x:expr),+ $(,)?) => {
2257 ::std::borrow::Cow::Borrowed(&[
2258 $(
2259 ::std::borrow::Cow::Borrowed($x),
2260 )*
2261 ])
2262 };
2263}
2264
2265pub(crate) use cvs;
2266
2267#[derive(Debug, PartialEq)]
2271pub struct TargetWarnings {
2272 unused_fields: Vec<String>,
2273}
2274
2275impl TargetWarnings {
2276 pub fn empty() -> Self {
2277 Self { unused_fields: Vec::new() }
2278 }
2279
2280 pub fn warning_messages(&self) -> Vec<String> {
2281 let mut warnings = vec![];
2282 if !self.unused_fields.is_empty() {
2283 warnings.push(format!(
2284 "target json file contains unused fields: {}",
2285 self.unused_fields.join(", ")
2286 ));
2287 }
2288 warnings
2289 }
2290}
2291
2292#[derive(Copy, Clone, Debug, PartialEq)]
2295enum TargetKind {
2296 Json,
2297 Builtin,
2298}
2299
2300#[derive(PartialEq, Clone, Debug)]
2304pub struct Target {
2305 pub llvm_target: StaticCow<str>,
2312 pub metadata: TargetMetadata,
2315 pub pointer_width: u32,
2317 pub arch: StaticCow<str>,
2320 pub data_layout: StaticCow<str>,
2322 pub options: TargetOptions,
2324}
2325
2326#[derive(Default, PartialEq, Clone, Debug)]
2330pub struct TargetMetadata {
2331 pub description: Option<StaticCow<str>>,
2334 pub tier: Option<u64>,
2336 pub host_tools: Option<bool>,
2338 pub std: Option<bool>,
2341}
2342
2343impl Target {
2344 pub fn parse_data_layout(&self) -> Result<TargetDataLayout, TargetDataLayoutErrors<'_>> {
2345 let mut dl = TargetDataLayout::parse_from_llvm_datalayout_string(
2346 &self.data_layout,
2347 self.options.default_address_space,
2348 )?;
2349
2350 if dl.endian != self.endian {
2352 return Err(TargetDataLayoutErrors::InconsistentTargetArchitecture {
2353 dl: dl.endian.as_str(),
2354 target: self.endian.as_str(),
2355 });
2356 }
2357
2358 let target_pointer_width: u64 = self.pointer_width.into();
2359 let dl_pointer_size: u64 = dl.pointer_size().bits();
2360 if dl_pointer_size != target_pointer_width {
2361 return Err(TargetDataLayoutErrors::InconsistentTargetPointerWidth {
2362 pointer_size: dl_pointer_size,
2363 target: self.pointer_width,
2364 });
2365 }
2366
2367 dl.c_enum_min_size = Integer::from_size(Size::from_bits(
2368 self.c_enum_min_bits.unwrap_or(self.c_int_width as _),
2369 ))
2370 .map_err(|err| TargetDataLayoutErrors::InvalidBitsSize { err })?;
2371
2372 Ok(dl)
2373 }
2374}
2375
2376pub trait HasTargetSpec {
2377 fn target_spec(&self) -> &Target;
2378}
2379
2380impl HasTargetSpec for Target {
2381 #[inline]
2382 fn target_spec(&self) -> &Target {
2383 self
2384 }
2385}
2386
2387#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
2389pub struct X86Abi {
2390 pub regparm: Option<u32>,
2393 pub reg_struct_return: bool,
2395}
2396
2397pub trait HasX86AbiOpt {
2398 fn x86_abi_opt(&self) -> X86Abi;
2399}
2400
2401type StaticCow<T> = Cow<'static, T>;
2402
2403#[derive(PartialEq, Clone, Debug)]
2412pub struct TargetOptions {
2413 pub endian: Endian,
2415 pub c_int_width: u16,
2417 pub os: StaticCow<str>,
2422 pub env: StaticCow<str>,
2424 pub abi: StaticCow<str>,
2429 pub vendor: StaticCow<str>,
2431
2432 pub linker: Option<StaticCow<str>>,
2434 pub linker_flavor: LinkerFlavor,
2437 linker_flavor_json: LinkerFlavorCli,
2438 lld_flavor_json: LldFlavor,
2439 linker_is_gnu_json: bool,
2440
2441 pub pre_link_objects: CrtObjects,
2443 pub post_link_objects: CrtObjects,
2444 pub pre_link_objects_self_contained: CrtObjects,
2446 pub post_link_objects_self_contained: CrtObjects,
2447 pub link_self_contained: LinkSelfContainedDefault,
2450
2451 pub pre_link_args: LinkArgs,
2453 pre_link_args_json: LinkArgsCli,
2454 pub late_link_args: LinkArgs,
2458 late_link_args_json: LinkArgsCli,
2459 pub late_link_args_dynamic: LinkArgs,
2462 late_link_args_dynamic_json: LinkArgsCli,
2463 pub late_link_args_static: LinkArgs,
2466 late_link_args_static_json: LinkArgsCli,
2467 pub post_link_args: LinkArgs,
2470 post_link_args_json: LinkArgsCli,
2471
2472 pub link_script: Option<StaticCow<str>>,
2476 pub link_env: StaticCow<[(StaticCow<str>, StaticCow<str>)]>,
2478 pub link_env_remove: StaticCow<[StaticCow<str>]>,
2480
2481 pub asm_args: StaticCow<[StaticCow<str>]>,
2483
2484 pub cpu: StaticCow<str>,
2487 pub need_explicit_cpu: bool,
2490 pub features: StaticCow<str>,
2499 pub direct_access_external_data: Option<bool>,
2501 pub dynamic_linking: bool,
2503 pub dll_tls_export: bool,
2505 pub only_cdylib: bool,
2507 pub executables: bool,
2509 pub relocation_model: RelocModel,
2512 pub code_model: Option<CodeModel>,
2515 pub tls_model: TlsModel,
2518 pub disable_redzone: bool,
2520 pub frame_pointer: FramePointer,
2522 pub function_sections: bool,
2524 pub dll_prefix: StaticCow<str>,
2526 pub dll_suffix: StaticCow<str>,
2528 pub exe_suffix: StaticCow<str>,
2530 pub staticlib_prefix: StaticCow<str>,
2532 pub staticlib_suffix: StaticCow<str>,
2534 pub families: StaticCow<[StaticCow<str>]>,
2540 pub abi_return_struct_as_int: bool,
2542 pub is_like_aix: bool,
2545 pub is_like_darwin: bool,
2550 pub is_like_solaris: bool,
2554 pub is_like_windows: bool,
2562 pub is_like_msvc: bool,
2572 pub is_like_wasm: bool,
2574 pub is_like_android: bool,
2576 pub is_like_vexos: bool,
2578 pub binary_format: BinaryFormat,
2580 pub default_dwarf_version: u32,
2583 pub allows_weak_linkage: bool,
2590 pub has_rpath: bool,
2592 pub no_default_libraries: bool,
2595 pub position_independent_executables: bool,
2601 pub static_position_independent_executables: bool,
2603 pub plt_by_default: bool,
2606 pub relro_level: RelroLevel,
2610 pub archive_format: StaticCow<str>,
2615 pub allow_asm: bool,
2617 pub main_needs_argc_argv: bool,
2620
2621 pub has_thread_local: bool,
2623 pub obj_is_bitcode: bool,
2627 pub bitcode_llvm_cmdline: StaticCow<str>,
2629
2630 pub min_atomic_width: Option<u64>,
2632
2633 pub max_atomic_width: Option<u64>,
2635
2636 pub atomic_cas: bool,
2638
2639 pub panic_strategy: PanicStrategy,
2641
2642 pub crt_static_allows_dylibs: bool,
2644 pub crt_static_default: bool,
2646 pub crt_static_respected: bool,
2648
2649 pub stack_probes: StackProbeType,
2651
2652 pub min_global_align: Option<Align>,
2654
2655 pub default_codegen_units: Option<u64>,
2657
2658 pub default_codegen_backend: Option<StaticCow<str>>,
2668
2669 pub trap_unreachable: bool,
2672
2673 pub requires_lto: bool,
2676
2677 pub singlethread: bool,
2679
2680 pub no_builtins: bool,
2683
2684 pub default_visibility: Option<SymbolVisibility>,
2690
2691 pub emit_debug_gdb_scripts: bool,
2693
2694 pub requires_uwtable: bool,
2698
2699 pub default_uwtable: bool,
2702
2703 pub simd_types_indirect: bool,
2708
2709 pub limit_rdylib_exports: bool,
2711
2712 pub override_export_symbols: Option<StaticCow<[StaticCow<str>]>>,
2715
2716 pub merge_functions: MergeFunctions,
2723
2724 pub mcount: StaticCow<str>,
2726
2727 pub llvm_mcount_intrinsic: Option<StaticCow<str>>,
2729
2730 pub llvm_abiname: StaticCow<str>,
2733
2734 pub llvm_floatabi: Option<FloatAbi>,
2741
2742 pub rustc_abi: Option<RustcAbi>,
2747
2748 pub relax_elf_relocations: bool,
2750
2751 pub llvm_args: StaticCow<[StaticCow<str>]>,
2753
2754 pub use_ctors_section: bool,
2757
2758 pub eh_frame_header: bool,
2762
2763 pub has_thumb_interworking: bool,
2766
2767 pub debuginfo_kind: DebuginfoKind,
2769 pub split_debuginfo: SplitDebuginfo,
2772 pub supported_split_debuginfo: StaticCow<[SplitDebuginfo]>,
2774
2775 pub supported_sanitizers: SanitizerSet,
2781
2782 pub c_enum_min_bits: Option<u64>,
2784
2785 pub generate_arange_section: bool,
2787
2788 pub supports_stack_protector: bool,
2791
2792 pub entry_name: StaticCow<str>,
2795
2796 pub entry_abi: CanonAbi,
2799
2800 pub supports_xray: bool,
2802
2803 pub default_address_space: rustc_abi::AddressSpace,
2807
2808 small_data_threshold_support: SmallDataThresholdSupport,
2810}
2811
2812fn add_link_args_iter(
2815 link_args: &mut LinkArgs,
2816 flavor: LinkerFlavor,
2817 args: impl Iterator<Item = StaticCow<str>> + Clone,
2818) {
2819 let mut insert = |flavor| link_args.entry(flavor).or_default().extend(args.clone());
2820 insert(flavor);
2821 match flavor {
2822 LinkerFlavor::Gnu(cc, lld) => {
2823 assert_eq!(lld, Lld::No);
2824 insert(LinkerFlavor::Gnu(cc, Lld::Yes));
2825 }
2826 LinkerFlavor::Darwin(cc, lld) => {
2827 assert_eq!(lld, Lld::No);
2828 insert(LinkerFlavor::Darwin(cc, Lld::Yes));
2829 }
2830 LinkerFlavor::Msvc(lld) => {
2831 assert_eq!(lld, Lld::No);
2832 insert(LinkerFlavor::Msvc(Lld::Yes));
2833 }
2834 LinkerFlavor::WasmLld(..)
2835 | LinkerFlavor::Unix(..)
2836 | LinkerFlavor::EmCc
2837 | LinkerFlavor::Bpf
2838 | LinkerFlavor::Llbc
2839 | LinkerFlavor::Ptx => {}
2840 }
2841}
2842
2843fn add_link_args(link_args: &mut LinkArgs, flavor: LinkerFlavor, args: &[&'static str]) {
2844 add_link_args_iter(link_args, flavor, args.iter().copied().map(Cow::Borrowed))
2845}
2846
2847impl TargetOptions {
2848 pub fn supports_comdat(&self) -> bool {
2849 !self.is_like_aix && !self.is_like_darwin
2851 }
2852}
2853
2854impl TargetOptions {
2855 fn link_args(flavor: LinkerFlavor, args: &[&'static str]) -> LinkArgs {
2856 let mut link_args = LinkArgs::new();
2857 add_link_args(&mut link_args, flavor, args);
2858 link_args
2859 }
2860
2861 fn add_pre_link_args(&mut self, flavor: LinkerFlavor, args: &[&'static str]) {
2862 add_link_args(&mut self.pre_link_args, flavor, args);
2863 }
2864
2865 fn update_from_cli(&mut self) {
2866 self.linker_flavor = LinkerFlavor::from_cli_json(
2867 self.linker_flavor_json,
2868 self.lld_flavor_json,
2869 self.linker_is_gnu_json,
2870 );
2871 for (args, args_json) in [
2872 (&mut self.pre_link_args, &self.pre_link_args_json),
2873 (&mut self.late_link_args, &self.late_link_args_json),
2874 (&mut self.late_link_args_dynamic, &self.late_link_args_dynamic_json),
2875 (&mut self.late_link_args_static, &self.late_link_args_static_json),
2876 (&mut self.post_link_args, &self.post_link_args_json),
2877 ] {
2878 args.clear();
2879 for (flavor, args_json) in args_json {
2880 let linker_flavor = self.linker_flavor.with_cli_hints(*flavor);
2881 let linker_flavor = match linker_flavor {
2883 LinkerFlavor::Gnu(cc, _) => LinkerFlavor::Gnu(cc, Lld::No),
2884 LinkerFlavor::Darwin(cc, _) => LinkerFlavor::Darwin(cc, Lld::No),
2885 LinkerFlavor::Msvc(_) => LinkerFlavor::Msvc(Lld::No),
2886 _ => linker_flavor,
2887 };
2888 if !args.contains_key(&linker_flavor) {
2889 add_link_args_iter(args, linker_flavor, args_json.iter().cloned());
2890 }
2891 }
2892 }
2893 }
2894
2895 fn update_to_cli(&mut self) {
2896 self.linker_flavor_json = self.linker_flavor.to_cli_counterpart();
2897 self.lld_flavor_json = self.linker_flavor.lld_flavor();
2898 self.linker_is_gnu_json = self.linker_flavor.is_gnu();
2899 for (args, args_json) in [
2900 (&self.pre_link_args, &mut self.pre_link_args_json),
2901 (&self.late_link_args, &mut self.late_link_args_json),
2902 (&self.late_link_args_dynamic, &mut self.late_link_args_dynamic_json),
2903 (&self.late_link_args_static, &mut self.late_link_args_static_json),
2904 (&self.post_link_args, &mut self.post_link_args_json),
2905 ] {
2906 *args_json = args
2907 .iter()
2908 .map(|(flavor, args)| (flavor.to_cli_counterpart(), args.clone()))
2909 .collect();
2910 }
2911 }
2912}
2913
2914impl Default for TargetOptions {
2915 fn default() -> TargetOptions {
2918 TargetOptions {
2919 endian: Endian::Little,
2920 c_int_width: 32,
2921 os: "none".into(),
2922 env: "".into(),
2923 abi: "".into(),
2924 vendor: "unknown".into(),
2925 linker: option_env!("CFG_DEFAULT_LINKER").map(|s| s.into()),
2926 linker_flavor: LinkerFlavor::Gnu(Cc::Yes, Lld::No),
2927 linker_flavor_json: LinkerFlavorCli::Gcc,
2928 lld_flavor_json: LldFlavor::Ld,
2929 linker_is_gnu_json: true,
2930 link_script: None,
2931 asm_args: cvs![],
2932 cpu: "generic".into(),
2933 need_explicit_cpu: false,
2934 features: "".into(),
2935 direct_access_external_data: None,
2936 dynamic_linking: false,
2937 dll_tls_export: true,
2938 only_cdylib: false,
2939 executables: true,
2940 relocation_model: RelocModel::Pic,
2941 code_model: None,
2942 tls_model: TlsModel::GeneralDynamic,
2943 disable_redzone: false,
2944 frame_pointer: FramePointer::MayOmit,
2945 function_sections: true,
2946 dll_prefix: "lib".into(),
2947 dll_suffix: ".so".into(),
2948 exe_suffix: "".into(),
2949 staticlib_prefix: "lib".into(),
2950 staticlib_suffix: ".a".into(),
2951 families: cvs![],
2952 abi_return_struct_as_int: false,
2953 is_like_aix: false,
2954 is_like_darwin: false,
2955 is_like_solaris: false,
2956 is_like_windows: false,
2957 is_like_msvc: false,
2958 is_like_wasm: false,
2959 is_like_android: false,
2960 is_like_vexos: false,
2961 binary_format: BinaryFormat::Elf,
2962 default_dwarf_version: 4,
2963 allows_weak_linkage: true,
2964 has_rpath: false,
2965 no_default_libraries: true,
2966 position_independent_executables: false,
2967 static_position_independent_executables: false,
2968 plt_by_default: true,
2969 relro_level: RelroLevel::None,
2970 pre_link_objects: Default::default(),
2971 post_link_objects: Default::default(),
2972 pre_link_objects_self_contained: Default::default(),
2973 post_link_objects_self_contained: Default::default(),
2974 link_self_contained: LinkSelfContainedDefault::False,
2975 pre_link_args: LinkArgs::new(),
2976 pre_link_args_json: LinkArgsCli::new(),
2977 late_link_args: LinkArgs::new(),
2978 late_link_args_json: LinkArgsCli::new(),
2979 late_link_args_dynamic: LinkArgs::new(),
2980 late_link_args_dynamic_json: LinkArgsCli::new(),
2981 late_link_args_static: LinkArgs::new(),
2982 late_link_args_static_json: LinkArgsCli::new(),
2983 post_link_args: LinkArgs::new(),
2984 post_link_args_json: LinkArgsCli::new(),
2985 link_env: cvs![],
2986 link_env_remove: cvs![],
2987 archive_format: "gnu".into(),
2988 main_needs_argc_argv: true,
2989 allow_asm: true,
2990 has_thread_local: false,
2991 obj_is_bitcode: false,
2992 bitcode_llvm_cmdline: "".into(),
2993 min_atomic_width: None,
2994 max_atomic_width: None,
2995 atomic_cas: true,
2996 panic_strategy: PanicStrategy::Unwind,
2997 crt_static_allows_dylibs: false,
2998 crt_static_default: false,
2999 crt_static_respected: false,
3000 stack_probes: StackProbeType::None,
3001 min_global_align: None,
3002 default_codegen_units: None,
3003 default_codegen_backend: None,
3004 trap_unreachable: true,
3005 requires_lto: false,
3006 singlethread: false,
3007 no_builtins: false,
3008 default_visibility: None,
3009 emit_debug_gdb_scripts: true,
3010 requires_uwtable: false,
3011 default_uwtable: false,
3012 simd_types_indirect: true,
3013 limit_rdylib_exports: true,
3014 override_export_symbols: None,
3015 merge_functions: MergeFunctions::Aliases,
3016 mcount: "mcount".into(),
3017 llvm_mcount_intrinsic: None,
3018 llvm_abiname: "".into(),
3019 llvm_floatabi: None,
3020 rustc_abi: None,
3021 relax_elf_relocations: false,
3022 llvm_args: cvs![],
3023 use_ctors_section: false,
3024 eh_frame_header: true,
3025 has_thumb_interworking: false,
3026 debuginfo_kind: Default::default(),
3027 split_debuginfo: Default::default(),
3028 supported_split_debuginfo: Cow::Borrowed(&[SplitDebuginfo::Off]),
3030 supported_sanitizers: SanitizerSet::empty(),
3031 c_enum_min_bits: None,
3032 generate_arange_section: true,
3033 supports_stack_protector: true,
3034 entry_name: "main".into(),
3035 entry_abi: CanonAbi::C,
3036 supports_xray: false,
3037 default_address_space: rustc_abi::AddressSpace::ZERO,
3038 small_data_threshold_support: SmallDataThresholdSupport::DefaultForArch,
3039 }
3040 }
3041}
3042
3043impl Deref for Target {
3047 type Target = TargetOptions;
3048
3049 #[inline]
3050 fn deref(&self) -> &Self::Target {
3051 &self.options
3052 }
3053}
3054impl DerefMut for Target {
3055 #[inline]
3056 fn deref_mut(&mut self) -> &mut Self::Target {
3057 &mut self.options
3058 }
3059}
3060
3061impl Target {
3062 pub fn is_abi_supported(&self, abi: ExternAbi) -> bool {
3063 let abi_map = AbiMap::from_target(self);
3064 abi_map.canonize_abi(abi, false).is_mapped()
3065 }
3066
3067 pub fn min_atomic_width(&self) -> u64 {
3070 self.min_atomic_width.unwrap_or(8)
3071 }
3072
3073 pub fn max_atomic_width(&self) -> u64 {
3076 self.max_atomic_width.unwrap_or_else(|| self.pointer_width.into())
3077 }
3078
3079 fn check_consistency(&self, kind: TargetKind) -> Result<(), String> {
3082 macro_rules! check {
3083 ($b:expr, $($msg:tt)*) => {
3084 if !$b {
3085 return Err(format!($($msg)*));
3086 }
3087 }
3088 }
3089 macro_rules! check_eq {
3090 ($left:expr, $right:expr, $($msg:tt)*) => {
3091 if ($left) != ($right) {
3092 return Err(format!($($msg)*));
3093 }
3094 }
3095 }
3096 macro_rules! check_ne {
3097 ($left:expr, $right:expr, $($msg:tt)*) => {
3098 if ($left) == ($right) {
3099 return Err(format!($($msg)*));
3100 }
3101 }
3102 }
3103 macro_rules! check_matches {
3104 ($left:expr, $right:pat, $($msg:tt)*) => {
3105 if !matches!($left, $right) {
3106 return Err(format!($($msg)*));
3107 }
3108 }
3109 }
3110
3111 check_eq!(
3112 self.is_like_darwin,
3113 self.vendor == "apple",
3114 "`is_like_darwin` must be set if and only if `vendor` is `apple`"
3115 );
3116 check_eq!(
3117 self.is_like_solaris,
3118 self.os == "solaris" || self.os == "illumos",
3119 "`is_like_solaris` must be set if and only if `os` is `solaris` or `illumos`"
3120 );
3121 check_eq!(
3122 self.is_like_windows,
3123 self.os == "windows" || self.os == "uefi" || self.os == "cygwin",
3124 "`is_like_windows` must be set if and only if `os` is `windows`, `uefi` or `cygwin`"
3125 );
3126 check_eq!(
3127 self.is_like_wasm,
3128 self.arch == "wasm32" || self.arch == "wasm64",
3129 "`is_like_wasm` must be set if and only if `arch` is `wasm32` or `wasm64`"
3130 );
3131 if self.is_like_msvc {
3132 check!(self.is_like_windows, "if `is_like_msvc` is set, `is_like_windows` must be set");
3133 }
3134 if self.os == "emscripten" {
3135 check!(self.is_like_wasm, "the `emcscripten` os only makes sense on wasm-like targets");
3136 }
3137
3138 check_eq!(
3140 self.is_like_darwin,
3141 matches!(self.linker_flavor, LinkerFlavor::Darwin(..)),
3142 "`linker_flavor` must be `darwin` if and only if `is_like_darwin` is set"
3143 );
3144 check_eq!(
3145 self.is_like_msvc,
3146 matches!(self.linker_flavor, LinkerFlavor::Msvc(..)),
3147 "`linker_flavor` must be `msvc` if and only if `is_like_msvc` is set"
3148 );
3149 check_eq!(
3150 self.is_like_wasm && self.os != "emscripten",
3151 matches!(self.linker_flavor, LinkerFlavor::WasmLld(..)),
3152 "`linker_flavor` must be `wasm-lld` if and only if `is_like_wasm` is set and the `os` is not `emscripten`",
3153 );
3154 check_eq!(
3155 self.os == "emscripten",
3156 matches!(self.linker_flavor, LinkerFlavor::EmCc),
3157 "`linker_flavor` must be `em-cc` if and only if `os` is `emscripten`"
3158 );
3159 check_eq!(
3160 self.arch == "bpf",
3161 matches!(self.linker_flavor, LinkerFlavor::Bpf),
3162 "`linker_flavor` must be `bpf` if and only if `arch` is `bpf`"
3163 );
3164 check_eq!(
3165 self.arch == "nvptx64",
3166 matches!(self.linker_flavor, LinkerFlavor::Ptx),
3167 "`linker_flavor` must be `ptc` if and only if `arch` is `nvptx64`"
3168 );
3169
3170 for args in [
3171 &self.pre_link_args,
3172 &self.late_link_args,
3173 &self.late_link_args_dynamic,
3174 &self.late_link_args_static,
3175 &self.post_link_args,
3176 ] {
3177 for (&flavor, flavor_args) in args {
3178 check!(
3179 !flavor_args.is_empty() || self.arch == "avr",
3180 "linker flavor args must not be empty"
3181 );
3182 match self.linker_flavor {
3184 LinkerFlavor::Gnu(..) => {
3185 check_matches!(
3186 flavor,
3187 LinkerFlavor::Gnu(..),
3188 "mixing GNU and non-GNU linker flavors"
3189 );
3190 }
3191 LinkerFlavor::Darwin(..) => {
3192 check_matches!(
3193 flavor,
3194 LinkerFlavor::Darwin(..),
3195 "mixing Darwin and non-Darwin linker flavors"
3196 )
3197 }
3198 LinkerFlavor::WasmLld(..) => {
3199 check_matches!(
3200 flavor,
3201 LinkerFlavor::WasmLld(..),
3202 "mixing wasm and non-wasm linker flavors"
3203 )
3204 }
3205 LinkerFlavor::Unix(..) => {
3206 check_matches!(
3207 flavor,
3208 LinkerFlavor::Unix(..),
3209 "mixing unix and non-unix linker flavors"
3210 );
3211 }
3212 LinkerFlavor::Msvc(..) => {
3213 check_matches!(
3214 flavor,
3215 LinkerFlavor::Msvc(..),
3216 "mixing MSVC and non-MSVC linker flavors"
3217 );
3218 }
3219 LinkerFlavor::EmCc
3220 | LinkerFlavor::Bpf
3221 | LinkerFlavor::Ptx
3222 | LinkerFlavor::Llbc => {
3223 check_eq!(flavor, self.linker_flavor, "mixing different linker flavors")
3224 }
3225 }
3226
3227 let check_noncc = |noncc_flavor| -> Result<(), String> {
3229 if let Some(noncc_args) = args.get(&noncc_flavor) {
3230 for arg in flavor_args {
3231 if let Some(suffix) = arg.strip_prefix("-Wl,") {
3232 check!(
3233 noncc_args.iter().any(|a| a == suffix),
3234 " link args for cc and non-cc versions of flavors are not consistent"
3235 );
3236 }
3237 }
3238 }
3239 Ok(())
3240 };
3241
3242 match self.linker_flavor {
3243 LinkerFlavor::Gnu(Cc::Yes, lld) => check_noncc(LinkerFlavor::Gnu(Cc::No, lld))?,
3244 LinkerFlavor::WasmLld(Cc::Yes) => check_noncc(LinkerFlavor::WasmLld(Cc::No))?,
3245 LinkerFlavor::Unix(Cc::Yes) => check_noncc(LinkerFlavor::Unix(Cc::No))?,
3246 _ => {}
3247 }
3248 }
3249
3250 for cc in [Cc::No, Cc::Yes] {
3252 check_eq!(
3253 args.get(&LinkerFlavor::Gnu(cc, Lld::No)),
3254 args.get(&LinkerFlavor::Gnu(cc, Lld::Yes)),
3255 "link args for lld and non-lld versions of flavors are not consistent",
3256 );
3257 check_eq!(
3258 args.get(&LinkerFlavor::Darwin(cc, Lld::No)),
3259 args.get(&LinkerFlavor::Darwin(cc, Lld::Yes)),
3260 "link args for lld and non-lld versions of flavors are not consistent",
3261 );
3262 }
3263 check_eq!(
3264 args.get(&LinkerFlavor::Msvc(Lld::No)),
3265 args.get(&LinkerFlavor::Msvc(Lld::Yes)),
3266 "link args for lld and non-lld versions of flavors are not consistent",
3267 );
3268 }
3269
3270 if self.link_self_contained.is_disabled() {
3271 check!(
3272 self.pre_link_objects_self_contained.is_empty()
3273 && self.post_link_objects_self_contained.is_empty(),
3274 "if `link_self_contained` is disabled, then `pre_link_objects_self_contained` and `post_link_objects_self_contained` must be empty",
3275 );
3276 }
3277
3278 check_ne!(self.vendor, "", "`vendor` cannot be empty");
3282 check_ne!(self.os, "", "`os` cannot be empty");
3283 if !self.can_use_os_unknown() {
3284 check_ne!(
3286 self.os,
3287 "unknown",
3288 "`unknown` os can only be used on particular targets; use `none` for bare-metal targets"
3289 );
3290 }
3291
3292 if kind == TargetKind::Builtin {
3298 if self.os == "none"
3302 && (self.arch != "bpf"
3303 && self.arch != "hexagon"
3304 && self.arch != "wasm32"
3305 && self.arch != "wasm64")
3306 {
3307 check!(
3308 !self.dynamic_linking,
3309 "dynamic linking is not supported on this OS/architecture"
3310 );
3311 }
3312 if self.only_cdylib
3313 || self.crt_static_allows_dylibs
3314 || !self.late_link_args_dynamic.is_empty()
3315 {
3316 check!(
3317 self.dynamic_linking,
3318 "dynamic linking must be allowed when `only_cdylib` or `crt_static_allows_dylibs` or `late_link_args_dynamic` are set"
3319 );
3320 }
3321 if self.dynamic_linking && !self.is_like_wasm {
3323 check_eq!(
3324 self.relocation_model,
3325 RelocModel::Pic,
3326 "targets that support dynamic linking must use the `pic` relocation model"
3327 );
3328 }
3329 if self.position_independent_executables {
3330 check_eq!(
3331 self.relocation_model,
3332 RelocModel::Pic,
3333 "targets that support position-independent executables must use the `pic` relocation model"
3334 );
3335 }
3336 if self.relocation_model == RelocModel::Pic && (self.os != "uefi") {
3338 check!(
3339 self.dynamic_linking || self.position_independent_executables,
3340 "when the relocation model is `pic`, the target must support dynamic linking or use position-independent executables. \
3341 Set the relocation model to `static` to avoid this requirement"
3342 );
3343 }
3344 if self.static_position_independent_executables {
3345 check!(
3346 self.position_independent_executables,
3347 "if `static_position_independent_executables` is set, then `position_independent_executables` must be set"
3348 );
3349 }
3350 if self.position_independent_executables {
3351 check!(
3352 self.executables,
3353 "if `position_independent_executables` is set then `executables` must be set"
3354 );
3355 }
3356 }
3357
3358 if self.crt_static_default || self.crt_static_allows_dylibs {
3360 check!(
3361 self.crt_static_respected,
3362 "static CRT can be enabled but `crt_static_respected` is not set"
3363 );
3364 }
3365
3366 match &*self.arch {
3369 "riscv32" => {
3370 check_matches!(
3371 &*self.llvm_abiname,
3372 "ilp32" | "ilp32f" | "ilp32d" | "ilp32e",
3373 "invalid RISC-V ABI name: {}",
3374 self.llvm_abiname,
3375 );
3376 }
3377 "riscv64" => {
3378 check_matches!(
3380 &*self.llvm_abiname,
3381 "lp64" | "lp64f" | "lp64d" | "lp64e",
3382 "invalid RISC-V ABI name: {}",
3383 self.llvm_abiname,
3384 );
3385 }
3386 "arm" => {
3387 check!(
3388 self.llvm_floatabi.is_some(),
3389 "ARM targets must set `llvm-floatabi` to `hard` or `soft`",
3390 )
3391 }
3392 _ => {}
3393 }
3394
3395 if let Some(rust_abi) = self.rustc_abi {
3397 match rust_abi {
3398 RustcAbi::X86Sse2 => check_matches!(
3399 &*self.arch,
3400 "x86",
3401 "`x86-sse2` ABI is only valid for x86-32 targets"
3402 ),
3403 RustcAbi::X86Softfloat => check_matches!(
3404 &*self.arch,
3405 "x86" | "x86_64",
3406 "`x86-softfloat` ABI is only valid for x86 targets"
3407 ),
3408 }
3409 }
3410
3411 if !self.features.is_empty() {
3413 let mut features_enabled = FxHashSet::default();
3414 let mut features_disabled = FxHashSet::default();
3415 for feat in self.features.split(',') {
3416 if let Some(feat) = feat.strip_prefix("+") {
3417 features_enabled.insert(feat);
3418 if features_disabled.contains(feat) {
3419 return Err(format!(
3420 "target feature `{feat}` is both enabled and disabled"
3421 ));
3422 }
3423 } else if let Some(feat) = feat.strip_prefix("-") {
3424 features_disabled.insert(feat);
3425 if features_enabled.contains(feat) {
3426 return Err(format!(
3427 "target feature `{feat}` is both enabled and disabled"
3428 ));
3429 }
3430 } else {
3431 return Err(format!(
3432 "target feature `{feat}` is invalid, must start with `+` or `-`"
3433 ));
3434 }
3435 }
3436 let abi_feature_constraints = self.abi_required_features();
3438 for feat in abi_feature_constraints.required {
3439 if features_disabled.contains(feat) {
3442 return Err(format!(
3443 "target feature `{feat}` is required by the ABI but gets disabled in target spec"
3444 ));
3445 }
3446 }
3447 for feat in abi_feature_constraints.incompatible {
3448 if features_enabled.contains(feat) {
3451 return Err(format!(
3452 "target feature `{feat}` is incompatible with the ABI but gets enabled in target spec"
3453 ));
3454 }
3455 }
3456 }
3457
3458 Ok(())
3459 }
3460
3461 #[cfg(test)]
3463 fn test_target(mut self) {
3464 let recycled_target =
3465 Target::from_json(&serde_json::to_string(&self.to_json()).unwrap()).map(|(j, _)| j);
3466 self.update_to_cli();
3467 self.check_consistency(TargetKind::Builtin).unwrap();
3468 assert_eq!(recycled_target, Ok(self));
3469 }
3470
3471 fn can_use_os_unknown(&self) -> bool {
3474 self.llvm_target == "wasm32-unknown-unknown"
3475 || self.llvm_target == "wasm64-unknown-unknown"
3476 || (self.env == "sgx" && self.vendor == "fortanix")
3477 }
3478
3479 pub fn expect_builtin(target_tuple: &TargetTuple) -> Target {
3481 match *target_tuple {
3482 TargetTuple::TargetTuple(ref target_tuple) => {
3483 load_builtin(target_tuple).expect("built-in target")
3484 }
3485 TargetTuple::TargetJson { .. } => {
3486 panic!("built-in targets doesn't support target-paths")
3487 }
3488 }
3489 }
3490
3491 pub fn builtins() -> impl Iterator<Item = Target> {
3493 load_all_builtins()
3494 }
3495
3496 pub fn search(
3506 target_tuple: &TargetTuple,
3507 sysroot: &Path,
3508 ) -> Result<(Target, TargetWarnings), String> {
3509 use std::{env, fs};
3510
3511 fn load_file(path: &Path) -> Result<(Target, TargetWarnings), String> {
3512 let contents = fs::read_to_string(path).map_err(|e| e.to_string())?;
3513 Target::from_json(&contents)
3514 }
3515
3516 match *target_tuple {
3517 TargetTuple::TargetTuple(ref target_tuple) => {
3518 if let Some(t) = load_builtin(target_tuple) {
3520 return Ok((t, TargetWarnings::empty()));
3521 }
3522
3523 let path = {
3525 let mut target = target_tuple.to_string();
3526 target.push_str(".json");
3527 PathBuf::from(target)
3528 };
3529
3530 let target_path = env::var_os("RUST_TARGET_PATH").unwrap_or_default();
3531
3532 for dir in env::split_paths(&target_path) {
3533 let p = dir.join(&path);
3534 if p.is_file() {
3535 return load_file(&p);
3536 }
3537 }
3538
3539 let rustlib_path = crate::relative_target_rustlib_path(sysroot, target_tuple);
3542 let p = PathBuf::from_iter([
3543 Path::new(sysroot),
3544 Path::new(&rustlib_path),
3545 Path::new("target.json"),
3546 ]);
3547 if p.is_file() {
3548 return load_file(&p);
3549 }
3550
3551 if target_tuple == "i586-pc-windows-msvc" {
3555 Err("the `i586-pc-windows-msvc` target has been removed. Use the `i686-pc-windows-msvc` target instead.\n\
3556 Windows 10 (the minimum required OS version) requires a CPU baseline of at least i686 so you can safely switch".into())
3557 } else {
3558 Err(format!("could not find specification for target {target_tuple:?}"))
3559 }
3560 }
3561 TargetTuple::TargetJson { ref contents, .. } => Target::from_json(contents),
3562 }
3563 }
3564
3565 pub fn small_data_threshold_support(&self) -> SmallDataThresholdSupport {
3568 match &self.options.small_data_threshold_support {
3569 SmallDataThresholdSupport::DefaultForArch => match self.arch.as_ref() {
3573 "mips" | "mips64" | "mips32r6" => {
3574 SmallDataThresholdSupport::LlvmArg("mips-ssection-threshold".into())
3575 }
3576 "hexagon" => {
3577 SmallDataThresholdSupport::LlvmArg("hexagon-small-data-threshold".into())
3578 }
3579 "m68k" => SmallDataThresholdSupport::LlvmArg("m68k-ssection-threshold".into()),
3580 "riscv32" | "riscv64" => {
3581 SmallDataThresholdSupport::LlvmModuleFlag("SmallDataLimit".into())
3582 }
3583 _ => SmallDataThresholdSupport::None,
3584 },
3585 s => s.clone(),
3586 }
3587 }
3588
3589 pub fn object_architecture(
3590 &self,
3591 unstable_target_features: &FxIndexSet<Symbol>,
3592 ) -> Option<(object::Architecture, Option<object::SubArchitecture>)> {
3593 use object::Architecture;
3594 Some(match self.arch.as_ref() {
3595 "arm" => (Architecture::Arm, None),
3596 "aarch64" => (
3597 if self.pointer_width == 32 {
3598 Architecture::Aarch64_Ilp32
3599 } else {
3600 Architecture::Aarch64
3601 },
3602 None,
3603 ),
3604 "x86" => (Architecture::I386, None),
3605 "s390x" => (Architecture::S390x, None),
3606 "m68k" => (Architecture::M68k, None),
3607 "mips" | "mips32r6" => (Architecture::Mips, None),
3608 "mips64" | "mips64r6" => (
3609 if self.options.llvm_abiname.as_ref() == "n32" {
3615 Architecture::Mips64_N32
3616 } else {
3617 Architecture::Mips64
3618 },
3619 None,
3620 ),
3621 "x86_64" => (
3622 if self.pointer_width == 32 {
3623 Architecture::X86_64_X32
3624 } else {
3625 Architecture::X86_64
3626 },
3627 None,
3628 ),
3629 "powerpc" => (Architecture::PowerPc, None),
3630 "powerpc64" => (Architecture::PowerPc64, None),
3631 "riscv32" => (Architecture::Riscv32, None),
3632 "riscv64" => (Architecture::Riscv64, None),
3633 "sparc" => {
3634 if unstable_target_features.contains(&sym::v8plus) {
3635 (Architecture::Sparc32Plus, None)
3637 } else {
3638 (Architecture::Sparc, None)
3640 }
3641 }
3642 "sparc64" => (Architecture::Sparc64, None),
3643 "avr" => (Architecture::Avr, None),
3644 "msp430" => (Architecture::Msp430, None),
3645 "hexagon" => (Architecture::Hexagon, None),
3646 "bpf" => (Architecture::Bpf, None),
3647 "loongarch32" => (Architecture::LoongArch32, None),
3648 "loongarch64" => (Architecture::LoongArch64, None),
3649 "csky" => (Architecture::Csky, None),
3650 "arm64ec" => (Architecture::Aarch64, Some(object::SubArchitecture::Arm64EC)),
3651 _ => return None,
3653 })
3654 }
3655
3656 pub fn max_reliable_alignment(&self) -> Align {
3665 if self.is_like_windows && self.arch == "x86" {
3669 Align::from_bytes(4).unwrap()
3670 } else {
3671 Align::MAX
3672 }
3673 }
3674}
3675
3676#[derive(Clone, Debug)]
3678pub enum TargetTuple {
3679 TargetTuple(String),
3680 TargetJson {
3681 path_for_rustdoc: PathBuf,
3684 tuple: String,
3685 contents: String,
3686 },
3687}
3688
3689impl PartialEq for TargetTuple {
3691 fn eq(&self, other: &Self) -> bool {
3692 match (self, other) {
3693 (Self::TargetTuple(l0), Self::TargetTuple(r0)) => l0 == r0,
3694 (
3695 Self::TargetJson { path_for_rustdoc: _, tuple: l_tuple, contents: l_contents },
3696 Self::TargetJson { path_for_rustdoc: _, tuple: r_tuple, contents: r_contents },
3697 ) => l_tuple == r_tuple && l_contents == r_contents,
3698 _ => false,
3699 }
3700 }
3701}
3702
3703impl Hash for TargetTuple {
3705 fn hash<H: Hasher>(&self, state: &mut H) -> () {
3706 match self {
3707 TargetTuple::TargetTuple(tuple) => {
3708 0u8.hash(state);
3709 tuple.hash(state)
3710 }
3711 TargetTuple::TargetJson { path_for_rustdoc: _, tuple, contents } => {
3712 1u8.hash(state);
3713 tuple.hash(state);
3714 contents.hash(state)
3715 }
3716 }
3717 }
3718}
3719
3720impl<S: Encoder> Encodable<S> for TargetTuple {
3722 fn encode(&self, s: &mut S) {
3723 match self {
3724 TargetTuple::TargetTuple(tuple) => {
3725 s.emit_u8(0);
3726 s.emit_str(tuple);
3727 }
3728 TargetTuple::TargetJson { path_for_rustdoc: _, tuple, contents } => {
3729 s.emit_u8(1);
3730 s.emit_str(tuple);
3731 s.emit_str(contents);
3732 }
3733 }
3734 }
3735}
3736
3737impl<D: Decoder> Decodable<D> for TargetTuple {
3738 fn decode(d: &mut D) -> Self {
3739 match d.read_u8() {
3740 0 => TargetTuple::TargetTuple(d.read_str().to_owned()),
3741 1 => TargetTuple::TargetJson {
3742 path_for_rustdoc: PathBuf::new(),
3743 tuple: d.read_str().to_owned(),
3744 contents: d.read_str().to_owned(),
3745 },
3746 _ => {
3747 panic!("invalid enum variant tag while decoding `TargetTuple`, expected 0..2");
3748 }
3749 }
3750 }
3751}
3752
3753impl TargetTuple {
3754 pub fn from_tuple(tuple: &str) -> Self {
3756 TargetTuple::TargetTuple(tuple.into())
3757 }
3758
3759 pub fn from_path(path: &Path) -> Result<Self, io::Error> {
3761 let canonicalized_path = try_canonicalize(path)?;
3762 let contents = std::fs::read_to_string(&canonicalized_path).map_err(|err| {
3763 io::Error::new(
3764 io::ErrorKind::InvalidInput,
3765 format!("target path {canonicalized_path:?} is not a valid file: {err}"),
3766 )
3767 })?;
3768 let tuple = canonicalized_path
3769 .file_stem()
3770 .expect("target path must not be empty")
3771 .to_str()
3772 .expect("target path must be valid unicode")
3773 .to_owned();
3774 Ok(TargetTuple::TargetJson { path_for_rustdoc: canonicalized_path, tuple, contents })
3775 }
3776
3777 pub fn tuple(&self) -> &str {
3781 match *self {
3782 TargetTuple::TargetTuple(ref tuple) | TargetTuple::TargetJson { ref tuple, .. } => {
3783 tuple
3784 }
3785 }
3786 }
3787
3788 pub fn debug_tuple(&self) -> String {
3793 use std::hash::DefaultHasher;
3794
3795 match self {
3796 TargetTuple::TargetTuple(tuple) => tuple.to_owned(),
3797 TargetTuple::TargetJson { path_for_rustdoc: _, tuple, contents: content } => {
3798 let mut hasher = DefaultHasher::new();
3799 content.hash(&mut hasher);
3800 let hash = hasher.finish();
3801 format!("{tuple}-{hash}")
3802 }
3803 }
3804 }
3805}
3806
3807impl fmt::Display for TargetTuple {
3808 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3809 write!(f, "{}", self.debug_tuple())
3810 }
3811}