]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_target/src/spec/mod.rs
New upstream version 1.64.0+dfsg1
[rustc.git] / compiler / rustc_target / src / spec / mod.rs
CommitLineData
1a4d82fc
JJ
1//! [Flexible target specification.](https://github.com/rust-lang/rfcs/pull/131)
2//!
3//! Rust targets a wide variety of usecases, and in the interest of flexibility,
4//! allows new target triples to be defined in configuration files. Most users
5//! will not need to care about these, but this is invaluable when porting Rust
6//! to a new platform, and allows for an unprecedented level of control over how
7//! the compiler works.
8//!
9//! # Using custom targets
10//!
11//! A target triple, as passed via `rustc --target=TRIPLE`, will first be
12//! compared against the list of built-in targets. This is to ease distributing
13//! rustc (no need for configuration files) and also to hold these built-in
14//! targets as immutable and sacred. If `TRIPLE` is not one of the built-in
15//! targets, rustc will check if a file named `TRIPLE` exists. If it does, it
16//! will be loaded as the target configuration. If the file does not exist,
17//! rustc will search each directory in the environment variable
18//! `RUST_TARGET_PATH` for a file named `TRIPLE.json`. The first one found will
19//! be loaded. If no file is found in any of those directories, a fatal error
a7813a04 20//! will be given.
1a4d82fc
JJ
21//!
22//! Projects defining their own targets should use
23//! `--target=path/to/my-awesome-platform.json` instead of adding to
24//! `RUST_TARGET_PATH`.
25//!
26//! # Defining a new target
27//!
136023e0 28//! Targets are defined using [JSON](https://json.org/). The `Target` struct in
1a4d82fc
JJ
29//! this module defines the format the JSON file should take, though each
30//! underscore in the field names should be replaced with a hyphen (`-`) in the
31//! JSON file. Some fields are required in every target specification, such as
54a0048b
SL
32//! `llvm-target`, `target-endian`, `target-pointer-width`, `data-layout`,
33//! `arch`, and `os`. In general, options passed to rustc with `-C` override
34//! the target's settings, though `target-feature` and `link-args` will *add*
35//! to the list specified by the target, rather than replace.
1a4d82fc 36
5869c6ff 37use crate::abi::Endian;
923072b8 38use crate::json::{Json, ToJson};
dfeec247 39use crate::spec::abi::{lookup as lookup_abi, Abi};
f9f354fc 40use crate::spec::crt_objects::{CrtObjects, CrtObjectsFallback};
cdc7bbd5 41use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
923072b8 42use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
29967ef6 43use rustc_span::symbol::{sym, Symbol};
923072b8 44use serde_json::Value;
5e7ed085 45use std::borrow::Cow;
5bcae85e 46use std::collections::BTreeMap;
5869c6ff 47use std::convert::TryFrom;
923072b8 48use std::hash::{Hash, Hasher};
a2a8927a 49use std::iter::FromIterator;
29967ef6 50use std::ops::{Deref, DerefMut};
0531ce1d 51use std::path::{Path, PathBuf};
83c7162d 52use std::str::FromStr;
dfeec247 53use std::{fmt, io};
1a4d82fc 54
60c5eb7d
XL
55use rustc_macros::HashStable_Generic;
56
83c7162d 57pub mod abi;
f9f354fc
XL
58pub mod crt_objects;
59
d9579d0f 60mod android_base;
1a4d82fc 61mod apple_base;
ba9703b0 62mod apple_sdk_base;
1b1a35ee 63mod avr_gnu_base;
17df50a5 64mod bpf_base;
d9579d0f
AL
65mod dragonfly_base;
66mod freebsd_base;
dfeec247 67mod fuchsia_base;
9e0c209e 68mod haiku_base;
b7449926 69mod hermit_base;
ba9703b0 70mod illumos_base;
dfeec247 71mod l4re_base;
d9579d0f 72mod linux_base;
29967ef6 73mod linux_gnu_base;
e1599b0c 74mod linux_kernel_base;
a7813a04 75mod linux_musl_base;
29967ef6 76mod linux_uclibc_base;
ba9703b0 77mod msvc_base;
c1a9b12d 78mod netbsd_base;
dfeec247
XL
79mod openbsd_base;
80mod redox_base;
7453a54e 81mod solaris_base;
c295e0f8 82mod solid_base;
dfeec247 83mod thumb_base;
ba9703b0 84mod uefi_msvc_base;
dfeec247 85mod vxworks_base;
cdc7bbd5 86mod wasm_base;
ba9703b0 87mod windows_gnu_base;
04454e1e 88mod windows_gnullvm_base;
62682a34 89mod windows_msvc_base;
ba9703b0 90mod windows_uwp_gnu_base;
e1599b0c 91mod windows_uwp_msvc_base;
1a4d82fc 92
e74abb32 93#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
83c7162d
XL
94pub enum LinkerFlavor {
95 Em,
96 Gcc,
5099ac24 97 L4Bender,
83c7162d
XL
98 Ld,
99 Msvc,
100 Lld(LldFlavor),
9fa01778 101 PtxLinker,
17df50a5 102 BpfLinker,
83c7162d
XL
103}
104
e74abb32 105#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
83c7162d
XL
106pub enum LldFlavor {
107 Wasm,
108 Ld64,
109 Ld,
110 Link,
111}
112
b7449926 113impl LldFlavor {
923072b8
FG
114 pub fn as_str(&self) -> &'static str {
115 match self {
116 LldFlavor::Wasm => "wasm",
117 LldFlavor::Ld64 => "darwin",
118 LldFlavor::Ld => "gnu",
119 LldFlavor::Link => "link",
120 }
121 }
122
b7449926
XL
123 fn from_str(s: &str) -> Option<Self> {
124 Some(match s {
125 "darwin" => LldFlavor::Ld64,
126 "gnu" => LldFlavor::Ld,
127 "link" => LldFlavor::Link,
128 "wasm" => LldFlavor::Wasm,
129 _ => return None,
130 })
131 }
132}
133
134impl ToJson for LldFlavor {
135 fn to_json(&self) -> Json {
923072b8 136 self.as_str().to_json()
b7449926
XL
137 }
138}
139
83c7162d
XL
140impl ToJson for LinkerFlavor {
141 fn to_json(&self) -> Json {
142 self.desc().to_json()
143 }
144}
145macro_rules! flavor_mappings {
146 ($((($($flavor:tt)*), $string:expr),)*) => (
147 impl LinkerFlavor {
148 pub const fn one_of() -> &'static str {
dc9dc135 149 concat!("one of: ", $($string, " ",)*)
83c7162d
XL
150 }
151
152 pub fn from_str(s: &str) -> Option<Self> {
153 Some(match s {
dc9dc135 154 $($string => $($flavor)*,)*
83c7162d
XL
155 _ => return None,
156 })
157 }
158
159 pub fn desc(&self) -> &str {
160 match *self {
dc9dc135 161 $($($flavor)* => $string,)*
83c7162d
XL
162 }
163 }
164 }
165 )
166}
167
83c7162d
XL
168flavor_mappings! {
169 ((LinkerFlavor::Em), "em"),
170 ((LinkerFlavor::Gcc), "gcc"),
5099ac24 171 ((LinkerFlavor::L4Bender), "l4-bender"),
83c7162d
XL
172 ((LinkerFlavor::Ld), "ld"),
173 ((LinkerFlavor::Msvc), "msvc"),
9fa01778 174 ((LinkerFlavor::PtxLinker), "ptx-linker"),
17df50a5 175 ((LinkerFlavor::BpfLinker), "bpf-linker"),
83c7162d
XL
176 ((LinkerFlavor::Lld(LldFlavor::Wasm)), "wasm-ld"),
177 ((LinkerFlavor::Lld(LldFlavor::Ld64)), "ld64.lld"),
178 ((LinkerFlavor::Lld(LldFlavor::Ld)), "ld.lld"),
179 ((LinkerFlavor::Lld(LldFlavor::Link)), "lld-link"),
180}
181
3dfed10e 182#[derive(Clone, Copy, Debug, PartialEq, Hash, Encodable, Decodable, HashStable_Generic)]
83c7162d
XL
183pub enum PanicStrategy {
184 Unwind,
185 Abort,
186}
187
188impl PanicStrategy {
189 pub fn desc(&self) -> &str {
190 match *self {
191 PanicStrategy::Unwind => "unwind",
192 PanicStrategy::Abort => "abort",
193 }
194 }
29967ef6 195
5e7ed085 196 pub const fn desc_symbol(&self) -> Symbol {
29967ef6
XL
197 match *self {
198 PanicStrategy::Unwind => sym::unwind,
199 PanicStrategy::Abort => sym::abort,
200 }
201 }
5e7ed085
FG
202
203 pub const fn all() -> [Symbol; 2] {
204 [Self::Abort.desc_symbol(), Self::Unwind.desc_symbol()]
205 }
83c7162d
XL
206}
207
208impl ToJson for PanicStrategy {
209 fn to_json(&self) -> Json {
210 match *self {
211 PanicStrategy::Abort => "abort".to_json(),
212 PanicStrategy::Unwind => "unwind".to_json(),
213 }
214 }
215}
216
923072b8 217#[derive(Clone, Copy, Debug, PartialEq, Hash)]
83c7162d
XL
218pub enum RelroLevel {
219 Full,
220 Partial,
221 Off,
222 None,
223}
224
225impl RelroLevel {
226 pub fn desc(&self) -> &str {
227 match *self {
228 RelroLevel::Full => "full",
229 RelroLevel::Partial => "partial",
230 RelroLevel::Off => "off",
231 RelroLevel::None => "none",
232 }
233 }
234}
235
236impl FromStr for RelroLevel {
237 type Err = ();
238
239 fn from_str(s: &str) -> Result<RelroLevel, ()> {
240 match s {
241 "full" => Ok(RelroLevel::Full),
242 "partial" => Ok(RelroLevel::Partial),
243 "off" => Ok(RelroLevel::Off),
244 "none" => Ok(RelroLevel::None),
245 _ => Err(()),
246 }
247 }
248}
249
250impl ToJson for RelroLevel {
251 fn to_json(&self) -> Json {
252 match *self {
253 RelroLevel::Full => "full".to_json(),
254 RelroLevel::Partial => "partial".to_json(),
255 RelroLevel::Off => "off".to_json(),
256 RelroLevel::None => "None".to_json(),
257 }
258 }
259}
260
923072b8 261#[derive(Clone, Copy, Debug, PartialEq, Hash)]
9fa01778
XL
262pub enum MergeFunctions {
263 Disabled,
264 Trampolines,
dfeec247 265 Aliases,
9fa01778
XL
266}
267
268impl MergeFunctions {
269 pub fn desc(&self) -> &str {
270 match *self {
271 MergeFunctions::Disabled => "disabled",
272 MergeFunctions::Trampolines => "trampolines",
273 MergeFunctions::Aliases => "aliases",
274 }
275 }
276}
277
278impl FromStr for MergeFunctions {
279 type Err = ();
280
281 fn from_str(s: &str) -> Result<MergeFunctions, ()> {
282 match s {
283 "disabled" => Ok(MergeFunctions::Disabled),
284 "trampolines" => Ok(MergeFunctions::Trampolines),
285 "aliases" => Ok(MergeFunctions::Aliases),
286 _ => Err(()),
287 }
288 }
289}
290
291impl ToJson for MergeFunctions {
292 fn to_json(&self) -> Json {
293 match *self {
294 MergeFunctions::Disabled => "disabled".to_json(),
295 MergeFunctions::Trampolines => "trampolines".to_json(),
296 MergeFunctions::Aliases => "aliases".to_json(),
297 }
298 }
299}
300
f9f354fc
XL
301#[derive(Clone, Copy, PartialEq, Hash, Debug)]
302pub enum RelocModel {
303 Static,
304 Pic,
c295e0f8 305 Pie,
f9f354fc
XL
306 DynamicNoPic,
307 Ropi,
308 Rwpi,
309 RopiRwpi,
310}
311
312impl FromStr for RelocModel {
313 type Err = ();
314
315 fn from_str(s: &str) -> Result<RelocModel, ()> {
316 Ok(match s {
317 "static" => RelocModel::Static,
318 "pic" => RelocModel::Pic,
c295e0f8 319 "pie" => RelocModel::Pie,
f9f354fc
XL
320 "dynamic-no-pic" => RelocModel::DynamicNoPic,
321 "ropi" => RelocModel::Ropi,
322 "rwpi" => RelocModel::Rwpi,
323 "ropi-rwpi" => RelocModel::RopiRwpi,
324 _ => return Err(()),
325 })
326 }
327}
328
329impl ToJson for RelocModel {
330 fn to_json(&self) -> Json {
331 match *self {
332 RelocModel::Static => "static",
333 RelocModel::Pic => "pic",
c295e0f8 334 RelocModel::Pie => "pie",
f9f354fc
XL
335 RelocModel::DynamicNoPic => "dynamic-no-pic",
336 RelocModel::Ropi => "ropi",
337 RelocModel::Rwpi => "rwpi",
338 RelocModel::RopiRwpi => "ropi-rwpi",
339 }
340 .to_json()
341 }
342}
343
344#[derive(Clone, Copy, PartialEq, Hash, Debug)]
345pub enum CodeModel {
346 Tiny,
347 Small,
348 Kernel,
349 Medium,
350 Large,
351}
352
353impl FromStr for CodeModel {
354 type Err = ();
355
356 fn from_str(s: &str) -> Result<CodeModel, ()> {
357 Ok(match s {
358 "tiny" => CodeModel::Tiny,
359 "small" => CodeModel::Small,
360 "kernel" => CodeModel::Kernel,
361 "medium" => CodeModel::Medium,
362 "large" => CodeModel::Large,
363 _ => return Err(()),
364 })
365 }
366}
367
368impl ToJson for CodeModel {
369 fn to_json(&self) -> Json {
370 match *self {
371 CodeModel::Tiny => "tiny",
372 CodeModel::Small => "small",
373 CodeModel::Kernel => "kernel",
374 CodeModel::Medium => "medium",
375 CodeModel::Large => "large",
376 }
377 .to_json()
378 }
379}
380
381#[derive(Clone, Copy, PartialEq, Hash, Debug)]
382pub enum TlsModel {
383 GeneralDynamic,
384 LocalDynamic,
385 InitialExec,
386 LocalExec,
387}
388
389impl FromStr for TlsModel {
390 type Err = ();
391
392 fn from_str(s: &str) -> Result<TlsModel, ()> {
393 Ok(match s {
394 // Note the difference "general" vs "global" difference. The model name is "general",
395 // but the user-facing option name is "global" for consistency with other compilers.
396 "global-dynamic" => TlsModel::GeneralDynamic,
397 "local-dynamic" => TlsModel::LocalDynamic,
398 "initial-exec" => TlsModel::InitialExec,
399 "local-exec" => TlsModel::LocalExec,
400 _ => return Err(()),
401 })
402 }
403}
404
405impl ToJson for TlsModel {
406 fn to_json(&self) -> Json {
407 match *self {
408 TlsModel::GeneralDynamic => "global-dynamic",
409 TlsModel::LocalDynamic => "local-dynamic",
410 TlsModel::InitialExec => "initial-exec",
411 TlsModel::LocalExec => "local-exec",
412 }
413 .to_json()
414 }
415}
416
417/// Everything is flattened to a single enum to make the json encoding/decoding less annoying.
418#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug)]
419pub enum LinkOutputKind {
420 /// Dynamically linked non position-independent executable.
421 DynamicNoPicExe,
422 /// Dynamically linked position-independent executable.
423 DynamicPicExe,
424 /// Statically linked non position-independent executable.
425 StaticNoPicExe,
426 /// Statically linked position-independent executable.
427 StaticPicExe,
428 /// Regular dynamic library ("dynamically linked").
429 DynamicDylib,
430 /// Dynamic library with bundled libc ("statically linked").
431 StaticDylib,
5869c6ff
XL
432 /// WASI module with a lifetime past the _initialize entry point
433 WasiReactorExe,
f9f354fc
XL
434}
435
436impl LinkOutputKind {
437 fn as_str(&self) -> &'static str {
438 match self {
439 LinkOutputKind::DynamicNoPicExe => "dynamic-nopic-exe",
440 LinkOutputKind::DynamicPicExe => "dynamic-pic-exe",
441 LinkOutputKind::StaticNoPicExe => "static-nopic-exe",
442 LinkOutputKind::StaticPicExe => "static-pic-exe",
443 LinkOutputKind::DynamicDylib => "dynamic-dylib",
444 LinkOutputKind::StaticDylib => "static-dylib",
5869c6ff 445 LinkOutputKind::WasiReactorExe => "wasi-reactor-exe",
f9f354fc
XL
446 }
447 }
448
449 pub(super) fn from_str(s: &str) -> Option<LinkOutputKind> {
450 Some(match s {
451 "dynamic-nopic-exe" => LinkOutputKind::DynamicNoPicExe,
452 "dynamic-pic-exe" => LinkOutputKind::DynamicPicExe,
453 "static-nopic-exe" => LinkOutputKind::StaticNoPicExe,
454 "static-pic-exe" => LinkOutputKind::StaticPicExe,
455 "dynamic-dylib" => LinkOutputKind::DynamicDylib,
456 "static-dylib" => LinkOutputKind::StaticDylib,
5869c6ff 457 "wasi-reactor-exe" => LinkOutputKind::WasiReactorExe,
f9f354fc
XL
458 _ => return None,
459 })
460 }
461}
462
463impl fmt::Display for LinkOutputKind {
464 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
465 f.write_str(self.as_str())
466 }
467}
468
5e7ed085 469pub type LinkArgs = BTreeMap<LinkerFlavor, Vec<StaticCow<str>>>;
5bcae85e 470
5869c6ff
XL
471#[derive(Clone, Copy, Hash, Debug, PartialEq, Eq)]
472pub enum SplitDebuginfo {
473 /// Split debug-information is disabled, meaning that on supported platforms
474 /// you can find all debug information in the executable itself. This is
475 /// only supported for ELF effectively.
476 ///
477 /// * Windows - not supported
478 /// * macOS - don't run `dsymutil`
479 /// * ELF - `.dwarf_*` sections
480 Off,
481
482 /// Split debug-information can be found in a "packed" location separate
483 /// from the final artifact. This is supported on all platforms.
484 ///
485 /// * Windows - `*.pdb`
486 /// * macOS - `*.dSYM` (run `dsymutil`)
487 /// * ELF - `*.dwp` (run `rust-llvm-dwp`)
488 Packed,
489
490 /// Split debug-information can be found in individual object files on the
491 /// filesystem. The main executable may point to the object files.
492 ///
493 /// * Windows - not supported
494 /// * macOS - supported, scattered object files
a2a8927a 495 /// * ELF - supported, scattered `*.dwo` or `*.o` files (see `SplitDwarfKind`)
5869c6ff
XL
496 Unpacked,
497}
498
499impl SplitDebuginfo {
500 fn as_str(&self) -> &'static str {
501 match self {
502 SplitDebuginfo::Off => "off",
503 SplitDebuginfo::Packed => "packed",
504 SplitDebuginfo::Unpacked => "unpacked",
505 }
506 }
507}
508
509impl FromStr for SplitDebuginfo {
510 type Err = ();
511
512 fn from_str(s: &str) -> Result<SplitDebuginfo, ()> {
513 Ok(match s {
514 "off" => SplitDebuginfo::Off,
515 "unpacked" => SplitDebuginfo::Unpacked,
516 "packed" => SplitDebuginfo::Packed,
517 _ => return Err(()),
518 })
519 }
520}
521
522impl ToJson for SplitDebuginfo {
523 fn to_json(&self) -> Json {
524 self.as_str().to_json()
525 }
526}
527
528impl fmt::Display for SplitDebuginfo {
529 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
530 f.write_str(self.as_str())
531 }
532}
533
5869c6ff
XL
534#[derive(Clone, Debug, PartialEq, Eq)]
535pub enum StackProbeType {
536 /// Don't emit any stack probes.
537 None,
538 /// It is harmless to use this option even on targets that do not have backend support for
539 /// stack probes as the failure mode is the same as if no stack-probe option was specified in
540 /// the first place.
541 Inline,
542 /// Call `__rust_probestack` whenever stack needs to be probed.
543 Call,
544 /// Use inline option for LLVM versions later than specified in `min_llvm_version_for_inline`
545 /// and call `__rust_probestack` otherwise.
546 InlineOrCall { min_llvm_version_for_inline: (u32, u32, u32) },
547}
548
549impl StackProbeType {
550 fn from_json(json: &Json) -> Result<Self, String> {
551 let object = json.as_object().ok_or_else(|| "expected a JSON object")?;
552 let kind = object
553 .get("kind")
923072b8 554 .and_then(|o| o.as_str())
5869c6ff
XL
555 .ok_or_else(|| "expected `kind` to be a string")?;
556 match kind {
557 "none" => Ok(StackProbeType::None),
558 "inline" => Ok(StackProbeType::Inline),
559 "call" => Ok(StackProbeType::Call),
560 "inline-or-call" => {
561 let min_version = object
562 .get("min-llvm-version-for-inline")
563 .and_then(|o| o.as_array())
564 .ok_or_else(|| "expected `min-llvm-version-for-inline` to be an array")?;
565 let mut iter = min_version.into_iter().map(|v| {
566 let int = v.as_u64().ok_or_else(
567 || "expected `min-llvm-version-for-inline` values to be integers",
568 )?;
569 u32::try_from(int)
570 .map_err(|_| "`min-llvm-version-for-inline` values don't convert to u32")
571 });
572 let min_llvm_version_for_inline = (
573 iter.next().unwrap_or(Ok(11))?,
574 iter.next().unwrap_or(Ok(0))?,
575 iter.next().unwrap_or(Ok(0))?,
576 );
577 Ok(StackProbeType::InlineOrCall { min_llvm_version_for_inline })
578 }
579 _ => Err(String::from(
6a06907d 580 "`kind` expected to be one of `none`, `inline`, `call` or `inline-or-call`",
5869c6ff
XL
581 )),
582 }
583 }
584}
585
586impl ToJson for StackProbeType {
587 fn to_json(&self) -> Json {
588 Json::Object(match self {
589 StackProbeType::None => {
5099ac24 590 [(String::from("kind"), "none".to_json())].into_iter().collect()
5869c6ff
XL
591 }
592 StackProbeType::Inline => {
5099ac24 593 [(String::from("kind"), "inline".to_json())].into_iter().collect()
5869c6ff
XL
594 }
595 StackProbeType::Call => {
5099ac24 596 [(String::from("kind"), "call".to_json())].into_iter().collect()
5869c6ff 597 }
923072b8 598 StackProbeType::InlineOrCall { min_llvm_version_for_inline: (maj, min, patch) } => [
5869c6ff
XL
599 (String::from("kind"), "inline-or-call".to_json()),
600 (
601 String::from("min-llvm-version-for-inline"),
923072b8 602 Json::Array(vec![maj.to_json(), min.to_json(), patch.to_json()]),
5869c6ff
XL
603 ),
604 ]
605 .into_iter()
606 .collect(),
607 })
608 }
609}
610
cdc7bbd5
XL
611bitflags::bitflags! {
612 #[derive(Default, Encodable, Decodable)]
613 pub struct SanitizerSet: u8 {
614 const ADDRESS = 1 << 0;
615 const LEAK = 1 << 1;
616 const MEMORY = 1 << 2;
617 const THREAD = 1 << 3;
618 const HWADDRESS = 1 << 4;
3c0e092e 619 const CFI = 1 << 5;
5099ac24 620 const MEMTAG = 1 << 6;
064997fb 621 const SHADOWCALLSTACK = 1 << 7;
cdc7bbd5
XL
622 }
623}
624
625impl SanitizerSet {
626 /// Return sanitizer's name
627 ///
628 /// Returns none if the flags is a set of sanitizers numbering not exactly one.
5e7ed085 629 pub fn as_str(self) -> Option<&'static str> {
cdc7bbd5
XL
630 Some(match self {
631 SanitizerSet::ADDRESS => "address",
3c0e092e 632 SanitizerSet::CFI => "cfi",
cdc7bbd5
XL
633 SanitizerSet::LEAK => "leak",
634 SanitizerSet::MEMORY => "memory",
5099ac24 635 SanitizerSet::MEMTAG => "memtag",
064997fb 636 SanitizerSet::SHADOWCALLSTACK => "shadow-call-stack",
cdc7bbd5
XL
637 SanitizerSet::THREAD => "thread",
638 SanitizerSet::HWADDRESS => "hwaddress",
639 _ => return None,
640 })
641 }
642}
643
644/// Formats a sanitizer set as a comma separated list of sanitizers' names.
645impl fmt::Display for SanitizerSet {
646 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
647 let mut first = true;
648 for s in *self {
649 let name = s.as_str().unwrap_or_else(|| panic!("unrecognized sanitizer {:?}", s));
650 if !first {
651 f.write_str(", ")?;
652 }
653 f.write_str(name)?;
654 first = false;
655 }
656 Ok(())
657 }
658}
659
660impl IntoIterator for SanitizerSet {
661 type Item = SanitizerSet;
662 type IntoIter = std::vec::IntoIter<SanitizerSet>;
663
664 fn into_iter(self) -> Self::IntoIter {
665 [
666 SanitizerSet::ADDRESS,
3c0e092e 667 SanitizerSet::CFI,
cdc7bbd5
XL
668 SanitizerSet::LEAK,
669 SanitizerSet::MEMORY,
5099ac24 670 SanitizerSet::MEMTAG,
064997fb 671 SanitizerSet::SHADOWCALLSTACK,
cdc7bbd5
XL
672 SanitizerSet::THREAD,
673 SanitizerSet::HWADDRESS,
674 ]
675 .iter()
676 .copied()
677 .filter(|&s| self.contains(s))
678 .collect::<Vec<_>>()
679 .into_iter()
680 }
681}
682
683impl<CTX> HashStable<CTX> for SanitizerSet {
684 fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
685 self.bits().hash_stable(ctx, hasher);
686 }
687}
688
689impl ToJson for SanitizerSet {
690 fn to_json(&self) -> Json {
691 self.into_iter()
692 .map(|v| Some(v.as_str()?.to_json()))
693 .collect::<Option<Vec<_>>>()
94222f64 694 .unwrap_or_default()
cdc7bbd5
XL
695 .to_json()
696 }
697}
698
136023e0
XL
699#[derive(Clone, Copy, PartialEq, Hash, Debug)]
700pub enum FramePointer {
701 /// Forces the machine code generator to always preserve the frame pointers.
702 Always,
703 /// Forces the machine code generator to preserve the frame pointers except for the leaf
704 /// functions (i.e. those that don't call other functions).
705 NonLeaf,
706 /// Allows the machine code generator to omit the frame pointers.
707 ///
708 /// This option does not guarantee that the frame pointers will be omitted.
709 MayOmit,
710}
711
712impl FromStr for FramePointer {
713 type Err = ();
714 fn from_str(s: &str) -> Result<Self, ()> {
715 Ok(match s {
716 "always" => Self::Always,
717 "non-leaf" => Self::NonLeaf,
718 "may-omit" => Self::MayOmit,
719 _ => return Err(()),
720 })
721 }
722}
723
724impl ToJson for FramePointer {
725 fn to_json(&self) -> Json {
726 match *self {
727 Self::Always => "always",
728 Self::NonLeaf => "non-leaf",
729 Self::MayOmit => "may-omit",
730 }
731 .to_json()
732 }
733}
734
3c0e092e
XL
735/// Controls use of stack canaries.
736#[derive(Clone, Copy, Debug, PartialEq, Hash, Eq)]
737pub enum StackProtector {
738 /// Disable stack canary generation.
739 None,
740
741 /// On LLVM, mark all generated LLVM functions with the `ssp` attribute (see
742 /// llvm/docs/LangRef.rst). This triggers stack canary generation in
743 /// functions which contain an array of a byte-sized type with more than
744 /// eight elements.
745 Basic,
746
747 /// On LLVM, mark all generated LLVM functions with the `sspstrong`
748 /// attribute (see llvm/docs/LangRef.rst). This triggers stack canary
749 /// generation in functions which either contain an array, or which take
750 /// the address of a local variable.
751 Strong,
752
753 /// Generate stack canaries in all functions.
754 All,
755}
756
757impl StackProtector {
758 fn as_str(&self) -> &'static str {
759 match self {
760 StackProtector::None => "none",
761 StackProtector::Basic => "basic",
762 StackProtector::Strong => "strong",
763 StackProtector::All => "all",
764 }
765 }
766}
767
768impl FromStr for StackProtector {
769 type Err = ();
770
771 fn from_str(s: &str) -> Result<StackProtector, ()> {
772 Ok(match s {
773 "none" => StackProtector::None,
774 "basic" => StackProtector::Basic,
775 "strong" => StackProtector::Strong,
776 "all" => StackProtector::All,
777 _ => return Err(()),
778 })
779 }
780}
781
782impl fmt::Display for StackProtector {
783 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
784 f.write_str(self.as_str())
785 }
786}
787
cdc7bbd5
XL
788macro_rules! supported_targets {
789 ( $(($( $triple:literal, )+ $module:ident ),)+ ) => {
790 $(mod $module;)+
791
792 /// List of supported targets
793 pub const TARGETS: &[&str] = &[$($($triple),+),+];
794
795 fn load_builtin(target: &str) -> Option<Target> {
796 let mut t = match target {
797 $( $($triple)|+ => $module::target(), )+
798 _ => return None,
799 };
800 t.is_builtin = true;
801 debug!("got builtin target: {:?}", t);
802 Some(t)
803 }
804
805 #[cfg(test)]
806 mod tests {
807 mod tests_impl;
808
809 // Cannot put this into a separate file without duplication, make an exception.
810 $(
811 #[test] // `#[test]`
812 fn $module() {
813 tests_impl::test_target(super::$module::target());
814 }
815 )+
816 }
817 };
818}
819
7453a54e
SL
820supported_targets! {
821 ("x86_64-unknown-linux-gnu", x86_64_unknown_linux_gnu),
abe05a73 822 ("x86_64-unknown-linux-gnux32", x86_64_unknown_linux_gnux32),
7453a54e
SL
823 ("i686-unknown-linux-gnu", i686_unknown_linux_gnu),
824 ("i586-unknown-linux-gnu", i586_unknown_linux_gnu),
c295e0f8 825 ("m68k-unknown-linux-gnu", m68k_unknown_linux_gnu),
7453a54e 826 ("mips-unknown-linux-gnu", mips_unknown_linux_gnu),
9e0c209e
SL
827 ("mips64-unknown-linux-gnuabi64", mips64_unknown_linux_gnuabi64),
828 ("mips64el-unknown-linux-gnuabi64", mips64el_unknown_linux_gnuabi64),
532ac7d7
XL
829 ("mipsisa32r6-unknown-linux-gnu", mipsisa32r6_unknown_linux_gnu),
830 ("mipsisa32r6el-unknown-linux-gnu", mipsisa32r6el_unknown_linux_gnu),
831 ("mipsisa64r6-unknown-linux-gnuabi64", mipsisa64r6_unknown_linux_gnuabi64),
832 ("mipsisa64r6el-unknown-linux-gnuabi64", mipsisa64r6el_unknown_linux_gnuabi64),
7453a54e
SL
833 ("mipsel-unknown-linux-gnu", mipsel_unknown_linux_gnu),
834 ("powerpc-unknown-linux-gnu", powerpc_unknown_linux_gnu),
0531ce1d 835 ("powerpc-unknown-linux-gnuspe", powerpc_unknown_linux_gnuspe),
a1dfa0c6 836 ("powerpc-unknown-linux-musl", powerpc_unknown_linux_musl),
7453a54e 837 ("powerpc64-unknown-linux-gnu", powerpc64_unknown_linux_gnu),
a1dfa0c6 838 ("powerpc64-unknown-linux-musl", powerpc64_unknown_linux_musl),
7453a54e 839 ("powerpc64le-unknown-linux-gnu", powerpc64le_unknown_linux_gnu),
8faf50e0 840 ("powerpc64le-unknown-linux-musl", powerpc64le_unknown_linux_musl),
9e0c209e 841 ("s390x-unknown-linux-gnu", s390x_unknown_linux_gnu),
6a06907d 842 ("s390x-unknown-linux-musl", s390x_unknown_linux_musl),
0531ce1d 843 ("sparc-unknown-linux-gnu", sparc_unknown_linux_gnu),
2c00a5a8 844 ("sparc64-unknown-linux-gnu", sparc64_unknown_linux_gnu),
7453a54e
SL
845 ("arm-unknown-linux-gnueabi", arm_unknown_linux_gnueabi),
846 ("arm-unknown-linux-gnueabihf", arm_unknown_linux_gnueabihf),
5bcae85e
SL
847 ("arm-unknown-linux-musleabi", arm_unknown_linux_musleabi),
848 ("arm-unknown-linux-musleabihf", arm_unknown_linux_musleabihf),
ff7c6d11 849 ("armv4t-unknown-linux-gnueabi", armv4t_unknown_linux_gnueabi),
476ff2be 850 ("armv5te-unknown-linux-gnueabi", armv5te_unknown_linux_gnueabi),
83c7162d 851 ("armv5te-unknown-linux-musleabi", armv5te_unknown_linux_musleabi),
fc512014 852 ("armv5te-unknown-linux-uclibceabi", armv5te_unknown_linux_uclibceabi),
416331ca 853 ("armv7-unknown-linux-gnueabi", armv7_unknown_linux_gnueabi),
7453a54e 854 ("armv7-unknown-linux-gnueabihf", armv7_unknown_linux_gnueabihf),
0731742a 855 ("thumbv7neon-unknown-linux-gnueabihf", thumbv7neon_unknown_linux_gnueabihf),
60c5eb7d 856 ("thumbv7neon-unknown-linux-musleabihf", thumbv7neon_unknown_linux_musleabihf),
416331ca 857 ("armv7-unknown-linux-musleabi", armv7_unknown_linux_musleabi),
5bcae85e 858 ("armv7-unknown-linux-musleabihf", armv7_unknown_linux_musleabihf),
7453a54e 859 ("aarch64-unknown-linux-gnu", aarch64_unknown_linux_gnu),
ea8adc8c 860 ("aarch64-unknown-linux-musl", aarch64_unknown_linux_musl),
7453a54e
SL
861 ("x86_64-unknown-linux-musl", x86_64_unknown_linux_musl),
862 ("i686-unknown-linux-musl", i686_unknown_linux_musl),
2c00a5a8 863 ("i586-unknown-linux-musl", i586_unknown_linux_musl),
7453a54e
SL
864 ("mips-unknown-linux-musl", mips_unknown_linux_musl),
865 ("mipsel-unknown-linux-musl", mipsel_unknown_linux_musl),
e1599b0c
XL
866 ("mips64-unknown-linux-muslabi64", mips64_unknown_linux_muslabi64),
867 ("mips64el-unknown-linux-muslabi64", mips64el_unknown_linux_muslabi64),
416331ca 868 ("hexagon-unknown-linux-musl", hexagon_unknown_linux_musl),
2c00a5a8 869
9e0c209e
SL
870 ("mips-unknown-linux-uclibc", mips_unknown_linux_uclibc),
871 ("mipsel-unknown-linux-uclibc", mipsel_unknown_linux_uclibc),
7453a54e
SL
872
873 ("i686-linux-android", i686_linux_android),
cc61c64b 874 ("x86_64-linux-android", x86_64_linux_android),
7453a54e 875 ("arm-linux-androideabi", arm_linux_androideabi),
a7813a04 876 ("armv7-linux-androideabi", armv7_linux_androideabi),
0731742a 877 ("thumbv7neon-linux-androideabi", thumbv7neon_linux_androideabi),
7453a54e
SL
878 ("aarch64-linux-android", aarch64_linux_android),
879
6a06907d 880 ("x86_64-unknown-none-linuxkernel", x86_64_unknown_none_linuxkernel),
e1599b0c 881
8bb4bdeb 882 ("aarch64-unknown-freebsd", aarch64_unknown_freebsd),
532ac7d7
XL
883 ("armv6-unknown-freebsd", armv6_unknown_freebsd),
884 ("armv7-unknown-freebsd", armv7_unknown_freebsd),
7453a54e 885 ("i686-unknown-freebsd", i686_unknown_freebsd),
94222f64 886 ("powerpc-unknown-freebsd", powerpc_unknown_freebsd),
9fa01778 887 ("powerpc64-unknown-freebsd", powerpc64_unknown_freebsd),
136023e0 888 ("powerpc64le-unknown-freebsd", powerpc64le_unknown_freebsd),
a2a8927a 889 ("riscv64gc-unknown-freebsd", riscv64gc_unknown_freebsd),
7453a54e
SL
890 ("x86_64-unknown-freebsd", x86_64_unknown_freebsd),
891
7453a54e
SL
892 ("x86_64-unknown-dragonfly", x86_64_unknown_dragonfly),
893
94b46f34 894 ("aarch64-unknown-openbsd", aarch64_unknown_openbsd),
476ff2be 895 ("i686-unknown-openbsd", i686_unknown_openbsd),
e1599b0c 896 ("sparc64-unknown-openbsd", sparc64_unknown_openbsd),
7453a54e 897 ("x86_64-unknown-openbsd", x86_64_unknown_openbsd),
6a06907d 898 ("powerpc-unknown-openbsd", powerpc_unknown_openbsd),
476ff2be 899
b7449926 900 ("aarch64-unknown-netbsd", aarch64_unknown_netbsd),
94b46f34
XL
901 ("armv6-unknown-netbsd-eabihf", armv6_unknown_netbsd_eabihf),
902 ("armv7-unknown-netbsd-eabihf", armv7_unknown_netbsd_eabihf),
8bb4bdeb 903 ("i686-unknown-netbsd", i686_unknown_netbsd),
0531ce1d 904 ("powerpc-unknown-netbsd", powerpc_unknown_netbsd),
32a655c1 905 ("sparc64-unknown-netbsd", sparc64_unknown_netbsd),
7453a54e 906 ("x86_64-unknown-netbsd", x86_64_unknown_netbsd),
7453a54e 907
c30ab7b3
SL
908 ("i686-unknown-haiku", i686_unknown_haiku),
909 ("x86_64-unknown-haiku", x86_64_unknown_haiku),
9e0c209e 910
f9652781 911 ("aarch64-apple-darwin", aarch64_apple_darwin),
7453a54e
SL
912 ("x86_64-apple-darwin", x86_64_apple_darwin),
913 ("i686-apple-darwin", i686_apple_darwin),
914
8faf50e0
XL
915 ("aarch64-fuchsia", aarch64_fuchsia),
916 ("x86_64-fuchsia", x86_64_fuchsia),
c30ab7b3 917
1b1a35ee 918 ("avr-unknown-gnu-atmega328", avr_unknown_gnu_atmega328),
f035d41b 919
3b2f2976
XL
920 ("x86_64-unknown-l4re-uclibc", x86_64_unknown_l4re_uclibc),
921
416331ca 922 ("aarch64-unknown-redox", aarch64_unknown_redox),
32a655c1
SL
923 ("x86_64-unknown-redox", x86_64_unknown_redox),
924
7453a54e
SL
925 ("i386-apple-ios", i386_apple_ios),
926 ("x86_64-apple-ios", x86_64_apple_ios),
927 ("aarch64-apple-ios", aarch64_apple_ios),
928 ("armv7-apple-ios", armv7_apple_ios),
929 ("armv7s-apple-ios", armv7s_apple_ios),
e1599b0c 930 ("x86_64-apple-ios-macabi", x86_64_apple_ios_macabi),
fc512014 931 ("aarch64-apple-ios-macabi", aarch64_apple_ios_macabi),
6a06907d 932 ("aarch64-apple-ios-sim", aarch64_apple_ios_sim),
ba9703b0
XL
933 ("aarch64-apple-tvos", aarch64_apple_tvos),
934 ("x86_64-apple-tvos", x86_64_apple_tvos),
7453a54e 935
923072b8
FG
936 ("armv7k-apple-watchos", armv7k_apple_watchos),
937 ("arm64_32-apple-watchos", arm64_32_apple_watchos),
938 ("x86_64-apple-watchos-sim", x86_64_apple_watchos_sim),
939 ("aarch64-apple-watchos-sim", aarch64_apple_watchos_sim),
940
b7449926 941 ("armebv7r-none-eabi", armebv7r_none_eabi),
94b46f34 942 ("armebv7r-none-eabihf", armebv7r_none_eabihf),
b7449926
XL
943 ("armv7r-none-eabi", armv7r_none_eabi),
944 ("armv7r-none-eabihf", armv7r_none_eabihf),
94b46f34 945
6a06907d
XL
946 ("x86_64-pc-solaris", x86_64_pc_solaris),
947 ("x86_64-sun-solaris", x86_64_sun_solaris),
8bb4bdeb 948 ("sparcv9-sun-solaris", sparcv9_sun_solaris),
7453a54e 949
ba9703b0
XL
950 ("x86_64-unknown-illumos", x86_64_unknown_illumos),
951
7453a54e
SL
952 ("x86_64-pc-windows-gnu", x86_64_pc_windows_gnu),
953 ("i686-pc-windows-gnu", i686_pc_windows_gnu),
416331ca
XL
954 ("i686-uwp-windows-gnu", i686_uwp_windows_gnu),
955 ("x86_64-uwp-windows-gnu", x86_64_uwp_windows_gnu),
7453a54e 956
04454e1e
FG
957 ("aarch64-pc-windows-gnullvm", aarch64_pc_windows_gnullvm),
958 ("x86_64-pc-windows-gnullvm", x86_64_pc_windows_gnullvm),
959
b7449926 960 ("aarch64-pc-windows-msvc", aarch64_pc_windows_msvc),
e1599b0c 961 ("aarch64-uwp-windows-msvc", aarch64_uwp_windows_msvc),
7453a54e 962 ("x86_64-pc-windows-msvc", x86_64_pc_windows_msvc),
e1599b0c 963 ("x86_64-uwp-windows-msvc", x86_64_uwp_windows_msvc),
7453a54e 964 ("i686-pc-windows-msvc", i686_pc_windows_msvc),
e1599b0c 965 ("i686-uwp-windows-msvc", i686_uwp_windows_msvc),
54a0048b 966 ("i586-pc-windows-msvc", i586_pc_windows_msvc),
b7449926 967 ("thumbv7a-pc-windows-msvc", thumbv7a_pc_windows_msvc),
f9f354fc 968 ("thumbv7a-uwp-windows-msvc", thumbv7a_uwp_windows_msvc),
7453a54e 969
c30ab7b3
SL
970 ("asmjs-unknown-emscripten", asmjs_unknown_emscripten),
971 ("wasm32-unknown-emscripten", wasm32_unknown_emscripten),
abe05a73 972 ("wasm32-unknown-unknown", wasm32_unknown_unknown),
48663c56 973 ("wasm32-wasi", wasm32_wasi),
cdc7bbd5 974 ("wasm64-unknown-unknown", wasm64_unknown_unknown),
c30ab7b3
SL
975
976 ("thumbv6m-none-eabi", thumbv6m_none_eabi),
977 ("thumbv7m-none-eabi", thumbv7m_none_eabi),
978 ("thumbv7em-none-eabi", thumbv7em_none_eabi),
979 ("thumbv7em-none-eabihf", thumbv7em_none_eabihf),
a1dfa0c6 980 ("thumbv8m.base-none-eabi", thumbv8m_base_none_eabi),
0731742a
XL
981 ("thumbv8m.main-none-eabi", thumbv8m_main_none_eabi),
982 ("thumbv8m.main-none-eabihf", thumbv8m_main_none_eabihf),
041b39d2 983
dfeec247
XL
984 ("armv7a-none-eabi", armv7a_none_eabi),
985 ("armv7a-none-eabihf", armv7a_none_eabihf),
986
041b39d2 987 ("msp430-none-elf", msp430_none_elf),
ff7c6d11 988
b7449926
XL
989 ("aarch64-unknown-hermit", aarch64_unknown_hermit),
990 ("x86_64-unknown-hermit", x86_64_unknown_hermit),
6a06907d 991
416331ca 992 ("riscv32i-unknown-none-elf", riscv32i_unknown_none_elf),
5e7ed085 993 ("riscv32im-unknown-none-elf", riscv32im_unknown_none_elf),
b7449926 994 ("riscv32imc-unknown-none-elf", riscv32imc_unknown_none_elf),
94222f64 995 ("riscv32imc-esp-espidf", riscv32imc_esp_espidf),
b7449926 996 ("riscv32imac-unknown-none-elf", riscv32imac_unknown_none_elf),
923072b8 997 ("riscv32imac-unknown-xous-elf", riscv32imac_unknown_xous_elf),
1b1a35ee 998 ("riscv32gc-unknown-linux-gnu", riscv32gc_unknown_linux_gnu),
6a06907d 999 ("riscv32gc-unknown-linux-musl", riscv32gc_unknown_linux_musl),
9fa01778
XL
1000 ("riscv64imac-unknown-none-elf", riscv64imac_unknown_none_elf),
1001 ("riscv64gc-unknown-none-elf", riscv64gc_unknown_none_elf),
60c5eb7d 1002 ("riscv64gc-unknown-linux-gnu", riscv64gc_unknown_linux_gnu),
6a06907d 1003 ("riscv64gc-unknown-linux-musl", riscv64gc_unknown_linux_musl),
b7449926
XL
1004
1005 ("aarch64-unknown-none", aarch64_unknown_none),
e74abb32 1006 ("aarch64-unknown-none-softfloat", aarch64_unknown_none_softfloat),
a1dfa0c6
XL
1007
1008 ("x86_64-fortanix-unknown-sgx", x86_64_fortanix_unknown_sgx),
0731742a
XL
1009
1010 ("x86_64-unknown-uefi", x86_64_unknown_uefi),
e1599b0c 1011 ("i686-unknown-uefi", i686_unknown_uefi),
94222f64 1012 ("aarch64-unknown-uefi", aarch64_unknown_uefi),
9fa01778
XL
1013
1014 ("nvptx64-nvidia-cuda", nvptx64_nvidia_cuda),
416331ca 1015
416331ca 1016 ("i686-wrs-vxworks", i686_wrs_vxworks),
e1599b0c
XL
1017 ("x86_64-wrs-vxworks", x86_64_wrs_vxworks),
1018 ("armv7-wrs-vxworks-eabihf", armv7_wrs_vxworks_eabihf),
416331ca
XL
1019 ("aarch64-wrs-vxworks", aarch64_wrs_vxworks),
1020 ("powerpc-wrs-vxworks", powerpc_wrs_vxworks),
1021 ("powerpc-wrs-vxworks-spe", powerpc_wrs_vxworks_spe),
1022 ("powerpc64-wrs-vxworks", powerpc64_wrs_vxworks),
f9f354fc 1023
c295e0f8
XL
1024 ("aarch64-kmc-solid_asp3", aarch64_kmc_solid_asp3),
1025 ("armv7a-kmc-solid_asp3-eabi", armv7a_kmc_solid_asp3_eabi),
1026 ("armv7a-kmc-solid_asp3-eabihf", armv7a_kmc_solid_asp3_eabihf),
1027
f9f354fc 1028 ("mipsel-sony-psp", mipsel_sony_psp),
29967ef6 1029 ("mipsel-unknown-none", mipsel_unknown_none),
3dfed10e 1030 ("thumbv4t-none-eabi", thumbv4t_none_eabi),
5869c6ff
XL
1031
1032 ("aarch64_be-unknown-linux-gnu", aarch64_be_unknown_linux_gnu),
1033 ("aarch64-unknown-linux-gnu_ilp32", aarch64_unknown_linux_gnu_ilp32),
1034 ("aarch64_be-unknown-linux-gnu_ilp32", aarch64_be_unknown_linux_gnu_ilp32),
17df50a5
XL
1035
1036 ("bpfeb-unknown-none", bpfeb_unknown_none),
1037 ("bpfel-unknown-none", bpfel_unknown_none),
c295e0f8
XL
1038
1039 ("armv6k-nintendo-3ds", armv6k_nintendo_3ds),
1040
064997fb
FG
1041 ("aarch64-nintendo-switch-freestanding", aarch64_nintendo_switch_freestanding),
1042
5099ac24 1043 ("armv7-unknown-linux-uclibceabi", armv7_unknown_linux_uclibceabi),
c295e0f8 1044 ("armv7-unknown-linux-uclibceabihf", armv7_unknown_linux_uclibceabihf),
3c0e092e
XL
1045
1046 ("x86_64-unknown-none", x86_64_unknown_none),
5099ac24
FG
1047
1048 ("mips64-openwrt-linux-musl", mips64_openwrt_linux_musl),
7453a54e
SL
1049}
1050
5e7ed085
FG
1051/// Cow-Vec-Str: Cow<'static, [Cow<'static, str>]>
1052macro_rules! cvs {
1053 () => {
1054 ::std::borrow::Cow::Borrowed(&[])
1055 };
1056 ($($x:expr),+ $(,)?) => {
1057 ::std::borrow::Cow::Borrowed(&[
1058 $(
1059 ::std::borrow::Cow::Borrowed($x),
1060 )*
1061 ])
1062 };
1063}
1064
1065pub(crate) use cvs;
1066
136023e0
XL
1067/// Warnings encountered when parsing the target `json`.
1068///
1069/// Includes fields that weren't recognized and fields that don't have the expected type.
1070#[derive(Debug, PartialEq)]
1071pub struct TargetWarnings {
1072 unused_fields: Vec<String>,
1073 incorrect_type: Vec<String>,
1074}
1075
1076impl TargetWarnings {
1077 pub fn empty() -> Self {
1078 Self { unused_fields: Vec::new(), incorrect_type: Vec::new() }
1079 }
1080
1081 pub fn warning_messages(&self) -> Vec<String> {
1082 let mut warnings = vec![];
1083 if !self.unused_fields.is_empty() {
1084 warnings.push(format!(
1085 "target json file contains unused fields: {}",
1086 self.unused_fields.join(", ")
1087 ));
1088 }
1089 if !self.incorrect_type.is_empty() {
1090 warnings.push(format!(
1091 "target json file contains fields whose value doesn't have the correct json type: {}",
1092 self.incorrect_type.join(", ")
1093 ));
1094 }
1095 warnings
1096 }
1097}
1098
1a4d82fc
JJ
1099/// Everything `rustc` knows about how to compile for a specific target.
1100///
1101/// Every field here must be specified, and has no default value.
5bcae85e 1102#[derive(PartialEq, Clone, Debug)]
1a4d82fc 1103pub struct Target {
1a4d82fc 1104 /// Target triple to pass to LLVM.
5e7ed085 1105 pub llvm_target: StaticCow<str>,
29967ef6
XL
1106 /// Number of bits in a pointer. Influences the `target_pointer_width` `cfg` variable.
1107 pub pointer_width: u32,
416331ca
XL
1108 /// Architecture to use for ABI considerations. Valid options include: "x86",
1109 /// "x86_64", "arm", "aarch64", "mips", "powerpc", "powerpc64", and others.
5e7ed085 1110 pub arch: StaticCow<str>,
136023e0 1111 /// [Data layout](https://llvm.org/docs/LangRef.html#data-layout) to pass to LLVM.
5e7ed085 1112 pub data_layout: StaticCow<str>,
1a4d82fc
JJ
1113 /// Optional settings with defaults.
1114 pub options: TargetOptions,
1115}
1116
a1dfa0c6 1117pub trait HasTargetSpec {
83c7162d
XL
1118 fn target_spec(&self) -> &Target;
1119}
1120
a1dfa0c6 1121impl HasTargetSpec for Target {
17df50a5 1122 #[inline]
83c7162d
XL
1123 fn target_spec(&self) -> &Target {
1124 self
1125 }
1126}
1127
5e7ed085
FG
1128type StaticCow<T> = Cow<'static, T>;
1129
1a4d82fc
JJ
1130/// Optional aspects of a target specification.
1131///
1132/// This has an implementation of `Default`, see each field for what the default is. In general,
1133/// these try to take "minimal defaults" that don't assume anything about the runtime they run in.
29967ef6
XL
1134///
1135/// `TargetOptions` as a separate structure is mostly an implementation detail of `Target`
1136/// construction, all its fields logically belong to `Target` and available from `Target`
1137/// through `Deref` impls.
5bcae85e 1138#[derive(PartialEq, Clone, Debug)]
1a4d82fc 1139pub struct TargetOptions {
54a0048b
SL
1140 /// Whether the target is built-in or loaded from a custom target specification.
1141 pub is_builtin: bool,
1142
5869c6ff
XL
1143 /// Used as the `target_endian` `cfg` variable. Defaults to little endian.
1144 pub endian: Endian,
29967ef6 1145 /// Width of c_int type. Defaults to "32".
5e7ed085 1146 pub c_int_width: StaticCow<str>,
fc512014
XL
1147 /// OS name to use for conditional compilation (`target_os`). Defaults to "none".
1148 /// "none" implies a bare metal target without `std` library.
1149 /// A couple of targets having `std` also use "unknown" as an `os` value,
1150 /// but they are exceptions.
5e7ed085 1151 pub os: StaticCow<str>,
fc512014 1152 /// Environment name to use for conditional compilation (`target_env`). Defaults to "".
5e7ed085 1153 pub env: StaticCow<str>,
136023e0
XL
1154 /// ABI name to distinguish multiple ABIs on the same OS and architecture. For instance, `"eabi"`
1155 /// or `"eabihf"`. Defaults to "".
5e7ed085 1156 pub abi: StaticCow<str>,
fc512014 1157 /// Vendor name to use for conditional compilation (`target_vendor`). Defaults to "unknown".
5e7ed085 1158 pub vendor: StaticCow<str>,
29967ef6
XL
1159 /// Default linker flavor used if `-C linker-flavor` or `-C linker` are not passed
1160 /// on the command line. Defaults to `LinkerFlavor::Gcc`.
1161 pub linker_flavor: LinkerFlavor,
1162
0531ce1d 1163 /// Linker to invoke
5e7ed085 1164 pub linker: Option<StaticCow<str>>,
92a42be0 1165
ba9703b0
XL
1166 /// LLD flavor used if `lld` (or `rust-lld`) is specified as a linker
1167 /// without clarifying its flavor in any way.
b7449926
XL
1168 pub lld_flavor: LldFlavor,
1169
94b46f34 1170 /// Linker arguments that are passed *before* any user-defined libraries.
f035d41b 1171 pub pre_link_args: LinkArgs,
f9f354fc
XL
1172 /// Objects to link before and after all other object code.
1173 pub pre_link_objects: CrtObjects,
1174 pub post_link_objects: CrtObjects,
1175 /// Same as `(pre|post)_link_objects`, but when we fail to pull the objects with help of the
1176 /// target's native gcc and fall back to the "self-contained" mode and pull them manually.
1177 /// See `crt_objects.rs` for some more detailed documentation.
1178 pub pre_link_objects_fallback: CrtObjects,
1179 pub post_link_objects_fallback: CrtObjects,
1180 /// Which logic to use to determine whether to fall back to the "self-contained" mode or not.
1181 pub crt_objects_fallback: Option<CrtObjectsFallback>,
1182
92a42be0 1183 /// Linker arguments that are unconditionally passed after any
f9f354fc 1184 /// user-defined but before post-link objects. Standard platform
92a42be0 1185 /// libraries that should be always be linked to, usually go here.
cc61c64b 1186 pub late_link_args: LinkArgs,
ba9703b0
XL
1187 /// Linker arguments used in addition to `late_link_args` if at least one
1188 /// Rust dependency is dynamically linked.
1189 pub late_link_args_dynamic: LinkArgs,
5e7ed085 1190 /// Linker arguments used in addition to `late_link_args` if all Rust
ba9703b0
XL
1191 /// dependencies are statically linked.
1192 pub late_link_args_static: LinkArgs,
d9579d0f
AL
1193 /// Linker arguments that are unconditionally passed *after* any
1194 /// user-defined libraries.
cc61c64b 1195 pub post_link_args: LinkArgs,
f9f354fc
XL
1196 /// Optional link script applied to `dylib` and `executable` crate types.
1197 /// This is a string containing the script, not a path. Can only be applied
1198 /// to linkers where `linker_is_gnu` is true.
5e7ed085 1199 pub link_script: Option<StaticCow<str>>,
92a42be0 1200
e1599b0c 1201 /// Environment variables to be set for the linker invocation.
5e7ed085 1202 pub link_env: StaticCow<[(StaticCow<str>, StaticCow<str>)]>,
e1599b0c 1203 /// Environment variables to be removed for the linker invocation.
5e7ed085 1204 pub link_env_remove: StaticCow<[StaticCow<str>]>,
041b39d2 1205
32a655c1 1206 /// Extra arguments to pass to the external assembler (when used)
5e7ed085 1207 pub asm_args: StaticCow<[StaticCow<str>]>,
32a655c1 1208
d9579d0f 1209 /// Default CPU to pass to LLVM. Corresponds to `llc -mcpu=$cpu`. Defaults
a7813a04 1210 /// to "generic".
5e7ed085 1211 pub cpu: StaticCow<str>,
d9579d0f
AL
1212 /// Default target features to pass to LLVM. These features will *always* be
1213 /// passed, and cannot be disabled even via `-C`. Corresponds to `llc
1214 /// -mattr=$features`.
5e7ed085 1215 pub features: StaticCow<str>,
1a4d82fc
JJ
1216 /// Whether dynamic linking is available on this target. Defaults to false.
1217 pub dynamic_linking: bool,
abe05a73
XL
1218 /// If dynamic linking is available, whether only cdylibs are supported.
1219 pub only_cdylib: bool,
064997fb 1220 /// Whether executables are available on this target. Defaults to true.
1a4d82fc 1221 pub executables: bool,
1a4d82fc 1222 /// Relocation model to use in object file. Corresponds to `llc
f9f354fc
XL
1223 /// -relocation-model=$relocation_model`. Defaults to `Pic`.
1224 pub relocation_model: RelocModel,
2c00a5a8 1225 /// Code model to use. Corresponds to `llc -code-model=$code_model`.
f9f354fc
XL
1226 /// Defaults to `None` which means "inherited from the base LLVM target".
1227 pub code_model: Option<CodeModel>,
abe05a73
XL
1228 /// TLS model to use. Options are "global-dynamic" (default), "local-dynamic", "initial-exec"
1229 /// and "local-exec". This is similar to the -ftls-model option in GCC/Clang.
f9f354fc 1230 pub tls_model: TlsModel,
1a4d82fc
JJ
1231 /// Do not emit code that uses the "red zone", if the ABI has one. Defaults to false.
1232 pub disable_redzone: bool,
136023e0
XL
1233 /// Frame pointer mode for this target. Defaults to `MayOmit`.
1234 pub frame_pointer: FramePointer,
1a4d82fc
JJ
1235 /// Emit each function in its own section. Defaults to true.
1236 pub function_sections: bool,
1237 /// String to prepend to the name of every dynamic library. Defaults to "lib".
5e7ed085 1238 pub dll_prefix: StaticCow<str>,
1a4d82fc 1239 /// String to append to the name of every dynamic library. Defaults to ".so".
5e7ed085 1240 pub dll_suffix: StaticCow<str>,
1a4d82fc 1241 /// String to append to the name of every executable.
5e7ed085 1242 pub exe_suffix: StaticCow<str>,
1a4d82fc 1243 /// String to prepend to the name of every static library. Defaults to "lib".
5e7ed085 1244 pub staticlib_prefix: StaticCow<str>,
1a4d82fc 1245 /// String to append to the name of every static library. Defaults to ".a".
5e7ed085 1246 pub staticlib_suffix: StaticCow<str>,
17df50a5
XL
1247 /// Values of the `target_family` cfg set for this target.
1248 ///
1249 /// Common options are: "unix", "windows". Defaults to no families.
1250 ///
1251 /// See <https://doc.rust-lang.org/reference/conditional-compilation.html#target_family>.
5e7ed085 1252 pub families: StaticCow<[StaticCow<str>]>,
0531ce1d
XL
1253 /// Whether the target toolchain's ABI supports returning small structs as an integer.
1254 pub abi_return_struct_as_int: bool,
cc61c64b
XL
1255 /// Whether the target toolchain is like macOS's. Only useful for compiling against iOS/macOS,
1256 /// in particular running dsymutil and some other stuff like `-dead_strip`. Defaults to false.
1a4d82fc 1257 pub is_like_osx: bool,
7453a54e
SL
1258 /// Whether the target toolchain is like Solaris's.
1259 /// Only useful for compiling against Illumos/Solaris,
1260 /// as they have a different set of linker flags. Defaults to false.
1261 pub is_like_solaris: bool,
fc512014
XL
1262 /// Whether the target is like Windows.
1263 /// This is a combination of several more specific properties represented as a single flag:
1264 /// - The target uses a Windows ABI,
1265 /// - uses PE/COFF as a format for object code,
1266 /// - uses Windows-style dllexport/dllimport for shared libraries,
1267 /// - uses import libraries and .def files for symbol exports,
1268 /// - executables support setting a subsystem.
1a4d82fc 1269 pub is_like_windows: bool,
fc512014
XL
1270 /// Whether the target is like MSVC.
1271 /// This is a combination of several more specific properties represented as a single flag:
1272 /// - The target has all the properties from `is_like_windows`
1273 /// (for in-tree targets "is_like_msvc ⇒ is_like_windows" is ensured by a unit test),
1274 /// - has some MSVC-specific Windows ABI properties,
1275 /// - uses a link.exe-like linker,
1276 /// - uses CodeView/PDB for debuginfo and natvis for its visualization,
1277 /// - uses SEH-based unwinding,
1278 /// - supports control flow guard mechanism.
62682a34 1279 pub is_like_msvc: bool,
cdc7bbd5
XL
1280 /// Whether a target toolchain is like WASM.
1281 pub is_like_wasm: bool,
064997fb 1282 /// Default supported version of DWARF on this platform.
29967ef6 1283 /// Useful because some platforms (osx, bsd) only want up to DWARF2.
064997fb 1284 pub default_dwarf_version: u32,
17df50a5 1285 /// Whether the linker support GNU-like arguments such as -O. Defaults to true.
1a4d82fc 1286 pub linker_is_gnu: bool,
5bcae85e 1287 /// The MinGW toolchain has a known issue that prevents it from correctly
ff7c6d11 1288 /// handling COFF object files with more than 2<sup>15</sup> sections. Since each weak
5bcae85e
SL
1289 /// symbol needs its own COMDAT section, weak linkage implies a large
1290 /// number sections that easily exceeds the given limit for larger
1291 /// codebases. Consequently we want a way to disallow weak linkage on some
1292 /// platforms.
1293 pub allows_weak_linkage: bool,
1a4d82fc
JJ
1294 /// Whether the linker support rpaths or not. Defaults to false.
1295 pub has_rpath: bool,
b039eaaf
SL
1296 /// Whether to disable linking to the default libraries, typically corresponds
1297 /// to `-nodefaultlibs`. Defaults to true.
1298 pub no_default_libraries: bool,
62682a34
SL
1299 /// Dynamically linked executables can be compiled as position independent
1300 /// if the default relocation model of position independent code is not
1301 /// changed. This is a requirement to take advantage of ASLR, as otherwise
1302 /// the functions in the executable are not randomized and can be used
1303 /// during an exploit of a vulnerability in any code.
1a4d82fc 1304 pub position_independent_executables: bool,
f9f354fc
XL
1305 /// Executables that are both statically linked and position-independent are supported.
1306 pub static_position_independent_executables: bool,
0bf4aa26
XL
1307 /// Determines if the target always requires using the PLT for indirect
1308 /// library calls or not. This controls the default value of the `-Z plt` flag.
1309 pub needs_plt: bool,
3b2f2976
XL
1310 /// Either partial, full, or off. Full RELRO makes the dynamic linker
1311 /// resolve all symbols at startup and marks the GOT read-only before
1312 /// starting the program, preventing overwriting the GOT.
1313 pub relro_level: RelroLevel,
c1a9b12d
SL
1314 /// Format that archives should be emitted in. This affects whether we use
1315 /// LLVM to assemble an archive or fall back to the system linker, and
1316 /// currently only "gnu" is used to fall into LLVM. Unknown strings cause
1317 /// the system linker to be used.
5e7ed085 1318 pub archive_format: StaticCow<str>,
e9174d1e
SL
1319 /// Is asm!() allowed? Defaults to true.
1320 pub allow_asm: bool,
e74abb32
XL
1321 /// Whether the runtime startup code requires the `main` function be passed
1322 /// `argc` and `argv` values.
1323 pub main_needs_argc_argv: bool,
e9174d1e 1324
a2a8927a
XL
1325 /// Flag indicating whether #[thread_local] is available for this target.
1326 pub has_thread_local: bool,
7453a54e
SL
1327 // This is mainly for easy compatibility with emscripten.
1328 // If we give emcc .o files that are actually .bc files it
1329 // will 'just work'.
1330 pub obj_is_bitcode: bool,
f9f354fc
XL
1331 /// Whether the target requires that emitted object code includes bitcode.
1332 pub forces_embed_bitcode: bool,
1333 /// Content of the LLVM cmdline section associated with embedded bitcode.
5e7ed085 1334 pub bitcode_llvm_cmdline: StaticCow<str>,
a7813a04 1335
32a655c1
SL
1336 /// Don't use this field; instead use the `.min_atomic_width()` method.
1337 pub min_atomic_width: Option<u64>,
1338
c30ab7b3
SL
1339 /// Don't use this field; instead use the `.max_atomic_width()` method.
1340 pub max_atomic_width: Option<u64>,
1341
8faf50e0
XL
1342 /// Whether the target supports atomic CAS operations natively
1343 pub atomic_cas: bool,
1344
c30ab7b3
SL
1345 /// Panic strategy: "unwind" or "abort"
1346 pub panic_strategy: PanicStrategy,
1347
3b2f2976
XL
1348 /// Whether or not linking dylibs to a static CRT is allowed.
1349 pub crt_static_allows_dylibs: bool,
476ff2be
SL
1350 /// Whether or not the CRT is statically linked by default.
1351 pub crt_static_default: bool,
3b2f2976
XL
1352 /// Whether or not crt-static is respected by the compiler (or is a no-op).
1353 pub crt_static_respected: bool,
041b39d2 1354
5869c6ff
XL
1355 /// The implementation of stack probes to use.
1356 pub stack_probes: StackProbeType,
ea8adc8c
XL
1357
1358 /// The minimum alignment for global symbols.
1359 pub min_global_align: Option<u64>,
abe05a73
XL
1360
1361 /// Default number of codegen units to use in debug mode
1362 pub default_codegen_units: Option<u64>,
1363
1364 /// Whether to generate trap instructions in places where optimization would
1365 /// otherwise produce control flow that falls through into unrelated memory.
1366 pub trap_unreachable: bool,
1367
1368 /// This target requires everything to be compiled with LTO to emit a final
1369 /// executable, aka there is no native linker for this target.
1370 pub requires_lto: bool,
1371
1372 /// This target has no support for threads.
1373 pub singlethread: bool,
1374
1375 /// Whether library functions call lowering/optimization is disabled in LLVM
1376 /// for this target unconditionally.
1377 pub no_builtins: bool,
ff7c6d11 1378
2c00a5a8
XL
1379 /// The default visibility for symbols in this target should be "hidden"
1380 /// rather than "default"
1381 pub default_hidden_visibility: bool,
0531ce1d 1382
83c7162d
XL
1383 /// Whether a .debug_gdb_scripts section will be added to the output object file
1384 pub emit_debug_gdb_scripts: bool,
1385
1386 /// Whether or not to unconditionally `uwtable` attributes on functions,
1387 /// typically because the platform needs to unwind for things like stack
1388 /// unwinders.
1389 pub requires_uwtable: bool,
0bf4aa26 1390
cdc7bbd5
XL
1391 /// Whether or not to emit `uwtable` attributes on functions if `-C force-unwind-tables`
1392 /// is not specified and `uwtable` is not required on this target.
1393 pub default_uwtable: bool,
1394
0bf4aa26
XL
1395 /// Whether or not SIMD types are passed by reference in the Rust ABI,
1396 /// typically required if a target can be compiled with a mixed set of
1397 /// target features. This is `true` by default, and `false` for targets like
1398 /// wasm32 where the whole program either has simd or not.
1399 pub simd_types_indirect: bool,
a1dfa0c6 1400
dc9dc135
XL
1401 /// Pass a list of symbol which should be exported in the dylib to the linker.
1402 pub limit_rdylib_exports: bool,
1403
a1dfa0c6
XL
1404 /// If set, have the linker export exactly these symbols, instead of using
1405 /// the usual logic to figure this out from the crate itself.
5e7ed085 1406 pub override_export_symbols: Option<StaticCow<[StaticCow<str>]>>,
9fa01778
XL
1407
1408 /// Determines how or whether the MergeFunctions LLVM pass should run for
1409 /// this target. Either "disabled", "trampolines", or "aliases".
1410 /// The MergeFunctions pass is generally useful, but some targets may need
1411 /// to opt out. The default is "aliases".
1412 ///
29967ef6 1413 /// Workaround for: <https://github.com/rust-lang/rust/issues/57356>
532ac7d7
XL
1414 pub merge_functions: MergeFunctions,
1415
1416 /// Use platform dependent mcount function
5e7ed085 1417 pub mcount: StaticCow<str>,
60c5eb7d
XL
1418
1419 /// LLVM ABI name, corresponds to the '-mabi' parameter available in multilib C compilers
5e7ed085 1420 pub llvm_abiname: StaticCow<str>,
60c5eb7d
XL
1421
1422 /// Whether or not RelaxElfRelocation flag will be passed to the linker
1423 pub relax_elf_relocations: bool,
dfeec247
XL
1424
1425 /// Additional arguments to pass to LLVM, similar to the `-C llvm-args` codegen option.
5e7ed085 1426 pub llvm_args: StaticCow<[StaticCow<str>]>,
f9f354fc
XL
1427
1428 /// Whether to use legacy .ctors initialization hooks rather than .init_array. Defaults
1429 /// to false (uses .init_array).
1430 pub use_ctors_section: bool,
f9652781
XL
1431
1432 /// Whether the linker is instructed to add a `GNU_EH_FRAME` ELF header
1433 /// used to locate unwinding information is passed
1434 /// (only has effect if the linker is `ld`-like).
1435 pub eh_frame_header: bool,
29967ef6
XL
1436
1437 /// Is true if the target is an ARM architecture using thumb v1 which allows for
1438 /// thumb and arm interworking.
1439 pub has_thumb_interworking: bool,
5869c6ff
XL
1440
1441 /// How to handle split debug information, if at all. Specifying `None` has
1442 /// target-specific meaning.
1443 pub split_debuginfo: SplitDebuginfo,
cdc7bbd5
XL
1444
1445 /// The sanitizers supported by this target
1446 ///
1447 /// Note that the support here is at a codegen level. If the machine code with sanitizer
1448 /// enabled can generated on this target, but the necessary supporting libraries are not
1449 /// distributed with the target, the sanitizer should still appear in this list for the target.
1450 pub supported_sanitizers: SanitizerSet,
1451
1452 /// If present it's a default value to use for adjusting the C ABI.
1453 pub default_adjusted_cabi: Option<Abi>,
94222f64
XL
1454
1455 /// Minimum number of bits in #[repr(C)] enum. Defaults to 32.
1456 pub c_enum_min_bits: u64,
3c0e092e
XL
1457
1458 /// Whether or not the DWARF `.debug_aranges` section should be generated.
1459 pub generate_arange_section: bool,
1460
1461 /// Whether the target supports stack canary checks. `true` by default,
1462 /// since this is most common among tier 1 and tier 2 targets.
1463 pub supports_stack_protector: bool,
1a4d82fc
JJ
1464}
1465
064997fb
FG
1466/// Add arguments for the given flavor and also for its "twin" flavors
1467/// that have a compatible command line interface.
1468fn add_link_args(link_args: &mut LinkArgs, flavor: LinkerFlavor, args: &[&'static str]) {
1469 let mut insert = |flavor| {
1470 link_args.entry(flavor).or_default().extend(args.iter().copied().map(Cow::Borrowed))
1471 };
1472 insert(flavor);
1473 match flavor {
1474 LinkerFlavor::Ld => insert(LinkerFlavor::Lld(LldFlavor::Ld)),
1475 LinkerFlavor::Msvc => insert(LinkerFlavor::Lld(LldFlavor::Link)),
1476 LinkerFlavor::Lld(LldFlavor::Wasm) => {}
1477 LinkerFlavor::Lld(lld_flavor) => {
1478 panic!("add_link_args: use non-LLD flavor for {:?}", lld_flavor)
1479 }
1480 LinkerFlavor::Gcc
1481 | LinkerFlavor::Em
1482 | LinkerFlavor::L4Bender
1483 | LinkerFlavor::BpfLinker
1484 | LinkerFlavor::PtxLinker => {}
1485 }
1486}
1487
1488impl TargetOptions {
1489 fn link_args(flavor: LinkerFlavor, args: &[&'static str]) -> LinkArgs {
1490 let mut link_args = LinkArgs::new();
1491 add_link_args(&mut link_args, flavor, args);
1492 link_args
1493 }
1494
1495 fn add_pre_link_args(&mut self, flavor: LinkerFlavor, args: &[&'static str]) {
1496 add_link_args(&mut self.pre_link_args, flavor, args);
1497 }
1498
1499 fn add_post_link_args(&mut self, flavor: LinkerFlavor, args: &[&'static str]) {
1500 add_link_args(&mut self.post_link_args, flavor, args);
1501 }
1502}
1503
1a4d82fc 1504impl Default for TargetOptions {
9fa01778 1505 /// Creates a set of "sane defaults" for any target. This is still
62682a34 1506 /// incomplete, and if used for compilation, will certainly not work.
1a4d82fc
JJ
1507 fn default() -> TargetOptions {
1508 TargetOptions {
54a0048b 1509 is_builtin: false,
5869c6ff 1510 endian: Endian::Little,
5e7ed085
FG
1511 c_int_width: "32".into(),
1512 os: "none".into(),
1513 env: "".into(),
1514 abi: "".into(),
1515 vendor: "unknown".into(),
29967ef6 1516 linker_flavor: LinkerFlavor::Gcc,
5e7ed085 1517 linker: option_env!("CFG_DEFAULT_LINKER").map(|s| s.into()),
b7449926 1518 lld_flavor: LldFlavor::Ld,
cc61c64b
XL
1519 pre_link_args: LinkArgs::new(),
1520 post_link_args: LinkArgs::new(),
f9f354fc 1521 link_script: None,
5e7ed085
FG
1522 asm_args: cvs![],
1523 cpu: "generic".into(),
1524 features: "".into(),
1a4d82fc 1525 dynamic_linking: false,
abe05a73 1526 only_cdylib: false,
064997fb 1527 executables: true,
f9f354fc 1528 relocation_model: RelocModel::Pic,
2c00a5a8 1529 code_model: None,
f9f354fc 1530 tls_model: TlsModel::GeneralDynamic,
1a4d82fc 1531 disable_redzone: false,
136023e0 1532 frame_pointer: FramePointer::MayOmit,
1a4d82fc 1533 function_sections: true,
5e7ed085
FG
1534 dll_prefix: "lib".into(),
1535 dll_suffix: ".so".into(),
1536 exe_suffix: "".into(),
1537 staticlib_prefix: "lib".into(),
1538 staticlib_suffix: ".a".into(),
1539 families: cvs![],
0531ce1d 1540 abi_return_struct_as_int: false,
1a4d82fc 1541 is_like_osx: false,
7453a54e 1542 is_like_solaris: false,
1a4d82fc 1543 is_like_windows: false,
62682a34 1544 is_like_msvc: false,
cdc7bbd5 1545 is_like_wasm: false,
064997fb 1546 default_dwarf_version: 4,
17df50a5 1547 linker_is_gnu: true,
5bcae85e 1548 allows_weak_linkage: true,
1a4d82fc 1549 has_rpath: false,
b039eaaf 1550 no_default_libraries: true,
1a4d82fc 1551 position_independent_executables: false,
f9f354fc 1552 static_position_independent_executables: false,
0bf4aa26 1553 needs_plt: false,
0531ce1d 1554 relro_level: RelroLevel::None,
f9f354fc
XL
1555 pre_link_objects: Default::default(),
1556 post_link_objects: Default::default(),
1557 pre_link_objects_fallback: Default::default(),
1558 post_link_objects_fallback: Default::default(),
1559 crt_objects_fallback: None,
cc61c64b 1560 late_link_args: LinkArgs::new(),
ba9703b0
XL
1561 late_link_args_dynamic: LinkArgs::new(),
1562 late_link_args_static: LinkArgs::new(),
5e7ed085
FG
1563 link_env: cvs![],
1564 link_env_remove: cvs![],
1565 archive_format: "gnu".into(),
e74abb32 1566 main_needs_argc_argv: true,
e9174d1e 1567 allow_asm: true,
a2a8927a 1568 has_thread_local: false,
7453a54e 1569 obj_is_bitcode: false,
f9f354fc 1570 forces_embed_bitcode: false,
5e7ed085 1571 bitcode_llvm_cmdline: "".into(),
32a655c1 1572 min_atomic_width: None,
c30ab7b3 1573 max_atomic_width: None,
8faf50e0 1574 atomic_cas: true,
c30ab7b3 1575 panic_strategy: PanicStrategy::Unwind,
3b2f2976 1576 crt_static_allows_dylibs: false,
476ff2be 1577 crt_static_default: false,
3b2f2976 1578 crt_static_respected: false,
5869c6ff 1579 stack_probes: StackProbeType::None,
ea8adc8c 1580 min_global_align: None,
abe05a73
XL
1581 default_codegen_units: None,
1582 trap_unreachable: true,
1583 requires_lto: false,
1584 singlethread: false,
1585 no_builtins: false,
2c00a5a8 1586 default_hidden_visibility: false,
83c7162d
XL
1587 emit_debug_gdb_scripts: true,
1588 requires_uwtable: false,
cdc7bbd5 1589 default_uwtable: false,
0bf4aa26 1590 simd_types_indirect: true,
dc9dc135 1591 limit_rdylib_exports: true,
a1dfa0c6 1592 override_export_symbols: None,
9fa01778 1593 merge_functions: MergeFunctions::Aliases,
5e7ed085
FG
1594 mcount: "mcount".into(),
1595 llvm_abiname: "".into(),
60c5eb7d 1596 relax_elf_relocations: false,
5e7ed085 1597 llvm_args: cvs![],
f9f354fc 1598 use_ctors_section: false,
f9652781 1599 eh_frame_header: true,
29967ef6 1600 has_thumb_interworking: false,
5869c6ff 1601 split_debuginfo: SplitDebuginfo::Off,
cdc7bbd5
XL
1602 supported_sanitizers: SanitizerSet::empty(),
1603 default_adjusted_cabi: None,
94222f64 1604 c_enum_min_bits: 32,
3c0e092e
XL
1605 generate_arange_section: true,
1606 supports_stack_protector: true,
1a4d82fc
JJ
1607 }
1608 }
1609}
1610
29967ef6
XL
1611/// `TargetOptions` being a separate type is basically an implementation detail of `Target` that is
1612/// used for providing defaults. Perhaps there's a way to merge `TargetOptions` into `Target` so
1613/// this `Deref` implementation is no longer necessary.
1614impl Deref for Target {
1615 type Target = TargetOptions;
1616
5099ac24 1617 #[inline]
29967ef6
XL
1618 fn deref(&self) -> &Self::Target {
1619 &self.options
1620 }
1621}
1622impl DerefMut for Target {
5099ac24 1623 #[inline]
29967ef6
XL
1624 fn deref_mut(&mut self) -> &mut Self::Target {
1625 &mut self.options
1626 }
1627}
1628
1a4d82fc 1629impl Target {
0bf4aa26 1630 /// Given a function ABI, turn it into the correct ABI for this target.
7453a54e 1631 pub fn adjust_abi(&self, abi: Abi) -> Abi {
1a4d82fc 1632 match abi {
136023e0
XL
1633 Abi::C { .. } => self.default_adjusted_cabi.unwrap_or(abi),
1634 Abi::System { unwind } if self.is_like_windows && self.arch == "x86" => {
1635 Abi::Stdcall { unwind }
dfeec247 1636 }
136023e0 1637 Abi::System { unwind } => Abi::C { unwind },
5099ac24 1638 Abi::EfiApi if self.arch == "x86_64" => Abi::Win64 { unwind: false },
136023e0 1639 Abi::EfiApi => Abi::C { unwind: false },
cdc7bbd5 1640
136023e0
XL
1641 // See commentary in `is_abi_supported`.
1642 Abi::Stdcall { .. } | Abi::Thiscall { .. } if self.arch == "x86" => abi,
1643 Abi::Stdcall { unwind } | Abi::Thiscall { unwind } => Abi::C { unwind },
5099ac24
FG
1644 Abi::Fastcall { .. } if self.arch == "x86" => abi,
1645 Abi::Vectorcall { .. } if ["x86", "x86_64"].contains(&&self.arch[..]) => abi,
1646 Abi::Fastcall { unwind } | Abi::Vectorcall { unwind } => Abi::C { unwind },
cdc7bbd5 1647
dfeec247 1648 abi => abi,
1a4d82fc
JJ
1649 }
1650 }
1651
136023e0
XL
1652 /// Returns a None if the UNSUPPORTED_CALLING_CONVENTIONS lint should be emitted
1653 pub fn is_abi_supported(&self, abi: Abi) -> Option<bool> {
1654 use Abi::*;
1655 Some(match abi {
1656 Rust
1657 | C { .. }
1658 | System { .. }
1659 | RustIntrinsic
1660 | RustCall
1661 | PlatformIntrinsic
1662 | Unadjusted
5099ac24 1663 | Cdecl { .. }
923072b8
FG
1664 | EfiApi
1665 | RustCold => true,
136023e0 1666 X86Interrupt => ["x86", "x86_64"].contains(&&self.arch[..]),
5099ac24 1667 Aapcs { .. } => "arm" == self.arch,
94222f64 1668 CCmseNonSecureCall => ["arm", "aarch64"].contains(&&self.arch[..]),
5099ac24 1669 Win64 { .. } | SysV64 { .. } => self.arch == "x86_64",
136023e0
XL
1670 PtxKernel => self.arch == "nvptx64",
1671 Msp430Interrupt => self.arch == "msp430",
1672 AmdGpuKernel => self.arch == "amdgcn",
1673 AvrInterrupt | AvrNonBlockingInterrupt => self.arch == "avr",
1674 Wasm => ["wasm32", "wasm64"].contains(&&self.arch[..]),
3c0e092e 1675 Thiscall { .. } => self.arch == "x86",
136023e0
XL
1676 // On windows these fall-back to platform native calling convention (C) when the
1677 // architecture is not supported.
1678 //
1679 // This is I believe a historical accident that has occurred as part of Microsoft
1680 // striving to allow most of the code to "just" compile when support for 64-bit x86
1681 // was added and then later again, when support for ARM architectures was added.
1682 //
1683 // This is well documented across MSDN. Support for this in Rust has been added in
1684 // #54576. This makes much more sense in context of Microsoft's C++ than it does in
1685 // Rust, but there isn't much leeway remaining here to change it back at the time this
1686 // comment has been written.
1687 //
1688 // Following are the relevant excerpts from the MSDN documentation.
1689 //
1690 // > The __vectorcall calling convention is only supported in native code on x86 and
1691 // x64 processors that include Streaming SIMD Extensions 2 (SSE2) and above.
1692 // > ...
1693 // > On ARM machines, __vectorcall is accepted and ignored by the compiler.
1694 //
1695 // -- https://docs.microsoft.com/en-us/cpp/cpp/vectorcall?view=msvc-160
1696 //
1697 // > On ARM and x64 processors, __stdcall is accepted and ignored by the compiler;
1698 //
1699 // -- https://docs.microsoft.com/en-us/cpp/cpp/stdcall?view=msvc-160
1700 //
1701 // > In most cases, keywords or compiler switches that specify an unsupported
1702 // > convention on a particular platform are ignored, and the platform default
1703 // > convention is used.
1704 //
1705 // -- https://docs.microsoft.com/en-us/cpp/cpp/argument-passing-and-naming-conventions
5099ac24 1706 Stdcall { .. } | Fastcall { .. } | Vectorcall { .. } if self.is_like_windows => true,
136023e0
XL
1707 // Outside of Windows we want to only support these calling conventions for the
1708 // architectures for which these calling conventions are actually well defined.
5099ac24
FG
1709 Stdcall { .. } | Fastcall { .. } if self.arch == "x86" => true,
1710 Vectorcall { .. } if ["x86", "x86_64"].contains(&&self.arch[..]) => true,
136023e0 1711 // Return a `None` for other cases so that we know to emit a future compat lint.
5099ac24 1712 Stdcall { .. } | Fastcall { .. } | Vectorcall { .. } => return None,
136023e0
XL
1713 })
1714 }
1715
32a655c1
SL
1716 /// Minimum integer size in bits that this target can perform atomic
1717 /// operations on.
1718 pub fn min_atomic_width(&self) -> u64 {
29967ef6 1719 self.min_atomic_width.unwrap_or(8)
32a655c1
SL
1720 }
1721
c30ab7b3
SL
1722 /// Maximum integer size in bits that this target can perform atomic
1723 /// operations on.
1724 pub fn max_atomic_width(&self) -> u64 {
29967ef6 1725 self.max_atomic_width.unwrap_or_else(|| self.pointer_width.into())
c30ab7b3
SL
1726 }
1727
9fa01778 1728 /// Loads a target descriptor from a JSON object.
923072b8 1729 pub fn from_json(obj: Json) -> Result<(Target, TargetWarnings), String> {
5bcae85e
SL
1730 // While ugly, this code must remain this way to retain
1731 // compatibility with existing JSON fields and the internal
1732 // expected naming of the Target and TargetOptions structs.
1733 // To ensure compatibility is retained, the built-in targets
1734 // are round-tripped through this code to catch cases where
1735 // the JSON parser is not updated to match the structs.
1a4d82fc 1736
923072b8
FG
1737 let mut obj = match obj {
1738 Value::Object(obj) => obj,
1739 _ => return Err("Expected JSON object for target")?,
1740 };
1741
136023e0 1742 let mut get_req_field = |name: &str| {
923072b8
FG
1743 obj.remove(name)
1744 .and_then(|j| j.as_str().map(str::to_string))
dfeec247 1745 .ok_or_else(|| format!("Field {} in target specification is required", name))
1a4d82fc
JJ
1746 };
1747
1748 let mut base = Target {
5e7ed085 1749 llvm_target: get_req_field("llvm-target")?.into(),
29967ef6
XL
1750 pointer_width: get_req_field("target-pointer-width")?
1751 .parse::<u32>()
1752 .map_err(|_| "target-pointer-width must be an integer".to_string())?,
5e7ed085
FG
1753 data_layout: get_req_field("data-layout")?.into(),
1754 arch: get_req_field("arch")?.into(),
1a4d82fc
JJ
1755 options: Default::default(),
1756 };
1757
136023e0
XL
1758 let mut incorrect_type = vec![];
1759
1a4d82fc
JJ
1760 macro_rules! key {
1761 ($key_name:ident) => ( {
1762 let name = (stringify!($key_name)).replace("_", "-");
923072b8 1763 if let Some(s) = obj.remove(&name).and_then(|s| s.as_str().map(str::to_string).map(Cow::from)) {
136023e0 1764 base.$key_name = s;
29967ef6
XL
1765 }
1766 } );
1767 ($key_name:ident = $json_name:expr) => ( {
1768 let name = $json_name;
923072b8 1769 if let Some(s) = obj.remove(name).and_then(|s| s.as_str().map(str::to_string).map(Cow::from)) {
136023e0 1770 base.$key_name = s;
f9f354fc 1771 }
1a4d82fc
JJ
1772 } );
1773 ($key_name:ident, bool) => ( {
1774 let name = (stringify!($key_name)).replace("_", "-");
923072b8 1775 if let Some(s) = obj.remove(&name).and_then(|b| b.as_bool()) {
29967ef6
XL
1776 base.$key_name = s;
1777 }
1778 } );
94222f64
XL
1779 ($key_name:ident, u64) => ( {
1780 let name = (stringify!($key_name)).replace("_", "-");
923072b8 1781 if let Some(s) = obj.remove(&name).and_then(|j| Json::as_u64(&j)) {
94222f64
XL
1782 base.$key_name = s;
1783 }
1784 } );
064997fb 1785 ($key_name:ident, u32) => ( {
29967ef6 1786 let name = (stringify!($key_name)).replace("_", "-");
923072b8 1787 if let Some(s) = obj.remove(&name).and_then(|b| b.as_u64()) {
29967ef6 1788 if s < 1 || s > 5 {
5e7ed085 1789 return Err("Not a valid DWARF version number".into());
29967ef6 1790 }
064997fb 1791 base.$key_name = s as u32;
f9f354fc 1792 }
1a4d82fc 1793 } );
c30ab7b3 1794 ($key_name:ident, Option<u64>) => ( {
a7813a04 1795 let name = (stringify!($key_name)).replace("_", "-");
923072b8 1796 if let Some(s) = obj.remove(&name).and_then(|b| b.as_u64()) {
29967ef6 1797 base.$key_name = Some(s);
f9f354fc 1798 }
c30ab7b3 1799 } );
9fa01778
XL
1800 ($key_name:ident, MergeFunctions) => ( {
1801 let name = (stringify!($key_name)).replace("_", "-");
923072b8 1802 obj.remove(&name).and_then(|o| o.as_str().and_then(|s| {
9fa01778 1803 match s.parse::<MergeFunctions>() {
29967ef6 1804 Ok(mergefunc) => base.$key_name = mergefunc,
9fa01778
XL
1805 _ => return Some(Err(format!("'{}' is not a valid value for \
1806 merge-functions. Use 'disabled', \
1807 'trampolines', or 'aliases'.",
1808 s))),
1809 }
1810 Some(Ok(()))
1811 })).unwrap_or(Ok(()))
1812 } );
f9f354fc
XL
1813 ($key_name:ident, RelocModel) => ( {
1814 let name = (stringify!($key_name)).replace("_", "-");
923072b8 1815 obj.remove(&name).and_then(|o| o.as_str().and_then(|s| {
f9f354fc 1816 match s.parse::<RelocModel>() {
29967ef6 1817 Ok(relocation_model) => base.$key_name = relocation_model,
f9f354fc
XL
1818 _ => return Some(Err(format!("'{}' is not a valid relocation model. \
1819 Run `rustc --print relocation-models` to \
1820 see the list of supported values.", s))),
1821 }
1822 Some(Ok(()))
1823 })).unwrap_or(Ok(()))
1824 } );
1825 ($key_name:ident, CodeModel) => ( {
1826 let name = (stringify!($key_name)).replace("_", "-");
923072b8 1827 obj.remove(&name).and_then(|o| o.as_str().and_then(|s| {
f9f354fc 1828 match s.parse::<CodeModel>() {
29967ef6 1829 Ok(code_model) => base.$key_name = Some(code_model),
f9f354fc
XL
1830 _ => return Some(Err(format!("'{}' is not a valid code model. \
1831 Run `rustc --print code-models` to \
1832 see the list of supported values.", s))),
1833 }
1834 Some(Ok(()))
1835 })).unwrap_or(Ok(()))
1836 } );
1837 ($key_name:ident, TlsModel) => ( {
1838 let name = (stringify!($key_name)).replace("_", "-");
923072b8 1839 obj.remove(&name).and_then(|o| o.as_str().and_then(|s| {
f9f354fc 1840 match s.parse::<TlsModel>() {
29967ef6 1841 Ok(tls_model) => base.$key_name = tls_model,
f9f354fc
XL
1842 _ => return Some(Err(format!("'{}' is not a valid TLS model. \
1843 Run `rustc --print tls-models` to \
1844 see the list of supported values.", s))),
1845 }
1846 Some(Ok(()))
1847 })).unwrap_or(Ok(()))
1848 } );
c30ab7b3
SL
1849 ($key_name:ident, PanicStrategy) => ( {
1850 let name = (stringify!($key_name)).replace("_", "-");
923072b8 1851 obj.remove(&name).and_then(|o| o.as_str().and_then(|s| {
c30ab7b3 1852 match s {
29967ef6
XL
1853 "unwind" => base.$key_name = PanicStrategy::Unwind,
1854 "abort" => base.$key_name = PanicStrategy::Abort,
c30ab7b3
SL
1855 _ => return Some(Err(format!("'{}' is not a valid value for \
1856 panic-strategy. Use 'unwind' or 'abort'.",
1857 s))),
1858 }
1859 Some(Ok(()))
1860 })).unwrap_or(Ok(()))
a7813a04 1861 } );
3b2f2976
XL
1862 ($key_name:ident, RelroLevel) => ( {
1863 let name = (stringify!($key_name)).replace("_", "-");
923072b8 1864 obj.remove(&name).and_then(|o| o.as_str().and_then(|s| {
3b2f2976 1865 match s.parse::<RelroLevel>() {
29967ef6 1866 Ok(level) => base.$key_name = level,
3b2f2976
XL
1867 _ => return Some(Err(format!("'{}' is not a valid value for \
1868 relro-level. Use 'full', 'partial, or 'off'.",
1869 s))),
1870 }
1871 Some(Ok(()))
1872 })).unwrap_or(Ok(()))
1873 } );
5869c6ff
XL
1874 ($key_name:ident, SplitDebuginfo) => ( {
1875 let name = (stringify!($key_name)).replace("_", "-");
923072b8 1876 obj.remove(&name).and_then(|o| o.as_str().and_then(|s| {
5869c6ff
XL
1877 match s.parse::<SplitDebuginfo>() {
1878 Ok(level) => base.$key_name = level,
1879 _ => return Some(Err(format!("'{}' is not a valid value for \
1880 split-debuginfo. Use 'off' or 'dsymutil'.",
1881 s))),
1882 }
1883 Some(Ok(()))
1884 })).unwrap_or(Ok(()))
1885 } );
1a4d82fc
JJ
1886 ($key_name:ident, list) => ( {
1887 let name = (stringify!($key_name)).replace("_", "-");
923072b8
FG
1888 if let Some(j) = obj.remove(&name) {
1889 if let Some(v) = j.as_array() {
136023e0 1890 base.$key_name = v.iter()
923072b8 1891 .map(|a| a.as_str().unwrap().to_string().into())
136023e0
XL
1892 .collect();
1893 } else {
1894 incorrect_type.push(name)
1895 }
f9f354fc 1896 }
1a4d82fc 1897 } );
a1dfa0c6
XL
1898 ($key_name:ident, opt_list) => ( {
1899 let name = (stringify!($key_name)).replace("_", "-");
923072b8
FG
1900 if let Some(j) = obj.remove(&name) {
1901 if let Some(v) = j.as_array() {
136023e0 1902 base.$key_name = Some(v.iter()
923072b8 1903 .map(|a| a.as_str().unwrap().to_string().into())
136023e0
XL
1904 .collect());
1905 } else {
1906 incorrect_type.push(name)
1907 }
f9f354fc 1908 }
a1dfa0c6 1909 } );
e9174d1e
SL
1910 ($key_name:ident, optional) => ( {
1911 let name = (stringify!($key_name)).replace("_", "-");
923072b8 1912 if let Some(o) = obj.remove(&name) {
29967ef6 1913 base.$key_name = o
923072b8 1914 .as_str()
5e7ed085 1915 .map(|s| s.to_string().into());
29967ef6
XL
1916 }
1917 } );
b7449926
XL
1918 ($key_name:ident, LldFlavor) => ( {
1919 let name = (stringify!($key_name)).replace("_", "-");
923072b8 1920 obj.remove(&name).and_then(|o| o.as_str().and_then(|s| {
b7449926 1921 if let Some(flavor) = LldFlavor::from_str(&s) {
29967ef6 1922 base.$key_name = flavor;
b7449926
XL
1923 } else {
1924 return Some(Err(format!(
1925 "'{}' is not a valid value for lld-flavor. \
1926 Use 'darwin', 'gnu', 'link' or 'wasm.",
1927 s)))
1928 }
1929 Some(Ok(()))
1930 })).unwrap_or(Ok(()))
1931 } );
cc61c64b
XL
1932 ($key_name:ident, LinkerFlavor) => ( {
1933 let name = (stringify!($key_name)).replace("_", "-");
923072b8 1934 obj.remove(&name).and_then(|o| o.as_str().and_then(|s| {
29967ef6
XL
1935 match LinkerFlavor::from_str(s) {
1936 Some(linker_flavor) => base.$key_name = linker_flavor,
1937 _ => return Some(Err(format!("'{}' is not a valid value for linker-flavor. \
1938 Use {}", s, LinkerFlavor::one_of()))),
1939 }
1940 Some(Ok(()))
cc61c64b
XL
1941 })).unwrap_or(Ok(()))
1942 } );
5869c6ff
XL
1943 ($key_name:ident, StackProbeType) => ( {
1944 let name = (stringify!($key_name)).replace("_", "-");
923072b8 1945 obj.remove(&name).and_then(|o| match StackProbeType::from_json(&o) {
5869c6ff
XL
1946 Ok(v) => {
1947 base.$key_name = v;
1948 Some(Ok(()))
1949 },
1950 Err(s) => Some(Err(
1951 format!("`{:?}` is not a valid value for `{}`: {}", o, name, s)
1952 )),
1953 }).unwrap_or(Ok(()))
1954 } );
cdc7bbd5
XL
1955 ($key_name:ident, SanitizerSet) => ( {
1956 let name = (stringify!($key_name)).replace("_", "-");
923072b8 1957 if let Some(o) = obj.remove(&name) {
136023e0
XL
1958 if let Some(a) = o.as_array() {
1959 for s in a {
923072b8 1960 base.$key_name |= match s.as_str() {
136023e0 1961 Some("address") => SanitizerSet::ADDRESS,
3c0e092e 1962 Some("cfi") => SanitizerSet::CFI,
136023e0
XL
1963 Some("leak") => SanitizerSet::LEAK,
1964 Some("memory") => SanitizerSet::MEMORY,
5099ac24 1965 Some("memtag") => SanitizerSet::MEMTAG,
064997fb 1966 Some("shadow-call-stack") => SanitizerSet::SHADOWCALLSTACK,
136023e0
XL
1967 Some("thread") => SanitizerSet::THREAD,
1968 Some("hwaddress") => SanitizerSet::HWADDRESS,
1969 Some(s) => return Err(format!("unknown sanitizer {}", s)),
1970 _ => return Err(format!("not a string: {:?}", s)),
1971 };
1972 }
1973 } else {
1974 incorrect_type.push(name)
cdc7bbd5 1975 }
136023e0
XL
1976 }
1977 Ok::<(), String>(())
cdc7bbd5
XL
1978 } );
1979
f9f354fc
XL
1980 ($key_name:ident, crt_objects_fallback) => ( {
1981 let name = (stringify!($key_name)).replace("_", "-");
923072b8 1982 obj.remove(&name).and_then(|o| o.as_str().and_then(|s| {
f9f354fc 1983 match s.parse::<CrtObjectsFallback>() {
29967ef6 1984 Ok(fallback) => base.$key_name = Some(fallback),
f9f354fc
XL
1985 _ => return Some(Err(format!("'{}' is not a valid CRT objects fallback. \
1986 Use 'musl', 'mingw' or 'wasm'", s))),
1987 }
1988 Some(Ok(()))
1989 })).unwrap_or(Ok(()))
1990 } );
1991 ($key_name:ident, link_objects) => ( {
1992 let name = (stringify!($key_name)).replace("_", "-");
923072b8 1993 if let Some(val) = obj.remove(&name) {
f9f354fc
XL
1994 let obj = val.as_object().ok_or_else(|| format!("{}: expected a \
1995 JSON object with fields per CRT object kind.", name))?;
1996 let mut args = CrtObjects::new();
1997 for (k, v) in obj {
1998 let kind = LinkOutputKind::from_str(&k).ok_or_else(|| {
1999 format!("{}: '{}' is not a valid value for CRT object kind. \
2000 Use '(dynamic,static)-(nopic,pic)-exe' or \
5869c6ff 2001 '(dynamic,static)-dylib' or 'wasi-reactor-exe'", name, k)
f9f354fc
XL
2002 })?;
2003
2004 let v = v.as_array().ok_or_else(||
2005 format!("{}.{}: expected a JSON array", name, k)
2006 )?.iter().enumerate()
2007 .map(|(i,s)| {
923072b8 2008 let s = s.as_str().ok_or_else(||
f9f354fc 2009 format!("{}.{}[{}]: expected a JSON string", name, k, i))?;
5e7ed085 2010 Ok(s.to_string().into())
f9f354fc
XL
2011 })
2012 .collect::<Result<Vec<_>, String>>()?;
2013
2014 args.insert(kind, v);
2015 }
29967ef6 2016 base.$key_name = args;
f9f354fc
XL
2017 }
2018 } );
cc61c64b
XL
2019 ($key_name:ident, link_args) => ( {
2020 let name = (stringify!($key_name)).replace("_", "-");
923072b8 2021 if let Some(val) = obj.remove(&name) {
8faf50e0
XL
2022 let obj = val.as_object().ok_or_else(|| format!("{}: expected a \
2023 JSON object with fields per linker-flavor.", name))?;
cc61c64b
XL
2024 let mut args = LinkArgs::new();
2025 for (k, v) in obj {
8faf50e0 2026 let flavor = LinkerFlavor::from_str(&k).ok_or_else(|| {
cc61c64b
XL
2027 format!("{}: '{}' is not a valid value for linker-flavor. \
2028 Use 'em', 'gcc', 'ld' or 'msvc'", name, k)
2029 })?;
2030
8faf50e0
XL
2031 let v = v.as_array().ok_or_else(||
2032 format!("{}.{}: expected a JSON array", name, k)
2033 )?.iter().enumerate()
2034 .map(|(i,s)| {
923072b8 2035 let s = s.as_str().ok_or_else(||
8faf50e0 2036 format!("{}.{}[{}]: expected a JSON string", name, k, i))?;
5e7ed085 2037 Ok(s.to_string().into())
8faf50e0
XL
2038 })
2039 .collect::<Result<Vec<_>, String>>()?;
2040
2041 args.insert(flavor, v);
cc61c64b 2042 }
29967ef6 2043 base.$key_name = args;
cc61c64b
XL
2044 }
2045 } );
041b39d2
XL
2046 ($key_name:ident, env) => ( {
2047 let name = (stringify!($key_name)).replace("_", "-");
923072b8 2048 if let Some(o) = obj.remove(&name) {
136023e0
XL
2049 if let Some(a) = o.as_array() {
2050 for o in a {
923072b8 2051 if let Some(s) = o.as_str() {
136023e0
XL
2052 let p = s.split('=').collect::<Vec<_>>();
2053 if p.len() == 2 {
2054 let k = p[0].to_string();
2055 let v = p[1].to_string();
5e7ed085 2056 base.$key_name.to_mut().push((k.into(), v.into()));
136023e0 2057 }
041b39d2
XL
2058 }
2059 }
136023e0
XL
2060 } else {
2061 incorrect_type.push(name)
041b39d2
XL
2062 }
2063 }
2064 } );
cdc7bbd5
XL
2065 ($key_name:ident, Option<Abi>) => ( {
2066 let name = (stringify!($key_name)).replace("_", "-");
923072b8 2067 obj.remove(&name).and_then(|o| o.as_str().and_then(|s| {
cdc7bbd5
XL
2068 match lookup_abi(s) {
2069 Some(abi) => base.$key_name = Some(abi),
2070 _ => return Some(Err(format!("'{}' is not a valid value for abi", s))),
2071 }
2072 Some(Ok(()))
2073 })).unwrap_or(Ok(()))
2074 } );
17df50a5 2075 ($key_name:ident, TargetFamilies) => ( {
923072b8
FG
2076 if let Some(value) = obj.remove("target-family") {
2077 if let Some(v) = value.as_array() {
136023e0 2078 base.$key_name = v.iter()
923072b8 2079 .map(|a| a.as_str().unwrap().to_string().into())
136023e0 2080 .collect();
923072b8 2081 } else if let Some(v) = value.as_str() {
5e7ed085 2082 base.$key_name = vec![v.to_string().into()].into();
136023e0 2083 }
17df50a5
XL
2084 }
2085 } );
1a4d82fc
JJ
2086 }
2087
923072b8
FG
2088 if let Some(j) = obj.remove("target-endian") {
2089 if let Some(s) = j.as_str() {
136023e0
XL
2090 base.endian = s.parse()?;
2091 } else {
5e7ed085 2092 incorrect_type.push("target-endian".into())
136023e0 2093 }
5869c6ff 2094 }
136023e0 2095
923072b8
FG
2096 if let Some(fp) = obj.remove("frame-pointer") {
2097 if let Some(s) = fp.as_str() {
136023e0
XL
2098 base.frame_pointer = s
2099 .parse()
2100 .map_err(|()| format!("'{}' is not a valid value for frame-pointer", s))?;
2101 } else {
5e7ed085 2102 incorrect_type.push("frame-pointer".into())
136023e0
XL
2103 }
2104 }
2105
5bcae85e 2106 key!(is_builtin, bool);
fc512014 2107 key!(c_int_width = "target-c-int-width");
29967ef6
XL
2108 key!(os);
2109 key!(env);
136023e0 2110 key!(abi);
29967ef6
XL
2111 key!(vendor);
2112 key!(linker_flavor, LinkerFlavor)?;
0531ce1d 2113 key!(linker, optional);
a1dfa0c6 2114 key!(lld_flavor, LldFlavor)?;
f9f354fc
XL
2115 key!(pre_link_objects, link_objects);
2116 key!(post_link_objects, link_objects);
2117 key!(pre_link_objects_fallback, link_objects);
2118 key!(post_link_objects_fallback, link_objects);
2119 key!(crt_objects_fallback, crt_objects_fallback)?;
cc61c64b 2120 key!(pre_link_args, link_args);
cc61c64b 2121 key!(late_link_args, link_args);
ba9703b0
XL
2122 key!(late_link_args_dynamic, link_args);
2123 key!(late_link_args_static, link_args);
cc61c64b 2124 key!(post_link_args, link_args);
f9f354fc 2125 key!(link_script, optional);
041b39d2 2126 key!(link_env, env);
e1599b0c 2127 key!(link_env_remove, list);
32a655c1 2128 key!(asm_args, list);
5bcae85e
SL
2129 key!(cpu);
2130 key!(features);
2131 key!(dynamic_linking, bool);
abe05a73 2132 key!(only_cdylib, bool);
5bcae85e 2133 key!(executables, bool);
f9f354fc
XL
2134 key!(relocation_model, RelocModel)?;
2135 key!(code_model, CodeModel)?;
2136 key!(tls_model, TlsModel)?;
5bcae85e 2137 key!(disable_redzone, bool);
5bcae85e 2138 key!(function_sections, bool);
1a4d82fc
JJ
2139 key!(dll_prefix);
2140 key!(dll_suffix);
2141 key!(exe_suffix);
2142 key!(staticlib_prefix);
2143 key!(staticlib_suffix);
17df50a5 2144 key!(families, TargetFamilies);
0531ce1d 2145 key!(abi_return_struct_as_int, bool);
1a4d82fc 2146 key!(is_like_osx, bool);
5bcae85e 2147 key!(is_like_solaris, bool);
1a4d82fc 2148 key!(is_like_windows, bool);
a7813a04 2149 key!(is_like_msvc, bool);
cdc7bbd5 2150 key!(is_like_wasm, bool);
064997fb 2151 key!(default_dwarf_version, u32);
1a4d82fc 2152 key!(linker_is_gnu, bool);
5bcae85e 2153 key!(allows_weak_linkage, bool);
1a4d82fc 2154 key!(has_rpath, bool);
b039eaaf 2155 key!(no_default_libraries, bool);
5bcae85e 2156 key!(position_independent_executables, bool);
f9f354fc 2157 key!(static_position_independent_executables, bool);
0bf4aa26 2158 key!(needs_plt, bool);
a1dfa0c6 2159 key!(relro_level, RelroLevel)?;
92a42be0 2160 key!(archive_format);
e9174d1e 2161 key!(allow_asm, bool);
e74abb32 2162 key!(main_needs_argc_argv, bool);
a2a8927a 2163 key!(has_thread_local, bool);
5bcae85e 2164 key!(obj_is_bitcode, bool);
f9f354fc
XL
2165 key!(forces_embed_bitcode, bool);
2166 key!(bitcode_llvm_cmdline);
c30ab7b3 2167 key!(max_atomic_width, Option<u64>);
32a655c1 2168 key!(min_atomic_width, Option<u64>);
8faf50e0 2169 key!(atomic_cas, bool);
a1dfa0c6 2170 key!(panic_strategy, PanicStrategy)?;
3b2f2976 2171 key!(crt_static_allows_dylibs, bool);
476ff2be 2172 key!(crt_static_default, bool);
3b2f2976 2173 key!(crt_static_respected, bool);
5869c6ff 2174 key!(stack_probes, StackProbeType)?;
ea8adc8c 2175 key!(min_global_align, Option<u64>);
abe05a73
XL
2176 key!(default_codegen_units, Option<u64>);
2177 key!(trap_unreachable, bool);
2178 key!(requires_lto, bool);
2179 key!(singlethread, bool);
2180 key!(no_builtins, bool);
2c00a5a8 2181 key!(default_hidden_visibility, bool);
83c7162d
XL
2182 key!(emit_debug_gdb_scripts, bool);
2183 key!(requires_uwtable, bool);
cdc7bbd5 2184 key!(default_uwtable, bool);
0bf4aa26 2185 key!(simd_types_indirect, bool);
dc9dc135 2186 key!(limit_rdylib_exports, bool);
a1dfa0c6 2187 key!(override_export_symbols, opt_list);
9fa01778 2188 key!(merge_functions, MergeFunctions)?;
fc512014 2189 key!(mcount = "target-mcount");
60c5eb7d
XL
2190 key!(llvm_abiname);
2191 key!(relax_elf_relocations, bool);
dfeec247 2192 key!(llvm_args, list);
f9f354fc 2193 key!(use_ctors_section, bool);
f9652781 2194 key!(eh_frame_header, bool);
29967ef6 2195 key!(has_thumb_interworking, bool);
5869c6ff 2196 key!(split_debuginfo, SplitDebuginfo)?;
cdc7bbd5
XL
2197 key!(supported_sanitizers, SanitizerSet)?;
2198 key!(default_adjusted_cabi, Option<Abi>)?;
94222f64 2199 key!(c_enum_min_bits, u64);
3c0e092e
XL
2200 key!(generate_arange_section, bool);
2201 key!(supports_stack_protector, bool);
c30ab7b3 2202
136023e0
XL
2203 if base.is_builtin {
2204 // This can cause unfortunate ICEs later down the line.
5e7ed085 2205 return Err("may not set is_builtin for targets not built-in".into());
c30ab7b3 2206 }
923072b8
FG
2207 // Each field should have been read using `Json::remove` so any keys remaining are unused.
2208 let remaining_keys = obj.keys();
136023e0
XL
2209 Ok((
2210 base,
2211 TargetWarnings { unused_fields: remaining_keys.cloned().collect(), incorrect_type },
2212 ))
1a4d82fc
JJ
2213 }
2214
5e7ed085
FG
2215 /// Load a built-in target
2216 pub fn expect_builtin(target_triple: &TargetTriple) -> Target {
2217 match *target_triple {
2218 TargetTriple::TargetTriple(ref target_triple) => {
2219 load_builtin(target_triple).expect("built-in target")
2220 }
923072b8 2221 TargetTriple::TargetJson { .. } => {
5e7ed085
FG
2222 panic!("built-in targets doens't support target-paths")
2223 }
2224 }
2225 }
2226
17df50a5
XL
2227 /// Search for a JSON file specifying the given target triple.
2228 ///
2229 /// If none is found in `$RUST_TARGET_PATH`, look for a file called `target.json` inside the
2230 /// sysroot under the target-triple's `rustlib` directory. Note that it could also just be a
2231 /// bare filename already, so also check for that. If one of the hardcoded targets we know
2232 /// about, just return it directly.
1a4d82fc 2233 ///
17df50a5
XL
2234 /// The error string could come from any of the APIs called, including filesystem access and
2235 /// JSON decoding.
136023e0
XL
2236 pub fn search(
2237 target_triple: &TargetTriple,
3c0e092e 2238 sysroot: &Path,
136023e0 2239 ) -> Result<(Target, TargetWarnings), String> {
85aaf69f 2240 use std::env;
2c00a5a8 2241 use std::fs;
1a4d82fc 2242
136023e0 2243 fn load_file(path: &Path) -> Result<(Target, TargetWarnings), String> {
5099ac24 2244 let contents = fs::read_to_string(path).map_err(|e| e.to_string())?;
923072b8 2245 let obj = serde_json::from_str(&contents).map_err(|e| e.to_string())?;
5bcae85e 2246 Target::from_json(obj)
1a4d82fc
JJ
2247 }
2248
b7449926
XL
2249 match *target_triple {
2250 TargetTriple::TargetTriple(ref target_triple) => {
29967ef6
XL
2251 // check if triple is in list of built-in targets
2252 if let Some(t) = load_builtin(target_triple) {
136023e0 2253 return Ok((t, TargetWarnings::empty()));
0531ce1d 2254 }
1a4d82fc 2255
0531ce1d
XL
2256 // search for a file named `target_triple`.json in RUST_TARGET_PATH
2257 let path = {
2258 let mut target = target_triple.to_string();
2259 target.push_str(".json");
2260 PathBuf::from(target)
2261 };
1a4d82fc 2262
b7449926 2263 let target_path = env::var_os("RUST_TARGET_PATH").unwrap_or_default();
1a4d82fc 2264
0531ce1d 2265 for dir in env::split_paths(&target_path) {
dfeec247 2266 let p = dir.join(&path);
0531ce1d
XL
2267 if p.is_file() {
2268 return load_file(&p);
2269 }
2270 }
17df50a5
XL
2271
2272 // Additionally look in the sysroot under `lib/rustlib/<triple>/target.json`
2273 // as a fallback.
2274 let rustlib_path = crate::target_rustlib_path(&sysroot, &target_triple);
a2a8927a 2275 let p = PathBuf::from_iter([
17df50a5
XL
2276 Path::new(sysroot),
2277 Path::new(&rustlib_path),
2278 Path::new("target.json"),
a2a8927a 2279 ]);
17df50a5
XL
2280 if p.is_file() {
2281 return load_file(&p);
2282 }
2283
0531ce1d
XL
2284 Err(format!("Could not find specification for target {:?}", target_triple))
2285 }
923072b8
FG
2286 TargetTriple::TargetJson { ref contents, .. } => {
2287 let obj = serde_json::from_str(contents).map_err(|e| e.to_string())?;
2288 Target::from_json(obj)
1a4d82fc
JJ
2289 }
2290 }
1a4d82fc
JJ
2291 }
2292}
e9174d1e 2293
5bcae85e
SL
2294impl ToJson for Target {
2295 fn to_json(&self) -> Json {
923072b8 2296 let mut d = serde_json::Map::new();
5bcae85e
SL
2297 let default: TargetOptions = Default::default();
2298
2299 macro_rules! target_val {
dfeec247 2300 ($attr:ident) => {{
5bcae85e 2301 let name = (stringify!($attr)).replace("_", "-");
0bf4aa26 2302 d.insert(name, self.$attr.to_json());
dfeec247 2303 }};
5bcae85e
SL
2304 }
2305
2306 macro_rules! target_option_val {
dfeec247 2307 ($attr:ident) => {{
5bcae85e 2308 let name = (stringify!($attr)).replace("_", "-");
29967ef6
XL
2309 if default.$attr != self.$attr {
2310 d.insert(name, self.$attr.to_json());
5bcae85e 2311 }
dfeec247
XL
2312 }};
2313 ($attr:ident, $key_name:expr) => {{
5bcae85e 2314 let name = $key_name;
29967ef6 2315 if default.$attr != self.$attr {
5e7ed085 2316 d.insert(name.into(), self.$attr.to_json());
5bcae85e 2317 }
dfeec247
XL
2318 }};
2319 (link_args - $attr:ident) => {{
cc61c64b 2320 let name = (stringify!($attr)).replace("_", "-");
29967ef6 2321 if default.$attr != self.$attr {
dfeec247 2322 let obj = self
dfeec247 2323 .$attr
cc61c64b 2324 .iter()
5e7ed085 2325 .map(|(k, v)| (k.desc().to_string(), v.clone()))
cc61c64b 2326 .collect::<BTreeMap<_, _>>();
0bf4aa26 2327 d.insert(name, obj.to_json());
cc61c64b 2328 }
dfeec247
XL
2329 }};
2330 (env - $attr:ident) => {{
041b39d2 2331 let name = (stringify!($attr)).replace("_", "-");
29967ef6 2332 if default.$attr != self.$attr {
dfeec247 2333 let obj = self
dfeec247 2334 .$attr
041b39d2 2335 .iter()
5e7ed085 2336 .map(|&(ref k, ref v)| format!("{k}={v}"))
041b39d2 2337 .collect::<Vec<_>>();
0bf4aa26 2338 d.insert(name, obj.to_json());
041b39d2 2339 }
dfeec247 2340 }};
5bcae85e
SL
2341 }
2342
2343 target_val!(llvm_target);
29967ef6 2344 d.insert("target-pointer-width".to_string(), self.pointer_width.to_string().to_json());
5bcae85e 2345 target_val!(arch);
5bcae85e
SL
2346 target_val!(data_layout);
2347
2348 target_option_val!(is_builtin);
fc512014
XL
2349 target_option_val!(endian, "target-endian");
2350 target_option_val!(c_int_width, "target-c-int-width");
29967ef6
XL
2351 target_option_val!(os);
2352 target_option_val!(env);
136023e0 2353 target_option_val!(abi);
29967ef6
XL
2354 target_option_val!(vendor);
2355 target_option_val!(linker_flavor);
5bcae85e 2356 target_option_val!(linker);
b7449926 2357 target_option_val!(lld_flavor);
f9f354fc
XL
2358 target_option_val!(pre_link_objects);
2359 target_option_val!(post_link_objects);
2360 target_option_val!(pre_link_objects_fallback);
2361 target_option_val!(post_link_objects_fallback);
2362 target_option_val!(crt_objects_fallback);
cc61c64b 2363 target_option_val!(link_args - pre_link_args);
cc61c64b 2364 target_option_val!(link_args - late_link_args);
ba9703b0
XL
2365 target_option_val!(link_args - late_link_args_dynamic);
2366 target_option_val!(link_args - late_link_args_static);
cc61c64b 2367 target_option_val!(link_args - post_link_args);
f9f354fc 2368 target_option_val!(link_script);
041b39d2 2369 target_option_val!(env - link_env);
e1599b0c 2370 target_option_val!(link_env_remove);
32a655c1 2371 target_option_val!(asm_args);
5bcae85e
SL
2372 target_option_val!(cpu);
2373 target_option_val!(features);
2374 target_option_val!(dynamic_linking);
abe05a73 2375 target_option_val!(only_cdylib);
5bcae85e
SL
2376 target_option_val!(executables);
2377 target_option_val!(relocation_model);
2378 target_option_val!(code_model);
abe05a73 2379 target_option_val!(tls_model);
5bcae85e 2380 target_option_val!(disable_redzone);
136023e0 2381 target_option_val!(frame_pointer);
5bcae85e
SL
2382 target_option_val!(function_sections);
2383 target_option_val!(dll_prefix);
2384 target_option_val!(dll_suffix);
2385 target_option_val!(exe_suffix);
2386 target_option_val!(staticlib_prefix);
2387 target_option_val!(staticlib_suffix);
17df50a5 2388 target_option_val!(families, "target-family");
0531ce1d 2389 target_option_val!(abi_return_struct_as_int);
5bcae85e
SL
2390 target_option_val!(is_like_osx);
2391 target_option_val!(is_like_solaris);
2392 target_option_val!(is_like_windows);
2393 target_option_val!(is_like_msvc);
cdc7bbd5 2394 target_option_val!(is_like_wasm);
064997fb 2395 target_option_val!(default_dwarf_version);
5bcae85e
SL
2396 target_option_val!(linker_is_gnu);
2397 target_option_val!(allows_weak_linkage);
2398 target_option_val!(has_rpath);
5bcae85e
SL
2399 target_option_val!(no_default_libraries);
2400 target_option_val!(position_independent_executables);
f9f354fc 2401 target_option_val!(static_position_independent_executables);
0bf4aa26 2402 target_option_val!(needs_plt);
3b2f2976 2403 target_option_val!(relro_level);
5bcae85e
SL
2404 target_option_val!(archive_format);
2405 target_option_val!(allow_asm);
e74abb32 2406 target_option_val!(main_needs_argc_argv);
a2a8927a 2407 target_option_val!(has_thread_local);
5bcae85e 2408 target_option_val!(obj_is_bitcode);
f9f354fc
XL
2409 target_option_val!(forces_embed_bitcode);
2410 target_option_val!(bitcode_llvm_cmdline);
32a655c1 2411 target_option_val!(min_atomic_width);
5bcae85e 2412 target_option_val!(max_atomic_width);
8faf50e0 2413 target_option_val!(atomic_cas);
c30ab7b3 2414 target_option_val!(panic_strategy);
3b2f2976 2415 target_option_val!(crt_static_allows_dylibs);
476ff2be 2416 target_option_val!(crt_static_default);
3b2f2976 2417 target_option_val!(crt_static_respected);
041b39d2 2418 target_option_val!(stack_probes);
ea8adc8c 2419 target_option_val!(min_global_align);
abe05a73
XL
2420 target_option_val!(default_codegen_units);
2421 target_option_val!(trap_unreachable);
2422 target_option_val!(requires_lto);
2423 target_option_val!(singlethread);
2424 target_option_val!(no_builtins);
2c00a5a8 2425 target_option_val!(default_hidden_visibility);
83c7162d
XL
2426 target_option_val!(emit_debug_gdb_scripts);
2427 target_option_val!(requires_uwtable);
cdc7bbd5 2428 target_option_val!(default_uwtable);
0bf4aa26 2429 target_option_val!(simd_types_indirect);
dc9dc135 2430 target_option_val!(limit_rdylib_exports);
a1dfa0c6 2431 target_option_val!(override_export_symbols);
9fa01778 2432 target_option_val!(merge_functions);
fc512014 2433 target_option_val!(mcount, "target-mcount");
60c5eb7d
XL
2434 target_option_val!(llvm_abiname);
2435 target_option_val!(relax_elf_relocations);
dfeec247 2436 target_option_val!(llvm_args);
f9f354fc 2437 target_option_val!(use_ctors_section);
f9652781 2438 target_option_val!(eh_frame_header);
29967ef6 2439 target_option_val!(has_thumb_interworking);
5869c6ff 2440 target_option_val!(split_debuginfo);
cdc7bbd5 2441 target_option_val!(supported_sanitizers);
94222f64 2442 target_option_val!(c_enum_min_bits);
3c0e092e
XL
2443 target_option_val!(generate_arange_section);
2444 target_option_val!(supports_stack_protector);
cdc7bbd5
XL
2445
2446 if let Some(abi) = self.default_adjusted_cabi {
5e7ed085 2447 d.insert("default-adjusted-cabi".into(), Abi::name(abi).to_json());
cdc7bbd5 2448 }
c30ab7b3 2449
5bcae85e
SL
2450 Json::Object(d)
2451 }
2452}
2453
0531ce1d 2454/// Either a target triple string or a path to a JSON file.
923072b8 2455#[derive(Clone, Debug)]
0531ce1d
XL
2456pub enum TargetTriple {
2457 TargetTriple(String),
923072b8
FG
2458 TargetJson {
2459 /// Warning: This field may only be used by rustdoc. Using it anywhere else will lead to
2460 /// inconsistencies as it is discarded during serialization.
2461 path_for_rustdoc: PathBuf,
2462 triple: String,
2463 contents: String,
2464 },
2465}
2466
2467// Use a manual implementation to ignore the path field
2468impl PartialEq for TargetTriple {
2469 fn eq(&self, other: &Self) -> bool {
2470 match (self, other) {
2471 (Self::TargetTriple(l0), Self::TargetTriple(r0)) => l0 == r0,
2472 (
2473 Self::TargetJson { path_for_rustdoc: _, triple: l_triple, contents: l_contents },
2474 Self::TargetJson { path_for_rustdoc: _, triple: r_triple, contents: r_contents },
2475 ) => l_triple == r_triple && l_contents == r_contents,
2476 _ => false,
2477 }
2478 }
2479}
2480
2481// Use a manual implementation to ignore the path field
2482impl Hash for TargetTriple {
2483 fn hash<H: Hasher>(&self, state: &mut H) -> () {
2484 match self {
2485 TargetTriple::TargetTriple(triple) => {
2486 0u8.hash(state);
2487 triple.hash(state)
2488 }
2489 TargetTriple::TargetJson { path_for_rustdoc: _, triple, contents } => {
2490 1u8.hash(state);
2491 triple.hash(state);
2492 contents.hash(state)
2493 }
2494 }
2495 }
2496}
2497
2498// Use a manual implementation to prevent encoding the target json file path in the crate metadata
2499impl<S: Encoder> Encodable<S> for TargetTriple {
2500 fn encode(&self, s: &mut S) {
2501 match self {
2502 TargetTriple::TargetTriple(triple) => s.emit_enum_variant(0, |s| s.emit_str(triple)),
2503 TargetTriple::TargetJson { path_for_rustdoc: _, triple, contents } => s
2504 .emit_enum_variant(1, |s| {
2505 s.emit_str(triple);
2506 s.emit_str(contents)
2507 }),
2508 }
2509 }
2510}
2511
2512impl<D: Decoder> Decodable<D> for TargetTriple {
2513 fn decode(d: &mut D) -> Self {
2514 match d.read_usize() {
2515 0 => TargetTriple::TargetTriple(d.read_str().to_owned()),
2516 1 => TargetTriple::TargetJson {
2517 path_for_rustdoc: PathBuf::new(),
2518 triple: d.read_str().to_owned(),
2519 contents: d.read_str().to_owned(),
2520 },
2521 _ => {
2522 panic!("invalid enum variant tag while decoding `TargetTriple`, expected 0..2");
2523 }
2524 }
2525 }
0531ce1d
XL
2526}
2527
2528impl TargetTriple {
2529 /// Creates a target triple from the passed target triple string.
2530 pub fn from_triple(triple: &str) -> Self {
5e7ed085 2531 TargetTriple::TargetTriple(triple.into())
0531ce1d
XL
2532 }
2533
2534 /// Creates a target triple from the passed target path.
2535 pub fn from_path(path: &Path) -> Result<Self, io::Error> {
2536 let canonicalized_path = path.canonicalize()?;
923072b8
FG
2537 let contents = std::fs::read_to_string(&canonicalized_path).map_err(|err| {
2538 io::Error::new(
2539 io::ErrorKind::InvalidInput,
2540 format!("target path {:?} is not a valid file: {}", canonicalized_path, err),
2541 )
2542 })?;
2543 let triple = canonicalized_path
2544 .file_stem()
2545 .expect("target path must not be empty")
2546 .to_str()
2547 .expect("target path must be valid unicode")
2548 .to_owned();
2549 Ok(TargetTriple::TargetJson { path_for_rustdoc: canonicalized_path, triple, contents })
0531ce1d
XL
2550 }
2551
2552 /// Returns a string triple for this target.
2553 ///
2554 /// If this target is a path, the file name (without extension) is returned.
2555 pub fn triple(&self) -> &str {
b7449926 2556 match *self {
923072b8
FG
2557 TargetTriple::TargetTriple(ref triple)
2558 | TargetTriple::TargetJson { ref triple, .. } => triple,
0531ce1d
XL
2559 }
2560 }
2561
2562 /// Returns an extended string triple for this target.
2563 ///
2564 /// If this target is a path, a hash of the path is appended to the triple returned
2565 /// by `triple()`.
2566 pub fn debug_triple(&self) -> String {
0531ce1d 2567 use std::collections::hash_map::DefaultHasher;
923072b8
FG
2568
2569 match self {
2570 TargetTriple::TargetTriple(triple) => triple.to_owned(),
2571 TargetTriple::TargetJson { path_for_rustdoc: _, triple, contents: content } => {
2572 let mut hasher = DefaultHasher::new();
2573 content.hash(&mut hasher);
2574 let hash = hasher.finish();
2575 format!("{}-{}", triple, hash)
2576 }
0531ce1d
XL
2577 }
2578 }
2579}
2580
2581impl fmt::Display for TargetTriple {
9fa01778 2582 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
0531ce1d
XL
2583 write!(f, "{}", self.debug_triple())
2584 }
2585}