diff --git a/compiler/rustc_target/src/lib.rs b/compiler/rustc_target/src/lib.rs index ecc91ab9a310e..2962b0ab61e7f 100644 --- a/compiler/rustc_target/src/lib.rs +++ b/compiler/rustc_target/src/lib.rs @@ -12,11 +12,13 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] #![feature(assert_matches)] +#![feature(fn_traits)] #![feature(iter_intersperse)] #![feature(let_chains)] #![feature(min_exhaustive_patterns)] #![feature(rustc_attrs)] #![feature(rustdoc_internals)] +#![feature(unboxed_closures)] // tidy-alphabetical-end use std::path::{Path, PathBuf}; diff --git a/compiler/rustc_target/src/spec/maybe_lazy.rs b/compiler/rustc_target/src/spec/maybe_lazy.rs new file mode 100644 index 0000000000000..3694679b01f1c --- /dev/null +++ b/compiler/rustc_target/src/spec/maybe_lazy.rs @@ -0,0 +1,144 @@ +//! A custom LazyLock+Cow suitable for holding borrowed, owned or lazy data. + +use std::borrow::{Borrow, Cow}; +use std::fmt::{Debug, Display}; +use std::ops::Deref; +use std::sync::LazyLock; + +enum MaybeLazyInner { + Lazy(LazyLock), + Cow(Cow<'static, T>), +} + +/// A custom LazyLock+Cow suitable for holding borrowed, owned or lazy data. +/// +/// Technically this structure has 3 states: borrowed, owned and lazy +/// They can all be constructed from the [`MaybeLazy::borrowed`], [`MaybeLazy::owned`] and +/// [`MaybeLazy::lazy`] methods. +#[repr(transparent)] +pub struct MaybeLazy ::Owned> { + // Inner state. + // + // Not to be inlined since we may want in the future to + // make this struct usable to statics and we might need to + // workaround const-eval limitation (particulary around drop). + inner: MaybeLazyInner, +} + +impl T::Owned> MaybeLazy { + /// Create a [`MaybeLazy`] from an borrowed `T`. + #[inline] + pub const fn borrowed(a: &'static T) -> Self { + MaybeLazy { inner: MaybeLazyInner::Cow(Cow::Borrowed(a)) } + } + + /// Create a [`MaybeLazy`] from an borrowed `T`. + #[inline] + pub const fn owned(a: T::Owned) -> Self { + MaybeLazy { inner: MaybeLazyInner::Cow(Cow::Owned(a)) } + } + + /// Create a [`MaybeLazy`] from a function-able `F`. + #[inline] + pub const fn lazied(f: F) -> Self { + MaybeLazy { inner: MaybeLazyInner::Lazy(LazyLock::new(f)) } + } +} + +impl MaybeLazy { + /// Create a [`MaybeLazy`] from a function pointer. + #[inline] + pub const fn lazy(a: fn() -> T::Owned) -> Self { + Self::lazied(a) + } +} + +impl, F: FnOnce() -> T::Owned> Clone + for MaybeLazy +{ + #[inline] + fn clone(&self) -> Self { + MaybeLazy { + inner: MaybeLazyInner::Cow(match &self.inner { + MaybeLazyInner::Lazy(f) => Cow::Owned((*f).to_owned()), + MaybeLazyInner::Cow(c) => c.clone(), + }), + } + } +} + +impl, F: FnOnce() -> T::Owned> Default + for MaybeLazy +{ + #[inline] + fn default() -> MaybeLazy { + MaybeLazy::owned(T::Owned::default()) + } +} + +// `Debug`, `Display` and other traits below are implemented in terms of this `Deref` +impl>, F: FnOnce() -> T::Owned> Deref + for MaybeLazy +{ + type Target = T; + + #[inline] + fn deref(&self) -> &T { + match &self.inner { + MaybeLazyInner::Lazy(f) => (&**f).borrow(), + MaybeLazyInner::Cow(c) => &*c, + } + } +} + +impl + Debug, F: FnOnce() -> T::Owned> Debug + for MaybeLazy +{ + #[inline] + fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + Debug::fmt(&**self, fmt) + } +} + +impl + Display, F: FnOnce() -> T::Owned> Display + for MaybeLazy +{ + #[inline] + fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + Display::fmt(&**self, fmt) + } +} + +impl T::Owned> AsRef for MaybeLazy { + #[inline] + fn as_ref(&self) -> &T { + &**self + } +} + +impl< + T1: ?Sized + PartialEq + ToOwned, + T2: ?Sized + ToOwned, + F1: FnOnce() -> T1::Owned, + F2: FnOnce() -> T2::Owned, +> PartialEq> for MaybeLazy +{ + #[inline] + fn eq(&self, other: &MaybeLazy) -> bool { + PartialEq::eq(&**self, &**other) + } +} + +impl String> PartialEq<&str> for MaybeLazy { + #[inline] + fn eq(&self, other: &&str) -> bool { + &**self == *other + } +} + +impl String> From<&'static str> for MaybeLazy { + #[inline] + fn from(s: &'static str) -> MaybeLazy { + MaybeLazy::borrowed(s) + } +} diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 42860b1059ed7..de0c3e8a391af 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -39,6 +39,7 @@ use crate::abi::{Endian, Integer, Size, TargetDataLayout, TargetDataLayoutErrors use crate::json::{Json, ToJson}; use crate::spec::abi::Abi; use crate::spec::crt_objects::CrtObjects; +use crate::spec::maybe_lazy::MaybeLazy; use rustc_fs_util::try_canonicalize; use rustc_macros::{Decodable, Encodable, HashStable_Generic}; use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; @@ -55,6 +56,7 @@ use tracing::debug; pub mod abi; pub mod crt_objects; +pub mod maybe_lazy; mod base; pub use base::apple::deployment_target as current_apple_deployment_target; @@ -1879,7 +1881,7 @@ impl TargetWarnings { #[derive(PartialEq, Clone, Debug)] pub struct Target { /// Target triple to pass to LLVM. - pub llvm_target: StaticCow, + pub llvm_target: MaybeLazy, /// Metadata about a target, for example the description or tier. /// Used for generating target documentation. pub metadata: TargetMetadata, @@ -2734,7 +2736,7 @@ impl Target { }; let mut base = Target { - llvm_target: get_req_field("llvm-target")?.into(), + llvm_target: MaybeLazy::owned(get_req_field("llvm-target")?), metadata: Default::default(), pointer_width: get_req_field("target-pointer-width")? .parse::() diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs index 4e2964174f925..4dd4592478010 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs @@ -1,9 +1,12 @@ use crate::spec::base::apple::{macos_llvm_target, opts, Arch, TargetAbi}; -use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions}; +use crate::spec::{FramePointer, MaybeLazy, SanitizerSet, Target, TargetOptions}; pub fn target() -> Target { - let arch = Arch::Arm64; - let mut base = opts("macos", arch, TargetAbi::Normal); + const ARCH: Arch = Arch::Arm64; + const OS: &'static str = "macos"; + const ABI: TargetAbi = TargetAbi::Normal; + + let mut base = opts(OS, ARCH, ABI); base.cpu = "apple-m1".into(); base.max_atomic_width = Some(128); @@ -14,7 +17,7 @@ pub fn target() -> Target { // Clang automatically chooses a more specific target based on // MACOSX_DEPLOYMENT_TARGET. To enable cross-language LTO to work // correctly, we do too. - llvm_target: macos_llvm_target(arch).into(), + llvm_target: MaybeLazy::lazy(|| macos_llvm_target(ARCH)), metadata: crate::spec::TargetMetadata { description: None, tier: None, @@ -23,7 +26,7 @@ pub fn target() -> Target { }, pointer_width: 64, data_layout: "e-m:o-i64:64-i128:128-n32:64-S128-Fn32".into(), - arch: arch.target_arch(), + arch: ARCH.target_arch(), options: TargetOptions { mcount: "\u{1}mcount".into(), frame_pointer: FramePointer::NonLeaf, diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios.rs index 20655689772d8..ebf28292551d1 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios.rs @@ -1,9 +1,12 @@ use crate::spec::base::apple::{ios_llvm_target, opts, Arch, TargetAbi}; -use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions}; +use crate::spec::{FramePointer, MaybeLazy, SanitizerSet, Target, TargetOptions}; pub fn target() -> Target { - let arch = Arch::Arm64; - let mut base = opts("ios", arch, TargetAbi::Normal); + const ARCH: Arch = Arch::Arm64; + const OS: &'static str = "ios"; + const ABI: TargetAbi = TargetAbi::Normal; + + let mut base = opts(OS, ARCH, ABI); base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::THREAD; Target { @@ -11,7 +14,7 @@ pub fn target() -> Target { // IPHONEOS_DEPLOYMENT_TARGET. // This is required for the target to pick the right // MACH-O commands, so we do too. - llvm_target: ios_llvm_target(arch).into(), + llvm_target: MaybeLazy::lazy(|| ios_llvm_target(ARCH)), metadata: crate::spec::TargetMetadata { description: None, tier: None, @@ -20,7 +23,7 @@ pub fn target() -> Target { }, pointer_width: 64, data_layout: "e-m:o-i64:64-i128:128-n32:64-S128-Fn32".into(), - arch: arch.target_arch(), + arch: ARCH.target_arch(), options: TargetOptions { features: "+neon,+fp-armv8,+apple-a7".into(), max_atomic_width: Some(128), diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_macabi.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_macabi.rs index 4c008f7985e6f..b2c5b1c4527b8 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_macabi.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_macabi.rs @@ -1,13 +1,16 @@ use crate::spec::base::apple::{mac_catalyst_llvm_target, opts, Arch, TargetAbi}; -use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions}; +use crate::spec::{FramePointer, MaybeLazy, SanitizerSet, Target, TargetOptions}; pub fn target() -> Target { - let arch = Arch::Arm64; - let mut base = opts("ios", arch, TargetAbi::MacCatalyst); + const ARCH: Arch = Arch::Arm64; + const OS: &'static str = "ios"; + const ABI: TargetAbi = TargetAbi::MacCatalyst; + + let mut base = opts(OS, ARCH, ABI); base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::LEAK | SanitizerSet::THREAD; Target { - llvm_target: mac_catalyst_llvm_target(arch).into(), + llvm_target: MaybeLazy::lazy(|| mac_catalyst_llvm_target(ARCH)), metadata: crate::spec::TargetMetadata { description: None, tier: None, @@ -16,7 +19,7 @@ pub fn target() -> Target { }, pointer_width: 64, data_layout: "e-m:o-i64:64-i128:128-n32:64-S128-Fn32".into(), - arch: arch.target_arch(), + arch: ARCH.target_arch(), options: TargetOptions { features: "+neon,+fp-armv8,+apple-a12".into(), max_atomic_width: Some(128), diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_sim.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_sim.rs index 4a63abdf5419f..a444993553d12 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_sim.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_sim.rs @@ -1,9 +1,12 @@ use crate::spec::base::apple::{ios_sim_llvm_target, opts, Arch, TargetAbi}; -use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions}; +use crate::spec::{FramePointer, MaybeLazy, SanitizerSet, Target, TargetOptions}; pub fn target() -> Target { - let arch = Arch::Arm64; - let mut base = opts("ios", arch, TargetAbi::Simulator); + const ARCH: Arch = Arch::Arm64; + const OS: &'static str = "ios"; + const ABI: TargetAbi = TargetAbi::Simulator; + + let mut base = opts(OS, ARCH, ABI); base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::THREAD; Target { @@ -11,7 +14,7 @@ pub fn target() -> Target { // IPHONEOS_DEPLOYMENT_TARGET. // This is required for the simulator target to pick the right // MACH-O commands, so we do too. - llvm_target: ios_sim_llvm_target(arch).into(), + llvm_target: MaybeLazy::lazy(|| ios_sim_llvm_target(ARCH)), metadata: crate::spec::TargetMetadata { description: None, tier: None, @@ -20,7 +23,7 @@ pub fn target() -> Target { }, pointer_width: 64, data_layout: "e-m:o-i64:64-i128:128-n32:64-S128-Fn32".into(), - arch: arch.target_arch(), + arch: ARCH.target_arch(), options: TargetOptions { features: "+neon,+fp-armv8,+apple-a7".into(), max_atomic_width: Some(128), diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos.rs index 3310e6c9e8a41..3434789425727 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos.rs @@ -1,10 +1,13 @@ use crate::spec::base::apple::{opts, tvos_llvm_target, Arch, TargetAbi}; -use crate::spec::{FramePointer, Target, TargetOptions}; +use crate::spec::{FramePointer, MaybeLazy, Target, TargetOptions}; pub fn target() -> Target { - let arch = Arch::Arm64; + const ARCH: Arch = Arch::Arm64; + const OS: &'static str = "tvos"; + const ABI: TargetAbi = TargetAbi::Normal; + Target { - llvm_target: tvos_llvm_target(arch).into(), + llvm_target: MaybeLazy::lazy(|| tvos_llvm_target(ARCH)), metadata: crate::spec::TargetMetadata { description: None, tier: None, @@ -13,12 +16,12 @@ pub fn target() -> Target { }, pointer_width: 64, data_layout: "e-m:o-i64:64-i128:128-n32:64-S128-Fn32".into(), - arch: arch.target_arch(), + arch: ARCH.target_arch(), options: TargetOptions { features: "+neon,+fp-armv8,+apple-a7".into(), max_atomic_width: Some(128), frame_pointer: FramePointer::NonLeaf, - ..opts("tvos", arch, TargetAbi::Normal) + ..opts(OS, ARCH, ABI) }, } } diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos_sim.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos_sim.rs index b901c663afaef..3d71d01785b07 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos_sim.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos_sim.rs @@ -1,10 +1,13 @@ use crate::spec::base::apple::{opts, tvos_sim_llvm_target, Arch, TargetAbi}; -use crate::spec::{FramePointer, Target, TargetOptions}; +use crate::spec::{FramePointer, MaybeLazy, Target, TargetOptions}; pub fn target() -> Target { - let arch = Arch::Arm64; + const ARCH: Arch = Arch::Arm64; + const OS: &'static str = "tvos"; + const ABI: TargetAbi = TargetAbi::Normal; + Target { - llvm_target: tvos_sim_llvm_target(arch).into(), + llvm_target: MaybeLazy::lazy(|| tvos_sim_llvm_target(ARCH)), metadata: crate::spec::TargetMetadata { description: None, tier: None, @@ -13,12 +16,12 @@ pub fn target() -> Target { }, pointer_width: 64, data_layout: "e-m:o-i64:64-i128:128-n32:64-S128-Fn32".into(), - arch: arch.target_arch(), + arch: ARCH.target_arch(), options: TargetOptions { features: "+neon,+fp-armv8,+apple-a7".into(), max_atomic_width: Some(128), frame_pointer: FramePointer::NonLeaf, - ..opts("tvos", arch, TargetAbi::Simulator) + ..opts(OS, ARCH, ABI) }, } } diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos.rs index b0798e5e4f580..0e6590ea4c445 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos.rs @@ -1,13 +1,16 @@ use crate::spec::base::apple::{opts, visionos_llvm_target, Arch, TargetAbi}; -use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions}; +use crate::spec::{FramePointer, MaybeLazy, SanitizerSet, Target, TargetOptions}; pub fn target() -> Target { - let arch = Arch::Arm64; - let mut base = opts("visionos", arch, TargetAbi::Normal); + const OS: &str = "visionos"; + const ABI: TargetAbi = TargetAbi::Normal; + const ARCH: Arch = Arch::Arm64; + + let mut base = opts(OS, ARCH, ABI); base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::THREAD; Target { - llvm_target: visionos_llvm_target(arch).into(), + llvm_target: MaybeLazy::lazy(|| visionos_llvm_target(ARCH)), metadata: crate::spec::TargetMetadata { description: Some("ARM64 Apple visionOS".into()), tier: Some(3), @@ -16,7 +19,7 @@ pub fn target() -> Target { }, pointer_width: 64, data_layout: "e-m:o-i64:64-i128:128-n32:64-S128-Fn32".into(), - arch: arch.target_arch(), + arch: ARCH.target_arch(), options: TargetOptions { features: "+neon,+fp-armv8,+apple-a16".into(), max_atomic_width: Some(128), diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos_sim.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos_sim.rs index 7b2d2b6a8e442..152a2487cec04 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos_sim.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos_sim.rs @@ -1,13 +1,16 @@ use crate::spec::base::apple::{opts, visionos_sim_llvm_target, Arch, TargetAbi}; -use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions}; +use crate::spec::{FramePointer, MaybeLazy, SanitizerSet, Target, TargetOptions}; pub fn target() -> Target { - let arch = Arch::Arm64; - let mut base = opts("visionos", arch, TargetAbi::Simulator); + const OS: &str = "visionos"; + const ABI: TargetAbi = TargetAbi::Simulator; + const ARCH: Arch = Arch::Arm64; + + let mut base = opts(OS, ARCH, ABI); base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::THREAD; Target { - llvm_target: visionos_sim_llvm_target(arch).into(), + llvm_target: MaybeLazy::lazy(|| visionos_sim_llvm_target(ARCH)), metadata: crate::spec::TargetMetadata { description: Some("ARM64 Apple visionOS simulator".into()), tier: Some(3), @@ -16,7 +19,7 @@ pub fn target() -> Target { }, pointer_width: 64, data_layout: "e-m:o-i64:64-i128:128-n32:64-S128-Fn32".into(), - arch: arch.target_arch(), + arch: ARCH.target_arch(), options: TargetOptions { features: "+neon,+fp-armv8,+apple-a16".into(), max_atomic_width: Some(128), diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos.rs index a00a97a133f60..ae5920b0ea819 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos.rs @@ -2,7 +2,11 @@ use crate::spec::base::apple::{opts, Arch, TargetAbi}; use crate::spec::{Target, TargetOptions}; pub fn target() -> Target { - let base = opts("watchos", Arch::Arm64, TargetAbi::Normal); + const ARCH: Arch = Arch::Arm64; + const OS: &'static str = "watchos"; + const ABI: TargetAbi = TargetAbi::Normal; + + let base = opts(OS, ARCH, ABI); Target { llvm_target: "aarch64-apple-watchos".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos_sim.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos_sim.rs index e2f80b7b7a888..17e0ea966feb9 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos_sim.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos_sim.rs @@ -1,14 +1,17 @@ use crate::spec::base::apple::{opts, watchos_sim_llvm_target, Arch, TargetAbi}; -use crate::spec::{FramePointer, Target, TargetOptions}; +use crate::spec::{FramePointer, MaybeLazy, Target, TargetOptions}; pub fn target() -> Target { - let arch = Arch::Arm64; + const ARCH: Arch = Arch::Arm64; + const OS: &'static str = "watchos"; + const ABI: TargetAbi = TargetAbi::Simulator; + Target { // Clang automatically chooses a more specific target based on // WATCHOS_DEPLOYMENT_TARGET. // This is required for the simulator target to pick the right // MACH-O commands, so we do too. - llvm_target: watchos_sim_llvm_target(arch).into(), + llvm_target: MaybeLazy::lazy(|| watchos_sim_llvm_target(ARCH)), metadata: crate::spec::TargetMetadata { description: None, tier: None, @@ -17,12 +20,12 @@ pub fn target() -> Target { }, pointer_width: 64, data_layout: "e-m:o-i64:64-i128:128-n32:64-S128-Fn32".into(), - arch: arch.target_arch(), + arch: ARCH.target_arch(), options: TargetOptions { features: "+neon,+fp-armv8,+apple-a7".into(), max_atomic_width: Some(128), frame_pointer: FramePointer::NonLeaf, - ..opts("watchos", arch, TargetAbi::Simulator) + ..opts(OS, ARCH, ABI) }, } } diff --git a/compiler/rustc_target/src/spec/targets/arm64_32_apple_watchos.rs b/compiler/rustc_target/src/spec/targets/arm64_32_apple_watchos.rs index 3ca8c9969c2d5..682ddc5c2c67d 100644 --- a/compiler/rustc_target/src/spec/targets/arm64_32_apple_watchos.rs +++ b/compiler/rustc_target/src/spec/targets/arm64_32_apple_watchos.rs @@ -1,11 +1,15 @@ use crate::spec::base::apple::{opts, watchos_llvm_target, Arch, TargetAbi}; -use crate::spec::{Target, TargetOptions}; +use crate::spec::{MaybeLazy, Target, TargetOptions}; pub fn target() -> Target { - let arch = Arch::Arm64_32; - let base = opts("watchos", arch, TargetAbi::Normal); + const OS: &str = "watchos"; + const ARCH: Arch = Arch::Arm64_32; + const ABI: TargetAbi = TargetAbi::Normal; + + let base = opts(OS, ARCH, ABI); + Target { - llvm_target: watchos_llvm_target(arch).into(), + llvm_target: MaybeLazy::lazy(|| watchos_llvm_target(ARCH)), metadata: crate::spec::TargetMetadata { description: None, tier: None, diff --git a/compiler/rustc_target/src/spec/targets/arm64e_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/arm64e_apple_darwin.rs index 90be518638e93..c0795dcba6be6 100644 --- a/compiler/rustc_target/src/spec/targets/arm64e_apple_darwin.rs +++ b/compiler/rustc_target/src/spec/targets/arm64e_apple_darwin.rs @@ -1,9 +1,12 @@ use crate::spec::base::apple::{macos_llvm_target, opts, Arch, TargetAbi}; -use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions}; +use crate::spec::{FramePointer, MaybeLazy, SanitizerSet, Target, TargetOptions}; pub fn target() -> Target { - let arch = Arch::Arm64e; - let mut base = opts("macos", arch, TargetAbi::Normal); + const ARCH: Arch = Arch::Arm64e; + const OS: &'static str = "macos"; + const ABI: TargetAbi = TargetAbi::Normal; + + let mut base = opts(OS, ARCH, ABI); base.cpu = "apple-m1".into(); base.max_atomic_width = Some(128); @@ -14,7 +17,7 @@ pub fn target() -> Target { // Clang automatically chooses a more specific target based on // MACOSX_DEPLOYMENT_TARGET. To enable cross-language LTO to work // correctly, we do too. - llvm_target: macos_llvm_target(arch).into(), + llvm_target: MaybeLazy::lazy(|| macos_llvm_target(ARCH)), metadata: crate::spec::TargetMetadata { description: None, tier: None, @@ -23,7 +26,7 @@ pub fn target() -> Target { }, pointer_width: 64, data_layout: "e-m:o-i64:64-i128:128-n32:64-S128-Fn32".into(), - arch: arch.target_arch(), + arch: ARCH.target_arch(), options: TargetOptions { mcount: "\u{1}mcount".into(), frame_pointer: FramePointer::NonLeaf, diff --git a/compiler/rustc_target/src/spec/targets/arm64e_apple_ios.rs b/compiler/rustc_target/src/spec/targets/arm64e_apple_ios.rs index 56470d29eae00..42f74d53c305d 100644 --- a/compiler/rustc_target/src/spec/targets/arm64e_apple_ios.rs +++ b/compiler/rustc_target/src/spec/targets/arm64e_apple_ios.rs @@ -1,9 +1,12 @@ use crate::spec::base::apple::{ios_llvm_target, opts, Arch, TargetAbi}; -use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions}; +use crate::spec::{FramePointer, MaybeLazy, SanitizerSet, Target, TargetOptions}; pub fn target() -> Target { - let arch = Arch::Arm64e; - let mut base = opts("ios", arch, TargetAbi::Normal); + const ARCH: Arch = Arch::Arm64e; + const OS: &'static str = "ios"; + const ABI: TargetAbi = TargetAbi::Normal; + + let mut base = opts(OS, ARCH, ABI); base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::THREAD; Target { @@ -11,7 +14,7 @@ pub fn target() -> Target { // IPHONEOS_DEPLOYMENT_TARGET. // This is required for the target to pick the right // MACH-O commands, so we do too. - llvm_target: ios_llvm_target(arch).into(), + llvm_target: MaybeLazy::lazy(|| ios_llvm_target(ARCH)), metadata: crate::spec::TargetMetadata { description: None, tier: None, @@ -20,7 +23,7 @@ pub fn target() -> Target { }, pointer_width: 64, data_layout: "e-m:o-i64:64-i128:128-n32:64-S128-Fn32".into(), - arch: arch.target_arch(), + arch: ARCH.target_arch(), options: TargetOptions { features: "+neon,+fp-armv8,+apple-a12,+v8.3a,+pauth".into(), max_atomic_width: Some(128), diff --git a/compiler/rustc_target/src/spec/targets/armv7k_apple_watchos.rs b/compiler/rustc_target/src/spec/targets/armv7k_apple_watchos.rs index 5c675c22ef511..0dbd06e587a9a 100644 --- a/compiler/rustc_target/src/spec/targets/armv7k_apple_watchos.rs +++ b/compiler/rustc_target/src/spec/targets/armv7k_apple_watchos.rs @@ -2,7 +2,10 @@ use crate::spec::base::apple::{opts, Arch, TargetAbi}; use crate::spec::{Target, TargetOptions}; pub fn target() -> Target { - let arch = Arch::Armv7k; + const ARCH: Arch = Arch::Armv7k; + const OS: &'static str = "watchos"; + const ABI: TargetAbi = TargetAbi::Normal; + Target { llvm_target: "armv7k-apple-watchos".into(), metadata: crate::spec::TargetMetadata { @@ -13,13 +16,13 @@ pub fn target() -> Target { }, pointer_width: 32, data_layout: "e-m:o-p:32:32-Fi8-i64:64-a:0:32-n32-S128".into(), - arch: arch.target_arch(), + arch: ARCH.target_arch(), options: TargetOptions { features: "+v7,+vfp4,+neon".into(), max_atomic_width: Some(64), dynamic_linking: false, position_independent_executables: true, - ..opts("watchos", arch, TargetAbi::Normal) + ..opts(OS, ARCH, ABI) }, } } diff --git a/compiler/rustc_target/src/spec/targets/armv7s_apple_ios.rs b/compiler/rustc_target/src/spec/targets/armv7s_apple_ios.rs index 4dd475e3a82da..f5693647040ca 100644 --- a/compiler/rustc_target/src/spec/targets/armv7s_apple_ios.rs +++ b/compiler/rustc_target/src/spec/targets/armv7s_apple_ios.rs @@ -1,10 +1,13 @@ use crate::spec::base::apple::{ios_llvm_target, opts, Arch, TargetAbi}; -use crate::spec::{Target, TargetOptions}; +use crate::spec::{MaybeLazy, Target, TargetOptions}; pub fn target() -> Target { - let arch = Arch::Armv7s; + const ARCH: Arch = Arch::Armv7s; + const OS: &'static str = "ios"; + const ABI: TargetAbi = TargetAbi::Normal; + Target { - llvm_target: ios_llvm_target(arch).into(), + llvm_target: MaybeLazy::lazy(|| ios_llvm_target(ARCH)), metadata: crate::spec::TargetMetadata { description: None, tier: None, @@ -13,11 +16,11 @@ pub fn target() -> Target { }, pointer_width: 32, data_layout: "e-m:o-p:32:32-Fi8-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32".into(), - arch: arch.target_arch(), + arch: ARCH.target_arch(), options: TargetOptions { features: "+v7,+vfp4,+neon".into(), max_atomic_width: Some(64), - ..opts("ios", arch, TargetAbi::Normal) + ..opts(OS, ARCH, ABI) }, } } diff --git a/compiler/rustc_target/src/spec/targets/i386_apple_ios.rs b/compiler/rustc_target/src/spec/targets/i386_apple_ios.rs index c03a0974bc1cb..747c881524621 100644 --- a/compiler/rustc_target/src/spec/targets/i386_apple_ios.rs +++ b/compiler/rustc_target/src/spec/targets/i386_apple_ios.rs @@ -1,17 +1,19 @@ use crate::spec::base::apple::{ios_sim_llvm_target, opts, Arch, TargetAbi}; -use crate::spec::{Target, TargetOptions}; +use crate::spec::{MaybeLazy, Target, TargetOptions}; pub fn target() -> Target { - let arch = Arch::I386; + const ARCH: Arch = Arch::I386; + const OS: &'static str = "ios"; // i386-apple-ios is a simulator target, even though it isn't declared // that way in the target name like the other ones... - let abi = TargetAbi::Simulator; + const ABI: TargetAbi = TargetAbi::Simulator; + Target { // Clang automatically chooses a more specific target based on // IPHONEOS_DEPLOYMENT_TARGET. // This is required for the target to pick the right // MACH-O commands, so we do too. - llvm_target: ios_sim_llvm_target(arch).into(), + llvm_target: MaybeLazy::lazy(|| ios_sim_llvm_target(ARCH)), metadata: crate::spec::TargetMetadata { description: None, tier: None, @@ -22,7 +24,7 @@ pub fn target() -> Target { data_layout: "e-m:o-p:32:32-p270:32:32-p271:32:32-p272:64:64-\ i128:128-f64:32:64-f80:128-n8:16:32-S128" .into(), - arch: arch.target_arch(), - options: TargetOptions { max_atomic_width: Some(64), ..opts("ios", arch, abi) }, + arch: ARCH.target_arch(), + options: TargetOptions { max_atomic_width: Some(64), ..opts(OS, ARCH, ABI) }, } } diff --git a/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs index aea6a1ac4ecea..a477cb622efc7 100644 --- a/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs +++ b/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs @@ -1,10 +1,13 @@ use crate::spec::base::apple::{macos_llvm_target, opts, Arch, TargetAbi}; -use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, Target, TargetOptions}; +use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, MaybeLazy, Target, TargetOptions}; pub fn target() -> Target { // ld64 only understands i386 and not i686 - let arch = Arch::I386; - let mut base = opts("macos", arch, TargetAbi::Normal); + const ARCH: Arch = Arch::I386; + const OS: &'static str = "macos"; + const ABI: TargetAbi = TargetAbi::Normal; + + let mut base = opts(OS, ARCH, ABI); base.max_atomic_width = Some(64); base.add_pre_link_args(LinkerFlavor::Darwin(Cc::Yes, Lld::No), &["-m32"]); base.frame_pointer = FramePointer::Always; @@ -15,7 +18,7 @@ pub fn target() -> Target { // correctly, we do too. // // While ld64 doesn't understand i686, LLVM does. - llvm_target: macos_llvm_target(Arch::I686).into(), + llvm_target: MaybeLazy::lazy(|| macos_llvm_target(Arch::I686)), metadata: crate::spec::TargetMetadata { description: None, tier: None, @@ -26,7 +29,7 @@ pub fn target() -> Target { data_layout: "e-m:o-p:32:32-p270:32:32-p271:32:32-p272:64:64-\ i128:128-f64:32:64-f80:128-n8:16:32-S128" .into(), - arch: arch.target_arch(), + arch: ARCH.target_arch(), options: TargetOptions { mcount: "\u{1}mcount".into(), ..base }, } } diff --git a/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs index 21acd750df2dc..6ca5514b11cd0 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs @@ -1,10 +1,13 @@ use crate::spec::base::apple::{macos_llvm_target, opts, Arch, TargetAbi}; -use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, SanitizerSet}; +use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, MaybeLazy, SanitizerSet}; use crate::spec::{Target, TargetOptions}; pub fn target() -> Target { - let arch = Arch::X86_64; - let mut base = opts("macos", arch, TargetAbi::Normal); + const ARCH: Arch = Arch::X86_64; + const OS: &'static str = "macos"; + const ABI: TargetAbi = TargetAbi::Normal; + + let mut base = opts(OS, ARCH, ABI); base.max_atomic_width = Some(128); // penryn+ supports cmpxchg16b base.frame_pointer = FramePointer::Always; base.add_pre_link_args(LinkerFlavor::Darwin(Cc::Yes, Lld::No), &["-m64"]); @@ -15,7 +18,7 @@ pub fn target() -> Target { // Clang automatically chooses a more specific target based on // MACOSX_DEPLOYMENT_TARGET. To enable cross-language LTO to work // correctly, we do too. - llvm_target: macos_llvm_target(arch).into(), + llvm_target: MaybeLazy::lazy(|| macos_llvm_target(ARCH)), metadata: crate::spec::TargetMetadata { description: None, tier: None, @@ -25,7 +28,7 @@ pub fn target() -> Target { pointer_width: 64, data_layout: "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(), - arch: arch.target_arch(), + arch: ARCH.target_arch(), options: TargetOptions { mcount: "\u{1}mcount".into(), ..base }, } } diff --git a/compiler/rustc_target/src/spec/targets/x86_64_apple_ios.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_ios.rs index ec61b7967646e..e59dbe0c6c761 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_apple_ios.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_ios.rs @@ -1,15 +1,18 @@ use crate::spec::base::apple::{ios_sim_llvm_target, opts, Arch, TargetAbi}; -use crate::spec::{SanitizerSet, Target, TargetOptions}; +use crate::spec::{MaybeLazy, SanitizerSet, Target, TargetOptions}; pub fn target() -> Target { - let arch = Arch::X86_64; + const ARCH: Arch = Arch::X86_64; + const OS: &'static str = "ios"; + const ABI: TargetAbi = TargetAbi::Simulator; + // x86_64-apple-ios is a simulator target, even though it isn't declared // that way in the target name like the other ones... - let mut base = opts("ios", arch, TargetAbi::Simulator); + let mut base = opts(OS, ARCH, ABI); base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::THREAD; Target { - llvm_target: ios_sim_llvm_target(arch).into(), + llvm_target: MaybeLazy::lazy(|| ios_sim_llvm_target(ARCH)), metadata: crate::spec::TargetMetadata { description: None, tier: None, @@ -19,7 +22,7 @@ pub fn target() -> Target { pointer_width: 64, data_layout: "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(), - arch: arch.target_arch(), + arch: ARCH.target_arch(), options: TargetOptions { max_atomic_width: Some(128), ..base }, } } diff --git a/compiler/rustc_target/src/spec/targets/x86_64_apple_ios_macabi.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_ios_macabi.rs index bd967ee972b32..04d0bc7775200 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_apple_ios_macabi.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_ios_macabi.rs @@ -1,13 +1,16 @@ use crate::spec::base::apple::{mac_catalyst_llvm_target, opts, Arch, TargetAbi}; -use crate::spec::{SanitizerSet, Target, TargetOptions}; +use crate::spec::{MaybeLazy, SanitizerSet, Target, TargetOptions}; pub fn target() -> Target { - let arch = Arch::X86_64; - let mut base = opts("ios", arch, TargetAbi::MacCatalyst); + const ARCH: Arch = Arch::X86_64; + const OS: &'static str = "ios"; + const ABI: TargetAbi = TargetAbi::MacCatalyst; + + let mut base = opts(OS, ARCH, ABI); base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::LEAK | SanitizerSet::THREAD; Target { - llvm_target: mac_catalyst_llvm_target(arch).into(), + llvm_target: MaybeLazy::lazy(|| mac_catalyst_llvm_target(ARCH)), metadata: crate::spec::TargetMetadata { description: None, tier: None, @@ -17,7 +20,7 @@ pub fn target() -> Target { pointer_width: 64, data_layout: "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(), - arch: arch.target_arch(), + arch: ARCH.target_arch(), options: TargetOptions { max_atomic_width: Some(128), ..base }, } } diff --git a/compiler/rustc_target/src/spec/targets/x86_64_apple_tvos.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_tvos.rs index 55b2e1afcd392..d6495f83c8ff9 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_apple_tvos.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_tvos.rs @@ -1,13 +1,16 @@ use crate::spec::base::apple::{opts, tvos_sim_llvm_target, Arch, TargetAbi}; -use crate::spec::{Target, TargetOptions}; +use crate::spec::{MaybeLazy, Target, TargetOptions}; pub fn target() -> Target { - let arch = Arch::X86_64; // x86_64-apple-tvos is a simulator target, even though it isn't declared // that way in the target name like the other ones... - let abi = TargetAbi::Simulator; + + const ARCH: Arch = Arch::X86_64; + const OS: &'static str = "tvos"; + const ABI: TargetAbi = TargetAbi::Simulator; + Target { - llvm_target: tvos_sim_llvm_target(arch).into(), + llvm_target: MaybeLazy::lazy(|| tvos_sim_llvm_target(ARCH)), metadata: crate::spec::TargetMetadata { description: None, tier: None, @@ -17,7 +20,7 @@ pub fn target() -> Target { pointer_width: 64, data_layout: "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(), - arch: arch.target_arch(), - options: TargetOptions { max_atomic_width: Some(128), ..opts("tvos", arch, abi) }, + arch: ARCH.target_arch(), + options: TargetOptions { max_atomic_width: Some(128), ..opts(OS, ARCH, ABI) }, } } diff --git a/compiler/rustc_target/src/spec/targets/x86_64_apple_watchos_sim.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_watchos_sim.rs index a783eff15b261..a00e94a1a713c 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_apple_watchos_sim.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_watchos_sim.rs @@ -1,10 +1,13 @@ use crate::spec::base::apple::{opts, watchos_sim_llvm_target, Arch, TargetAbi}; -use crate::spec::{Target, TargetOptions}; +use crate::spec::{MaybeLazy, Target, TargetOptions}; pub fn target() -> Target { - let arch = Arch::X86_64; + const ARCH: Arch = Arch::X86_64; + const OS: &'static str = "watchos"; + const ABI: TargetAbi = TargetAbi::Simulator; + Target { - llvm_target: watchos_sim_llvm_target(arch).into(), + llvm_target: MaybeLazy::lazy(|| watchos_sim_llvm_target(ARCH)), metadata: crate::spec::TargetMetadata { description: None, tier: None, @@ -14,10 +17,7 @@ pub fn target() -> Target { pointer_width: 64, data_layout: "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(), - arch: arch.target_arch(), - options: TargetOptions { - max_atomic_width: Some(128), - ..opts("watchos", arch, TargetAbi::Simulator) - }, + arch: ARCH.target_arch(), + options: TargetOptions { max_atomic_width: Some(128), ..opts(OS, ARCH, ABI) }, } } diff --git a/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs index fe6cbca32c748..ff2b236db3722 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs @@ -1,10 +1,13 @@ use crate::spec::base::apple::{macos_llvm_target, opts, Arch, TargetAbi}; -use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, SanitizerSet}; +use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, MaybeLazy, SanitizerSet}; use crate::spec::{Target, TargetOptions}; pub fn target() -> Target { - let arch = Arch::X86_64h; - let mut base = opts("macos", arch, TargetAbi::Normal); + const ARCH: Arch = Arch::X86_64h; + const OS: &'static str = "macos"; + const ABI: TargetAbi = TargetAbi::Normal; + + let mut base = opts(OS, ARCH, ABI); base.max_atomic_width = Some(128); base.frame_pointer = FramePointer::Always; base.add_pre_link_args(LinkerFlavor::Darwin(Cc::Yes, Lld::No), &["-m64"]); @@ -33,7 +36,7 @@ pub fn target() -> Target { // Clang automatically chooses a more specific target based on // MACOSX_DEPLOYMENT_TARGET. To enable cross-language LTO to work // correctly, we do too. - llvm_target: macos_llvm_target(arch).into(), + llvm_target: MaybeLazy::lazy(|| macos_llvm_target(ARCH)), metadata: crate::spec::TargetMetadata { description: None, tier: None, @@ -43,7 +46,7 @@ pub fn target() -> Target { pointer_width: 64, data_layout: "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(), - arch: arch.target_arch(), + arch: ARCH.target_arch(), options: TargetOptions { mcount: "\u{1}mcount".into(), ..base }, } }