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