Skip to content

Commit b75347b

Browse files
committed
Make TargetOptions::link_args stateful lazy - part 1
1 parent 1dffc91 commit b75347b

File tree

90 files changed

+378
-471
lines changed

Some content is hidden

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

90 files changed

+378
-471
lines changed

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ pub fn pre_link_args(os: &'static str, arch: Arch, abi: TargetAbi) -> LinkArgs {
114114
};
115115
let sdk_version = min_version.clone();
116116

117-
let mut args = TargetOptions::link_args(
117+
let mut args = TargetOptions::link_args_base(
118118
LinkerFlavor::Darwin(Cc::No, Lld::No),
119119
&["-arch", arch.target_name(), "-platform_version"],
120120
);
@@ -144,7 +144,7 @@ pub fn opts(
144144
os: &'static str,
145145
arch: Arch,
146146
abi: TargetAbi,
147-
pre_link_args: MaybeLazy<LinkArgs>,
147+
pre_link_args: MaybeLazy<LinkArgs, (LinkerFlavor, &'static [&'static str])>,
148148
) -> TargetOptions {
149149
TargetOptions {
150150
abi: abi.target_abi().into(),

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

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::spec::{Cc, LinkerFlavor, Lld, MaybeLazy, RelocModel, Target, TargetOptions};
1+
use crate::spec::{Cc, LinkerFlavor, Lld, RelocModel, Target, TargetOptions};
22
use object::elf;
33

44
/// A base target for AVR devices using the GNU toolchain.
@@ -23,12 +23,14 @@ pub fn target(target_cpu: &'static str) -> Target {
2323

2424
linker: Some("avr-gcc".into()),
2525
eh_frame_header: false,
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-
}),
26+
pre_link_args: TargetOptions::link_args(
27+
LinkerFlavor::Gnu(Cc::Yes, Lld::No),
28+
&["-mmcu=atmega328"],
29+
),
30+
late_link_args: TargetOptions::link_args(
31+
LinkerFlavor::Gnu(Cc::Yes, Lld::No),
32+
&["-lgcc"],
33+
),
3234
max_atomic_width: Some(16),
3335
atomic_cas: false,
3436
relocation_model: RelocModel::Static,

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

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -8,24 +8,22 @@ 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 = 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-
});
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+
);
2927

3028
TargetOptions {
3129
os: "fuchsia".into(),

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

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

33
pub fn opts() -> TargetOptions {
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-
});
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+
);
2826

2927
TargetOptions {
3028
os: "illumos".into(),

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

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
1-
use crate::spec::{DebuginfoKind, LinkerFlavor, Lld, MaybeLazy, SplitDebuginfo, TargetOptions};
1+
use crate::spec::{DebuginfoKind, LinkerFlavor, Lld, 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 =
8-
MaybeLazy::lazy(|| TargetOptions::link_args(LinkerFlavor::Msvc(Lld::No), &["/NOLOGO"]));
7+
let pre_link_args = TargetOptions::link_args(LinkerFlavor::Msvc(Lld::No), &["/NOLOGO"]);
98

109
TargetOptions {
1110
linker_flavor: LinkerFlavor::Msvc(Lld::No),

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ pub fn opts() -> TargetOptions {
77
let lld_args = &["-zmax-page-size=4096", "-znow", "-ztext", "--execute-only"];
88
let cc_args = &["-Wl,-zmax-page-size=4096", "-Wl,-znow", "-Wl,-ztext", "-mexecute-only"];
99
let mut pre_link_args =
10-
TargetOptions::link_args(LinkerFlavor::Gnu(Cc::No, Lld::No), lld_args);
10+
TargetOptions::link_args_base(LinkerFlavor::Gnu(Cc::No, Lld::No), lld_args);
1111
add_link_args(&mut pre_link_args, LinkerFlavor::Gnu(Cc::Yes, Lld::No), cc_args);
1212
pre_link_args
1313
});

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

Lines changed: 20 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -9,33 +9,31 @@
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, MaybeLazy};
12+
use crate::spec::{base, LinkerFlavor, Lld};
1313
use crate::spec::{PanicStrategy, StackProbeType, TargetOptions};
1414

1515
pub fn opts() -> TargetOptions {
1616
let mut base = base::msvc::opts();
1717

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

4038
TargetOptions {
4139
os: "uefi".into(),

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,8 @@ pub fn options() -> TargetOptions {
4949
}
5050

5151
let pre_link_args = MaybeLazy::lazy(|| {
52-
let mut pre_link_args = TargetOptions::link_args(LinkerFlavor::WasmLld(Cc::No), args!(""));
52+
let mut pre_link_args =
53+
TargetOptions::link_args_base(LinkerFlavor::WasmLld(Cc::No), args!(""));
5354
add_link_args(&mut pre_link_args, LinkerFlavor::WasmLld(Cc::Yes), args!("-Wl,"));
5455
pre_link_args
5556
});

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use std::borrow::Cow;
55

66
pub fn opts() -> TargetOptions {
77
let pre_link_args = MaybeLazy::lazy(|| {
8-
let mut pre_link_args = TargetOptions::link_args(
8+
let mut pre_link_args = TargetOptions::link_args_base(
99
LinkerFlavor::Gnu(Cc::No, Lld::No),
1010
&[
1111
// Enable ASLR
@@ -51,7 +51,7 @@ pub fn opts() -> TargetOptions {
5151
"-lkernel32",
5252
];
5353
let mut late_link_args =
54-
TargetOptions::link_args(LinkerFlavor::Gnu(Cc::No, Lld::No), mingw_libs);
54+
TargetOptions::link_args_base(LinkerFlavor::Gnu(Cc::No, Lld::No), mingw_libs);
5555
add_link_args(&mut late_link_args, LinkerFlavor::Gnu(Cc::Yes, Lld::No), mingw_libs);
5656
late_link_args
5757
});
@@ -61,7 +61,7 @@ pub fn opts() -> TargetOptions {
6161
let late_link_args_dynamic = MaybeLazy::lazy(|| {
6262
let dynamic_unwind_libs = &["-lgcc_s"];
6363
let mut late_link_args_dynamic =
64-
TargetOptions::link_args(LinkerFlavor::Gnu(Cc::No, Lld::No), dynamic_unwind_libs);
64+
TargetOptions::link_args_base(LinkerFlavor::Gnu(Cc::No, Lld::No), dynamic_unwind_libs);
6565
add_link_args(
6666
&mut late_link_args_dynamic,
6767
LinkerFlavor::Gnu(Cc::Yes, Lld::No),
@@ -77,7 +77,7 @@ pub fn opts() -> TargetOptions {
7777
let late_link_args_static = MaybeLazy::lazy(|| {
7878
let static_unwind_libs = &["-lgcc_eh", "-l:libpthread.a"];
7979
let mut late_link_args_static =
80-
TargetOptions::link_args(LinkerFlavor::Gnu(Cc::No, Lld::No), static_unwind_libs);
80+
TargetOptions::link_args_base(LinkerFlavor::Gnu(Cc::No, Lld::No), static_unwind_libs);
8181
add_link_args(
8282
&mut late_link_args_static,
8383
LinkerFlavor::Gnu(Cc::Yes, Lld::No),

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

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,20 @@
1-
use crate::spec::{
2-
cvs, Cc, DebuginfoKind, LinkerFlavor, Lld, MaybeLazy, SplitDebuginfo, TargetOptions,
3-
};
1+
use crate::spec::{cvs, Cc, DebuginfoKind, LinkerFlavor, Lld, SplitDebuginfo, TargetOptions};
42
use std::borrow::Cow;
53

64
pub fn opts() -> TargetOptions {
75
// We cannot use `-nodefaultlibs` because compiler-rt has to be passed
86
// as a path since it's not added to linker search path by the default.
97
// There were attempts to make it behave like libgcc (so one can just use -l<name>)
108
// but LLVM maintainers rejected it: https://reviews.llvm.org/D51440
11-
let pre_link_args = MaybeLazy::lazy(|| {
12-
TargetOptions::link_args(
13-
LinkerFlavor::Gnu(Cc::Yes, Lld::No),
14-
&["-nolibc", "--unwindlib=none"],
15-
)
16-
});
9+
let pre_link_args = TargetOptions::link_args(
10+
LinkerFlavor::Gnu(Cc::Yes, Lld::No),
11+
&["-nolibc", "--unwindlib=none"],
12+
);
1713
// Order of `late_link_args*` does not matter with LLD.
18-
let late_link_args = MaybeLazy::lazy(|| {
19-
TargetOptions::link_args(
20-
LinkerFlavor::Gnu(Cc::Yes, Lld::No),
21-
&["-lmingw32", "-lmingwex", "-lmsvcrt", "-lkernel32", "-luser32"],
22-
)
23-
});
14+
let late_link_args = TargetOptions::link_args(
15+
LinkerFlavor::Gnu(Cc::Yes, Lld::No),
16+
&["-lmingw32", "-lmingwex", "-lmsvcrt", "-lkernel32", "-luser32"],
17+
);
2418

2519
TargetOptions {
2620
os: "windows".into(),

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ pub fn opts() -> TargetOptions {
1717
"-lmingw32",
1818
];
1919
let mut late_link_args =
20-
TargetOptions::link_args(LinkerFlavor::Gnu(Cc::No, Lld::No), mingw_libs);
20+
TargetOptions::link_args_base(LinkerFlavor::Gnu(Cc::No, Lld::No), mingw_libs);
2121
add_link_args(&mut late_link_args, LinkerFlavor::Gnu(Cc::Yes, Lld::No), mingw_libs);
2222
late_link_args
2323
});
Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
1-
use crate::spec::{base, LinkerFlavor, Lld, MaybeLazy, TargetOptions};
1+
use crate::spec::{base, LinkerFlavor, Lld, TargetOptions};
22

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

66
opts.abi = "uwp".into();
77
opts.vendor = "uwp".into();
8-
opts.pre_link_args = MaybeLazy::lazy(|| {
9-
TargetOptions::link_args(LinkerFlavor::Msvc(Lld::No), &["/APPCONTAINER", "mincore.lib"])
10-
});
8+
opts.pre_link_args =
9+
TargetOptions::link_args(LinkerFlavor::Msvc(Lld::No), &["/APPCONTAINER", "mincore.lib"]);
1110

1211
opts
1312
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
//! Linker arguments
2+
3+
use crate::spec::{LinkerFlavor, LinkerFlavorCli};
4+
use crate::spec::{MaybeLazy, TargetOptions};
5+
use crate::spec::StaticCow;
6+
7+
use std::collections::BTreeMap;
8+
9+
pub type LinkArgs = BTreeMap<LinkerFlavor, Vec<StaticCow<str>>>;
10+
pub type LinkArgsCli = BTreeMap<LinkerFlavorCli, Vec<StaticCow<str>>>;
11+
12+
pub type LazyLinkArgs = MaybeLazy<LinkArgs, LazyLinkArgsState>;
13+
14+
pub(super) enum LazyLinkArgsState {
15+
Simple(LinkerFlavor, &'static [&'static str])
16+
}
17+
18+
impl FnOnce<()> for LazyLinkArgsState {
19+
type Output = LinkArgs;
20+
extern "rust-call" fn call_once(self, _args: ()) -> Self::Output {
21+
match self {
22+
LazyLinkArgsState::Simple(flavor, args) =>
23+
TargetOptions::link_args_base(flavor, args),
24+
}
25+
}
26+
}

0 commit comments

Comments
 (0)