Skip to content

Commit b03bde9

Browse files
committed
trans: move the linker support to compute symbols on-demand.
1 parent c9a10bd commit b03bde9

File tree

4 files changed

+88
-45
lines changed

4 files changed

+88
-45
lines changed

src/librustc_trans/back/link.rs

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
// except according to those terms.
1010

1111
use super::archive::{ArchiveBuilder, ArchiveConfig};
12-
use super::linker::{Linker, GnuLinker, MsvcLinker};
12+
use super::linker::Linker;
1313
use super::rpath::RPathConfig;
1414
use super::rpath;
1515
use super::msvc;
@@ -637,13 +637,9 @@ fn link_natively(sess: &Session,
637637
}
638638

639639
{
640-
let mut linker = if sess.target.target.options.is_like_msvc {
641-
Box::new(MsvcLinker { cmd: &mut cmd, sess: &sess }) as Box<Linker>
642-
} else {
643-
Box::new(GnuLinker { cmd: &mut cmd, sess: &sess }) as Box<Linker>
644-
};
640+
let mut linker = trans.linker_info.to_linker(&mut cmd, &sess);
645641
link_args(&mut *linker, sess, crate_type, tmpdir,
646-
objects, out_filename, trans, outputs);
642+
objects, out_filename, outputs);
647643
if !sess.target.target.options.no_compiler_rt {
648644
linker.link_staticlib("compiler-rt");
649645
}
@@ -712,7 +708,6 @@ fn link_args(cmd: &mut Linker,
712708
tmpdir: &Path,
713709
objects: &[PathBuf],
714710
out_filename: &Path,
715-
trans: &CrateTranslation,
716711
outputs: &OutputFilenames) {
717712

718713
// The default library location, we need this to find the runtime.
@@ -731,7 +726,7 @@ fn link_args(cmd: &mut Linker,
731726
// If we're building a dynamic library then some platforms need to make sure
732727
// that all symbols are exported correctly from the dynamic library.
733728
if crate_type != config::CrateTypeExecutable {
734-
cmd.export_symbols(sess, trans, tmpdir, crate_type);
729+
cmd.export_symbols(tmpdir, crate_type);
735730
}
736731

737732
// When linking a dynamic library, we put the metadata into a section of the

src/librustc_trans/back/linker.rs

Lines changed: 80 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,50 @@ use std::io::prelude::*;
1515
use std::path::{Path, PathBuf};
1616
use std::process::Command;
1717

18+
use context::SharedCrateContext;
19+
use monomorphize::Instance;
20+
1821
use back::archive;
1922
use middle::dependency_format::Linkage;
2023
use session::Session;
2124
use session::config::CrateType;
2225
use session::config;
2326
use syntax::ast;
24-
use CrateTranslation;
27+
28+
/// For all the linkers we support, and information they might
29+
/// need out of the shared crate context before we get rid of it.
30+
pub struct LinkerInfo {
31+
dylib_exports: Vec<String>,
32+
cdylib_exports: Vec<String>
33+
}
34+
35+
impl<'a, 'tcx> LinkerInfo {
36+
pub fn new(scx: &SharedCrateContext<'a, 'tcx>,
37+
reachable: &[String]) -> LinkerInfo {
38+
LinkerInfo {
39+
dylib_exports: exported_symbols(scx, reachable, CrateType::CrateTypeDylib),
40+
cdylib_exports: exported_symbols(scx, reachable, CrateType::CrateTypeCdylib)
41+
}
42+
}
43+
44+
pub fn to_linker(&'a self,
45+
cmd: &'a mut Command,
46+
sess: &'a Session) -> Box<Linker+'a> {
47+
if sess.target.target.options.is_like_msvc {
48+
Box::new(MsvcLinker {
49+
cmd: cmd,
50+
sess: sess,
51+
info: self
52+
}) as Box<Linker>
53+
} else {
54+
Box::new(GnuLinker {
55+
cmd: cmd,
56+
sess: sess,
57+
info: self
58+
}) as Box<Linker>
59+
}
60+
}
61+
}
2562

2663
/// Linker abstraction used by back::link to build up the command to invoke a
2764
/// linker.
@@ -53,16 +90,13 @@ pub trait Linker {
5390
fn hint_dynamic(&mut self);
5491
fn whole_archives(&mut self);
5592
fn no_whole_archives(&mut self);
56-
fn export_symbols(&mut self,
57-
sess: &Session,
58-
trans: &CrateTranslation,
59-
tmpdir: &Path,
60-
crate_type: CrateType);
93+
fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType);
6194
}
6295

6396
pub struct GnuLinker<'a> {
64-
pub cmd: &'a mut Command,
65-
pub sess: &'a Session,
97+
cmd: &'a mut Command,
98+
sess: &'a Session,
99+
info: &'a LinkerInfo
66100
}
67101

68102
impl<'a> GnuLinker<'a> {
@@ -201,11 +235,7 @@ impl<'a> Linker for GnuLinker<'a> {
201235
self.cmd.arg("-Wl,-Bdynamic");
202236
}
203237

204-
fn export_symbols(&mut self,
205-
sess: &Session,
206-
trans: &CrateTranslation,
207-
tmpdir: &Path,
208-
crate_type: CrateType) {
238+
fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType) {
209239
// If we're compiling a dylib, then we let symbol visibility in object
210240
// files to take care of whether they're exported or not.
211241
//
@@ -225,13 +255,13 @@ impl<'a> Linker for GnuLinker<'a> {
225255
};
226256
let res = (|| -> io::Result<()> {
227257
let mut f = BufWriter::new(File::create(&path)?);
228-
for sym in exported_symbols(sess, trans, crate_type) {
258+
for sym in &self.info.cdylib_exports {
229259
writeln!(f, "{}{}", prefix, sym)?;
230260
}
231261
Ok(())
232262
})();
233263
if let Err(e) = res {
234-
sess.fatal(&format!("failed to write lib.def file: {}", e));
264+
self.sess.fatal(&format!("failed to write lib.def file: {}", e));
235265
}
236266
let mut arg = OsString::new();
237267
if self.sess.target.target.options.is_like_osx {
@@ -245,8 +275,9 @@ impl<'a> Linker for GnuLinker<'a> {
245275
}
246276

247277
pub struct MsvcLinker<'a> {
248-
pub cmd: &'a mut Command,
249-
pub sess: &'a Session,
278+
cmd: &'a mut Command,
279+
sess: &'a Session,
280+
info: &'a LinkerInfo
250281
}
251282

252283
impl<'a> Linker for MsvcLinker<'a> {
@@ -366,8 +397,6 @@ impl<'a> Linker for MsvcLinker<'a> {
366397
// in which case they may continue to transitively be used and hence need
367398
// their symbols exported.
368399
fn export_symbols(&mut self,
369-
sess: &Session,
370-
trans: &CrateTranslation,
371400
tmpdir: &Path,
372401
crate_type: CrateType) {
373402
let path = tmpdir.join("lib.def");
@@ -378,26 +407,42 @@ impl<'a> Linker for MsvcLinker<'a> {
378407
// straight to exports.
379408
writeln!(f, "LIBRARY")?;
380409
writeln!(f, "EXPORTS")?;
381-
382-
for sym in exported_symbols(sess, trans, crate_type) {
383-
writeln!(f, " {}", sym)?;
410+
let symbols = if crate_type == CrateType::CrateTypeCdylib {
411+
&self.info.cdylib_exports
412+
} else {
413+
&self.info.dylib_exports
414+
};
415+
for symbol in symbols {
416+
writeln!(f, " {}", symbol)?;
384417
}
385-
386418
Ok(())
387419
})();
388420
if let Err(e) = res {
389-
sess.fatal(&format!("failed to write lib.def file: {}", e));
421+
self.sess.fatal(&format!("failed to write lib.def file: {}", e));
390422
}
391423
let mut arg = OsString::from("/DEF:");
392424
arg.push(path);
393425
self.cmd.arg(&arg);
394426
}
395427
}
396428

397-
fn exported_symbols(sess: &Session,
398-
trans: &CrateTranslation,
399-
crate_type: CrateType) -> Vec<String> {
400-
let mut symbols = trans.reachable.iter().cloned().collect::<Vec<_>>();
429+
fn exported_symbols(scx: &SharedCrateContext,
430+
reachable: &[String],
431+
crate_type: CrateType)
432+
-> Vec<String> {
433+
if !scx.sess().crate_types.borrow().contains(&crate_type) {
434+
return vec![];
435+
}
436+
437+
// See explanation in GnuLinker::export_symbols, for
438+
// why we don't ever need dylib symbols on non-MSVC.
439+
if crate_type == CrateType::CrateTypeDylib {
440+
if !scx.sess().target.target.options.is_like_msvc {
441+
return vec![];
442+
}
443+
}
444+
445+
let mut symbols = reachable.to_vec();
401446

402447
// If we're producing anything other than a dylib then the `reachable` array
403448
// above is the exhaustive set of symbols we should be exporting.
@@ -409,20 +454,19 @@ fn exported_symbols(sess: &Session,
409454
return symbols
410455
}
411456

412-
let cstore = &sess.cstore;
413-
let formats = sess.dependency_formats.borrow();
414-
let upstream_symbols = formats[&crate_type].iter();
415-
symbols.extend(upstream_symbols.enumerate().filter_map(|(i, f)| {
457+
let cstore = &scx.sess().cstore;
458+
let formats = scx.sess().dependency_formats.borrow();
459+
let deps = formats[&crate_type].iter();
460+
symbols.extend(deps.enumerate().filter_map(|(i, f)| {
416461
if *f == Linkage::Static {
417462
Some((i + 1) as ast::CrateNum)
418463
} else {
419464
None
420465
}
421466
}).flat_map(|cnum| {
422467
cstore.reachable_ids(cnum)
423-
}).map(|did| {
424-
cstore.item_symbol(did)
468+
}).map(|did| -> String {
469+
Instance::mono(scx, did).symbol_name(scx)
425470
}));
426-
427-
return symbols
471+
symbols
428472
}

src/librustc_trans/base.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ use super::CrateTranslation;
3131
use super::ModuleTranslation;
3232

3333
use back::link;
34+
use back::linker::LinkerInfo;
3435
use lint;
3536
use llvm::{BasicBlockRef, Linkage, ValueRef, Vector, get_param};
3637
use llvm;
@@ -2828,13 +2829,15 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
28282829
};
28292830
let no_builtins = attr::contains_name(&krate.attrs, "no_builtins");
28302831

2832+
let linker_info = LinkerInfo::new(&shared_ccx, &reachable_symbols);
28312833
CrateTranslation {
28322834
modules: modules,
28332835
metadata_module: metadata_module,
28342836
link: link_meta,
28352837
metadata: metadata,
28362838
reachable: reachable_symbols,
28372839
no_builtins: no_builtins,
2840+
linker_info: linker_info
28382841
}
28392842
}
28402843

src/librustc_trans/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@ pub struct CrateTranslation {
145145
pub metadata: Vec<u8>,
146146
pub reachable: Vec<String>,
147147
pub no_builtins: bool,
148+
pub linker_info: back::linker::LinkerInfo
148149
}
149150

150151
__build_diagnostic_array! { librustc_trans, DIAGNOSTICS }

0 commit comments

Comments
 (0)