1use std::borrow::Cow;
38use std::collections::BTreeMap;
39use std::hash::{Hash, Hasher};
40use std::ops::{Deref, DerefMut};
41use std::path::{Path, PathBuf};
42use std::str::FromStr;
43use std::{fmt, io};
44
45use rustc_abi::{
46 Align, Endian, ExternAbi, Integer, Size, TargetDataLayout, TargetDataLayoutErrors,
47};
48use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
49use rustc_fs_util::try_canonicalize;
50use rustc_macros::{Decodable, Encodable, HashStable_Generic};
51use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
52use rustc_span::{Symbol, kw, sym};
53use serde_json::Value;
54use tracing::debug;
55
56use crate::callconv::Conv;
57use crate::json::{Json, ToJson};
58use crate::spec::crt_objects::CrtObjects;
59
60pub mod crt_objects;
61
62mod base;
63mod json;
64
65pub use base::apple;
66pub use base::avr::ef_avr_arch;
67
68#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
70pub enum Cc {
71 Yes,
72 No,
73}
74
75#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
77pub enum Lld {
78 Yes,
79 No,
80}
81
82#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
103pub enum LinkerFlavor {
104 Gnu(Cc, Lld),
108 Darwin(Cc, Lld),
111 WasmLld(Cc),
115 Unix(Cc),
119 Msvc(Lld),
121 EmCc,
124 Bpf,
127 Ptx,
129 Llbc,
131}
132
133#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
138pub enum LinkerFlavorCli {
139 Gnu(Cc, Lld),
141 Darwin(Cc, Lld),
142 WasmLld(Cc),
143 Unix(Cc),
144 Msvc(Lld),
146 EmCc,
147 Bpf,
148 Ptx,
149 Llbc,
150
151 Gcc,
153 Ld,
154 Lld(LldFlavor),
155 Em,
156}
157
158impl LinkerFlavorCli {
159 pub fn is_unstable(&self) -> bool {
161 match self {
162 LinkerFlavorCli::Gnu(..)
163 | LinkerFlavorCli::Darwin(..)
164 | LinkerFlavorCli::WasmLld(..)
165 | LinkerFlavorCli::Unix(..)
166 | LinkerFlavorCli::Msvc(Lld::Yes)
167 | LinkerFlavorCli::EmCc
168 | LinkerFlavorCli::Bpf
169 | LinkerFlavorCli::Llbc
170 | LinkerFlavorCli::Ptx => true,
171 LinkerFlavorCli::Gcc
172 | LinkerFlavorCli::Ld
173 | LinkerFlavorCli::Lld(..)
174 | LinkerFlavorCli::Msvc(Lld::No)
175 | LinkerFlavorCli::Em => false,
176 }
177 }
178}
179
180#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
181pub enum LldFlavor {
182 Wasm,
183 Ld64,
184 Ld,
185 Link,
186}
187
188impl LldFlavor {
189 pub fn as_str(&self) -> &'static str {
190 match self {
191 LldFlavor::Wasm => "wasm",
192 LldFlavor::Ld64 => "darwin",
193 LldFlavor::Ld => "gnu",
194 LldFlavor::Link => "link",
195 }
196 }
197
198 fn from_str(s: &str) -> Option<Self> {
199 Some(match s {
200 "darwin" => LldFlavor::Ld64,
201 "gnu" => LldFlavor::Ld,
202 "link" => LldFlavor::Link,
203 "wasm" => LldFlavor::Wasm,
204 _ => return None,
205 })
206 }
207}
208
209impl ToJson for LldFlavor {
210 fn to_json(&self) -> Json {
211 self.as_str().to_json()
212 }
213}
214
215impl LinkerFlavor {
216 fn from_cli_json(cli: LinkerFlavorCli, lld_flavor: LldFlavor, is_gnu: bool) -> LinkerFlavor {
221 match cli {
222 LinkerFlavorCli::Gnu(cc, lld) => LinkerFlavor::Gnu(cc, lld),
223 LinkerFlavorCli::Darwin(cc, lld) => LinkerFlavor::Darwin(cc, lld),
224 LinkerFlavorCli::WasmLld(cc) => LinkerFlavor::WasmLld(cc),
225 LinkerFlavorCli::Unix(cc) => LinkerFlavor::Unix(cc),
226 LinkerFlavorCli::Msvc(lld) => LinkerFlavor::Msvc(lld),
227 LinkerFlavorCli::EmCc => LinkerFlavor::EmCc,
228 LinkerFlavorCli::Bpf => LinkerFlavor::Bpf,
229 LinkerFlavorCli::Llbc => LinkerFlavor::Llbc,
230 LinkerFlavorCli::Ptx => LinkerFlavor::Ptx,
231
232 LinkerFlavorCli::Gcc => match lld_flavor {
234 LldFlavor::Ld if is_gnu => LinkerFlavor::Gnu(Cc::Yes, Lld::No),
235 LldFlavor::Ld64 => LinkerFlavor::Darwin(Cc::Yes, Lld::No),
236 LldFlavor::Wasm => LinkerFlavor::WasmLld(Cc::Yes),
237 LldFlavor::Ld | LldFlavor::Link => LinkerFlavor::Unix(Cc::Yes),
238 },
239 LinkerFlavorCli::Ld => match lld_flavor {
240 LldFlavor::Ld if is_gnu => LinkerFlavor::Gnu(Cc::No, Lld::No),
241 LldFlavor::Ld64 => LinkerFlavor::Darwin(Cc::No, Lld::No),
242 LldFlavor::Ld | LldFlavor::Wasm | LldFlavor::Link => LinkerFlavor::Unix(Cc::No),
243 },
244 LinkerFlavorCli::Lld(LldFlavor::Ld) => LinkerFlavor::Gnu(Cc::No, Lld::Yes),
245 LinkerFlavorCli::Lld(LldFlavor::Ld64) => LinkerFlavor::Darwin(Cc::No, Lld::Yes),
246 LinkerFlavorCli::Lld(LldFlavor::Wasm) => LinkerFlavor::WasmLld(Cc::No),
247 LinkerFlavorCli::Lld(LldFlavor::Link) => LinkerFlavor::Msvc(Lld::Yes),
248 LinkerFlavorCli::Em => LinkerFlavor::EmCc,
249 }
250 }
251
252 fn to_cli(self) -> LinkerFlavorCli {
254 match self {
255 LinkerFlavor::Gnu(Cc::Yes, _)
256 | LinkerFlavor::Darwin(Cc::Yes, _)
257 | LinkerFlavor::WasmLld(Cc::Yes)
258 | LinkerFlavor::Unix(Cc::Yes) => LinkerFlavorCli::Gcc,
259 LinkerFlavor::Gnu(_, Lld::Yes) => LinkerFlavorCli::Lld(LldFlavor::Ld),
260 LinkerFlavor::Darwin(_, Lld::Yes) => LinkerFlavorCli::Lld(LldFlavor::Ld64),
261 LinkerFlavor::WasmLld(..) => LinkerFlavorCli::Lld(LldFlavor::Wasm),
262 LinkerFlavor::Gnu(..) | LinkerFlavor::Darwin(..) | LinkerFlavor::Unix(..) => {
263 LinkerFlavorCli::Ld
264 }
265 LinkerFlavor::Msvc(Lld::Yes) => LinkerFlavorCli::Lld(LldFlavor::Link),
266 LinkerFlavor::Msvc(..) => LinkerFlavorCli::Msvc(Lld::No),
267 LinkerFlavor::EmCc => LinkerFlavorCli::Em,
268 LinkerFlavor::Bpf => LinkerFlavorCli::Bpf,
269 LinkerFlavor::Llbc => LinkerFlavorCli::Llbc,
270 LinkerFlavor::Ptx => LinkerFlavorCli::Ptx,
271 }
272 }
273
274 fn to_cli_counterpart(self) -> LinkerFlavorCli {
276 match self {
277 LinkerFlavor::Gnu(cc, lld) => LinkerFlavorCli::Gnu(cc, lld),
278 LinkerFlavor::Darwin(cc, lld) => LinkerFlavorCli::Darwin(cc, lld),
279 LinkerFlavor::WasmLld(cc) => LinkerFlavorCli::WasmLld(cc),
280 LinkerFlavor::Unix(cc) => LinkerFlavorCli::Unix(cc),
281 LinkerFlavor::Msvc(lld) => LinkerFlavorCli::Msvc(lld),
282 LinkerFlavor::EmCc => LinkerFlavorCli::EmCc,
283 LinkerFlavor::Bpf => LinkerFlavorCli::Bpf,
284 LinkerFlavor::Llbc => LinkerFlavorCli::Llbc,
285 LinkerFlavor::Ptx => LinkerFlavorCli::Ptx,
286 }
287 }
288
289 fn infer_cli_hints(cli: LinkerFlavorCli) -> (Option<Cc>, Option<Lld>) {
290 match cli {
291 LinkerFlavorCli::Gnu(cc, lld) | LinkerFlavorCli::Darwin(cc, lld) => {
292 (Some(cc), Some(lld))
293 }
294 LinkerFlavorCli::WasmLld(cc) => (Some(cc), Some(Lld::Yes)),
295 LinkerFlavorCli::Unix(cc) => (Some(cc), None),
296 LinkerFlavorCli::Msvc(lld) => (Some(Cc::No), Some(lld)),
297 LinkerFlavorCli::EmCc => (Some(Cc::Yes), Some(Lld::Yes)),
298 LinkerFlavorCli::Bpf | LinkerFlavorCli::Ptx => (None, None),
299 LinkerFlavorCli::Llbc => (None, None),
300
301 LinkerFlavorCli::Gcc => (Some(Cc::Yes), None),
303 LinkerFlavorCli::Ld => (Some(Cc::No), Some(Lld::No)),
304 LinkerFlavorCli::Lld(_) => (Some(Cc::No), Some(Lld::Yes)),
305 LinkerFlavorCli::Em => (Some(Cc::Yes), Some(Lld::Yes)),
306 }
307 }
308
309 fn infer_linker_hints(linker_stem: &str) -> Result<Self, (Option<Cc>, Option<Lld>)> {
310 let stem = linker_stem
312 .rsplit_once('-')
313 .and_then(|(lhs, rhs)| rhs.chars().all(char::is_numeric).then_some(lhs))
314 .unwrap_or(linker_stem);
315
316 if stem == "llvm-bitcode-linker" {
317 Ok(Self::Llbc)
318 } else if stem == "emcc" || stem == "gcc"
320 || stem.ends_with("-gcc")
321 || stem == "g++"
322 || stem.ends_with("-g++")
323 || stem == "clang"
324 || stem.ends_with("-clang")
325 || stem == "clang++"
326 || stem.ends_with("-clang++")
327 {
328 Err((Some(Cc::Yes), Some(Lld::No)))
329 } else if stem == "wasm-ld"
330 || stem.ends_with("-wasm-ld")
331 || stem == "ld.lld"
332 || stem == "lld"
333 || stem == "rust-lld"
334 || stem == "lld-link"
335 {
336 Err((Some(Cc::No), Some(Lld::Yes)))
337 } else if stem == "ld" || stem.ends_with("-ld") || stem == "link" {
338 Err((Some(Cc::No), Some(Lld::No)))
339 } else {
340 Err((None, None))
341 }
342 }
343
344 fn with_hints(self, (cc_hint, lld_hint): (Option<Cc>, Option<Lld>)) -> LinkerFlavor {
345 match self {
346 LinkerFlavor::Gnu(cc, lld) => {
347 LinkerFlavor::Gnu(cc_hint.unwrap_or(cc), lld_hint.unwrap_or(lld))
348 }
349 LinkerFlavor::Darwin(cc, lld) => {
350 LinkerFlavor::Darwin(cc_hint.unwrap_or(cc), lld_hint.unwrap_or(lld))
351 }
352 LinkerFlavor::WasmLld(cc) => LinkerFlavor::WasmLld(cc_hint.unwrap_or(cc)),
353 LinkerFlavor::Unix(cc) => LinkerFlavor::Unix(cc_hint.unwrap_or(cc)),
354 LinkerFlavor::Msvc(lld) => LinkerFlavor::Msvc(lld_hint.unwrap_or(lld)),
355 LinkerFlavor::EmCc | LinkerFlavor::Bpf | LinkerFlavor::Llbc | LinkerFlavor::Ptx => self,
356 }
357 }
358
359 pub fn with_cli_hints(self, cli: LinkerFlavorCli) -> LinkerFlavor {
360 self.with_hints(LinkerFlavor::infer_cli_hints(cli))
361 }
362
363 pub fn with_linker_hints(self, linker_stem: &str) -> LinkerFlavor {
364 match LinkerFlavor::infer_linker_hints(linker_stem) {
365 Ok(linker_flavor) => linker_flavor,
366 Err(hints) => self.with_hints(hints),
367 }
368 }
369
370 pub fn check_compatibility(self, cli: LinkerFlavorCli) -> Option<String> {
371 let compatible = |cli| {
372 match (self, cli) {
374 (LinkerFlavor::Gnu(..), LinkerFlavorCli::Gnu(..))
376 | (LinkerFlavor::Darwin(..), LinkerFlavorCli::Darwin(..))
377 | (LinkerFlavor::WasmLld(..), LinkerFlavorCli::WasmLld(..))
378 | (LinkerFlavor::Unix(..), LinkerFlavorCli::Unix(..))
379 | (LinkerFlavor::Msvc(..), LinkerFlavorCli::Msvc(..))
380 | (LinkerFlavor::EmCc, LinkerFlavorCli::EmCc)
381 | (LinkerFlavor::Bpf, LinkerFlavorCli::Bpf)
382 | (LinkerFlavor::Llbc, LinkerFlavorCli::Llbc)
383 | (LinkerFlavor::Ptx, LinkerFlavorCli::Ptx) => return true,
384 (LinkerFlavor::Ptx, LinkerFlavorCli::Llbc) => return true,
386 _ => {}
387 }
388
389 cli == self.with_cli_hints(cli).to_cli()
391 };
392 (!compatible(cli)).then(|| {
393 LinkerFlavorCli::all()
394 .iter()
395 .filter(|cli| compatible(**cli))
396 .map(|cli| cli.desc())
397 .intersperse(", ")
398 .collect()
399 })
400 }
401
402 pub fn lld_flavor(self) -> LldFlavor {
403 match self {
404 LinkerFlavor::Gnu(..)
405 | LinkerFlavor::Unix(..)
406 | LinkerFlavor::EmCc
407 | LinkerFlavor::Bpf
408 | LinkerFlavor::Llbc
409 | LinkerFlavor::Ptx => LldFlavor::Ld,
410 LinkerFlavor::Darwin(..) => LldFlavor::Ld64,
411 LinkerFlavor::WasmLld(..) => LldFlavor::Wasm,
412 LinkerFlavor::Msvc(..) => LldFlavor::Link,
413 }
414 }
415
416 pub fn is_gnu(self) -> bool {
417 matches!(self, LinkerFlavor::Gnu(..))
418 }
419
420 pub fn uses_lld(self) -> bool {
422 match self {
424 LinkerFlavor::Gnu(_, Lld::Yes)
425 | LinkerFlavor::Darwin(_, Lld::Yes)
426 | LinkerFlavor::WasmLld(..)
427 | LinkerFlavor::EmCc
428 | LinkerFlavor::Msvc(Lld::Yes) => true,
429 LinkerFlavor::Gnu(..)
430 | LinkerFlavor::Darwin(..)
431 | LinkerFlavor::Msvc(_)
432 | LinkerFlavor::Unix(_)
433 | LinkerFlavor::Bpf
434 | LinkerFlavor::Llbc
435 | LinkerFlavor::Ptx => false,
436 }
437 }
438
439 pub fn uses_cc(self) -> bool {
441 match self {
443 LinkerFlavor::Gnu(Cc::Yes, _)
444 | LinkerFlavor::Darwin(Cc::Yes, _)
445 | LinkerFlavor::WasmLld(Cc::Yes)
446 | LinkerFlavor::Unix(Cc::Yes)
447 | LinkerFlavor::EmCc => true,
448 LinkerFlavor::Gnu(..)
449 | LinkerFlavor::Darwin(..)
450 | LinkerFlavor::WasmLld(_)
451 | LinkerFlavor::Msvc(_)
452 | LinkerFlavor::Unix(_)
453 | LinkerFlavor::Bpf
454 | LinkerFlavor::Llbc
455 | LinkerFlavor::Ptx => false,
456 }
457 }
458
459 pub fn with_lld_enabled(self) -> LinkerFlavor {
462 match self {
463 LinkerFlavor::Gnu(cc, Lld::No) => LinkerFlavor::Gnu(cc, Lld::Yes),
464 LinkerFlavor::Darwin(cc, Lld::No) => LinkerFlavor::Darwin(cc, Lld::Yes),
465 LinkerFlavor::Msvc(Lld::No) => LinkerFlavor::Msvc(Lld::Yes),
466 _ => self,
467 }
468 }
469
470 pub fn with_lld_disabled(self) -> LinkerFlavor {
473 match self {
474 LinkerFlavor::Gnu(cc, Lld::Yes) => LinkerFlavor::Gnu(cc, Lld::No),
475 LinkerFlavor::Darwin(cc, Lld::Yes) => LinkerFlavor::Darwin(cc, Lld::No),
476 LinkerFlavor::Msvc(Lld::Yes) => LinkerFlavor::Msvc(Lld::No),
477 _ => self,
478 }
479 }
480}
481
482macro_rules! linker_flavor_cli_impls {
483 ($(($($flavor:tt)*) $string:literal)*) => (
484 impl LinkerFlavorCli {
485 const fn all() -> &'static [LinkerFlavorCli] {
486 &[$($($flavor)*,)*]
487 }
488
489 pub const fn one_of() -> &'static str {
490 concat!("one of: ", $($string, " ",)*)
491 }
492
493 pub fn from_str(s: &str) -> Option<LinkerFlavorCli> {
494 Some(match s {
495 $($string => $($flavor)*,)*
496 _ => return None,
497 })
498 }
499
500 pub fn desc(self) -> &'static str {
501 match self {
502 $($($flavor)* => $string,)*
503 }
504 }
505 }
506 )
507}
508
509linker_flavor_cli_impls! {
510 (LinkerFlavorCli::Gnu(Cc::No, Lld::No)) "gnu"
511 (LinkerFlavorCli::Gnu(Cc::No, Lld::Yes)) "gnu-lld"
512 (LinkerFlavorCli::Gnu(Cc::Yes, Lld::No)) "gnu-cc"
513 (LinkerFlavorCli::Gnu(Cc::Yes, Lld::Yes)) "gnu-lld-cc"
514 (LinkerFlavorCli::Darwin(Cc::No, Lld::No)) "darwin"
515 (LinkerFlavorCli::Darwin(Cc::No, Lld::Yes)) "darwin-lld"
516 (LinkerFlavorCli::Darwin(Cc::Yes, Lld::No)) "darwin-cc"
517 (LinkerFlavorCli::Darwin(Cc::Yes, Lld::Yes)) "darwin-lld-cc"
518 (LinkerFlavorCli::WasmLld(Cc::No)) "wasm-lld"
519 (LinkerFlavorCli::WasmLld(Cc::Yes)) "wasm-lld-cc"
520 (LinkerFlavorCli::Unix(Cc::No)) "unix"
521 (LinkerFlavorCli::Unix(Cc::Yes)) "unix-cc"
522 (LinkerFlavorCli::Msvc(Lld::Yes)) "msvc-lld"
523 (LinkerFlavorCli::Msvc(Lld::No)) "msvc"
524 (LinkerFlavorCli::EmCc) "em-cc"
525 (LinkerFlavorCli::Bpf) "bpf"
526 (LinkerFlavorCli::Llbc) "llbc"
527 (LinkerFlavorCli::Ptx) "ptx"
528
529 (LinkerFlavorCli::Gcc) "gcc"
531 (LinkerFlavorCli::Ld) "ld"
532 (LinkerFlavorCli::Lld(LldFlavor::Ld)) "ld.lld"
533 (LinkerFlavorCli::Lld(LldFlavor::Ld64)) "ld64.lld"
534 (LinkerFlavorCli::Lld(LldFlavor::Link)) "lld-link"
535 (LinkerFlavorCli::Lld(LldFlavor::Wasm)) "wasm-ld"
536 (LinkerFlavorCli::Em) "em"
537}
538
539impl ToJson for LinkerFlavorCli {
540 fn to_json(&self) -> Json {
541 self.desc().to_json()
542 }
543}
544
545#[derive(Clone, Copy, PartialEq, Debug)]
552pub enum LinkSelfContainedDefault {
553 True,
555
556 False,
558
559 InferredForMusl,
561
562 InferredForMingw,
564
565 WithComponents(LinkSelfContainedComponents),
568}
569
570impl FromStr for LinkSelfContainedDefault {
572 type Err = ();
573
574 fn from_str(s: &str) -> Result<LinkSelfContainedDefault, ()> {
575 Ok(match s {
576 "false" => LinkSelfContainedDefault::False,
577 "true" | "wasm" => LinkSelfContainedDefault::True,
578 "musl" => LinkSelfContainedDefault::InferredForMusl,
579 "mingw" => LinkSelfContainedDefault::InferredForMingw,
580 _ => return Err(()),
581 })
582 }
583}
584
585impl ToJson for LinkSelfContainedDefault {
586 fn to_json(&self) -> Json {
587 match *self {
588 LinkSelfContainedDefault::WithComponents(components) => {
589 let mut map = BTreeMap::new();
593 map.insert("components", components);
594 map.to_json()
595 }
596
597 LinkSelfContainedDefault::True => "true".to_json(),
599 LinkSelfContainedDefault::False => "false".to_json(),
600 LinkSelfContainedDefault::InferredForMusl => "musl".to_json(),
601 LinkSelfContainedDefault::InferredForMingw => "mingw".to_json(),
602 }
603 }
604}
605
606impl LinkSelfContainedDefault {
607 pub fn is_disabled(self) -> bool {
610 self == LinkSelfContainedDefault::False
611 }
612
613 fn json_key(self) -> &'static str {
617 match self {
618 LinkSelfContainedDefault::WithComponents(_) => "link-self-contained",
619 _ => "crt-objects-fallback",
620 }
621 }
622
623 pub fn with_linker() -> LinkSelfContainedDefault {
626 LinkSelfContainedDefault::WithComponents(LinkSelfContainedComponents::LINKER)
627 }
628}
629
630bitflags::bitflags! {
631 #[derive(Clone, Copy, PartialEq, Eq, Default)]
632 pub struct LinkSelfContainedComponents: u8 {
634 const CRT_OBJECTS = 1 << 0;
636 const LIBC = 1 << 1;
638 const UNWIND = 1 << 2;
640 const LINKER = 1 << 3;
642 const SANITIZERS = 1 << 4;
644 const MINGW = 1 << 5;
646 }
647}
648rustc_data_structures::external_bitflags_debug! { LinkSelfContainedComponents }
649
650impl LinkSelfContainedComponents {
651 pub fn from_str(s: &str) -> Option<LinkSelfContainedComponents> {
653 Some(match s {
654 "crto" => LinkSelfContainedComponents::CRT_OBJECTS,
655 "libc" => LinkSelfContainedComponents::LIBC,
656 "unwind" => LinkSelfContainedComponents::UNWIND,
657 "linker" => LinkSelfContainedComponents::LINKER,
658 "sanitizers" => LinkSelfContainedComponents::SANITIZERS,
659 "mingw" => LinkSelfContainedComponents::MINGW,
660 _ => return None,
661 })
662 }
663
664 pub fn as_str(self) -> Option<&'static str> {
668 Some(match self {
669 LinkSelfContainedComponents::CRT_OBJECTS => "crto",
670 LinkSelfContainedComponents::LIBC => "libc",
671 LinkSelfContainedComponents::UNWIND => "unwind",
672 LinkSelfContainedComponents::LINKER => "linker",
673 LinkSelfContainedComponents::SANITIZERS => "sanitizers",
674 LinkSelfContainedComponents::MINGW => "mingw",
675 _ => return None,
676 })
677 }
678
679 fn all_components() -> [LinkSelfContainedComponents; 6] {
681 [
682 LinkSelfContainedComponents::CRT_OBJECTS,
683 LinkSelfContainedComponents::LIBC,
684 LinkSelfContainedComponents::UNWIND,
685 LinkSelfContainedComponents::LINKER,
686 LinkSelfContainedComponents::SANITIZERS,
687 LinkSelfContainedComponents::MINGW,
688 ]
689 }
690
691 pub fn are_any_components_enabled(self) -> bool {
693 !self.is_empty()
694 }
695
696 pub fn is_linker_enabled(self) -> bool {
698 self.contains(LinkSelfContainedComponents::LINKER)
699 }
700
701 pub fn is_crt_objects_enabled(self) -> bool {
703 self.contains(LinkSelfContainedComponents::CRT_OBJECTS)
704 }
705}
706
707impl ToJson for LinkSelfContainedComponents {
708 fn to_json(&self) -> Json {
709 let components: Vec<_> = Self::all_components()
710 .into_iter()
711 .filter(|c| self.contains(*c))
712 .map(|c| {
713 c.as_str().unwrap().to_owned()
716 })
717 .collect();
718
719 components.to_json()
720 }
721}
722
723bitflags::bitflags! {
724 #[derive(Clone, Copy, PartialEq, Eq, Default)]
745 pub struct LinkerFeatures: u8 {
746 const CC = 1 << 0;
748 const LLD = 1 << 1;
750 }
751}
752rustc_data_structures::external_bitflags_debug! { LinkerFeatures }
753
754impl LinkerFeatures {
755 pub fn from_str(s: &str) -> Option<LinkerFeatures> {
757 Some(match s {
758 "cc" => LinkerFeatures::CC,
759 "lld" => LinkerFeatures::LLD,
760 _ => return None,
761 })
762 }
763
764 pub fn is_lld_enabled(self) -> bool {
766 self.contains(LinkerFeatures::LLD)
767 }
768
769 pub fn is_cc_enabled(self) -> bool {
771 self.contains(LinkerFeatures::CC)
772 }
773}
774
775#[derive(Clone, Copy, Debug, PartialEq, Hash, Encodable, Decodable, HashStable_Generic)]
776pub enum PanicStrategy {
777 Unwind,
778 Abort,
779}
780
781#[derive(Clone, Copy, Debug, PartialEq, Hash, Encodable, Decodable, HashStable_Generic)]
782pub enum OnBrokenPipe {
783 Default,
784 Kill,
785 Error,
786 Inherit,
787}
788
789impl PanicStrategy {
790 pub fn desc(&self) -> &str {
791 match *self {
792 PanicStrategy::Unwind => "unwind",
793 PanicStrategy::Abort => "abort",
794 }
795 }
796
797 pub const fn desc_symbol(&self) -> Symbol {
798 match *self {
799 PanicStrategy::Unwind => sym::unwind,
800 PanicStrategy::Abort => sym::abort,
801 }
802 }
803
804 pub const fn all() -> [Symbol; 2] {
805 [Self::Abort.desc_symbol(), Self::Unwind.desc_symbol()]
806 }
807}
808
809impl ToJson for PanicStrategy {
810 fn to_json(&self) -> Json {
811 match *self {
812 PanicStrategy::Abort => "abort".to_json(),
813 PanicStrategy::Unwind => "unwind".to_json(),
814 }
815 }
816}
817
818#[derive(Clone, Copy, Debug, PartialEq, Hash)]
819pub enum RelroLevel {
820 Full,
821 Partial,
822 Off,
823 None,
824}
825
826impl RelroLevel {
827 pub fn desc(&self) -> &str {
828 match *self {
829 RelroLevel::Full => "full",
830 RelroLevel::Partial => "partial",
831 RelroLevel::Off => "off",
832 RelroLevel::None => "none",
833 }
834 }
835}
836
837#[derive(Clone, Copy, Debug, PartialEq, Hash)]
838pub enum SymbolVisibility {
839 Hidden,
840 Protected,
841 Interposable,
842}
843
844impl SymbolVisibility {
845 pub fn desc(&self) -> &str {
846 match *self {
847 SymbolVisibility::Hidden => "hidden",
848 SymbolVisibility::Protected => "protected",
849 SymbolVisibility::Interposable => "interposable",
850 }
851 }
852}
853
854impl FromStr for SymbolVisibility {
855 type Err = ();
856
857 fn from_str(s: &str) -> Result<SymbolVisibility, ()> {
858 match s {
859 "hidden" => Ok(SymbolVisibility::Hidden),
860 "protected" => Ok(SymbolVisibility::Protected),
861 "interposable" => Ok(SymbolVisibility::Interposable),
862 _ => Err(()),
863 }
864 }
865}
866
867impl ToJson for SymbolVisibility {
868 fn to_json(&self) -> Json {
869 match *self {
870 SymbolVisibility::Hidden => "hidden".to_json(),
871 SymbolVisibility::Protected => "protected".to_json(),
872 SymbolVisibility::Interposable => "interposable".to_json(),
873 }
874 }
875}
876
877impl FromStr for RelroLevel {
878 type Err = ();
879
880 fn from_str(s: &str) -> Result<RelroLevel, ()> {
881 match s {
882 "full" => Ok(RelroLevel::Full),
883 "partial" => Ok(RelroLevel::Partial),
884 "off" => Ok(RelroLevel::Off),
885 "none" => Ok(RelroLevel::None),
886 _ => Err(()),
887 }
888 }
889}
890
891impl ToJson for RelroLevel {
892 fn to_json(&self) -> Json {
893 match *self {
894 RelroLevel::Full => "full".to_json(),
895 RelroLevel::Partial => "partial".to_json(),
896 RelroLevel::Off => "off".to_json(),
897 RelroLevel::None => "None".to_json(),
898 }
899 }
900}
901
902#[derive(Clone, Debug, PartialEq, Hash)]
903pub enum SmallDataThresholdSupport {
904 None,
905 DefaultForArch,
906 LlvmModuleFlag(StaticCow<str>),
907 LlvmArg(StaticCow<str>),
908}
909
910impl FromStr for SmallDataThresholdSupport {
911 type Err = ();
912
913 fn from_str(s: &str) -> Result<Self, Self::Err> {
914 if s == "none" {
915 Ok(Self::None)
916 } else if s == "default-for-arch" {
917 Ok(Self::DefaultForArch)
918 } else if let Some(flag) = s.strip_prefix("llvm-module-flag=") {
919 Ok(Self::LlvmModuleFlag(flag.to_string().into()))
920 } else if let Some(arg) = s.strip_prefix("llvm-arg=") {
921 Ok(Self::LlvmArg(arg.to_string().into()))
922 } else {
923 Err(())
924 }
925 }
926}
927
928impl ToJson for SmallDataThresholdSupport {
929 fn to_json(&self) -> Value {
930 match self {
931 Self::None => "none".to_json(),
932 Self::DefaultForArch => "default-for-arch".to_json(),
933 Self::LlvmModuleFlag(flag) => format!("llvm-module-flag={flag}").to_json(),
934 Self::LlvmArg(arg) => format!("llvm-arg={arg}").to_json(),
935 }
936 }
937}
938
939#[derive(Clone, Copy, Debug, PartialEq, Hash)]
940pub enum MergeFunctions {
941 Disabled,
942 Trampolines,
943 Aliases,
944}
945
946impl MergeFunctions {
947 pub fn desc(&self) -> &str {
948 match *self {
949 MergeFunctions::Disabled => "disabled",
950 MergeFunctions::Trampolines => "trampolines",
951 MergeFunctions::Aliases => "aliases",
952 }
953 }
954}
955
956impl FromStr for MergeFunctions {
957 type Err = ();
958
959 fn from_str(s: &str) -> Result<MergeFunctions, ()> {
960 match s {
961 "disabled" => Ok(MergeFunctions::Disabled),
962 "trampolines" => Ok(MergeFunctions::Trampolines),
963 "aliases" => Ok(MergeFunctions::Aliases),
964 _ => Err(()),
965 }
966 }
967}
968
969impl ToJson for MergeFunctions {
970 fn to_json(&self) -> Json {
971 match *self {
972 MergeFunctions::Disabled => "disabled".to_json(),
973 MergeFunctions::Trampolines => "trampolines".to_json(),
974 MergeFunctions::Aliases => "aliases".to_json(),
975 }
976 }
977}
978
979#[derive(Clone, Copy, PartialEq, Hash, Debug)]
980pub enum RelocModel {
981 Static,
982 Pic,
983 Pie,
984 DynamicNoPic,
985 Ropi,
986 Rwpi,
987 RopiRwpi,
988}
989
990impl RelocModel {
991 pub fn desc(&self) -> &str {
992 match *self {
993 RelocModel::Static => "static",
994 RelocModel::Pic => "pic",
995 RelocModel::Pie => "pie",
996 RelocModel::DynamicNoPic => "dynamic-no-pic",
997 RelocModel::Ropi => "ropi",
998 RelocModel::Rwpi => "rwpi",
999 RelocModel::RopiRwpi => "ropi-rwpi",
1000 }
1001 }
1002 pub const fn desc_symbol(&self) -> Symbol {
1003 match *self {
1004 RelocModel::Static => kw::Static,
1005 RelocModel::Pic => sym::pic,
1006 RelocModel::Pie => sym::pie,
1007 RelocModel::DynamicNoPic => sym::dynamic_no_pic,
1008 RelocModel::Ropi => sym::ropi,
1009 RelocModel::Rwpi => sym::rwpi,
1010 RelocModel::RopiRwpi => sym::ropi_rwpi,
1011 }
1012 }
1013
1014 pub const fn all() -> [Symbol; 7] {
1015 [
1016 RelocModel::Static.desc_symbol(),
1017 RelocModel::Pic.desc_symbol(),
1018 RelocModel::Pie.desc_symbol(),
1019 RelocModel::DynamicNoPic.desc_symbol(),
1020 RelocModel::Ropi.desc_symbol(),
1021 RelocModel::Rwpi.desc_symbol(),
1022 RelocModel::RopiRwpi.desc_symbol(),
1023 ]
1024 }
1025}
1026
1027impl FromStr for RelocModel {
1028 type Err = ();
1029
1030 fn from_str(s: &str) -> Result<RelocModel, ()> {
1031 Ok(match s {
1032 "static" => RelocModel::Static,
1033 "pic" => RelocModel::Pic,
1034 "pie" => RelocModel::Pie,
1035 "dynamic-no-pic" => RelocModel::DynamicNoPic,
1036 "ropi" => RelocModel::Ropi,
1037 "rwpi" => RelocModel::Rwpi,
1038 "ropi-rwpi" => RelocModel::RopiRwpi,
1039 _ => return Err(()),
1040 })
1041 }
1042}
1043
1044impl ToJson for RelocModel {
1045 fn to_json(&self) -> Json {
1046 self.desc().to_json()
1047 }
1048}
1049
1050#[derive(Clone, Copy, PartialEq, Hash, Debug)]
1051pub enum CodeModel {
1052 Tiny,
1053 Small,
1054 Kernel,
1055 Medium,
1056 Large,
1057}
1058
1059impl FromStr for CodeModel {
1060 type Err = ();
1061
1062 fn from_str(s: &str) -> Result<CodeModel, ()> {
1063 Ok(match s {
1064 "tiny" => CodeModel::Tiny,
1065 "small" => CodeModel::Small,
1066 "kernel" => CodeModel::Kernel,
1067 "medium" => CodeModel::Medium,
1068 "large" => CodeModel::Large,
1069 _ => return Err(()),
1070 })
1071 }
1072}
1073
1074impl ToJson for CodeModel {
1075 fn to_json(&self) -> Json {
1076 match *self {
1077 CodeModel::Tiny => "tiny",
1078 CodeModel::Small => "small",
1079 CodeModel::Kernel => "kernel",
1080 CodeModel::Medium => "medium",
1081 CodeModel::Large => "large",
1082 }
1083 .to_json()
1084 }
1085}
1086
1087#[derive(Clone, Copy, PartialEq, Hash, Debug)]
1089pub enum FloatAbi {
1090 Soft,
1091 Hard,
1092}
1093
1094impl FromStr for FloatAbi {
1095 type Err = ();
1096
1097 fn from_str(s: &str) -> Result<FloatAbi, ()> {
1098 Ok(match s {
1099 "soft" => FloatAbi::Soft,
1100 "hard" => FloatAbi::Hard,
1101 _ => return Err(()),
1102 })
1103 }
1104}
1105
1106impl ToJson for FloatAbi {
1107 fn to_json(&self) -> Json {
1108 match *self {
1109 FloatAbi::Soft => "soft",
1110 FloatAbi::Hard => "hard",
1111 }
1112 .to_json()
1113 }
1114}
1115
1116#[derive(Clone, Copy, PartialEq, Hash, Debug)]
1118pub enum RustcAbi {
1119 X86Sse2,
1121 X86Softfloat,
1123}
1124
1125impl FromStr for RustcAbi {
1126 type Err = ();
1127
1128 fn from_str(s: &str) -> Result<RustcAbi, ()> {
1129 Ok(match s {
1130 "x86-sse2" => RustcAbi::X86Sse2,
1131 "x86-softfloat" => RustcAbi::X86Softfloat,
1132 _ => return Err(()),
1133 })
1134 }
1135}
1136
1137impl ToJson for RustcAbi {
1138 fn to_json(&self) -> Json {
1139 match *self {
1140 RustcAbi::X86Sse2 => "x86-sse2",
1141 RustcAbi::X86Softfloat => "x86-softfloat",
1142 }
1143 .to_json()
1144 }
1145}
1146
1147#[derive(Clone, Copy, PartialEq, Hash, Debug)]
1148pub enum TlsModel {
1149 GeneralDynamic,
1150 LocalDynamic,
1151 InitialExec,
1152 LocalExec,
1153 Emulated,
1154}
1155
1156impl FromStr for TlsModel {
1157 type Err = ();
1158
1159 fn from_str(s: &str) -> Result<TlsModel, ()> {
1160 Ok(match s {
1161 "global-dynamic" => TlsModel::GeneralDynamic,
1164 "local-dynamic" => TlsModel::LocalDynamic,
1165 "initial-exec" => TlsModel::InitialExec,
1166 "local-exec" => TlsModel::LocalExec,
1167 "emulated" => TlsModel::Emulated,
1168 _ => return Err(()),
1169 })
1170 }
1171}
1172
1173impl ToJson for TlsModel {
1174 fn to_json(&self) -> Json {
1175 match *self {
1176 TlsModel::GeneralDynamic => "global-dynamic",
1177 TlsModel::LocalDynamic => "local-dynamic",
1178 TlsModel::InitialExec => "initial-exec",
1179 TlsModel::LocalExec => "local-exec",
1180 TlsModel::Emulated => "emulated",
1181 }
1182 .to_json()
1183 }
1184}
1185
1186#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug)]
1188pub enum LinkOutputKind {
1189 DynamicNoPicExe,
1191 DynamicPicExe,
1193 StaticNoPicExe,
1195 StaticPicExe,
1197 DynamicDylib,
1199 StaticDylib,
1201 WasiReactorExe,
1203}
1204
1205impl LinkOutputKind {
1206 fn as_str(&self) -> &'static str {
1207 match self {
1208 LinkOutputKind::DynamicNoPicExe => "dynamic-nopic-exe",
1209 LinkOutputKind::DynamicPicExe => "dynamic-pic-exe",
1210 LinkOutputKind::StaticNoPicExe => "static-nopic-exe",
1211 LinkOutputKind::StaticPicExe => "static-pic-exe",
1212 LinkOutputKind::DynamicDylib => "dynamic-dylib",
1213 LinkOutputKind::StaticDylib => "static-dylib",
1214 LinkOutputKind::WasiReactorExe => "wasi-reactor-exe",
1215 }
1216 }
1217
1218 pub(super) fn from_str(s: &str) -> Option<LinkOutputKind> {
1219 Some(match s {
1220 "dynamic-nopic-exe" => LinkOutputKind::DynamicNoPicExe,
1221 "dynamic-pic-exe" => LinkOutputKind::DynamicPicExe,
1222 "static-nopic-exe" => LinkOutputKind::StaticNoPicExe,
1223 "static-pic-exe" => LinkOutputKind::StaticPicExe,
1224 "dynamic-dylib" => LinkOutputKind::DynamicDylib,
1225 "static-dylib" => LinkOutputKind::StaticDylib,
1226 "wasi-reactor-exe" => LinkOutputKind::WasiReactorExe,
1227 _ => return None,
1228 })
1229 }
1230
1231 pub fn can_link_dylib(self) -> bool {
1232 match self {
1233 LinkOutputKind::StaticNoPicExe | LinkOutputKind::StaticPicExe => false,
1234 LinkOutputKind::DynamicNoPicExe
1235 | LinkOutputKind::DynamicPicExe
1236 | LinkOutputKind::DynamicDylib
1237 | LinkOutputKind::StaticDylib
1238 | LinkOutputKind::WasiReactorExe => true,
1239 }
1240 }
1241}
1242
1243impl fmt::Display for LinkOutputKind {
1244 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1245 f.write_str(self.as_str())
1246 }
1247}
1248
1249pub type LinkArgs = BTreeMap<LinkerFlavor, Vec<StaticCow<str>>>;
1250pub type LinkArgsCli = BTreeMap<LinkerFlavorCli, Vec<StaticCow<str>>>;
1251
1252#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
1257pub enum DebuginfoKind {
1258 #[default]
1260 Dwarf,
1261 DwarfDsym,
1263 Pdb,
1265}
1266
1267impl DebuginfoKind {
1268 fn as_str(&self) -> &'static str {
1269 match self {
1270 DebuginfoKind::Dwarf => "dwarf",
1271 DebuginfoKind::DwarfDsym => "dwarf-dsym",
1272 DebuginfoKind::Pdb => "pdb",
1273 }
1274 }
1275}
1276
1277impl FromStr for DebuginfoKind {
1278 type Err = ();
1279
1280 fn from_str(s: &str) -> Result<Self, ()> {
1281 Ok(match s {
1282 "dwarf" => DebuginfoKind::Dwarf,
1283 "dwarf-dsym" => DebuginfoKind::DwarfDsym,
1284 "pdb" => DebuginfoKind::Pdb,
1285 _ => return Err(()),
1286 })
1287 }
1288}
1289
1290impl ToJson for DebuginfoKind {
1291 fn to_json(&self) -> Json {
1292 self.as_str().to_json()
1293 }
1294}
1295
1296impl fmt::Display for DebuginfoKind {
1297 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1298 f.write_str(self.as_str())
1299 }
1300}
1301
1302#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
1303pub enum SplitDebuginfo {
1304 #[default]
1312 Off,
1313
1314 Packed,
1321
1322 Unpacked,
1329}
1330
1331impl SplitDebuginfo {
1332 fn as_str(&self) -> &'static str {
1333 match self {
1334 SplitDebuginfo::Off => "off",
1335 SplitDebuginfo::Packed => "packed",
1336 SplitDebuginfo::Unpacked => "unpacked",
1337 }
1338 }
1339}
1340
1341impl FromStr for SplitDebuginfo {
1342 type Err = ();
1343
1344 fn from_str(s: &str) -> Result<Self, ()> {
1345 Ok(match s {
1346 "off" => SplitDebuginfo::Off,
1347 "unpacked" => SplitDebuginfo::Unpacked,
1348 "packed" => SplitDebuginfo::Packed,
1349 _ => return Err(()),
1350 })
1351 }
1352}
1353
1354impl ToJson for SplitDebuginfo {
1355 fn to_json(&self) -> Json {
1356 self.as_str().to_json()
1357 }
1358}
1359
1360impl fmt::Display for SplitDebuginfo {
1361 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1362 f.write_str(self.as_str())
1363 }
1364}
1365
1366#[derive(Clone, Debug, PartialEq, Eq)]
1367pub enum StackProbeType {
1368 None,
1370 Inline,
1374 Call,
1376 InlineOrCall { min_llvm_version_for_inline: (u32, u32, u32) },
1379}
1380
1381impl StackProbeType {
1382 fn from_json(json: &Json) -> Result<Self, String> {
1383 let object = json.as_object().ok_or_else(|| "expected a JSON object")?;
1384 let kind = object
1385 .get("kind")
1386 .and_then(|o| o.as_str())
1387 .ok_or_else(|| "expected `kind` to be a string")?;
1388 match kind {
1389 "none" => Ok(StackProbeType::None),
1390 "inline" => Ok(StackProbeType::Inline),
1391 "call" => Ok(StackProbeType::Call),
1392 "inline-or-call" => {
1393 let min_version = object
1394 .get("min-llvm-version-for-inline")
1395 .and_then(|o| o.as_array())
1396 .ok_or_else(|| "expected `min-llvm-version-for-inline` to be an array")?;
1397 let mut iter = min_version.into_iter().map(|v| {
1398 let int = v.as_u64().ok_or_else(
1399 || "expected `min-llvm-version-for-inline` values to be integers",
1400 )?;
1401 u32::try_from(int)
1402 .map_err(|_| "`min-llvm-version-for-inline` values don't convert to u32")
1403 });
1404 let min_llvm_version_for_inline = (
1405 iter.next().unwrap_or(Ok(11))?,
1406 iter.next().unwrap_or(Ok(0))?,
1407 iter.next().unwrap_or(Ok(0))?,
1408 );
1409 Ok(StackProbeType::InlineOrCall { min_llvm_version_for_inline })
1410 }
1411 _ => Err(String::from(
1412 "`kind` expected to be one of `none`, `inline`, `call` or `inline-or-call`",
1413 )),
1414 }
1415 }
1416}
1417
1418impl ToJson for StackProbeType {
1419 fn to_json(&self) -> Json {
1420 Json::Object(match self {
1421 StackProbeType::None => {
1422 [(String::from("kind"), "none".to_json())].into_iter().collect()
1423 }
1424 StackProbeType::Inline => {
1425 [(String::from("kind"), "inline".to_json())].into_iter().collect()
1426 }
1427 StackProbeType::Call => {
1428 [(String::from("kind"), "call".to_json())].into_iter().collect()
1429 }
1430 StackProbeType::InlineOrCall { min_llvm_version_for_inline: (maj, min, patch) } => [
1431 (String::from("kind"), "inline-or-call".to_json()),
1432 (
1433 String::from("min-llvm-version-for-inline"),
1434 Json::Array(vec![maj.to_json(), min.to_json(), patch.to_json()]),
1435 ),
1436 ]
1437 .into_iter()
1438 .collect(),
1439 })
1440 }
1441}
1442
1443#[derive(Default, Clone, Copy, PartialEq, Eq, Hash, Encodable, Decodable, HashStable_Generic)]
1444pub struct SanitizerSet(u16);
1445bitflags::bitflags! {
1446 impl SanitizerSet: u16 {
1447 const ADDRESS = 1 << 0;
1448 const LEAK = 1 << 1;
1449 const MEMORY = 1 << 2;
1450 const THREAD = 1 << 3;
1451 const HWADDRESS = 1 << 4;
1452 const CFI = 1 << 5;
1453 const MEMTAG = 1 << 6;
1454 const SHADOWCALLSTACK = 1 << 7;
1455 const KCFI = 1 << 8;
1456 const KERNELADDRESS = 1 << 9;
1457 const SAFESTACK = 1 << 10;
1458 const DATAFLOW = 1 << 11;
1459 }
1460}
1461rustc_data_structures::external_bitflags_debug! { SanitizerSet }
1462
1463impl SanitizerSet {
1464 const MUTUALLY_EXCLUSIVE: &'static [(SanitizerSet, SanitizerSet)] = &[
1467 (SanitizerSet::ADDRESS, SanitizerSet::MEMORY),
1468 (SanitizerSet::ADDRESS, SanitizerSet::THREAD),
1469 (SanitizerSet::ADDRESS, SanitizerSet::HWADDRESS),
1470 (SanitizerSet::ADDRESS, SanitizerSet::MEMTAG),
1471 (SanitizerSet::ADDRESS, SanitizerSet::KERNELADDRESS),
1472 (SanitizerSet::ADDRESS, SanitizerSet::SAFESTACK),
1473 (SanitizerSet::LEAK, SanitizerSet::MEMORY),
1474 (SanitizerSet::LEAK, SanitizerSet::THREAD),
1475 (SanitizerSet::LEAK, SanitizerSet::KERNELADDRESS),
1476 (SanitizerSet::LEAK, SanitizerSet::SAFESTACK),
1477 (SanitizerSet::MEMORY, SanitizerSet::THREAD),
1478 (SanitizerSet::MEMORY, SanitizerSet::HWADDRESS),
1479 (SanitizerSet::MEMORY, SanitizerSet::KERNELADDRESS),
1480 (SanitizerSet::MEMORY, SanitizerSet::SAFESTACK),
1481 (SanitizerSet::THREAD, SanitizerSet::HWADDRESS),
1482 (SanitizerSet::THREAD, SanitizerSet::KERNELADDRESS),
1483 (SanitizerSet::THREAD, SanitizerSet::SAFESTACK),
1484 (SanitizerSet::HWADDRESS, SanitizerSet::MEMTAG),
1485 (SanitizerSet::HWADDRESS, SanitizerSet::KERNELADDRESS),
1486 (SanitizerSet::HWADDRESS, SanitizerSet::SAFESTACK),
1487 (SanitizerSet::CFI, SanitizerSet::KCFI),
1488 (SanitizerSet::MEMTAG, SanitizerSet::KERNELADDRESS),
1489 (SanitizerSet::KERNELADDRESS, SanitizerSet::SAFESTACK),
1490 ];
1491
1492 pub fn as_str(self) -> Option<&'static str> {
1496 Some(match self {
1497 SanitizerSet::ADDRESS => "address",
1498 SanitizerSet::CFI => "cfi",
1499 SanitizerSet::DATAFLOW => "dataflow",
1500 SanitizerSet::KCFI => "kcfi",
1501 SanitizerSet::KERNELADDRESS => "kernel-address",
1502 SanitizerSet::LEAK => "leak",
1503 SanitizerSet::MEMORY => "memory",
1504 SanitizerSet::MEMTAG => "memtag",
1505 SanitizerSet::SAFESTACK => "safestack",
1506 SanitizerSet::SHADOWCALLSTACK => "shadow-call-stack",
1507 SanitizerSet::THREAD => "thread",
1508 SanitizerSet::HWADDRESS => "hwaddress",
1509 _ => return None,
1510 })
1511 }
1512
1513 pub fn mutually_exclusive(self) -> Option<(SanitizerSet, SanitizerSet)> {
1514 Self::MUTUALLY_EXCLUSIVE
1515 .into_iter()
1516 .find(|&(a, b)| self.contains(*a) && self.contains(*b))
1517 .copied()
1518 }
1519}
1520
1521impl fmt::Display for SanitizerSet {
1523 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1524 let mut first = true;
1525 for s in *self {
1526 let name = s.as_str().unwrap_or_else(|| panic!("unrecognized sanitizer {s:?}"));
1527 if !first {
1528 f.write_str(", ")?;
1529 }
1530 f.write_str(name)?;
1531 first = false;
1532 }
1533 Ok(())
1534 }
1535}
1536
1537impl ToJson for SanitizerSet {
1538 fn to_json(&self) -> Json {
1539 self.into_iter()
1540 .map(|v| Some(v.as_str()?.to_json()))
1541 .collect::<Option<Vec<_>>>()
1542 .unwrap_or_default()
1543 .to_json()
1544 }
1545}
1546
1547#[derive(Clone, Copy, PartialEq, Hash, Debug)]
1548pub enum FramePointer {
1549 Always,
1551 NonLeaf,
1554 MayOmit,
1558}
1559
1560impl FramePointer {
1561 #[inline]
1564 pub fn ratchet(&mut self, rhs: FramePointer) -> FramePointer {
1565 *self = match (*self, rhs) {
1566 (FramePointer::Always, _) | (_, FramePointer::Always) => FramePointer::Always,
1567 (FramePointer::NonLeaf, _) | (_, FramePointer::NonLeaf) => FramePointer::NonLeaf,
1568 _ => FramePointer::MayOmit,
1569 };
1570 *self
1571 }
1572}
1573
1574impl FromStr for FramePointer {
1575 type Err = ();
1576 fn from_str(s: &str) -> Result<Self, ()> {
1577 Ok(match s {
1578 "always" => Self::Always,
1579 "non-leaf" => Self::NonLeaf,
1580 "may-omit" => Self::MayOmit,
1581 _ => return Err(()),
1582 })
1583 }
1584}
1585
1586impl ToJson for FramePointer {
1587 fn to_json(&self) -> Json {
1588 match *self {
1589 Self::Always => "always",
1590 Self::NonLeaf => "non-leaf",
1591 Self::MayOmit => "may-omit",
1592 }
1593 .to_json()
1594 }
1595}
1596
1597#[derive(Clone, Copy, Debug, PartialEq, Hash, Eq)]
1599pub enum StackProtector {
1600 None,
1602
1603 Basic,
1608
1609 Strong,
1614
1615 All,
1617}
1618
1619impl StackProtector {
1620 fn as_str(&self) -> &'static str {
1621 match self {
1622 StackProtector::None => "none",
1623 StackProtector::Basic => "basic",
1624 StackProtector::Strong => "strong",
1625 StackProtector::All => "all",
1626 }
1627 }
1628}
1629
1630impl FromStr for StackProtector {
1631 type Err = ();
1632
1633 fn from_str(s: &str) -> Result<StackProtector, ()> {
1634 Ok(match s {
1635 "none" => StackProtector::None,
1636 "basic" => StackProtector::Basic,
1637 "strong" => StackProtector::Strong,
1638 "all" => StackProtector::All,
1639 _ => return Err(()),
1640 })
1641 }
1642}
1643
1644impl fmt::Display for StackProtector {
1645 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1646 f.write_str(self.as_str())
1647 }
1648}
1649
1650#[derive(PartialEq, Clone, Debug)]
1651pub enum BinaryFormat {
1652 Coff,
1653 Elf,
1654 MachO,
1655 Wasm,
1656 Xcoff,
1657}
1658
1659impl BinaryFormat {
1660 pub fn to_object(&self) -> object::BinaryFormat {
1662 match self {
1663 Self::Coff => object::BinaryFormat::Coff,
1664 Self::Elf => object::BinaryFormat::Elf,
1665 Self::MachO => object::BinaryFormat::MachO,
1666 Self::Wasm => object::BinaryFormat::Wasm,
1667 Self::Xcoff => object::BinaryFormat::Xcoff,
1668 }
1669 }
1670}
1671
1672impl FromStr for BinaryFormat {
1673 type Err = ();
1674 fn from_str(s: &str) -> Result<Self, Self::Err> {
1675 match s {
1676 "coff" => Ok(Self::Coff),
1677 "elf" => Ok(Self::Elf),
1678 "mach-o" => Ok(Self::MachO),
1679 "wasm" => Ok(Self::Wasm),
1680 "xcoff" => Ok(Self::Xcoff),
1681 _ => Err(()),
1682 }
1683 }
1684}
1685
1686impl ToJson for BinaryFormat {
1687 fn to_json(&self) -> Json {
1688 match self {
1689 Self::Coff => "coff",
1690 Self::Elf => "elf",
1691 Self::MachO => "mach-o",
1692 Self::Wasm => "wasm",
1693 Self::Xcoff => "xcoff",
1694 }
1695 .to_json()
1696 }
1697}
1698
1699macro_rules! supported_targets {
1700 ( $(($tuple:literal, $module:ident),)+ ) => {
1701 mod targets {
1702 $(pub(crate) mod $module;)+
1703 }
1704
1705 pub static TARGETS: &[&str] = &[$($tuple),+];
1707
1708 fn load_builtin(target: &str) -> Option<Target> {
1709 let t = match target {
1710 $( $tuple => targets::$module::target(), )+
1711 _ => return None,
1712 };
1713 debug!("got builtin target: {:?}", t);
1714 Some(t)
1715 }
1716
1717 fn load_all_builtins() -> impl Iterator<Item = Target> {
1718 [
1719 $( targets::$module::target, )+
1720 ]
1721 .into_iter()
1722 .map(|f| f())
1723 }
1724
1725 #[cfg(test)]
1726 mod tests {
1727 $(
1729 #[test] fn $module() {
1731 crate::spec::targets::$module::target().test_target()
1732 }
1733 )+
1734 }
1735 };
1736}
1737
1738supported_targets! {
1739 ("x86_64-unknown-linux-gnu", x86_64_unknown_linux_gnu),
1740 ("x86_64-unknown-linux-gnux32", x86_64_unknown_linux_gnux32),
1741 ("i686-unknown-linux-gnu", i686_unknown_linux_gnu),
1742 ("i586-unknown-linux-gnu", i586_unknown_linux_gnu),
1743 ("loongarch64-unknown-linux-gnu", loongarch64_unknown_linux_gnu),
1744 ("loongarch64-unknown-linux-musl", loongarch64_unknown_linux_musl),
1745 ("m68k-unknown-linux-gnu", m68k_unknown_linux_gnu),
1746 ("m68k-unknown-none-elf", m68k_unknown_none_elf),
1747 ("csky-unknown-linux-gnuabiv2", csky_unknown_linux_gnuabiv2),
1748 ("csky-unknown-linux-gnuabiv2hf", csky_unknown_linux_gnuabiv2hf),
1749 ("mips-unknown-linux-gnu", mips_unknown_linux_gnu),
1750 ("mips64-unknown-linux-gnuabi64", mips64_unknown_linux_gnuabi64),
1751 ("mips64el-unknown-linux-gnuabi64", mips64el_unknown_linux_gnuabi64),
1752 ("mipsisa32r6-unknown-linux-gnu", mipsisa32r6_unknown_linux_gnu),
1753 ("mipsisa32r6el-unknown-linux-gnu", mipsisa32r6el_unknown_linux_gnu),
1754 ("mipsisa64r6-unknown-linux-gnuabi64", mipsisa64r6_unknown_linux_gnuabi64),
1755 ("mipsisa64r6el-unknown-linux-gnuabi64", mipsisa64r6el_unknown_linux_gnuabi64),
1756 ("mipsel-unknown-linux-gnu", mipsel_unknown_linux_gnu),
1757 ("powerpc-unknown-linux-gnu", powerpc_unknown_linux_gnu),
1758 ("powerpc-unknown-linux-gnuspe", powerpc_unknown_linux_gnuspe),
1759 ("powerpc-unknown-linux-musl", powerpc_unknown_linux_musl),
1760 ("powerpc-unknown-linux-muslspe", powerpc_unknown_linux_muslspe),
1761 ("powerpc64-ibm-aix", powerpc64_ibm_aix),
1762 ("powerpc64-unknown-linux-gnu", powerpc64_unknown_linux_gnu),
1763 ("powerpc64-unknown-linux-musl", powerpc64_unknown_linux_musl),
1764 ("powerpc64le-unknown-linux-gnu", powerpc64le_unknown_linux_gnu),
1765 ("powerpc64le-unknown-linux-musl", powerpc64le_unknown_linux_musl),
1766 ("s390x-unknown-linux-gnu", s390x_unknown_linux_gnu),
1767 ("s390x-unknown-linux-musl", s390x_unknown_linux_musl),
1768 ("sparc-unknown-linux-gnu", sparc_unknown_linux_gnu),
1769 ("sparc64-unknown-linux-gnu", sparc64_unknown_linux_gnu),
1770 ("arm-unknown-linux-gnueabi", arm_unknown_linux_gnueabi),
1771 ("arm-unknown-linux-gnueabihf", arm_unknown_linux_gnueabihf),
1772 ("armeb-unknown-linux-gnueabi", armeb_unknown_linux_gnueabi),
1773 ("arm-unknown-linux-musleabi", arm_unknown_linux_musleabi),
1774 ("arm-unknown-linux-musleabihf", arm_unknown_linux_musleabihf),
1775 ("armv4t-unknown-linux-gnueabi", armv4t_unknown_linux_gnueabi),
1776 ("armv5te-unknown-linux-gnueabi", armv5te_unknown_linux_gnueabi),
1777 ("armv5te-unknown-linux-musleabi", armv5te_unknown_linux_musleabi),
1778 ("armv5te-unknown-linux-uclibceabi", armv5te_unknown_linux_uclibceabi),
1779 ("armv7-unknown-linux-gnueabi", armv7_unknown_linux_gnueabi),
1780 ("armv7-unknown-linux-gnueabihf", armv7_unknown_linux_gnueabihf),
1781 ("thumbv7neon-unknown-linux-gnueabihf", thumbv7neon_unknown_linux_gnueabihf),
1782 ("thumbv7neon-unknown-linux-musleabihf", thumbv7neon_unknown_linux_musleabihf),
1783 ("armv7-unknown-linux-musleabi", armv7_unknown_linux_musleabi),
1784 ("armv7-unknown-linux-musleabihf", armv7_unknown_linux_musleabihf),
1785 ("aarch64-unknown-linux-gnu", aarch64_unknown_linux_gnu),
1786 ("aarch64-unknown-linux-musl", aarch64_unknown_linux_musl),
1787 ("x86_64-unknown-linux-musl", x86_64_unknown_linux_musl),
1788 ("i686-unknown-linux-musl", i686_unknown_linux_musl),
1789 ("i586-unknown-linux-musl", i586_unknown_linux_musl),
1790 ("mips-unknown-linux-musl", mips_unknown_linux_musl),
1791 ("mipsel-unknown-linux-musl", mipsel_unknown_linux_musl),
1792 ("mips64-unknown-linux-muslabi64", mips64_unknown_linux_muslabi64),
1793 ("mips64el-unknown-linux-muslabi64", mips64el_unknown_linux_muslabi64),
1794 ("hexagon-unknown-linux-musl", hexagon_unknown_linux_musl),
1795 ("hexagon-unknown-none-elf", hexagon_unknown_none_elf),
1796
1797 ("mips-unknown-linux-uclibc", mips_unknown_linux_uclibc),
1798 ("mipsel-unknown-linux-uclibc", mipsel_unknown_linux_uclibc),
1799
1800 ("i686-linux-android", i686_linux_android),
1801 ("x86_64-linux-android", x86_64_linux_android),
1802 ("arm-linux-androideabi", arm_linux_androideabi),
1803 ("armv7-linux-androideabi", armv7_linux_androideabi),
1804 ("thumbv7neon-linux-androideabi", thumbv7neon_linux_androideabi),
1805 ("aarch64-linux-android", aarch64_linux_android),
1806 ("riscv64-linux-android", riscv64_linux_android),
1807
1808 ("aarch64-unknown-freebsd", aarch64_unknown_freebsd),
1809 ("armv6-unknown-freebsd", armv6_unknown_freebsd),
1810 ("armv7-unknown-freebsd", armv7_unknown_freebsd),
1811 ("i686-unknown-freebsd", i686_unknown_freebsd),
1812 ("powerpc-unknown-freebsd", powerpc_unknown_freebsd),
1813 ("powerpc64-unknown-freebsd", powerpc64_unknown_freebsd),
1814 ("powerpc64le-unknown-freebsd", powerpc64le_unknown_freebsd),
1815 ("riscv64gc-unknown-freebsd", riscv64gc_unknown_freebsd),
1816 ("x86_64-unknown-freebsd", x86_64_unknown_freebsd),
1817
1818 ("x86_64-unknown-dragonfly", x86_64_unknown_dragonfly),
1819
1820 ("aarch64-unknown-openbsd", aarch64_unknown_openbsd),
1821 ("i686-unknown-openbsd", i686_unknown_openbsd),
1822 ("powerpc-unknown-openbsd", powerpc_unknown_openbsd),
1823 ("powerpc64-unknown-openbsd", powerpc64_unknown_openbsd),
1824 ("riscv64gc-unknown-openbsd", riscv64gc_unknown_openbsd),
1825 ("sparc64-unknown-openbsd", sparc64_unknown_openbsd),
1826 ("x86_64-unknown-openbsd", x86_64_unknown_openbsd),
1827
1828 ("aarch64-unknown-netbsd", aarch64_unknown_netbsd),
1829 ("aarch64_be-unknown-netbsd", aarch64_be_unknown_netbsd),
1830 ("armv6-unknown-netbsd-eabihf", armv6_unknown_netbsd_eabihf),
1831 ("armv7-unknown-netbsd-eabihf", armv7_unknown_netbsd_eabihf),
1832 ("i586-unknown-netbsd", i586_unknown_netbsd),
1833 ("i686-unknown-netbsd", i686_unknown_netbsd),
1834 ("mipsel-unknown-netbsd", mipsel_unknown_netbsd),
1835 ("powerpc-unknown-netbsd", powerpc_unknown_netbsd),
1836 ("riscv64gc-unknown-netbsd", riscv64gc_unknown_netbsd),
1837 ("sparc64-unknown-netbsd", sparc64_unknown_netbsd),
1838 ("x86_64-unknown-netbsd", x86_64_unknown_netbsd),
1839
1840 ("i686-unknown-haiku", i686_unknown_haiku),
1841 ("x86_64-unknown-haiku", x86_64_unknown_haiku),
1842
1843 ("i686-unknown-hurd-gnu", i686_unknown_hurd_gnu),
1844 ("x86_64-unknown-hurd-gnu", x86_64_unknown_hurd_gnu),
1845
1846 ("aarch64-apple-darwin", aarch64_apple_darwin),
1847 ("arm64e-apple-darwin", arm64e_apple_darwin),
1848 ("x86_64-apple-darwin", x86_64_apple_darwin),
1849 ("x86_64h-apple-darwin", x86_64h_apple_darwin),
1850 ("i686-apple-darwin", i686_apple_darwin),
1851
1852 ("aarch64-unknown-fuchsia", aarch64_unknown_fuchsia),
1853 ("riscv64gc-unknown-fuchsia", riscv64gc_unknown_fuchsia),
1854 ("x86_64-unknown-fuchsia", x86_64_unknown_fuchsia),
1855
1856 ("avr-none", avr_none),
1857
1858 ("x86_64-unknown-l4re-uclibc", x86_64_unknown_l4re_uclibc),
1859
1860 ("aarch64-unknown-redox", aarch64_unknown_redox),
1861 ("i586-unknown-redox", i586_unknown_redox),
1862 ("x86_64-unknown-redox", x86_64_unknown_redox),
1863
1864 ("i386-apple-ios", i386_apple_ios),
1865 ("x86_64-apple-ios", x86_64_apple_ios),
1866 ("aarch64-apple-ios", aarch64_apple_ios),
1867 ("arm64e-apple-ios", arm64e_apple_ios),
1868 ("armv7s-apple-ios", armv7s_apple_ios),
1869 ("x86_64-apple-ios-macabi", x86_64_apple_ios_macabi),
1870 ("aarch64-apple-ios-macabi", aarch64_apple_ios_macabi),
1871 ("aarch64-apple-ios-sim", aarch64_apple_ios_sim),
1872
1873 ("aarch64-apple-tvos", aarch64_apple_tvos),
1874 ("aarch64-apple-tvos-sim", aarch64_apple_tvos_sim),
1875 ("arm64e-apple-tvos", arm64e_apple_tvos),
1876 ("x86_64-apple-tvos", x86_64_apple_tvos),
1877
1878 ("armv7k-apple-watchos", armv7k_apple_watchos),
1879 ("arm64_32-apple-watchos", arm64_32_apple_watchos),
1880 ("x86_64-apple-watchos-sim", x86_64_apple_watchos_sim),
1881 ("aarch64-apple-watchos", aarch64_apple_watchos),
1882 ("aarch64-apple-watchos-sim", aarch64_apple_watchos_sim),
1883
1884 ("aarch64-apple-visionos", aarch64_apple_visionos),
1885 ("aarch64-apple-visionos-sim", aarch64_apple_visionos_sim),
1886
1887 ("armebv7r-none-eabi", armebv7r_none_eabi),
1888 ("armebv7r-none-eabihf", armebv7r_none_eabihf),
1889 ("armv7r-none-eabi", armv7r_none_eabi),
1890 ("armv7r-none-eabihf", armv7r_none_eabihf),
1891 ("armv8r-none-eabihf", armv8r_none_eabihf),
1892
1893 ("armv7-rtems-eabihf", armv7_rtems_eabihf),
1894
1895 ("x86_64-pc-solaris", x86_64_pc_solaris),
1896 ("sparcv9-sun-solaris", sparcv9_sun_solaris),
1897
1898 ("x86_64-unknown-illumos", x86_64_unknown_illumos),
1899 ("aarch64-unknown-illumos", aarch64_unknown_illumos),
1900
1901 ("x86_64-pc-windows-gnu", x86_64_pc_windows_gnu),
1902 ("x86_64-uwp-windows-gnu", x86_64_uwp_windows_gnu),
1903 ("x86_64-win7-windows-gnu", x86_64_win7_windows_gnu),
1904 ("i686-pc-windows-gnu", i686_pc_windows_gnu),
1905 ("i686-uwp-windows-gnu", i686_uwp_windows_gnu),
1906 ("i686-win7-windows-gnu", i686_win7_windows_gnu),
1907
1908 ("aarch64-pc-windows-gnullvm", aarch64_pc_windows_gnullvm),
1909 ("i686-pc-windows-gnullvm", i686_pc_windows_gnullvm),
1910 ("x86_64-pc-windows-gnullvm", x86_64_pc_windows_gnullvm),
1911
1912 ("aarch64-pc-windows-msvc", aarch64_pc_windows_msvc),
1913 ("aarch64-uwp-windows-msvc", aarch64_uwp_windows_msvc),
1914 ("arm64ec-pc-windows-msvc", arm64ec_pc_windows_msvc),
1915 ("x86_64-pc-windows-msvc", x86_64_pc_windows_msvc),
1916 ("x86_64-uwp-windows-msvc", x86_64_uwp_windows_msvc),
1917 ("x86_64-win7-windows-msvc", x86_64_win7_windows_msvc),
1918 ("i686-pc-windows-msvc", i686_pc_windows_msvc),
1919 ("i686-uwp-windows-msvc", i686_uwp_windows_msvc),
1920 ("i686-win7-windows-msvc", i686_win7_windows_msvc),
1921 ("thumbv7a-pc-windows-msvc", thumbv7a_pc_windows_msvc),
1922 ("thumbv7a-uwp-windows-msvc", thumbv7a_uwp_windows_msvc),
1923
1924 ("wasm32-unknown-emscripten", wasm32_unknown_emscripten),
1925 ("wasm32-unknown-unknown", wasm32_unknown_unknown),
1926 ("wasm32v1-none", wasm32v1_none),
1927 ("wasm32-wasip1", wasm32_wasip1),
1928 ("wasm32-wasip2", wasm32_wasip2),
1929 ("wasm32-wasip1-threads", wasm32_wasip1_threads),
1930 ("wasm32-wali-linux-musl", wasm32_wali_linux_musl),
1931 ("wasm64-unknown-unknown", wasm64_unknown_unknown),
1932
1933 ("thumbv6m-none-eabi", thumbv6m_none_eabi),
1934 ("thumbv7m-none-eabi", thumbv7m_none_eabi),
1935 ("thumbv7em-none-eabi", thumbv7em_none_eabi),
1936 ("thumbv7em-none-eabihf", thumbv7em_none_eabihf),
1937 ("thumbv8m.base-none-eabi", thumbv8m_base_none_eabi),
1938 ("thumbv8m.main-none-eabi", thumbv8m_main_none_eabi),
1939 ("thumbv8m.main-none-eabihf", thumbv8m_main_none_eabihf),
1940
1941 ("armv7a-none-eabi", armv7a_none_eabi),
1942 ("armv7a-none-eabihf", armv7a_none_eabihf),
1943 ("armv7a-nuttx-eabi", armv7a_nuttx_eabi),
1944 ("armv7a-nuttx-eabihf", armv7a_nuttx_eabihf),
1945
1946 ("msp430-none-elf", msp430_none_elf),
1947
1948 ("aarch64-unknown-hermit", aarch64_unknown_hermit),
1949 ("riscv64gc-unknown-hermit", riscv64gc_unknown_hermit),
1950 ("x86_64-unknown-hermit", x86_64_unknown_hermit),
1951
1952 ("x86_64-unikraft-linux-musl", x86_64_unikraft_linux_musl),
1953
1954 ("armv7-unknown-trusty", armv7_unknown_trusty),
1955 ("aarch64-unknown-trusty", aarch64_unknown_trusty),
1956 ("x86_64-unknown-trusty", x86_64_unknown_trusty),
1957
1958 ("riscv32i-unknown-none-elf", riscv32i_unknown_none_elf),
1959 ("riscv32im-risc0-zkvm-elf", riscv32im_risc0_zkvm_elf),
1960 ("riscv32im-unknown-none-elf", riscv32im_unknown_none_elf),
1961 ("riscv32ima-unknown-none-elf", riscv32ima_unknown_none_elf),
1962 ("riscv32imc-unknown-none-elf", riscv32imc_unknown_none_elf),
1963 ("riscv32imc-esp-espidf", riscv32imc_esp_espidf),
1964 ("riscv32imac-esp-espidf", riscv32imac_esp_espidf),
1965 ("riscv32imafc-esp-espidf", riscv32imafc_esp_espidf),
1966
1967 ("riscv32e-unknown-none-elf", riscv32e_unknown_none_elf),
1968 ("riscv32em-unknown-none-elf", riscv32em_unknown_none_elf),
1969 ("riscv32emc-unknown-none-elf", riscv32emc_unknown_none_elf),
1970
1971 ("riscv32imac-unknown-none-elf", riscv32imac_unknown_none_elf),
1972 ("riscv32imafc-unknown-none-elf", riscv32imafc_unknown_none_elf),
1973 ("riscv32imac-unknown-xous-elf", riscv32imac_unknown_xous_elf),
1974 ("riscv32gc-unknown-linux-gnu", riscv32gc_unknown_linux_gnu),
1975 ("riscv32gc-unknown-linux-musl", riscv32gc_unknown_linux_musl),
1976 ("riscv64imac-unknown-none-elf", riscv64imac_unknown_none_elf),
1977 ("riscv64gc-unknown-none-elf", riscv64gc_unknown_none_elf),
1978 ("riscv64gc-unknown-linux-gnu", riscv64gc_unknown_linux_gnu),
1979 ("riscv64gc-unknown-linux-musl", riscv64gc_unknown_linux_musl),
1980
1981 ("sparc-unknown-none-elf", sparc_unknown_none_elf),
1982
1983 ("loongarch64-unknown-none", loongarch64_unknown_none),
1984 ("loongarch64-unknown-none-softfloat", loongarch64_unknown_none_softfloat),
1985
1986 ("aarch64-unknown-none", aarch64_unknown_none),
1987 ("aarch64-unknown-none-softfloat", aarch64_unknown_none_softfloat),
1988 ("aarch64-unknown-nuttx", aarch64_unknown_nuttx),
1989
1990 ("x86_64-fortanix-unknown-sgx", x86_64_fortanix_unknown_sgx),
1991
1992 ("x86_64-unknown-uefi", x86_64_unknown_uefi),
1993 ("i686-unknown-uefi", i686_unknown_uefi),
1994 ("aarch64-unknown-uefi", aarch64_unknown_uefi),
1995
1996 ("nvptx64-nvidia-cuda", nvptx64_nvidia_cuda),
1997
1998 ("amdgcn-amd-amdhsa", amdgcn_amd_amdhsa),
1999
2000 ("xtensa-esp32-none-elf", xtensa_esp32_none_elf),
2001 ("xtensa-esp32-espidf", xtensa_esp32_espidf),
2002 ("xtensa-esp32s2-none-elf", xtensa_esp32s2_none_elf),
2003 ("xtensa-esp32s2-espidf", xtensa_esp32s2_espidf),
2004 ("xtensa-esp32s3-none-elf", xtensa_esp32s3_none_elf),
2005 ("xtensa-esp32s3-espidf", xtensa_esp32s3_espidf),
2006
2007 ("i686-wrs-vxworks", i686_wrs_vxworks),
2008 ("x86_64-wrs-vxworks", x86_64_wrs_vxworks),
2009 ("armv7-wrs-vxworks-eabihf", armv7_wrs_vxworks_eabihf),
2010 ("aarch64-wrs-vxworks", aarch64_wrs_vxworks),
2011 ("powerpc-wrs-vxworks", powerpc_wrs_vxworks),
2012 ("powerpc-wrs-vxworks-spe", powerpc_wrs_vxworks_spe),
2013 ("powerpc64-wrs-vxworks", powerpc64_wrs_vxworks),
2014 ("riscv32-wrs-vxworks", riscv32_wrs_vxworks),
2015 ("riscv64-wrs-vxworks", riscv64_wrs_vxworks),
2016
2017 ("aarch64-kmc-solid_asp3", aarch64_kmc_solid_asp3),
2018 ("armv7a-kmc-solid_asp3-eabi", armv7a_kmc_solid_asp3_eabi),
2019 ("armv7a-kmc-solid_asp3-eabihf", armv7a_kmc_solid_asp3_eabihf),
2020
2021 ("mipsel-sony-psp", mipsel_sony_psp),
2022 ("mipsel-sony-psx", mipsel_sony_psx),
2023 ("mipsel-unknown-none", mipsel_unknown_none),
2024 ("mips-mti-none-elf", mips_mti_none_elf),
2025 ("mipsel-mti-none-elf", mipsel_mti_none_elf),
2026 ("thumbv4t-none-eabi", thumbv4t_none_eabi),
2027 ("armv4t-none-eabi", armv4t_none_eabi),
2028 ("thumbv5te-none-eabi", thumbv5te_none_eabi),
2029 ("armv5te-none-eabi", armv5te_none_eabi),
2030
2031 ("aarch64_be-unknown-linux-gnu", aarch64_be_unknown_linux_gnu),
2032 ("aarch64-unknown-linux-gnu_ilp32", aarch64_unknown_linux_gnu_ilp32),
2033 ("aarch64_be-unknown-linux-gnu_ilp32", aarch64_be_unknown_linux_gnu_ilp32),
2034
2035 ("bpfeb-unknown-none", bpfeb_unknown_none),
2036 ("bpfel-unknown-none", bpfel_unknown_none),
2037
2038 ("armv6k-nintendo-3ds", armv6k_nintendo_3ds),
2039
2040 ("aarch64-nintendo-switch-freestanding", aarch64_nintendo_switch_freestanding),
2041
2042 ("armv7-sony-vita-newlibeabihf", armv7_sony_vita_newlibeabihf),
2043
2044 ("armv7-unknown-linux-uclibceabi", armv7_unknown_linux_uclibceabi),
2045 ("armv7-unknown-linux-uclibceabihf", armv7_unknown_linux_uclibceabihf),
2046
2047 ("x86_64-unknown-none", x86_64_unknown_none),
2048
2049 ("aarch64-unknown-teeos", aarch64_unknown_teeos),
2050
2051 ("mips64-openwrt-linux-musl", mips64_openwrt_linux_musl),
2052
2053 ("aarch64-unknown-nto-qnx700", aarch64_unknown_nto_qnx700),
2054 ("aarch64-unknown-nto-qnx710", aarch64_unknown_nto_qnx710),
2055 ("aarch64-unknown-nto-qnx710_iosock", aarch64_unknown_nto_qnx710_iosock),
2056 ("aarch64-unknown-nto-qnx800", aarch64_unknown_nto_qnx800),
2057 ("x86_64-pc-nto-qnx710", x86_64_pc_nto_qnx710),
2058 ("x86_64-pc-nto-qnx710_iosock", x86_64_pc_nto_qnx710_iosock),
2059 ("x86_64-pc-nto-qnx800", x86_64_pc_nto_qnx800),
2060 ("i686-pc-nto-qnx700", i686_pc_nto_qnx700),
2061
2062 ("aarch64-unknown-linux-ohos", aarch64_unknown_linux_ohos),
2063 ("armv7-unknown-linux-ohos", armv7_unknown_linux_ohos),
2064 ("loongarch64-unknown-linux-ohos", loongarch64_unknown_linux_ohos),
2065 ("x86_64-unknown-linux-ohos", x86_64_unknown_linux_ohos),
2066
2067 ("x86_64-unknown-linux-none", x86_64_unknown_linux_none),
2068
2069 ("thumbv6m-nuttx-eabi", thumbv6m_nuttx_eabi),
2070 ("thumbv7a-nuttx-eabi", thumbv7a_nuttx_eabi),
2071 ("thumbv7a-nuttx-eabihf", thumbv7a_nuttx_eabihf),
2072 ("thumbv7m-nuttx-eabi", thumbv7m_nuttx_eabi),
2073 ("thumbv7em-nuttx-eabi", thumbv7em_nuttx_eabi),
2074 ("thumbv7em-nuttx-eabihf", thumbv7em_nuttx_eabihf),
2075 ("thumbv8m.base-nuttx-eabi", thumbv8m_base_nuttx_eabi),
2076 ("thumbv8m.main-nuttx-eabi", thumbv8m_main_nuttx_eabi),
2077 ("thumbv8m.main-nuttx-eabihf", thumbv8m_main_nuttx_eabihf),
2078 ("riscv32imc-unknown-nuttx-elf", riscv32imc_unknown_nuttx_elf),
2079 ("riscv32imac-unknown-nuttx-elf", riscv32imac_unknown_nuttx_elf),
2080 ("riscv32imafc-unknown-nuttx-elf", riscv32imafc_unknown_nuttx_elf),
2081 ("riscv64imac-unknown-nuttx-elf", riscv64imac_unknown_nuttx_elf),
2082 ("riscv64gc-unknown-nuttx-elf", riscv64gc_unknown_nuttx_elf),
2083 ("x86_64-lynx-lynxos178", x86_64_lynx_lynxos178),
2084
2085 ("x86_64-pc-cygwin", x86_64_pc_cygwin),
2086}
2087
2088macro_rules! cvs {
2090 () => {
2091 ::std::borrow::Cow::Borrowed(&[])
2092 };
2093 ($($x:expr),+ $(,)?) => {
2094 ::std::borrow::Cow::Borrowed(&[
2095 $(
2096 ::std::borrow::Cow::Borrowed($x),
2097 )*
2098 ])
2099 };
2100}
2101
2102pub(crate) use cvs;
2103
2104#[derive(Debug, PartialEq)]
2108pub struct TargetWarnings {
2109 unused_fields: Vec<String>,
2110 incorrect_type: Vec<String>,
2111}
2112
2113impl TargetWarnings {
2114 pub fn empty() -> Self {
2115 Self { unused_fields: Vec::new(), incorrect_type: Vec::new() }
2116 }
2117
2118 pub fn warning_messages(&self) -> Vec<String> {
2119 let mut warnings = vec![];
2120 if !self.unused_fields.is_empty() {
2121 warnings.push(format!(
2122 "target json file contains unused fields: {}",
2123 self.unused_fields.join(", ")
2124 ));
2125 }
2126 if !self.incorrect_type.is_empty() {
2127 warnings.push(format!(
2128 "target json file contains fields whose value doesn't have the correct json type: {}",
2129 self.incorrect_type.join(", ")
2130 ));
2131 }
2132 warnings
2133 }
2134}
2135
2136#[derive(Copy, Clone, Debug, PartialEq)]
2139enum TargetKind {
2140 Json,
2141 Builtin,
2142}
2143
2144#[derive(PartialEq, Clone, Debug)]
2148pub struct Target {
2149 pub llvm_target: StaticCow<str>,
2156 pub metadata: TargetMetadata,
2159 pub pointer_width: u32,
2161 pub arch: StaticCow<str>,
2164 pub data_layout: StaticCow<str>,
2166 pub options: TargetOptions,
2168}
2169
2170#[derive(Default, PartialEq, Clone, Debug)]
2174pub struct TargetMetadata {
2175 pub description: Option<StaticCow<str>>,
2178 pub tier: Option<u64>,
2180 pub host_tools: Option<bool>,
2182 pub std: Option<bool>,
2185}
2186
2187impl Target {
2188 pub fn parse_data_layout(&self) -> Result<TargetDataLayout, TargetDataLayoutErrors<'_>> {
2189 let mut dl = TargetDataLayout::parse_from_llvm_datalayout_string(&self.data_layout)?;
2190
2191 if dl.endian != self.endian {
2193 return Err(TargetDataLayoutErrors::InconsistentTargetArchitecture {
2194 dl: dl.endian.as_str(),
2195 target: self.endian.as_str(),
2196 });
2197 }
2198
2199 let target_pointer_width: u64 = self.pointer_width.into();
2200 if dl.pointer_size.bits() != target_pointer_width {
2201 return Err(TargetDataLayoutErrors::InconsistentTargetPointerWidth {
2202 pointer_size: dl.pointer_size.bits(),
2203 target: self.pointer_width,
2204 });
2205 }
2206
2207 dl.c_enum_min_size = self
2208 .c_enum_min_bits
2209 .map_or_else(
2210 || {
2211 self.c_int_width
2212 .parse()
2213 .map_err(|_| String::from("failed to parse c_int_width"))
2214 },
2215 Ok,
2216 )
2217 .and_then(|i| Integer::from_size(Size::from_bits(i)))
2218 .map_err(|err| TargetDataLayoutErrors::InvalidBitsSize { err })?;
2219
2220 Ok(dl)
2221 }
2222}
2223
2224pub trait HasTargetSpec {
2225 fn target_spec(&self) -> &Target;
2226}
2227
2228impl HasTargetSpec for Target {
2229 #[inline]
2230 fn target_spec(&self) -> &Target {
2231 self
2232 }
2233}
2234
2235#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
2237pub enum WasmCAbi {
2238 Spec,
2240 Legacy {
2242 with_lint: bool,
2244 },
2245}
2246
2247pub trait HasWasmCAbiOpt {
2248 fn wasm_c_abi_opt(&self) -> WasmCAbi;
2249}
2250
2251#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
2253pub struct X86Abi {
2254 pub regparm: Option<u32>,
2257 pub reg_struct_return: bool,
2259}
2260
2261pub trait HasX86AbiOpt {
2262 fn x86_abi_opt(&self) -> X86Abi;
2263}
2264
2265type StaticCow<T> = Cow<'static, T>;
2266
2267#[derive(PartialEq, Clone, Debug)]
2276pub struct TargetOptions {
2277 pub endian: Endian,
2279 pub c_int_width: StaticCow<str>,
2281 pub os: StaticCow<str>,
2286 pub env: StaticCow<str>,
2288 pub abi: StaticCow<str>,
2293 pub vendor: StaticCow<str>,
2295
2296 pub linker: Option<StaticCow<str>>,
2298 pub linker_flavor: LinkerFlavor,
2301 linker_flavor_json: LinkerFlavorCli,
2302 lld_flavor_json: LldFlavor,
2303 linker_is_gnu_json: bool,
2304
2305 pub pre_link_objects: CrtObjects,
2307 pub post_link_objects: CrtObjects,
2308 pub pre_link_objects_self_contained: CrtObjects,
2310 pub post_link_objects_self_contained: CrtObjects,
2311 pub link_self_contained: LinkSelfContainedDefault,
2314
2315 pub pre_link_args: LinkArgs,
2317 pre_link_args_json: LinkArgsCli,
2318 pub late_link_args: LinkArgs,
2322 late_link_args_json: LinkArgsCli,
2323 pub late_link_args_dynamic: LinkArgs,
2326 late_link_args_dynamic_json: LinkArgsCli,
2327 pub late_link_args_static: LinkArgs,
2330 late_link_args_static_json: LinkArgsCli,
2331 pub post_link_args: LinkArgs,
2334 post_link_args_json: LinkArgsCli,
2335
2336 pub link_script: Option<StaticCow<str>>,
2340 pub link_env: StaticCow<[(StaticCow<str>, StaticCow<str>)]>,
2342 pub link_env_remove: StaticCow<[StaticCow<str>]>,
2344
2345 pub asm_args: StaticCow<[StaticCow<str>]>,
2347
2348 pub cpu: StaticCow<str>,
2351 pub need_explicit_cpu: bool,
2354 pub features: StaticCow<str>,
2363 pub direct_access_external_data: Option<bool>,
2365 pub dynamic_linking: bool,
2367 pub dll_tls_export: bool,
2369 pub only_cdylib: bool,
2371 pub executables: bool,
2373 pub relocation_model: RelocModel,
2376 pub code_model: Option<CodeModel>,
2379 pub tls_model: TlsModel,
2382 pub disable_redzone: bool,
2384 pub frame_pointer: FramePointer,
2386 pub function_sections: bool,
2388 pub dll_prefix: StaticCow<str>,
2390 pub dll_suffix: StaticCow<str>,
2392 pub exe_suffix: StaticCow<str>,
2394 pub staticlib_prefix: StaticCow<str>,
2396 pub staticlib_suffix: StaticCow<str>,
2398 pub families: StaticCow<[StaticCow<str>]>,
2404 pub abi_return_struct_as_int: bool,
2406 pub is_like_aix: bool,
2409 pub is_like_darwin: bool,
2414 pub is_like_solaris: bool,
2418 pub is_like_windows: bool,
2426 pub is_like_msvc: bool,
2436 pub is_like_wasm: bool,
2438 pub is_like_android: bool,
2440 pub binary_format: BinaryFormat,
2442 pub default_dwarf_version: u32,
2445 pub allows_weak_linkage: bool,
2452 pub has_rpath: bool,
2454 pub no_default_libraries: bool,
2457 pub position_independent_executables: bool,
2463 pub static_position_independent_executables: bool,
2465 pub plt_by_default: bool,
2468 pub relro_level: RelroLevel,
2472 pub archive_format: StaticCow<str>,
2477 pub allow_asm: bool,
2479 pub main_needs_argc_argv: bool,
2482
2483 pub has_thread_local: bool,
2485 pub obj_is_bitcode: bool,
2489 pub bitcode_llvm_cmdline: StaticCow<str>,
2491
2492 pub min_atomic_width: Option<u64>,
2494
2495 pub max_atomic_width: Option<u64>,
2497
2498 pub atomic_cas: bool,
2500
2501 pub panic_strategy: PanicStrategy,
2503
2504 pub crt_static_allows_dylibs: bool,
2506 pub crt_static_default: bool,
2508 pub crt_static_respected: bool,
2510
2511 pub stack_probes: StackProbeType,
2513
2514 pub min_global_align: Option<u64>,
2516
2517 pub default_codegen_units: Option<u64>,
2519
2520 pub default_codegen_backend: Option<StaticCow<str>>,
2530
2531 pub trap_unreachable: bool,
2534
2535 pub requires_lto: bool,
2538
2539 pub singlethread: bool,
2541
2542 pub no_builtins: bool,
2545
2546 pub default_visibility: Option<SymbolVisibility>,
2552
2553 pub emit_debug_gdb_scripts: bool,
2555
2556 pub requires_uwtable: bool,
2560
2561 pub default_uwtable: bool,
2564
2565 pub simd_types_indirect: bool,
2570
2571 pub limit_rdylib_exports: bool,
2573
2574 pub override_export_symbols: Option<StaticCow<[StaticCow<str>]>>,
2577
2578 pub merge_functions: MergeFunctions,
2585
2586 pub mcount: StaticCow<str>,
2588
2589 pub llvm_mcount_intrinsic: Option<StaticCow<str>>,
2591
2592 pub llvm_abiname: StaticCow<str>,
2595
2596 pub llvm_floatabi: Option<FloatAbi>,
2603
2604 pub rustc_abi: Option<RustcAbi>,
2609
2610 pub relax_elf_relocations: bool,
2612
2613 pub llvm_args: StaticCow<[StaticCow<str>]>,
2615
2616 pub use_ctors_section: bool,
2619
2620 pub eh_frame_header: bool,
2624
2625 pub has_thumb_interworking: bool,
2628
2629 pub debuginfo_kind: DebuginfoKind,
2631 pub split_debuginfo: SplitDebuginfo,
2634 pub supported_split_debuginfo: StaticCow<[SplitDebuginfo]>,
2636
2637 pub supported_sanitizers: SanitizerSet,
2643
2644 pub c_enum_min_bits: Option<u64>,
2646
2647 pub generate_arange_section: bool,
2649
2650 pub supports_stack_protector: bool,
2653
2654 pub entry_name: StaticCow<str>,
2657
2658 pub entry_abi: Conv,
2661
2662 pub supports_xray: bool,
2664
2665 small_data_threshold_support: SmallDataThresholdSupport,
2667}
2668
2669fn add_link_args_iter(
2672 link_args: &mut LinkArgs,
2673 flavor: LinkerFlavor,
2674 args: impl Iterator<Item = StaticCow<str>> + Clone,
2675) {
2676 let mut insert = |flavor| link_args.entry(flavor).or_default().extend(args.clone());
2677 insert(flavor);
2678 match flavor {
2679 LinkerFlavor::Gnu(cc, lld) => {
2680 assert_eq!(lld, Lld::No);
2681 insert(LinkerFlavor::Gnu(cc, Lld::Yes));
2682 }
2683 LinkerFlavor::Darwin(cc, lld) => {
2684 assert_eq!(lld, Lld::No);
2685 insert(LinkerFlavor::Darwin(cc, Lld::Yes));
2686 }
2687 LinkerFlavor::Msvc(lld) => {
2688 assert_eq!(lld, Lld::No);
2689 insert(LinkerFlavor::Msvc(Lld::Yes));
2690 }
2691 LinkerFlavor::WasmLld(..)
2692 | LinkerFlavor::Unix(..)
2693 | LinkerFlavor::EmCc
2694 | LinkerFlavor::Bpf
2695 | LinkerFlavor::Llbc
2696 | LinkerFlavor::Ptx => {}
2697 }
2698}
2699
2700fn add_link_args(link_args: &mut LinkArgs, flavor: LinkerFlavor, args: &[&'static str]) {
2701 add_link_args_iter(link_args, flavor, args.iter().copied().map(Cow::Borrowed))
2702}
2703
2704impl TargetOptions {
2705 pub fn supports_comdat(&self) -> bool {
2706 !self.is_like_aix && !self.is_like_darwin
2708 }
2709}
2710
2711impl TargetOptions {
2712 fn link_args(flavor: LinkerFlavor, args: &[&'static str]) -> LinkArgs {
2713 let mut link_args = LinkArgs::new();
2714 add_link_args(&mut link_args, flavor, args);
2715 link_args
2716 }
2717
2718 fn add_pre_link_args(&mut self, flavor: LinkerFlavor, args: &[&'static str]) {
2719 add_link_args(&mut self.pre_link_args, flavor, args);
2720 }
2721
2722 fn update_from_cli(&mut self) {
2723 self.linker_flavor = LinkerFlavor::from_cli_json(
2724 self.linker_flavor_json,
2725 self.lld_flavor_json,
2726 self.linker_is_gnu_json,
2727 );
2728 for (args, args_json) in [
2729 (&mut self.pre_link_args, &self.pre_link_args_json),
2730 (&mut self.late_link_args, &self.late_link_args_json),
2731 (&mut self.late_link_args_dynamic, &self.late_link_args_dynamic_json),
2732 (&mut self.late_link_args_static, &self.late_link_args_static_json),
2733 (&mut self.post_link_args, &self.post_link_args_json),
2734 ] {
2735 args.clear();
2736 for (flavor, args_json) in args_json {
2737 let linker_flavor = self.linker_flavor.with_cli_hints(*flavor);
2738 let linker_flavor = match linker_flavor {
2740 LinkerFlavor::Gnu(cc, _) => LinkerFlavor::Gnu(cc, Lld::No),
2741 LinkerFlavor::Darwin(cc, _) => LinkerFlavor::Darwin(cc, Lld::No),
2742 LinkerFlavor::Msvc(_) => LinkerFlavor::Msvc(Lld::No),
2743 _ => linker_flavor,
2744 };
2745 if !args.contains_key(&linker_flavor) {
2746 add_link_args_iter(args, linker_flavor, args_json.iter().cloned());
2747 }
2748 }
2749 }
2750 }
2751
2752 fn update_to_cli(&mut self) {
2753 self.linker_flavor_json = self.linker_flavor.to_cli_counterpart();
2754 self.lld_flavor_json = self.linker_flavor.lld_flavor();
2755 self.linker_is_gnu_json = self.linker_flavor.is_gnu();
2756 for (args, args_json) in [
2757 (&self.pre_link_args, &mut self.pre_link_args_json),
2758 (&self.late_link_args, &mut self.late_link_args_json),
2759 (&self.late_link_args_dynamic, &mut self.late_link_args_dynamic_json),
2760 (&self.late_link_args_static, &mut self.late_link_args_static_json),
2761 (&self.post_link_args, &mut self.post_link_args_json),
2762 ] {
2763 *args_json = args
2764 .iter()
2765 .map(|(flavor, args)| (flavor.to_cli_counterpart(), args.clone()))
2766 .collect();
2767 }
2768 }
2769}
2770
2771impl Default for TargetOptions {
2772 fn default() -> TargetOptions {
2775 TargetOptions {
2776 endian: Endian::Little,
2777 c_int_width: "32".into(),
2778 os: "none".into(),
2779 env: "".into(),
2780 abi: "".into(),
2781 vendor: "unknown".into(),
2782 linker: option_env!("CFG_DEFAULT_LINKER").map(|s| s.into()),
2783 linker_flavor: LinkerFlavor::Gnu(Cc::Yes, Lld::No),
2784 linker_flavor_json: LinkerFlavorCli::Gcc,
2785 lld_flavor_json: LldFlavor::Ld,
2786 linker_is_gnu_json: true,
2787 link_script: None,
2788 asm_args: cvs![],
2789 cpu: "generic".into(),
2790 need_explicit_cpu: false,
2791 features: "".into(),
2792 direct_access_external_data: None,
2793 dynamic_linking: false,
2794 dll_tls_export: true,
2795 only_cdylib: false,
2796 executables: true,
2797 relocation_model: RelocModel::Pic,
2798 code_model: None,
2799 tls_model: TlsModel::GeneralDynamic,
2800 disable_redzone: false,
2801 frame_pointer: FramePointer::MayOmit,
2802 function_sections: true,
2803 dll_prefix: "lib".into(),
2804 dll_suffix: ".so".into(),
2805 exe_suffix: "".into(),
2806 staticlib_prefix: "lib".into(),
2807 staticlib_suffix: ".a".into(),
2808 families: cvs![],
2809 abi_return_struct_as_int: false,
2810 is_like_aix: false,
2811 is_like_darwin: false,
2812 is_like_solaris: false,
2813 is_like_windows: false,
2814 is_like_msvc: false,
2815 is_like_wasm: false,
2816 is_like_android: false,
2817 binary_format: BinaryFormat::Elf,
2818 default_dwarf_version: 4,
2819 allows_weak_linkage: true,
2820 has_rpath: false,
2821 no_default_libraries: true,
2822 position_independent_executables: false,
2823 static_position_independent_executables: false,
2824 plt_by_default: true,
2825 relro_level: RelroLevel::None,
2826 pre_link_objects: Default::default(),
2827 post_link_objects: Default::default(),
2828 pre_link_objects_self_contained: Default::default(),
2829 post_link_objects_self_contained: Default::default(),
2830 link_self_contained: LinkSelfContainedDefault::False,
2831 pre_link_args: LinkArgs::new(),
2832 pre_link_args_json: LinkArgsCli::new(),
2833 late_link_args: LinkArgs::new(),
2834 late_link_args_json: LinkArgsCli::new(),
2835 late_link_args_dynamic: LinkArgs::new(),
2836 late_link_args_dynamic_json: LinkArgsCli::new(),
2837 late_link_args_static: LinkArgs::new(),
2838 late_link_args_static_json: LinkArgsCli::new(),
2839 post_link_args: LinkArgs::new(),
2840 post_link_args_json: LinkArgsCli::new(),
2841 link_env: cvs![],
2842 link_env_remove: cvs![],
2843 archive_format: "gnu".into(),
2844 main_needs_argc_argv: true,
2845 allow_asm: true,
2846 has_thread_local: false,
2847 obj_is_bitcode: false,
2848 bitcode_llvm_cmdline: "".into(),
2849 min_atomic_width: None,
2850 max_atomic_width: None,
2851 atomic_cas: true,
2852 panic_strategy: PanicStrategy::Unwind,
2853 crt_static_allows_dylibs: false,
2854 crt_static_default: false,
2855 crt_static_respected: false,
2856 stack_probes: StackProbeType::None,
2857 min_global_align: None,
2858 default_codegen_units: None,
2859 default_codegen_backend: None,
2860 trap_unreachable: true,
2861 requires_lto: false,
2862 singlethread: false,
2863 no_builtins: false,
2864 default_visibility: None,
2865 emit_debug_gdb_scripts: true,
2866 requires_uwtable: false,
2867 default_uwtable: false,
2868 simd_types_indirect: true,
2869 limit_rdylib_exports: true,
2870 override_export_symbols: None,
2871 merge_functions: MergeFunctions::Aliases,
2872 mcount: "mcount".into(),
2873 llvm_mcount_intrinsic: None,
2874 llvm_abiname: "".into(),
2875 llvm_floatabi: None,
2876 rustc_abi: None,
2877 relax_elf_relocations: false,
2878 llvm_args: cvs![],
2879 use_ctors_section: false,
2880 eh_frame_header: true,
2881 has_thumb_interworking: false,
2882 debuginfo_kind: Default::default(),
2883 split_debuginfo: Default::default(),
2884 supported_split_debuginfo: Cow::Borrowed(&[SplitDebuginfo::Off]),
2886 supported_sanitizers: SanitizerSet::empty(),
2887 c_enum_min_bits: None,
2888 generate_arange_section: true,
2889 supports_stack_protector: true,
2890 entry_name: "main".into(),
2891 entry_abi: Conv::C,
2892 supports_xray: false,
2893 small_data_threshold_support: SmallDataThresholdSupport::DefaultForArch,
2894 }
2895 }
2896}
2897
2898impl Deref for Target {
2902 type Target = TargetOptions;
2903
2904 #[inline]
2905 fn deref(&self) -> &Self::Target {
2906 &self.options
2907 }
2908}
2909impl DerefMut for Target {
2910 #[inline]
2911 fn deref_mut(&mut self) -> &mut Self::Target {
2912 &mut self.options
2913 }
2914}
2915
2916impl Target {
2917 pub fn adjust_abi(&self, abi: ExternAbi, c_variadic: bool) -> ExternAbi {
2919 use ExternAbi::*;
2920 match abi {
2921 System { unwind } => {
2925 if self.is_like_windows && self.arch == "x86" && !c_variadic {
2926 Stdcall { unwind }
2927 } else {
2928 C { unwind }
2929 }
2930 }
2931
2932 EfiApi => {
2933 if self.arch == "arm" {
2934 Aapcs { unwind: false }
2935 } else if self.arch == "x86_64" {
2936 Win64 { unwind: false }
2937 } else {
2938 C { unwind: false }
2939 }
2940 }
2941
2942 Stdcall { unwind } | Thiscall { unwind } | Fastcall { unwind } => {
2944 if self.arch == "x86" { abi } else { C { unwind } }
2945 }
2946 Vectorcall { unwind } => {
2947 if ["x86", "x86_64"].contains(&&*self.arch) {
2948 abi
2949 } else {
2950 C { unwind }
2951 }
2952 }
2953
2954 RustCold if self.is_like_windows && self.arch == "x86_64" => Rust,
2960
2961 abi => abi,
2962 }
2963 }
2964
2965 pub fn is_abi_supported(&self, abi: ExternAbi) -> bool {
2966 use ExternAbi::*;
2967 match abi {
2968 Rust | C { .. } | System { .. } | RustCall | Unadjusted | Cdecl { .. } | RustCold => {
2969 true
2970 }
2971 EfiApi => {
2972 ["arm", "aarch64", "riscv32", "riscv64", "x86", "x86_64"].contains(&&self.arch[..])
2973 }
2974 X86Interrupt => ["x86", "x86_64"].contains(&&self.arch[..]),
2975 Aapcs { .. } => "arm" == self.arch,
2976 CCmseNonSecureCall | CCmseNonSecureEntry => {
2977 ["thumbv8m.main-none-eabi", "thumbv8m.main-none-eabihf", "thumbv8m.base-none-eabi"]
2978 .contains(&&self.llvm_target[..])
2979 }
2980 Win64 { .. } | SysV64 { .. } => self.arch == "x86_64",
2981 PtxKernel => self.arch == "nvptx64",
2982 GpuKernel => ["amdgpu", "nvptx64"].contains(&&self.arch[..]),
2983 Msp430Interrupt => self.arch == "msp430",
2984 RiscvInterruptM | RiscvInterruptS => ["riscv32", "riscv64"].contains(&&self.arch[..]),
2985 AvrInterrupt | AvrNonBlockingInterrupt => self.arch == "avr",
2986 Thiscall { .. } => self.arch == "x86",
2987 Stdcall { .. } | Fastcall { .. } | Vectorcall { .. } if self.is_like_windows => true,
3018 Stdcall { .. } | Fastcall { .. } if self.arch == "x86" => true,
3021 Vectorcall { .. } if ["x86", "x86_64"].contains(&&self.arch[..]) => true,
3022 Stdcall { .. } | Fastcall { .. } | Vectorcall { .. } => false,
3024 }
3025 }
3026
3027 pub fn min_atomic_width(&self) -> u64 {
3030 self.min_atomic_width.unwrap_or(8)
3031 }
3032
3033 pub fn max_atomic_width(&self) -> u64 {
3036 self.max_atomic_width.unwrap_or_else(|| self.pointer_width.into())
3037 }
3038
3039 fn check_consistency(&self, kind: TargetKind) -> Result<(), String> {
3042 macro_rules! check {
3043 ($b:expr, $($msg:tt)*) => {
3044 if !$b {
3045 return Err(format!($($msg)*));
3046 }
3047 }
3048 }
3049 macro_rules! check_eq {
3050 ($left:expr, $right:expr, $($msg:tt)*) => {
3051 if ($left) != ($right) {
3052 return Err(format!($($msg)*));
3053 }
3054 }
3055 }
3056 macro_rules! check_ne {
3057 ($left:expr, $right:expr, $($msg:tt)*) => {
3058 if ($left) == ($right) {
3059 return Err(format!($($msg)*));
3060 }
3061 }
3062 }
3063 macro_rules! check_matches {
3064 ($left:expr, $right:pat, $($msg:tt)*) => {
3065 if !matches!($left, $right) {
3066 return Err(format!($($msg)*));
3067 }
3068 }
3069 }
3070
3071 check_eq!(
3072 self.is_like_darwin,
3073 self.vendor == "apple",
3074 "`is_like_darwin` must be set if and only if `vendor` is `apple`"
3075 );
3076 check_eq!(
3077 self.is_like_solaris,
3078 self.os == "solaris" || self.os == "illumos",
3079 "`is_like_solaris` must be set if and only if `os` is `solaris` or `illumos`"
3080 );
3081 check_eq!(
3082 self.is_like_windows,
3083 self.os == "windows" || self.os == "uefi" || self.os == "cygwin",
3084 "`is_like_windows` must be set if and only if `os` is `windows`, `uefi` or `cygwin`"
3085 );
3086 check_eq!(
3087 self.is_like_wasm,
3088 self.arch == "wasm32" || self.arch == "wasm64",
3089 "`is_like_wasm` must be set if and only if `arch` is `wasm32` or `wasm64`"
3090 );
3091 if self.is_like_msvc {
3092 check!(self.is_like_windows, "if `is_like_msvc` is set, `is_like_windows` must be set");
3093 }
3094 if self.os == "emscripten" {
3095 check!(self.is_like_wasm, "the `emcscripten` os only makes sense on wasm-like targets");
3096 }
3097
3098 check_eq!(
3100 self.is_like_darwin,
3101 matches!(self.linker_flavor, LinkerFlavor::Darwin(..)),
3102 "`linker_flavor` must be `darwin` if and only if `is_like_darwin` is set"
3103 );
3104 check_eq!(
3105 self.is_like_msvc,
3106 matches!(self.linker_flavor, LinkerFlavor::Msvc(..)),
3107 "`linker_flavor` must be `msvc` if and only if `is_like_msvc` is set"
3108 );
3109 check_eq!(
3110 self.is_like_wasm && self.os != "emscripten",
3111 matches!(self.linker_flavor, LinkerFlavor::WasmLld(..)),
3112 "`linker_flavor` must be `wasm-lld` if and only if `is_like_wasm` is set and the `os` is not `emscripten`",
3113 );
3114 check_eq!(
3115 self.os == "emscripten",
3116 matches!(self.linker_flavor, LinkerFlavor::EmCc),
3117 "`linker_flavor` must be `em-cc` if and only if `os` is `emscripten`"
3118 );
3119 check_eq!(
3120 self.arch == "bpf",
3121 matches!(self.linker_flavor, LinkerFlavor::Bpf),
3122 "`linker_flavor` must be `bpf` if and only if `arch` is `bpf`"
3123 );
3124 check_eq!(
3125 self.arch == "nvptx64",
3126 matches!(self.linker_flavor, LinkerFlavor::Ptx),
3127 "`linker_flavor` must be `ptc` if and only if `arch` is `nvptx64`"
3128 );
3129
3130 for args in [
3131 &self.pre_link_args,
3132 &self.late_link_args,
3133 &self.late_link_args_dynamic,
3134 &self.late_link_args_static,
3135 &self.post_link_args,
3136 ] {
3137 for (&flavor, flavor_args) in args {
3138 check!(
3139 !flavor_args.is_empty() || self.arch == "avr",
3140 "linker flavor args must not be empty"
3141 );
3142 match self.linker_flavor {
3144 LinkerFlavor::Gnu(..) => {
3145 check_matches!(
3146 flavor,
3147 LinkerFlavor::Gnu(..),
3148 "mixing GNU and non-GNU linker flavors"
3149 );
3150 }
3151 LinkerFlavor::Darwin(..) => {
3152 check_matches!(
3153 flavor,
3154 LinkerFlavor::Darwin(..),
3155 "mixing Darwin and non-Darwin linker flavors"
3156 )
3157 }
3158 LinkerFlavor::WasmLld(..) => {
3159 check_matches!(
3160 flavor,
3161 LinkerFlavor::WasmLld(..),
3162 "mixing wasm and non-wasm linker flavors"
3163 )
3164 }
3165 LinkerFlavor::Unix(..) => {
3166 check_matches!(
3167 flavor,
3168 LinkerFlavor::Unix(..),
3169 "mixing unix and non-unix linker flavors"
3170 );
3171 }
3172 LinkerFlavor::Msvc(..) => {
3173 check_matches!(
3174 flavor,
3175 LinkerFlavor::Msvc(..),
3176 "mixing MSVC and non-MSVC linker flavors"
3177 );
3178 }
3179 LinkerFlavor::EmCc
3180 | LinkerFlavor::Bpf
3181 | LinkerFlavor::Ptx
3182 | LinkerFlavor::Llbc => {
3183 check_eq!(flavor, self.linker_flavor, "mixing different linker flavors")
3184 }
3185 }
3186
3187 let check_noncc = |noncc_flavor| -> Result<(), String> {
3189 if let Some(noncc_args) = args.get(&noncc_flavor) {
3190 for arg in flavor_args {
3191 if let Some(suffix) = arg.strip_prefix("-Wl,") {
3192 check!(
3193 noncc_args.iter().any(|a| a == suffix),
3194 " link args for cc and non-cc versions of flavors are not consistent"
3195 );
3196 }
3197 }
3198 }
3199 Ok(())
3200 };
3201
3202 match self.linker_flavor {
3203 LinkerFlavor::Gnu(Cc::Yes, lld) => check_noncc(LinkerFlavor::Gnu(Cc::No, lld))?,
3204 LinkerFlavor::WasmLld(Cc::Yes) => check_noncc(LinkerFlavor::WasmLld(Cc::No))?,
3205 LinkerFlavor::Unix(Cc::Yes) => check_noncc(LinkerFlavor::Unix(Cc::No))?,
3206 _ => {}
3207 }
3208 }
3209
3210 for cc in [Cc::No, Cc::Yes] {
3212 check_eq!(
3213 args.get(&LinkerFlavor::Gnu(cc, Lld::No)),
3214 args.get(&LinkerFlavor::Gnu(cc, Lld::Yes)),
3215 "link args for lld and non-lld versions of flavors are not consistent",
3216 );
3217 check_eq!(
3218 args.get(&LinkerFlavor::Darwin(cc, Lld::No)),
3219 args.get(&LinkerFlavor::Darwin(cc, Lld::Yes)),
3220 "link args for lld and non-lld versions of flavors are not consistent",
3221 );
3222 }
3223 check_eq!(
3224 args.get(&LinkerFlavor::Msvc(Lld::No)),
3225 args.get(&LinkerFlavor::Msvc(Lld::Yes)),
3226 "link args for lld and non-lld versions of flavors are not consistent",
3227 );
3228 }
3229
3230 if self.link_self_contained.is_disabled() {
3231 check!(
3232 self.pre_link_objects_self_contained.is_empty()
3233 && self.post_link_objects_self_contained.is_empty(),
3234 "if `link_self_contained` is disabled, then `pre_link_objects_self_contained` and `post_link_objects_self_contained` must be empty",
3235 );
3236 }
3237
3238 check_ne!(self.vendor, "", "`vendor` cannot be empty");
3242 check_ne!(self.os, "", "`os` cannot be empty");
3243 if !self.can_use_os_unknown() {
3244 check_ne!(
3246 self.os,
3247 "unknown",
3248 "`unknown` os can only be used on particular targets; use `none` for bare-metal targets"
3249 );
3250 }
3251
3252 if kind == TargetKind::Builtin {
3258 if self.os == "none"
3262 && (self.arch != "bpf"
3263 && self.arch != "hexagon"
3264 && self.arch != "wasm32"
3265 && self.arch != "wasm64")
3266 {
3267 check!(
3268 !self.dynamic_linking,
3269 "dynamic linking is not supported on this OS/architecture"
3270 );
3271 }
3272 if self.only_cdylib
3273 || self.crt_static_allows_dylibs
3274 || !self.late_link_args_dynamic.is_empty()
3275 {
3276 check!(
3277 self.dynamic_linking,
3278 "dynamic linking must be allowed when `only_cdylib` or `crt_static_allows_dylibs` or `late_link_args_dynamic` are set"
3279 );
3280 }
3281 if self.dynamic_linking && !self.is_like_wasm {
3283 check_eq!(
3284 self.relocation_model,
3285 RelocModel::Pic,
3286 "targets that support dynamic linking must use the `pic` relocation model"
3287 );
3288 }
3289 if self.position_independent_executables {
3290 check_eq!(
3291 self.relocation_model,
3292 RelocModel::Pic,
3293 "targets that support position-independent executables must use the `pic` relocation model"
3294 );
3295 }
3296 if self.relocation_model == RelocModel::Pic && (self.os != "uefi") {
3298 check!(
3299 self.dynamic_linking || self.position_independent_executables,
3300 "when the relocation model is `pic`, the target must support dynamic linking or use position-independent executables. \
3301 Set the relocation model to `static` to avoid this requirement"
3302 );
3303 }
3304 if self.static_position_independent_executables {
3305 check!(
3306 self.position_independent_executables,
3307 "if `static_position_independent_executables` is set, then `position_independent_executables` must be set"
3308 );
3309 }
3310 if self.position_independent_executables {
3311 check!(
3312 self.executables,
3313 "if `position_independent_executables` is set then `executables` must be set"
3314 );
3315 }
3316 }
3317
3318 if self.crt_static_default || self.crt_static_allows_dylibs {
3320 check!(
3321 self.crt_static_respected,
3322 "static CRT can be enabled but `crt_static_respected` is not set"
3323 );
3324 }
3325
3326 match &*self.arch {
3329 "riscv32" => {
3330 check_matches!(
3331 &*self.llvm_abiname,
3332 "ilp32" | "ilp32f" | "ilp32d" | "ilp32e",
3333 "invalid RISC-V ABI name: {}",
3334 self.llvm_abiname,
3335 );
3336 }
3337 "riscv64" => {
3338 check_matches!(
3340 &*self.llvm_abiname,
3341 "lp64" | "lp64f" | "lp64d" | "lp64e",
3342 "invalid RISC-V ABI name: {}",
3343 self.llvm_abiname,
3344 );
3345 }
3346 "arm" => {
3347 check!(
3348 self.llvm_floatabi.is_some(),
3349 "ARM targets must set `llvm-floatabi` to `hard` or `soft`",
3350 )
3351 }
3352 _ => {}
3353 }
3354
3355 if let Some(rust_abi) = self.rustc_abi {
3357 match rust_abi {
3358 RustcAbi::X86Sse2 => check_matches!(
3359 &*self.arch,
3360 "x86",
3361 "`x86-sse2` ABI is only valid for x86-32 targets"
3362 ),
3363 RustcAbi::X86Softfloat => check_matches!(
3364 &*self.arch,
3365 "x86" | "x86_64",
3366 "`x86-softfloat` ABI is only valid for x86 targets"
3367 ),
3368 }
3369 }
3370
3371 if !self.features.is_empty() {
3373 let mut features_enabled = FxHashSet::default();
3374 let mut features_disabled = FxHashSet::default();
3375 for feat in self.features.split(',') {
3376 if let Some(feat) = feat.strip_prefix("+") {
3377 features_enabled.insert(feat);
3378 if features_disabled.contains(feat) {
3379 return Err(format!(
3380 "target feature `{feat}` is both enabled and disabled"
3381 ));
3382 }
3383 } else if let Some(feat) = feat.strip_prefix("-") {
3384 features_disabled.insert(feat);
3385 if features_enabled.contains(feat) {
3386 return Err(format!(
3387 "target feature `{feat}` is both enabled and disabled"
3388 ));
3389 }
3390 } else {
3391 return Err(format!(
3392 "target feature `{feat}` is invalid, must start with `+` or `-`"
3393 ));
3394 }
3395 }
3396 let abi_feature_constraints = self.abi_required_features();
3398 for feat in abi_feature_constraints.required {
3399 if features_disabled.contains(feat) {
3402 return Err(format!(
3403 "target feature `{feat}` is required by the ABI but gets disabled in target spec"
3404 ));
3405 }
3406 }
3407 for feat in abi_feature_constraints.incompatible {
3408 if features_enabled.contains(feat) {
3411 return Err(format!(
3412 "target feature `{feat}` is incompatible with the ABI but gets enabled in target spec"
3413 ));
3414 }
3415 }
3416 }
3417
3418 Ok(())
3419 }
3420
3421 #[cfg(test)]
3423 fn test_target(mut self) {
3424 let recycled_target = Target::from_json(self.to_json()).map(|(j, _)| j);
3425 self.update_to_cli();
3426 self.check_consistency(TargetKind::Builtin).unwrap();
3427 assert_eq!(recycled_target, Ok(self));
3428 }
3429
3430 fn can_use_os_unknown(&self) -> bool {
3433 self.llvm_target == "wasm32-unknown-unknown"
3434 || self.llvm_target == "wasm64-unknown-unknown"
3435 || (self.env == "sgx" && self.vendor == "fortanix")
3436 }
3437
3438 pub fn expect_builtin(target_tuple: &TargetTuple) -> Target {
3440 match *target_tuple {
3441 TargetTuple::TargetTuple(ref target_tuple) => {
3442 load_builtin(target_tuple).expect("built-in target")
3443 }
3444 TargetTuple::TargetJson { .. } => {
3445 panic!("built-in targets doesn't support target-paths")
3446 }
3447 }
3448 }
3449
3450 pub fn builtins() -> impl Iterator<Item = Target> {
3452 load_all_builtins()
3453 }
3454
3455 pub fn search(
3465 target_tuple: &TargetTuple,
3466 sysroot: &Path,
3467 ) -> Result<(Target, TargetWarnings), String> {
3468 use std::{env, fs};
3469
3470 fn load_file(path: &Path) -> Result<(Target, TargetWarnings), String> {
3471 let contents = fs::read_to_string(path).map_err(|e| e.to_string())?;
3472 let obj = serde_json::from_str(&contents).map_err(|e| e.to_string())?;
3473 Target::from_json(obj)
3474 }
3475
3476 match *target_tuple {
3477 TargetTuple::TargetTuple(ref target_tuple) => {
3478 if let Some(t) = load_builtin(target_tuple) {
3480 return Ok((t, TargetWarnings::empty()));
3481 }
3482
3483 let path = {
3485 let mut target = target_tuple.to_string();
3486 target.push_str(".json");
3487 PathBuf::from(target)
3488 };
3489
3490 let target_path = env::var_os("RUST_TARGET_PATH").unwrap_or_default();
3491
3492 for dir in env::split_paths(&target_path) {
3493 let p = dir.join(&path);
3494 if p.is_file() {
3495 return load_file(&p);
3496 }
3497 }
3498
3499 let rustlib_path = crate::relative_target_rustlib_path(sysroot, target_tuple);
3502 let p = PathBuf::from_iter([
3503 Path::new(sysroot),
3504 Path::new(&rustlib_path),
3505 Path::new("target.json"),
3506 ]);
3507 if p.is_file() {
3508 return load_file(&p);
3509 }
3510
3511 if target_tuple == "i586-pc-windows-msvc" {
3515 Err("the `i586-pc-windows-msvc` target has been removed. Use the `i686-pc-windows-msvc` target instead.\n\
3516 Windows 10 (the minimum required OS version) requires a CPU baseline of at least i686 so you can safely switch".into())
3517 } else {
3518 Err(format!("could not find specification for target {target_tuple:?}"))
3519 }
3520 }
3521 TargetTuple::TargetJson { ref contents, .. } => {
3522 let obj = serde_json::from_str(contents).map_err(|e| e.to_string())?;
3523 Target::from_json(obj)
3524 }
3525 }
3526 }
3527
3528 pub fn small_data_threshold_support(&self) -> SmallDataThresholdSupport {
3531 match &self.options.small_data_threshold_support {
3532 SmallDataThresholdSupport::DefaultForArch => match self.arch.as_ref() {
3536 "mips" | "mips64" | "mips32r6" => {
3537 SmallDataThresholdSupport::LlvmArg("mips-ssection-threshold".into())
3538 }
3539 "hexagon" => {
3540 SmallDataThresholdSupport::LlvmArg("hexagon-small-data-threshold".into())
3541 }
3542 "m68k" => SmallDataThresholdSupport::LlvmArg("m68k-ssection-threshold".into()),
3543 "riscv32" | "riscv64" => {
3544 SmallDataThresholdSupport::LlvmModuleFlag("SmallDataLimit".into())
3545 }
3546 _ => SmallDataThresholdSupport::None,
3547 },
3548 s => s.clone(),
3549 }
3550 }
3551
3552 pub fn object_architecture(
3553 &self,
3554 unstable_target_features: &FxIndexSet<Symbol>,
3555 ) -> Option<(object::Architecture, Option<object::SubArchitecture>)> {
3556 use object::Architecture;
3557 Some(match self.arch.as_ref() {
3558 "arm" => (Architecture::Arm, None),
3559 "aarch64" => (
3560 if self.pointer_width == 32 {
3561 Architecture::Aarch64_Ilp32
3562 } else {
3563 Architecture::Aarch64
3564 },
3565 None,
3566 ),
3567 "x86" => (Architecture::I386, None),
3568 "s390x" => (Architecture::S390x, None),
3569 "mips" | "mips32r6" => (Architecture::Mips, None),
3570 "mips64" | "mips64r6" => (Architecture::Mips64, None),
3571 "x86_64" => (
3572 if self.pointer_width == 32 {
3573 Architecture::X86_64_X32
3574 } else {
3575 Architecture::X86_64
3576 },
3577 None,
3578 ),
3579 "powerpc" => (Architecture::PowerPc, None),
3580 "powerpc64" => (Architecture::PowerPc64, None),
3581 "riscv32" => (Architecture::Riscv32, None),
3582 "riscv64" => (Architecture::Riscv64, None),
3583 "sparc" => {
3584 if unstable_target_features.contains(&sym::v8plus) {
3585 (Architecture::Sparc32Plus, None)
3587 } else {
3588 (Architecture::Sparc, None)
3590 }
3591 }
3592 "sparc64" => (Architecture::Sparc64, None),
3593 "avr" => (Architecture::Avr, None),
3594 "msp430" => (Architecture::Msp430, None),
3595 "hexagon" => (Architecture::Hexagon, None),
3596 "bpf" => (Architecture::Bpf, None),
3597 "loongarch64" => (Architecture::LoongArch64, None),
3598 "csky" => (Architecture::Csky, None),
3599 "arm64ec" => (Architecture::Aarch64, Some(object::SubArchitecture::Arm64EC)),
3600 _ => return None,
3602 })
3603 }
3604
3605 pub fn max_reliable_alignment(&self) -> Align {
3614 if self.is_like_windows && self.arch == "x86" {
3618 Align::from_bytes(4).unwrap()
3619 } else {
3620 Align::MAX
3621 }
3622 }
3623}
3624
3625#[derive(Clone, Debug)]
3627pub enum TargetTuple {
3628 TargetTuple(String),
3629 TargetJson {
3630 path_for_rustdoc: PathBuf,
3633 tuple: String,
3634 contents: String,
3635 },
3636}
3637
3638impl PartialEq for TargetTuple {
3640 fn eq(&self, other: &Self) -> bool {
3641 match (self, other) {
3642 (Self::TargetTuple(l0), Self::TargetTuple(r0)) => l0 == r0,
3643 (
3644 Self::TargetJson { path_for_rustdoc: _, tuple: l_tuple, contents: l_contents },
3645 Self::TargetJson { path_for_rustdoc: _, tuple: r_tuple, contents: r_contents },
3646 ) => l_tuple == r_tuple && l_contents == r_contents,
3647 _ => false,
3648 }
3649 }
3650}
3651
3652impl Hash for TargetTuple {
3654 fn hash<H: Hasher>(&self, state: &mut H) -> () {
3655 match self {
3656 TargetTuple::TargetTuple(tuple) => {
3657 0u8.hash(state);
3658 tuple.hash(state)
3659 }
3660 TargetTuple::TargetJson { path_for_rustdoc: _, tuple, contents } => {
3661 1u8.hash(state);
3662 tuple.hash(state);
3663 contents.hash(state)
3664 }
3665 }
3666 }
3667}
3668
3669impl<S: Encoder> Encodable<S> for TargetTuple {
3671 fn encode(&self, s: &mut S) {
3672 match self {
3673 TargetTuple::TargetTuple(tuple) => {
3674 s.emit_u8(0);
3675 s.emit_str(tuple);
3676 }
3677 TargetTuple::TargetJson { path_for_rustdoc: _, tuple, contents } => {
3678 s.emit_u8(1);
3679 s.emit_str(tuple);
3680 s.emit_str(contents);
3681 }
3682 }
3683 }
3684}
3685
3686impl<D: Decoder> Decodable<D> for TargetTuple {
3687 fn decode(d: &mut D) -> Self {
3688 match d.read_u8() {
3689 0 => TargetTuple::TargetTuple(d.read_str().to_owned()),
3690 1 => TargetTuple::TargetJson {
3691 path_for_rustdoc: PathBuf::new(),
3692 tuple: d.read_str().to_owned(),
3693 contents: d.read_str().to_owned(),
3694 },
3695 _ => {
3696 panic!("invalid enum variant tag while decoding `TargetTuple`, expected 0..2");
3697 }
3698 }
3699 }
3700}
3701
3702impl TargetTuple {
3703 pub fn from_tuple(tuple: &str) -> Self {
3705 TargetTuple::TargetTuple(tuple.into())
3706 }
3707
3708 pub fn from_path(path: &Path) -> Result<Self, io::Error> {
3710 let canonicalized_path = try_canonicalize(path)?;
3711 let contents = std::fs::read_to_string(&canonicalized_path).map_err(|err| {
3712 io::Error::new(
3713 io::ErrorKind::InvalidInput,
3714 format!("target path {canonicalized_path:?} is not a valid file: {err}"),
3715 )
3716 })?;
3717 let tuple = canonicalized_path
3718 .file_stem()
3719 .expect("target path must not be empty")
3720 .to_str()
3721 .expect("target path must be valid unicode")
3722 .to_owned();
3723 Ok(TargetTuple::TargetJson { path_for_rustdoc: canonicalized_path, tuple, contents })
3724 }
3725
3726 pub fn tuple(&self) -> &str {
3730 match *self {
3731 TargetTuple::TargetTuple(ref tuple) | TargetTuple::TargetJson { ref tuple, .. } => {
3732 tuple
3733 }
3734 }
3735 }
3736
3737 pub fn debug_tuple(&self) -> String {
3742 use std::hash::DefaultHasher;
3743
3744 match self {
3745 TargetTuple::TargetTuple(tuple) => tuple.to_owned(),
3746 TargetTuple::TargetJson { path_for_rustdoc: _, tuple, contents: content } => {
3747 let mut hasher = DefaultHasher::new();
3748 content.hash(&mut hasher);
3749 let hash = hasher.finish();
3750 format!("{tuple}-{hash}")
3751 }
3752 }
3753 }
3754}
3755
3756impl fmt::Display for TargetTuple {
3757 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3758 write!(f, "{}", self.debug_tuple())
3759 }
3760}