Skip to content

Commit 03141ca

Browse files
committed
Separating the back folder between backend-agnostic and LLVM-specific code
1 parent 6a2d174 commit 03141ca

29 files changed

+4435
-2480
lines changed

src/librustc_codegen_llvm/back/archive.rs

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use std::ptr;
1818
use std::str;
1919

2020
use back::bytecode::RLIB_BYTECODE_EXTENSION;
21+
use rustc_codegen_ssa::back::archive::find_library;
2122
use libc;
2223
use llvm::archive_ro::{ArchiveRO, Child};
2324
use llvm::{self, ArchiveKind};

src/librustc_codegen_llvm/back/link.rs

+23-200
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,12 @@
99
// except according to those terms.
1010

1111
use back::wasm;
12-
use cc::windows_registry;
1312
use super::archive::{ArchiveBuilder, ArchiveConfig};
1413
use super::bytecode::RLIB_BYTECODE_EXTENSION;
14+
use rustc_codegen_ssa::back::linker::Linker;
15+
use rustc_codegen_ssa::back::link::{remove, ignored_for_lto, each_linked_rlib, linker_and_flavor,
16+
get_linker};
17+
use rustc_codegen_ssa::back::command::Command;
1518
use super::rpath::RPathConfig;
1619
use super::rpath;
1720
use metadata::METADATA_FILENAME;
@@ -20,10 +23,9 @@ use rustc::session::config::{RUST_CGU_EXT, Lto};
2023
use rustc::session::filesearch;
2124
use rustc::session::search_paths::PathKind;
2225
use rustc::session::Session;
23-
use rustc::middle::cstore::{NativeLibrary, LibSource, NativeLibraryKind};
26+
use rustc::middle::cstore::{NativeLibrary, NativeLibraryKind};
2427
use rustc::middle::dependency_format::Linkage;
25-
use rustc_codegen_ssa::CrateInfo;
26-
use CodegenResults;
28+
use rustc_codegen_ssa::CodegenResults;
2729
use rustc::util::common::time;
2830
use rustc_fs_util::fix_windows_verbatim_for_gcc;
2931
use rustc::hir::def_id::CrateNum;
@@ -34,6 +36,7 @@ use rustc_codegen_utils::linker::Linker;
3436
use rustc_codegen_utils::command::Command;
3537
use context::get_reloc_model;
3638
use llvm;
39+
use LlvmCodegenBackend;
3740

3841
use std::ascii;
3942
use std::char;
@@ -51,77 +54,11 @@ pub use rustc_codegen_utils::link::{find_crate_name, filename_for_input, default
5154
invalid_output_for_target, out_filename, check_file_is_writeable,
5255
filename_for_metadata};
5356

54-
// The third parameter is for env vars, used on windows to set up the
55-
// path for MSVC to find its DLLs, and gcc to find its bundled
56-
// toolchain
57-
pub fn get_linker(sess: &Session, linker: &Path, flavor: LinkerFlavor) -> (PathBuf, Command) {
58-
let msvc_tool = windows_registry::find_tool(&sess.opts.target_triple.triple(), "link.exe");
59-
60-
// If our linker looks like a batch script on Windows then to execute this
61-
// we'll need to spawn `cmd` explicitly. This is primarily done to handle
62-
// emscripten where the linker is `emcc.bat` and needs to be spawned as
63-
// `cmd /c emcc.bat ...`.
64-
//
65-
// This worked historically but is needed manually since #42436 (regression
66-
// was tagged as #42791) and some more info can be found on #44443 for
67-
// emscripten itself.
68-
let mut cmd = match linker.to_str() {
69-
Some(linker) if cfg!(windows) && linker.ends_with(".bat") => Command::bat_script(linker),
70-
_ => match flavor {
71-
LinkerFlavor::Lld(f) => Command::lld(linker, f),
72-
LinkerFlavor::Msvc
73-
if sess.opts.cg.linker.is_none() && sess.target.target.options.linker.is_none() =>
74-
{
75-
Command::new(msvc_tool.as_ref().map(|t| t.path()).unwrap_or(linker))
76-
},
77-
_ => Command::new(linker),
78-
}
79-
};
80-
81-
// The compiler's sysroot often has some bundled tools, so add it to the
82-
// PATH for the child.
83-
let mut new_path = sess.host_filesearch(PathKind::All)
84-
.get_tools_search_paths();
85-
let mut msvc_changed_path = false;
86-
if sess.target.target.options.is_like_msvc {
87-
if let Some(ref tool) = msvc_tool {
88-
cmd.args(tool.args());
89-
for &(ref k, ref v) in tool.env() {
90-
if k == "PATH" {
91-
new_path.extend(env::split_paths(v));
92-
msvc_changed_path = true;
93-
} else {
94-
cmd.env(k, v);
95-
}
96-
}
97-
}
98-
}
99-
100-
if !msvc_changed_path {
101-
if let Some(path) = env::var_os("PATH") {
102-
new_path.extend(env::split_paths(&path));
103-
}
104-
}
105-
cmd.env("PATH", env::join_paths(new_path).unwrap());
106-
107-
(linker.to_path_buf(), cmd)
108-
}
109-
110-
pub fn remove(sess: &Session, path: &Path) {
111-
match fs::remove_file(path) {
112-
Ok(..) => {}
113-
Err(e) => {
114-
sess.err(&format!("failed to remove {}: {}",
115-
path.display(),
116-
e));
117-
}
118-
}
119-
}
12057

12158
/// Perform the linkage portion of the compilation phase. This will generate all
12259
/// of the requested outputs for this compilation session.
12360
pub(crate) fn link_binary(sess: &Session,
124-
codegen_results: &CodegenResults,
61+
codegen_results: &CodegenResults<LlvmCodegenBackend>,
12562
outputs: &OutputFilenames,
12663
crate_name: &str) -> Vec<PathBuf> {
12764
let mut out_filenames = Vec::new();
@@ -220,62 +157,8 @@ fn preserve_objects_for_their_debuginfo(sess: &Session) -> bool {
220157
false
221158
}
222159

223-
pub(crate) fn each_linked_rlib(sess: &Session,
224-
info: &CrateInfo,
225-
f: &mut dyn FnMut(CrateNum, &Path)) -> Result<(), String> {
226-
let crates = info.used_crates_static.iter();
227-
let fmts = sess.dependency_formats.borrow();
228-
let fmts = fmts.get(&config::CrateType::Executable)
229-
.or_else(|| fmts.get(&config::CrateType::Staticlib))
230-
.or_else(|| fmts.get(&config::CrateType::Cdylib))
231-
.or_else(|| fmts.get(&config::CrateType::ProcMacro));
232-
let fmts = match fmts {
233-
Some(f) => f,
234-
None => return Err("could not find formats for rlibs".to_string())
235-
};
236-
for &(cnum, ref path) in crates {
237-
match fmts.get(cnum.as_usize() - 1) {
238-
Some(&Linkage::NotLinked) |
239-
Some(&Linkage::IncludedFromDylib) => continue,
240-
Some(_) => {}
241-
None => return Err("could not find formats for rlibs".to_string())
242-
}
243-
let name = &info.crate_name[&cnum];
244-
let path = match *path {
245-
LibSource::Some(ref p) => p,
246-
LibSource::MetadataOnly => {
247-
return Err(format!("could not find rlib for: `{}`, found rmeta (metadata) file",
248-
name))
249-
}
250-
LibSource::None => {
251-
return Err(format!("could not find rlib for: `{}`", name))
252-
}
253-
};
254-
f(cnum, &path);
255-
}
256-
Ok(())
257-
}
258-
259-
/// Returns a boolean indicating whether the specified crate should be ignored
260-
/// during LTO.
261-
///
262-
/// Crates ignored during LTO are not lumped together in the "massive object
263-
/// file" that we create and are linked in their normal rlib states. See
264-
/// comments below for what crates do not participate in LTO.
265-
///
266-
/// It's unusual for a crate to not participate in LTO. Typically only
267-
/// compiler-specific and unstable crates have a reason to not participate in
268-
/// LTO.
269-
pub(crate) fn ignored_for_lto(sess: &Session, info: &CrateInfo, cnum: CrateNum) -> bool {
270-
// If our target enables builtin function lowering in LLVM then the
271-
// crates providing these functions don't participate in LTO (e.g.
272-
// no_builtins or compiler builtins crates).
273-
!sess.target.target.options.no_builtins &&
274-
(info.is_no_builtins.contains(&cnum) || info.compiler_builtins == Some(cnum))
275-
}
276-
277160
fn link_binary_output(sess: &Session,
278-
codegen_results: &CodegenResults,
161+
codegen_results: &CodegenResults<LlvmCodegenBackend>,
279162
crate_type: config::CrateType,
280163
outputs: &OutputFilenames,
281164
crate_name: &str) -> Vec<PathBuf> {
@@ -362,8 +245,11 @@ fn archive_config<'a>(sess: &'a Session,
362245
/// building an `.rlib` (stomping over one another), or writing an `.rmeta` into a
363246
/// directory being searched for `extern crate` (observing an incomplete file).
364247
/// The returned path is the temporary file containing the complete metadata.
365-
fn emit_metadata<'a>(sess: &'a Session, codegen_results: &CodegenResults, tmpdir: &TempDir)
366-
-> PathBuf {
248+
fn emit_metadata<'a>(
249+
sess: &'a Session,
250+
codegen_results: &CodegenResults<LlvmCodegenBackend>,
251+
tmpdir: &TempDir
252+
) -> PathBuf {
367253
let out_filename = tmpdir.path().join(METADATA_FILENAME);
368254
let result = fs::write(&out_filename, &codegen_results.metadata.raw_data);
369255

@@ -386,7 +272,7 @@ enum RlibFlavor {
386272
// all of the object files from native libraries. This is done by unzipping
387273
// native libraries and inserting all of the contents into this archive.
388274
fn link_rlib<'a>(sess: &'a Session,
389-
codegen_results: &CodegenResults,
275+
codegen_results: &CodegenResults<LlvmCodegenBackend>,
390276
flavor: RlibFlavor,
391277
out_filename: &Path,
392278
tmpdir: &TempDir) -> ArchiveBuilder<'a> {
@@ -500,7 +386,7 @@ fn link_rlib<'a>(sess: &'a Session,
500386
// link in the metadata object file (and also don't prepare the archive with a
501387
// metadata file).
502388
fn link_staticlib(sess: &Session,
503-
codegen_results: &CodegenResults,
389+
codegen_results: &CodegenResults<LlvmCodegenBackend>,
504390
out_filename: &Path,
505391
tempdir: &TempDir) {
506392
let mut ab = link_rlib(sess,
@@ -585,77 +471,14 @@ fn print_native_static_libs(sess: &Session, all_native_libs: &[NativeLibrary]) {
585471
}
586472
}
587473

588-
pub fn linker_and_flavor(sess: &Session) -> (PathBuf, LinkerFlavor) {
589-
fn infer_from(
590-
sess: &Session,
591-
linker: Option<PathBuf>,
592-
flavor: Option<LinkerFlavor>,
593-
) -> Option<(PathBuf, LinkerFlavor)> {
594-
match (linker, flavor) {
595-
(Some(linker), Some(flavor)) => Some((linker, flavor)),
596-
// only the linker flavor is known; use the default linker for the selected flavor
597-
(None, Some(flavor)) => Some((PathBuf::from(match flavor {
598-
LinkerFlavor::Em => if cfg!(windows) { "emcc.bat" } else { "emcc" },
599-
LinkerFlavor::Gcc => "cc",
600-
LinkerFlavor::Ld => "ld",
601-
LinkerFlavor::Msvc => "link.exe",
602-
LinkerFlavor::Lld(_) => "lld",
603-
}), flavor)),
604-
(Some(linker), None) => {
605-
let stem = linker.file_stem().and_then(|stem| stem.to_str()).unwrap_or_else(|| {
606-
sess.fatal("couldn't extract file stem from specified linker");
607-
}).to_owned();
608-
609-
let flavor = if stem == "emcc" {
610-
LinkerFlavor::Em
611-
} else if stem == "gcc" || stem.ends_with("-gcc") {
612-
LinkerFlavor::Gcc
613-
} else if stem == "ld" || stem == "ld.lld" || stem.ends_with("-ld") {
614-
LinkerFlavor::Ld
615-
} else if stem == "link" || stem == "lld-link" {
616-
LinkerFlavor::Msvc
617-
} else if stem == "lld" || stem == "rust-lld" {
618-
LinkerFlavor::Lld(sess.target.target.options.lld_flavor)
619-
} else {
620-
// fall back to the value in the target spec
621-
sess.target.target.linker_flavor
622-
};
623-
624-
Some((linker, flavor))
625-
},
626-
(None, None) => None,
627-
}
628-
}
629-
630-
// linker and linker flavor specified via command line have precedence over what the target
631-
// specification specifies
632-
if let Some(ret) = infer_from(
633-
sess,
634-
sess.opts.cg.linker.clone(),
635-
sess.opts.debugging_opts.linker_flavor,
636-
) {
637-
return ret;
638-
}
639-
640-
if let Some(ret) = infer_from(
641-
sess,
642-
sess.target.target.options.linker.clone().map(PathBuf::from),
643-
Some(sess.target.target.linker_flavor),
644-
) {
645-
return ret;
646-
}
647-
648-
bug!("Not enough information provided to determine how to invoke the linker");
649-
}
650-
651474
// Create a dynamic library or executable
652475
//
653476
// This will invoke the system linker/cc to create the resulting file. This
654477
// links to all upstream files as well.
655478
fn link_natively(sess: &Session,
656479
crate_type: config::CrateType,
657480
out_filename: &Path,
658-
codegen_results: &CodegenResults,
481+
codegen_results: &CodegenResults<LlvmCodegenBackend>,
659482
tmpdir: &Path) {
660483
info!("preparing {:?} to {:?}", crate_type, out_filename);
661484
let (linker, flavor) = linker_and_flavor(sess);
@@ -1030,7 +853,7 @@ fn link_args(cmd: &mut dyn Linker,
1030853
crate_type: config::CrateType,
1031854
tmpdir: &Path,
1032855
out_filename: &Path,
1033-
codegen_results: &CodegenResults) {
856+
codegen_results: &CodegenResults<LlvmCodegenBackend>) {
1034857

1035858
// Linker plugins should be specified early in the list of arguments
1036859
cmd.cross_lang_lto();
@@ -1242,7 +1065,7 @@ fn link_args(cmd: &mut dyn Linker,
12421065
// may have their native library pulled in above.
12431066
fn add_local_native_libraries(cmd: &mut dyn Linker,
12441067
sess: &Session,
1245-
codegen_results: &CodegenResults) {
1068+
codegen_results: &CodegenResults<LlvmCodegenBackend>) {
12461069
sess.target_filesearch(PathKind::All).for_each_lib_search_path(|path, k| {
12471070
match k {
12481071
PathKind::Framework => { cmd.framework_path(path); }
@@ -1277,7 +1100,7 @@ fn add_local_native_libraries(cmd: &mut dyn Linker,
12771100
// the intermediate rlib version)
12781101
fn add_upstream_rust_crates(cmd: &mut dyn Linker,
12791102
sess: &Session,
1280-
codegen_results: &CodegenResults,
1103+
codegen_results: &CodegenResults<LlvmCodegenBackend>,
12811104
crate_type: config::CrateType,
12821105
tmpdir: &Path) {
12831106
// All of the heavy lifting has previously been accomplished by the
@@ -1401,7 +1224,7 @@ fn add_upstream_rust_crates(cmd: &mut dyn Linker,
14011224
// linking it.
14021225
fn link_sanitizer_runtime(cmd: &mut dyn Linker,
14031226
sess: &Session,
1404-
codegen_results: &CodegenResults,
1227+
codegen_results: &CodegenResults<LlvmCodegenBackend>,
14051228
tmpdir: &Path,
14061229
cnum: CrateNum) {
14071230
let src = &codegen_results.crate_info.used_crate_source[&cnum];
@@ -1470,7 +1293,7 @@ fn add_upstream_rust_crates(cmd: &mut dyn Linker,
14701293
// we're at the end of the dependency chain.
14711294
fn add_static_crate(cmd: &mut dyn Linker,
14721295
sess: &Session,
1473-
codegen_results: &CodegenResults,
1296+
codegen_results: &CodegenResults<LlvmCodegenBackend>,
14741297
tmpdir: &Path,
14751298
crate_type: config::CrateType,
14761299
cnum: CrateNum) {
@@ -1610,7 +1433,7 @@ fn add_upstream_rust_crates(cmd: &mut dyn Linker,
16101433
// also be resolved in the target crate.
16111434
fn add_upstream_native_libraries(cmd: &mut dyn Linker,
16121435
sess: &Session,
1613-
codegen_results: &CodegenResults,
1436+
codegen_results: &CodegenResults<LlvmCodegenBackend>,
16141437
crate_type: config::CrateType) {
16151438
// Be sure to use a topological sorting of crates because there may be
16161439
// interdependencies between native libraries. When passing -nodefaultlibs,

0 commit comments

Comments
 (0)