Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lazify TargetOptions::*link_args fields #127992

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions compiler/rustc_target/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down
14 changes: 10 additions & 4 deletions compiler/rustc_target/src/spec/base/apple/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::{borrow::Cow, env};

use crate::spec::{add_link_args, add_link_args_iter};
use crate::spec::link_args::LazyLinkArgsState;
use crate::spec::{add_link_args, add_link_args_iter, MaybeLazy};
use crate::spec::{cvs, Cc, DebuginfoKind, FramePointer, LinkArgs, LinkerFlavor, Lld};
use crate::spec::{SplitDebuginfo, StackProbeType, StaticCow, Target, TargetOptions};

Expand Down Expand Up @@ -94,7 +95,10 @@ impl TargetAbi {
}
}

fn pre_link_args(os: &'static str, arch: Arch, abi: TargetAbi) -> LinkArgs {
pub(crate) type ApplePreLinkArgs =
(/*os:*/ &'static str, /*arch:*/ Arch, /*abi:*/ TargetAbi);

pub(crate) fn pre_link_args((os, arch, abi): ApplePreLinkArgs) -> LinkArgs {
let platform_name: StaticCow<str> = match abi {
TargetAbi::Normal => os.into(),
TargetAbi::Simulator => format!("{os}-simulator").into(),
Expand All @@ -114,7 +118,9 @@ fn pre_link_args(os: &'static str, arch: Arch, abi: TargetAbi) -> LinkArgs {
};
let sdk_version = min_version.clone();

let mut args = TargetOptions::link_args(
let mut args = LinkArgs::new();
add_link_args(
&mut args,
LinkerFlavor::Darwin(Cc::No, Lld::No),
&["-arch", arch.target_name(), "-platform_version"],
);
Expand Down Expand Up @@ -151,7 +157,7 @@ pub fn opts(os: &'static str, arch: Arch, abi: TargetAbi) -> TargetOptions {
// macOS has -dead_strip, which doesn't rely on function_sections
function_sections: false,
dynamic_linking: true,
pre_link_args: pre_link_args(os, arch, abi),
pre_link_args: MaybeLazy::lazied(LazyLinkArgsState::Apple((os, arch, abi))),
families: cvs!["unix"],
is_like_osx: true,
// LLVM notes that macOS 10.11+ and iOS 9+ default
Expand Down
8 changes: 5 additions & 3 deletions compiler/rustc_target/src/spec/base/avr_gnu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@ use object::elf;
/// A base target for AVR devices using the GNU toolchain.
///
/// Requires GNU avr-gcc and avr-binutils on the host system.
/// FIXME: Remove the second parameter when const string concatenation is possible.
pub fn target(target_cpu: &'static str, mmcu: &'static str) -> Target {
pub fn target(target_cpu: &'static str) -> Target {
Target {
arch: "avr".into(),
metadata: crate::spec::TargetMetadata {
Expand All @@ -24,7 +23,10 @@ pub fn target(target_cpu: &'static str, mmcu: &'static str) -> Target {

linker: Some("avr-gcc".into()),
eh_frame_header: false,
pre_link_args: TargetOptions::link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &[mmcu]),
pre_link_args: TargetOptions::link_args(
LinkerFlavor::Gnu(Cc::Yes, Lld::No),
&["-mmcu=atmega328"],
),
late_link_args: TargetOptions::link_args(
LinkerFlavor::Gnu(Cc::Yes, Lld::No),
&["-lgcc"],
Expand Down
16 changes: 10 additions & 6 deletions compiler/rustc_target/src/spec/base/teeos.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
use crate::spec::{add_link_args, Cc, LinkerFlavor, Lld, PanicStrategy, RelroLevel, TargetOptions};
use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelroLevel, TargetOptions};

pub fn opts() -> TargetOptions {
let lld_args = &["-zmax-page-size=4096", "-znow", "-ztext", "--execute-only"];
let cc_args = &["-Wl,-zmax-page-size=4096", "-Wl,-znow", "-Wl,-ztext", "-mexecute-only"];

let mut pre_link_args = TargetOptions::link_args(LinkerFlavor::Gnu(Cc::No, Lld::No), lld_args);
add_link_args(&mut pre_link_args, LinkerFlavor::Gnu(Cc::Yes, Lld::No), cc_args);
let pre_link_args = {
const LLD_ARGS: &[&str] = &["-zmax-page-size=4096", "-znow", "-ztext", "--execute-only"];
const CC_ARGS: &[&str] =
&["-Wl,-zmax-page-size=4096", "-Wl,-znow", "-Wl,-ztext", "-mexecute-only"];
TargetOptions::link_args_list(&[
(LinkerFlavor::Gnu(Cc::No, Lld::No), LLD_ARGS),
(LinkerFlavor::Gnu(Cc::Yes, Lld::No), CC_ARGS),
])
};

TargetOptions {
os: "teeos".into(),
Expand Down
5 changes: 3 additions & 2 deletions compiler/rustc_target/src/spec/base/uefi_msvc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,13 @@
// the timer-interrupt. Device-drivers are required to use polling-based models. Furthermore, all
// code runs in the same environment, no process separation is supported.

use crate::spec::{base, LinkerFlavor, Lld, PanicStrategy, StackProbeType, TargetOptions};
use crate::spec::{base, LinkerFlavor, Lld};
use crate::spec::{PanicStrategy, StackProbeType, TargetOptions};

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

base.add_pre_link_args(
base.pre_link_args = TargetOptions::link_args(
LinkerFlavor::Msvc(Lld::No),
&[
// Non-standard subsystems have no default entry-point in PE+ files. We have to define
Expand Down
12 changes: 6 additions & 6 deletions compiler/rustc_target/src/spec/base/wasm.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
use crate::spec::{
add_link_args, cvs, Cc, LinkSelfContainedDefault, LinkerFlavor, PanicStrategy, RelocModel,
TargetOptions, TlsModel,
};
use crate::spec::{cvs, Cc, LinkSelfContainedDefault, LinkerFlavor, PanicStrategy};
use crate::spec::{RelocModel, TargetOptions, TlsModel};

pub fn options() -> TargetOptions {
macro_rules! args {
Expand Down Expand Up @@ -48,8 +46,10 @@ pub fn options() -> TargetOptions {
};
}

let mut pre_link_args = TargetOptions::link_args(LinkerFlavor::WasmLld(Cc::No), args!(""));
add_link_args(&mut pre_link_args, LinkerFlavor::WasmLld(Cc::Yes), args!("-Wl,"));
let pre_link_args = TargetOptions::link_args_list(&[
(LinkerFlavor::WasmLld(Cc::No), args!("")),
(LinkerFlavor::WasmLld(Cc::Yes), args!("-Wl,")),
]);

TargetOptions {
is_like_wasm: true,
Expand Down
124 changes: 63 additions & 61 deletions compiler/rustc_target/src/spec/base/windows_gnu.rs
Original file line number Diff line number Diff line change
@@ -1,78 +1,80 @@
use crate::spec::crt_objects;
use crate::spec::LinkSelfContainedDefault;
use crate::spec::{add_link_args, crt_objects};
use crate::spec::{cvs, Cc, DebuginfoKind, LinkerFlavor, Lld, SplitDebuginfo, TargetOptions};
use std::borrow::Cow;

pub fn opts() -> TargetOptions {
let mut pre_link_args = TargetOptions::link_args(
LinkerFlavor::Gnu(Cc::No, Lld::No),
&[
// Enable ASLR
"--dynamicbase",
// ASLR will rebase it anyway so leaving that option enabled only leads to confusion
"--disable-auto-image-base",
],
);
add_link_args(
&mut pre_link_args,
LinkerFlavor::Gnu(Cc::Yes, Lld::No),
&[
// Tell GCC to avoid linker plugins, because we are not bundling
// them with Windows installer, and Rust does its own LTO anyways.
"-fno-use-linker-plugin",
"-Wl,--dynamicbase",
"-Wl,--disable-auto-image-base",
],
);
let pre_link_args = TargetOptions::link_args_list(&[
(
LinkerFlavor::Gnu(Cc::No, Lld::No),
&[
// Enable ASLR
"--dynamicbase",
// ASLR will rebase it anyway so leaving that option enabled only leads to confusion
"--disable-auto-image-base",
],
),
(
LinkerFlavor::Gnu(Cc::Yes, Lld::No),
&[
// Tell GCC to avoid linker plugins, because we are not bundling
// them with Windows installer, and Rust does its own LTO anyways.
"-fno-use-linker-plugin",
"-Wl,--dynamicbase",
"-Wl,--disable-auto-image-base",
],
),
]);

// Order of `late_link_args*` was found through trial and error to work with various
// mingw-w64 versions (not tested on the CI). It's expected to change from time to time.
let mingw_libs = &[
"-lmsvcrt",
"-lmingwex",
"-lmingw32",
"-lgcc", // alas, mingw* libraries above depend on libgcc
// mingw's msvcrt is a weird hybrid import library and static library.
// And it seems that the linker fails to use import symbols from msvcrt
// that are required from functions in msvcrt in certain cases. For example
// `_fmode` that is used by an implementation of `__p__fmode` in x86_64.
// The library is purposely listed twice to fix that.
//
// See https://github.com/rust-lang/rust/pull/47483 for some more details.
"-lmsvcrt",
// Math functions missing in MSVCRT (they are present in UCRT) require
// this dependency cycle: `libmingwex.a` -> `libmsvcrt.a` -> `libmingwex.a`.
"-lmingwex",
"-luser32",
"-lkernel32",
];
let mut late_link_args =
TargetOptions::link_args(LinkerFlavor::Gnu(Cc::No, Lld::No), mingw_libs);
add_link_args(&mut late_link_args, LinkerFlavor::Gnu(Cc::Yes, Lld::No), mingw_libs);
let late_link_args = {
// Order of `late_link_args*` was found through trial and error to work with various
// mingw-w64 versions (not tested on the CI). It's expected to change from time to time.
const MINGW_LIBS: &[&str] = &[
"-lmsvcrt",
"-lmingwex",
"-lmingw32",
"-lgcc", // alas, mingw* libraries above depend on libgcc
// mingw's msvcrt is a weird hybrid import library and static library.
// And it seems that the linker fails to use import symbols from msvcrt
// that are required from functions in msvcrt in certain cases. For example
// `_fmode` that is used by an implementation of `__p__fmode` in x86_64.
// The library is purposely listed twice to fix that.
//
// See https://github.com/rust-lang/rust/pull/47483 for some more details.
"-lmsvcrt",
// Math functions missing in MSVCRT (they are present in UCRT) require
// this dependency cycle: `libmingwex.a` -> `libmsvcrt.a` -> `libmingwex.a`.
"-lmingwex",
"-luser32",
"-lkernel32",
];
TargetOptions::link_args_list(&[
(LinkerFlavor::Gnu(Cc::No, Lld::No), MINGW_LIBS),
(LinkerFlavor::Gnu(Cc::Yes, Lld::No), MINGW_LIBS),
])
};
// If any of our crates are dynamically linked then we need to use
// the shared libgcc_s-dw2-1.dll. This is required to support
// unwinding across DLL boundaries.
let dynamic_unwind_libs = &["-lgcc_s"];
let mut late_link_args_dynamic =
TargetOptions::link_args(LinkerFlavor::Gnu(Cc::No, Lld::No), dynamic_unwind_libs);
add_link_args(
&mut late_link_args_dynamic,
LinkerFlavor::Gnu(Cc::Yes, Lld::No),
dynamic_unwind_libs,
);
let late_link_args_dynamic = {
const DYNAMIC_UNWIND_LIBS: &[&str] = &["-lgcc_s"];
TargetOptions::link_args_list(&[
(LinkerFlavor::Gnu(Cc::No, Lld::No), DYNAMIC_UNWIND_LIBS),
(LinkerFlavor::Gnu(Cc::Yes, Lld::No), DYNAMIC_UNWIND_LIBS),
])
};
// If all of our crates are statically linked then we can get away
// with statically linking the libgcc unwinding code. This allows
// binaries to be redistributed without the libgcc_s-dw2-1.dll
// dependency, but unfortunately break unwinding across DLL
// boundaries when unwinding across FFI boundaries.
let static_unwind_libs = &["-lgcc_eh", "-l:libpthread.a"];
let mut late_link_args_static =
TargetOptions::link_args(LinkerFlavor::Gnu(Cc::No, Lld::No), static_unwind_libs);
add_link_args(
&mut late_link_args_static,
LinkerFlavor::Gnu(Cc::Yes, Lld::No),
static_unwind_libs,
);
let late_link_args_static = {
const STATIC_UNWIND_LIBS: &[&str] = &["-lgcc_eh", "-l:libpthread.a"];
TargetOptions::link_args_list(&[
(LinkerFlavor::Gnu(Cc::No, Lld::No), STATIC_UNWIND_LIBS),
(LinkerFlavor::Gnu(Cc::Yes, Lld::No), STATIC_UNWIND_LIBS),
])
};

TargetOptions {
os: "windows".into(),
Expand Down
39 changes: 21 additions & 18 deletions compiler/rustc_target/src/spec/base/windows_uwp_gnu.rs
Original file line number Diff line number Diff line change
@@ -1,26 +1,29 @@
use crate::spec::{add_link_args, base, Cc, LinkArgs, LinkerFlavor, Lld, TargetOptions};
use crate::spec::{base, Cc, LinkerFlavor, Lld, TargetOptions};

pub fn opts() -> TargetOptions {
let base = base::windows_gnu::opts();

// FIXME: This should be updated for the exception machinery changes from #67502
// and inherit from `windows_gnu_base`, at least partially.
let mingw_libs = &[
"-lwinstorecompat",
"-lruntimeobject",
"-lsynchronization",
"-lvcruntime140_app",
"-lucrt",
"-lwindowsapp",
"-lmingwex",
"-lmingw32",
];
let mut late_link_args =
TargetOptions::link_args(LinkerFlavor::Gnu(Cc::No, Lld::No), mingw_libs);
add_link_args(&mut late_link_args, LinkerFlavor::Gnu(Cc::Yes, Lld::No), mingw_libs);
let late_link_args = {
// FIXME: This should be updated for the exception machinery changes from #67502
// and inherit from `windows_gnu_base`, at least partially.
const MINGW_LIBS: &[&str] = &[
"-lwinstorecompat",
"-lruntimeobject",
"-lsynchronization",
"-lvcruntime140_app",
"-lucrt",
"-lwindowsapp",
"-lmingwex",
"-lmingw32",
];
TargetOptions::link_args_list(&[
(LinkerFlavor::Gnu(Cc::No, Lld::No), MINGW_LIBS),
(LinkerFlavor::Gnu(Cc::Yes, Lld::No), MINGW_LIBS),
])
};
// Reset the flags back to empty until the FIXME above is addressed.
let late_link_args_dynamic = LinkArgs::new();
let late_link_args_static = LinkArgs::new();
let late_link_args_dynamic = Default::default();
let late_link_args_static = Default::default();

TargetOptions {
abi: "uwp".into(),
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_target/src/spec/base/windows_uwp_msvc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ pub fn opts() -> TargetOptions {

opts.abi = "uwp".into();
opts.vendor = "uwp".into();
opts.add_pre_link_args(LinkerFlavor::Msvc(Lld::No), &["/APPCONTAINER", "mincore.lib"]);
opts.pre_link_args =
TargetOptions::link_args(LinkerFlavor::Msvc(Lld::No), &["/APPCONTAINER", "mincore.lib"]);

opts
}
41 changes: 41 additions & 0 deletions compiler/rustc_target/src/spec/link_args.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
//! Linker arguments

use crate::spec::add_link_args;
use crate::spec::{LinkerFlavor, LinkerFlavorCli};
use crate::spec::{MaybeLazy, StaticCow};

use std::collections::BTreeMap;

pub type LinkArgs = BTreeMap<LinkerFlavor, Vec<StaticCow<str>>>;
pub type LinkArgsCli = BTreeMap<LinkerFlavorCli, Vec<StaticCow<str>>>;

pub type LazyLinkArgs = MaybeLazy<LinkArgs, LazyLinkArgsState>;

pub enum LazyLinkArgsState {
Simple(LinkerFlavor, &'static [&'static str]),
List(&'static [(LinkerFlavor, &'static [&'static str])]),
Apple(super::base::apple::ApplePreLinkArgs),
}

impl FnOnce<()> for LazyLinkArgsState {
type Output = LinkArgs;

#[inline]
extern "rust-call" fn call_once(self, _args: ()) -> Self::Output {
match self {
LazyLinkArgsState::Simple(flavor, args) => {
let mut link_args = LinkArgs::new();
add_link_args(&mut link_args, flavor, args);
link_args
}
LazyLinkArgsState::List(l) => {
let mut link_args = LinkArgs::new();
for (flavor, args) in l {
add_link_args(&mut link_args, *flavor, args)
}
link_args
}
LazyLinkArgsState::Apple(args) => super::base::apple::pre_link_args(args),
}
}
}
Loading
Loading