Skip to content

Commit

Permalink
Separating the back folder between backend-agnostic and LLVM-specific…
Browse files Browse the repository at this point in the history
… code
  • Loading branch information
denismerigoux authored and eddyb committed Nov 16, 2018
1 parent b25b804 commit b9e5cf9
Show file tree
Hide file tree
Showing 23 changed files with 2,724 additions and 2,467 deletions.
8 changes: 6 additions & 2 deletions src/Cargo.lock
Expand Up @@ -2129,6 +2129,12 @@ dependencies = [
[[package]]
name = "rustc_codegen_ssa"
version = "0.0.0"
dependencies = [
"cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
"memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "rustc_codegen_utils"
Expand All @@ -2137,13 +2143,11 @@ dependencies = [
"flate2 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc 0.0.0",
"rustc_allocator 0.0.0",
"rustc_data_structures 0.0.0",
"rustc_incremental 0.0.0",
"rustc_metadata 0.0.0",
"rustc_mir 0.0.0",
"rustc_target 0.0.0",
"serialize 0.0.0",
"syntax 0.0.0",
"syntax_pos 0.0.0",
]
Expand Down
4 changes: 2 additions & 2 deletions src/librustc_codegen_llvm/back/archive.rs
Expand Up @@ -18,6 +18,7 @@ use std::ptr;
use std::str;

use back::bytecode::RLIB_BYTECODE_EXTENSION;
use rustc_codegen_ssa::back::archive::find_library;
use libc;
use llvm::archive_ro::{ArchiveRO, Child};
use llvm::{self, ArchiveKind};
Expand Down Expand Up @@ -52,7 +53,6 @@ enum Addition {
},
}


fn is_relevant_child(c: &Child) -> bool {
match c.name() {
Some(name) => !name.contains("SYMDEF"),
Expand Down Expand Up @@ -107,7 +107,7 @@ impl<'a> ArchiveBuilder<'a> {
/// Adds all of the contents of a native library to this archive. This will
/// search in the relevant locations for a library named `name`.
pub fn add_native_library(&mut self, name: &str) {
let location = ::rustc_codegen_utils::find_library(name, &self.config.lib_search_paths,
let location = find_library(name, &self.config.lib_search_paths,
self.config.sess);
self.add_archive(&location, |_| false).unwrap_or_else(|e| {
self.config.sess.fatal(&format!("failed to add native library {}: {}",
Expand Down
199 changes: 11 additions & 188 deletions src/librustc_codegen_llvm/back/link.rs
Expand Up @@ -9,9 +9,12 @@
// except according to those terms.

use back::wasm;
use cc::windows_registry;
use super::archive::{ArchiveBuilder, ArchiveConfig};
use super::bytecode::RLIB_BYTECODE_EXTENSION;
use rustc_codegen_ssa::back::linker::Linker;
use rustc_codegen_ssa::back::link::{remove, ignored_for_lto, each_linked_rlib, linker_and_flavor,
get_linker};
use rustc_codegen_ssa::back::command::Command;
use super::rpath::RPathConfig;
use super::rpath;
use metadata::METADATA_FILENAME;
Expand All @@ -20,18 +23,15 @@ use rustc::session::config::{RUST_CGU_EXT, Lto};
use rustc::session::filesearch;
use rustc::session::search_paths::PathKind;
use rustc::session::Session;
use rustc::middle::cstore::{NativeLibrary, LibSource, NativeLibraryKind};
use rustc::middle::cstore::{NativeLibrary, NativeLibraryKind};
use rustc::middle::dependency_format::Linkage;
use rustc_codegen_ssa::CrateInfo;
use CodegenResults;
use rustc_codegen_ssa::CodegenResults;
use rustc::util::common::time;
use rustc_fs_util::fix_windows_verbatim_for_gcc;
use rustc::hir::def_id::CrateNum;
use tempfile::{Builder as TempFileBuilder, TempDir};
use rustc_target::spec::{PanicStrategy, RelroLevel, LinkerFlavor};
use rustc_data_structures::fx::FxHashSet;
use rustc_codegen_utils::linker::Linker;
use rustc_codegen_utils::command::Command;
use context::get_reloc_model;
use llvm;

Expand All @@ -51,69 +51,6 @@ pub use rustc_codegen_utils::link::{find_crate_name, filename_for_input, default
invalid_output_for_target, filename_for_metadata,
out_filename, check_file_is_writeable};

// 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
pub fn get_linker(sess: &Session, linker: &Path, flavor: LinkerFlavor) -> (PathBuf, 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.target.options.linker.is_none() =>
{
Command::new(msvc_tool.as_ref().map(|t| t.path()).unwrap_or(linker))
},
_ => Command::new(linker),
}
};

// 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();
let mut msvc_changed_path = false;
if sess.target.target.options.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());

(linker.to_path_buf(), cmd)
}

pub fn remove(sess: &Session, path: &Path) {
if let Err(e) = fs::remove_file(path) {
sess.err(&format!("failed to remove {}: {}",
path.display(),
e));
}
}

/// Perform the linkage portion of the compilation phase. This will generate all
/// of the requested outputs for this compilation session.
Expand Down Expand Up @@ -215,60 +152,6 @@ fn preserve_objects_for_their_debuginfo(sess: &Session) -> bool {
false
}

pub(crate) fn each_linked_rlib(sess: &Session,
info: &CrateInfo,
f: &mut dyn FnMut(CrateNum, &Path)) -> Result<(), String> {
let crates = info.used_crates_static.iter();
let fmts = sess.dependency_formats.borrow();
let fmts = fmts.get(&config::CrateType::Executable)
.or_else(|| fmts.get(&config::CrateType::Staticlib))
.or_else(|| fmts.get(&config::CrateType::Cdylib))
.or_else(|| fmts.get(&config::CrateType::ProcMacro));
let fmts = match fmts {
Some(f) => f,
None => return Err("could not find formats for rlibs".to_string())
};
for &(cnum, ref path) in crates {
match fmts.get(cnum.as_usize() - 1) {
Some(&Linkage::NotLinked) |
Some(&Linkage::IncludedFromDylib) => continue,
Some(_) => {}
None => return Err("could not find formats for rlibs".to_string())
}
let name = &info.crate_name[&cnum];
let path = match *path {
LibSource::Some(ref p) => p,
LibSource::MetadataOnly => {
return Err(format!("could not find rlib for: `{}`, found rmeta (metadata) file",
name))
}
LibSource::None => {
return Err(format!("could not find rlib for: `{}`", name))
}
};
f(cnum, &path);
}
Ok(())
}

/// Returns a boolean indicating whether the specified crate should be ignored
/// during LTO.
///
/// Crates ignored during LTO are not lumped together in the "massive object
/// file" that we create and are linked in their normal rlib states. See
/// comments below for what crates do not participate in LTO.
///
/// It's unusual for a crate to not participate in LTO. Typically only
/// compiler-specific and unstable crates have a reason to not participate in
/// LTO.
pub(crate) fn ignored_for_lto(sess: &Session, info: &CrateInfo, cnum: CrateNum) -> bool {
// If our target enables builtin function lowering in LLVM then the
// crates providing these functions don't participate in LTO (e.g.
// no_builtins or compiler builtins crates).
!sess.target.target.options.no_builtins &&
(info.compiler_builtins == Some(cnum) || info.is_no_builtins.contains(&cnum))
}

fn link_binary_output(sess: &Session,
codegen_results: &CodegenResults,
crate_type: config::CrateType,
Expand Down Expand Up @@ -353,8 +236,11 @@ fn archive_config<'a>(sess: &'a Session,
/// building an `.rlib` (stomping over one another), or writing an `.rmeta` into a
/// directory being searched for `extern crate` (observing an incomplete file).
/// The returned path is the temporary file containing the complete metadata.
fn emit_metadata<'a>(sess: &'a Session, codegen_results: &CodegenResults, tmpdir: &TempDir)
-> PathBuf {
fn emit_metadata<'a>(
sess: &'a Session,
codegen_results: &CodegenResults,
tmpdir: &TempDir
) -> PathBuf {
let out_filename = tmpdir.path().join(METADATA_FILENAME);
let result = fs::write(&out_filename, &codegen_results.metadata.raw_data);

Expand Down Expand Up @@ -576,69 +462,6 @@ fn print_native_static_libs(sess: &Session, all_native_libs: &[NativeLibrary]) {
}
}

pub fn linker_and_flavor(sess: &Session) -> (PathBuf, LinkerFlavor) {
fn infer_from(
sess: &Session,
linker: Option<PathBuf>,
flavor: Option<LinkerFlavor>,
) -> Option<(PathBuf, LinkerFlavor)> {
match (linker, flavor) {
(Some(linker), Some(flavor)) => Some((linker, flavor)),
// only the linker flavor is known; use the default linker for the selected flavor
(None, Some(flavor)) => Some((PathBuf::from(match flavor {
LinkerFlavor::Em => if cfg!(windows) { "emcc.bat" } else { "emcc" },
LinkerFlavor::Gcc => "cc",
LinkerFlavor::Ld => "ld",
LinkerFlavor::Msvc => "link.exe",
LinkerFlavor::Lld(_) => "lld",
}), flavor)),
(Some(linker), None) => {
let stem = linker.file_stem().and_then(|stem| stem.to_str()).unwrap_or_else(|| {
sess.fatal("couldn't extract file stem from specified linker");
}).to_owned();

let flavor = if stem == "emcc" {
LinkerFlavor::Em
} else if stem == "gcc" || stem.ends_with("-gcc") {
LinkerFlavor::Gcc
} else if stem == "ld" || stem == "ld.lld" || stem.ends_with("-ld") {
LinkerFlavor::Ld
} else if stem == "link" || stem == "lld-link" {
LinkerFlavor::Msvc
} else if stem == "lld" || stem == "rust-lld" {
LinkerFlavor::Lld(sess.target.target.options.lld_flavor)
} else {
// fall back to the value in the target spec
sess.target.target.linker_flavor
};

Some((linker, flavor))
},
(None, None) => None,
}
}

// linker and linker flavor specified via command line have precedence over what the target
// specification specifies
if let Some(ret) = infer_from(
sess,
sess.opts.cg.linker.clone(),
sess.opts.debugging_opts.linker_flavor,
) {
return ret;
}

if let Some(ret) = infer_from(
sess,
sess.target.target.options.linker.clone().map(PathBuf::from),
Some(sess.target.target.linker_flavor),
) {
return ret;
}

bug!("Not enough information provided to determine how to invoke the linker");
}

// Create a dynamic library or executable
//
// This will invoke the system linker/cc to create the resulting file. This
Expand Down

0 comments on commit b9e5cf9

Please sign in to comment.