]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_target/src/spec/mod.rs
Auto merge of #77618 - fusion-engineering-forks:windows-parker, r=Amanieu
[rust.git] / compiler / rustc_target / src / spec / mod.rs
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
20 //! will be given.
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 //!
28 //! Targets are defined using [JSON](http://json.org/). The `Target` struct in
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
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.
36
37 use crate::spec::abi::{lookup as lookup_abi, Abi};
38 use crate::spec::crt_objects::{CrtObjects, CrtObjectsFallback};
39 use rustc_serialize::json::{Json, ToJson};
40 use rustc_span::symbol::{sym, Symbol};
41 use std::collections::BTreeMap;
42 use std::ops::{Deref, DerefMut};
43 use std::path::{Path, PathBuf};
44 use std::str::FromStr;
45 use std::{fmt, io};
46
47 use rustc_macros::HashStable_Generic;
48
49 pub mod abi;
50 pub mod crt_objects;
51
52 mod android_base;
53 mod apple_base;
54 mod apple_sdk_base;
55 mod arm_base;
56 mod avr_gnu_base;
57 mod dragonfly_base;
58 mod freebsd_base;
59 mod fuchsia_base;
60 mod haiku_base;
61 mod hermit_base;
62 mod hermit_kernel_base;
63 mod illumos_base;
64 mod l4re_base;
65 mod linux_base;
66 mod linux_gnu_base;
67 mod linux_kernel_base;
68 mod linux_musl_base;
69 mod linux_uclibc_base;
70 mod msvc_base;
71 mod netbsd_base;
72 mod openbsd_base;
73 mod redox_base;
74 mod riscv_base;
75 mod solaris_base;
76 mod thumb_base;
77 mod uefi_msvc_base;
78 mod vxworks_base;
79 mod wasm32_base;
80 mod windows_gnu_base;
81 mod windows_msvc_base;
82 mod windows_uwp_gnu_base;
83 mod windows_uwp_msvc_base;
84
85 #[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
86 pub enum LinkerFlavor {
87     Em,
88     Gcc,
89     Ld,
90     Msvc,
91     Lld(LldFlavor),
92     PtxLinker,
93 }
94
95 #[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
96 pub enum LldFlavor {
97     Wasm,
98     Ld64,
99     Ld,
100     Link,
101 }
102
103 impl LldFlavor {
104     fn from_str(s: &str) -> Option<Self> {
105         Some(match s {
106             "darwin" => LldFlavor::Ld64,
107             "gnu" => LldFlavor::Ld,
108             "link" => LldFlavor::Link,
109             "wasm" => LldFlavor::Wasm,
110             _ => return None,
111         })
112     }
113 }
114
115 impl ToJson for LldFlavor {
116     fn to_json(&self) -> Json {
117         match *self {
118             LldFlavor::Ld64 => "darwin",
119             LldFlavor::Ld => "gnu",
120             LldFlavor::Link => "link",
121             LldFlavor::Wasm => "wasm",
122         }
123         .to_json()
124     }
125 }
126
127 impl ToJson for LinkerFlavor {
128     fn to_json(&self) -> Json {
129         self.desc().to_json()
130     }
131 }
132 macro_rules! flavor_mappings {
133     ($((($($flavor:tt)*), $string:expr),)*) => (
134         impl LinkerFlavor {
135             pub const fn one_of() -> &'static str {
136                 concat!("one of: ", $($string, " ",)*)
137             }
138
139             pub fn from_str(s: &str) -> Option<Self> {
140                 Some(match s {
141                     $($string => $($flavor)*,)*
142                     _ => return None,
143                 })
144             }
145
146             pub fn desc(&self) -> &str {
147                 match *self {
148                     $($($flavor)* => $string,)*
149                 }
150             }
151         }
152     )
153 }
154
155 flavor_mappings! {
156     ((LinkerFlavor::Em), "em"),
157     ((LinkerFlavor::Gcc), "gcc"),
158     ((LinkerFlavor::Ld), "ld"),
159     ((LinkerFlavor::Msvc), "msvc"),
160     ((LinkerFlavor::PtxLinker), "ptx-linker"),
161     ((LinkerFlavor::Lld(LldFlavor::Wasm)), "wasm-ld"),
162     ((LinkerFlavor::Lld(LldFlavor::Ld64)), "ld64.lld"),
163     ((LinkerFlavor::Lld(LldFlavor::Ld)), "ld.lld"),
164     ((LinkerFlavor::Lld(LldFlavor::Link)), "lld-link"),
165 }
166
167 #[derive(Clone, Copy, Debug, PartialEq, Hash, Encodable, Decodable, HashStable_Generic)]
168 pub enum PanicStrategy {
169     Unwind,
170     Abort,
171 }
172
173 impl PanicStrategy {
174     pub fn desc(&self) -> &str {
175         match *self {
176             PanicStrategy::Unwind => "unwind",
177             PanicStrategy::Abort => "abort",
178         }
179     }
180
181     pub fn desc_symbol(&self) -> Symbol {
182         match *self {
183             PanicStrategy::Unwind => sym::unwind,
184             PanicStrategy::Abort => sym::abort,
185         }
186     }
187 }
188
189 impl ToJson for PanicStrategy {
190     fn to_json(&self) -> Json {
191         match *self {
192             PanicStrategy::Abort => "abort".to_json(),
193             PanicStrategy::Unwind => "unwind".to_json(),
194         }
195     }
196 }
197
198 #[derive(Clone, Copy, Debug, PartialEq, Hash, Encodable, Decodable)]
199 pub enum RelroLevel {
200     Full,
201     Partial,
202     Off,
203     None,
204 }
205
206 impl RelroLevel {
207     pub fn desc(&self) -> &str {
208         match *self {
209             RelroLevel::Full => "full",
210             RelroLevel::Partial => "partial",
211             RelroLevel::Off => "off",
212             RelroLevel::None => "none",
213         }
214     }
215 }
216
217 impl FromStr for RelroLevel {
218     type Err = ();
219
220     fn from_str(s: &str) -> Result<RelroLevel, ()> {
221         match s {
222             "full" => Ok(RelroLevel::Full),
223             "partial" => Ok(RelroLevel::Partial),
224             "off" => Ok(RelroLevel::Off),
225             "none" => Ok(RelroLevel::None),
226             _ => Err(()),
227         }
228     }
229 }
230
231 impl ToJson for RelroLevel {
232     fn to_json(&self) -> Json {
233         match *self {
234             RelroLevel::Full => "full".to_json(),
235             RelroLevel::Partial => "partial".to_json(),
236             RelroLevel::Off => "off".to_json(),
237             RelroLevel::None => "None".to_json(),
238         }
239     }
240 }
241
242 #[derive(Clone, Copy, Debug, PartialEq, Hash, Encodable, Decodable)]
243 pub enum MergeFunctions {
244     Disabled,
245     Trampolines,
246     Aliases,
247 }
248
249 impl MergeFunctions {
250     pub fn desc(&self) -> &str {
251         match *self {
252             MergeFunctions::Disabled => "disabled",
253             MergeFunctions::Trampolines => "trampolines",
254             MergeFunctions::Aliases => "aliases",
255         }
256     }
257 }
258
259 impl FromStr for MergeFunctions {
260     type Err = ();
261
262     fn from_str(s: &str) -> Result<MergeFunctions, ()> {
263         match s {
264             "disabled" => Ok(MergeFunctions::Disabled),
265             "trampolines" => Ok(MergeFunctions::Trampolines),
266             "aliases" => Ok(MergeFunctions::Aliases),
267             _ => Err(()),
268         }
269     }
270 }
271
272 impl ToJson for MergeFunctions {
273     fn to_json(&self) -> Json {
274         match *self {
275             MergeFunctions::Disabled => "disabled".to_json(),
276             MergeFunctions::Trampolines => "trampolines".to_json(),
277             MergeFunctions::Aliases => "aliases".to_json(),
278         }
279     }
280 }
281
282 #[derive(Clone, Copy, PartialEq, Hash, Debug)]
283 pub enum RelocModel {
284     Static,
285     Pic,
286     DynamicNoPic,
287     Ropi,
288     Rwpi,
289     RopiRwpi,
290 }
291
292 impl FromStr for RelocModel {
293     type Err = ();
294
295     fn from_str(s: &str) -> Result<RelocModel, ()> {
296         Ok(match s {
297             "static" => RelocModel::Static,
298             "pic" => RelocModel::Pic,
299             "dynamic-no-pic" => RelocModel::DynamicNoPic,
300             "ropi" => RelocModel::Ropi,
301             "rwpi" => RelocModel::Rwpi,
302             "ropi-rwpi" => RelocModel::RopiRwpi,
303             _ => return Err(()),
304         })
305     }
306 }
307
308 impl ToJson for RelocModel {
309     fn to_json(&self) -> Json {
310         match *self {
311             RelocModel::Static => "static",
312             RelocModel::Pic => "pic",
313             RelocModel::DynamicNoPic => "dynamic-no-pic",
314             RelocModel::Ropi => "ropi",
315             RelocModel::Rwpi => "rwpi",
316             RelocModel::RopiRwpi => "ropi-rwpi",
317         }
318         .to_json()
319     }
320 }
321
322 #[derive(Clone, Copy, PartialEq, Hash, Debug)]
323 pub enum CodeModel {
324     Tiny,
325     Small,
326     Kernel,
327     Medium,
328     Large,
329 }
330
331 impl FromStr for CodeModel {
332     type Err = ();
333
334     fn from_str(s: &str) -> Result<CodeModel, ()> {
335         Ok(match s {
336             "tiny" => CodeModel::Tiny,
337             "small" => CodeModel::Small,
338             "kernel" => CodeModel::Kernel,
339             "medium" => CodeModel::Medium,
340             "large" => CodeModel::Large,
341             _ => return Err(()),
342         })
343     }
344 }
345
346 impl ToJson for CodeModel {
347     fn to_json(&self) -> Json {
348         match *self {
349             CodeModel::Tiny => "tiny",
350             CodeModel::Small => "small",
351             CodeModel::Kernel => "kernel",
352             CodeModel::Medium => "medium",
353             CodeModel::Large => "large",
354         }
355         .to_json()
356     }
357 }
358
359 #[derive(Clone, Copy, PartialEq, Hash, Debug)]
360 pub enum TlsModel {
361     GeneralDynamic,
362     LocalDynamic,
363     InitialExec,
364     LocalExec,
365 }
366
367 impl FromStr for TlsModel {
368     type Err = ();
369
370     fn from_str(s: &str) -> Result<TlsModel, ()> {
371         Ok(match s {
372             // Note the difference "general" vs "global" difference. The model name is "general",
373             // but the user-facing option name is "global" for consistency with other compilers.
374             "global-dynamic" => TlsModel::GeneralDynamic,
375             "local-dynamic" => TlsModel::LocalDynamic,
376             "initial-exec" => TlsModel::InitialExec,
377             "local-exec" => TlsModel::LocalExec,
378             _ => return Err(()),
379         })
380     }
381 }
382
383 impl ToJson for TlsModel {
384     fn to_json(&self) -> Json {
385         match *self {
386             TlsModel::GeneralDynamic => "global-dynamic",
387             TlsModel::LocalDynamic => "local-dynamic",
388             TlsModel::InitialExec => "initial-exec",
389             TlsModel::LocalExec => "local-exec",
390         }
391         .to_json()
392     }
393 }
394
395 /// Everything is flattened to a single enum to make the json encoding/decoding less annoying.
396 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug)]
397 pub enum LinkOutputKind {
398     /// Dynamically linked non position-independent executable.
399     DynamicNoPicExe,
400     /// Dynamically linked position-independent executable.
401     DynamicPicExe,
402     /// Statically linked non position-independent executable.
403     StaticNoPicExe,
404     /// Statically linked position-independent executable.
405     StaticPicExe,
406     /// Regular dynamic library ("dynamically linked").
407     DynamicDylib,
408     /// Dynamic library with bundled libc ("statically linked").
409     StaticDylib,
410 }
411
412 impl LinkOutputKind {
413     fn as_str(&self) -> &'static str {
414         match self {
415             LinkOutputKind::DynamicNoPicExe => "dynamic-nopic-exe",
416             LinkOutputKind::DynamicPicExe => "dynamic-pic-exe",
417             LinkOutputKind::StaticNoPicExe => "static-nopic-exe",
418             LinkOutputKind::StaticPicExe => "static-pic-exe",
419             LinkOutputKind::DynamicDylib => "dynamic-dylib",
420             LinkOutputKind::StaticDylib => "static-dylib",
421         }
422     }
423
424     pub(super) fn from_str(s: &str) -> Option<LinkOutputKind> {
425         Some(match s {
426             "dynamic-nopic-exe" => LinkOutputKind::DynamicNoPicExe,
427             "dynamic-pic-exe" => LinkOutputKind::DynamicPicExe,
428             "static-nopic-exe" => LinkOutputKind::StaticNoPicExe,
429             "static-pic-exe" => LinkOutputKind::StaticPicExe,
430             "dynamic-dylib" => LinkOutputKind::DynamicDylib,
431             "static-dylib" => LinkOutputKind::StaticDylib,
432             _ => return None,
433         })
434     }
435 }
436
437 impl fmt::Display for LinkOutputKind {
438     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
439         f.write_str(self.as_str())
440     }
441 }
442
443 pub type LinkArgs = BTreeMap<LinkerFlavor, Vec<String>>;
444
445 macro_rules! supported_targets {
446     ( $(($( $triple:literal, )+ $module:ident ),)+ ) => {
447         $(mod $module;)+
448
449         /// List of supported targets
450         pub const TARGETS: &[&str] = &[$($($triple),+),+];
451
452         fn load_builtin(target: &str) -> Option<Target> {
453             let mut t = match target {
454                 $( $($triple)|+ => $module::target(), )+
455                 _ => return None,
456             };
457             t.is_builtin = true;
458             debug!("got builtin target: {:?}", t);
459             Some(t)
460         }
461
462         #[cfg(test)]
463         mod tests {
464             mod tests_impl;
465
466             // Cannot put this into a separate file without duplication, make an exception.
467             $(
468                 #[test] // `#[test]`
469                 fn $module() {
470                     tests_impl::test_target(super::$module::target());
471                 }
472             )+
473         }
474     };
475 }
476
477 supported_targets! {
478     ("x86_64-unknown-linux-gnu", x86_64_unknown_linux_gnu),
479     ("x86_64-unknown-linux-gnux32", x86_64_unknown_linux_gnux32),
480     ("i686-unknown-linux-gnu", i686_unknown_linux_gnu),
481     ("i586-unknown-linux-gnu", i586_unknown_linux_gnu),
482     ("mips-unknown-linux-gnu", mips_unknown_linux_gnu),
483     ("mips64-unknown-linux-gnuabi64", mips64_unknown_linux_gnuabi64),
484     ("mips64el-unknown-linux-gnuabi64", mips64el_unknown_linux_gnuabi64),
485     ("mipsisa32r6-unknown-linux-gnu", mipsisa32r6_unknown_linux_gnu),
486     ("mipsisa32r6el-unknown-linux-gnu", mipsisa32r6el_unknown_linux_gnu),
487     ("mipsisa64r6-unknown-linux-gnuabi64", mipsisa64r6_unknown_linux_gnuabi64),
488     ("mipsisa64r6el-unknown-linux-gnuabi64", mipsisa64r6el_unknown_linux_gnuabi64),
489     ("mipsel-unknown-linux-gnu", mipsel_unknown_linux_gnu),
490     ("powerpc-unknown-linux-gnu", powerpc_unknown_linux_gnu),
491     ("powerpc-unknown-linux-gnuspe", powerpc_unknown_linux_gnuspe),
492     ("powerpc-unknown-linux-musl", powerpc_unknown_linux_musl),
493     ("powerpc64-unknown-linux-gnu", powerpc64_unknown_linux_gnu),
494     ("powerpc64-unknown-linux-musl", powerpc64_unknown_linux_musl),
495     ("powerpc64le-unknown-linux-gnu", powerpc64le_unknown_linux_gnu),
496     ("powerpc64le-unknown-linux-musl", powerpc64le_unknown_linux_musl),
497     ("s390x-unknown-linux-gnu", s390x_unknown_linux_gnu),
498     ("sparc-unknown-linux-gnu", sparc_unknown_linux_gnu),
499     ("sparc64-unknown-linux-gnu", sparc64_unknown_linux_gnu),
500     ("arm-unknown-linux-gnueabi", arm_unknown_linux_gnueabi),
501     ("arm-unknown-linux-gnueabihf", arm_unknown_linux_gnueabihf),
502     ("arm-unknown-linux-musleabi", arm_unknown_linux_musleabi),
503     ("arm-unknown-linux-musleabihf", arm_unknown_linux_musleabihf),
504     ("armv4t-unknown-linux-gnueabi", armv4t_unknown_linux_gnueabi),
505     ("armv5te-unknown-linux-gnueabi", armv5te_unknown_linux_gnueabi),
506     ("armv5te-unknown-linux-musleabi", armv5te_unknown_linux_musleabi),
507     ("armv5te-unknown-linux-uclibceabi", armv5te_unknown_linux_uclibceabi),
508     ("armv7-unknown-linux-gnueabi", armv7_unknown_linux_gnueabi),
509     ("armv7-unknown-linux-gnueabihf", armv7_unknown_linux_gnueabihf),
510     ("thumbv7neon-unknown-linux-gnueabihf", thumbv7neon_unknown_linux_gnueabihf),
511     ("thumbv7neon-unknown-linux-musleabihf", thumbv7neon_unknown_linux_musleabihf),
512     ("armv7-unknown-linux-musleabi", armv7_unknown_linux_musleabi),
513     ("armv7-unknown-linux-musleabihf", armv7_unknown_linux_musleabihf),
514     ("aarch64-unknown-linux-gnu", aarch64_unknown_linux_gnu),
515     ("aarch64-unknown-linux-musl", aarch64_unknown_linux_musl),
516     ("x86_64-unknown-linux-musl", x86_64_unknown_linux_musl),
517     ("i686-unknown-linux-musl", i686_unknown_linux_musl),
518     ("i586-unknown-linux-musl", i586_unknown_linux_musl),
519     ("mips-unknown-linux-musl", mips_unknown_linux_musl),
520     ("mipsel-unknown-linux-musl", mipsel_unknown_linux_musl),
521     ("mips64-unknown-linux-muslabi64", mips64_unknown_linux_muslabi64),
522     ("mips64el-unknown-linux-muslabi64", mips64el_unknown_linux_muslabi64),
523     ("hexagon-unknown-linux-musl", hexagon_unknown_linux_musl),
524
525     ("mips-unknown-linux-uclibc", mips_unknown_linux_uclibc),
526     ("mipsel-unknown-linux-uclibc", mipsel_unknown_linux_uclibc),
527
528     ("i686-linux-android", i686_linux_android),
529     ("x86_64-linux-android", x86_64_linux_android),
530     ("arm-linux-androideabi", arm_linux_androideabi),
531     ("armv7-linux-androideabi", armv7_linux_androideabi),
532     ("thumbv7neon-linux-androideabi", thumbv7neon_linux_androideabi),
533     ("aarch64-linux-android", aarch64_linux_android),
534
535     ("x86_64-linux-kernel", x86_64_linux_kernel),
536
537     ("aarch64-unknown-freebsd", aarch64_unknown_freebsd),
538     ("armv6-unknown-freebsd", armv6_unknown_freebsd),
539     ("armv7-unknown-freebsd", armv7_unknown_freebsd),
540     ("i686-unknown-freebsd", i686_unknown_freebsd),
541     ("powerpc64-unknown-freebsd", powerpc64_unknown_freebsd),
542     ("x86_64-unknown-freebsd", x86_64_unknown_freebsd),
543
544     ("x86_64-unknown-dragonfly", x86_64_unknown_dragonfly),
545
546     ("aarch64-unknown-openbsd", aarch64_unknown_openbsd),
547     ("i686-unknown-openbsd", i686_unknown_openbsd),
548     ("sparc64-unknown-openbsd", sparc64_unknown_openbsd),
549     ("x86_64-unknown-openbsd", x86_64_unknown_openbsd),
550
551     ("aarch64-unknown-netbsd", aarch64_unknown_netbsd),
552     ("armv6-unknown-netbsd-eabihf", armv6_unknown_netbsd_eabihf),
553     ("armv7-unknown-netbsd-eabihf", armv7_unknown_netbsd_eabihf),
554     ("i686-unknown-netbsd", i686_unknown_netbsd),
555     ("powerpc-unknown-netbsd", powerpc_unknown_netbsd),
556     ("sparc64-unknown-netbsd", sparc64_unknown_netbsd),
557     ("x86_64-unknown-netbsd", x86_64_unknown_netbsd),
558     ("x86_64-rumprun-netbsd", x86_64_rumprun_netbsd),
559
560     ("i686-unknown-haiku", i686_unknown_haiku),
561     ("x86_64-unknown-haiku", x86_64_unknown_haiku),
562
563     ("aarch64-apple-darwin", aarch64_apple_darwin),
564     ("x86_64-apple-darwin", x86_64_apple_darwin),
565     ("i686-apple-darwin", i686_apple_darwin),
566
567     ("aarch64-fuchsia", aarch64_fuchsia),
568     ("x86_64-fuchsia", x86_64_fuchsia),
569
570     ("avr-unknown-gnu-atmega328", avr_unknown_gnu_atmega328),
571
572     ("x86_64-unknown-l4re-uclibc", x86_64_unknown_l4re_uclibc),
573
574     ("aarch64-unknown-redox", aarch64_unknown_redox),
575     ("x86_64-unknown-redox", x86_64_unknown_redox),
576
577     ("i386-apple-ios", i386_apple_ios),
578     ("x86_64-apple-ios", x86_64_apple_ios),
579     ("aarch64-apple-ios", aarch64_apple_ios),
580     ("armv7-apple-ios", armv7_apple_ios),
581     ("armv7s-apple-ios", armv7s_apple_ios),
582     ("x86_64-apple-ios-macabi", x86_64_apple_ios_macabi),
583     ("aarch64-apple-ios-macabi", aarch64_apple_ios_macabi),
584     ("aarch64-apple-tvos", aarch64_apple_tvos),
585     ("x86_64-apple-tvos", x86_64_apple_tvos),
586
587     ("armebv7r-none-eabi", armebv7r_none_eabi),
588     ("armebv7r-none-eabihf", armebv7r_none_eabihf),
589     ("armv7r-none-eabi", armv7r_none_eabi),
590     ("armv7r-none-eabihf", armv7r_none_eabihf),
591
592     // `x86_64-pc-solaris` is an alias for `x86_64_sun_solaris` for backwards compatibility reasons.
593     // (See <https://github.com/rust-lang/rust/issues/40531>.)
594     ("x86_64-sun-solaris", "x86_64-pc-solaris", x86_64_sun_solaris),
595     ("sparcv9-sun-solaris", sparcv9_sun_solaris),
596
597     ("x86_64-unknown-illumos", x86_64_unknown_illumos),
598
599     ("x86_64-pc-windows-gnu", x86_64_pc_windows_gnu),
600     ("i686-pc-windows-gnu", i686_pc_windows_gnu),
601     ("i686-uwp-windows-gnu", i686_uwp_windows_gnu),
602     ("x86_64-uwp-windows-gnu", x86_64_uwp_windows_gnu),
603
604     ("aarch64-pc-windows-msvc", aarch64_pc_windows_msvc),
605     ("aarch64-uwp-windows-msvc", aarch64_uwp_windows_msvc),
606     ("x86_64-pc-windows-msvc", x86_64_pc_windows_msvc),
607     ("x86_64-uwp-windows-msvc", x86_64_uwp_windows_msvc),
608     ("i686-pc-windows-msvc", i686_pc_windows_msvc),
609     ("i686-uwp-windows-msvc", i686_uwp_windows_msvc),
610     ("i586-pc-windows-msvc", i586_pc_windows_msvc),
611     ("thumbv7a-pc-windows-msvc", thumbv7a_pc_windows_msvc),
612     ("thumbv7a-uwp-windows-msvc", thumbv7a_uwp_windows_msvc),
613
614     ("asmjs-unknown-emscripten", asmjs_unknown_emscripten),
615     ("wasm32-unknown-emscripten", wasm32_unknown_emscripten),
616     ("wasm32-unknown-unknown", wasm32_unknown_unknown),
617     ("wasm32-wasi", wasm32_wasi),
618
619     ("thumbv6m-none-eabi", thumbv6m_none_eabi),
620     ("thumbv7m-none-eabi", thumbv7m_none_eabi),
621     ("thumbv7em-none-eabi", thumbv7em_none_eabi),
622     ("thumbv7em-none-eabihf", thumbv7em_none_eabihf),
623     ("thumbv8m.base-none-eabi", thumbv8m_base_none_eabi),
624     ("thumbv8m.main-none-eabi", thumbv8m_main_none_eabi),
625     ("thumbv8m.main-none-eabihf", thumbv8m_main_none_eabihf),
626
627     ("armv7a-none-eabi", armv7a_none_eabi),
628     ("armv7a-none-eabihf", armv7a_none_eabihf),
629
630     ("msp430-none-elf", msp430_none_elf),
631
632     ("aarch64-unknown-hermit", aarch64_unknown_hermit),
633     ("x86_64-unknown-hermit", x86_64_unknown_hermit),
634     ("x86_64-unknown-hermit-kernel", x86_64_unknown_hermit_kernel),
635
636     ("riscv32i-unknown-none-elf", riscv32i_unknown_none_elf),
637     ("riscv32imc-unknown-none-elf", riscv32imc_unknown_none_elf),
638     ("riscv32imac-unknown-none-elf", riscv32imac_unknown_none_elf),
639     ("riscv32gc-unknown-linux-gnu", riscv32gc_unknown_linux_gnu),
640     ("riscv64imac-unknown-none-elf", riscv64imac_unknown_none_elf),
641     ("riscv64gc-unknown-none-elf", riscv64gc_unknown_none_elf),
642     ("riscv64gc-unknown-linux-gnu", riscv64gc_unknown_linux_gnu),
643
644     ("aarch64-unknown-none", aarch64_unknown_none),
645     ("aarch64-unknown-none-softfloat", aarch64_unknown_none_softfloat),
646
647     ("x86_64-fortanix-unknown-sgx", x86_64_fortanix_unknown_sgx),
648
649     ("x86_64-unknown-uefi", x86_64_unknown_uefi),
650     ("i686-unknown-uefi", i686_unknown_uefi),
651
652     ("nvptx64-nvidia-cuda", nvptx64_nvidia_cuda),
653
654     ("i686-wrs-vxworks", i686_wrs_vxworks),
655     ("x86_64-wrs-vxworks", x86_64_wrs_vxworks),
656     ("armv7-wrs-vxworks-eabihf", armv7_wrs_vxworks_eabihf),
657     ("aarch64-wrs-vxworks", aarch64_wrs_vxworks),
658     ("powerpc-wrs-vxworks", powerpc_wrs_vxworks),
659     ("powerpc-wrs-vxworks-spe", powerpc_wrs_vxworks_spe),
660     ("powerpc64-wrs-vxworks", powerpc64_wrs_vxworks),
661
662     ("mipsel-sony-psp", mipsel_sony_psp),
663     ("mipsel-unknown-none", mipsel_unknown_none),
664     ("thumbv4t-none-eabi", thumbv4t_none_eabi),
665 }
666
667 /// Everything `rustc` knows about how to compile for a specific target.
668 ///
669 /// Every field here must be specified, and has no default value.
670 #[derive(PartialEq, Clone, Debug)]
671 pub struct Target {
672     /// Target triple to pass to LLVM.
673     pub llvm_target: String,
674     /// Number of bits in a pointer. Influences the `target_pointer_width` `cfg` variable.
675     pub pointer_width: u32,
676     /// Architecture to use for ABI considerations. Valid options include: "x86",
677     /// "x86_64", "arm", "aarch64", "mips", "powerpc", "powerpc64", and others.
678     pub arch: String,
679     /// [Data layout](http://llvm.org/docs/LangRef.html#data-layout) to pass to LLVM.
680     pub data_layout: String,
681     /// Optional settings with defaults.
682     pub options: TargetOptions,
683 }
684
685 pub trait HasTargetSpec {
686     fn target_spec(&self) -> &Target;
687 }
688
689 impl HasTargetSpec for Target {
690     fn target_spec(&self) -> &Target {
691         self
692     }
693 }
694
695 /// Optional aspects of a target specification.
696 ///
697 /// This has an implementation of `Default`, see each field for what the default is. In general,
698 /// these try to take "minimal defaults" that don't assume anything about the runtime they run in.
699 ///
700 /// `TargetOptions` as a separate structure is mostly an implementation detail of `Target`
701 /// construction, all its fields logically belong to `Target` and available from `Target`
702 /// through `Deref` impls.
703 #[derive(PartialEq, Clone, Debug)]
704 pub struct TargetOptions {
705     /// Whether the target is built-in or loaded from a custom target specification.
706     pub is_builtin: bool,
707
708     /// String to use as the `target_endian` `cfg` variable. Defaults to "little".
709     pub endian: String,
710     /// Width of c_int type. Defaults to "32".
711     pub c_int_width: String,
712     /// OS name to use for conditional compilation (`target_os`). Defaults to "none".
713     /// "none" implies a bare metal target without `std` library.
714     /// A couple of targets having `std` also use "unknown" as an `os` value,
715     /// but they are exceptions.
716     pub os: String,
717     /// Environment name to use for conditional compilation (`target_env`). Defaults to "".
718     pub env: String,
719     /// Vendor name to use for conditional compilation (`target_vendor`). Defaults to "unknown".
720     pub vendor: String,
721     /// Default linker flavor used if `-C linker-flavor` or `-C linker` are not passed
722     /// on the command line. Defaults to `LinkerFlavor::Gcc`.
723     pub linker_flavor: LinkerFlavor,
724
725     /// Linker to invoke
726     pub linker: Option<String>,
727
728     /// LLD flavor used if `lld` (or `rust-lld`) is specified as a linker
729     /// without clarifying its flavor in any way.
730     pub lld_flavor: LldFlavor,
731
732     /// Linker arguments that are passed *before* any user-defined libraries.
733     pub pre_link_args: LinkArgs,
734     /// Objects to link before and after all other object code.
735     pub pre_link_objects: CrtObjects,
736     pub post_link_objects: CrtObjects,
737     /// Same as `(pre|post)_link_objects`, but when we fail to pull the objects with help of the
738     /// target's native gcc and fall back to the "self-contained" mode and pull them manually.
739     /// See `crt_objects.rs` for some more detailed documentation.
740     pub pre_link_objects_fallback: CrtObjects,
741     pub post_link_objects_fallback: CrtObjects,
742     /// Which logic to use to determine whether to fall back to the "self-contained" mode or not.
743     pub crt_objects_fallback: Option<CrtObjectsFallback>,
744
745     /// Linker arguments that are unconditionally passed after any
746     /// user-defined but before post-link objects. Standard platform
747     /// libraries that should be always be linked to, usually go here.
748     pub late_link_args: LinkArgs,
749     /// Linker arguments used in addition to `late_link_args` if at least one
750     /// Rust dependency is dynamically linked.
751     pub late_link_args_dynamic: LinkArgs,
752     /// Linker arguments used in addition to `late_link_args` if aall Rust
753     /// dependencies are statically linked.
754     pub late_link_args_static: LinkArgs,
755     /// Linker arguments that are unconditionally passed *after* any
756     /// user-defined libraries.
757     pub post_link_args: LinkArgs,
758     /// Optional link script applied to `dylib` and `executable` crate types.
759     /// This is a string containing the script, not a path. Can only be applied
760     /// to linkers where `linker_is_gnu` is true.
761     pub link_script: Option<String>,
762
763     /// Environment variables to be set for the linker invocation.
764     pub link_env: Vec<(String, String)>,
765     /// Environment variables to be removed for the linker invocation.
766     pub link_env_remove: Vec<String>,
767
768     /// Extra arguments to pass to the external assembler (when used)
769     pub asm_args: Vec<String>,
770
771     /// Default CPU to pass to LLVM. Corresponds to `llc -mcpu=$cpu`. Defaults
772     /// to "generic".
773     pub cpu: String,
774     /// Default target features to pass to LLVM. These features will *always* be
775     /// passed, and cannot be disabled even via `-C`. Corresponds to `llc
776     /// -mattr=$features`.
777     pub features: String,
778     /// Whether dynamic linking is available on this target. Defaults to false.
779     pub dynamic_linking: bool,
780     /// If dynamic linking is available, whether only cdylibs are supported.
781     pub only_cdylib: bool,
782     /// Whether executables are available on this target. iOS, for example, only allows static
783     /// libraries. Defaults to false.
784     pub executables: bool,
785     /// Relocation model to use in object file. Corresponds to `llc
786     /// -relocation-model=$relocation_model`. Defaults to `Pic`.
787     pub relocation_model: RelocModel,
788     /// Code model to use. Corresponds to `llc -code-model=$code_model`.
789     /// Defaults to `None` which means "inherited from the base LLVM target".
790     pub code_model: Option<CodeModel>,
791     /// TLS model to use. Options are "global-dynamic" (default), "local-dynamic", "initial-exec"
792     /// and "local-exec". This is similar to the -ftls-model option in GCC/Clang.
793     pub tls_model: TlsModel,
794     /// Do not emit code that uses the "red zone", if the ABI has one. Defaults to false.
795     pub disable_redzone: bool,
796     /// Eliminate frame pointers from stack frames if possible. Defaults to true.
797     pub eliminate_frame_pointer: bool,
798     /// Emit each function in its own section. Defaults to true.
799     pub function_sections: bool,
800     /// String to prepend to the name of every dynamic library. Defaults to "lib".
801     pub dll_prefix: String,
802     /// String to append to the name of every dynamic library. Defaults to ".so".
803     pub dll_suffix: String,
804     /// String to append to the name of every executable.
805     pub exe_suffix: String,
806     /// String to prepend to the name of every static library. Defaults to "lib".
807     pub staticlib_prefix: String,
808     /// String to append to the name of every static library. Defaults to ".a".
809     pub staticlib_suffix: String,
810     /// OS family to use for conditional compilation. Valid options: "unix", "windows".
811     pub os_family: Option<String>,
812     /// Whether the target toolchain's ABI supports returning small structs as an integer.
813     pub abi_return_struct_as_int: bool,
814     /// Whether the target toolchain is like macOS's. Only useful for compiling against iOS/macOS,
815     /// in particular running dsymutil and some other stuff like `-dead_strip`. Defaults to false.
816     pub is_like_osx: bool,
817     /// Whether the target toolchain is like Solaris's.
818     /// Only useful for compiling against Illumos/Solaris,
819     /// as they have a different set of linker flags. Defaults to false.
820     pub is_like_solaris: bool,
821     /// Whether the target is like Windows.
822     /// This is a combination of several more specific properties represented as a single flag:
823     ///   - The target uses a Windows ABI,
824     ///   - uses PE/COFF as a format for object code,
825     ///   - uses Windows-style dllexport/dllimport for shared libraries,
826     ///   - uses import libraries and .def files for symbol exports,
827     ///   - executables support setting a subsystem.
828     pub is_like_windows: bool,
829     /// Whether the target is like MSVC.
830     /// This is a combination of several more specific properties represented as a single flag:
831     ///   - The target has all the properties from `is_like_windows`
832     ///     (for in-tree targets "is_like_msvc â‡’ is_like_windows" is ensured by a unit test),
833     ///   - has some MSVC-specific Windows ABI properties,
834     ///   - uses a link.exe-like linker,
835     ///   - uses CodeView/PDB for debuginfo and natvis for its visualization,
836     ///   - uses SEH-based unwinding,
837     ///   - supports control flow guard mechanism.
838     pub is_like_msvc: bool,
839     /// Whether the target toolchain is like Emscripten's. Only useful for compiling with
840     /// Emscripten toolchain.
841     /// Defaults to false.
842     pub is_like_emscripten: bool,
843     /// Whether the target toolchain is like Fuchsia's.
844     pub is_like_fuchsia: bool,
845     /// Version of DWARF to use if not using the default.
846     /// Useful because some platforms (osx, bsd) only want up to DWARF2.
847     pub dwarf_version: Option<u32>,
848     /// Whether the linker support GNU-like arguments such as -O. Defaults to false.
849     pub linker_is_gnu: bool,
850     /// The MinGW toolchain has a known issue that prevents it from correctly
851     /// handling COFF object files with more than 2<sup>15</sup> sections. Since each weak
852     /// symbol needs its own COMDAT section, weak linkage implies a large
853     /// number sections that easily exceeds the given limit for larger
854     /// codebases. Consequently we want a way to disallow weak linkage on some
855     /// platforms.
856     pub allows_weak_linkage: bool,
857     /// Whether the linker support rpaths or not. Defaults to false.
858     pub has_rpath: bool,
859     /// Whether to disable linking to the default libraries, typically corresponds
860     /// to `-nodefaultlibs`. Defaults to true.
861     pub no_default_libraries: bool,
862     /// Dynamically linked executables can be compiled as position independent
863     /// if the default relocation model of position independent code is not
864     /// changed. This is a requirement to take advantage of ASLR, as otherwise
865     /// the functions in the executable are not randomized and can be used
866     /// during an exploit of a vulnerability in any code.
867     pub position_independent_executables: bool,
868     /// Executables that are both statically linked and position-independent are supported.
869     pub static_position_independent_executables: bool,
870     /// Determines if the target always requires using the PLT for indirect
871     /// library calls or not. This controls the default value of the `-Z plt` flag.
872     pub needs_plt: bool,
873     /// Either partial, full, or off. Full RELRO makes the dynamic linker
874     /// resolve all symbols at startup and marks the GOT read-only before
875     /// starting the program, preventing overwriting the GOT.
876     pub relro_level: RelroLevel,
877     /// Format that archives should be emitted in. This affects whether we use
878     /// LLVM to assemble an archive or fall back to the system linker, and
879     /// currently only "gnu" is used to fall into LLVM. Unknown strings cause
880     /// the system linker to be used.
881     pub archive_format: String,
882     /// Is asm!() allowed? Defaults to true.
883     pub allow_asm: bool,
884     /// Whether the runtime startup code requires the `main` function be passed
885     /// `argc` and `argv` values.
886     pub main_needs_argc_argv: bool,
887
888     /// Flag indicating whether ELF TLS (e.g., #[thread_local]) is available for
889     /// this target.
890     pub has_elf_tls: bool,
891     // This is mainly for easy compatibility with emscripten.
892     // If we give emcc .o files that are actually .bc files it
893     // will 'just work'.
894     pub obj_is_bitcode: bool,
895     /// Whether the target requires that emitted object code includes bitcode.
896     pub forces_embed_bitcode: bool,
897     /// Content of the LLVM cmdline section associated with embedded bitcode.
898     pub bitcode_llvm_cmdline: String,
899
900     /// Don't use this field; instead use the `.min_atomic_width()` method.
901     pub min_atomic_width: Option<u64>,
902
903     /// Don't use this field; instead use the `.max_atomic_width()` method.
904     pub max_atomic_width: Option<u64>,
905
906     /// Whether the target supports atomic CAS operations natively
907     pub atomic_cas: bool,
908
909     /// Panic strategy: "unwind" or "abort"
910     pub panic_strategy: PanicStrategy,
911
912     /// A list of ABIs unsupported by the current target. Note that generic ABIs
913     /// are considered to be supported on all platforms and cannot be marked
914     /// unsupported.
915     pub unsupported_abis: Vec<Abi>,
916
917     /// Whether or not linking dylibs to a static CRT is allowed.
918     pub crt_static_allows_dylibs: bool,
919     /// Whether or not the CRT is statically linked by default.
920     pub crt_static_default: bool,
921     /// Whether or not crt-static is respected by the compiler (or is a no-op).
922     pub crt_static_respected: bool,
923
924     /// Whether or not stack probes (__rust_probestack) are enabled
925     pub stack_probes: bool,
926
927     /// The minimum alignment for global symbols.
928     pub min_global_align: Option<u64>,
929
930     /// Default number of codegen units to use in debug mode
931     pub default_codegen_units: Option<u64>,
932
933     /// Whether to generate trap instructions in places where optimization would
934     /// otherwise produce control flow that falls through into unrelated memory.
935     pub trap_unreachable: bool,
936
937     /// This target requires everything to be compiled with LTO to emit a final
938     /// executable, aka there is no native linker for this target.
939     pub requires_lto: bool,
940
941     /// This target has no support for threads.
942     pub singlethread: bool,
943
944     /// Whether library functions call lowering/optimization is disabled in LLVM
945     /// for this target unconditionally.
946     pub no_builtins: bool,
947
948     /// The default visibility for symbols in this target should be "hidden"
949     /// rather than "default"
950     pub default_hidden_visibility: bool,
951
952     /// Whether a .debug_gdb_scripts section will be added to the output object file
953     pub emit_debug_gdb_scripts: bool,
954
955     /// Whether or not to unconditionally `uwtable` attributes on functions,
956     /// typically because the platform needs to unwind for things like stack
957     /// unwinders.
958     pub requires_uwtable: bool,
959
960     /// Whether or not SIMD types are passed by reference in the Rust ABI,
961     /// typically required if a target can be compiled with a mixed set of
962     /// target features. This is `true` by default, and `false` for targets like
963     /// wasm32 where the whole program either has simd or not.
964     pub simd_types_indirect: bool,
965
966     /// Pass a list of symbol which should be exported in the dylib to the linker.
967     pub limit_rdylib_exports: bool,
968
969     /// If set, have the linker export exactly these symbols, instead of using
970     /// the usual logic to figure this out from the crate itself.
971     pub override_export_symbols: Option<Vec<String>>,
972
973     /// Determines how or whether the MergeFunctions LLVM pass should run for
974     /// this target. Either "disabled", "trampolines", or "aliases".
975     /// The MergeFunctions pass is generally useful, but some targets may need
976     /// to opt out. The default is "aliases".
977     ///
978     /// Workaround for: <https://github.com/rust-lang/rust/issues/57356>
979     pub merge_functions: MergeFunctions,
980
981     /// Use platform dependent mcount function
982     pub mcount: String,
983
984     /// LLVM ABI name, corresponds to the '-mabi' parameter available in multilib C compilers
985     pub llvm_abiname: String,
986
987     /// Whether or not RelaxElfRelocation flag will be passed to the linker
988     pub relax_elf_relocations: bool,
989
990     /// Additional arguments to pass to LLVM, similar to the `-C llvm-args` codegen option.
991     pub llvm_args: Vec<String>,
992
993     /// Whether to use legacy .ctors initialization hooks rather than .init_array. Defaults
994     /// to false (uses .init_array).
995     pub use_ctors_section: bool,
996
997     /// Whether the linker is instructed to add a `GNU_EH_FRAME` ELF header
998     /// used to locate unwinding information is passed
999     /// (only has effect if the linker is `ld`-like).
1000     pub eh_frame_header: bool,
1001
1002     /// Is true if the target is an ARM architecture using thumb v1 which allows for
1003     /// thumb and arm interworking.
1004     pub has_thumb_interworking: bool,
1005 }
1006
1007 impl Default for TargetOptions {
1008     /// Creates a set of "sane defaults" for any target. This is still
1009     /// incomplete, and if used for compilation, will certainly not work.
1010     fn default() -> TargetOptions {
1011         TargetOptions {
1012             is_builtin: false,
1013             endian: "little".to_string(),
1014             c_int_width: "32".to_string(),
1015             os: "none".to_string(),
1016             env: String::new(),
1017             vendor: "unknown".to_string(),
1018             linker_flavor: LinkerFlavor::Gcc,
1019             linker: option_env!("CFG_DEFAULT_LINKER").map(|s| s.to_string()),
1020             lld_flavor: LldFlavor::Ld,
1021             pre_link_args: LinkArgs::new(),
1022             post_link_args: LinkArgs::new(),
1023             link_script: None,
1024             asm_args: Vec::new(),
1025             cpu: "generic".to_string(),
1026             features: String::new(),
1027             dynamic_linking: false,
1028             only_cdylib: false,
1029             executables: false,
1030             relocation_model: RelocModel::Pic,
1031             code_model: None,
1032             tls_model: TlsModel::GeneralDynamic,
1033             disable_redzone: false,
1034             eliminate_frame_pointer: true,
1035             function_sections: true,
1036             dll_prefix: "lib".to_string(),
1037             dll_suffix: ".so".to_string(),
1038             exe_suffix: String::new(),
1039             staticlib_prefix: "lib".to_string(),
1040             staticlib_suffix: ".a".to_string(),
1041             os_family: None,
1042             abi_return_struct_as_int: false,
1043             is_like_osx: false,
1044             is_like_solaris: false,
1045             is_like_windows: false,
1046             is_like_emscripten: false,
1047             is_like_msvc: false,
1048             is_like_fuchsia: false,
1049             dwarf_version: None,
1050             linker_is_gnu: false,
1051             allows_weak_linkage: true,
1052             has_rpath: false,
1053             no_default_libraries: true,
1054             position_independent_executables: false,
1055             static_position_independent_executables: false,
1056             needs_plt: false,
1057             relro_level: RelroLevel::None,
1058             pre_link_objects: Default::default(),
1059             post_link_objects: Default::default(),
1060             pre_link_objects_fallback: Default::default(),
1061             post_link_objects_fallback: Default::default(),
1062             crt_objects_fallback: None,
1063             late_link_args: LinkArgs::new(),
1064             late_link_args_dynamic: LinkArgs::new(),
1065             late_link_args_static: LinkArgs::new(),
1066             link_env: Vec::new(),
1067             link_env_remove: Vec::new(),
1068             archive_format: "gnu".to_string(),
1069             main_needs_argc_argv: true,
1070             allow_asm: true,
1071             has_elf_tls: false,
1072             obj_is_bitcode: false,
1073             forces_embed_bitcode: false,
1074             bitcode_llvm_cmdline: String::new(),
1075             min_atomic_width: None,
1076             max_atomic_width: None,
1077             atomic_cas: true,
1078             panic_strategy: PanicStrategy::Unwind,
1079             unsupported_abis: vec![],
1080             crt_static_allows_dylibs: false,
1081             crt_static_default: false,
1082             crt_static_respected: false,
1083             stack_probes: false,
1084             min_global_align: None,
1085             default_codegen_units: None,
1086             trap_unreachable: true,
1087             requires_lto: false,
1088             singlethread: false,
1089             no_builtins: false,
1090             default_hidden_visibility: false,
1091             emit_debug_gdb_scripts: true,
1092             requires_uwtable: false,
1093             simd_types_indirect: true,
1094             limit_rdylib_exports: true,
1095             override_export_symbols: None,
1096             merge_functions: MergeFunctions::Aliases,
1097             mcount: "mcount".to_string(),
1098             llvm_abiname: "".to_string(),
1099             relax_elf_relocations: false,
1100             llvm_args: vec![],
1101             use_ctors_section: false,
1102             eh_frame_header: true,
1103             has_thumb_interworking: false,
1104         }
1105     }
1106 }
1107
1108 /// `TargetOptions` being a separate type is basically an implementation detail of `Target` that is
1109 /// used for providing defaults. Perhaps there's a way to merge `TargetOptions` into `Target` so
1110 /// this `Deref` implementation is no longer necessary.
1111 impl Deref for Target {
1112     type Target = TargetOptions;
1113
1114     fn deref(&self) -> &Self::Target {
1115         &self.options
1116     }
1117 }
1118 impl DerefMut for Target {
1119     fn deref_mut(&mut self) -> &mut Self::Target {
1120         &mut self.options
1121     }
1122 }
1123
1124 impl Target {
1125     /// Given a function ABI, turn it into the correct ABI for this target.
1126     pub fn adjust_abi(&self, abi: Abi) -> Abi {
1127         match abi {
1128             Abi::System => {
1129                 if self.is_like_windows && self.arch == "x86" {
1130                     Abi::Stdcall
1131                 } else {
1132                     Abi::C
1133                 }
1134             }
1135             // These ABI kinds are ignored on non-x86 Windows targets.
1136             // See https://docs.microsoft.com/en-us/cpp/cpp/argument-passing-and-naming-conventions
1137             // and the individual pages for __stdcall et al.
1138             Abi::Stdcall | Abi::Fastcall | Abi::Vectorcall | Abi::Thiscall => {
1139                 if self.is_like_windows && self.arch != "x86" { Abi::C } else { abi }
1140             }
1141             Abi::EfiApi => {
1142                 if self.arch == "x86_64" {
1143                     Abi::Win64
1144                 } else {
1145                     Abi::C
1146                 }
1147             }
1148             abi => abi,
1149         }
1150     }
1151
1152     /// Minimum integer size in bits that this target can perform atomic
1153     /// operations on.
1154     pub fn min_atomic_width(&self) -> u64 {
1155         self.min_atomic_width.unwrap_or(8)
1156     }
1157
1158     /// Maximum integer size in bits that this target can perform atomic
1159     /// operations on.
1160     pub fn max_atomic_width(&self) -> u64 {
1161         self.max_atomic_width.unwrap_or_else(|| self.pointer_width.into())
1162     }
1163
1164     pub fn is_abi_supported(&self, abi: Abi) -> bool {
1165         abi.generic() || !self.unsupported_abis.contains(&abi)
1166     }
1167
1168     /// Loads a target descriptor from a JSON object.
1169     pub fn from_json(obj: Json) -> Result<Target, String> {
1170         // While ugly, this code must remain this way to retain
1171         // compatibility with existing JSON fields and the internal
1172         // expected naming of the Target and TargetOptions structs.
1173         // To ensure compatibility is retained, the built-in targets
1174         // are round-tripped through this code to catch cases where
1175         // the JSON parser is not updated to match the structs.
1176
1177         let get_req_field = |name: &str| {
1178             obj.find(name)
1179                 .map(|s| s.as_string())
1180                 .and_then(|os| os.map(|s| s.to_string()))
1181                 .ok_or_else(|| format!("Field {} in target specification is required", name))
1182         };
1183
1184         let mut base = Target {
1185             llvm_target: get_req_field("llvm-target")?,
1186             pointer_width: get_req_field("target-pointer-width")?
1187                 .parse::<u32>()
1188                 .map_err(|_| "target-pointer-width must be an integer".to_string())?,
1189             data_layout: get_req_field("data-layout")?,
1190             arch: get_req_field("arch")?,
1191             options: Default::default(),
1192         };
1193
1194         macro_rules! key {
1195             ($key_name:ident) => ( {
1196                 let name = (stringify!($key_name)).replace("_", "-");
1197                 if let Some(s) = obj.find(&name).and_then(Json::as_string) {
1198                     base.$key_name = s.to_string();
1199                 }
1200             } );
1201             ($key_name:ident = $json_name:expr) => ( {
1202                 let name = $json_name;
1203                 if let Some(s) = obj.find(&name).and_then(Json::as_string) {
1204                     base.$key_name = s.to_string();
1205                 }
1206             } );
1207             ($key_name:ident, bool) => ( {
1208                 let name = (stringify!($key_name)).replace("_", "-");
1209                 if let Some(s) = obj.find(&name).and_then(Json::as_boolean) {
1210                     base.$key_name = s;
1211                 }
1212             } );
1213             ($key_name:ident, Option<u32>) => ( {
1214                 let name = (stringify!($key_name)).replace("_", "-");
1215                 if let Some(s) = obj.find(&name).and_then(Json::as_u64) {
1216                     if s < 1 || s > 5 {
1217                         return Err("Not a valid DWARF version number".to_string());
1218                     }
1219                     base.$key_name = Some(s as u32);
1220                 }
1221             } );
1222             ($key_name:ident, Option<u64>) => ( {
1223                 let name = (stringify!($key_name)).replace("_", "-");
1224                 if let Some(s) = obj.find(&name).and_then(Json::as_u64) {
1225                     base.$key_name = Some(s);
1226                 }
1227             } );
1228             ($key_name:ident, MergeFunctions) => ( {
1229                 let name = (stringify!($key_name)).replace("_", "-");
1230                 obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| {
1231                     match s.parse::<MergeFunctions>() {
1232                         Ok(mergefunc) => base.$key_name = mergefunc,
1233                         _ => return Some(Err(format!("'{}' is not a valid value for \
1234                                                       merge-functions. Use 'disabled', \
1235                                                       'trampolines', or 'aliases'.",
1236                                                       s))),
1237                     }
1238                     Some(Ok(()))
1239                 })).unwrap_or(Ok(()))
1240             } );
1241             ($key_name:ident, RelocModel) => ( {
1242                 let name = (stringify!($key_name)).replace("_", "-");
1243                 obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| {
1244                     match s.parse::<RelocModel>() {
1245                         Ok(relocation_model) => base.$key_name = relocation_model,
1246                         _ => return Some(Err(format!("'{}' is not a valid relocation model. \
1247                                                       Run `rustc --print relocation-models` to \
1248                                                       see the list of supported values.", s))),
1249                     }
1250                     Some(Ok(()))
1251                 })).unwrap_or(Ok(()))
1252             } );
1253             ($key_name:ident, CodeModel) => ( {
1254                 let name = (stringify!($key_name)).replace("_", "-");
1255                 obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| {
1256                     match s.parse::<CodeModel>() {
1257                         Ok(code_model) => base.$key_name = Some(code_model),
1258                         _ => return Some(Err(format!("'{}' is not a valid code model. \
1259                                                       Run `rustc --print code-models` to \
1260                                                       see the list of supported values.", s))),
1261                     }
1262                     Some(Ok(()))
1263                 })).unwrap_or(Ok(()))
1264             } );
1265             ($key_name:ident, TlsModel) => ( {
1266                 let name = (stringify!($key_name)).replace("_", "-");
1267                 obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| {
1268                     match s.parse::<TlsModel>() {
1269                         Ok(tls_model) => base.$key_name = tls_model,
1270                         _ => return Some(Err(format!("'{}' is not a valid TLS model. \
1271                                                       Run `rustc --print tls-models` to \
1272                                                       see the list of supported values.", s))),
1273                     }
1274                     Some(Ok(()))
1275                 })).unwrap_or(Ok(()))
1276             } );
1277             ($key_name:ident, PanicStrategy) => ( {
1278                 let name = (stringify!($key_name)).replace("_", "-");
1279                 obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| {
1280                     match s {
1281                         "unwind" => base.$key_name = PanicStrategy::Unwind,
1282                         "abort" => base.$key_name = PanicStrategy::Abort,
1283                         _ => return Some(Err(format!("'{}' is not a valid value for \
1284                                                       panic-strategy. Use 'unwind' or 'abort'.",
1285                                                      s))),
1286                 }
1287                 Some(Ok(()))
1288             })).unwrap_or(Ok(()))
1289             } );
1290             ($key_name:ident, RelroLevel) => ( {
1291                 let name = (stringify!($key_name)).replace("_", "-");
1292                 obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| {
1293                     match s.parse::<RelroLevel>() {
1294                         Ok(level) => base.$key_name = level,
1295                         _ => return Some(Err(format!("'{}' is not a valid value for \
1296                                                       relro-level. Use 'full', 'partial, or 'off'.",
1297                                                       s))),
1298                     }
1299                     Some(Ok(()))
1300                 })).unwrap_or(Ok(()))
1301             } );
1302             ($key_name:ident, list) => ( {
1303                 let name = (stringify!($key_name)).replace("_", "-");
1304                 if let Some(v) = obj.find(&name).and_then(Json::as_array) {
1305                     base.$key_name = v.iter()
1306                         .map(|a| a.as_string().unwrap().to_string())
1307                         .collect();
1308                 }
1309             } );
1310             ($key_name:ident, opt_list) => ( {
1311                 let name = (stringify!($key_name)).replace("_", "-");
1312                 if let Some(v) = obj.find(&name).and_then(Json::as_array) {
1313                     base.$key_name = Some(v.iter()
1314                         .map(|a| a.as_string().unwrap().to_string())
1315                         .collect());
1316                 }
1317             } );
1318             ($key_name:ident, optional) => ( {
1319                 let name = (stringify!($key_name)).replace("_", "-");
1320                 if let Some(o) = obj.find(&name[..]) {
1321                     base.$key_name = o
1322                         .as_string()
1323                         .map(|s| s.to_string() );
1324                 }
1325             } );
1326             ($key_name:ident = $json_name:expr, optional) => ( {
1327                 let name = $json_name;
1328                 if let Some(o) = obj.find(&name[..]) {
1329                     base.$key_name = o
1330                         .as_string()
1331                         .map(|s| s.to_string() );
1332                 }
1333             } );
1334             ($key_name:ident, LldFlavor) => ( {
1335                 let name = (stringify!($key_name)).replace("_", "-");
1336                 obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| {
1337                     if let Some(flavor) = LldFlavor::from_str(&s) {
1338                         base.$key_name = flavor;
1339                     } else {
1340                         return Some(Err(format!(
1341                             "'{}' is not a valid value for lld-flavor. \
1342                              Use 'darwin', 'gnu', 'link' or 'wasm.",
1343                             s)))
1344                     }
1345                     Some(Ok(()))
1346                 })).unwrap_or(Ok(()))
1347             } );
1348             ($key_name:ident, LinkerFlavor) => ( {
1349                 let name = (stringify!($key_name)).replace("_", "-");
1350                 obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| {
1351                     match LinkerFlavor::from_str(s) {
1352                         Some(linker_flavor) => base.$key_name = linker_flavor,
1353                         _ => return Some(Err(format!("'{}' is not a valid value for linker-flavor. \
1354                                                       Use {}", s, LinkerFlavor::one_of()))),
1355                     }
1356                     Some(Ok(()))
1357                 })).unwrap_or(Ok(()))
1358             } );
1359             ($key_name:ident, crt_objects_fallback) => ( {
1360                 let name = (stringify!($key_name)).replace("_", "-");
1361                 obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| {
1362                     match s.parse::<CrtObjectsFallback>() {
1363                         Ok(fallback) => base.$key_name = Some(fallback),
1364                         _ => return Some(Err(format!("'{}' is not a valid CRT objects fallback. \
1365                                                       Use 'musl', 'mingw' or 'wasm'", s))),
1366                     }
1367                     Some(Ok(()))
1368                 })).unwrap_or(Ok(()))
1369             } );
1370             ($key_name:ident, link_objects) => ( {
1371                 let name = (stringify!($key_name)).replace("_", "-");
1372                 if let Some(val) = obj.find(&name[..]) {
1373                     let obj = val.as_object().ok_or_else(|| format!("{}: expected a \
1374                         JSON object with fields per CRT object kind.", name))?;
1375                     let mut args = CrtObjects::new();
1376                     for (k, v) in obj {
1377                         let kind = LinkOutputKind::from_str(&k).ok_or_else(|| {
1378                             format!("{}: '{}' is not a valid value for CRT object kind. \
1379                                      Use '(dynamic,static)-(nopic,pic)-exe' or \
1380                                      '(dynamic,static)-dylib'", name, k)
1381                         })?;
1382
1383                         let v = v.as_array().ok_or_else(||
1384                             format!("{}.{}: expected a JSON array", name, k)
1385                         )?.iter().enumerate()
1386                             .map(|(i,s)| {
1387                                 let s = s.as_string().ok_or_else(||
1388                                     format!("{}.{}[{}]: expected a JSON string", name, k, i))?;
1389                                 Ok(s.to_owned())
1390                             })
1391                             .collect::<Result<Vec<_>, String>>()?;
1392
1393                         args.insert(kind, v);
1394                     }
1395                     base.$key_name = args;
1396                 }
1397             } );
1398             ($key_name:ident, link_args) => ( {
1399                 let name = (stringify!($key_name)).replace("_", "-");
1400                 if let Some(val) = obj.find(&name[..]) {
1401                     let obj = val.as_object().ok_or_else(|| format!("{}: expected a \
1402                         JSON object with fields per linker-flavor.", name))?;
1403                     let mut args = LinkArgs::new();
1404                     for (k, v) in obj {
1405                         let flavor = LinkerFlavor::from_str(&k).ok_or_else(|| {
1406                             format!("{}: '{}' is not a valid value for linker-flavor. \
1407                                      Use 'em', 'gcc', 'ld' or 'msvc'", name, k)
1408                         })?;
1409
1410                         let v = v.as_array().ok_or_else(||
1411                             format!("{}.{}: expected a JSON array", name, k)
1412                         )?.iter().enumerate()
1413                             .map(|(i,s)| {
1414                                 let s = s.as_string().ok_or_else(||
1415                                     format!("{}.{}[{}]: expected a JSON string", name, k, i))?;
1416                                 Ok(s.to_owned())
1417                             })
1418                             .collect::<Result<Vec<_>, String>>()?;
1419
1420                         args.insert(flavor, v);
1421                     }
1422                     base.$key_name = args;
1423                 }
1424             } );
1425             ($key_name:ident, env) => ( {
1426                 let name = (stringify!($key_name)).replace("_", "-");
1427                 if let Some(a) = obj.find(&name[..]).and_then(|o| o.as_array()) {
1428                     for o in a {
1429                         if let Some(s) = o.as_string() {
1430                             let p = s.split('=').collect::<Vec<_>>();
1431                             if p.len() == 2 {
1432                                 let k = p[0].to_string();
1433                                 let v = p[1].to_string();
1434                                 base.$key_name.push((k, v));
1435                             }
1436                         }
1437                     }
1438                 }
1439             } );
1440         }
1441
1442         key!(is_builtin, bool);
1443         key!(endian = "target-endian");
1444         key!(c_int_width = "target-c-int-width");
1445         key!(os);
1446         key!(env);
1447         key!(vendor);
1448         key!(linker_flavor, LinkerFlavor)?;
1449         key!(linker, optional);
1450         key!(lld_flavor, LldFlavor)?;
1451         key!(pre_link_objects, link_objects);
1452         key!(post_link_objects, link_objects);
1453         key!(pre_link_objects_fallback, link_objects);
1454         key!(post_link_objects_fallback, link_objects);
1455         key!(crt_objects_fallback, crt_objects_fallback)?;
1456         key!(pre_link_args, link_args);
1457         key!(late_link_args, link_args);
1458         key!(late_link_args_dynamic, link_args);
1459         key!(late_link_args_static, link_args);
1460         key!(post_link_args, link_args);
1461         key!(link_script, optional);
1462         key!(link_env, env);
1463         key!(link_env_remove, list);
1464         key!(asm_args, list);
1465         key!(cpu);
1466         key!(features);
1467         key!(dynamic_linking, bool);
1468         key!(only_cdylib, bool);
1469         key!(executables, bool);
1470         key!(relocation_model, RelocModel)?;
1471         key!(code_model, CodeModel)?;
1472         key!(tls_model, TlsModel)?;
1473         key!(disable_redzone, bool);
1474         key!(eliminate_frame_pointer, bool);
1475         key!(function_sections, bool);
1476         key!(dll_prefix);
1477         key!(dll_suffix);
1478         key!(exe_suffix);
1479         key!(staticlib_prefix);
1480         key!(staticlib_suffix);
1481         key!(os_family = "target-family", optional);
1482         key!(abi_return_struct_as_int, bool);
1483         key!(is_like_osx, bool);
1484         key!(is_like_solaris, bool);
1485         key!(is_like_windows, bool);
1486         key!(is_like_msvc, bool);
1487         key!(is_like_emscripten, bool);
1488         key!(is_like_fuchsia, bool);
1489         key!(dwarf_version, Option<u32>);
1490         key!(linker_is_gnu, bool);
1491         key!(allows_weak_linkage, bool);
1492         key!(has_rpath, bool);
1493         key!(no_default_libraries, bool);
1494         key!(position_independent_executables, bool);
1495         key!(static_position_independent_executables, bool);
1496         key!(needs_plt, bool);
1497         key!(relro_level, RelroLevel)?;
1498         key!(archive_format);
1499         key!(allow_asm, bool);
1500         key!(main_needs_argc_argv, bool);
1501         key!(has_elf_tls, bool);
1502         key!(obj_is_bitcode, bool);
1503         key!(forces_embed_bitcode, bool);
1504         key!(bitcode_llvm_cmdline);
1505         key!(max_atomic_width, Option<u64>);
1506         key!(min_atomic_width, Option<u64>);
1507         key!(atomic_cas, bool);
1508         key!(panic_strategy, PanicStrategy)?;
1509         key!(crt_static_allows_dylibs, bool);
1510         key!(crt_static_default, bool);
1511         key!(crt_static_respected, bool);
1512         key!(stack_probes, bool);
1513         key!(min_global_align, Option<u64>);
1514         key!(default_codegen_units, Option<u64>);
1515         key!(trap_unreachable, bool);
1516         key!(requires_lto, bool);
1517         key!(singlethread, bool);
1518         key!(no_builtins, bool);
1519         key!(default_hidden_visibility, bool);
1520         key!(emit_debug_gdb_scripts, bool);
1521         key!(requires_uwtable, bool);
1522         key!(simd_types_indirect, bool);
1523         key!(limit_rdylib_exports, bool);
1524         key!(override_export_symbols, opt_list);
1525         key!(merge_functions, MergeFunctions)?;
1526         key!(mcount = "target-mcount");
1527         key!(llvm_abiname);
1528         key!(relax_elf_relocations, bool);
1529         key!(llvm_args, list);
1530         key!(use_ctors_section, bool);
1531         key!(eh_frame_header, bool);
1532         key!(has_thumb_interworking, bool);
1533
1534         // NB: The old name is deprecated, but support for it is retained for
1535         // compatibility.
1536         for name in ["abi-blacklist", "unsupported-abis"].iter() {
1537             if let Some(array) = obj.find(name).and_then(Json::as_array) {
1538                 for name in array.iter().filter_map(|abi| abi.as_string()) {
1539                     match lookup_abi(name) {
1540                         Some(abi) => {
1541                             if abi.generic() {
1542                                 return Err(format!(
1543                                     "The ABI \"{}\" is considered to be supported on all \
1544                                     targets and cannot be marked unsupported",
1545                                     abi
1546                                 ));
1547                             }
1548
1549                             base.unsupported_abis.push(abi)
1550                         }
1551                         None => {
1552                             return Err(format!(
1553                                 "Unknown ABI \"{}\" in target specification",
1554                                 name
1555                             ));
1556                         }
1557                     }
1558                 }
1559             }
1560         }
1561
1562         Ok(base)
1563     }
1564
1565     /// Search RUST_TARGET_PATH for a JSON file specifying the given target
1566     /// triple. Note that it could also just be a bare filename already, so also
1567     /// check for that. If one of the hardcoded targets we know about, just
1568     /// return it directly.
1569     ///
1570     /// The error string could come from any of the APIs called, including
1571     /// filesystem access and JSON decoding.
1572     pub fn search(target_triple: &TargetTriple) -> Result<Target, String> {
1573         use rustc_serialize::json;
1574         use std::env;
1575         use std::fs;
1576
1577         fn load_file(path: &Path) -> Result<Target, String> {
1578             let contents = fs::read(path).map_err(|e| e.to_string())?;
1579             let obj = json::from_reader(&mut &contents[..]).map_err(|e| e.to_string())?;
1580             Target::from_json(obj)
1581         }
1582
1583         match *target_triple {
1584             TargetTriple::TargetTriple(ref target_triple) => {
1585                 // check if triple is in list of built-in targets
1586                 if let Some(t) = load_builtin(target_triple) {
1587                     return Ok(t);
1588                 }
1589
1590                 // search for a file named `target_triple`.json in RUST_TARGET_PATH
1591                 let path = {
1592                     let mut target = target_triple.to_string();
1593                     target.push_str(".json");
1594                     PathBuf::from(target)
1595                 };
1596
1597                 let target_path = env::var_os("RUST_TARGET_PATH").unwrap_or_default();
1598
1599                 // FIXME 16351: add a sane default search path?
1600
1601                 for dir in env::split_paths(&target_path) {
1602                     let p = dir.join(&path);
1603                     if p.is_file() {
1604                         return load_file(&p);
1605                     }
1606                 }
1607                 Err(format!("Could not find specification for target {:?}", target_triple))
1608             }
1609             TargetTriple::TargetPath(ref target_path) => {
1610                 if target_path.is_file() {
1611                     return load_file(&target_path);
1612                 }
1613                 Err(format!("Target path {:?} is not a valid file", target_path))
1614             }
1615         }
1616     }
1617 }
1618
1619 impl ToJson for Target {
1620     fn to_json(&self) -> Json {
1621         let mut d = BTreeMap::new();
1622         let default: TargetOptions = Default::default();
1623
1624         macro_rules! target_val {
1625             ($attr:ident) => {{
1626                 let name = (stringify!($attr)).replace("_", "-");
1627                 d.insert(name, self.$attr.to_json());
1628             }};
1629             ($attr:ident, $key_name:expr) => {{
1630                 let name = $key_name;
1631                 d.insert(name.to_string(), self.$attr.to_json());
1632             }};
1633         }
1634
1635         macro_rules! target_option_val {
1636             ($attr:ident) => {{
1637                 let name = (stringify!($attr)).replace("_", "-");
1638                 if default.$attr != self.$attr {
1639                     d.insert(name, self.$attr.to_json());
1640                 }
1641             }};
1642             ($attr:ident, $key_name:expr) => {{
1643                 let name = $key_name;
1644                 if default.$attr != self.$attr {
1645                     d.insert(name.to_string(), self.$attr.to_json());
1646                 }
1647             }};
1648             (link_args - $attr:ident) => {{
1649                 let name = (stringify!($attr)).replace("_", "-");
1650                 if default.$attr != self.$attr {
1651                     let obj = self
1652                         .$attr
1653                         .iter()
1654                         .map(|(k, v)| (k.desc().to_owned(), v.clone()))
1655                         .collect::<BTreeMap<_, _>>();
1656                     d.insert(name, obj.to_json());
1657                 }
1658             }};
1659             (env - $attr:ident) => {{
1660                 let name = (stringify!($attr)).replace("_", "-");
1661                 if default.$attr != self.$attr {
1662                     let obj = self
1663                         .$attr
1664                         .iter()
1665                         .map(|&(ref k, ref v)| k.clone() + "=" + &v)
1666                         .collect::<Vec<_>>();
1667                     d.insert(name, obj.to_json());
1668                 }
1669             }};
1670         }
1671
1672         target_val!(llvm_target);
1673         d.insert("target-pointer-width".to_string(), self.pointer_width.to_string().to_json());
1674         target_val!(arch);
1675         target_val!(data_layout);
1676
1677         target_option_val!(is_builtin);
1678         target_option_val!(endian, "target-endian");
1679         target_option_val!(c_int_width, "target-c-int-width");
1680         target_option_val!(os);
1681         target_option_val!(env);
1682         target_option_val!(vendor);
1683         target_option_val!(linker_flavor);
1684         target_option_val!(linker);
1685         target_option_val!(lld_flavor);
1686         target_option_val!(pre_link_objects);
1687         target_option_val!(post_link_objects);
1688         target_option_val!(pre_link_objects_fallback);
1689         target_option_val!(post_link_objects_fallback);
1690         target_option_val!(crt_objects_fallback);
1691         target_option_val!(link_args - pre_link_args);
1692         target_option_val!(link_args - late_link_args);
1693         target_option_val!(link_args - late_link_args_dynamic);
1694         target_option_val!(link_args - late_link_args_static);
1695         target_option_val!(link_args - post_link_args);
1696         target_option_val!(link_script);
1697         target_option_val!(env - link_env);
1698         target_option_val!(link_env_remove);
1699         target_option_val!(asm_args);
1700         target_option_val!(cpu);
1701         target_option_val!(features);
1702         target_option_val!(dynamic_linking);
1703         target_option_val!(only_cdylib);
1704         target_option_val!(executables);
1705         target_option_val!(relocation_model);
1706         target_option_val!(code_model);
1707         target_option_val!(tls_model);
1708         target_option_val!(disable_redzone);
1709         target_option_val!(eliminate_frame_pointer);
1710         target_option_val!(function_sections);
1711         target_option_val!(dll_prefix);
1712         target_option_val!(dll_suffix);
1713         target_option_val!(exe_suffix);
1714         target_option_val!(staticlib_prefix);
1715         target_option_val!(staticlib_suffix);
1716         target_option_val!(os_family, "target-family");
1717         target_option_val!(abi_return_struct_as_int);
1718         target_option_val!(is_like_osx);
1719         target_option_val!(is_like_solaris);
1720         target_option_val!(is_like_windows);
1721         target_option_val!(is_like_msvc);
1722         target_option_val!(is_like_emscripten);
1723         target_option_val!(is_like_fuchsia);
1724         target_option_val!(dwarf_version);
1725         target_option_val!(linker_is_gnu);
1726         target_option_val!(allows_weak_linkage);
1727         target_option_val!(has_rpath);
1728         target_option_val!(no_default_libraries);
1729         target_option_val!(position_independent_executables);
1730         target_option_val!(static_position_independent_executables);
1731         target_option_val!(needs_plt);
1732         target_option_val!(relro_level);
1733         target_option_val!(archive_format);
1734         target_option_val!(allow_asm);
1735         target_option_val!(main_needs_argc_argv);
1736         target_option_val!(has_elf_tls);
1737         target_option_val!(obj_is_bitcode);
1738         target_option_val!(forces_embed_bitcode);
1739         target_option_val!(bitcode_llvm_cmdline);
1740         target_option_val!(min_atomic_width);
1741         target_option_val!(max_atomic_width);
1742         target_option_val!(atomic_cas);
1743         target_option_val!(panic_strategy);
1744         target_option_val!(crt_static_allows_dylibs);
1745         target_option_val!(crt_static_default);
1746         target_option_val!(crt_static_respected);
1747         target_option_val!(stack_probes);
1748         target_option_val!(min_global_align);
1749         target_option_val!(default_codegen_units);
1750         target_option_val!(trap_unreachable);
1751         target_option_val!(requires_lto);
1752         target_option_val!(singlethread);
1753         target_option_val!(no_builtins);
1754         target_option_val!(default_hidden_visibility);
1755         target_option_val!(emit_debug_gdb_scripts);
1756         target_option_val!(requires_uwtable);
1757         target_option_val!(simd_types_indirect);
1758         target_option_val!(limit_rdylib_exports);
1759         target_option_val!(override_export_symbols);
1760         target_option_val!(merge_functions);
1761         target_option_val!(mcount, "target-mcount");
1762         target_option_val!(llvm_abiname);
1763         target_option_val!(relax_elf_relocations);
1764         target_option_val!(llvm_args);
1765         target_option_val!(use_ctors_section);
1766         target_option_val!(eh_frame_header);
1767         target_option_val!(has_thumb_interworking);
1768
1769         if default.unsupported_abis != self.unsupported_abis {
1770             d.insert(
1771                 "unsupported-abis".to_string(),
1772                 self.unsupported_abis
1773                     .iter()
1774                     .map(|&name| Abi::name(name).to_json())
1775                     .collect::<Vec<_>>()
1776                     .to_json(),
1777             );
1778         }
1779
1780         Json::Object(d)
1781     }
1782 }
1783
1784 /// Either a target triple string or a path to a JSON file.
1785 #[derive(PartialEq, Clone, Debug, Hash, Encodable, Decodable)]
1786 pub enum TargetTriple {
1787     TargetTriple(String),
1788     TargetPath(PathBuf),
1789 }
1790
1791 impl TargetTriple {
1792     /// Creates a target triple from the passed target triple string.
1793     pub fn from_triple(triple: &str) -> Self {
1794         TargetTriple::TargetTriple(triple.to_string())
1795     }
1796
1797     /// Creates a target triple from the passed target path.
1798     pub fn from_path(path: &Path) -> Result<Self, io::Error> {
1799         let canonicalized_path = path.canonicalize()?;
1800         Ok(TargetTriple::TargetPath(canonicalized_path))
1801     }
1802
1803     /// Returns a string triple for this target.
1804     ///
1805     /// If this target is a path, the file name (without extension) is returned.
1806     pub fn triple(&self) -> &str {
1807         match *self {
1808             TargetTriple::TargetTriple(ref triple) => triple,
1809             TargetTriple::TargetPath(ref path) => path
1810                 .file_stem()
1811                 .expect("target path must not be empty")
1812                 .to_str()
1813                 .expect("target path must be valid unicode"),
1814         }
1815     }
1816
1817     /// Returns an extended string triple for this target.
1818     ///
1819     /// If this target is a path, a hash of the path is appended to the triple returned
1820     /// by `triple()`.
1821     pub fn debug_triple(&self) -> String {
1822         use std::collections::hash_map::DefaultHasher;
1823         use std::hash::{Hash, Hasher};
1824
1825         let triple = self.triple();
1826         if let TargetTriple::TargetPath(ref path) = *self {
1827             let mut hasher = DefaultHasher::new();
1828             path.hash(&mut hasher);
1829             let hash = hasher.finish();
1830             format!("{}-{}", triple, hash)
1831         } else {
1832             triple.to_owned()
1833         }
1834     }
1835 }
1836
1837 impl fmt::Display for TargetTriple {
1838     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1839         write!(f, "{}", self.debug_triple())
1840     }
1841 }