1use core::result::Result;
23use rustc_abi::Endian;
4use rustc_data_structures::fx::FxHashSet;
56use crate::spec::{
7Arch, Cc, CfgAbi, Env, FloatAbi, LinkerFlavor, Lld, LlvmAbi, Os, RelocModel, RustcAbi, Target,
8TargetKind,
9};
1011impl Target {
12/// Check some basic consistency of the current target. For JSON targets we are less strict;
13 /// some of these checks are more guidelines than strict rules.
14pub(super) fn check_consistency(&self, kind: TargetKind) -> Result<(), String> {
15macro_rules! check {
16 ($b:expr, $($msg:tt)*) => {
17if !$b {
18return Err(format!($($msg)*));
19 }
20 }
21 }
22macro_rules! check_eq {
23 ($left:expr, $right:expr, $($msg:tt)*) => {
24if ($left) != ($right) {
25return Err(format!($($msg)*));
26 }
27 }
28 }
29macro_rules! check_ne {
30 ($left:expr, $right:expr, $($msg:tt)*) => {
31if ($left) == ($right) {
32return Err(format!($($msg)*));
33 }
34 }
35 }
36macro_rules! check_matches {
37 ($left:expr, $right:pat, $($msg:tt)*) => {
38if !matches!($left, $right) {
39return Err(format!($($msg)*));
40 }
41 }
42 }
4344if (self.is_like_darwin) != (self.vendor == "apple") {
return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`is_like_darwin` must be set if and only if `vendor` is `apple`"))
}));
};check_eq!(
45self.is_like_darwin,
46self.vendor == "apple",
47"`is_like_darwin` must be set if and only if `vendor` is `apple`"
48);
49if (self.is_like_solaris) !=
(#[allow(non_exhaustive_omitted_patterns)] match self.os {
Os::Solaris | Os::Illumos => true,
_ => false,
}) {
return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`is_like_solaris` must be set if and only if `os` is `solaris` or `illumos`"))
}));
};check_eq!(
50self.is_like_solaris,
51matches!(self.os, Os::Solaris | Os::Illumos),
52"`is_like_solaris` must be set if and only if `os` is `solaris` or `illumos`"
53);
54if (self.is_like_gpu) !=
(self.arch == Arch::Nvptx64 || self.arch == Arch::AmdGpu) {
return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`is_like_gpu` must be set if and only if `target` is `nvptx64` or `amdgcn`"))
}));
};check_eq!(
55self.is_like_gpu,
56self.arch == Arch::Nvptx64 || self.arch == Arch::AmdGpu,
57"`is_like_gpu` must be set if and only if `target` is `nvptx64` or `amdgcn`"
58);
59if (self.is_like_windows) !=
(#[allow(non_exhaustive_omitted_patterns)] match self.os {
Os::Windows | Os::Uefi | Os::Cygwin => true,
_ => false,
}) {
return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`is_like_windows` must be set if and only if `os` is `windows`, `uefi` or `cygwin`"))
}));
};check_eq!(
60self.is_like_windows,
61matches!(self.os, Os::Windows | Os::Uefi | Os::Cygwin),
62"`is_like_windows` must be set if and only if `os` is `windows`, `uefi` or `cygwin`"
63);
64if (self.is_like_wasm) !=
(#[allow(non_exhaustive_omitted_patterns)] match self.arch {
Arch::Wasm32 | Arch::Wasm64 => true,
_ => false,
}) {
return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`is_like_wasm` must be set if and only if `arch` is `wasm32` or `wasm64`"))
}));
};check_eq!(
65self.is_like_wasm,
66matches!(self.arch, Arch::Wasm32 | Arch::Wasm64),
67"`is_like_wasm` must be set if and only if `arch` is `wasm32` or `wasm64`"
68);
69if self.is_like_msvc {
70if !self.is_like_windows {
return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("if `is_like_msvc` is set, `is_like_windows` must be set"))
}));
};check!(self.is_like_windows, "if `is_like_msvc` is set, `is_like_windows` must be set");
71 }
72if self.os == Os::Emscripten {
73if !self.is_like_wasm {
return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("the `emcscripten` os only makes sense on wasm-like targets"))
}));
};check!(self.is_like_wasm, "the `emcscripten` os only makes sense on wasm-like targets");
74 }
7576// Check that default linker flavor is compatible with some other key properties.
77if (self.is_like_darwin) !=
(#[allow(non_exhaustive_omitted_patterns)] match self.linker_flavor {
LinkerFlavor::Darwin(..) => true,
_ => false,
}) {
return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`linker_flavor` must be `darwin` if and only if `is_like_darwin` is set"))
}));
};check_eq!(
78self.is_like_darwin,
79matches!(self.linker_flavor, LinkerFlavor::Darwin(..)),
80"`linker_flavor` must be `darwin` if and only if `is_like_darwin` is set"
81);
82if (self.is_like_msvc) !=
(#[allow(non_exhaustive_omitted_patterns)] match self.linker_flavor {
LinkerFlavor::Msvc(..) => true,
_ => false,
}) {
return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`linker_flavor` must be `msvc` if and only if `is_like_msvc` is set"))
}));
};check_eq!(
83self.is_like_msvc,
84matches!(self.linker_flavor, LinkerFlavor::Msvc(..)),
85"`linker_flavor` must be `msvc` if and only if `is_like_msvc` is set"
86);
87if (self.is_like_wasm && self.os != Os::Emscripten) !=
(#[allow(non_exhaustive_omitted_patterns)] match self.linker_flavor {
LinkerFlavor::WasmLld(..) => true,
_ => false,
}) {
return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`linker_flavor` must be `wasm-lld` if and only if `is_like_wasm` is set and the `os` is not `emscripten`"))
}));
};check_eq!(
88self.is_like_wasm && self.os != Os::Emscripten,
89matches!(self.linker_flavor, LinkerFlavor::WasmLld(..)),
90"`linker_flavor` must be `wasm-lld` if and only if `is_like_wasm` is set and the `os` is not `emscripten`",
91 );
92if (self.os == Os::Emscripten) !=
(#[allow(non_exhaustive_omitted_patterns)] match self.linker_flavor {
LinkerFlavor::EmCc => true,
_ => false,
}) {
return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`linker_flavor` must be `em-cc` if and only if `os` is `emscripten`"))
}));
};check_eq!(
93self.os == Os::Emscripten,
94matches!(self.linker_flavor, LinkerFlavor::EmCc),
95"`linker_flavor` must be `em-cc` if and only if `os` is `emscripten`"
96);
97if (self.arch == Arch::Bpf) !=
(#[allow(non_exhaustive_omitted_patterns)] match self.linker_flavor {
LinkerFlavor::Bpf => true,
_ => false,
}) {
return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`linker_flavor` must be `bpf` if and only if `arch` is `bpf`"))
}));
};check_eq!(
98self.arch == Arch::Bpf,
99matches!(self.linker_flavor, LinkerFlavor::Bpf),
100"`linker_flavor` must be `bpf` if and only if `arch` is `bpf`"
101);
102103for args in [
104&self.pre_link_args,
105&self.late_link_args,
106&self.late_link_args_dynamic,
107&self.late_link_args_static,
108&self.post_link_args,
109 ] {
110for (&flavor, flavor_args) in args {
111if !(!flavor_args.is_empty() || self.arch == Arch::Avr) {
return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("linker flavor args must not be empty"))
}));
};check!(
112 !flavor_args.is_empty() || self.arch == Arch::Avr,
113"linker flavor args must not be empty"
114);
115// Check that flavors mentioned in link args are compatible with the default flavor.
116match self.linker_flavor {
117 LinkerFlavor::Gnu(..) => {
118if !#[allow(non_exhaustive_omitted_patterns)] match flavor {
LinkerFlavor::Gnu(..) => true,
_ => false,
} {
return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("mixing GNU and non-GNU linker flavors"))
}));
};check_matches!(
119 flavor,
120 LinkerFlavor::Gnu(..),
121"mixing GNU and non-GNU linker flavors"
122);
123 }
124 LinkerFlavor::Darwin(..) => {
125if !#[allow(non_exhaustive_omitted_patterns)] match flavor {
LinkerFlavor::Darwin(..) => true,
_ => false,
} {
return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("mixing Darwin and non-Darwin linker flavors"))
}));
}check_matches!(
126 flavor,
127 LinkerFlavor::Darwin(..),
128"mixing Darwin and non-Darwin linker flavors"
129)130 }
131 LinkerFlavor::WasmLld(..) => {
132if !#[allow(non_exhaustive_omitted_patterns)] match flavor {
LinkerFlavor::WasmLld(..) => true,
_ => false,
} {
return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("mixing wasm and non-wasm linker flavors"))
}));
}check_matches!(
133 flavor,
134 LinkerFlavor::WasmLld(..),
135"mixing wasm and non-wasm linker flavors"
136)137 }
138 LinkerFlavor::Unix(..) => {
139if !#[allow(non_exhaustive_omitted_patterns)] match flavor {
LinkerFlavor::Unix(..) => true,
_ => false,
} {
return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("mixing unix and non-unix linker flavors"))
}));
};check_matches!(
140 flavor,
141 LinkerFlavor::Unix(..),
142"mixing unix and non-unix linker flavors"
143);
144 }
145 LinkerFlavor::Msvc(..) => {
146if !#[allow(non_exhaustive_omitted_patterns)] match flavor {
LinkerFlavor::Msvc(..) => true,
_ => false,
} {
return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("mixing MSVC and non-MSVC linker flavors"))
}));
};check_matches!(
147 flavor,
148 LinkerFlavor::Msvc(..),
149"mixing MSVC and non-MSVC linker flavors"
150);
151 }
152 LinkerFlavor::EmCc | LinkerFlavor::Bpf | LinkerFlavor::Llbc => {
153if (flavor) != (self.linker_flavor) {
return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("mixing different linker flavors"))
}));
}check_eq!(flavor, self.linker_flavor, "mixing different linker flavors")154 }
155 }
156157// Check that link args for cc and non-cc versions of flavors are consistent.
158let check_noncc = |noncc_flavor| -> Result<(), String> {
159if let Some(noncc_args) = args.get(&noncc_flavor) {
160for arg in flavor_args {
161if let Some(suffix) = arg.strip_prefix("-Wl,") {
162if !noncc_args.iter().any(|a| a == suffix) {
return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!(" link args for cc and non-cc versions of flavors are not consistent"))
}));
};check!(
163 noncc_args.iter().any(|a| a == suffix),
164" link args for cc and non-cc versions of flavors are not consistent"
165);
166 }
167 }
168 }
169Ok(())
170 };
171172match self.linker_flavor {
173 LinkerFlavor::Gnu(Cc::Yes, lld) => check_noncc(LinkerFlavor::Gnu(Cc::No, lld))?,
174 LinkerFlavor::WasmLld(Cc::Yes) => check_noncc(LinkerFlavor::WasmLld(Cc::No))?,
175 LinkerFlavor::Unix(Cc::Yes) => check_noncc(LinkerFlavor::Unix(Cc::No))?,
176_ => {}
177 }
178 }
179180// Check that link args for lld and non-lld versions of flavors are consistent.
181for cc in [Cc::No, Cc::Yes] {
182if (args.get(&LinkerFlavor::Gnu(cc, Lld::No))) !=
(args.get(&LinkerFlavor::Gnu(cc, Lld::Yes))) {
return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("link args for lld and non-lld versions of flavors are not consistent"))
}));
};check_eq!(
183 args.get(&LinkerFlavor::Gnu(cc, Lld::No)),
184 args.get(&LinkerFlavor::Gnu(cc, Lld::Yes)),
185"link args for lld and non-lld versions of flavors are not consistent",
186 );
187if (args.get(&LinkerFlavor::Darwin(cc, Lld::No))) !=
(args.get(&LinkerFlavor::Darwin(cc, Lld::Yes))) {
return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("link args for lld and non-lld versions of flavors are not consistent"))
}));
};check_eq!(
188 args.get(&LinkerFlavor::Darwin(cc, Lld::No)),
189 args.get(&LinkerFlavor::Darwin(cc, Lld::Yes)),
190"link args for lld and non-lld versions of flavors are not consistent",
191 );
192 }
193if (args.get(&LinkerFlavor::Msvc(Lld::No))) !=
(args.get(&LinkerFlavor::Msvc(Lld::Yes))) {
return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("link args for lld and non-lld versions of flavors are not consistent"))
}));
};check_eq!(
194 args.get(&LinkerFlavor::Msvc(Lld::No)),
195 args.get(&LinkerFlavor::Msvc(Lld::Yes)),
196"link args for lld and non-lld versions of flavors are not consistent",
197 );
198 }
199200if self.link_self_contained.is_disabled() {
201if !(self.pre_link_objects_self_contained.is_empty() &&
self.post_link_objects_self_contained.is_empty()) {
return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("if `link_self_contained` is disabled, then `pre_link_objects_self_contained` and `post_link_objects_self_contained` must be empty"))
}));
};check!(
202self.pre_link_objects_self_contained.is_empty()
203 && self.post_link_objects_self_contained.is_empty(),
204"if `link_self_contained` is disabled, then `pre_link_objects_self_contained` and `post_link_objects_self_contained` must be empty",
205 );
206 }
207208// If your target really needs to deviate from the rules below,
209 // except it and document the reasons.
210 // Keep the default "unknown" vendor instead.
211if (self.vendor) == ("") {
return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`vendor` cannot be empty"))
}));
};check_ne!(self.vendor, "", "`vendor` cannot be empty");
212if let Os::Other(s) = &self.os {
213if !!s.is_empty() {
return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`os` cannot be empty"))
}));
};check!(!s.is_empty(), "`os` cannot be empty");
214 }
215if !self.can_use_os_unknown() {
216// Keep the default "none" for bare metal targets instead.
217if (self.os) == (Os::Unknown) {
return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`unknown` os can only be used on particular targets; use `none` for bare-metal targets"))
}));
};check_ne!(
218self.os,
219 Os::Unknown,
220"`unknown` os can only be used on particular targets; use `none` for bare-metal targets"
221);
222 }
223224// Check dynamic linking stuff.
225 // We skip this for JSON targets since otherwise, our default values would fail this test.
226 // These checks are not critical for correctness, but more like default guidelines.
227 // FIXME (https://github.com/rust-lang/rust/issues/133459): do we want to change the JSON
228 // target defaults so that they pass these checks?
229if kind == TargetKind::Builtin {
230// BPF: when targeting user space vms (like rbpf), those can load dynamic libraries.
231 // hexagon: when targeting QuRT, that OS can load dynamic libraries.
232 // wasm{32,64}: dynamic linking is inherent in the definition of the VM.
233if self.os == Os::None234 && !#[allow(non_exhaustive_omitted_patterns)] match self.arch {
Arch::Bpf | Arch::Hexagon | Arch::Wasm32 | Arch::Wasm64 => true,
_ => false,
}matches!(self.arch, Arch::Bpf | Arch::Hexagon | Arch::Wasm32 | Arch::Wasm64)235 {
236if !!self.dynamic_linking {
return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("dynamic linking is not supported on this OS/architecture"))
}));
};check!(
237 !self.dynamic_linking,
238"dynamic linking is not supported on this OS/architecture"
239);
240 }
241if self.only_cdylib
242 || self.crt_static_allows_dylibs
243 || !self.late_link_args_dynamic.is_empty()
244 {
245if !self.dynamic_linking {
return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("dynamic linking must be allowed when `only_cdylib` or `crt_static_allows_dylibs` or `late_link_args_dynamic` are set"))
}));
};check!(
246self.dynamic_linking,
247"dynamic linking must be allowed when `only_cdylib` or `crt_static_allows_dylibs` or `late_link_args_dynamic` are set"
248);
249 }
250// Apparently PIC was slow on wasm at some point, see comments in wasm_base.rs
251if self.dynamic_linking && !self.is_like_wasm {
252if (self.relocation_model) != (RelocModel::Pic) {
return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("targets that support dynamic linking must use the `pic` relocation model"))
}));
};check_eq!(
253self.relocation_model,
254 RelocModel::Pic,
255"targets that support dynamic linking must use the `pic` relocation model"
256);
257 }
258if self.position_independent_executables {
259if (self.relocation_model) != (RelocModel::Pic) {
return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("targets that support position-independent executables must use the `pic` relocation model"))
}));
};check_eq!(
260self.relocation_model,
261 RelocModel::Pic,
262"targets that support position-independent executables must use the `pic` relocation model"
263);
264 }
265// The UEFI targets do not support dynamic linking but still require PIC (#101377).
266if self.relocation_model == RelocModel::Pic && self.os != Os::Uefi {
267if !(self.dynamic_linking || self.position_independent_executables) {
return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("when the relocation model is `pic`, the target must support dynamic linking or use position-independent executables. Set the relocation model to `static` to avoid this requirement"))
}));
};check!(
268self.dynamic_linking || self.position_independent_executables,
269"when the relocation model is `pic`, the target must support dynamic linking or use position-independent executables. \
270 Set the relocation model to `static` to avoid this requirement"
271);
272 }
273if self.static_position_independent_executables {
274if !self.position_independent_executables {
return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("if `static_position_independent_executables` is set, then `position_independent_executables` must be set"))
}));
};check!(
275self.position_independent_executables,
276"if `static_position_independent_executables` is set, then `position_independent_executables` must be set"
277);
278 }
279if self.position_independent_executables {
280if !self.executables {
return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("if `position_independent_executables` is set then `executables` must be set"))
}));
};check!(
281self.executables,
282"if `position_independent_executables` is set then `executables` must be set"
283);
284 }
285 }
286287// Check crt static stuff
288if self.crt_static_default || self.crt_static_allows_dylibs {
289if !self.crt_static_respected {
return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("static CRT can be enabled but `crt_static_respected` is not set"))
}));
};check!(
290self.crt_static_respected,
291"static CRT can be enabled but `crt_static_respected` is not set"
292);
293 }
294295// Ensure built-in targets don't use the `Other` variants.
296if kind == TargetKind::Builtin {
297if !!#[allow(non_exhaustive_omitted_patterns)] match self.arch {
Arch::Other(_) => true,
_ => false,
} {
return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`Arch::Other` is only meant for JSON targets"))
}));
};check!(
298 !matches!(self.arch, Arch::Other(_)),
299"`Arch::Other` is only meant for JSON targets"
300);
301if !!#[allow(non_exhaustive_omitted_patterns)] match self.os {
Os::Other(_) => true,
_ => false,
} {
return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`Os::Other` is only meant for JSON targets"))
}));
};check!(!matches!(self.os, Os::Other(_)), "`Os::Other` is only meant for JSON targets");
302if !!#[allow(non_exhaustive_omitted_patterns)] match self.env {
Env::Other(_) => true,
_ => false,
} {
return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`Env::Other` is only meant for JSON targets"))
}));
};check!(
303 !matches!(self.env, Env::Other(_)),
304"`Env::Other` is only meant for JSON targets"
305);
306if !!#[allow(non_exhaustive_omitted_patterns)] match self.cfg_abi {
CfgAbi::Other(_) => true,
_ => false,
} {
return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`CfgAbi::Other` is only meant for JSON targets"))
}));
};check!(
307 !matches!(self.cfg_abi, CfgAbi::Other(_)),
308"`CfgAbi::Other` is only meant for JSON targets"
309);
310if !!#[allow(non_exhaustive_omitted_patterns)] match self.llvm_abiname {
LlvmAbi::Other(_) => true,
_ => false,
} {
return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`LlvmAbi::Other` is only meant for JSON targets"))
}));
};check!(
311 !matches!(self.llvm_abiname, LlvmAbi::Other(_)),
312"`LlvmAbi::Other` is only meant for JSON targets"
313);
314 }
315316// Check ABI flag consistency, for the architectures where we have proper ABI treatment.
317 // To ensure targets are trated consistently, please consult with the team before allowing
318 // new cases.
319match self.arch {
320 Arch::X86 => {
321if !(self.llvm_abiname == LlvmAbi::Unspecified) {
return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`llvm_abiname` is unused on x86-32"))
}));
};check!(
322self.llvm_abiname == LlvmAbi::Unspecified,
323"`llvm_abiname` is unused on x86-32"
324);
325if !self.llvm_floatabi.is_none() {
return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`llvm_floatabi` is unused on x86-32"))
}));
};check!(self.llvm_floatabi.is_none(), "`llvm_floatabi` is unused on x86-32");
326if !#[allow(non_exhaustive_omitted_patterns)] match (&self.rustc_abi,
&self.cfg_abi) {
(Some(RustcAbi::Softfloat),
CfgAbi::SoftFloat | CfgAbi::Unspecified | CfgAbi::Other(_)) |
(Some(RustcAbi::X86Sse2) | None,
CfgAbi::Uwp | CfgAbi::Llvm | CfgAbi::Sim | CfgAbi::Unspecified
| CfgAbi::Other(_)) => true,
_ => false,
} {
return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("invalid x86-32 Rust-specific ABI and `cfg(target_abi)` combination:\nRust-specific ABI: {0:?}\ncfg(target_abi): {1}",
self.rustc_abi, self.cfg_abi))
}));
};check_matches!(
327 (&self.rustc_abi, &self.cfg_abi),
328// FIXME: we do not currently set a target_abi for softfloat targets here,
329 // but we probably should, so we already allow it.
330(
331Some(RustcAbi::Softfloat),
332 CfgAbi::SoftFloat | CfgAbi::Unspecified | CfgAbi::Other(_)
333 ) | (
334Some(RustcAbi::X86Sse2) | None,
335 CfgAbi::Uwp
336 | CfgAbi::Llvm
337 | CfgAbi::Sim
338 | CfgAbi::Unspecified
339 | CfgAbi::Other(_)
340 ),
341"invalid x86-32 Rust-specific ABI and `cfg(target_abi)` combination:\n\
342 Rust-specific ABI: {:?}\n\
343 cfg(target_abi): {}",
344self.rustc_abi,
345self.cfg_abi,
346 );
347 }
348 Arch::X86_64 => {
349if !(self.llvm_abiname == LlvmAbi::Unspecified) {
return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`llvm_abiname` is unused on x86-64"))
}));
};check!(
350self.llvm_abiname == LlvmAbi::Unspecified,
351"`llvm_abiname` is unused on x86-64"
352);
353if !self.llvm_floatabi.is_none() {
return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`llvm_floatabi` is unused on x86-64"))
}));
};check!(self.llvm_floatabi.is_none(), "`llvm_floatabi` is unused on x86-64");
354// FIXME: we do not currently set a target_abi for softfloat targets here, but we
355 // probably should, so we already allow it.
356 // FIXME: Ensure that target_abi = "x32" correlates with actually using that ABI.
357 // Do any of the others need a similar check?
358if !#[allow(non_exhaustive_omitted_patterns)] match (&self.rustc_abi,
&self.cfg_abi) {
(Some(RustcAbi::Softfloat),
CfgAbi::SoftFloat | CfgAbi::Unspecified | CfgAbi::Other(_)) |
(None,
CfgAbi::X32 | CfgAbi::Llvm | CfgAbi::Fortanix | CfgAbi::Uwp |
CfgAbi::MacAbi | CfgAbi::Sim | CfgAbi::Unspecified |
CfgAbi::Other(_)) => true,
_ => false,
} {
return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("invalid x86-64 Rust-specific ABI and `cfg(target_abi)` combination:\nRust-specific ABI: {0:?}\ncfg(target_abi): {1}",
self.rustc_abi, self.cfg_abi))
}));
};check_matches!(
359 (&self.rustc_abi, &self.cfg_abi),
360 (
361Some(RustcAbi::Softfloat),
362 CfgAbi::SoftFloat | CfgAbi::Unspecified | CfgAbi::Other(_)
363 ) | (
364None,
365 CfgAbi::X32
366 | CfgAbi::Llvm
367 | CfgAbi::Fortanix
368 | CfgAbi::Uwp
369 | CfgAbi::MacAbi
370 | CfgAbi::Sim
371 | CfgAbi::Unspecified
372 | CfgAbi::Other(_)
373 ),
374"invalid x86-64 Rust-specific ABI and `cfg(target_abi)` combination:\n\
375 Rust-specific ABI: {:?}\n\
376 cfg(target_abi): {}",
377self.rustc_abi,
378self.cfg_abi,
379 );
380 }
381 Arch::RiscV32 => {
382if !self.llvm_floatabi.is_none() {
return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`llvm_floatabi` is unused on RISC-V"))
}));
};check!(self.llvm_floatabi.is_none(), "`llvm_floatabi` is unused on RISC-V");
383if !self.rustc_abi.is_none() {
return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`rustc_abi` is unused on RISC-V"))
}));
};check!(self.rustc_abi.is_none(), "`rustc_abi` is unused on RISC-V");
384if !#[allow(non_exhaustive_omitted_patterns)] match (&self.llvm_abiname,
&self.cfg_abi) {
(LlvmAbi::Ilp32, CfgAbi::Unspecified | CfgAbi::Other(_)) |
(LlvmAbi::Ilp32f, CfgAbi::Unspecified | CfgAbi::Other(_)) |
(LlvmAbi::Ilp32d, CfgAbi::Unspecified | CfgAbi::Other(_)) |
(LlvmAbi::Ilp32e, CfgAbi::Ilp32e) => true,
_ => false,
} {
return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("invalid RISC-V ABI name and `cfg(target_abi)` combination:\nABI name: {0}\ncfg(target_abi): {1}",
self.llvm_abiname, self.cfg_abi))
}));
};check_matches!(
385 (&self.llvm_abiname, &self.cfg_abi),
386 (LlvmAbi::Ilp32, CfgAbi::Unspecified | CfgAbi::Other(_))
387 | (LlvmAbi::Ilp32f, CfgAbi::Unspecified | CfgAbi::Other(_))
388 | (LlvmAbi::Ilp32d, CfgAbi::Unspecified | CfgAbi::Other(_))
389 | (LlvmAbi::Ilp32e, CfgAbi::Ilp32e),
390"invalid RISC-V ABI name and `cfg(target_abi)` combination:\n\
391 ABI name: {}\n\
392 cfg(target_abi): {}",
393self.llvm_abiname,
394self.cfg_abi,
395 );
396 }
397 Arch::RiscV64 => {
398// Note that the `lp64e` is still unstable as it's not (yet) part of the ELF psABI.
399if !self.llvm_floatabi.is_none() {
return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`llvm_floatabi` is unused on RISC-V"))
}));
};check!(self.llvm_floatabi.is_none(), "`llvm_floatabi` is unused on RISC-V");
400if !self.rustc_abi.is_none() {
return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`rustc_abi` is unused on RISC-V"))
}));
};check!(self.rustc_abi.is_none(), "`rustc_abi` is unused on RISC-V");
401if !#[allow(non_exhaustive_omitted_patterns)] match (&self.llvm_abiname,
&self.cfg_abi) {
(LlvmAbi::Lp64, CfgAbi::Unspecified | CfgAbi::Other(_)) |
(LlvmAbi::Lp64f, CfgAbi::Unspecified | CfgAbi::Other(_)) |
(LlvmAbi::Lp64d, CfgAbi::Unspecified | CfgAbi::Other(_)) |
(LlvmAbi::Lp64e, CfgAbi::Unspecified | CfgAbi::Other(_)) =>
true,
_ => false,
} {
return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("invalid RISC-V ABI name and `cfg(target_abi)` combination:\nABI name: {0}\ncfg(target_abi): {1}",
self.llvm_abiname, self.cfg_abi))
}));
};check_matches!(
402 (&self.llvm_abiname, &self.cfg_abi),
403 (LlvmAbi::Lp64, CfgAbi::Unspecified | CfgAbi::Other(_))
404 | (LlvmAbi::Lp64f, CfgAbi::Unspecified | CfgAbi::Other(_))
405 | (LlvmAbi::Lp64d, CfgAbi::Unspecified | CfgAbi::Other(_))
406 | (LlvmAbi::Lp64e, CfgAbi::Unspecified | CfgAbi::Other(_)),
407"invalid RISC-V ABI name and `cfg(target_abi)` combination:\n\
408 ABI name: {}\n\
409 cfg(target_abi): {}",
410self.llvm_abiname,
411self.cfg_abi,
412 );
413 }
414 Arch::Arm => {
415if !(self.llvm_abiname == LlvmAbi::Unspecified) {
return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`llvm_abiname` is unused on ARM"))
}));
};check!(
416self.llvm_abiname == LlvmAbi::Unspecified,
417"`llvm_abiname` is unused on ARM"
418);
419if !self.rustc_abi.is_none() {
return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`rustc_abi` is unused on ARM"))
}));
};check!(self.rustc_abi.is_none(), "`rustc_abi` is unused on ARM");
420if !#[allow(non_exhaustive_omitted_patterns)] match (&self.llvm_floatabi,
&self.cfg_abi) {
(Some(FloatAbi::Hard),
CfgAbi::EabiHf | CfgAbi::Uwp | CfgAbi::Unspecified |
CfgAbi::Other(_)) | (Some(FloatAbi::Soft), CfgAbi::Eabi) =>
true,
_ => false,
} {
return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("Invalid combination of float ABI and `cfg(target_abi)` for ARM target\nfloat ABI: {0:?}\ncfg(target_abi): {1}",
self.llvm_floatabi, self.cfg_abi))
}));
}check_matches!(
421 (&self.llvm_floatabi, &self.cfg_abi),
422 (
423Some(FloatAbi::Hard),
424 CfgAbi::EabiHf | CfgAbi::Uwp | CfgAbi::Unspecified | CfgAbi::Other(_)
425 ) | (Some(FloatAbi::Soft), CfgAbi::Eabi),
426"Invalid combination of float ABI and `cfg(target_abi)` for ARM target\n\
427 float ABI: {:?}\n\
428 cfg(target_abi): {}",
429self.llvm_floatabi,
430self.cfg_abi,
431 )432 }
433 Arch::AArch64 => {
434if !self.llvm_floatabi.is_none() {
return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`llvm_floatabi` is unused on aarch64"))
}));
};check!(self.llvm_floatabi.is_none(), "`llvm_floatabi` is unused on aarch64");
435// FIXME: Ensure that target_abi = "ilp32" correlates with actually using that ABI.
436 // Do any of the others need a similar check?
437if !#[allow(non_exhaustive_omitted_patterns)] match (&self.llvm_abiname,
&self.rustc_abi, &self.cfg_abi) {
(LlvmAbi::Pauthtest, None, CfgAbi::Pauthtest) |
(LlvmAbi::Unspecified, Some(RustcAbi::Softfloat),
CfgAbi::SoftFloat) |
(LlvmAbi::Unspecified, None,
CfgAbi::Ilp32 | CfgAbi::Llvm | CfgAbi::MacAbi | CfgAbi::Sim |
CfgAbi::Uwp | CfgAbi::Unspecified | CfgAbi::Other(_)) => true,
_ => false,
} {
return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("invalid aarch64 ABI combination:\nLLVM ABI: {0}\nRust-specific ABI: {1:?}\ncfg(target_abi): {2}",
self.llvm_abiname, self.rustc_abi, self.cfg_abi))
}));
};check_matches!(
438 (&self.llvm_abiname, &self.rustc_abi, &self.cfg_abi),
439 (LlvmAbi::Pauthtest, None, CfgAbi::Pauthtest)
440 | (LlvmAbi::Unspecified, Some(RustcAbi::Softfloat), CfgAbi::SoftFloat)
441 | (
442 LlvmAbi::Unspecified,
443None,
444 CfgAbi::Ilp32
445 | CfgAbi::Llvm
446 | CfgAbi::MacAbi
447 | CfgAbi::Sim
448 | CfgAbi::Uwp
449 | CfgAbi::Unspecified
450 | CfgAbi::Other(_)
451 ),
452"invalid aarch64 ABI combination:\n\
453 LLVM ABI: {}\n\
454 Rust-specific ABI: {:?}\n\
455 cfg(target_abi): {}",
456self.llvm_abiname,
457self.rustc_abi,
458self.cfg_abi,
459 );
460 }
461 Arch::PowerPC => {
462if !(self.llvm_abiname == LlvmAbi::Unspecified) {
return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`llvm_abiname` is unused on PowerPC"))
}));
};check!(
463self.llvm_abiname == LlvmAbi::Unspecified,
464"`llvm_abiname` is unused on PowerPC"
465);
466if !self.llvm_floatabi.is_none() {
return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`llvm_floatabi` is unused on PowerPC"))
}));
};check!(self.llvm_floatabi.is_none(), "`llvm_floatabi` is unused on PowerPC");
467if !#[allow(non_exhaustive_omitted_patterns)] match (&self.rustc_abi,
&self.cfg_abi) {
(Some(RustcAbi::PowerPcSpe), CfgAbi::Spe) |
(None, CfgAbi::Unspecified | CfgAbi::Other(_)) => true,
_ => false,
} {
return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("invalid PowerPC Rust-specific ABI and `cfg(target_abi)` combination:\nRust-specific ABI: {0:?}\ncfg(target_abi): {1}",
self.rustc_abi, self.cfg_abi))
}));
};check_matches!(
468 (&self.rustc_abi, &self.cfg_abi),
469 (Some(RustcAbi::PowerPcSpe), CfgAbi::Spe)
470 | (None, CfgAbi::Unspecified | CfgAbi::Other(_)),
471"invalid PowerPC Rust-specific ABI and `cfg(target_abi)` combination:\n\
472 Rust-specific ABI: {:?}\n\
473 cfg(target_abi): {}",
474self.rustc_abi,
475self.cfg_abi,
476 );
477 }
478 Arch::PowerPC64 => {
479if !self.llvm_floatabi.is_none() {
return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`llvm_floatabi` is unused on PowerPC64"))
}));
};check!(self.llvm_floatabi.is_none(), "`llvm_floatabi` is unused on PowerPC64");
480if !self.rustc_abi.is_none() {
return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`rustc_abi` is unused on PowerPC64"))
}));
};check!(self.rustc_abi.is_none(), "`rustc_abi` is unused on PowerPC64");
481// PowerPC64 targets that are not AIX must set their ABI to either ELFv1 or ELFv2
482if self.os == Os::Aix {
483// FIXME: Check that `target_abi` matches the actually configured ABI
484 // (vec-default vs vec-ext).
485if !#[allow(non_exhaustive_omitted_patterns)] match (&self.llvm_abiname,
&self.cfg_abi) {
(LlvmAbi::Unspecified, CfgAbi::VecDefault | CfgAbi::VecExtAbi) =>
true,
_ => false,
} {
return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("invalid PowerPC64 AIX ABI name and `cfg(target_abi)` combination:\nABI name: {0}\ncfg(target_abi): {1}",
self.llvm_abiname, self.cfg_abi))
}));
};check_matches!(
486 (&self.llvm_abiname, &self.cfg_abi),
487 (LlvmAbi::Unspecified, CfgAbi::VecDefault | CfgAbi::VecExtAbi),
488"invalid PowerPC64 AIX ABI name and `cfg(target_abi)` combination:\n\
489 ABI name: {}\n\
490 cfg(target_abi): {}",
491self.llvm_abiname,
492self.cfg_abi,
493 );
494 } else if self.endian == Endian::Big {
495if !#[allow(non_exhaustive_omitted_patterns)] match (&self.llvm_abiname,
&self.cfg_abi) {
(LlvmAbi::ElfV1, CfgAbi::ElfV1) | (LlvmAbi::ElfV2, CfgAbi::ElfV2)
=> true,
_ => false,
} {
return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("invalid PowerPC64 big-endian ABI name and `cfg(target_abi)` combination:\nABI name: {0}\ncfg(target_abi): {1}",
self.llvm_abiname, self.cfg_abi))
}));
};check_matches!(
496 (&self.llvm_abiname, &self.cfg_abi),
497 (LlvmAbi::ElfV1, CfgAbi::ElfV1) | (LlvmAbi::ElfV2, CfgAbi::ElfV2),
498"invalid PowerPC64 big-endian ABI name and `cfg(target_abi)` combination:\n\
499 ABI name: {}\n\
500 cfg(target_abi): {}",
501self.llvm_abiname,
502self.cfg_abi,
503 );
504 } else {
505if !#[allow(non_exhaustive_omitted_patterns)] match (&self.llvm_abiname,
&self.cfg_abi) {
(LlvmAbi::ElfV2, CfgAbi::ElfV2) => true,
_ => false,
} {
return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("invalid PowerPC64 little-endian ABI name and `cfg(target_abi)` combination:\nABI name: {0}\ncfg(target_abi): {1}",
self.llvm_abiname, self.cfg_abi))
}));
};check_matches!(
506 (&self.llvm_abiname, &self.cfg_abi),
507 (LlvmAbi::ElfV2, CfgAbi::ElfV2),
508"invalid PowerPC64 little-endian ABI name and `cfg(target_abi)` combination:\n\
509 ABI name: {}\n\
510 cfg(target_abi): {}",
511self.llvm_abiname,
512self.cfg_abi,
513 );
514 }
515 }
516 Arch::S390x => {
517if !(self.llvm_abiname == LlvmAbi::Unspecified) {
return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`llvm_abiname` is unused on s390x"))
}));
};check!(
518self.llvm_abiname == LlvmAbi::Unspecified,
519"`llvm_abiname` is unused on s390x"
520);
521if !self.llvm_floatabi.is_none() {
return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`llvm_floatabi` is unused on s390x"))
}));
};check!(self.llvm_floatabi.is_none(), "`llvm_floatabi` is unused on s390x");
522if !#[allow(non_exhaustive_omitted_patterns)] match (&self.rustc_abi,
&self.cfg_abi) {
(Some(RustcAbi::Softfloat), CfgAbi::SoftFloat) |
(None, CfgAbi::Unspecified | CfgAbi::Other(_)) => true,
_ => false,
} {
return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("invalid s390x Rust-specific ABI and `cfg(target_abi)` combination:\nRust-specific ABI: {0:?}\ncfg(target_abi): {1}",
self.rustc_abi, self.cfg_abi))
}));
};check_matches!(
523 (&self.rustc_abi, &self.cfg_abi),
524 (Some(RustcAbi::Softfloat), CfgAbi::SoftFloat)
525 | (None, CfgAbi::Unspecified | CfgAbi::Other(_)),
526"invalid s390x Rust-specific ABI and `cfg(target_abi)` combination:\n\
527 Rust-specific ABI: {:?}\n\
528 cfg(target_abi): {}",
529self.rustc_abi,
530self.cfg_abi,
531 );
532 }
533 Arch::LoongArch32 => {
534if !self.llvm_floatabi.is_none() {
return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`llvm_floatabi` is unused on LoongArch"))
}));
};check!(self.llvm_floatabi.is_none(), "`llvm_floatabi` is unused on LoongArch");
535if !self.rustc_abi.is_none() {
return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`rustc_abi` is unused on LoongArch"))
}));
};check!(self.rustc_abi.is_none(), "`rustc_abi` is unused on LoongArch");
536if !#[allow(non_exhaustive_omitted_patterns)] match (&self.llvm_abiname,
&self.cfg_abi) {
(LlvmAbi::Ilp32s, CfgAbi::SoftFloat) |
(LlvmAbi::Ilp32f, CfgAbi::Unspecified | CfgAbi::Other(_)) |
(LlvmAbi::Ilp32d, CfgAbi::Unspecified | CfgAbi::Other(_)) =>
true,
_ => false,
} {
return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("invalid LoongArch ABI name and `cfg(target_abi)` combination:\nABI name: {0}\ncfg(target_abi): {1}",
self.llvm_abiname, self.cfg_abi))
}));
};check_matches!(
537 (&self.llvm_abiname, &self.cfg_abi),
538 (LlvmAbi::Ilp32s, CfgAbi::SoftFloat)
539 | (LlvmAbi::Ilp32f, CfgAbi::Unspecified | CfgAbi::Other(_))
540 | (LlvmAbi::Ilp32d, CfgAbi::Unspecified | CfgAbi::Other(_)),
541"invalid LoongArch ABI name and `cfg(target_abi)` combination:\n\
542 ABI name: {}\n\
543 cfg(target_abi): {}",
544self.llvm_abiname,
545self.cfg_abi,
546 );
547 }
548 Arch::LoongArch64 => {
549if !self.llvm_floatabi.is_none() {
return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`llvm_floatabi` is unused on LoongArch"))
}));
};check!(self.llvm_floatabi.is_none(), "`llvm_floatabi` is unused on LoongArch");
550if !self.rustc_abi.is_none() {
return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`rustc_abi` is unused on LoongArch"))
}));
};check!(self.rustc_abi.is_none(), "`rustc_abi` is unused on LoongArch");
551if !#[allow(non_exhaustive_omitted_patterns)] match (&self.llvm_abiname,
&self.cfg_abi) {
(LlvmAbi::Lp64s, CfgAbi::SoftFloat) |
(LlvmAbi::Lp64f, CfgAbi::Unspecified | CfgAbi::Other(_)) |
(LlvmAbi::Lp64d, CfgAbi::Unspecified | CfgAbi::Other(_)) =>
true,
_ => false,
} {
return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("invalid LoongArch ABI name and `cfg(target_abi)` combination:\nABI name: {0}\ncfg(target_abi): {1}",
self.llvm_abiname, self.cfg_abi))
}));
};check_matches!(
552 (&self.llvm_abiname, &self.cfg_abi),
553 (LlvmAbi::Lp64s, CfgAbi::SoftFloat)
554 | (LlvmAbi::Lp64f, CfgAbi::Unspecified | CfgAbi::Other(_))
555 | (LlvmAbi::Lp64d, CfgAbi::Unspecified | CfgAbi::Other(_)),
556"invalid LoongArch ABI name and `cfg(target_abi)` combination:\n\
557 ABI name: {}\n\
558 cfg(target_abi): {}",
559self.llvm_abiname,
560self.cfg_abi,
561 );
562 }
563 Arch::Mips | Arch::Mips32r6 => {
564if !self.llvm_floatabi.is_none() {
return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`llvm_floatabi` is unused on MIPS"))
}));
};check!(self.llvm_floatabi.is_none(), "`llvm_floatabi` is unused on MIPS");
565if !self.rustc_abi.is_none() {
return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`rustc_abi` is unused on MIPS"))
}));
};check!(self.rustc_abi.is_none(), "`rustc_abi` is unused on MIPS");
566if !#[allow(non_exhaustive_omitted_patterns)] match (&self.llvm_abiname,
&self.cfg_abi) {
(LlvmAbi::O32, CfgAbi::Unspecified | CfgAbi::Other(_)) => true,
_ => false,
} {
return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("invalid MIPS ABI name and `cfg(target_abi)` combination:\nABI name: {0}\ncfg(target_abi): {1}",
self.llvm_abiname, self.cfg_abi))
}));
};check_matches!(
567 (&self.llvm_abiname, &self.cfg_abi),
568 (LlvmAbi::O32, CfgAbi::Unspecified | CfgAbi::Other(_)),
569"invalid MIPS ABI name and `cfg(target_abi)` combination:\n\
570 ABI name: {}\n\
571 cfg(target_abi): {}",
572self.llvm_abiname,
573self.cfg_abi,
574 );
575 }
576 Arch::Mips64 | Arch::Mips64r6 => {
577if !self.llvm_floatabi.is_none() {
return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`llvm_floatabi` is unused on MIPS"))
}));
};check!(self.llvm_floatabi.is_none(), "`llvm_floatabi` is unused on MIPS");
578if !self.rustc_abi.is_none() {
return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`rustc_abi` is unused on MIPS"))
}));
};check!(self.rustc_abi.is_none(), "`rustc_abi` is unused on MIPS");
579if !#[allow(non_exhaustive_omitted_patterns)] match (&self.llvm_abiname,
&self.cfg_abi) {
(LlvmAbi::N64, CfgAbi::Abi64) |
(LlvmAbi::N32, CfgAbi::Unspecified | CfgAbi::Other(_)) =>
true,
_ => false,
} {
return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("invalid MIPS ABI name and `cfg(target_abi)` combination:\nABI name: {0}\ncfg(target_abi): {1}",
self.llvm_abiname, self.cfg_abi))
}));
};check_matches!(
580 (&self.llvm_abiname, &self.cfg_abi),
581// No in-tree targets use "n32" but at least for now we let out-of-tree targets
582 // experiment with that.
583(LlvmAbi::N64, CfgAbi::Abi64)
584 | (LlvmAbi::N32, CfgAbi::Unspecified | CfgAbi::Other(_)),
585"invalid MIPS ABI name and `cfg(target_abi)` combination:\n\
586 ABI name: {}\n\
587 cfg(target_abi): {}",
588self.llvm_abiname,
589self.cfg_abi,
590 );
591 }
592 Arch::CSky => {
593if !(self.llvm_abiname == LlvmAbi::Unspecified) {
return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`llvm_abiname` is unused on CSky"))
}));
};check!(
594self.llvm_abiname == LlvmAbi::Unspecified,
595"`llvm_abiname` is unused on CSky"
596);
597if !self.llvm_floatabi.is_none() {
return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`llvm_floatabi` is unused on CSky"))
}));
};check!(self.llvm_floatabi.is_none(), "`llvm_floatabi` is unused on CSky");
598if !self.rustc_abi.is_none() {
return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`rustc_abi` is unused on CSky"))
}));
};check!(self.rustc_abi.is_none(), "`rustc_abi` is unused on CSky");
599// FIXME: Check that `target_abi` matches the actually configured ABI (v2 vs v2hf).
600if !#[allow(non_exhaustive_omitted_patterns)] match self.cfg_abi {
CfgAbi::AbiV2 | CfgAbi::AbiV2Hf => true,
_ => false,
} {
return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("invalid `target_abi` for CSky"))
}));
};check_matches!(
601self.cfg_abi,
602 CfgAbi::AbiV2 | CfgAbi::AbiV2Hf,
603"invalid `target_abi` for CSky"
604);
605 }
606 Arch::Wasm32 | Arch::Wasm64 => {
607if !(self.llvm_abiname == LlvmAbi::Unspecified) {
return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`llvm_abiname` is unused on wasm"))
}));
};check!(
608self.llvm_abiname == LlvmAbi::Unspecified,
609"`llvm_abiname` is unused on wasm"
610);
611if !self.llvm_floatabi.is_none() {
return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`llvm_floatabi` is unused on wasm"))
}));
};check!(self.llvm_floatabi.is_none(), "`llvm_floatabi` is unused on wasm");
612if !self.rustc_abi.is_none() {
return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`rustc_abi` is unused on wasm"))
}));
};check!(self.rustc_abi.is_none(), "`rustc_abi` is unused on wasm");
613if !#[allow(non_exhaustive_omitted_patterns)] match self.cfg_abi {
CfgAbi::Unspecified | CfgAbi::Other(_) => true,
_ => false,
} {
return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("invalid `target_abi` for wasm"))
}));
};check_matches!(
614self.cfg_abi,
615 CfgAbi::Unspecified | CfgAbi::Other(_),
616"invalid `target_abi` for wasm"
617);
618 }
619ref arch => {
620if !self.rustc_abi.is_none() {
return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`rustc_abi` is unused on {0}",
arch))
}));
};check!(self.rustc_abi.is_none(), "`rustc_abi` is unused on {arch}");
621// Ensure consistency among built-in targets, but give JSON targets the opportunity
622 // to experiment with these.
623if kind == TargetKind::Builtin {
624if !(self.llvm_abiname == LlvmAbi::Unspecified) {
return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`llvm_abiname` is unused on {0}",
arch))
}));
};check!(
625self.llvm_abiname == LlvmAbi::Unspecified,
626"`llvm_abiname` is unused on {arch}"
627);
628if !self.llvm_floatabi.is_none() {
return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`llvm_floatabi` is unused on {0}",
arch))
}));
};check!(self.llvm_floatabi.is_none(), "`llvm_floatabi` is unused on {arch}");
629if !#[allow(non_exhaustive_omitted_patterns)] match self.cfg_abi {
CfgAbi::Unspecified | CfgAbi::Other(_) => true,
_ => false,
} {
return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`target_abi` is unused on {0}",
arch))
}));
};check_matches!(
630self.cfg_abi,
631 CfgAbi::Unspecified | CfgAbi::Other(_),
632"`target_abi` is unused on {arch}"
633);
634 }
635 }
636 }
637638// Check that the target cpu constraints make sense.
639if self.need_explicit_cpu {
640if !self.requires_consistent_cpu {
return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("if `need_explicit_cpu` is set, then `requires_consistent_cpu` must be set"))
}));
};check!(
641self.requires_consistent_cpu,
642"if `need_explicit_cpu` is set, then `requires_consistent_cpu` must be set"
643);
644 }
645646// Check that the given target-features string makes some basic sense.
647if !self.features.is_empty() {
648let mut features_enabled = FxHashSet::default();
649let mut features_disabled = FxHashSet::default();
650for feat in self.features.split(',') {
651if let Some(feat) = feat.strip_prefix("+") {
652 features_enabled.insert(feat);
653if features_disabled.contains(feat) {
654return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("target feature `{0}` is both enabled and disabled",
feat))
})format!(
655"target feature `{feat}` is both enabled and disabled"
656));
657 }
658 } else if let Some(feat) = feat.strip_prefix("-") {
659 features_disabled.insert(feat);
660if features_enabled.contains(feat) {
661return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("target feature `{0}` is both enabled and disabled",
feat))
})format!(
662"target feature `{feat}` is both enabled and disabled"
663));
664 }
665 } else {
666return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("target feature `{0}` is invalid, must start with `+` or `-`",
feat))
})format!(
667"target feature `{feat}` is invalid, must start with `+` or `-`"
668));
669 }
670 }
671// Check that we don't mis-set any of the ABI-relevant features.
672let abi_feature_constraints = self.abi_required_features();
673for feat in abi_feature_constraints.required {
674// The feature might be enabled by default so we can't *require* it to show up.
675 // But it must not be *disabled*.
676if features_disabled.contains(feat) {
677return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("target feature `{0}` is required by the ABI but gets disabled in target spec",
feat))
})format!(
678"target feature `{feat}` is required by the ABI but gets disabled in target spec"
679));
680 }
681 }
682for feat in abi_feature_constraints.incompatible {
683// The feature might be disabled by default so we can't *require* it to show up.
684 // But it must not be *enabled*.
685if features_enabled.contains(feat) {
686return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("target feature `{0}` is incompatible with the ABI but gets enabled in target spec",
feat))
})format!(
687"target feature `{feat}` is incompatible with the ABI but gets enabled in target spec"
688));
689 }
690 }
691 }
692693Ok(())
694 }
695}