Skip to content

Refactor linker code #86911

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

Merged
merged 8 commits into from
Jul 7, 2021
Merged
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
4 changes: 1 addition & 3 deletions compiler/rustc_codegen_cranelift/src/driver/aot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
use std::path::PathBuf;

use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
use rustc_codegen_ssa::back::linker::LinkerInfo;
use rustc_codegen_ssa::{CodegenResults, CompiledModule, CrateInfo, ModuleKind};
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
Expand Down Expand Up @@ -296,8 +295,7 @@ pub(crate) fn run_aot(
allocator_module,
metadata_module,
metadata,
linker_info: LinkerInfo::new(tcx, crate::target_triple(tcx.sess).to_string()),
crate_info: CrateInfo::new(tcx),
crate_info: CrateInfo::new(tcx, crate::target_triple(tcx.sess).to_string()),
},
work_products,
))
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_cranelift/src/driver/jit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ fn load_imported_symbols_for_jit(tcx: TyCtxt<'_>) -> Vec<(String, *const u8)> {

let mut dylib_paths = Vec::new();

let crate_info = CrateInfo::new(tcx);
let crate_info = CrateInfo::new(tcx, "dummy_target_cpu".to_string());
let formats = tcx.dependency_formats(());
let data = &formats
.iter()
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_codegen_cranelift/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,6 @@ impl CodegenBackend for CraneliftCodegenBackend {
sess,
&codegen_results,
outputs,
&codegen_results.crate_info.local_crate_name.as_str(),
);

Ok(())
Expand Down
7 changes: 1 addition & 6 deletions compiler/rustc_codegen_llvm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -292,12 +292,7 @@ impl CodegenBackend for LlvmCodegenBackend {

// Run the linker on any artifacts that resulted from the LLVM run.
// This should produce either a finished executable or library.
link_binary::<LlvmArchiveBuilder<'_>>(
sess,
&codegen_results,
outputs,
&codegen_results.crate_info.local_crate_name.as_str(),
);
link_binary::<LlvmArchiveBuilder<'_>>(sess, &codegen_results, outputs);

Ok(())
}
Expand Down
121 changes: 20 additions & 101 deletions compiler/rustc_codegen_ssa/src/back/link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ pub fn link_binary<'a, B: ArchiveBuilder<'a>>(
sess: &'a Session,
codegen_results: &CodegenResults,
outputs: &OutputFilenames,
crate_name: &str,
) {
let _timer = sess.timer("link_binary");
let output_metadata = sess.opts.output_types.contains_key(&OutputType::Metadata);
Expand Down Expand Up @@ -87,7 +86,12 @@ pub fn link_binary<'a, B: ArchiveBuilder<'a>>(
.tempdir()
.unwrap_or_else(|err| sess.fatal(&format!("couldn't create a temp dir: {}", err)));
let path = MaybeTempDir::new(tmpdir, sess.opts.cg.save_temps);
let out_filename = out_filename(sess, crate_type, outputs, crate_name);
let out_filename = out_filename(
sess,
crate_type,
outputs,
&codegen_results.crate_info.local_crate_name.as_str(),
);
match crate_type {
CrateType::Rlib => {
let _timer = sess.timer("link_rlib");
Expand Down Expand Up @@ -143,97 +147,6 @@ pub fn link_binary<'a, B: ArchiveBuilder<'a>>(
});
}

// The third parameter is for env vars, used on windows to set up the
// path for MSVC to find its DLLs, and gcc to find its bundled
// toolchain
fn get_linker(
sess: &Session,
linker: &Path,
flavor: LinkerFlavor,
self_contained: bool,
) -> Command {
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
// emscripten where the linker is `emcc.bat` and needs to be spawned as
// `cmd /c emcc.bat ...`.
//
// This worked historically but is needed manually since #42436 (regression
// was tagged as #42791) and some more info can be found on #44443 for
// emscripten itself.
let mut cmd = match linker.to_str() {
Some(linker) if cfg!(windows) && linker.ends_with(".bat") => Command::bat_script(linker),
_ => match flavor {
LinkerFlavor::Lld(f) => Command::lld(linker, f),
LinkerFlavor::Msvc if sess.opts.cg.linker.is_none() && sess.target.linker.is_none() => {
Command::new(msvc_tool.as_ref().map_or(linker, |t| t.path()))
}
_ => Command::new(linker),
},
};

// UWP apps have API restrictions enforced during Store submissions.
// To comply with the Windows App Certification Kit,
// MSVC needs to link with the Store versions of the runtime libraries (vcruntime, msvcrt, etc).
let t = &sess.target;
if (flavor == LinkerFlavor::Msvc || flavor == LinkerFlavor::Lld(LldFlavor::Link))
&& 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) {
let arch = match t.arch.as_str() {
"x86_64" => Some("x64"),
"x86" => Some("x86"),
"aarch64" => Some("arm64"),
"arm" => Some("arm"),
_ => None,
};
if let Some(ref a) = arch {
// FIXME: Move this to `fn linker_with_args`.
let mut arg = OsString::from("/LIBPATH:");
arg.push(format!("{}\\lib\\{}\\store", root_lib_path.display(), a));
cmd.arg(&arg);
} else {
warn!("arch is not supported");
}
} else {
warn!("MSVC root path lib location not found");
}
} else {
warn!("link.exe not found");
}
}

// The compiler's sysroot often has some bundled tools, so add it to the
// PATH for the child.
let mut new_path = sess.host_filesearch(PathKind::All).get_tools_search_paths(self_contained);
let mut msvc_changed_path = false;
if sess.target.is_like_msvc {
if let Some(ref tool) = msvc_tool {
cmd.args(tool.args());
for &(ref k, ref v) in tool.env() {
if k == "PATH" {
new_path.extend(env::split_paths(v));
msvc_changed_path = true;
} else {
cmd.env(k, v);
}
}
}
}

if !msvc_changed_path {
if let Some(path) = env::var_os("PATH") {
new_path.extend(env::split_paths(&path));
}
}
cmd.env("PATH", env::join_paths(new_path).unwrap());

cmd
}

pub fn each_linked_rlib(
info: &CrateInfo,
f: &mut dyn FnMut(CrateNum, &Path),
Expand Down Expand Up @@ -1800,11 +1713,13 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>(
codegen_results: &CodegenResults,
) -> Command {
let crt_objects_fallback = crt_objects_fallback(sess, crate_type);
let base_cmd = get_linker(sess, path, flavor, crt_objects_fallback);
// FIXME: Move `/LIBPATH` addition for uwp targets from the linker construction
// to the linker args construction.
assert!(base_cmd.get_args().is_empty() || sess.target.vendor == "uwp");
let cmd = &mut *codegen_results.linker_info.to_linker(base_cmd, &sess, flavor);
let cmd = &mut *super::linker::get_linker(
sess,
path,
flavor,
crt_objects_fallback,
&codegen_results.crate_info.target_cpu,
);
let link_output_kind = link_output_kind(sess, crate_type);

// ------------ Early order-dependent options ------------
Expand All @@ -1814,7 +1729,11 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>(
// dynamic library.
// Must be passed before any libraries to prevent the symbols to export from being thrown away,
// at least on some platforms (e.g. windows-gnu).
cmd.export_symbols(tmpdir, crate_type);
cmd.export_symbols(
tmpdir,
crate_type,
&codegen_results.crate_info.exported_symbols[&crate_type],
);

// Can be used for adding custom CRT objects or overriding order-dependent options above.
// FIXME: In practice built-in target specs use this for arbitrary order-independent options,
Expand Down Expand Up @@ -1986,10 +1905,10 @@ fn add_order_independent_options(
if flavor == LinkerFlavor::PtxLinker {
// Provide the linker with fallback to internal `target-cpu`.
cmd.arg("--fallback-arch");
cmd.arg(&codegen_results.linker_info.target_cpu);
cmd.arg(&codegen_results.crate_info.target_cpu);
} else if flavor == LinkerFlavor::BpfLinker {
cmd.arg("--cpu");
cmd.arg(&codegen_results.linker_info.target_cpu);
cmd.arg(&codegen_results.crate_info.target_cpu);
cmd.arg("--cpu-features");
cmd.arg(match &sess.opts.cg.target_feature {
feat if !feat.is_empty() => feat,
Expand Down
Loading