Skip to content

Commit c3871b5

Browse files
committed
Auto merge of rust-lang#122703 - Urgau:lazy-targets, r=<try>
Lazify more work in builtins targets This PR make some fields in `Target` and `TargetOptions` lazifyable. This is done in order to reduce the impact of check-cfg which needs to load all the built-ins targets but doesn't need all the fields. In paticular this PR introduce a `MaybeLazy<T>` struct to support a borrowed, owned and lazy state. The fields that are changed are: - `LinkArgs` fields (access to env + allocate): ~54 023 236 ins[^1] -> ~53 478 072 ins - `CrtObjects` fields (allocate): ~53 478 072 ins -> ~53 127 832 ins - `llvm_name` field (access to env + allocate): ~53 127 832 ins -> ~53 057 110 ins This brings around -1 000 000 ins*tructions* and -0.2/0.3ms of less wall-time (with some measurement even having the same minimum wall-time with or without check-cfg) 🎉. *This PR is also a step further to completely `static`-fying all the build-in targets, if we one day we decide to do it, but that's a separate conversion.* [^1]: This is the total number of instructions as measured with `cachegrind` for the entire `rustc` invocation on a cargo --lib hello world, variance was really low (<15 000 ins). In the scale of the check-cfg feature, last time I measured `CheckCfg::fill_well_known` was around ~2.8 millions ins. r? `@petrochenkov`
2 parents 8cef37d + 2a57448 commit c3871b5

File tree

116 files changed

+1085
-658
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

116 files changed

+1085
-658
lines changed

compiler/rustc_codegen_ssa/src/back/link.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1832,7 +1832,7 @@ fn add_pre_link_objects(
18321832
// FIXME: we are currently missing some infra here (per-linker-flavor CRT objects),
18331833
// so Fuchsia has to be special-cased.
18341834
let opts = &sess.target;
1835-
let empty = Default::default();
1835+
let empty = CrtObjects::default();
18361836
let objects = if self_contained {
18371837
&opts.pre_link_objects_self_contained
18381838
} else if !(sess.target.os == "fuchsia" && matches!(flavor, LinkerFlavor::Gnu(Cc::Yes, _))) {

compiler/rustc_target/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#![feature(assert_matches)]
1515
#![feature(iter_intersperse)]
1616
#![feature(let_chains)]
17+
#![feature(lazy_cell)]
1718
#![feature(rustc_attrs)]
1819
#![feature(step_trait)]
1920
#![allow(internal_features)]

compiler/rustc_target/src/spec/base/aix.rs

+8-5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use crate::abi::Endian;
2-
use crate::spec::{crt_objects, cvs, Cc, CodeModel, LinkOutputKind, LinkerFlavor, TargetOptions};
2+
use crate::spec::{crt_objects, cvs, Cc, CodeModel, LinkOutputKind, LinkerFlavor};
3+
use crate::spec::{MaybeLazy, TargetOptions};
34

45
pub fn opts() -> TargetOptions {
56
TargetOptions {
@@ -22,10 +23,12 @@ pub fn opts() -> TargetOptions {
2223
is_like_aix: true,
2324
default_dwarf_version: 3,
2425
function_sections: true,
25-
pre_link_objects: crt_objects::new(&[
26-
(LinkOutputKind::DynamicNoPicExe, &["/usr/lib/crt0_64.o", "/usr/lib/crti_64.o"]),
27-
(LinkOutputKind::DynamicPicExe, &["/usr/lib/crt0_64.o", "/usr/lib/crti_64.o"]),
28-
]),
26+
pre_link_objects: MaybeLazy::lazy(|| {
27+
crt_objects::new(&[
28+
(LinkOutputKind::DynamicNoPicExe, &["/usr/lib/crt0_64.o", "/usr/lib/crti_64.o"]),
29+
(LinkOutputKind::DynamicPicExe, &["/usr/lib/crt0_64.o", "/usr/lib/crti_64.o"]),
30+
])
31+
}),
2932
dll_suffix: ".a".into(),
3033
..Default::default()
3134
}

compiler/rustc_target/src/spec/base/apple/mod.rs

+6-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::{borrow::Cow, env};
22

3-
use crate::spec::{add_link_args, add_link_args_iter};
3+
use crate::spec::{add_link_args, add_link_args_iter, MaybeLazy};
44
use crate::spec::{cvs, Cc, DebuginfoKind, FramePointer, LinkArgs, LinkerFlavor, Lld};
55
use crate::spec::{SplitDebuginfo, StackProbeType, StaticCow, Target, TargetOptions};
66

@@ -90,7 +90,9 @@ impl Arch {
9090
}
9191
}
9292

93-
fn pre_link_args(os: &'static str, arch: Arch, abi: &'static str) -> LinkArgs {
93+
pub fn pre_link_args(os: &'static str, arch: Arch) -> LinkArgs {
94+
let abi = arch.target_abi();
95+
9496
let platform_name: StaticCow<str> = match abi {
9597
"sim" => format!("{os}-simulator").into(),
9698
"macabi" => "mac-catalyst".into(),
@@ -136,7 +138,7 @@ fn pre_link_args(os: &'static str, arch: Arch, abi: &'static str) -> LinkArgs {
136138
args
137139
}
138140

139-
pub fn opts(os: &'static str, arch: Arch) -> TargetOptions {
141+
pub fn opts(os: &'static str, arch: Arch, pre_link_args: MaybeLazy<LinkArgs>) -> TargetOptions {
140142
let abi = arch.target_abi();
141143

142144
TargetOptions {
@@ -149,7 +151,7 @@ pub fn opts(os: &'static str, arch: Arch) -> TargetOptions {
149151
// macOS has -dead_strip, which doesn't rely on function_sections
150152
function_sections: false,
151153
dynamic_linking: true,
152-
pre_link_args: pre_link_args(os, arch, abi),
154+
pre_link_args,
153155
families: cvs!["unix"],
154156
is_like_osx: true,
155157
// LLVM notes that macOS 10.11+ and iOS 9+ default

compiler/rustc_target/src/spec/base/avr_gnu.rs

+8-8
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
1-
use crate::spec::{Cc, LinkerFlavor, Lld, RelocModel, Target, TargetOptions};
1+
use crate::spec::{Cc, LinkerFlavor, Lld, MaybeLazy, RelocModel, Target, TargetOptions};
22
use object::elf;
33

44
/// A base target for AVR devices using the GNU toolchain.
55
///
66
/// Requires GNU avr-gcc and avr-binutils on the host system.
7-
/// FIXME: Remove the second parameter when const string concatenation is possible.
8-
pub fn target(target_cpu: &'static str, mmcu: &'static str) -> Target {
7+
pub fn target(target_cpu: &'static str) -> Target {
98
Target {
109
arch: "avr".into(),
1110
metadata: crate::spec::TargetMetadata {
@@ -24,11 +23,12 @@ pub fn target(target_cpu: &'static str, mmcu: &'static str) -> Target {
2423

2524
linker: Some("avr-gcc".into()),
2625
eh_frame_header: false,
27-
pre_link_args: TargetOptions::link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &[mmcu]),
28-
late_link_args: TargetOptions::link_args(
29-
LinkerFlavor::Gnu(Cc::Yes, Lld::No),
30-
&["-lgcc"],
31-
),
26+
pre_link_args: MaybeLazy::lazy(|| {
27+
TargetOptions::link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-mmcu=atmega328"])
28+
}),
29+
late_link_args: MaybeLazy::lazy(|| {
30+
TargetOptions::link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-lgcc"])
31+
}),
3232
max_atomic_width: Some(16),
3333
atomic_cas: false,
3434
relocation_model: RelocModel::Static,

compiler/rustc_target/src/spec/base/fuchsia.rs

+27-23
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::spec::{
2-
crt_objects, cvs, Cc, FramePointer, LinkOutputKind, LinkerFlavor, Lld, TargetOptions,
2+
crt_objects, cvs, Cc, FramePointer, LinkOutputKind, LinkerFlavor, Lld, MaybeLazy, TargetOptions,
33
};
44

55
pub fn opts() -> TargetOptions {
@@ -8,22 +8,24 @@ pub fn opts() -> TargetOptions {
88
// so we only list them for ld/lld.
99
//
1010
// https://github.com/llvm/llvm-project/blob/db9322b2066c55254e7691efeab863f43bfcc084/clang/lib/Driver/ToolChains/Fuchsia.cpp#L31
11-
let pre_link_args = TargetOptions::link_args(
12-
LinkerFlavor::Gnu(Cc::No, Lld::No),
13-
&[
14-
"--build-id",
15-
"--hash-style=gnu",
16-
"-z",
17-
"max-page-size=4096",
18-
"-z",
19-
"now",
20-
"-z",
21-
"rodynamic",
22-
"-z",
23-
"separate-loadable-segments",
24-
"--pack-dyn-relocs=relr",
25-
],
26-
);
11+
let pre_link_args = MaybeLazy::lazy(|| {
12+
TargetOptions::link_args(
13+
LinkerFlavor::Gnu(Cc::No, Lld::No),
14+
&[
15+
"--build-id",
16+
"--hash-style=gnu",
17+
"-z",
18+
"max-page-size=4096",
19+
"-z",
20+
"now",
21+
"-z",
22+
"rodynamic",
23+
"-z",
24+
"separate-loadable-segments",
25+
"--pack-dyn-relocs=relr",
26+
],
27+
)
28+
});
2729

2830
TargetOptions {
2931
os: "fuchsia".into(),
@@ -32,12 +34,14 @@ pub fn opts() -> TargetOptions {
3234
dynamic_linking: true,
3335
families: cvs!["unix"],
3436
pre_link_args,
35-
pre_link_objects: crt_objects::new(&[
36-
(LinkOutputKind::DynamicNoPicExe, &["Scrt1.o"]),
37-
(LinkOutputKind::DynamicPicExe, &["Scrt1.o"]),
38-
(LinkOutputKind::StaticNoPicExe, &["Scrt1.o"]),
39-
(LinkOutputKind::StaticPicExe, &["Scrt1.o"]),
40-
]),
37+
pre_link_objects: MaybeLazy::lazy(|| {
38+
crt_objects::new(&[
39+
(LinkOutputKind::DynamicNoPicExe, &["Scrt1.o"]),
40+
(LinkOutputKind::DynamicPicExe, &["Scrt1.o"]),
41+
(LinkOutputKind::StaticNoPicExe, &["Scrt1.o"]),
42+
(LinkOutputKind::StaticPicExe, &["Scrt1.o"]),
43+
])
44+
}),
4145
position_independent_executables: true,
4246
has_thread_local: true,
4347
frame_pointer: FramePointer::NonLeaf,

compiler/rustc_target/src/spec/base/illumos.rs

+25-23
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,30 @@
1-
use crate::spec::{cvs, Cc, FramePointer, LinkerFlavor, TargetOptions};
1+
use crate::spec::{cvs, Cc, FramePointer, LinkerFlavor, MaybeLazy, TargetOptions};
22

33
pub fn opts() -> TargetOptions {
4-
let late_link_args = TargetOptions::link_args(
5-
LinkerFlavor::Unix(Cc::Yes),
6-
&[
7-
// The illumos libc contains a stack unwinding implementation, as
8-
// does libgcc_s. The latter implementation includes several
9-
// additional symbols that are not always in base libc. To force
10-
// the consistent use of just one unwinder, we ensure libc appears
11-
// after libgcc_s in the NEEDED list for the resultant binary by
12-
// ignoring any attempts to add it as a dynamic dependency until the
13-
// very end.
14-
// FIXME: This should be replaced by a more complete and generic
15-
// mechanism for controlling the order of library arguments passed
16-
// to the linker.
17-
"-lc",
18-
// LLVM will insert calls to the stack protector functions
19-
// "__stack_chk_fail" and "__stack_chk_guard" into code in native
20-
// object files. Some platforms include these symbols directly in
21-
// libc, but at least historically these have been provided in
22-
// libssp.so on illumos and Solaris systems.
23-
"-lssp",
24-
],
25-
);
4+
let late_link_args = MaybeLazy::lazy(|| {
5+
TargetOptions::link_args(
6+
LinkerFlavor::Unix(Cc::Yes),
7+
&[
8+
// The illumos libc contains a stack unwinding implementation, as
9+
// does libgcc_s. The latter implementation includes several
10+
// additional symbols that are not always in base libc. To force
11+
// the consistent use of just one unwinder, we ensure libc appears
12+
// after libgcc_s in the NEEDED list for the resultant binary by
13+
// ignoring any attempts to add it as a dynamic dependency until the
14+
// very end.
15+
// FIXME: This should be replaced by a more complete and generic
16+
// mechanism for controlling the order of library arguments passed
17+
// to the linker.
18+
"-lc",
19+
// LLVM will insert calls to the stack protector functions
20+
// "__stack_chk_fail" and "__stack_chk_guard" into code in native
21+
// object files. Some platforms include these symbols directly in
22+
// libc, but at least historically these have been provided in
23+
// libssp.so on illumos and Solaris systems.
24+
"-lssp",
25+
],
26+
)
27+
});
2628

2729
TargetOptions {
2830
os: "illumos".into(),

compiler/rustc_target/src/spec/base/linux_musl.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
use crate::spec::crt_objects;
2-
use crate::spec::{base, LinkSelfContainedDefault, TargetOptions};
2+
use crate::spec::{base, LinkSelfContainedDefault, MaybeLazy, TargetOptions};
33

44
pub fn opts() -> TargetOptions {
55
let mut base = base::linux::opts();
66

77
base.env = "musl".into();
8-
base.pre_link_objects_self_contained = crt_objects::pre_musl_self_contained();
9-
base.post_link_objects_self_contained = crt_objects::post_musl_self_contained();
8+
base.pre_link_objects_self_contained = MaybeLazy::lazy(crt_objects::pre_musl_self_contained);
9+
base.post_link_objects_self_contained = MaybeLazy::lazy(crt_objects::post_musl_self_contained);
1010
base.link_self_contained = LinkSelfContainedDefault::InferredForMusl;
1111

1212
// These targets statically link libc by default

compiler/rustc_target/src/spec/base/msvc.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
use crate::spec::{DebuginfoKind, LinkerFlavor, Lld, SplitDebuginfo, TargetOptions};
1+
use crate::spec::{DebuginfoKind, LinkerFlavor, Lld, MaybeLazy, SplitDebuginfo, TargetOptions};
22
use std::borrow::Cow;
33

44
pub fn opts() -> TargetOptions {
55
// Suppress the verbose logo and authorship debugging output, which would needlessly
66
// clog any log files.
7-
let pre_link_args = TargetOptions::link_args(LinkerFlavor::Msvc(Lld::No), &["/NOLOGO"]);
7+
let pre_link_args =
8+
MaybeLazy::lazy(|| TargetOptions::link_args(LinkerFlavor::Msvc(Lld::No), &["/NOLOGO"]));
89

910
TargetOptions {
1011
linker_flavor: LinkerFlavor::Msvc(Lld::No),

compiler/rustc_target/src/spec/base/teeos.rs

+11-6
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
1-
use crate::spec::{add_link_args, Cc, LinkerFlavor, Lld, PanicStrategy, RelroLevel, TargetOptions};
1+
use crate::spec::{
2+
add_link_args, Cc, LinkerFlavor, Lld, MaybeLazy, PanicStrategy, RelroLevel, TargetOptions,
3+
};
24

35
pub fn opts() -> TargetOptions {
4-
let lld_args = &["-zmax-page-size=4096", "-znow", "-ztext", "--execute-only"];
5-
let cc_args = &["-Wl,-zmax-page-size=4096", "-Wl,-znow", "-Wl,-ztext", "-mexecute-only"];
6-
7-
let mut pre_link_args = TargetOptions::link_args(LinkerFlavor::Gnu(Cc::No, Lld::No), lld_args);
8-
add_link_args(&mut pre_link_args, LinkerFlavor::Gnu(Cc::Yes, Lld::No), cc_args);
6+
let pre_link_args = MaybeLazy::lazy(|| {
7+
let lld_args = &["-zmax-page-size=4096", "-znow", "-ztext", "--execute-only"];
8+
let cc_args = &["-Wl,-zmax-page-size=4096", "-Wl,-znow", "-Wl,-ztext", "-mexecute-only"];
9+
let mut pre_link_args =
10+
TargetOptions::link_args(LinkerFlavor::Gnu(Cc::No, Lld::No), lld_args);
11+
add_link_args(&mut pre_link_args, LinkerFlavor::Gnu(Cc::Yes, Lld::No), cc_args);
12+
pre_link_args
13+
});
914

1015
TargetOptions {
1116
os: "teeos".into(),

compiler/rustc_target/src/spec/base/uefi_msvc.rs

+24-20
Original file line numberDiff line numberDiff line change
@@ -9,30 +9,34 @@
99
// the timer-interrupt. Device-drivers are required to use polling-based models. Furthermore, all
1010
// code runs in the same environment, no process separation is supported.
1111

12-
use crate::spec::{base, LinkerFlavor, Lld, PanicStrategy, StackProbeType, TargetOptions};
12+
use crate::spec::{
13+
base, LinkerFlavor, Lld, MaybeLazy, PanicStrategy, StackProbeType, TargetOptions,
14+
};
1315

1416
pub fn opts() -> TargetOptions {
1517
let mut base = base::msvc::opts();
1618

17-
base.add_pre_link_args(
18-
LinkerFlavor::Msvc(Lld::No),
19-
&[
20-
// Non-standard subsystems have no default entry-point in PE+ files. We have to define
21-
// one. "efi_main" seems to be a common choice amongst other implementations and the
22-
// spec.
23-
"/entry:efi_main",
24-
// COFF images have a "Subsystem" field in their header, which defines what kind of
25-
// program it is. UEFI has 3 fields reserved, which are EFI_APPLICATION,
26-
// EFI_BOOT_SERVICE_DRIVER, and EFI_RUNTIME_DRIVER. We default to EFI_APPLICATION,
27-
// which is very likely the most common option. Individual projects can override this
28-
// with custom linker flags.
29-
// The subsystem-type only has minor effects on the application. It defines the memory
30-
// regions the application is loaded into (runtime-drivers need to be put into
31-
// reserved areas), as well as whether a return from the entry-point is treated as
32-
// exit (default for applications).
33-
"/subsystem:efi_application",
34-
],
35-
);
19+
base.pre_link_args = MaybeLazy::lazy(|| {
20+
TargetOptions::link_args(
21+
LinkerFlavor::Msvc(Lld::No),
22+
&[
23+
// Non-standard subsystems have no default entry-point in PE+ files. We have to define
24+
// one. "efi_main" seems to be a common choice amongst other implementations and the
25+
// spec.
26+
"/entry:efi_main",
27+
// COFF images have a "Subsystem" field in their header, which defines what kind of
28+
// program it is. UEFI has 3 fields reserved, which are EFI_APPLICATION,
29+
// EFI_BOOT_SERVICE_DRIVER, and EFI_RUNTIME_DRIVER. We default to EFI_APPLICATION,
30+
// which is very likely the most common option. Individual projects can override this
31+
// with custom linker flags.
32+
// The subsystem-type only has minor effects on the application. It defines the memory
33+
// regions the application is loaded into (runtime-drivers need to be put into
34+
// reserved areas), as well as whether a return from the entry-point is treated as
35+
// exit (default for applications).
36+
"/subsystem:efi_application",
37+
],
38+
)
39+
});
3640

3741
TargetOptions {
3842
os: "uefi".into(),

compiler/rustc_target/src/spec/base/wasm.rs

+7-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::spec::{
2-
add_link_args, cvs, Cc, LinkSelfContainedDefault, LinkerFlavor, PanicStrategy, RelocModel,
3-
TargetOptions, TlsModel,
2+
add_link_args, cvs, Cc, LinkSelfContainedDefault, LinkerFlavor, MaybeLazy, PanicStrategy,
3+
RelocModel, TargetOptions, TlsModel,
44
};
55

66
pub fn options() -> TargetOptions {
@@ -48,8 +48,11 @@ pub fn options() -> TargetOptions {
4848
};
4949
}
5050

51-
let mut pre_link_args = TargetOptions::link_args(LinkerFlavor::WasmLld(Cc::No), args!(""));
52-
add_link_args(&mut pre_link_args, LinkerFlavor::WasmLld(Cc::Yes), args!("-Wl,"));
51+
let pre_link_args = MaybeLazy::lazy(|| {
52+
let mut pre_link_args = TargetOptions::link_args(LinkerFlavor::WasmLld(Cc::No), args!(""));
53+
add_link_args(&mut pre_link_args, LinkerFlavor::WasmLld(Cc::Yes), args!("-Wl,"));
54+
pre_link_args
55+
});
5356

5457
TargetOptions {
5558
is_like_wasm: true,

0 commit comments

Comments
 (0)