]> git.lizzy.rs Git - rust.git/commitdiff
trans: move the linker support to compute symbols on-demand.
authorEduard Burtescu <edy.burt@gmail.com>
Tue, 24 May 2016 22:45:25 +0000 (01:45 +0300)
committerEduard Burtescu <edy.burt@gmail.com>
Tue, 24 May 2016 22:45:25 +0000 (01:45 +0300)
src/librustc_trans/back/link.rs
src/librustc_trans/back/linker.rs
src/librustc_trans/base.rs
src/librustc_trans/lib.rs

index 53cc03198292e825c191688e554eeb0f323b3a06..0a7c3b6fc8f499de14a44835e6e955e6538eb593 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 use super::archive::{ArchiveBuilder, ArchiveConfig};
-use super::linker::{Linker, GnuLinker, MsvcLinker};
+use super::linker::Linker;
 use super::rpath::RPathConfig;
 use super::rpath;
 use super::msvc;
@@ -637,13 +637,9 @@ fn link_natively(sess: &Session,
     }
 
     {
-        let mut linker = if sess.target.target.options.is_like_msvc {
-            Box::new(MsvcLinker { cmd: &mut cmd, sess: &sess }) as Box<Linker>
-        } else {
-            Box::new(GnuLinker { cmd: &mut cmd, sess: &sess }) as Box<Linker>
-        };
+        let mut linker = trans.linker_info.to_linker(&mut cmd, &sess);
         link_args(&mut *linker, sess, crate_type, tmpdir,
-                  objects, out_filename, trans, outputs);
+                  objects, out_filename, outputs);
         if !sess.target.target.options.no_compiler_rt {
             linker.link_staticlib("compiler-rt");
         }
@@ -712,7 +708,6 @@ fn link_args(cmd: &mut Linker,
              tmpdir: &Path,
              objects: &[PathBuf],
              out_filename: &Path,
-             trans: &CrateTranslation,
              outputs: &OutputFilenames) {
 
     // The default library location, we need this to find the runtime.
@@ -731,7 +726,7 @@ fn link_args(cmd: &mut Linker,
     // If we're building a dynamic library then some platforms need to make sure
     // that all symbols are exported correctly from the dynamic library.
     if crate_type != config::CrateTypeExecutable {
-        cmd.export_symbols(sess, trans, tmpdir, crate_type);
+        cmd.export_symbols(tmpdir, crate_type);
     }
 
     // When linking a dynamic library, we put the metadata into a section of the
index 50f6366e85c8680f8a9608146b99d190e729ec4e..cb990ead8e81e94ae0de9f5982d8817517e2e9d6 100644 (file)
 use std::path::{Path, PathBuf};
 use std::process::Command;
 
+use context::SharedCrateContext;
+use monomorphize::Instance;
+
 use back::archive;
 use middle::dependency_format::Linkage;
 use session::Session;
 use session::config::CrateType;
 use session::config;
 use syntax::ast;
-use CrateTranslation;
+
+/// For all the linkers we support, and information they might
+/// need out of the shared crate context before we get rid of it.
+pub struct LinkerInfo {
+    dylib_exports: Vec<String>,
+    cdylib_exports: Vec<String>
+}
+
+impl<'a, 'tcx> LinkerInfo {
+    pub fn new(scx: &SharedCrateContext<'a, 'tcx>,
+               reachable: &[String]) -> LinkerInfo {
+        LinkerInfo {
+            dylib_exports: exported_symbols(scx, reachable, CrateType::CrateTypeDylib),
+            cdylib_exports: exported_symbols(scx, reachable, CrateType::CrateTypeCdylib)
+        }
+    }
+
+    pub fn to_linker(&'a self,
+                     cmd: &'a mut Command,
+                     sess: &'a Session) -> Box<Linker+'a> {
+        if sess.target.target.options.is_like_msvc {
+            Box::new(MsvcLinker {
+                cmd: cmd,
+                sess: sess,
+                info: self
+            }) as Box<Linker>
+        } else {
+            Box::new(GnuLinker {
+                cmd: cmd,
+                sess: sess,
+                info: self
+            }) as Box<Linker>
+        }
+    }
+}
 
 /// Linker abstraction used by back::link to build up the command to invoke a
 /// linker.
@@ -53,16 +90,13 @@ pub trait Linker {
     fn hint_dynamic(&mut self);
     fn whole_archives(&mut self);
     fn no_whole_archives(&mut self);
-    fn export_symbols(&mut self,
-                      sess: &Session,
-                      trans: &CrateTranslation,
-                      tmpdir: &Path,
-                      crate_type: CrateType);
+    fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType);
 }
 
 pub struct GnuLinker<'a> {
-    pub cmd: &'a mut Command,
-    pub sess: &'a Session,
+    cmd: &'a mut Command,
+    sess: &'a Session,
+    info: &'a LinkerInfo
 }
 
 impl<'a> GnuLinker<'a> {
@@ -201,11 +235,7 @@ fn hint_dynamic(&mut self) {
         self.cmd.arg("-Wl,-Bdynamic");
     }
 
-    fn export_symbols(&mut self,
-                      sess: &Session,
-                      trans: &CrateTranslation,
-                      tmpdir: &Path,
-                      crate_type: CrateType) {
+    fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType) {
         // If we're compiling a dylib, then we let symbol visibility in object
         // files to take care of whether they're exported or not.
         //
@@ -225,13 +255,13 @@ fn export_symbols(&mut self,
         };
         let res = (|| -> io::Result<()> {
             let mut f = BufWriter::new(File::create(&path)?);
-            for sym in exported_symbols(sess, trans, crate_type) {
+            for sym in &self.info.cdylib_exports {
                 writeln!(f, "{}{}", prefix, sym)?;
             }
             Ok(())
         })();
         if let Err(e) = res {
-            sess.fatal(&format!("failed to write lib.def file: {}", e));
+            self.sess.fatal(&format!("failed to write lib.def file: {}", e));
         }
         let mut arg = OsString::new();
         if self.sess.target.target.options.is_like_osx {
@@ -245,8 +275,9 @@ fn export_symbols(&mut self,
 }
 
 pub struct MsvcLinker<'a> {
-    pub cmd: &'a mut Command,
-    pub sess: &'a Session,
+    cmd: &'a mut Command,
+    sess: &'a Session,
+    info: &'a LinkerInfo
 }
 
 impl<'a> Linker for MsvcLinker<'a> {
@@ -366,8 +397,6 @@ fn hint_dynamic(&mut self) {}
     // in which case they may continue to transitively be used and hence need
     // their symbols exported.
     fn export_symbols(&mut self,
-                      sess: &Session,
-                      trans: &CrateTranslation,
                       tmpdir: &Path,
                       crate_type: CrateType) {
         let path = tmpdir.join("lib.def");
@@ -378,15 +407,18 @@ fn export_symbols(&mut self,
             // straight to exports.
             writeln!(f, "LIBRARY")?;
             writeln!(f, "EXPORTS")?;
-
-            for sym in exported_symbols(sess, trans, crate_type) {
-                writeln!(f, "  {}", sym)?;
+            let symbols = if crate_type == CrateType::CrateTypeCdylib {
+                &self.info.cdylib_exports
+            } else {
+                &self.info.dylib_exports
+            };
+            for symbol in symbols {
+                writeln!(f, "  {}", symbol)?;
             }
-
             Ok(())
         })();
         if let Err(e) = res {
-            sess.fatal(&format!("failed to write lib.def file: {}", e));
+            self.sess.fatal(&format!("failed to write lib.def file: {}", e));
         }
         let mut arg = OsString::from("/DEF:");
         arg.push(path);
@@ -394,10 +426,23 @@ fn export_symbols(&mut self,
     }
 }
 
-fn exported_symbols(sess: &Session,
-                    trans: &CrateTranslation,
-                    crate_type: CrateType) -> Vec<String> {
-    let mut symbols = trans.reachable.iter().cloned().collect::<Vec<_>>();
+fn exported_symbols(scx: &SharedCrateContext,
+                    reachable: &[String],
+                    crate_type: CrateType)
+                    -> Vec<String> {
+    if !scx.sess().crate_types.borrow().contains(&crate_type) {
+        return vec![];
+    }
+
+    // See explanation in GnuLinker::export_symbols, for
+    // why we don't ever need dylib symbols on non-MSVC.
+    if crate_type == CrateType::CrateTypeDylib {
+        if !scx.sess().target.target.options.is_like_msvc {
+            return vec![];
+        }
+    }
+
+    let mut symbols = reachable.to_vec();
 
     // If we're producing anything other than a dylib then the `reachable` array
     // above is the exhaustive set of symbols we should be exporting.
@@ -409,10 +454,10 @@ fn exported_symbols(sess: &Session,
         return symbols
     }
 
-    let cstore = &sess.cstore;
-    let formats = sess.dependency_formats.borrow();
-    let upstream_symbols = formats[&crate_type].iter();
-    symbols.extend(upstream_symbols.enumerate().filter_map(|(i, f)| {
+    let cstore = &scx.sess().cstore;
+    let formats = scx.sess().dependency_formats.borrow();
+    let deps = formats[&crate_type].iter();
+    symbols.extend(deps.enumerate().filter_map(|(i, f)| {
         if *f == Linkage::Static {
             Some((i + 1) as ast::CrateNum)
         } else {
@@ -420,9 +465,8 @@ fn exported_symbols(sess: &Session,
         }
     }).flat_map(|cnum| {
         cstore.reachable_ids(cnum)
-    }).map(|did| {
-        cstore.item_symbol(did)
+    }).map(|did| -> String {
+        Instance::mono(scx, did).symbol_name(scx)
     }));
-
-    return symbols
+    symbols
 }
index 94ef80d3b858759d037cfeb3cf134d89151c9c25..84dd633a45265300f814bd32286f0a633b9d6d20 100644 (file)
@@ -31,6 +31,7 @@
 use super::ModuleTranslation;
 
 use back::link;
+use back::linker::LinkerInfo;
 use lint;
 use llvm::{BasicBlockRef, Linkage, ValueRef, Vector, get_param};
 use llvm;
@@ -2828,6 +2829,7 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     };
     let no_builtins = attr::contains_name(&krate.attrs, "no_builtins");
 
+    let linker_info = LinkerInfo::new(&shared_ccx, &reachable_symbols);
     CrateTranslation {
         modules: modules,
         metadata_module: metadata_module,
@@ -2835,6 +2837,7 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         metadata: metadata,
         reachable: reachable_symbols,
         no_builtins: no_builtins,
+        linker_info: linker_info
     }
 }
 
index bccb5aa050b511c60ffe7356efd6d3fd47b4d6c3..0188a6d54de2dc88ea0e71515d5f850b6fb3d774 100644 (file)
@@ -145,6 +145,7 @@ pub struct CrateTranslation {
     pub metadata: Vec<u8>,
     pub reachable: Vec<String>,
     pub no_builtins: bool,
+    pub linker_info: back::linker::LinkerInfo
 }
 
 __build_diagnostic_array! { librustc_trans, DIAGNOSTICS }