about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc_codegen_llvm/back/archive.rs91
-rw-r--r--src/librustc_codegen_llvm/back/link.rs77
-rw-r--r--src/librustc_codegen_ssa/back/archive.rs17
3 files changed, 101 insertions, 84 deletions
diff --git a/src/librustc_codegen_llvm/back/archive.rs b/src/librustc_codegen_llvm/back/archive.rs
index 8de0f9ac980..e0e26e9af25 100644
--- a/src/librustc_codegen_llvm/back/archive.rs
+++ b/src/librustc_codegen_llvm/back/archive.rs
@@ -10,10 +10,10 @@ use std::str;
 use crate::llvm::archive_ro::{ArchiveRO, Child};
 use crate::llvm::{self, ArchiveKind};
 use rustc_codegen_ssa::{METADATA_FILENAME, RLIB_BYTECODE_EXTENSION};
-use rustc_codegen_ssa::back::archive::find_library;
+use rustc_codegen_ssa::back::archive::{ArchiveBuilder, find_library};
 use rustc::session::Session;
 
-pub struct ArchiveConfig<'a> {
+struct ArchiveConfig<'a> {
     pub sess: &'a Session,
     pub dst: PathBuf,
     pub src: Option<PathBuf>,
@@ -22,7 +22,7 @@ pub struct ArchiveConfig<'a> {
 
 /// Helper for adding many files to an archive.
 #[must_use = "must call build() to finish building the archive"]
-pub struct ArchiveBuilder<'a> {
+pub struct LlvmArchiveBuilder<'a> {
     config: ArchiveConfig<'a>,
     removals: Vec<String>,
     additions: Vec<Addition>,
@@ -48,11 +48,26 @@ fn is_relevant_child(c: &Child<'_>) -> bool {
     }
 }
 
-impl<'a> ArchiveBuilder<'a> {
+fn archive_config<'a>(sess: &'a Session,
+                      output: &Path,
+                      input: Option<&Path>) -> ArchiveConfig<'a> {
+    use rustc_codegen_ssa::back::link::archive_search_paths;
+    ArchiveConfig {
+        sess,
+        dst: output.to_path_buf(),
+        src: input.map(|p| p.to_path_buf()),
+        lib_search_paths: archive_search_paths(sess),
+    }
+}
+
+impl<'a> ArchiveBuilder<'a> for LlvmArchiveBuilder<'a> {
     /// Creates a new static archive, ready for modifying the archive specified
     /// by `config`.
-    pub fn new(config: ArchiveConfig<'a>) -> ArchiveBuilder<'a> {
-        ArchiveBuilder {
+    fn new(sess: &'a Session,
+            output: &Path,
+            input: Option<&Path>) -> LlvmArchiveBuilder<'a> {
+        let config = archive_config(sess, output, input);
+        LlvmArchiveBuilder {
             config,
             removals: Vec::new(),
             additions: Vec::new(),
@@ -62,12 +77,12 @@ impl<'a> ArchiveBuilder<'a> {
     }
 
     /// Removes a file from this archive
-    pub fn remove_file(&mut self, file: &str) {
+    fn remove_file(&mut self, file: &str) {
         self.removals.push(file.to_string());
     }
 
     /// Lists all files in an archive
-    pub fn src_files(&mut self) -> Vec<String> {
+    fn src_files(&mut self) -> Vec<String> {
         if self.src_archive().is_none() {
             return Vec::new()
         }
@@ -83,18 +98,9 @@ impl<'a> ArchiveBuilder<'a> {
                .collect()
     }
 
-    fn src_archive(&mut self) -> Option<&ArchiveRO> {
-        if let Some(ref a) = self.src_archive {
-            return a.as_ref()
-        }
-        let src = self.config.src.as_ref()?;
-        self.src_archive = Some(ArchiveRO::open(src).ok());
-        self.src_archive.as_ref().unwrap().as_ref()
-    }
-
     /// 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) {
+    fn add_native_library(&mut self, name: &str) {
         let location = find_library(name, &self.config.lib_search_paths,
                                     self.config.sess);
         self.add_archive(&location, |_| false).unwrap_or_else(|e| {
@@ -108,7 +114,7 @@ impl<'a> ArchiveBuilder<'a> {
     ///
     /// This ignores adding the bytecode from the rlib, and if LTO is enabled
     /// then the object file also isn't added.
-    pub fn add_rlib(&mut self,
+    fn add_rlib(&mut self,
                     rlib: &Path,
                     name: &str,
                     lto: bool,
@@ -140,23 +146,8 @@ impl<'a> ArchiveBuilder<'a> {
         })
     }
 
-    fn add_archive<F>(&mut self, archive: &Path, skip: F)
-                      -> io::Result<()>
-        where F: FnMut(&str) -> bool + 'static
-    {
-        let archive = match ArchiveRO::open(archive) {
-            Ok(ar) => ar,
-            Err(e) => return Err(io::Error::new(io::ErrorKind::Other, e)),
-        };
-        self.additions.push(Addition::Archive {
-            archive,
-            skip: Box::new(skip),
-        });
-        Ok(())
-    }
-
     /// Adds an arbitrary file to this archive
-    pub fn add_file(&mut self, file: &Path) {
+    fn add_file(&mut self, file: &Path) {
         let name = file.file_name().unwrap().to_str().unwrap();
         self.additions.push(Addition::File {
             path: file.to_path_buf(),
@@ -166,13 +157,13 @@ impl<'a> ArchiveBuilder<'a> {
 
     /// Indicate that the next call to `build` should update all symbols in
     /// the archive (equivalent to running 'ar s' over it).
-    pub fn update_symbols(&mut self) {
+    fn update_symbols(&mut self) {
         self.should_update_symbols = true;
     }
 
     /// Combine the provided files, rlibs, and native libraries into a single
     /// `Archive`.
-    pub fn build(&mut self) {
+    fn build(mut self) {
         let kind = self.llvm_archive_kind().unwrap_or_else(|kind|
             self.config.sess.fatal(&format!("Don't know how to build archive of type: {}", kind)));
 
@@ -181,6 +172,32 @@ impl<'a> ArchiveBuilder<'a> {
         }
 
     }
+}
+
+impl<'a> LlvmArchiveBuilder<'a> {
+    fn src_archive(&mut self) -> Option<&ArchiveRO> {
+        if let Some(ref a) = self.src_archive {
+            return a.as_ref()
+        }
+        let src = self.config.src.as_ref()?;
+        self.src_archive = Some(ArchiveRO::open(src).ok());
+        self.src_archive.as_ref().unwrap().as_ref()
+    }
+
+    fn add_archive<F>(&mut self, archive: &Path, skip: F)
+                      -> io::Result<()>
+        where F: FnMut(&str) -> bool + 'static
+    {
+        let archive = match ArchiveRO::open(archive) {
+            Ok(ar) => ar,
+            Err(e) => return Err(io::Error::new(io::ErrorKind::Other, e)),
+        };
+        self.additions.push(Addition::Archive {
+            archive,
+            skip: Box::new(skip),
+        });
+        Ok(())
+    }
 
     fn llvm_archive_kind(&self) -> Result<ArchiveKind, &str> {
         let kind = &*self.config.sess.target.target.options.archive_format;
diff --git a/src/librustc_codegen_llvm/back/link.rs b/src/librustc_codegen_llvm/back/link.rs
index a5934d0e709..3658bb11862 100644
--- a/src/librustc_codegen_llvm/back/link.rs
+++ b/src/librustc_codegen_llvm/back/link.rs
@@ -1,10 +1,11 @@
-use super::archive::{ArchiveBuilder, ArchiveConfig};
+use super::archive::LlvmArchiveBuilder;
 use super::rpath::RPathConfig;
 use super::rpath;
 use crate::back::wasm;
 use crate::context::get_reloc_model;
 use crate::llvm;
 use rustc_codegen_ssa::{METADATA_FILENAME, RLIB_BYTECODE_EXTENSION};
+use rustc_codegen_ssa::back::archive::ArchiveBuilder;
 use rustc_codegen_ssa::back::linker::Linker;
 use rustc_codegen_ssa::back::link::*;
 use rustc_codegen_ssa::back::command::Command;
@@ -31,14 +32,11 @@ use std::io;
 use std::path::{Path, PathBuf};
 use std::str;
 
-pub use rustc_codegen_utils::link::{find_crate_name, filename_for_input, default_output_for_target,
-                                    invalid_output_for_target, filename_for_metadata,
-                                    out_filename, check_file_is_writeable};
-
+pub use rustc_codegen_utils::link::*;
 
 /// Performs the linkage portion of the compilation phase. This will generate all
 /// of the requested outputs for this compilation session.
-pub(crate) fn link_binary(sess: &Session,
+pub(crate) fn link_binary<'a>(sess: &'a Session,
                           codegen_results: &CodegenResults,
                           outputs: &OutputFilenames,
                           crate_name: &str) -> Vec<PathBuf> {
@@ -56,7 +54,7 @@ pub(crate) fn link_binary(sess: &Session,
            bug!("invalid output type `{:?}` for target os `{}`",
                 crate_type, sess.opts.target_triple);
         }
-        let out_files = link_binary_output(sess,
+        let out_files = link_binary_output::<LlvmArchiveBuilder<'a>>(sess,
                                            codegen_results,
                                            crate_type,
                                            outputs,
@@ -90,7 +88,7 @@ pub(crate) fn link_binary(sess: &Session,
     out_filenames
 }
 
-fn link_binary_output(sess: &Session,
+fn link_binary_output<'a, B: ArchiveBuilder<'a>>(sess: &'a Session,
                       codegen_results: &CodegenResults,
                       crate_type: config::CrateType,
                       outputs: &OutputFilenames,
@@ -126,17 +124,17 @@ fn link_binary_output(sess: &Session,
         let out_filename = out_filename(sess, crate_type, outputs, crate_name);
         match crate_type {
             config::CrateType::Rlib => {
-                link_rlib(sess,
+                link_rlib::<B>(sess,
                           codegen_results,
                           RlibFlavor::Normal,
                           &out_filename,
                           &tmpdir).build();
             }
             config::CrateType::Staticlib => {
-                link_staticlib(sess, codegen_results, &out_filename, &tmpdir);
+                link_staticlib::<B>(sess, codegen_results, &out_filename, &tmpdir);
             }
             _ => {
-                link_natively(sess, crate_type, &out_filename, codegen_results, tmpdir.path());
+                link_natively::<B>(sess, crate_type, &out_filename, codegen_results, tmpdir.path());
             }
         }
         out_filenames.push(out_filename);
@@ -149,17 +147,6 @@ fn link_binary_output(sess: &Session,
     out_filenames
 }
 
-fn archive_config<'a>(sess: &'a Session,
-                      output: &Path,
-                      input: Option<&Path>) -> ArchiveConfig<'a> {
-    ArchiveConfig {
-        sess,
-        dst: output.to_path_buf(),
-        src: input.map(|p| p.to_path_buf()),
-        lib_search_paths: archive_search_paths(sess),
-    }
-}
-
 /// We use a temp directory here to avoid races between concurrent rustc processes,
 /// such as builds in the same directory using the same filename for metadata while
 /// building an `.rlib` (stomping over one another), or writing an `.rmeta` into a
@@ -191,13 +178,13 @@ enum RlibFlavor {
 // rlib primarily contains the object file of the crate, but it also contains
 // all of the object files from native libraries. This is done by unzipping
 // native libraries and inserting all of the contents into this archive.
-fn link_rlib<'a>(sess: &'a Session,
+fn link_rlib<'a, B: ArchiveBuilder<'a>>(sess: &'a Session,
                  codegen_results: &CodegenResults,
                  flavor: RlibFlavor,
                  out_filename: &Path,
-                 tmpdir: &TempDir) -> ArchiveBuilder<'a> {
+                 tmpdir: &TempDir) -> B {
     info!("preparing rlib to {:?}", out_filename);
-    let mut ab = ArchiveBuilder::new(archive_config(sess, out_filename, None));
+    let mut ab = <B as ArchiveBuilder>::new(sess, out_filename, None);
 
     for obj in codegen_results.modules.iter().filter_map(|m| m.object.as_ref()) {
         ab.add_file(obj);
@@ -305,11 +292,11 @@ fn link_rlib<'a>(sess: &'a Session,
 // There's no need to include metadata in a static archive, so ensure to not
 // link in the metadata object file (and also don't prepare the archive with a
 // metadata file).
-fn link_staticlib(sess: &Session,
+fn link_staticlib<'a, B: ArchiveBuilder<'a>>(sess: &'a Session,
                   codegen_results: &CodegenResults,
                   out_filename: &Path,
                   tempdir: &TempDir) {
-    let mut ab = link_rlib(sess,
+    let mut ab = link_rlib::<B>(sess,
                            codegen_results,
                            RlibFlavor::StaticlibBase,
                            out_filename,
@@ -363,7 +350,7 @@ fn link_staticlib(sess: &Session,
 //
 // This will invoke the system linker/cc to create the resulting file. This
 // links to all upstream files as well.
-fn link_natively(sess: &Session,
+fn link_natively<'a, B: ArchiveBuilder<'a>>(sess: &'a Session,
                  crate_type: config::CrateType,
                  out_filename: &Path,
                  codegen_results: &CodegenResults,
@@ -422,7 +409,7 @@ fn link_natively(sess: &Session,
     {
         let target_cpu = crate::llvm_util::target_cpu(sess);
         let mut linker = codegen_results.linker_info.to_linker(cmd, &sess, flavor, target_cpu);
-        link_args(&mut *linker, flavor, sess, crate_type, tmpdir,
+        link_args::<B>(&mut *linker, flavor, sess, crate_type, tmpdir,
                   out_filename, codegen_results);
         cmd = linker.finalize();
     }
@@ -603,9 +590,9 @@ fn link_natively(sess: &Session,
     }
 }
 
-fn link_args(cmd: &mut dyn Linker,
+fn link_args<'a, B: ArchiveBuilder<'a>>(cmd: &mut dyn Linker,
              flavor: LinkerFlavor,
-             sess: &Session,
+             sess: &'a Session,
              crate_type: config::CrateType,
              tmpdir: &Path,
              out_filename: &Path,
@@ -759,7 +746,7 @@ fn link_args(cmd: &mut dyn Linker,
     // in this DAG so far because they're only dylibs and dylibs can only depend
     // on other dylibs (e.g., other native deps).
     add_local_native_libraries(cmd, sess, codegen_results);
-    add_upstream_rust_crates(cmd, sess, codegen_results, crate_type, tmpdir);
+    add_upstream_rust_crates::<B>(cmd, sess, codegen_results, crate_type, tmpdir);
     add_upstream_native_libraries(cmd, sess, codegen_results, crate_type);
 
     // Tell the linker what we're doing.
@@ -812,8 +799,8 @@ fn link_args(cmd: &mut dyn Linker,
 // Rust crates are not considered at all when creating an rlib output. All
 // dependencies will be linked when producing the final output (instead of
 // the intermediate rlib version)
-fn add_upstream_rust_crates(cmd: &mut dyn Linker,
-                            sess: &Session,
+fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>(cmd: &mut dyn Linker,
+                            sess: &'a Session,
                             codegen_results: &CodegenResults,
                             crate_type: config::CrateType,
                             tmpdir: &Path) {
@@ -888,10 +875,10 @@ fn add_upstream_rust_crates(cmd: &mut dyn Linker,
         let src = &codegen_results.crate_info.used_crate_source[&cnum];
         match data[cnum.as_usize() - 1] {
             _ if codegen_results.crate_info.profiler_runtime == Some(cnum) => {
-                add_static_crate(cmd, sess, codegen_results, tmpdir, crate_type, cnum);
+                add_static_crate::<B>(cmd, sess, codegen_results, tmpdir, crate_type, cnum);
             }
             _ if codegen_results.crate_info.sanitizer_runtime == Some(cnum) => {
-                link_sanitizer_runtime(cmd, sess, codegen_results, tmpdir, cnum);
+                link_sanitizer_runtime::<B>(cmd, sess, codegen_results, tmpdir, cnum);
             }
             // compiler-builtins are always placed last to ensure that they're
             // linked correctly.
@@ -902,7 +889,7 @@ fn add_upstream_rust_crates(cmd: &mut dyn Linker,
             Linkage::NotLinked |
             Linkage::IncludedFromDylib => {}
             Linkage::Static => {
-                add_static_crate(cmd, sess, codegen_results, tmpdir, crate_type, cnum);
+                add_static_crate::<B>(cmd, sess, codegen_results, tmpdir, crate_type, cnum);
             }
             Linkage::Dynamic => {
                 add_dynamic_crate(cmd, sess, &src.dylib.as_ref().unwrap().0)
@@ -920,7 +907,7 @@ fn add_upstream_rust_crates(cmd: &mut dyn Linker,
     // was already "included" in a dylib (e.g., `libstd` when `-C prefer-dynamic`
     // is used)
     if let Some(cnum) = compiler_builtins {
-        add_static_crate(cmd, sess, codegen_results, tmpdir, crate_type, cnum);
+        add_static_crate::<B>(cmd, sess, codegen_results, tmpdir, crate_type, cnum);
     }
 
     // Converts a library file-stem into a cc -l argument
@@ -936,8 +923,8 @@ fn add_upstream_rust_crates(cmd: &mut dyn Linker,
     // it's packed in a .rlib, it contains stuff that are not objects that will
     // make the linker error. So we must remove those bits from the .rlib before
     // linking it.
-    fn link_sanitizer_runtime(cmd: &mut dyn Linker,
-                              sess: &Session,
+    fn link_sanitizer_runtime<'a, B: ArchiveBuilder<'a>>(cmd: &mut dyn Linker,
+                              sess: &'a Session,
                               codegen_results: &CodegenResults,
                               tmpdir: &Path,
                               cnum: CrateNum) {
@@ -957,8 +944,7 @@ fn add_upstream_rust_crates(cmd: &mut dyn Linker,
         }
 
         let dst = tmpdir.join(cratepath.file_name().unwrap());
-        let cfg = archive_config(sess, &dst, Some(cratepath));
-        let mut archive = ArchiveBuilder::new(cfg);
+        let mut archive = <B as ArchiveBuilder>::new(sess, &dst, Some(cratepath));
         archive.update_symbols();
 
         for f in archive.src_files() {
@@ -1004,8 +990,8 @@ fn add_upstream_rust_crates(cmd: &mut dyn Linker,
     // (aka we're making an executable), we can just pass the rlib blindly to
     // the linker (fast) because it's fine if it's not actually included as
     // we're at the end of the dependency chain.
-    fn add_static_crate(cmd: &mut dyn Linker,
-                        sess: &Session,
+    fn add_static_crate<'a, B: ArchiveBuilder<'a>>(cmd: &mut dyn Linker,
+                        sess: &'a Session,
                         codegen_results: &CodegenResults,
                         tmpdir: &Path,
                         crate_type: config::CrateType,
@@ -1034,8 +1020,7 @@ fn add_upstream_rust_crates(cmd: &mut dyn Linker,
         let name = &name[3..name.len() - 5]; // chop off lib/.rlib
 
         time_ext(sess.time_extended(), Some(sess), &format!("altering {}.rlib", name), || {
-            let cfg = archive_config(sess, &dst, Some(cratepath));
-            let mut archive = ArchiveBuilder::new(cfg);
+            let mut archive = <B as ArchiveBuilder>::new(sess, &dst, Some(cratepath));
             archive.update_symbols();
 
             let mut any_objects = false;
diff --git a/src/librustc_codegen_ssa/back/archive.rs b/src/librustc_codegen_ssa/back/archive.rs
index 0a16d1b03e2..cfe75b7b9bc 100644
--- a/src/librustc_codegen_ssa/back/archive.rs
+++ b/src/librustc_codegen_ssa/back/archive.rs
@@ -1,6 +1,7 @@
 use rustc::session::Session;
 
-use std::path::PathBuf;
+use std::io;
+use std::path::{Path, PathBuf};
 
 pub fn find_library(name: &str, search_paths: &[PathBuf], sess: &Session)
                     -> PathBuf {
@@ -24,3 +25,17 @@ pub fn find_library(name: &str, search_paths: &[PathBuf], sess: &Session)
     sess.fatal(&format!("could not find native static library `{}`, \
                          perhaps an -L flag is missing?", name));
 }
+
+pub trait ArchiveBuilder<'a> {
+    fn new(sess: &'a Session, output: &Path, input: Option<&Path>) -> Self;
+
+    fn add_file(&mut self, path: &Path);
+    fn remove_file(&mut self, name: &str);
+    fn src_files(&mut self) -> Vec<String>;
+
+    fn add_rlib(&mut self, path: &Path, name: &str, lto: bool, skip_objects: bool) -> io::Result<()>;
+    fn add_native_library(&mut self, name: &str);
+    fn update_symbols(&mut self);
+
+    fn build(self);
+}