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