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;
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_gnu::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) -> (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 == "emcc"
315 || stem == "gcc"
316 || stem.ends_with("-gcc")
317 || stem == "g++"
318 || stem.ends_with("-g++")
319 || stem == "clang"
320 || stem.ends_with("-clang")
321 || stem == "clang++"
322 || stem.ends_with("-clang++")
323 {
324 (Some(Cc::Yes), Some(Lld::No))
325 } else if stem == "wasm-ld"
326 || stem.ends_with("-wasm-ld")
327 || stem == "ld.lld"
328 || stem == "lld"
329 || stem == "rust-lld"
330 || stem == "lld-link"
331 {
332 (Some(Cc::No), Some(Lld::Yes))
333 } else if stem == "ld" || stem.ends_with("-ld") || stem == "link" {
334 (Some(Cc::No), Some(Lld::No))
335 } else {
336 (None, None)
337 }
338 }
339
340 fn with_hints(self, (cc_hint, lld_hint): (Option<Cc>, Option<Lld>)) -> LinkerFlavor {
341 match self {
342 LinkerFlavor::Gnu(cc, lld) => {
343 LinkerFlavor::Gnu(cc_hint.unwrap_or(cc), lld_hint.unwrap_or(lld))
344 }
345 LinkerFlavor::Darwin(cc, lld) => {
346 LinkerFlavor::Darwin(cc_hint.unwrap_or(cc), lld_hint.unwrap_or(lld))
347 }
348 LinkerFlavor::WasmLld(cc) => LinkerFlavor::WasmLld(cc_hint.unwrap_or(cc)),
349 LinkerFlavor::Unix(cc) => LinkerFlavor::Unix(cc_hint.unwrap_or(cc)),
350 LinkerFlavor::Msvc(lld) => LinkerFlavor::Msvc(lld_hint.unwrap_or(lld)),
351 LinkerFlavor::EmCc | LinkerFlavor::Bpf | LinkerFlavor::Llbc | LinkerFlavor::Ptx => self,
352 }
353 }
354
355 pub fn with_cli_hints(self, cli: LinkerFlavorCli) -> LinkerFlavor {
356 self.with_hints(LinkerFlavor::infer_cli_hints(cli))
357 }
358
359 pub fn with_linker_hints(self, linker_stem: &str) -> LinkerFlavor {
360 self.with_hints(LinkerFlavor::infer_linker_hints(linker_stem))
361 }
362
363 pub fn check_compatibility(self, cli: LinkerFlavorCli) -> Option<String> {
364 let compatible = |cli| {
365 match (self, cli) {
367 (LinkerFlavor::Gnu(..), LinkerFlavorCli::Gnu(..))
369 | (LinkerFlavor::Darwin(..), LinkerFlavorCli::Darwin(..))
370 | (LinkerFlavor::WasmLld(..), LinkerFlavorCli::WasmLld(..))
371 | (LinkerFlavor::Unix(..), LinkerFlavorCli::Unix(..))
372 | (LinkerFlavor::Msvc(..), LinkerFlavorCli::Msvc(..))
373 | (LinkerFlavor::EmCc, LinkerFlavorCli::EmCc)
374 | (LinkerFlavor::Bpf, LinkerFlavorCli::Bpf)
375 | (LinkerFlavor::Llbc, LinkerFlavorCli::Llbc)
376 | (LinkerFlavor::Ptx, LinkerFlavorCli::Ptx) => return true,
377 (LinkerFlavor::Ptx, LinkerFlavorCli::Llbc) => return true,
379 _ => {}
380 }
381
382 cli == self.with_cli_hints(cli).to_cli()
384 };
385 (!compatible(cli)).then(|| {
386 LinkerFlavorCli::all()
387 .iter()
388 .filter(|cli| compatible(**cli))
389 .map(|cli| cli.desc())
390 .intersperse(", ")
391 .collect()
392 })
393 }
394
395 pub fn lld_flavor(self) -> LldFlavor {
396 match self {
397 LinkerFlavor::Gnu(..)
398 | LinkerFlavor::Unix(..)
399 | LinkerFlavor::EmCc
400 | LinkerFlavor::Bpf
401 | LinkerFlavor::Llbc
402 | LinkerFlavor::Ptx => LldFlavor::Ld,
403 LinkerFlavor::Darwin(..) => LldFlavor::Ld64,
404 LinkerFlavor::WasmLld(..) => LldFlavor::Wasm,
405 LinkerFlavor::Msvc(..) => LldFlavor::Link,
406 }
407 }
408
409 pub fn is_gnu(self) -> bool {
410 matches!(self, LinkerFlavor::Gnu(..))
411 }
412
413 pub fn uses_lld(self) -> bool {
415 match self {
417 LinkerFlavor::Gnu(_, Lld::Yes)
418 | LinkerFlavor::Darwin(_, Lld::Yes)
419 | LinkerFlavor::WasmLld(..)
420 | LinkerFlavor::EmCc
421 | LinkerFlavor::Msvc(Lld::Yes) => true,
422 LinkerFlavor::Gnu(..)
423 | LinkerFlavor::Darwin(..)
424 | LinkerFlavor::Msvc(_)
425 | LinkerFlavor::Unix(_)
426 | LinkerFlavor::Bpf
427 | LinkerFlavor::Llbc
428 | LinkerFlavor::Ptx => false,
429 }
430 }
431
432 pub fn uses_cc(self) -> bool {
434 match self {
436 LinkerFlavor::Gnu(Cc::Yes, _)
437 | LinkerFlavor::Darwin(Cc::Yes, _)
438 | LinkerFlavor::WasmLld(Cc::Yes)
439 | LinkerFlavor::Unix(Cc::Yes)
440 | LinkerFlavor::EmCc => true,
441 LinkerFlavor::Gnu(..)
442 | LinkerFlavor::Darwin(..)
443 | LinkerFlavor::WasmLld(_)
444 | LinkerFlavor::Msvc(_)
445 | LinkerFlavor::Unix(_)
446 | LinkerFlavor::Bpf
447 | LinkerFlavor::Llbc
448 | LinkerFlavor::Ptx => false,
449 }
450 }
451
452 pub fn with_lld_enabled(self) -> LinkerFlavor {
455 match self {
456 LinkerFlavor::Gnu(cc, Lld::No) => LinkerFlavor::Gnu(cc, Lld::Yes),
457 LinkerFlavor::Darwin(cc, Lld::No) => LinkerFlavor::Darwin(cc, Lld::Yes),
458 LinkerFlavor::Msvc(Lld::No) => LinkerFlavor::Msvc(Lld::Yes),
459 _ => self,
460 }
461 }
462
463 pub fn with_lld_disabled(self) -> LinkerFlavor {
466 match self {
467 LinkerFlavor::Gnu(cc, Lld::Yes) => LinkerFlavor::Gnu(cc, Lld::No),
468 LinkerFlavor::Darwin(cc, Lld::Yes) => LinkerFlavor::Darwin(cc, Lld::No),
469 LinkerFlavor::Msvc(Lld::Yes) => LinkerFlavor::Msvc(Lld::No),
470 _ => self,
471 }
472 }
473}
474
475macro_rules! linker_flavor_cli_impls {
476 ($(($($flavor:tt)*) $string:literal)*) => (
477 impl LinkerFlavorCli {
478 const fn all() -> &'static [LinkerFlavorCli] {
479 &[$($($flavor)*,)*]
480 }
481
482 pub const fn one_of() -> &'static str {
483 concat!("one of: ", $($string, " ",)*)
484 }
485
486 pub fn from_str(s: &str) -> Option<LinkerFlavorCli> {
487 Some(match s {
488 $($string => $($flavor)*,)*
489 _ => return None,
490 })
491 }
492
493 pub fn desc(self) -> &'static str {
494 match self {
495 $($($flavor)* => $string,)*
496 }
497 }
498 }
499 )
500}
501
502linker_flavor_cli_impls! {
503 (LinkerFlavorCli::Gnu(Cc::No, Lld::No)) "gnu"
504 (LinkerFlavorCli::Gnu(Cc::No, Lld::Yes)) "gnu-lld"
505 (LinkerFlavorCli::Gnu(Cc::Yes, Lld::No)) "gnu-cc"
506 (LinkerFlavorCli::Gnu(Cc::Yes, Lld::Yes)) "gnu-lld-cc"
507 (LinkerFlavorCli::Darwin(Cc::No, Lld::No)) "darwin"
508 (LinkerFlavorCli::Darwin(Cc::No, Lld::Yes)) "darwin-lld"
509 (LinkerFlavorCli::Darwin(Cc::Yes, Lld::No)) "darwin-cc"
510 (LinkerFlavorCli::Darwin(Cc::Yes, Lld::Yes)) "darwin-lld-cc"
511 (LinkerFlavorCli::WasmLld(Cc::No)) "wasm-lld"
512 (LinkerFlavorCli::WasmLld(Cc::Yes)) "wasm-lld-cc"
513 (LinkerFlavorCli::Unix(Cc::No)) "unix"
514 (LinkerFlavorCli::Unix(Cc::Yes)) "unix-cc"
515 (LinkerFlavorCli::Msvc(Lld::Yes)) "msvc-lld"
516 (LinkerFlavorCli::Msvc(Lld::No)) "msvc"
517 (LinkerFlavorCli::EmCc) "em-cc"
518 (LinkerFlavorCli::Bpf) "bpf"
519 (LinkerFlavorCli::Llbc) "llbc"
520 (LinkerFlavorCli::Ptx) "ptx"
521
522 (LinkerFlavorCli::Gcc) "gcc"
524 (LinkerFlavorCli::Ld) "ld"
525 (LinkerFlavorCli::Lld(LldFlavor::Ld)) "ld.lld"
526 (LinkerFlavorCli::Lld(LldFlavor::Ld64)) "ld64.lld"
527 (LinkerFlavorCli::Lld(LldFlavor::Link)) "lld-link"
528 (LinkerFlavorCli::Lld(LldFlavor::Wasm)) "wasm-ld"
529 (LinkerFlavorCli::Em) "em"
530}
531
532impl ToJson for LinkerFlavorCli {
533 fn to_json(&self) -> Json {
534 self.desc().to_json()
535 }
536}
537
538#[derive(Clone, Copy, PartialEq, Debug)]
545pub enum LinkSelfContainedDefault {
546 True,
548
549 False,
551
552 InferredForMusl,
554
555 InferredForMingw,
557
558 WithComponents(LinkSelfContainedComponents),
561}
562
563impl FromStr for LinkSelfContainedDefault {
565 type Err = ();
566
567 fn from_str(s: &str) -> Result<LinkSelfContainedDefault, ()> {
568 Ok(match s {
569 "false" => LinkSelfContainedDefault::False,
570 "true" | "wasm" => LinkSelfContainedDefault::True,
571 "musl" => LinkSelfContainedDefault::InferredForMusl,
572 "mingw" => LinkSelfContainedDefault::InferredForMingw,
573 _ => return Err(()),
574 })
575 }
576}
577
578impl ToJson for LinkSelfContainedDefault {
579 fn to_json(&self) -> Json {
580 match *self {
581 LinkSelfContainedDefault::WithComponents(components) => {
582 let mut map = BTreeMap::new();
586 map.insert("components", components);
587 map.to_json()
588 }
589
590 LinkSelfContainedDefault::True => "true".to_json(),
592 LinkSelfContainedDefault::False => "false".to_json(),
593 LinkSelfContainedDefault::InferredForMusl => "musl".to_json(),
594 LinkSelfContainedDefault::InferredForMingw => "mingw".to_json(),
595 }
596 }
597}
598
599impl LinkSelfContainedDefault {
600 pub fn is_disabled(self) -> bool {
603 self == LinkSelfContainedDefault::False
604 }
605
606 fn json_key(self) -> &'static str {
610 match self {
611 LinkSelfContainedDefault::WithComponents(_) => "link-self-contained",
612 _ => "crt-objects-fallback",
613 }
614 }
615
616 pub fn with_linker() -> LinkSelfContainedDefault {
619 LinkSelfContainedDefault::WithComponents(LinkSelfContainedComponents::LINKER)
620 }
621}
622
623bitflags::bitflags! {
624 #[derive(Clone, Copy, PartialEq, Eq, Default)]
625 pub struct LinkSelfContainedComponents: u8 {
627 const CRT_OBJECTS = 1 << 0;
629 const LIBC = 1 << 1;
631 const UNWIND = 1 << 2;
633 const LINKER = 1 << 3;
635 const SANITIZERS = 1 << 4;
637 const MINGW = 1 << 5;
639 }
640}
641rustc_data_structures::external_bitflags_debug! { LinkSelfContainedComponents }
642
643impl LinkSelfContainedComponents {
644 pub fn from_str(s: &str) -> Option<LinkSelfContainedComponents> {
646 Some(match s {
647 "crto" => LinkSelfContainedComponents::CRT_OBJECTS,
648 "libc" => LinkSelfContainedComponents::LIBC,
649 "unwind" => LinkSelfContainedComponents::UNWIND,
650 "linker" => LinkSelfContainedComponents::LINKER,
651 "sanitizers" => LinkSelfContainedComponents::SANITIZERS,
652 "mingw" => LinkSelfContainedComponents::MINGW,
653 _ => return None,
654 })
655 }
656
657 pub fn as_str(self) -> Option<&'static str> {
661 Some(match self {
662 LinkSelfContainedComponents::CRT_OBJECTS => "crto",
663 LinkSelfContainedComponents::LIBC => "libc",
664 LinkSelfContainedComponents::UNWIND => "unwind",
665 LinkSelfContainedComponents::LINKER => "linker",
666 LinkSelfContainedComponents::SANITIZERS => "sanitizers",
667 LinkSelfContainedComponents::MINGW => "mingw",
668 _ => return None,
669 })
670 }
671
672 fn all_components() -> [LinkSelfContainedComponents; 6] {
674 [
675 LinkSelfContainedComponents::CRT_OBJECTS,
676 LinkSelfContainedComponents::LIBC,
677 LinkSelfContainedComponents::UNWIND,
678 LinkSelfContainedComponents::LINKER,
679 LinkSelfContainedComponents::SANITIZERS,
680 LinkSelfContainedComponents::MINGW,
681 ]
682 }
683
684 pub fn are_any_components_enabled(self) -> bool {
686 !self.is_empty()
687 }
688
689 pub fn is_linker_enabled(self) -> bool {
691 self.contains(LinkSelfContainedComponents::LINKER)
692 }
693
694 pub fn is_crt_objects_enabled(self) -> bool {
696 self.contains(LinkSelfContainedComponents::CRT_OBJECTS)
697 }
698}
699
700impl ToJson for LinkSelfContainedComponents {
701 fn to_json(&self) -> Json {
702 let components: Vec<_> = Self::all_components()
703 .into_iter()
704 .filter(|c| self.contains(*c))
705 .map(|c| {
706 c.as_str().unwrap().to_owned()
709 })
710 .collect();
711
712 components.to_json()
713 }
714}
715
716bitflags::bitflags! {
717 #[derive(Clone, Copy, PartialEq, Eq, Default)]
738 pub struct LinkerFeatures: u8 {
739 const CC = 1 << 0;
741 const LLD = 1 << 1;
743 }
744}
745rustc_data_structures::external_bitflags_debug! { LinkerFeatures }
746
747impl LinkerFeatures {
748 pub fn from_str(s: &str) -> Option<LinkerFeatures> {
750 Some(match s {
751 "cc" => LinkerFeatures::CC,
752 "lld" => LinkerFeatures::LLD,
753 _ => return None,
754 })
755 }
756
757 pub fn is_lld_enabled(self) -> bool {
759 self.contains(LinkerFeatures::LLD)
760 }
761
762 pub fn is_cc_enabled(self) -> bool {
764 self.contains(LinkerFeatures::CC)
765 }
766}
767
768#[derive(Clone, Copy, Debug, PartialEq, Hash, Encodable, Decodable, HashStable_Generic)]
769pub enum PanicStrategy {
770 Unwind,
771 Abort,
772}
773
774#[derive(Clone, Copy, Debug, PartialEq, Hash, Encodable, Decodable, HashStable_Generic)]
775pub enum OnBrokenPipe {
776 Default,
777 Kill,
778 Error,
779 Inherit,
780}
781
782impl PanicStrategy {
783 pub fn desc(&self) -> &str {
784 match *self {
785 PanicStrategy::Unwind => "unwind",
786 PanicStrategy::Abort => "abort",
787 }
788 }
789
790 pub const fn desc_symbol(&self) -> Symbol {
791 match *self {
792 PanicStrategy::Unwind => sym::unwind,
793 PanicStrategy::Abort => sym::abort,
794 }
795 }
796
797 pub const fn all() -> [Symbol; 2] {
798 [Self::Abort.desc_symbol(), Self::Unwind.desc_symbol()]
799 }
800}
801
802impl ToJson for PanicStrategy {
803 fn to_json(&self) -> Json {
804 match *self {
805 PanicStrategy::Abort => "abort".to_json(),
806 PanicStrategy::Unwind => "unwind".to_json(),
807 }
808 }
809}
810
811#[derive(Clone, Copy, Debug, PartialEq, Hash)]
812pub enum RelroLevel {
813 Full,
814 Partial,
815 Off,
816 None,
817}
818
819impl RelroLevel {
820 pub fn desc(&self) -> &str {
821 match *self {
822 RelroLevel::Full => "full",
823 RelroLevel::Partial => "partial",
824 RelroLevel::Off => "off",
825 RelroLevel::None => "none",
826 }
827 }
828}
829
830#[derive(Clone, Copy, Debug, PartialEq, Hash)]
831pub enum SymbolVisibility {
832 Hidden,
833 Protected,
834 Interposable,
835}
836
837impl SymbolVisibility {
838 pub fn desc(&self) -> &str {
839 match *self {
840 SymbolVisibility::Hidden => "hidden",
841 SymbolVisibility::Protected => "protected",
842 SymbolVisibility::Interposable => "interposable",
843 }
844 }
845}
846
847impl FromStr for SymbolVisibility {
848 type Err = ();
849
850 fn from_str(s: &str) -> Result<SymbolVisibility, ()> {
851 match s {
852 "hidden" => Ok(SymbolVisibility::Hidden),
853 "protected" => Ok(SymbolVisibility::Protected),
854 "interposable" => Ok(SymbolVisibility::Interposable),
855 _ => Err(()),
856 }
857 }
858}
859
860impl ToJson for SymbolVisibility {
861 fn to_json(&self) -> Json {
862 match *self {
863 SymbolVisibility::Hidden => "hidden".to_json(),
864 SymbolVisibility::Protected => "protected".to_json(),
865 SymbolVisibility::Interposable => "interposable".to_json(),
866 }
867 }
868}
869
870impl FromStr for RelroLevel {
871 type Err = ();
872
873 fn from_str(s: &str) -> Result<RelroLevel, ()> {
874 match s {
875 "full" => Ok(RelroLevel::Full),
876 "partial" => Ok(RelroLevel::Partial),
877 "off" => Ok(RelroLevel::Off),
878 "none" => Ok(RelroLevel::None),
879 _ => Err(()),
880 }
881 }
882}
883
884impl ToJson for RelroLevel {
885 fn to_json(&self) -> Json {
886 match *self {
887 RelroLevel::Full => "full".to_json(),
888 RelroLevel::Partial => "partial".to_json(),
889 RelroLevel::Off => "off".to_json(),
890 RelroLevel::None => "None".to_json(),
891 }
892 }
893}
894
895#[derive(Clone, Debug, PartialEq, Hash)]
896pub enum SmallDataThresholdSupport {
897 None,
898 DefaultForArch,
899 LlvmModuleFlag(StaticCow<str>),
900 LlvmArg(StaticCow<str>),
901}
902
903impl FromStr for SmallDataThresholdSupport {
904 type Err = ();
905
906 fn from_str(s: &str) -> Result<Self, Self::Err> {
907 if s == "none" {
908 Ok(Self::None)
909 } else if s == "default-for-arch" {
910 Ok(Self::DefaultForArch)
911 } else if let Some(flag) = s.strip_prefix("llvm-module-flag=") {
912 Ok(Self::LlvmModuleFlag(flag.to_string().into()))
913 } else if let Some(arg) = s.strip_prefix("llvm-arg=") {
914 Ok(Self::LlvmArg(arg.to_string().into()))
915 } else {
916 Err(())
917 }
918 }
919}
920
921impl ToJson for SmallDataThresholdSupport {
922 fn to_json(&self) -> Value {
923 match self {
924 Self::None => "none".to_json(),
925 Self::DefaultForArch => "default-for-arch".to_json(),
926 Self::LlvmModuleFlag(flag) => format!("llvm-module-flag={flag}").to_json(),
927 Self::LlvmArg(arg) => format!("llvm-arg={arg}").to_json(),
928 }
929 }
930}
931
932#[derive(Clone, Copy, Debug, PartialEq, Hash)]
933pub enum MergeFunctions {
934 Disabled,
935 Trampolines,
936 Aliases,
937}
938
939impl MergeFunctions {
940 pub fn desc(&self) -> &str {
941 match *self {
942 MergeFunctions::Disabled => "disabled",
943 MergeFunctions::Trampolines => "trampolines",
944 MergeFunctions::Aliases => "aliases",
945 }
946 }
947}
948
949impl FromStr for MergeFunctions {
950 type Err = ();
951
952 fn from_str(s: &str) -> Result<MergeFunctions, ()> {
953 match s {
954 "disabled" => Ok(MergeFunctions::Disabled),
955 "trampolines" => Ok(MergeFunctions::Trampolines),
956 "aliases" => Ok(MergeFunctions::Aliases),
957 _ => Err(()),
958 }
959 }
960}
961
962impl ToJson for MergeFunctions {
963 fn to_json(&self) -> Json {
964 match *self {
965 MergeFunctions::Disabled => "disabled".to_json(),
966 MergeFunctions::Trampolines => "trampolines".to_json(),
967 MergeFunctions::Aliases => "aliases".to_json(),
968 }
969 }
970}
971
972#[derive(Clone, Copy, PartialEq, Hash, Debug)]
973pub enum RelocModel {
974 Static,
975 Pic,
976 Pie,
977 DynamicNoPic,
978 Ropi,
979 Rwpi,
980 RopiRwpi,
981}
982
983impl RelocModel {
984 pub fn desc(&self) -> &str {
985 match *self {
986 RelocModel::Static => "static",
987 RelocModel::Pic => "pic",
988 RelocModel::Pie => "pie",
989 RelocModel::DynamicNoPic => "dynamic-no-pic",
990 RelocModel::Ropi => "ropi",
991 RelocModel::Rwpi => "rwpi",
992 RelocModel::RopiRwpi => "ropi-rwpi",
993 }
994 }
995 pub const fn desc_symbol(&self) -> Symbol {
996 match *self {
997 RelocModel::Static => kw::Static,
998 RelocModel::Pic => sym::pic,
999 RelocModel::Pie => sym::pie,
1000 RelocModel::DynamicNoPic => sym::dynamic_no_pic,
1001 RelocModel::Ropi => sym::ropi,
1002 RelocModel::Rwpi => sym::rwpi,
1003 RelocModel::RopiRwpi => sym::ropi_rwpi,
1004 }
1005 }
1006
1007 pub const fn all() -> [Symbol; 7] {
1008 [
1009 RelocModel::Static.desc_symbol(),
1010 RelocModel::Pic.desc_symbol(),
1011 RelocModel::Pie.desc_symbol(),
1012 RelocModel::DynamicNoPic.desc_symbol(),
1013 RelocModel::Ropi.desc_symbol(),
1014 RelocModel::Rwpi.desc_symbol(),
1015 RelocModel::RopiRwpi.desc_symbol(),
1016 ]
1017 }
1018}
1019
1020impl FromStr for RelocModel {
1021 type Err = ();
1022
1023 fn from_str(s: &str) -> Result<RelocModel, ()> {
1024 Ok(match s {
1025 "static" => RelocModel::Static,
1026 "pic" => RelocModel::Pic,
1027 "pie" => RelocModel::Pie,
1028 "dynamic-no-pic" => RelocModel::DynamicNoPic,
1029 "ropi" => RelocModel::Ropi,
1030 "rwpi" => RelocModel::Rwpi,
1031 "ropi-rwpi" => RelocModel::RopiRwpi,
1032 _ => return Err(()),
1033 })
1034 }
1035}
1036
1037impl ToJson for RelocModel {
1038 fn to_json(&self) -> Json {
1039 self.desc().to_json()
1040 }
1041}
1042
1043#[derive(Clone, Copy, PartialEq, Hash, Debug)]
1044pub enum CodeModel {
1045 Tiny,
1046 Small,
1047 Kernel,
1048 Medium,
1049 Large,
1050}
1051
1052impl FromStr for CodeModel {
1053 type Err = ();
1054
1055 fn from_str(s: &str) -> Result<CodeModel, ()> {
1056 Ok(match s {
1057 "tiny" => CodeModel::Tiny,
1058 "small" => CodeModel::Small,
1059 "kernel" => CodeModel::Kernel,
1060 "medium" => CodeModel::Medium,
1061 "large" => CodeModel::Large,
1062 _ => return Err(()),
1063 })
1064 }
1065}
1066
1067impl ToJson for CodeModel {
1068 fn to_json(&self) -> Json {
1069 match *self {
1070 CodeModel::Tiny => "tiny",
1071 CodeModel::Small => "small",
1072 CodeModel::Kernel => "kernel",
1073 CodeModel::Medium => "medium",
1074 CodeModel::Large => "large",
1075 }
1076 .to_json()
1077 }
1078}
1079
1080#[derive(Clone, Copy, PartialEq, Hash, Debug)]
1082pub enum FloatAbi {
1083 Soft,
1084 Hard,
1085}
1086
1087impl FromStr for FloatAbi {
1088 type Err = ();
1089
1090 fn from_str(s: &str) -> Result<FloatAbi, ()> {
1091 Ok(match s {
1092 "soft" => FloatAbi::Soft,
1093 "hard" => FloatAbi::Hard,
1094 _ => return Err(()),
1095 })
1096 }
1097}
1098
1099impl ToJson for FloatAbi {
1100 fn to_json(&self) -> Json {
1101 match *self {
1102 FloatAbi::Soft => "soft",
1103 FloatAbi::Hard => "hard",
1104 }
1105 .to_json()
1106 }
1107}
1108
1109#[derive(Clone, Copy, PartialEq, Hash, Debug)]
1111pub enum RustcAbi {
1112 X86Sse2,
1114 X86Softfloat,
1116}
1117
1118impl FromStr for RustcAbi {
1119 type Err = ();
1120
1121 fn from_str(s: &str) -> Result<RustcAbi, ()> {
1122 Ok(match s {
1123 "x86-sse2" => RustcAbi::X86Sse2,
1124 "x86-softfloat" => RustcAbi::X86Softfloat,
1125 _ => return Err(()),
1126 })
1127 }
1128}
1129
1130impl ToJson for RustcAbi {
1131 fn to_json(&self) -> Json {
1132 match *self {
1133 RustcAbi::X86Sse2 => "x86-sse2",
1134 RustcAbi::X86Softfloat => "x86-softfloat",
1135 }
1136 .to_json()
1137 }
1138}
1139
1140#[derive(Clone, Copy, PartialEq, Hash, Debug)]
1141pub enum TlsModel {
1142 GeneralDynamic,
1143 LocalDynamic,
1144 InitialExec,
1145 LocalExec,
1146 Emulated,
1147}
1148
1149impl FromStr for TlsModel {
1150 type Err = ();
1151
1152 fn from_str(s: &str) -> Result<TlsModel, ()> {
1153 Ok(match s {
1154 "global-dynamic" => TlsModel::GeneralDynamic,
1157 "local-dynamic" => TlsModel::LocalDynamic,
1158 "initial-exec" => TlsModel::InitialExec,
1159 "local-exec" => TlsModel::LocalExec,
1160 "emulated" => TlsModel::Emulated,
1161 _ => return Err(()),
1162 })
1163 }
1164}
1165
1166impl ToJson for TlsModel {
1167 fn to_json(&self) -> Json {
1168 match *self {
1169 TlsModel::GeneralDynamic => "global-dynamic",
1170 TlsModel::LocalDynamic => "local-dynamic",
1171 TlsModel::InitialExec => "initial-exec",
1172 TlsModel::LocalExec => "local-exec",
1173 TlsModel::Emulated => "emulated",
1174 }
1175 .to_json()
1176 }
1177}
1178
1179#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug)]
1181pub enum LinkOutputKind {
1182 DynamicNoPicExe,
1184 DynamicPicExe,
1186 StaticNoPicExe,
1188 StaticPicExe,
1190 DynamicDylib,
1192 StaticDylib,
1194 WasiReactorExe,
1196}
1197
1198impl LinkOutputKind {
1199 fn as_str(&self) -> &'static str {
1200 match self {
1201 LinkOutputKind::DynamicNoPicExe => "dynamic-nopic-exe",
1202 LinkOutputKind::DynamicPicExe => "dynamic-pic-exe",
1203 LinkOutputKind::StaticNoPicExe => "static-nopic-exe",
1204 LinkOutputKind::StaticPicExe => "static-pic-exe",
1205 LinkOutputKind::DynamicDylib => "dynamic-dylib",
1206 LinkOutputKind::StaticDylib => "static-dylib",
1207 LinkOutputKind::WasiReactorExe => "wasi-reactor-exe",
1208 }
1209 }
1210
1211 pub(super) fn from_str(s: &str) -> Option<LinkOutputKind> {
1212 Some(match s {
1213 "dynamic-nopic-exe" => LinkOutputKind::DynamicNoPicExe,
1214 "dynamic-pic-exe" => LinkOutputKind::DynamicPicExe,
1215 "static-nopic-exe" => LinkOutputKind::StaticNoPicExe,
1216 "static-pic-exe" => LinkOutputKind::StaticPicExe,
1217 "dynamic-dylib" => LinkOutputKind::DynamicDylib,
1218 "static-dylib" => LinkOutputKind::StaticDylib,
1219 "wasi-reactor-exe" => LinkOutputKind::WasiReactorExe,
1220 _ => return None,
1221 })
1222 }
1223
1224 pub fn can_link_dylib(self) -> bool {
1225 match self {
1226 LinkOutputKind::StaticNoPicExe | LinkOutputKind::StaticPicExe => false,
1227 LinkOutputKind::DynamicNoPicExe
1228 | LinkOutputKind::DynamicPicExe
1229 | LinkOutputKind::DynamicDylib
1230 | LinkOutputKind::StaticDylib
1231 | LinkOutputKind::WasiReactorExe => true,
1232 }
1233 }
1234}
1235
1236impl fmt::Display for LinkOutputKind {
1237 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1238 f.write_str(self.as_str())
1239 }
1240}
1241
1242pub type LinkArgs = BTreeMap<LinkerFlavor, Vec<StaticCow<str>>>;
1243pub type LinkArgsCli = BTreeMap<LinkerFlavorCli, Vec<StaticCow<str>>>;
1244
1245#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
1250pub enum DebuginfoKind {
1251 #[default]
1253 Dwarf,
1254 DwarfDsym,
1256 Pdb,
1258}
1259
1260impl DebuginfoKind {
1261 fn as_str(&self) -> &'static str {
1262 match self {
1263 DebuginfoKind::Dwarf => "dwarf",
1264 DebuginfoKind::DwarfDsym => "dwarf-dsym",
1265 DebuginfoKind::Pdb => "pdb",
1266 }
1267 }
1268}
1269
1270impl FromStr for DebuginfoKind {
1271 type Err = ();
1272
1273 fn from_str(s: &str) -> Result<Self, ()> {
1274 Ok(match s {
1275 "dwarf" => DebuginfoKind::Dwarf,
1276 "dwarf-dsym" => DebuginfoKind::DwarfDsym,
1277 "pdb" => DebuginfoKind::Pdb,
1278 _ => return Err(()),
1279 })
1280 }
1281}
1282
1283impl ToJson for DebuginfoKind {
1284 fn to_json(&self) -> Json {
1285 self.as_str().to_json()
1286 }
1287}
1288
1289impl fmt::Display for DebuginfoKind {
1290 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1291 f.write_str(self.as_str())
1292 }
1293}
1294
1295#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
1296pub enum SplitDebuginfo {
1297 #[default]
1305 Off,
1306
1307 Packed,
1314
1315 Unpacked,
1322}
1323
1324impl SplitDebuginfo {
1325 fn as_str(&self) -> &'static str {
1326 match self {
1327 SplitDebuginfo::Off => "off",
1328 SplitDebuginfo::Packed => "packed",
1329 SplitDebuginfo::Unpacked => "unpacked",
1330 }
1331 }
1332}
1333
1334impl FromStr for SplitDebuginfo {
1335 type Err = ();
1336
1337 fn from_str(s: &str) -> Result<Self, ()> {
1338 Ok(match s {
1339 "off" => SplitDebuginfo::Off,
1340 "unpacked" => SplitDebuginfo::Unpacked,
1341 "packed" => SplitDebuginfo::Packed,
1342 _ => return Err(()),
1343 })
1344 }
1345}
1346
1347impl ToJson for SplitDebuginfo {
1348 fn to_json(&self) -> Json {
1349 self.as_str().to_json()
1350 }
1351}
1352
1353impl fmt::Display for SplitDebuginfo {
1354 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1355 f.write_str(self.as_str())
1356 }
1357}
1358
1359#[derive(Clone, Debug, PartialEq, Eq)]
1360pub enum StackProbeType {
1361 None,
1363 Inline,
1367 Call,
1369 InlineOrCall { min_llvm_version_for_inline: (u32, u32, u32) },
1372}
1373
1374impl StackProbeType {
1375 fn from_json(json: &Json) -> Result<Self, String> {
1376 let object = json.as_object().ok_or_else(|| "expected a JSON object")?;
1377 let kind = object
1378 .get("kind")
1379 .and_then(|o| o.as_str())
1380 .ok_or_else(|| "expected `kind` to be a string")?;
1381 match kind {
1382 "none" => Ok(StackProbeType::None),
1383 "inline" => Ok(StackProbeType::Inline),
1384 "call" => Ok(StackProbeType::Call),
1385 "inline-or-call" => {
1386 let min_version = object
1387 .get("min-llvm-version-for-inline")
1388 .and_then(|o| o.as_array())
1389 .ok_or_else(|| "expected `min-llvm-version-for-inline` to be an array")?;
1390 let mut iter = min_version.into_iter().map(|v| {
1391 let int = v.as_u64().ok_or_else(
1392 || "expected `min-llvm-version-for-inline` values to be integers",
1393 )?;
1394 u32::try_from(int)
1395 .map_err(|_| "`min-llvm-version-for-inline` values don't convert to u32")
1396 });
1397 let min_llvm_version_for_inline = (
1398 iter.next().unwrap_or(Ok(11))?,
1399 iter.next().unwrap_or(Ok(0))?,
1400 iter.next().unwrap_or(Ok(0))?,
1401 );
1402 Ok(StackProbeType::InlineOrCall { min_llvm_version_for_inline })
1403 }
1404 _ => Err(String::from(
1405 "`kind` expected to be one of `none`, `inline`, `call` or `inline-or-call`",
1406 )),
1407 }
1408 }
1409}
1410
1411impl ToJson for StackProbeType {
1412 fn to_json(&self) -> Json {
1413 Json::Object(match self {
1414 StackProbeType::None => {
1415 [(String::from("kind"), "none".to_json())].into_iter().collect()
1416 }
1417 StackProbeType::Inline => {
1418 [(String::from("kind"), "inline".to_json())].into_iter().collect()
1419 }
1420 StackProbeType::Call => {
1421 [(String::from("kind"), "call".to_json())].into_iter().collect()
1422 }
1423 StackProbeType::InlineOrCall { min_llvm_version_for_inline: (maj, min, patch) } => [
1424 (String::from("kind"), "inline-or-call".to_json()),
1425 (
1426 String::from("min-llvm-version-for-inline"),
1427 Json::Array(vec![maj.to_json(), min.to_json(), patch.to_json()]),
1428 ),
1429 ]
1430 .into_iter()
1431 .collect(),
1432 })
1433 }
1434}
1435
1436#[derive(Default, Clone, Copy, PartialEq, Eq, Hash, Encodable, Decodable, HashStable_Generic)]
1437pub struct SanitizerSet(u16);
1438bitflags::bitflags! {
1439 impl SanitizerSet: u16 {
1440 const ADDRESS = 1 << 0;
1441 const LEAK = 1 << 1;
1442 const MEMORY = 1 << 2;
1443 const THREAD = 1 << 3;
1444 const HWADDRESS = 1 << 4;
1445 const CFI = 1 << 5;
1446 const MEMTAG = 1 << 6;
1447 const SHADOWCALLSTACK = 1 << 7;
1448 const KCFI = 1 << 8;
1449 const KERNELADDRESS = 1 << 9;
1450 const SAFESTACK = 1 << 10;
1451 const DATAFLOW = 1 << 11;
1452 }
1453}
1454rustc_data_structures::external_bitflags_debug! { SanitizerSet }
1455
1456impl SanitizerSet {
1457 const MUTUALLY_EXCLUSIVE: &'static [(SanitizerSet, SanitizerSet)] = &[
1460 (SanitizerSet::ADDRESS, SanitizerSet::MEMORY),
1461 (SanitizerSet::ADDRESS, SanitizerSet::THREAD),
1462 (SanitizerSet::ADDRESS, SanitizerSet::HWADDRESS),
1463 (SanitizerSet::ADDRESS, SanitizerSet::MEMTAG),
1464 (SanitizerSet::ADDRESS, SanitizerSet::KERNELADDRESS),
1465 (SanitizerSet::ADDRESS, SanitizerSet::SAFESTACK),
1466 (SanitizerSet::LEAK, SanitizerSet::MEMORY),
1467 (SanitizerSet::LEAK, SanitizerSet::THREAD),
1468 (SanitizerSet::LEAK, SanitizerSet::KERNELADDRESS),
1469 (SanitizerSet::LEAK, SanitizerSet::SAFESTACK),
1470 (SanitizerSet::MEMORY, SanitizerSet::THREAD),
1471 (SanitizerSet::MEMORY, SanitizerSet::HWADDRESS),
1472 (SanitizerSet::MEMORY, SanitizerSet::KERNELADDRESS),
1473 (SanitizerSet::MEMORY, SanitizerSet::SAFESTACK),
1474 (SanitizerSet::THREAD, SanitizerSet::HWADDRESS),
1475 (SanitizerSet::THREAD, SanitizerSet::KERNELADDRESS),
1476 (SanitizerSet::THREAD, SanitizerSet::SAFESTACK),
1477 (SanitizerSet::HWADDRESS, SanitizerSet::MEMTAG),
1478 (SanitizerSet::HWADDRESS, SanitizerSet::KERNELADDRESS),
1479 (SanitizerSet::HWADDRESS, SanitizerSet::SAFESTACK),
1480 (SanitizerSet::CFI, SanitizerSet::KCFI),
1481 (SanitizerSet::MEMTAG, SanitizerSet::KERNELADDRESS),
1482 (SanitizerSet::KERNELADDRESS, SanitizerSet::SAFESTACK),
1483 ];
1484
1485 pub fn as_str(self) -> Option<&'static str> {
1489 Some(match self {
1490 SanitizerSet::ADDRESS => "address",
1491 SanitizerSet::CFI => "cfi",
1492 SanitizerSet::DATAFLOW => "dataflow",
1493 SanitizerSet::KCFI => "kcfi",
1494 SanitizerSet::KERNELADDRESS => "kernel-address",
1495 SanitizerSet::LEAK => "leak",
1496 SanitizerSet::MEMORY => "memory",
1497 SanitizerSet::MEMTAG => "memtag",
1498 SanitizerSet::SAFESTACK => "safestack",
1499 SanitizerSet::SHADOWCALLSTACK => "shadow-call-stack",
1500 SanitizerSet::THREAD => "thread",
1501 SanitizerSet::HWADDRESS => "hwaddress",
1502 _ => return None,
1503 })
1504 }
1505
1506 pub fn mutually_exclusive(self) -> Option<(SanitizerSet, SanitizerSet)> {
1507 Self::MUTUALLY_EXCLUSIVE
1508 .into_iter()
1509 .find(|&(a, b)| self.contains(*a) && self.contains(*b))
1510 .copied()
1511 }
1512}
1513
1514impl fmt::Display for SanitizerSet {
1516 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1517 let mut first = true;
1518 for s in *self {
1519 let name = s.as_str().unwrap_or_else(|| panic!("unrecognized sanitizer {s:?}"));
1520 if !first {
1521 f.write_str(", ")?;
1522 }
1523 f.write_str(name)?;
1524 first = false;
1525 }
1526 Ok(())
1527 }
1528}
1529
1530impl ToJson for SanitizerSet {
1531 fn to_json(&self) -> Json {
1532 self.into_iter()
1533 .map(|v| Some(v.as_str()?.to_json()))
1534 .collect::<Option<Vec<_>>>()
1535 .unwrap_or_default()
1536 .to_json()
1537 }
1538}
1539
1540#[derive(Clone, Copy, PartialEq, Hash, Debug)]
1541pub enum FramePointer {
1542 Always,
1544 NonLeaf,
1547 MayOmit,
1551}
1552
1553impl FramePointer {
1554 #[inline]
1557 pub fn ratchet(&mut self, rhs: FramePointer) -> FramePointer {
1558 *self = match (*self, rhs) {
1559 (FramePointer::Always, _) | (_, FramePointer::Always) => FramePointer::Always,
1560 (FramePointer::NonLeaf, _) | (_, FramePointer::NonLeaf) => FramePointer::NonLeaf,
1561 _ => FramePointer::MayOmit,
1562 };
1563 *self
1564 }
1565}
1566
1567impl FromStr for FramePointer {
1568 type Err = ();
1569 fn from_str(s: &str) -> Result<Self, ()> {
1570 Ok(match s {
1571 "always" => Self::Always,
1572 "non-leaf" => Self::NonLeaf,
1573 "may-omit" => Self::MayOmit,
1574 _ => return Err(()),
1575 })
1576 }
1577}
1578
1579impl ToJson for FramePointer {
1580 fn to_json(&self) -> Json {
1581 match *self {
1582 Self::Always => "always",
1583 Self::NonLeaf => "non-leaf",
1584 Self::MayOmit => "may-omit",
1585 }
1586 .to_json()
1587 }
1588}
1589
1590#[derive(Clone, Copy, Debug, PartialEq, Hash, Eq)]
1592pub enum StackProtector {
1593 None,
1595
1596 Basic,
1601
1602 Strong,
1607
1608 All,
1610}
1611
1612impl StackProtector {
1613 fn as_str(&self) -> &'static str {
1614 match self {
1615 StackProtector::None => "none",
1616 StackProtector::Basic => "basic",
1617 StackProtector::Strong => "strong",
1618 StackProtector::All => "all",
1619 }
1620 }
1621}
1622
1623impl FromStr for StackProtector {
1624 type Err = ();
1625
1626 fn from_str(s: &str) -> Result<StackProtector, ()> {
1627 Ok(match s {
1628 "none" => StackProtector::None,
1629 "basic" => StackProtector::Basic,
1630 "strong" => StackProtector::Strong,
1631 "all" => StackProtector::All,
1632 _ => return Err(()),
1633 })
1634 }
1635}
1636
1637impl fmt::Display for StackProtector {
1638 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1639 f.write_str(self.as_str())
1640 }
1641}
1642
1643macro_rules! supported_targets {
1644 ( $(($tuple:literal, $module:ident),)+ ) => {
1645 mod targets {
1646 $(pub(crate) mod $module;)+
1647 }
1648
1649 pub static TARGETS: &[&str] = &[$($tuple),+];
1651
1652 fn load_builtin(target: &str) -> Option<Target> {
1653 let t = match target {
1654 $( $tuple => targets::$module::target(), )+
1655 _ => return None,
1656 };
1657 debug!("got builtin target: {:?}", t);
1658 Some(t)
1659 }
1660
1661 #[cfg(test)]
1662 mod tests {
1663 $(
1665 #[test] fn $module() {
1667 crate::spec::targets::$module::target().test_target()
1668 }
1669 )+
1670 }
1671 };
1672}
1673
1674supported_targets! {
1675 ("x86_64-unknown-linux-gnu", x86_64_unknown_linux_gnu),
1676 ("x86_64-unknown-linux-gnux32", x86_64_unknown_linux_gnux32),
1677 ("i686-unknown-linux-gnu", i686_unknown_linux_gnu),
1678 ("i586-unknown-linux-gnu", i586_unknown_linux_gnu),
1679 ("loongarch64-unknown-linux-gnu", loongarch64_unknown_linux_gnu),
1680 ("loongarch64-unknown-linux-musl", loongarch64_unknown_linux_musl),
1681 ("m68k-unknown-linux-gnu", m68k_unknown_linux_gnu),
1682 ("m68k-unknown-none-elf", m68k_unknown_none_elf),
1683 ("csky-unknown-linux-gnuabiv2", csky_unknown_linux_gnuabiv2),
1684 ("csky-unknown-linux-gnuabiv2hf", csky_unknown_linux_gnuabiv2hf),
1685 ("mips-unknown-linux-gnu", mips_unknown_linux_gnu),
1686 ("mips64-unknown-linux-gnuabi64", mips64_unknown_linux_gnuabi64),
1687 ("mips64el-unknown-linux-gnuabi64", mips64el_unknown_linux_gnuabi64),
1688 ("mipsisa32r6-unknown-linux-gnu", mipsisa32r6_unknown_linux_gnu),
1689 ("mipsisa32r6el-unknown-linux-gnu", mipsisa32r6el_unknown_linux_gnu),
1690 ("mipsisa64r6-unknown-linux-gnuabi64", mipsisa64r6_unknown_linux_gnuabi64),
1691 ("mipsisa64r6el-unknown-linux-gnuabi64", mipsisa64r6el_unknown_linux_gnuabi64),
1692 ("mipsel-unknown-linux-gnu", mipsel_unknown_linux_gnu),
1693 ("powerpc-unknown-linux-gnu", powerpc_unknown_linux_gnu),
1694 ("powerpc-unknown-linux-gnuspe", powerpc_unknown_linux_gnuspe),
1695 ("powerpc-unknown-linux-musl", powerpc_unknown_linux_musl),
1696 ("powerpc-unknown-linux-muslspe", powerpc_unknown_linux_muslspe),
1697 ("powerpc64-ibm-aix", powerpc64_ibm_aix),
1698 ("powerpc64-unknown-linux-gnu", powerpc64_unknown_linux_gnu),
1699 ("powerpc64-unknown-linux-musl", powerpc64_unknown_linux_musl),
1700 ("powerpc64le-unknown-linux-gnu", powerpc64le_unknown_linux_gnu),
1701 ("powerpc64le-unknown-linux-musl", powerpc64le_unknown_linux_musl),
1702 ("s390x-unknown-linux-gnu", s390x_unknown_linux_gnu),
1703 ("s390x-unknown-linux-musl", s390x_unknown_linux_musl),
1704 ("sparc-unknown-linux-gnu", sparc_unknown_linux_gnu),
1705 ("sparc64-unknown-linux-gnu", sparc64_unknown_linux_gnu),
1706 ("arm-unknown-linux-gnueabi", arm_unknown_linux_gnueabi),
1707 ("arm-unknown-linux-gnueabihf", arm_unknown_linux_gnueabihf),
1708 ("armeb-unknown-linux-gnueabi", armeb_unknown_linux_gnueabi),
1709 ("arm-unknown-linux-musleabi", arm_unknown_linux_musleabi),
1710 ("arm-unknown-linux-musleabihf", arm_unknown_linux_musleabihf),
1711 ("armv4t-unknown-linux-gnueabi", armv4t_unknown_linux_gnueabi),
1712 ("armv5te-unknown-linux-gnueabi", armv5te_unknown_linux_gnueabi),
1713 ("armv5te-unknown-linux-musleabi", armv5te_unknown_linux_musleabi),
1714 ("armv5te-unknown-linux-uclibceabi", armv5te_unknown_linux_uclibceabi),
1715 ("armv7-unknown-linux-gnueabi", armv7_unknown_linux_gnueabi),
1716 ("armv7-unknown-linux-gnueabihf", armv7_unknown_linux_gnueabihf),
1717 ("thumbv7neon-unknown-linux-gnueabihf", thumbv7neon_unknown_linux_gnueabihf),
1718 ("thumbv7neon-unknown-linux-musleabihf", thumbv7neon_unknown_linux_musleabihf),
1719 ("armv7-unknown-linux-musleabi", armv7_unknown_linux_musleabi),
1720 ("armv7-unknown-linux-musleabihf", armv7_unknown_linux_musleabihf),
1721 ("aarch64-unknown-linux-gnu", aarch64_unknown_linux_gnu),
1722 ("aarch64-unknown-linux-musl", aarch64_unknown_linux_musl),
1723 ("x86_64-unknown-linux-musl", x86_64_unknown_linux_musl),
1724 ("i686-unknown-linux-musl", i686_unknown_linux_musl),
1725 ("i586-unknown-linux-musl", i586_unknown_linux_musl),
1726 ("mips-unknown-linux-musl", mips_unknown_linux_musl),
1727 ("mipsel-unknown-linux-musl", mipsel_unknown_linux_musl),
1728 ("mips64-unknown-linux-muslabi64", mips64_unknown_linux_muslabi64),
1729 ("mips64el-unknown-linux-muslabi64", mips64el_unknown_linux_muslabi64),
1730 ("hexagon-unknown-linux-musl", hexagon_unknown_linux_musl),
1731 ("hexagon-unknown-none-elf", hexagon_unknown_none_elf),
1732
1733 ("mips-unknown-linux-uclibc", mips_unknown_linux_uclibc),
1734 ("mipsel-unknown-linux-uclibc", mipsel_unknown_linux_uclibc),
1735
1736 ("i686-linux-android", i686_linux_android),
1737 ("x86_64-linux-android", x86_64_linux_android),
1738 ("arm-linux-androideabi", arm_linux_androideabi),
1739 ("armv7-linux-androideabi", armv7_linux_androideabi),
1740 ("thumbv7neon-linux-androideabi", thumbv7neon_linux_androideabi),
1741 ("aarch64-linux-android", aarch64_linux_android),
1742 ("riscv64-linux-android", riscv64_linux_android),
1743
1744 ("aarch64-unknown-freebsd", aarch64_unknown_freebsd),
1745 ("armv6-unknown-freebsd", armv6_unknown_freebsd),
1746 ("armv7-unknown-freebsd", armv7_unknown_freebsd),
1747 ("i686-unknown-freebsd", i686_unknown_freebsd),
1748 ("powerpc-unknown-freebsd", powerpc_unknown_freebsd),
1749 ("powerpc64-unknown-freebsd", powerpc64_unknown_freebsd),
1750 ("powerpc64le-unknown-freebsd", powerpc64le_unknown_freebsd),
1751 ("riscv64gc-unknown-freebsd", riscv64gc_unknown_freebsd),
1752 ("x86_64-unknown-freebsd", x86_64_unknown_freebsd),
1753
1754 ("x86_64-unknown-dragonfly", x86_64_unknown_dragonfly),
1755
1756 ("aarch64-unknown-openbsd", aarch64_unknown_openbsd),
1757 ("i686-unknown-openbsd", i686_unknown_openbsd),
1758 ("powerpc-unknown-openbsd", powerpc_unknown_openbsd),
1759 ("powerpc64-unknown-openbsd", powerpc64_unknown_openbsd),
1760 ("riscv64gc-unknown-openbsd", riscv64gc_unknown_openbsd),
1761 ("sparc64-unknown-openbsd", sparc64_unknown_openbsd),
1762 ("x86_64-unknown-openbsd", x86_64_unknown_openbsd),
1763
1764 ("aarch64-unknown-netbsd", aarch64_unknown_netbsd),
1765 ("aarch64_be-unknown-netbsd", aarch64_be_unknown_netbsd),
1766 ("armv6-unknown-netbsd-eabihf", armv6_unknown_netbsd_eabihf),
1767 ("armv7-unknown-netbsd-eabihf", armv7_unknown_netbsd_eabihf),
1768 ("i586-unknown-netbsd", i586_unknown_netbsd),
1769 ("i686-unknown-netbsd", i686_unknown_netbsd),
1770 ("mipsel-unknown-netbsd", mipsel_unknown_netbsd),
1771 ("powerpc-unknown-netbsd", powerpc_unknown_netbsd),
1772 ("riscv64gc-unknown-netbsd", riscv64gc_unknown_netbsd),
1773 ("sparc64-unknown-netbsd", sparc64_unknown_netbsd),
1774 ("x86_64-unknown-netbsd", x86_64_unknown_netbsd),
1775
1776 ("i686-unknown-haiku", i686_unknown_haiku),
1777 ("x86_64-unknown-haiku", x86_64_unknown_haiku),
1778
1779 ("i686-unknown-hurd-gnu", i686_unknown_hurd_gnu),
1780 ("x86_64-unknown-hurd-gnu", x86_64_unknown_hurd_gnu),
1781
1782 ("aarch64-apple-darwin", aarch64_apple_darwin),
1783 ("arm64e-apple-darwin", arm64e_apple_darwin),
1784 ("x86_64-apple-darwin", x86_64_apple_darwin),
1785 ("x86_64h-apple-darwin", x86_64h_apple_darwin),
1786 ("i686-apple-darwin", i686_apple_darwin),
1787
1788 ("aarch64-unknown-fuchsia", aarch64_unknown_fuchsia),
1789 ("riscv64gc-unknown-fuchsia", riscv64gc_unknown_fuchsia),
1790 ("x86_64-unknown-fuchsia", x86_64_unknown_fuchsia),
1791
1792 ("avr-unknown-gnu-atmega328", avr_unknown_gnu_atmega328),
1793
1794 ("x86_64-unknown-l4re-uclibc", x86_64_unknown_l4re_uclibc),
1795
1796 ("aarch64-unknown-redox", aarch64_unknown_redox),
1797 ("i586-unknown-redox", i586_unknown_redox),
1798 ("x86_64-unknown-redox", x86_64_unknown_redox),
1799
1800 ("i386-apple-ios", i386_apple_ios),
1801 ("x86_64-apple-ios", x86_64_apple_ios),
1802 ("aarch64-apple-ios", aarch64_apple_ios),
1803 ("arm64e-apple-ios", arm64e_apple_ios),
1804 ("armv7s-apple-ios", armv7s_apple_ios),
1805 ("x86_64-apple-ios-macabi", x86_64_apple_ios_macabi),
1806 ("aarch64-apple-ios-macabi", aarch64_apple_ios_macabi),
1807 ("aarch64-apple-ios-sim", aarch64_apple_ios_sim),
1808
1809 ("aarch64-apple-tvos", aarch64_apple_tvos),
1810 ("aarch64-apple-tvos-sim", aarch64_apple_tvos_sim),
1811 ("arm64e-apple-tvos", arm64e_apple_tvos),
1812 ("x86_64-apple-tvos", x86_64_apple_tvos),
1813
1814 ("armv7k-apple-watchos", armv7k_apple_watchos),
1815 ("arm64_32-apple-watchos", arm64_32_apple_watchos),
1816 ("x86_64-apple-watchos-sim", x86_64_apple_watchos_sim),
1817 ("aarch64-apple-watchos", aarch64_apple_watchos),
1818 ("aarch64-apple-watchos-sim", aarch64_apple_watchos_sim),
1819
1820 ("aarch64-apple-visionos", aarch64_apple_visionos),
1821 ("aarch64-apple-visionos-sim", aarch64_apple_visionos_sim),
1822
1823 ("armebv7r-none-eabi", armebv7r_none_eabi),
1824 ("armebv7r-none-eabihf", armebv7r_none_eabihf),
1825 ("armv7r-none-eabi", armv7r_none_eabi),
1826 ("armv7r-none-eabihf", armv7r_none_eabihf),
1827 ("armv8r-none-eabihf", armv8r_none_eabihf),
1828
1829 ("armv7-rtems-eabihf", armv7_rtems_eabihf),
1830
1831 ("x86_64-pc-solaris", x86_64_pc_solaris),
1832 ("sparcv9-sun-solaris", sparcv9_sun_solaris),
1833
1834 ("x86_64-unknown-illumos", x86_64_unknown_illumos),
1835 ("aarch64-unknown-illumos", aarch64_unknown_illumos),
1836
1837 ("x86_64-pc-windows-gnu", x86_64_pc_windows_gnu),
1838 ("x86_64-uwp-windows-gnu", x86_64_uwp_windows_gnu),
1839 ("x86_64-win7-windows-gnu", x86_64_win7_windows_gnu),
1840 ("i686-pc-windows-gnu", i686_pc_windows_gnu),
1841 ("i686-uwp-windows-gnu", i686_uwp_windows_gnu),
1842 ("i686-win7-windows-gnu", i686_win7_windows_gnu),
1843
1844 ("aarch64-pc-windows-gnullvm", aarch64_pc_windows_gnullvm),
1845 ("i686-pc-windows-gnullvm", i686_pc_windows_gnullvm),
1846 ("x86_64-pc-windows-gnullvm", x86_64_pc_windows_gnullvm),
1847
1848 ("aarch64-pc-windows-msvc", aarch64_pc_windows_msvc),
1849 ("aarch64-uwp-windows-msvc", aarch64_uwp_windows_msvc),
1850 ("arm64ec-pc-windows-msvc", arm64ec_pc_windows_msvc),
1851 ("x86_64-pc-windows-msvc", x86_64_pc_windows_msvc),
1852 ("x86_64-uwp-windows-msvc", x86_64_uwp_windows_msvc),
1853 ("x86_64-win7-windows-msvc", x86_64_win7_windows_msvc),
1854 ("i686-pc-windows-msvc", i686_pc_windows_msvc),
1855 ("i686-uwp-windows-msvc", i686_uwp_windows_msvc),
1856 ("i686-win7-windows-msvc", i686_win7_windows_msvc),
1857 ("i586-pc-windows-msvc", i586_pc_windows_msvc),
1858 ("thumbv7a-pc-windows-msvc", thumbv7a_pc_windows_msvc),
1859 ("thumbv7a-uwp-windows-msvc", thumbv7a_uwp_windows_msvc),
1860
1861 ("wasm32-unknown-emscripten", wasm32_unknown_emscripten),
1862 ("wasm32-unknown-unknown", wasm32_unknown_unknown),
1863 ("wasm32v1-none", wasm32v1_none),
1864 ("wasm32-wasip1", wasm32_wasip1),
1865 ("wasm32-wasip2", wasm32_wasip2),
1866 ("wasm32-wasip1-threads", wasm32_wasip1_threads),
1867 ("wasm64-unknown-unknown", wasm64_unknown_unknown),
1868
1869 ("thumbv6m-none-eabi", thumbv6m_none_eabi),
1870 ("thumbv7m-none-eabi", thumbv7m_none_eabi),
1871 ("thumbv7em-none-eabi", thumbv7em_none_eabi),
1872 ("thumbv7em-none-eabihf", thumbv7em_none_eabihf),
1873 ("thumbv8m.base-none-eabi", thumbv8m_base_none_eabi),
1874 ("thumbv8m.main-none-eabi", thumbv8m_main_none_eabi),
1875 ("thumbv8m.main-none-eabihf", thumbv8m_main_none_eabihf),
1876
1877 ("armv7a-none-eabi", armv7a_none_eabi),
1878 ("armv7a-none-eabihf", armv7a_none_eabihf),
1879 ("armv7a-nuttx-eabi", armv7a_nuttx_eabi),
1880 ("armv7a-nuttx-eabihf", armv7a_nuttx_eabihf),
1881
1882 ("msp430-none-elf", msp430_none_elf),
1883
1884 ("aarch64-unknown-hermit", aarch64_unknown_hermit),
1885 ("riscv64gc-unknown-hermit", riscv64gc_unknown_hermit),
1886 ("x86_64-unknown-hermit", x86_64_unknown_hermit),
1887
1888 ("x86_64-unikraft-linux-musl", x86_64_unikraft_linux_musl),
1889
1890 ("armv7-unknown-trusty", armv7_unknown_trusty),
1891 ("aarch64-unknown-trusty", aarch64_unknown_trusty),
1892 ("x86_64-unknown-trusty", x86_64_unknown_trusty),
1893
1894 ("riscv32i-unknown-none-elf", riscv32i_unknown_none_elf),
1895 ("riscv32im-risc0-zkvm-elf", riscv32im_risc0_zkvm_elf),
1896 ("riscv32im-unknown-none-elf", riscv32im_unknown_none_elf),
1897 ("riscv32ima-unknown-none-elf", riscv32ima_unknown_none_elf),
1898 ("riscv32imc-unknown-none-elf", riscv32imc_unknown_none_elf),
1899 ("riscv32imc-esp-espidf", riscv32imc_esp_espidf),
1900 ("riscv32imac-esp-espidf", riscv32imac_esp_espidf),
1901 ("riscv32imafc-esp-espidf", riscv32imafc_esp_espidf),
1902
1903 ("riscv32e-unknown-none-elf", riscv32e_unknown_none_elf),
1904 ("riscv32em-unknown-none-elf", riscv32em_unknown_none_elf),
1905 ("riscv32emc-unknown-none-elf", riscv32emc_unknown_none_elf),
1906
1907 ("riscv32imac-unknown-none-elf", riscv32imac_unknown_none_elf),
1908 ("riscv32imafc-unknown-none-elf", riscv32imafc_unknown_none_elf),
1909 ("riscv32imac-unknown-xous-elf", riscv32imac_unknown_xous_elf),
1910 ("riscv32gc-unknown-linux-gnu", riscv32gc_unknown_linux_gnu),
1911 ("riscv32gc-unknown-linux-musl", riscv32gc_unknown_linux_musl),
1912 ("riscv64imac-unknown-none-elf", riscv64imac_unknown_none_elf),
1913 ("riscv64gc-unknown-none-elf", riscv64gc_unknown_none_elf),
1914 ("riscv64gc-unknown-linux-gnu", riscv64gc_unknown_linux_gnu),
1915 ("riscv64gc-unknown-linux-musl", riscv64gc_unknown_linux_musl),
1916
1917 ("sparc-unknown-none-elf", sparc_unknown_none_elf),
1918
1919 ("loongarch64-unknown-none", loongarch64_unknown_none),
1920 ("loongarch64-unknown-none-softfloat", loongarch64_unknown_none_softfloat),
1921
1922 ("aarch64-unknown-none", aarch64_unknown_none),
1923 ("aarch64-unknown-none-softfloat", aarch64_unknown_none_softfloat),
1924 ("aarch64-unknown-nuttx", aarch64_unknown_nuttx),
1925
1926 ("x86_64-fortanix-unknown-sgx", x86_64_fortanix_unknown_sgx),
1927
1928 ("x86_64-unknown-uefi", x86_64_unknown_uefi),
1929 ("i686-unknown-uefi", i686_unknown_uefi),
1930 ("aarch64-unknown-uefi", aarch64_unknown_uefi),
1931
1932 ("nvptx64-nvidia-cuda", nvptx64_nvidia_cuda),
1933
1934 ("amdgcn-amd-amdhsa", amdgcn_amd_amdhsa),
1935
1936 ("xtensa-esp32-none-elf", xtensa_esp32_none_elf),
1937 ("xtensa-esp32-espidf", xtensa_esp32_espidf),
1938 ("xtensa-esp32s2-none-elf", xtensa_esp32s2_none_elf),
1939 ("xtensa-esp32s2-espidf", xtensa_esp32s2_espidf),
1940 ("xtensa-esp32s3-none-elf", xtensa_esp32s3_none_elf),
1941 ("xtensa-esp32s3-espidf", xtensa_esp32s3_espidf),
1942
1943 ("i686-wrs-vxworks", i686_wrs_vxworks),
1944 ("x86_64-wrs-vxworks", x86_64_wrs_vxworks),
1945 ("armv7-wrs-vxworks-eabihf", armv7_wrs_vxworks_eabihf),
1946 ("aarch64-wrs-vxworks", aarch64_wrs_vxworks),
1947 ("powerpc-wrs-vxworks", powerpc_wrs_vxworks),
1948 ("powerpc-wrs-vxworks-spe", powerpc_wrs_vxworks_spe),
1949 ("powerpc64-wrs-vxworks", powerpc64_wrs_vxworks),
1950 ("riscv32-wrs-vxworks", riscv32_wrs_vxworks),
1951 ("riscv64-wrs-vxworks", riscv64_wrs_vxworks),
1952
1953 ("aarch64-kmc-solid_asp3", aarch64_kmc_solid_asp3),
1954 ("armv7a-kmc-solid_asp3-eabi", armv7a_kmc_solid_asp3_eabi),
1955 ("armv7a-kmc-solid_asp3-eabihf", armv7a_kmc_solid_asp3_eabihf),
1956
1957 ("mipsel-sony-psp", mipsel_sony_psp),
1958 ("mipsel-sony-psx", mipsel_sony_psx),
1959 ("mipsel-unknown-none", mipsel_unknown_none),
1960 ("mips-mti-none-elf", mips_mti_none_elf),
1961 ("mipsel-mti-none-elf", mipsel_mti_none_elf),
1962 ("thumbv4t-none-eabi", thumbv4t_none_eabi),
1963 ("armv4t-none-eabi", armv4t_none_eabi),
1964 ("thumbv5te-none-eabi", thumbv5te_none_eabi),
1965 ("armv5te-none-eabi", armv5te_none_eabi),
1966
1967 ("aarch64_be-unknown-linux-gnu", aarch64_be_unknown_linux_gnu),
1968 ("aarch64-unknown-linux-gnu_ilp32", aarch64_unknown_linux_gnu_ilp32),
1969 ("aarch64_be-unknown-linux-gnu_ilp32", aarch64_be_unknown_linux_gnu_ilp32),
1970
1971 ("bpfeb-unknown-none", bpfeb_unknown_none),
1972 ("bpfel-unknown-none", bpfel_unknown_none),
1973
1974 ("armv6k-nintendo-3ds", armv6k_nintendo_3ds),
1975
1976 ("aarch64-nintendo-switch-freestanding", aarch64_nintendo_switch_freestanding),
1977
1978 ("armv7-sony-vita-newlibeabihf", armv7_sony_vita_newlibeabihf),
1979
1980 ("armv7-unknown-linux-uclibceabi", armv7_unknown_linux_uclibceabi),
1981 ("armv7-unknown-linux-uclibceabihf", armv7_unknown_linux_uclibceabihf),
1982
1983 ("x86_64-unknown-none", x86_64_unknown_none),
1984
1985 ("aarch64-unknown-teeos", aarch64_unknown_teeos),
1986
1987 ("mips64-openwrt-linux-musl", mips64_openwrt_linux_musl),
1988
1989 ("aarch64-unknown-nto-qnx700", aarch64_unknown_nto_qnx700),
1990 ("aarch64-unknown-nto-qnx710", aarch64_unknown_nto_qnx710),
1991 ("aarch64-unknown-nto-qnx710_iosock", aarch64_unknown_nto_qnx710_iosock),
1992 ("aarch64-unknown-nto-qnx800", aarch64_unknown_nto_qnx800),
1993 ("x86_64-pc-nto-qnx710", x86_64_pc_nto_qnx710),
1994 ("x86_64-pc-nto-qnx710_iosock", x86_64_pc_nto_qnx710_iosock),
1995 ("x86_64-pc-nto-qnx800", x86_64_pc_nto_qnx800),
1996 ("i586-pc-nto-qnx700", i586_pc_nto_qnx700),
1997
1998 ("aarch64-unknown-linux-ohos", aarch64_unknown_linux_ohos),
1999 ("armv7-unknown-linux-ohos", armv7_unknown_linux_ohos),
2000 ("loongarch64-unknown-linux-ohos", loongarch64_unknown_linux_ohos),
2001 ("x86_64-unknown-linux-ohos", x86_64_unknown_linux_ohos),
2002
2003 ("x86_64-unknown-linux-none", x86_64_unknown_linux_none),
2004
2005 ("thumbv6m-nuttx-eabi", thumbv6m_nuttx_eabi),
2006 ("thumbv7a-nuttx-eabi", thumbv7a_nuttx_eabi),
2007 ("thumbv7a-nuttx-eabihf", thumbv7a_nuttx_eabihf),
2008 ("thumbv7m-nuttx-eabi", thumbv7m_nuttx_eabi),
2009 ("thumbv7em-nuttx-eabi", thumbv7em_nuttx_eabi),
2010 ("thumbv7em-nuttx-eabihf", thumbv7em_nuttx_eabihf),
2011 ("thumbv8m.base-nuttx-eabi", thumbv8m_base_nuttx_eabi),
2012 ("thumbv8m.main-nuttx-eabi", thumbv8m_main_nuttx_eabi),
2013 ("thumbv8m.main-nuttx-eabihf", thumbv8m_main_nuttx_eabihf),
2014 ("riscv32imc-unknown-nuttx-elf", riscv32imc_unknown_nuttx_elf),
2015 ("riscv32imac-unknown-nuttx-elf", riscv32imac_unknown_nuttx_elf),
2016 ("riscv32imafc-unknown-nuttx-elf", riscv32imafc_unknown_nuttx_elf),
2017 ("riscv64imac-unknown-nuttx-elf", riscv64imac_unknown_nuttx_elf),
2018 ("riscv64gc-unknown-nuttx-elf", riscv64gc_unknown_nuttx_elf),
2019
2020 ("x86_64-pc-cygwin", x86_64_pc_cygwin),
2021}
2022
2023macro_rules! cvs {
2025 () => {
2026 ::std::borrow::Cow::Borrowed(&[])
2027 };
2028 ($($x:expr),+ $(,)?) => {
2029 ::std::borrow::Cow::Borrowed(&[
2030 $(
2031 ::std::borrow::Cow::Borrowed($x),
2032 )*
2033 ])
2034 };
2035}
2036
2037pub(crate) use cvs;
2038
2039#[derive(Debug, PartialEq)]
2043pub struct TargetWarnings {
2044 unused_fields: Vec<String>,
2045 incorrect_type: Vec<String>,
2046}
2047
2048impl TargetWarnings {
2049 pub fn empty() -> Self {
2050 Self { unused_fields: Vec::new(), incorrect_type: Vec::new() }
2051 }
2052
2053 pub fn warning_messages(&self) -> Vec<String> {
2054 let mut warnings = vec![];
2055 if !self.unused_fields.is_empty() {
2056 warnings.push(format!(
2057 "target json file contains unused fields: {}",
2058 self.unused_fields.join(", ")
2059 ));
2060 }
2061 if !self.incorrect_type.is_empty() {
2062 warnings.push(format!(
2063 "target json file contains fields whose value doesn't have the correct json type: {}",
2064 self.incorrect_type.join(", ")
2065 ));
2066 }
2067 warnings
2068 }
2069}
2070
2071#[derive(Copy, Clone, Debug, PartialEq)]
2074enum TargetKind {
2075 Json,
2076 Builtin,
2077}
2078
2079#[derive(PartialEq, Clone, Debug)]
2083pub struct Target {
2084 pub llvm_target: StaticCow<str>,
2091 pub metadata: TargetMetadata,
2094 pub pointer_width: u32,
2096 pub arch: StaticCow<str>,
2099 pub data_layout: StaticCow<str>,
2101 pub options: TargetOptions,
2103}
2104
2105#[derive(Default, PartialEq, Clone, Debug)]
2109pub struct TargetMetadata {
2110 pub description: Option<StaticCow<str>>,
2113 pub tier: Option<u64>,
2115 pub host_tools: Option<bool>,
2117 pub std: Option<bool>,
2120}
2121
2122impl Target {
2123 pub fn parse_data_layout(&self) -> Result<TargetDataLayout, TargetDataLayoutErrors<'_>> {
2124 let mut dl = TargetDataLayout::parse_from_llvm_datalayout_string(&self.data_layout)?;
2125
2126 if dl.endian != self.endian {
2128 return Err(TargetDataLayoutErrors::InconsistentTargetArchitecture {
2129 dl: dl.endian.as_str(),
2130 target: self.endian.as_str(),
2131 });
2132 }
2133
2134 let target_pointer_width: u64 = self.pointer_width.into();
2135 if dl.pointer_size.bits() != target_pointer_width {
2136 return Err(TargetDataLayoutErrors::InconsistentTargetPointerWidth {
2137 pointer_size: dl.pointer_size.bits(),
2138 target: self.pointer_width,
2139 });
2140 }
2141
2142 dl.c_enum_min_size = self
2143 .c_enum_min_bits
2144 .map_or_else(
2145 || {
2146 self.c_int_width
2147 .parse()
2148 .map_err(|_| String::from("failed to parse c_int_width"))
2149 },
2150 Ok,
2151 )
2152 .and_then(|i| Integer::from_size(Size::from_bits(i)))
2153 .map_err(|err| TargetDataLayoutErrors::InvalidBitsSize { err })?;
2154
2155 Ok(dl)
2156 }
2157}
2158
2159pub trait HasTargetSpec {
2160 fn target_spec(&self) -> &Target;
2161}
2162
2163impl HasTargetSpec for Target {
2164 #[inline]
2165 fn target_spec(&self) -> &Target {
2166 self
2167 }
2168}
2169
2170#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
2172pub enum WasmCAbi {
2173 Spec,
2175 Legacy,
2177}
2178
2179pub trait HasWasmCAbiOpt {
2180 fn wasm_c_abi_opt(&self) -> WasmCAbi;
2181}
2182
2183#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
2185pub struct X86Abi {
2186 pub regparm: Option<u32>,
2189 pub reg_struct_return: bool,
2191}
2192
2193pub trait HasX86AbiOpt {
2194 fn x86_abi_opt(&self) -> X86Abi;
2195}
2196
2197type StaticCow<T> = Cow<'static, T>;
2198
2199#[derive(PartialEq, Clone, Debug)]
2208pub struct TargetOptions {
2209 pub endian: Endian,
2211 pub c_int_width: StaticCow<str>,
2213 pub os: StaticCow<str>,
2218 pub env: StaticCow<str>,
2220 pub abi: StaticCow<str>,
2225 pub vendor: StaticCow<str>,
2227
2228 pub linker: Option<StaticCow<str>>,
2230 pub linker_flavor: LinkerFlavor,
2233 linker_flavor_json: LinkerFlavorCli,
2234 lld_flavor_json: LldFlavor,
2235 linker_is_gnu_json: bool,
2236
2237 pub pre_link_objects: CrtObjects,
2239 pub post_link_objects: CrtObjects,
2240 pub pre_link_objects_self_contained: CrtObjects,
2242 pub post_link_objects_self_contained: CrtObjects,
2243 pub link_self_contained: LinkSelfContainedDefault,
2246
2247 pub pre_link_args: LinkArgs,
2249 pre_link_args_json: LinkArgsCli,
2250 pub late_link_args: LinkArgs,
2254 late_link_args_json: LinkArgsCli,
2255 pub late_link_args_dynamic: LinkArgs,
2258 late_link_args_dynamic_json: LinkArgsCli,
2259 pub late_link_args_static: LinkArgs,
2262 late_link_args_static_json: LinkArgsCli,
2263 pub post_link_args: LinkArgs,
2266 post_link_args_json: LinkArgsCli,
2267
2268 pub link_script: Option<StaticCow<str>>,
2272 pub link_env: StaticCow<[(StaticCow<str>, StaticCow<str>)]>,
2274 pub link_env_remove: StaticCow<[StaticCow<str>]>,
2276
2277 pub asm_args: StaticCow<[StaticCow<str>]>,
2279
2280 pub cpu: StaticCow<str>,
2283 pub need_explicit_cpu: bool,
2286 pub features: StaticCow<str>,
2295 pub direct_access_external_data: Option<bool>,
2297 pub dynamic_linking: bool,
2299 pub dll_tls_export: bool,
2301 pub only_cdylib: bool,
2303 pub executables: bool,
2305 pub relocation_model: RelocModel,
2308 pub code_model: Option<CodeModel>,
2311 pub tls_model: TlsModel,
2314 pub disable_redzone: bool,
2316 pub frame_pointer: FramePointer,
2318 pub function_sections: bool,
2320 pub dll_prefix: StaticCow<str>,
2322 pub dll_suffix: StaticCow<str>,
2324 pub exe_suffix: StaticCow<str>,
2326 pub staticlib_prefix: StaticCow<str>,
2328 pub staticlib_suffix: StaticCow<str>,
2330 pub families: StaticCow<[StaticCow<str>]>,
2336 pub abi_return_struct_as_int: bool,
2338 pub is_like_aix: bool,
2341 pub is_like_osx: bool,
2346 pub is_like_solaris: bool,
2350 pub is_like_windows: bool,
2358 pub is_like_msvc: bool,
2368 pub is_like_wasm: bool,
2370 pub is_like_android: bool,
2372 pub default_dwarf_version: u32,
2375 pub allows_weak_linkage: bool,
2382 pub has_rpath: bool,
2384 pub no_default_libraries: bool,
2387 pub position_independent_executables: bool,
2393 pub static_position_independent_executables: bool,
2395 pub plt_by_default: bool,
2398 pub relro_level: RelroLevel,
2402 pub archive_format: StaticCow<str>,
2407 pub allow_asm: bool,
2409 pub main_needs_argc_argv: bool,
2412
2413 pub has_thread_local: bool,
2415 pub obj_is_bitcode: bool,
2419 pub bitcode_llvm_cmdline: StaticCow<str>,
2421
2422 pub min_atomic_width: Option<u64>,
2424
2425 pub max_atomic_width: Option<u64>,
2427
2428 pub atomic_cas: bool,
2430
2431 pub panic_strategy: PanicStrategy,
2433
2434 pub crt_static_allows_dylibs: bool,
2436 pub crt_static_default: bool,
2438 pub crt_static_respected: bool,
2440
2441 pub stack_probes: StackProbeType,
2443
2444 pub min_global_align: Option<u64>,
2446
2447 pub default_codegen_units: Option<u64>,
2449
2450 pub default_codegen_backend: Option<StaticCow<str>>,
2460
2461 pub trap_unreachable: bool,
2464
2465 pub requires_lto: bool,
2468
2469 pub singlethread: bool,
2471
2472 pub no_builtins: bool,
2475
2476 pub default_visibility: Option<SymbolVisibility>,
2482
2483 pub emit_debug_gdb_scripts: bool,
2485
2486 pub requires_uwtable: bool,
2490
2491 pub default_uwtable: bool,
2494
2495 pub simd_types_indirect: bool,
2500
2501 pub limit_rdylib_exports: bool,
2503
2504 pub override_export_symbols: Option<StaticCow<[StaticCow<str>]>>,
2507
2508 pub merge_functions: MergeFunctions,
2515
2516 pub mcount: StaticCow<str>,
2518
2519 pub llvm_mcount_intrinsic: Option<StaticCow<str>>,
2521
2522 pub llvm_abiname: StaticCow<str>,
2525
2526 pub llvm_floatabi: Option<FloatAbi>,
2533
2534 pub rustc_abi: Option<RustcAbi>,
2539
2540 pub relax_elf_relocations: bool,
2542
2543 pub llvm_args: StaticCow<[StaticCow<str>]>,
2545
2546 pub use_ctors_section: bool,
2549
2550 pub eh_frame_header: bool,
2554
2555 pub has_thumb_interworking: bool,
2558
2559 pub debuginfo_kind: DebuginfoKind,
2561 pub split_debuginfo: SplitDebuginfo,
2564 pub supported_split_debuginfo: StaticCow<[SplitDebuginfo]>,
2566
2567 pub supported_sanitizers: SanitizerSet,
2573
2574 pub c_enum_min_bits: Option<u64>,
2576
2577 pub generate_arange_section: bool,
2579
2580 pub supports_stack_protector: bool,
2583
2584 pub entry_name: StaticCow<str>,
2587
2588 pub entry_abi: Conv,
2591
2592 pub supports_xray: bool,
2594
2595 small_data_threshold_support: SmallDataThresholdSupport,
2597}
2598
2599fn add_link_args_iter(
2602 link_args: &mut LinkArgs,
2603 flavor: LinkerFlavor,
2604 args: impl Iterator<Item = StaticCow<str>> + Clone,
2605) {
2606 let mut insert = |flavor| link_args.entry(flavor).or_default().extend(args.clone());
2607 insert(flavor);
2608 match flavor {
2609 LinkerFlavor::Gnu(cc, lld) => {
2610 assert_eq!(lld, Lld::No);
2611 insert(LinkerFlavor::Gnu(cc, Lld::Yes));
2612 }
2613 LinkerFlavor::Darwin(cc, lld) => {
2614 assert_eq!(lld, Lld::No);
2615 insert(LinkerFlavor::Darwin(cc, Lld::Yes));
2616 }
2617 LinkerFlavor::Msvc(lld) => {
2618 assert_eq!(lld, Lld::No);
2619 insert(LinkerFlavor::Msvc(Lld::Yes));
2620 }
2621 LinkerFlavor::WasmLld(..)
2622 | LinkerFlavor::Unix(..)
2623 | LinkerFlavor::EmCc
2624 | LinkerFlavor::Bpf
2625 | LinkerFlavor::Llbc
2626 | LinkerFlavor::Ptx => {}
2627 }
2628}
2629
2630fn add_link_args(link_args: &mut LinkArgs, flavor: LinkerFlavor, args: &[&'static str]) {
2631 add_link_args_iter(link_args, flavor, args.iter().copied().map(Cow::Borrowed))
2632}
2633
2634impl TargetOptions {
2635 pub fn supports_comdat(&self) -> bool {
2636 !self.is_like_aix && !self.is_like_osx
2638 }
2639}
2640
2641impl TargetOptions {
2642 fn link_args(flavor: LinkerFlavor, args: &[&'static str]) -> LinkArgs {
2643 let mut link_args = LinkArgs::new();
2644 add_link_args(&mut link_args, flavor, args);
2645 link_args
2646 }
2647
2648 fn add_pre_link_args(&mut self, flavor: LinkerFlavor, args: &[&'static str]) {
2649 add_link_args(&mut self.pre_link_args, flavor, args);
2650 }
2651
2652 fn update_from_cli(&mut self) {
2653 self.linker_flavor = LinkerFlavor::from_cli_json(
2654 self.linker_flavor_json,
2655 self.lld_flavor_json,
2656 self.linker_is_gnu_json,
2657 );
2658 for (args, args_json) in [
2659 (&mut self.pre_link_args, &self.pre_link_args_json),
2660 (&mut self.late_link_args, &self.late_link_args_json),
2661 (&mut self.late_link_args_dynamic, &self.late_link_args_dynamic_json),
2662 (&mut self.late_link_args_static, &self.late_link_args_static_json),
2663 (&mut self.post_link_args, &self.post_link_args_json),
2664 ] {
2665 args.clear();
2666 for (flavor, args_json) in args_json {
2667 let linker_flavor = self.linker_flavor.with_cli_hints(*flavor);
2668 let linker_flavor = match linker_flavor {
2670 LinkerFlavor::Gnu(cc, _) => LinkerFlavor::Gnu(cc, Lld::No),
2671 LinkerFlavor::Darwin(cc, _) => LinkerFlavor::Darwin(cc, Lld::No),
2672 LinkerFlavor::Msvc(_) => LinkerFlavor::Msvc(Lld::No),
2673 _ => linker_flavor,
2674 };
2675 if !args.contains_key(&linker_flavor) {
2676 add_link_args_iter(args, linker_flavor, args_json.iter().cloned());
2677 }
2678 }
2679 }
2680 }
2681
2682 fn update_to_cli(&mut self) {
2683 self.linker_flavor_json = self.linker_flavor.to_cli_counterpart();
2684 self.lld_flavor_json = self.linker_flavor.lld_flavor();
2685 self.linker_is_gnu_json = self.linker_flavor.is_gnu();
2686 for (args, args_json) in [
2687 (&self.pre_link_args, &mut self.pre_link_args_json),
2688 (&self.late_link_args, &mut self.late_link_args_json),
2689 (&self.late_link_args_dynamic, &mut self.late_link_args_dynamic_json),
2690 (&self.late_link_args_static, &mut self.late_link_args_static_json),
2691 (&self.post_link_args, &mut self.post_link_args_json),
2692 ] {
2693 *args_json = args
2694 .iter()
2695 .map(|(flavor, args)| (flavor.to_cli_counterpart(), args.clone()))
2696 .collect();
2697 }
2698 }
2699}
2700
2701impl Default for TargetOptions {
2702 fn default() -> TargetOptions {
2705 TargetOptions {
2706 endian: Endian::Little,
2707 c_int_width: "32".into(),
2708 os: "none".into(),
2709 env: "".into(),
2710 abi: "".into(),
2711 vendor: "unknown".into(),
2712 linker: option_env!("CFG_DEFAULT_LINKER").map(|s| s.into()),
2713 linker_flavor: LinkerFlavor::Gnu(Cc::Yes, Lld::No),
2714 linker_flavor_json: LinkerFlavorCli::Gcc,
2715 lld_flavor_json: LldFlavor::Ld,
2716 linker_is_gnu_json: true,
2717 link_script: None,
2718 asm_args: cvs![],
2719 cpu: "generic".into(),
2720 need_explicit_cpu: false,
2721 features: "".into(),
2722 direct_access_external_data: None,
2723 dynamic_linking: false,
2724 dll_tls_export: true,
2725 only_cdylib: false,
2726 executables: true,
2727 relocation_model: RelocModel::Pic,
2728 code_model: None,
2729 tls_model: TlsModel::GeneralDynamic,
2730 disable_redzone: false,
2731 frame_pointer: FramePointer::MayOmit,
2732 function_sections: true,
2733 dll_prefix: "lib".into(),
2734 dll_suffix: ".so".into(),
2735 exe_suffix: "".into(),
2736 staticlib_prefix: "lib".into(),
2737 staticlib_suffix: ".a".into(),
2738 families: cvs![],
2739 abi_return_struct_as_int: false,
2740 is_like_aix: false,
2741 is_like_osx: false,
2742 is_like_solaris: false,
2743 is_like_windows: false,
2744 is_like_msvc: false,
2745 is_like_wasm: false,
2746 is_like_android: false,
2747 default_dwarf_version: 4,
2748 allows_weak_linkage: true,
2749 has_rpath: false,
2750 no_default_libraries: true,
2751 position_independent_executables: false,
2752 static_position_independent_executables: false,
2753 plt_by_default: true,
2754 relro_level: RelroLevel::None,
2755 pre_link_objects: Default::default(),
2756 post_link_objects: Default::default(),
2757 pre_link_objects_self_contained: Default::default(),
2758 post_link_objects_self_contained: Default::default(),
2759 link_self_contained: LinkSelfContainedDefault::False,
2760 pre_link_args: LinkArgs::new(),
2761 pre_link_args_json: LinkArgsCli::new(),
2762 late_link_args: LinkArgs::new(),
2763 late_link_args_json: LinkArgsCli::new(),
2764 late_link_args_dynamic: LinkArgs::new(),
2765 late_link_args_dynamic_json: LinkArgsCli::new(),
2766 late_link_args_static: LinkArgs::new(),
2767 late_link_args_static_json: LinkArgsCli::new(),
2768 post_link_args: LinkArgs::new(),
2769 post_link_args_json: LinkArgsCli::new(),
2770 link_env: cvs![],
2771 link_env_remove: cvs![],
2772 archive_format: "gnu".into(),
2773 main_needs_argc_argv: true,
2774 allow_asm: true,
2775 has_thread_local: false,
2776 obj_is_bitcode: false,
2777 bitcode_llvm_cmdline: "".into(),
2778 min_atomic_width: None,
2779 max_atomic_width: None,
2780 atomic_cas: true,
2781 panic_strategy: PanicStrategy::Unwind,
2782 crt_static_allows_dylibs: false,
2783 crt_static_default: false,
2784 crt_static_respected: false,
2785 stack_probes: StackProbeType::None,
2786 min_global_align: None,
2787 default_codegen_units: None,
2788 default_codegen_backend: None,
2789 trap_unreachable: true,
2790 requires_lto: false,
2791 singlethread: false,
2792 no_builtins: false,
2793 default_visibility: None,
2794 emit_debug_gdb_scripts: true,
2795 requires_uwtable: false,
2796 default_uwtable: false,
2797 simd_types_indirect: true,
2798 limit_rdylib_exports: true,
2799 override_export_symbols: None,
2800 merge_functions: MergeFunctions::Aliases,
2801 mcount: "mcount".into(),
2802 llvm_mcount_intrinsic: None,
2803 llvm_abiname: "".into(),
2804 llvm_floatabi: None,
2805 rustc_abi: None,
2806 relax_elf_relocations: false,
2807 llvm_args: cvs![],
2808 use_ctors_section: false,
2809 eh_frame_header: true,
2810 has_thumb_interworking: false,
2811 debuginfo_kind: Default::default(),
2812 split_debuginfo: Default::default(),
2813 supported_split_debuginfo: Cow::Borrowed(&[SplitDebuginfo::Off]),
2815 supported_sanitizers: SanitizerSet::empty(),
2816 c_enum_min_bits: None,
2817 generate_arange_section: true,
2818 supports_stack_protector: true,
2819 entry_name: "main".into(),
2820 entry_abi: Conv::C,
2821 supports_xray: false,
2822 small_data_threshold_support: SmallDataThresholdSupport::DefaultForArch,
2823 }
2824 }
2825}
2826
2827impl Deref for Target {
2831 type Target = TargetOptions;
2832
2833 #[inline]
2834 fn deref(&self) -> &Self::Target {
2835 &self.options
2836 }
2837}
2838impl DerefMut for Target {
2839 #[inline]
2840 fn deref_mut(&mut self) -> &mut Self::Target {
2841 &mut self.options
2842 }
2843}
2844
2845impl Target {
2846 pub fn adjust_abi(&self, abi: ExternAbi, c_variadic: bool) -> ExternAbi {
2848 use ExternAbi::*;
2849 match abi {
2850 System { unwind } if self.is_like_windows && self.arch == "x86" && !c_variadic => {
2854 Stdcall { unwind }
2855 }
2856 System { unwind } => C { unwind },
2857 EfiApi if self.arch == "arm" => Aapcs { unwind: false },
2858 EfiApi if self.arch == "x86_64" => Win64 { unwind: false },
2859 EfiApi => C { unwind: false },
2860
2861 Stdcall { .. } | Thiscall { .. } if self.arch == "x86" => abi,
2863 Stdcall { unwind } | Thiscall { unwind } => C { unwind },
2864 Fastcall { .. } if self.arch == "x86" => abi,
2865 Vectorcall { .. } if ["x86", "x86_64"].contains(&&self.arch[..]) => abi,
2866 Fastcall { unwind } | Vectorcall { unwind } => C { unwind },
2867
2868 RustCold if self.is_like_windows && self.arch == "x86_64" => Rust,
2874
2875 abi => abi,
2876 }
2877 }
2878
2879 pub fn is_abi_supported(&self, abi: ExternAbi) -> bool {
2880 use ExternAbi::*;
2881 match abi {
2882 Rust
2883 | C { .. }
2884 | System { .. }
2885 | RustIntrinsic
2886 | RustCall
2887 | Unadjusted
2888 | Cdecl { .. }
2889 | RustCold => true,
2890 EfiApi => {
2891 ["arm", "aarch64", "riscv32", "riscv64", "x86", "x86_64"].contains(&&self.arch[..])
2892 }
2893 X86Interrupt => ["x86", "x86_64"].contains(&&self.arch[..]),
2894 Aapcs { .. } => "arm" == self.arch,
2895 CCmseNonSecureCall | CCmseNonSecureEntry => {
2896 ["thumbv8m.main-none-eabi", "thumbv8m.main-none-eabihf", "thumbv8m.base-none-eabi"]
2897 .contains(&&self.llvm_target[..])
2898 }
2899 Win64 { .. } | SysV64 { .. } => self.arch == "x86_64",
2900 PtxKernel => self.arch == "nvptx64",
2901 GpuKernel => ["amdgpu", "nvptx64"].contains(&&self.arch[..]),
2902 Msp430Interrupt => self.arch == "msp430",
2903 RiscvInterruptM | RiscvInterruptS => ["riscv32", "riscv64"].contains(&&self.arch[..]),
2904 AvrInterrupt | AvrNonBlockingInterrupt => self.arch == "avr",
2905 Thiscall { .. } => self.arch == "x86",
2906 Stdcall { .. } | Fastcall { .. } | Vectorcall { .. } if self.is_like_windows => true,
2937 Stdcall { .. } | Fastcall { .. } if self.arch == "x86" => true,
2940 Vectorcall { .. } if ["x86", "x86_64"].contains(&&self.arch[..]) => true,
2941 Stdcall { .. } | Fastcall { .. } | Vectorcall { .. } => false,
2943 }
2944 }
2945
2946 pub fn min_atomic_width(&self) -> u64 {
2949 self.min_atomic_width.unwrap_or(8)
2950 }
2951
2952 pub fn max_atomic_width(&self) -> u64 {
2955 self.max_atomic_width.unwrap_or_else(|| self.pointer_width.into())
2956 }
2957
2958 fn check_consistency(&self, kind: TargetKind) -> Result<(), String> {
2961 macro_rules! check {
2962 ($b:expr, $($msg:tt)*) => {
2963 if !$b {
2964 return Err(format!($($msg)*));
2965 }
2966 }
2967 }
2968 macro_rules! check_eq {
2969 ($left:expr, $right:expr, $($msg:tt)*) => {
2970 if ($left) != ($right) {
2971 return Err(format!($($msg)*));
2972 }
2973 }
2974 }
2975 macro_rules! check_ne {
2976 ($left:expr, $right:expr, $($msg:tt)*) => {
2977 if ($left) == ($right) {
2978 return Err(format!($($msg)*));
2979 }
2980 }
2981 }
2982 macro_rules! check_matches {
2983 ($left:expr, $right:pat, $($msg:tt)*) => {
2984 if !matches!($left, $right) {
2985 return Err(format!($($msg)*));
2986 }
2987 }
2988 }
2989
2990 check_eq!(
2991 self.is_like_osx,
2992 self.vendor == "apple",
2993 "`is_like_osx` must be set if and only if `vendor` is `apple`"
2994 );
2995 check_eq!(
2996 self.is_like_solaris,
2997 self.os == "solaris" || self.os == "illumos",
2998 "`is_like_solaris` must be set if and only if `os` is `solaris` or `illumos`"
2999 );
3000 check_eq!(
3001 self.is_like_windows,
3002 self.os == "windows" || self.os == "uefi" || self.os == "cygwin",
3003 "`is_like_windows` must be set if and only if `os` is `windows`, `uefi` or `cygwin`"
3004 );
3005 check_eq!(
3006 self.is_like_wasm,
3007 self.arch == "wasm32" || self.arch == "wasm64",
3008 "`is_like_wasm` must be set if and only if `arch` is `wasm32` or `wasm64`"
3009 );
3010 if self.is_like_msvc {
3011 check!(self.is_like_windows, "if `is_like_msvc` is set, `is_like_windows` must be set");
3012 }
3013 if self.os == "emscripten" {
3014 check!(self.is_like_wasm, "the `emcscripten` os only makes sense on wasm-like targets");
3015 }
3016
3017 check_eq!(
3019 self.is_like_osx,
3020 matches!(self.linker_flavor, LinkerFlavor::Darwin(..)),
3021 "`linker_flavor` must be `darwin` if and only if `is_like_osx` is set"
3022 );
3023 check_eq!(
3024 self.is_like_msvc,
3025 matches!(self.linker_flavor, LinkerFlavor::Msvc(..)),
3026 "`linker_flavor` must be `msvc` if and only if `is_like_msvc` is set"
3027 );
3028 check_eq!(
3029 self.is_like_wasm && self.os != "emscripten",
3030 matches!(self.linker_flavor, LinkerFlavor::WasmLld(..)),
3031 "`linker_flavor` must be `wasm-lld` if and only if `is_like_wasm` is set and the `os` is not `emscripten`",
3032 );
3033 check_eq!(
3034 self.os == "emscripten",
3035 matches!(self.linker_flavor, LinkerFlavor::EmCc),
3036 "`linker_flavor` must be `em-cc` if and only if `os` is `emscripten`"
3037 );
3038 check_eq!(
3039 self.arch == "bpf",
3040 matches!(self.linker_flavor, LinkerFlavor::Bpf),
3041 "`linker_flavor` must be `bpf` if and only if `arch` is `bpf`"
3042 );
3043 check_eq!(
3044 self.arch == "nvptx64",
3045 matches!(self.linker_flavor, LinkerFlavor::Ptx),
3046 "`linker_flavor` must be `ptc` if and only if `arch` is `nvptx64`"
3047 );
3048
3049 for args in [
3050 &self.pre_link_args,
3051 &self.late_link_args,
3052 &self.late_link_args_dynamic,
3053 &self.late_link_args_static,
3054 &self.post_link_args,
3055 ] {
3056 for (&flavor, flavor_args) in args {
3057 check!(!flavor_args.is_empty(), "linker flavor args must not be empty");
3058 match self.linker_flavor {
3060 LinkerFlavor::Gnu(..) => {
3061 check_matches!(
3062 flavor,
3063 LinkerFlavor::Gnu(..),
3064 "mixing GNU and non-GNU linker flavors"
3065 );
3066 }
3067 LinkerFlavor::Darwin(..) => {
3068 check_matches!(
3069 flavor,
3070 LinkerFlavor::Darwin(..),
3071 "mixing Darwin and non-Darwin linker flavors"
3072 )
3073 }
3074 LinkerFlavor::WasmLld(..) => {
3075 check_matches!(
3076 flavor,
3077 LinkerFlavor::WasmLld(..),
3078 "mixing wasm and non-wasm linker flavors"
3079 )
3080 }
3081 LinkerFlavor::Unix(..) => {
3082 check_matches!(
3083 flavor,
3084 LinkerFlavor::Unix(..),
3085 "mixing unix and non-unix linker flavors"
3086 );
3087 }
3088 LinkerFlavor::Msvc(..) => {
3089 check_matches!(
3090 flavor,
3091 LinkerFlavor::Msvc(..),
3092 "mixing MSVC and non-MSVC linker flavors"
3093 );
3094 }
3095 LinkerFlavor::EmCc
3096 | LinkerFlavor::Bpf
3097 | LinkerFlavor::Ptx
3098 | LinkerFlavor::Llbc => {
3099 check_eq!(flavor, self.linker_flavor, "mixing different linker flavors")
3100 }
3101 }
3102
3103 let check_noncc = |noncc_flavor| -> Result<(), String> {
3105 if let Some(noncc_args) = args.get(&noncc_flavor) {
3106 for arg in flavor_args {
3107 if let Some(suffix) = arg.strip_prefix("-Wl,") {
3108 check!(
3109 noncc_args.iter().any(|a| a == suffix),
3110 " link args for cc and non-cc versions of flavors are not consistent"
3111 );
3112 }
3113 }
3114 }
3115 Ok(())
3116 };
3117
3118 match self.linker_flavor {
3119 LinkerFlavor::Gnu(Cc::Yes, lld) => check_noncc(LinkerFlavor::Gnu(Cc::No, lld))?,
3120 LinkerFlavor::WasmLld(Cc::Yes) => check_noncc(LinkerFlavor::WasmLld(Cc::No))?,
3121 LinkerFlavor::Unix(Cc::Yes) => check_noncc(LinkerFlavor::Unix(Cc::No))?,
3122 _ => {}
3123 }
3124 }
3125
3126 for cc in [Cc::No, Cc::Yes] {
3128 check_eq!(
3129 args.get(&LinkerFlavor::Gnu(cc, Lld::No)),
3130 args.get(&LinkerFlavor::Gnu(cc, Lld::Yes)),
3131 "link args for lld and non-lld versions of flavors are not consistent",
3132 );
3133 check_eq!(
3134 args.get(&LinkerFlavor::Darwin(cc, Lld::No)),
3135 args.get(&LinkerFlavor::Darwin(cc, Lld::Yes)),
3136 "link args for lld and non-lld versions of flavors are not consistent",
3137 );
3138 }
3139 check_eq!(
3140 args.get(&LinkerFlavor::Msvc(Lld::No)),
3141 args.get(&LinkerFlavor::Msvc(Lld::Yes)),
3142 "link args for lld and non-lld versions of flavors are not consistent",
3143 );
3144 }
3145
3146 if self.link_self_contained.is_disabled() {
3147 check!(
3148 self.pre_link_objects_self_contained.is_empty()
3149 && self.post_link_objects_self_contained.is_empty(),
3150 "if `link_self_contained` is disabled, then `pre_link_objects_self_contained` and `post_link_objects_self_contained` must be empty",
3151 );
3152 }
3153
3154 check_ne!(self.vendor, "", "`vendor` cannot be empty");
3158 check_ne!(self.os, "", "`os` cannot be empty");
3159 if !self.can_use_os_unknown() {
3160 check_ne!(
3162 self.os,
3163 "unknown",
3164 "`unknown` os can only be used on particular targets; use `none` for bare-metal targets"
3165 );
3166 }
3167
3168 if kind == TargetKind::Builtin {
3174 if self.os == "none"
3178 && (self.arch != "bpf"
3179 && self.arch != "hexagon"
3180 && self.arch != "wasm32"
3181 && self.arch != "wasm64")
3182 {
3183 check!(
3184 !self.dynamic_linking,
3185 "dynamic linking is not supported on this OS/architecture"
3186 );
3187 }
3188 if self.only_cdylib
3189 || self.crt_static_allows_dylibs
3190 || !self.late_link_args_dynamic.is_empty()
3191 {
3192 check!(
3193 self.dynamic_linking,
3194 "dynamic linking must be allowed when `only_cdylib` or `crt_static_allows_dylibs` or `late_link_args_dynamic` are set"
3195 );
3196 }
3197 if self.dynamic_linking && !self.is_like_wasm {
3199 check_eq!(
3200 self.relocation_model,
3201 RelocModel::Pic,
3202 "targets that support dynamic linking must use the `pic` relocation model"
3203 );
3204 }
3205 if self.position_independent_executables {
3206 check_eq!(
3207 self.relocation_model,
3208 RelocModel::Pic,
3209 "targets that support position-independent executables must use the `pic` relocation model"
3210 );
3211 }
3212 if self.relocation_model == RelocModel::Pic && (self.os != "uefi") {
3214 check!(
3215 self.dynamic_linking || self.position_independent_executables,
3216 "when the relocation model is `pic`, the target must support dynamic linking or use position-independent executables. \
3217 Set the relocation model to `static` to avoid this requirement"
3218 );
3219 }
3220 if self.static_position_independent_executables {
3221 check!(
3222 self.position_independent_executables,
3223 "if `static_position_independent_executables` is set, then `position_independent_executables` must be set"
3224 );
3225 }
3226 if self.position_independent_executables {
3227 check!(
3228 self.executables,
3229 "if `position_independent_executables` is set then `executables` must be set"
3230 );
3231 }
3232 }
3233
3234 if self.crt_static_default || self.crt_static_allows_dylibs {
3236 check!(
3237 self.crt_static_respected,
3238 "static CRT can be enabled but `crt_static_respected` is not set"
3239 );
3240 }
3241
3242 match &*self.arch {
3245 "riscv32" => {
3246 check_matches!(
3247 &*self.llvm_abiname,
3248 "ilp32" | "ilp32f" | "ilp32d" | "ilp32e",
3249 "invalid RISC-V ABI name: {}",
3250 self.llvm_abiname,
3251 );
3252 }
3253 "riscv64" => {
3254 check_matches!(
3256 &*self.llvm_abiname,
3257 "lp64" | "lp64f" | "lp64d" | "lp64e",
3258 "invalid RISC-V ABI name: {}",
3259 self.llvm_abiname,
3260 );
3261 }
3262 "arm" => {
3263 check!(self.llvm_floatabi.is_some(), "ARM targets must specify their float ABI",)
3264 }
3265 _ => {}
3266 }
3267
3268 if let Some(rust_abi) = self.rustc_abi {
3270 match rust_abi {
3271 RustcAbi::X86Sse2 => check_matches!(
3272 &*self.arch,
3273 "x86",
3274 "`x86-sse2` ABI is only valid for x86-32 targets"
3275 ),
3276 RustcAbi::X86Softfloat => check_matches!(
3277 &*self.arch,
3278 "x86" | "x86_64",
3279 "`x86-softfloat` ABI is only valid for x86 targets"
3280 ),
3281 }
3282 }
3283
3284 if !self.features.is_empty() {
3286 let mut features_enabled = FxHashSet::default();
3287 let mut features_disabled = FxHashSet::default();
3288 for feat in self.features.split(',') {
3289 if let Some(feat) = feat.strip_prefix("+") {
3290 features_enabled.insert(feat);
3291 if features_disabled.contains(feat) {
3292 return Err(format!(
3293 "target feature `{feat}` is both enabled and disabled"
3294 ));
3295 }
3296 } else if let Some(feat) = feat.strip_prefix("-") {
3297 features_disabled.insert(feat);
3298 if features_enabled.contains(feat) {
3299 return Err(format!(
3300 "target feature `{feat}` is both enabled and disabled"
3301 ));
3302 }
3303 } else {
3304 return Err(format!(
3305 "target feature `{feat}` is invalid, must start with `+` or `-`"
3306 ));
3307 }
3308 }
3309 let abi_feature_constraints = self.abi_required_features();
3311 for feat in abi_feature_constraints.required {
3312 if features_disabled.contains(feat) {
3315 return Err(format!(
3316 "target feature `{feat}` is required by the ABI but gets disabled in target spec"
3317 ));
3318 }
3319 }
3320 for feat in abi_feature_constraints.incompatible {
3321 if features_enabled.contains(feat) {
3324 return Err(format!(
3325 "target feature `{feat}` is incompatible with the ABI but gets enabled in target spec"
3326 ));
3327 }
3328 }
3329 }
3330
3331 Ok(())
3332 }
3333
3334 #[cfg(test)]
3336 fn test_target(mut self) {
3337 let recycled_target = Target::from_json(self.to_json()).map(|(j, _)| j);
3338 self.update_to_cli();
3339 self.check_consistency(TargetKind::Builtin).unwrap();
3340 assert_eq!(recycled_target, Ok(self));
3341 }
3342
3343 fn can_use_os_unknown(&self) -> bool {
3346 self.llvm_target == "wasm32-unknown-unknown"
3347 || self.llvm_target == "wasm64-unknown-unknown"
3348 || (self.env == "sgx" && self.vendor == "fortanix")
3349 }
3350
3351 pub fn expect_builtin(target_tuple: &TargetTuple) -> Target {
3353 match *target_tuple {
3354 TargetTuple::TargetTuple(ref target_tuple) => {
3355 load_builtin(target_tuple).expect("built-in target")
3356 }
3357 TargetTuple::TargetJson { .. } => {
3358 panic!("built-in targets doesn't support target-paths")
3359 }
3360 }
3361 }
3362
3363 pub fn search(
3373 target_tuple: &TargetTuple,
3374 sysroot: &Path,
3375 ) -> Result<(Target, TargetWarnings), String> {
3376 use std::{env, fs};
3377
3378 fn load_file(path: &Path) -> Result<(Target, TargetWarnings), String> {
3379 let contents = fs::read_to_string(path).map_err(|e| e.to_string())?;
3380 let obj = serde_json::from_str(&contents).map_err(|e| e.to_string())?;
3381 Target::from_json(obj)
3382 }
3383
3384 match *target_tuple {
3385 TargetTuple::TargetTuple(ref target_tuple) => {
3386 if let Some(t) = load_builtin(target_tuple) {
3388 return Ok((t, TargetWarnings::empty()));
3389 }
3390
3391 let path = {
3393 let mut target = target_tuple.to_string();
3394 target.push_str(".json");
3395 PathBuf::from(target)
3396 };
3397
3398 let target_path = env::var_os("RUST_TARGET_PATH").unwrap_or_default();
3399
3400 for dir in env::split_paths(&target_path) {
3401 let p = dir.join(&path);
3402 if p.is_file() {
3403 return load_file(&p);
3404 }
3405 }
3406
3407 let rustlib_path = crate::relative_target_rustlib_path(sysroot, target_tuple);
3410 let p = PathBuf::from_iter([
3411 Path::new(sysroot),
3412 Path::new(&rustlib_path),
3413 Path::new("target.json"),
3414 ]);
3415 if p.is_file() {
3416 return load_file(&p);
3417 }
3418
3419 Err(format!("Could not find specification for target {target_tuple:?}"))
3420 }
3421 TargetTuple::TargetJson { ref contents, .. } => {
3422 let obj = serde_json::from_str(contents).map_err(|e| e.to_string())?;
3423 Target::from_json(obj)
3424 }
3425 }
3426 }
3427
3428 pub fn small_data_threshold_support(&self) -> SmallDataThresholdSupport {
3431 match &self.options.small_data_threshold_support {
3432 SmallDataThresholdSupport::DefaultForArch => match self.arch.as_ref() {
3436 "mips" | "mips64" | "mips32r6" => {
3437 SmallDataThresholdSupport::LlvmArg("mips-ssection-threshold".into())
3438 }
3439 "hexagon" => {
3440 SmallDataThresholdSupport::LlvmArg("hexagon-small-data-threshold".into())
3441 }
3442 "m68k" => SmallDataThresholdSupport::LlvmArg("m68k-ssection-threshold".into()),
3443 "riscv32" | "riscv64" => {
3444 SmallDataThresholdSupport::LlvmModuleFlag("SmallDataLimit".into())
3445 }
3446 _ => SmallDataThresholdSupport::None,
3447 },
3448 s => s.clone(),
3449 }
3450 }
3451}
3452
3453#[derive(Clone, Debug)]
3455pub enum TargetTuple {
3456 TargetTuple(String),
3457 TargetJson {
3458 path_for_rustdoc: PathBuf,
3461 tuple: String,
3462 contents: String,
3463 },
3464}
3465
3466impl PartialEq for TargetTuple {
3468 fn eq(&self, other: &Self) -> bool {
3469 match (self, other) {
3470 (Self::TargetTuple(l0), Self::TargetTuple(r0)) => l0 == r0,
3471 (
3472 Self::TargetJson { path_for_rustdoc: _, tuple: l_tuple, contents: l_contents },
3473 Self::TargetJson { path_for_rustdoc: _, tuple: r_tuple, contents: r_contents },
3474 ) => l_tuple == r_tuple && l_contents == r_contents,
3475 _ => false,
3476 }
3477 }
3478}
3479
3480impl Hash for TargetTuple {
3482 fn hash<H: Hasher>(&self, state: &mut H) -> () {
3483 match self {
3484 TargetTuple::TargetTuple(tuple) => {
3485 0u8.hash(state);
3486 tuple.hash(state)
3487 }
3488 TargetTuple::TargetJson { path_for_rustdoc: _, tuple, contents } => {
3489 1u8.hash(state);
3490 tuple.hash(state);
3491 contents.hash(state)
3492 }
3493 }
3494 }
3495}
3496
3497impl<S: Encoder> Encodable<S> for TargetTuple {
3499 fn encode(&self, s: &mut S) {
3500 match self {
3501 TargetTuple::TargetTuple(tuple) => {
3502 s.emit_u8(0);
3503 s.emit_str(tuple);
3504 }
3505 TargetTuple::TargetJson { path_for_rustdoc: _, tuple, contents } => {
3506 s.emit_u8(1);
3507 s.emit_str(tuple);
3508 s.emit_str(contents);
3509 }
3510 }
3511 }
3512}
3513
3514impl<D: Decoder> Decodable<D> for TargetTuple {
3515 fn decode(d: &mut D) -> Self {
3516 match d.read_u8() {
3517 0 => TargetTuple::TargetTuple(d.read_str().to_owned()),
3518 1 => TargetTuple::TargetJson {
3519 path_for_rustdoc: PathBuf::new(),
3520 tuple: d.read_str().to_owned(),
3521 contents: d.read_str().to_owned(),
3522 },
3523 _ => {
3524 panic!("invalid enum variant tag while decoding `TargetTuple`, expected 0..2");
3525 }
3526 }
3527 }
3528}
3529
3530impl TargetTuple {
3531 pub fn from_tuple(tuple: &str) -> Self {
3533 TargetTuple::TargetTuple(tuple.into())
3534 }
3535
3536 pub fn from_path(path: &Path) -> Result<Self, io::Error> {
3538 let canonicalized_path = try_canonicalize(path)?;
3539 let contents = std::fs::read_to_string(&canonicalized_path).map_err(|err| {
3540 io::Error::new(
3541 io::ErrorKind::InvalidInput,
3542 format!("target path {canonicalized_path:?} is not a valid file: {err}"),
3543 )
3544 })?;
3545 let tuple = canonicalized_path
3546 .file_stem()
3547 .expect("target path must not be empty")
3548 .to_str()
3549 .expect("target path must be valid unicode")
3550 .to_owned();
3551 Ok(TargetTuple::TargetJson { path_for_rustdoc: canonicalized_path, tuple, contents })
3552 }
3553
3554 pub fn tuple(&self) -> &str {
3558 match *self {
3559 TargetTuple::TargetTuple(ref tuple) | TargetTuple::TargetJson { ref tuple, .. } => {
3560 tuple
3561 }
3562 }
3563 }
3564
3565 pub fn debug_tuple(&self) -> String {
3570 use std::hash::DefaultHasher;
3571
3572 match self {
3573 TargetTuple::TargetTuple(tuple) => tuple.to_owned(),
3574 TargetTuple::TargetJson { path_for_rustdoc: _, tuple, contents: content } => {
3575 let mut hasher = DefaultHasher::new();
3576 content.hash(&mut hasher);
3577 let hash = hasher.finish();
3578 format!("{tuple}-{hash}")
3579 }
3580 }
3581 }
3582}
3583
3584impl fmt::Display for TargetTuple {
3585 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3586 write!(f, "{}", self.debug_tuple())
3587 }
3588}