Skip to content

Commit 10163ec

Browse files
committed
Auto merge of rust-lang#126702 - Urgau:lazy-targets-llvm_target, r=<try>
Lazify `Target::llvm_target` field This PR lazify the `Target::llvm_target` field by introducing `MaybeLazy`, a 3-way lazy container (borrowed, owned and lazied state). Split from rust-lang#122703 r? `@petrochenkov`
2 parents 894f7a4 + b997b6a commit 10163ec

26 files changed

+330
-115
lines changed

compiler/rustc_target/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,13 @@
1212
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
1313
#![doc(rust_logo)]
1414
#![feature(assert_matches)]
15+
#![feature(fn_traits)]
1516
#![feature(iter_intersperse)]
1617
#![feature(let_chains)]
1718
#![feature(min_exhaustive_patterns)]
1819
#![feature(rustc_attrs)]
1920
#![feature(rustdoc_internals)]
21+
#![feature(unboxed_closures)]
2022
// tidy-alphabetical-end
2123

2224
use std::path::{Path, PathBuf};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
//! A custom LazyLock+Cow suitable for holding borrowed, owned or lazy data.
2+
3+
use std::borrow::{Borrow, Cow};
4+
use std::fmt::{Debug, Display};
5+
use std::ops::Deref;
6+
use std::sync::LazyLock;
7+
8+
enum MaybeLazyInner<T: 'static + ToOwned + ?Sized, F> {
9+
Lazy(LazyLock<T::Owned, F>),
10+
Cow(Cow<'static, T>),
11+
}
12+
13+
/// A custom LazyLock+Cow suitable for holding borrowed, owned or lazy data.
14+
///
15+
/// Technically this structure has 3 states: borrowed, owned and lazy
16+
/// They can all be constructed from the [`MaybeLazy::borrowed`], [`MaybeLazy::owned`] and
17+
/// [`MaybeLazy::lazy`] methods.
18+
#[repr(transparent)]
19+
pub struct MaybeLazy<T: 'static + ToOwned + ?Sized, F = fn() -> <T as ToOwned>::Owned> {
20+
// Inner state.
21+
//
22+
// Not to be inlined since we may want in the future to
23+
// make this struct usable to statics and we might need to
24+
// workaround const-eval limitation (particulary around drop).
25+
inner: MaybeLazyInner<T, F>,
26+
}
27+
28+
impl<T: 'static + ?Sized + ToOwned, F: FnOnce() -> T::Owned> MaybeLazy<T, F> {
29+
/// Create a [`MaybeLazy`] from an borrowed `T`.
30+
#[inline]
31+
pub const fn borrowed(a: &'static T) -> Self {
32+
MaybeLazy { inner: MaybeLazyInner::Cow(Cow::Borrowed(a)) }
33+
}
34+
35+
/// Create a [`MaybeLazy`] from an borrowed `T`.
36+
#[inline]
37+
pub const fn owned(a: T::Owned) -> Self {
38+
MaybeLazy { inner: MaybeLazyInner::Cow(Cow::Owned(a)) }
39+
}
40+
41+
/// Create a [`MaybeLazy`] from a function-able `F`.
42+
#[inline]
43+
pub const fn lazied(f: F) -> Self {
44+
MaybeLazy { inner: MaybeLazyInner::Lazy(LazyLock::new(f)) }
45+
}
46+
}
47+
48+
impl<T: 'static + ?Sized + ToOwned> MaybeLazy<T> {
49+
/// Create a [`MaybeLazy`] from a function pointer.
50+
#[inline]
51+
pub const fn lazy(a: fn() -> T::Owned) -> Self {
52+
Self::lazied(a)
53+
}
54+
}
55+
56+
impl<T: 'static + ?Sized + ToOwned<Owned: Clone>, F: FnOnce() -> T::Owned> Clone
57+
for MaybeLazy<T, F>
58+
{
59+
#[inline]
60+
fn clone(&self) -> Self {
61+
MaybeLazy {
62+
inner: MaybeLazyInner::Cow(match &self.inner {
63+
MaybeLazyInner::Lazy(f) => Cow::Owned((*f).to_owned()),
64+
MaybeLazyInner::Cow(c) => c.clone(),
65+
}),
66+
}
67+
}
68+
}
69+
70+
impl<T: 'static + ?Sized + ToOwned<Owned: Default>, F: FnOnce() -> T::Owned> Default
71+
for MaybeLazy<T, F>
72+
{
73+
#[inline]
74+
fn default() -> MaybeLazy<T, F> {
75+
MaybeLazy::owned(T::Owned::default())
76+
}
77+
}
78+
79+
// `Debug`, `Display` and other traits below are implemented in terms of this `Deref`
80+
impl<T: 'static + ?Sized + ToOwned<Owned: Borrow<T>>, F: FnOnce() -> T::Owned> Deref
81+
for MaybeLazy<T, F>
82+
{
83+
type Target = T;
84+
85+
#[inline]
86+
fn deref(&self) -> &T {
87+
match &self.inner {
88+
MaybeLazyInner::Lazy(f) => (&**f).borrow(),
89+
MaybeLazyInner::Cow(c) => &*c,
90+
}
91+
}
92+
}
93+
94+
impl<T: 'static + ?Sized + ToOwned<Owned: Debug> + Debug, F: FnOnce() -> T::Owned> Debug
95+
for MaybeLazy<T, F>
96+
{
97+
#[inline]
98+
fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
99+
Debug::fmt(&**self, fmt)
100+
}
101+
}
102+
103+
impl<T: 'static + ?Sized + ToOwned<Owned: Display> + Display, F: FnOnce() -> T::Owned> Display
104+
for MaybeLazy<T, F>
105+
{
106+
#[inline]
107+
fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
108+
Display::fmt(&**self, fmt)
109+
}
110+
}
111+
112+
impl<T: 'static + ?Sized + ToOwned, F: FnOnce() -> T::Owned> AsRef<T> for MaybeLazy<T, F> {
113+
#[inline]
114+
fn as_ref(&self) -> &T {
115+
&**self
116+
}
117+
}
118+
119+
impl<
120+
T1: ?Sized + PartialEq<T2> + ToOwned,
121+
T2: ?Sized + ToOwned,
122+
F1: FnOnce() -> T1::Owned,
123+
F2: FnOnce() -> T2::Owned,
124+
> PartialEq<MaybeLazy<T2, F2>> for MaybeLazy<T1, F1>
125+
{
126+
#[inline]
127+
fn eq(&self, other: &MaybeLazy<T2, F2>) -> bool {
128+
PartialEq::eq(&**self, &**other)
129+
}
130+
}
131+
132+
impl<F: FnOnce() -> String> PartialEq<&str> for MaybeLazy<str, F> {
133+
#[inline]
134+
fn eq(&self, other: &&str) -> bool {
135+
&**self == *other
136+
}
137+
}
138+
139+
impl<F: FnOnce() -> String> From<&'static str> for MaybeLazy<str, F> {
140+
#[inline]
141+
fn from(s: &'static str) -> MaybeLazy<str, F> {
142+
MaybeLazy::borrowed(s)
143+
}
144+
}

compiler/rustc_target/src/spec/mod.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ use crate::abi::{Endian, Integer, Size, TargetDataLayout, TargetDataLayoutErrors
3939
use crate::json::{Json, ToJson};
4040
use crate::spec::abi::Abi;
4141
use crate::spec::crt_objects::CrtObjects;
42+
use crate::spec::maybe_lazy::MaybeLazy;
4243
use rustc_fs_util::try_canonicalize;
4344
use rustc_macros::{Decodable, Encodable, HashStable_Generic};
4445
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
@@ -55,6 +56,7 @@ use tracing::debug;
5556

5657
pub mod abi;
5758
pub mod crt_objects;
59+
pub mod maybe_lazy;
5860

5961
mod base;
6062
pub use base::apple::deployment_target as current_apple_deployment_target;
@@ -1879,7 +1881,7 @@ impl TargetWarnings {
18791881
#[derive(PartialEq, Clone, Debug)]
18801882
pub struct Target {
18811883
/// Target triple to pass to LLVM.
1882-
pub llvm_target: StaticCow<str>,
1884+
pub llvm_target: MaybeLazy<str>,
18831885
/// Metadata about a target, for example the description or tier.
18841886
/// Used for generating target documentation.
18851887
pub metadata: TargetMetadata,
@@ -2734,7 +2736,7 @@ impl Target {
27342736
};
27352737

27362738
let mut base = Target {
2737-
llvm_target: get_req_field("llvm-target")?.into(),
2739+
llvm_target: MaybeLazy::owned(get_req_field("llvm-target")?),
27382740
metadata: Default::default(),
27392741
pointer_width: get_req_field("target-pointer-width")?
27402742
.parse::<u32>()

compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs

+8-5
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
use crate::spec::base::apple::{macos_llvm_target, opts, Arch, TargetAbi};
2-
use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions};
2+
use crate::spec::{FramePointer, MaybeLazy, SanitizerSet, Target, TargetOptions};
33

44
pub fn target() -> Target {
5-
let arch = Arch::Arm64;
6-
let mut base = opts("macos", arch, TargetAbi::Normal);
5+
const ARCH: Arch = Arch::Arm64;
6+
const OS: &'static str = "macos";
7+
const ABI: TargetAbi = TargetAbi::Normal;
8+
9+
let mut base = opts(OS, ARCH, ABI);
710
base.cpu = "apple-m1".into();
811
base.max_atomic_width = Some(128);
912

@@ -14,7 +17,7 @@ pub fn target() -> Target {
1417
// Clang automatically chooses a more specific target based on
1518
// MACOSX_DEPLOYMENT_TARGET. To enable cross-language LTO to work
1619
// correctly, we do too.
17-
llvm_target: macos_llvm_target(arch).into(),
20+
llvm_target: MaybeLazy::lazy(|| macos_llvm_target(ARCH)),
1821
metadata: crate::spec::TargetMetadata {
1922
description: None,
2023
tier: None,
@@ -23,7 +26,7 @@ pub fn target() -> Target {
2326
},
2427
pointer_width: 64,
2528
data_layout: "e-m:o-i64:64-i128:128-n32:64-S128-Fn32".into(),
26-
arch: arch.target_arch(),
29+
arch: ARCH.target_arch(),
2730
options: TargetOptions {
2831
mcount: "\u{1}mcount".into(),
2932
frame_pointer: FramePointer::NonLeaf,

compiler/rustc_target/src/spec/targets/aarch64_apple_ios.rs

+8-5
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,20 @@
11
use crate::spec::base::apple::{ios_llvm_target, opts, Arch, TargetAbi};
2-
use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions};
2+
use crate::spec::{FramePointer, MaybeLazy, SanitizerSet, Target, TargetOptions};
33

44
pub fn target() -> Target {
5-
let arch = Arch::Arm64;
6-
let mut base = opts("ios", arch, TargetAbi::Normal);
5+
const ARCH: Arch = Arch::Arm64;
6+
const OS: &'static str = "ios";
7+
const ABI: TargetAbi = TargetAbi::Normal;
8+
9+
let mut base = opts(OS, ARCH, ABI);
710
base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::THREAD;
811

912
Target {
1013
// Clang automatically chooses a more specific target based on
1114
// IPHONEOS_DEPLOYMENT_TARGET.
1215
// This is required for the target to pick the right
1316
// MACH-O commands, so we do too.
14-
llvm_target: ios_llvm_target(arch).into(),
17+
llvm_target: MaybeLazy::lazy(|| ios_llvm_target(ARCH)),
1518
metadata: crate::spec::TargetMetadata {
1619
description: None,
1720
tier: None,
@@ -20,7 +23,7 @@ pub fn target() -> Target {
2023
},
2124
pointer_width: 64,
2225
data_layout: "e-m:o-i64:64-i128:128-n32:64-S128-Fn32".into(),
23-
arch: arch.target_arch(),
26+
arch: ARCH.target_arch(),
2427
options: TargetOptions {
2528
features: "+neon,+fp-armv8,+apple-a7".into(),
2629
max_atomic_width: Some(128),

compiler/rustc_target/src/spec/targets/aarch64_apple_ios_macabi.rs

+8-5
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
use crate::spec::base::apple::{mac_catalyst_llvm_target, opts, Arch, TargetAbi};
2-
use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions};
2+
use crate::spec::{FramePointer, MaybeLazy, SanitizerSet, Target, TargetOptions};
33

44
pub fn target() -> Target {
5-
let arch = Arch::Arm64;
6-
let mut base = opts("ios", arch, TargetAbi::MacCatalyst);
5+
const ARCH: Arch = Arch::Arm64;
6+
const OS: &'static str = "ios";
7+
const ABI: TargetAbi = TargetAbi::MacCatalyst;
8+
9+
let mut base = opts(OS, ARCH, ABI);
710
base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::LEAK | SanitizerSet::THREAD;
811

912
Target {
10-
llvm_target: mac_catalyst_llvm_target(arch).into(),
13+
llvm_target: MaybeLazy::lazy(|| mac_catalyst_llvm_target(ARCH)),
1114
metadata: crate::spec::TargetMetadata {
1215
description: None,
1316
tier: None,
@@ -16,7 +19,7 @@ pub fn target() -> Target {
1619
},
1720
pointer_width: 64,
1821
data_layout: "e-m:o-i64:64-i128:128-n32:64-S128-Fn32".into(),
19-
arch: arch.target_arch(),
22+
arch: ARCH.target_arch(),
2023
options: TargetOptions {
2124
features: "+neon,+fp-armv8,+apple-a12".into(),
2225
max_atomic_width: Some(128),

compiler/rustc_target/src/spec/targets/aarch64_apple_ios_sim.rs

+8-5
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,20 @@
11
use crate::spec::base::apple::{ios_sim_llvm_target, opts, Arch, TargetAbi};
2-
use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions};
2+
use crate::spec::{FramePointer, MaybeLazy, SanitizerSet, Target, TargetOptions};
33

44
pub fn target() -> Target {
5-
let arch = Arch::Arm64;
6-
let mut base = opts("ios", arch, TargetAbi::Simulator);
5+
const ARCH: Arch = Arch::Arm64;
6+
const OS: &'static str = "ios";
7+
const ABI: TargetAbi = TargetAbi::Simulator;
8+
9+
let mut base = opts(OS, ARCH, ABI);
710
base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::THREAD;
811

912
Target {
1013
// Clang automatically chooses a more specific target based on
1114
// IPHONEOS_DEPLOYMENT_TARGET.
1215
// This is required for the simulator target to pick the right
1316
// MACH-O commands, so we do too.
14-
llvm_target: ios_sim_llvm_target(arch).into(),
17+
llvm_target: MaybeLazy::lazy(|| ios_sim_llvm_target(ARCH)),
1518
metadata: crate::spec::TargetMetadata {
1619
description: None,
1720
tier: None,
@@ -20,7 +23,7 @@ pub fn target() -> Target {
2023
},
2124
pointer_width: 64,
2225
data_layout: "e-m:o-i64:64-i128:128-n32:64-S128-Fn32".into(),
23-
arch: arch.target_arch(),
26+
arch: ARCH.target_arch(),
2427
options: TargetOptions {
2528
features: "+neon,+fp-armv8,+apple-a7".into(),
2629
max_atomic_width: Some(128),
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
use crate::spec::base::apple::{opts, tvos_llvm_target, Arch, TargetAbi};
2-
use crate::spec::{FramePointer, Target, TargetOptions};
2+
use crate::spec::{FramePointer, MaybeLazy, Target, TargetOptions};
33

44
pub fn target() -> Target {
5-
let arch = Arch::Arm64;
5+
const ARCH: Arch = Arch::Arm64;
6+
const OS: &'static str = "tvos";
7+
const ABI: TargetAbi = TargetAbi::Normal;
8+
69
Target {
7-
llvm_target: tvos_llvm_target(arch).into(),
10+
llvm_target: MaybeLazy::lazy(|| tvos_llvm_target(ARCH)),
811
metadata: crate::spec::TargetMetadata {
912
description: None,
1013
tier: None,
@@ -13,12 +16,12 @@ pub fn target() -> Target {
1316
},
1417
pointer_width: 64,
1518
data_layout: "e-m:o-i64:64-i128:128-n32:64-S128-Fn32".into(),
16-
arch: arch.target_arch(),
19+
arch: ARCH.target_arch(),
1720
options: TargetOptions {
1821
features: "+neon,+fp-armv8,+apple-a7".into(),
1922
max_atomic_width: Some(128),
2023
frame_pointer: FramePointer::NonLeaf,
21-
..opts("tvos", arch, TargetAbi::Normal)
24+
..opts(OS, ARCH, ABI)
2225
},
2326
}
2427
}
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
use crate::spec::base::apple::{opts, tvos_sim_llvm_target, Arch, TargetAbi};
2-
use crate::spec::{FramePointer, Target, TargetOptions};
2+
use crate::spec::{FramePointer, MaybeLazy, Target, TargetOptions};
33

44
pub fn target() -> Target {
5-
let arch = Arch::Arm64;
5+
const ARCH: Arch = Arch::Arm64;
6+
const OS: &'static str = "tvos";
7+
const ABI: TargetAbi = TargetAbi::Normal;
8+
69
Target {
7-
llvm_target: tvos_sim_llvm_target(arch).into(),
10+
llvm_target: MaybeLazy::lazy(|| tvos_sim_llvm_target(ARCH)),
811
metadata: crate::spec::TargetMetadata {
912
description: None,
1013
tier: None,
@@ -13,12 +16,12 @@ pub fn target() -> Target {
1316
},
1417
pointer_width: 64,
1518
data_layout: "e-m:o-i64:64-i128:128-n32:64-S128-Fn32".into(),
16-
arch: arch.target_arch(),
19+
arch: ARCH.target_arch(),
1720
options: TargetOptions {
1821
features: "+neon,+fp-armv8,+apple-a7".into(),
1922
max_atomic_width: Some(128),
2023
frame_pointer: FramePointer::NonLeaf,
21-
..opts("tvos", arch, TargetAbi::Simulator)
24+
..opts(OS, ARCH, ABI)
2225
},
2326
}
2427
}

0 commit comments

Comments
 (0)