summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_codegen_ssa/src/back/linker.rs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-19 09:26:03 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-19 09:26:03 +0000
commit9918693037dce8aa4bb6f08741b6812923486c18 (patch)
tree21d2b40bec7e6a7ea664acee056eb3d08e15a1cf /compiler/rustc_codegen_ssa/src/back/linker.rs
parentReleasing progress-linux version 1.75.0+dfsg1-5~progress7.99u1. (diff)
downloadrustc-9918693037dce8aa4bb6f08741b6812923486c18.tar.xz
rustc-9918693037dce8aa4bb6f08741b6812923486c18.zip
Merging upstream version 1.76.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'compiler/rustc_codegen_ssa/src/back/linker.rs')
-rw-r--r--compiler/rustc_codegen_ssa/src/back/linker.rs131
1 files changed, 93 insertions, 38 deletions
diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs
index 09434513e..eeb57d4d0 100644
--- a/compiler/rustc_codegen_ssa/src/back/linker.rs
+++ b/compiler/rustc_codegen_ssa/src/back/linker.rs
@@ -45,7 +45,7 @@ pub fn get_linker<'a>(
self_contained: bool,
target_cpu: &'a str,
) -> Box<dyn Linker + 'a> {
- let msvc_tool = windows_registry::find_tool(&sess.opts.target_triple.triple(), "link.exe");
+ let msvc_tool = windows_registry::find_tool(sess.opts.target_triple.triple(), "link.exe");
// If our linker looks like a batch script on Windows then to execute this
// we'll need to spawn `cmd` explicitly. This is primarily done to handle
@@ -78,7 +78,7 @@ pub fn get_linker<'a>(
if matches!(flavor, LinkerFlavor::Msvc(..)) && t.vendor == "uwp" {
if let Some(ref tool) = msvc_tool {
let original_path = tool.path();
- if let Some(ref root_lib_path) = original_path.ancestors().nth(4) {
+ if let Some(root_lib_path) = original_path.ancestors().nth(4) {
let arch = match t.arch.as_ref() {
"x86_64" => Some("x64"),
"x86" => Some("x86"),
@@ -185,6 +185,7 @@ pub trait Linker {
fn optimize(&mut self);
fn pgo_gen(&mut self);
fn control_flow_guard(&mut self);
+ fn ehcont_guard(&mut self);
fn debuginfo(&mut self, strip: Strip, natvis_debugger_visualizers: &[PathBuf]);
fn no_crt_objects(&mut self);
fn no_default_libraries(&mut self);
@@ -195,6 +196,14 @@ pub trait Linker {
fn add_no_exec(&mut self) {}
fn add_as_needed(&mut self) {}
fn reset_per_library_state(&mut self) {}
+ fn linker_arg(&mut self, arg: &OsStr, verbatim: bool) {
+ self.linker_args(&[arg], verbatim);
+ }
+ fn linker_args(&mut self, args: &[&OsStr], _verbatim: bool) {
+ args.into_iter().for_each(|a| {
+ self.cmd().arg(a);
+ });
+ }
}
impl dyn Linker + '_ {
@@ -222,38 +231,12 @@ pub struct GccLinker<'a> {
}
impl<'a> GccLinker<'a> {
- /// Passes an argument directly to the linker.
- ///
- /// When the linker is not ld-like such as when using a compiler as a linker, the argument is
- /// prepended by `-Wl,`.
- fn linker_arg(&mut self, arg: impl AsRef<OsStr>) -> &mut Self {
- self.linker_args(&[arg]);
- self
+ fn linker_arg(&mut self, arg: impl AsRef<OsStr>) {
+ Linker::linker_arg(self, arg.as_ref(), false);
}
-
- /// Passes a series of arguments directly to the linker.
- ///
- /// When the linker is ld-like, the arguments are simply appended to the command. When the
- /// linker is not ld-like such as when using a compiler as a linker, the arguments are joined by
- /// commas to form an argument that is then prepended with `-Wl`. In this situation, only a
- /// single argument is appended to the command to ensure that the order of the arguments is
- /// preserved by the compiler.
- fn linker_args(&mut self, args: &[impl AsRef<OsStr>]) -> &mut Self {
- if self.is_ld {
- args.into_iter().for_each(|a| {
- self.cmd.arg(a);
- });
- } else {
- if !args.is_empty() {
- let mut s = OsString::from("-Wl");
- for a in args {
- s.push(",");
- s.push(a);
- }
- self.cmd.arg(s);
- }
- }
- self
+ fn linker_args(&mut self, args: &[impl AsRef<OsStr>]) {
+ let args_vec: Vec<&OsStr> = args.iter().map(|x| x.as_ref()).collect();
+ Linker::linker_args(self, &args_vec, false);
}
fn takes_hints(&self) -> bool {
@@ -360,6 +343,30 @@ impl<'a> GccLinker<'a> {
}
impl<'a> Linker for GccLinker<'a> {
+ /// Passes a series of arguments directly to the linker.
+ ///
+ /// When the linker is ld-like, the arguments are simply appended to the command. When the
+ /// linker is not ld-like such as when using a compiler as a linker, the arguments are joined by
+ /// commas to form an argument that is then prepended with `-Wl`. In this situation, only a
+ /// single argument is appended to the command to ensure that the order of the arguments is
+ /// preserved by the compiler.
+ fn linker_args(&mut self, args: &[&OsStr], verbatim: bool) {
+ if self.is_ld || verbatim {
+ args.into_iter().for_each(|a| {
+ self.cmd.arg(a);
+ });
+ } else {
+ if !args.is_empty() {
+ let mut s = OsString::from("-Wl");
+ for a in args {
+ s.push(",");
+ s.push(a);
+ }
+ self.cmd.arg(s);
+ }
+ }
+ }
+
fn cmd(&mut self) -> &mut Command {
&mut self.cmd
}
@@ -519,7 +526,7 @@ impl<'a> Linker for GccLinker<'a> {
// -force_load is the macOS equivalent of --whole-archive, but it
// involves passing the full path to the library to link.
self.linker_arg("-force_load");
- let lib = find_native_static_library(lib, verbatim, search_path, &self.sess);
+ let lib = find_native_static_library(lib, verbatim, search_path, self.sess);
self.linker_arg(&lib);
}
}
@@ -530,7 +537,7 @@ impl<'a> Linker for GccLinker<'a> {
self.linker_arg("-force_load");
self.linker_arg(&lib);
} else {
- self.linker_arg("--whole-archive").cmd.arg(lib);
+ self.linker_args(&[OsString::from("--whole-archive"), lib.into()]);
self.linker_arg("--no-whole-archive");
}
}
@@ -605,6 +612,8 @@ impl<'a> Linker for GccLinker<'a> {
fn control_flow_guard(&mut self) {}
+ fn ehcont_guard(&mut self) {}
+
fn debuginfo(&mut self, strip: Strip, _: &[PathBuf]) {
// MacOS linker doesn't support stripping symbols directly anymore.
if self.sess.target.is_like_osx {
@@ -914,6 +923,12 @@ impl<'a> Linker for MsvcLinker<'a> {
self.cmd.arg("/guard:cf");
}
+ fn ehcont_guard(&mut self) {
+ if self.sess.target.pointer_width == 64 {
+ self.cmd.arg("/guard:ehcont");
+ }
+ }
+
fn debuginfo(&mut self, strip: Strip, natvis_debugger_visualizers: &[PathBuf]) {
match strip {
Strip::None => {
@@ -1127,6 +1142,8 @@ impl<'a> Linker for EmLinker<'a> {
fn control_flow_guard(&mut self) {}
+ fn ehcont_guard(&mut self) {}
+
fn debuginfo(&mut self, _strip: Strip, _: &[PathBuf]) {
// Preserve names or generate source maps depending on debug info
// For more information see https://emscripten.org/docs/tools_reference/emcc.html#emcc-g
@@ -1291,6 +1308,8 @@ impl<'a> Linker for WasmLd<'a> {
}
fn optimize(&mut self) {
+ // The -O flag is, as of late 2023, only used for merging of strings and debuginfo, and
+ // only differentiates -O0 and -O1. It does not apply to LTO.
self.cmd.arg(match self.sess.opts.optimize {
OptLevel::No => "-O0",
OptLevel::Less => "-O1",
@@ -1319,6 +1338,8 @@ impl<'a> Linker for WasmLd<'a> {
fn control_flow_guard(&mut self) {}
+ fn ehcont_guard(&mut self) {}
+
fn no_crt_objects(&mut self) {}
fn no_default_libraries(&mut self) {}
@@ -1341,7 +1362,31 @@ impl<'a> Linker for WasmLd<'a> {
fn subsystem(&mut self, _subsystem: &str) {}
fn linker_plugin_lto(&mut self) {
- // Do nothing for now
+ match self.sess.opts.cg.linker_plugin_lto {
+ LinkerPluginLto::Disabled => {
+ // Nothing to do
+ }
+ LinkerPluginLto::LinkerPluginAuto => {
+ self.push_linker_plugin_lto_args();
+ }
+ LinkerPluginLto::LinkerPlugin(_) => {
+ self.push_linker_plugin_lto_args();
+ }
+ }
+ }
+}
+
+impl<'a> WasmLd<'a> {
+ fn push_linker_plugin_lto_args(&mut self) {
+ let opt_level = match self.sess.opts.optimize {
+ config::OptLevel::No => "O0",
+ config::OptLevel::Less => "O1",
+ config::OptLevel::Default => "O2",
+ config::OptLevel::Aggressive => "O3",
+ // wasm-ld only handles integer LTO opt levels. Use O2
+ config::OptLevel::Size | config::OptLevel::SizeMin => "O2",
+ };
+ self.cmd.arg(&format!("--lto-{opt_level}"));
}
}
@@ -1472,6 +1517,8 @@ impl<'a> Linker for L4Bender<'a> {
fn control_flow_guard(&mut self) {}
+ fn ehcont_guard(&mut self) {}
+
fn no_crt_objects(&mut self) {}
}
@@ -1590,7 +1637,7 @@ impl<'a> Linker for AixLinker<'a> {
fn link_whole_staticlib(&mut self, lib: &str, verbatim: bool, search_path: &[PathBuf]) {
self.hint_static();
- let lib = find_native_static_library(lib, verbatim, search_path, &self.sess);
+ let lib = find_native_static_library(lib, verbatim, search_path, self.sess);
self.cmd.arg(format!("-bkeepfile:{}", lib.to_str().unwrap()));
}
@@ -1613,6 +1660,8 @@ impl<'a> Linker for AixLinker<'a> {
fn control_flow_guard(&mut self) {}
+ fn ehcont_guard(&mut self) {}
+
fn debuginfo(&mut self, strip: Strip, _: &[PathBuf]) {
match strip {
Strip::None => {}
@@ -1699,7 +1748,9 @@ fn exported_symbols_for_non_proc_macro(tcx: TyCtxt<'_>, crate_type: CrateType) -
let export_threshold = symbol_export::crates_export_threshold(&[crate_type]);
for_each_exported_symbols_include_dep(tcx, crate_type, |symbol, info, cnum| {
if info.level.is_below_threshold(export_threshold) {
- symbols.push(symbol_export::symbol_name_for_instance_in_crate(tcx, symbol, cnum));
+ symbols.push(symbol_export::exporting_symbol_name_for_instance_in_crate(
+ tcx, symbol, cnum,
+ ));
}
});
@@ -1835,6 +1886,8 @@ impl<'a> Linker for PtxLinker<'a> {
fn control_flow_guard(&mut self) {}
+ fn ehcont_guard(&mut self) {}
+
fn export_symbols(&mut self, _tmpdir: &Path, _crate_type: CrateType, _symbols: &[String]) {}
fn subsystem(&mut self, _subsystem: &str) {}
@@ -1931,6 +1984,8 @@ impl<'a> Linker for BpfLinker<'a> {
fn control_flow_guard(&mut self) {}
+ fn ehcont_guard(&mut self) {}
+
fn export_symbols(&mut self, tmpdir: &Path, _crate_type: CrateType, symbols: &[String]) {
let path = tmpdir.join("symbols");
let res: io::Result<()> = try {