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