Skip to content

Commit 133aeac

Browse files
Refactor symbol export list generation.
1 parent 5fd7c2b commit 133aeac

File tree

9 files changed

+371
-170
lines changed

9 files changed

+371
-170
lines changed

src/librustc/middle/cstore.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,7 @@ pub trait CrateStore<'tcx> {
328328
fn crate_hash(&self, cnum: CrateNum) -> Svh;
329329
fn crate_disambiguator(&self, cnum: CrateNum) -> Symbol;
330330
fn plugin_registrar_fn(&self, cnum: CrateNum) -> Option<DefId>;
331+
fn derive_registrar_fn(&self, cnum: CrateNum) -> Option<DefId>;
331332
fn native_libraries(&self, cnum: CrateNum) -> Vec<NativeLibrary>;
332333
fn exported_symbols(&self, cnum: CrateNum) -> Vec<DefId>;
333334
fn is_no_builtins(&self, cnum: CrateNum) -> bool;
@@ -491,6 +492,8 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore {
491492
-> Symbol { bug!("crate_disambiguator") }
492493
fn plugin_registrar_fn(&self, cnum: CrateNum) -> Option<DefId>
493494
{ bug!("plugin_registrar_fn") }
495+
fn derive_registrar_fn(&self, cnum: CrateNum) -> Option<DefId>
496+
{ bug!("derive_registrar_fn") }
494497
fn native_libraries(&self, cnum: CrateNum) -> Vec<NativeLibrary>
495498
{ bug!("native_libraries") }
496499
fn exported_symbols(&self, cnum: CrateNum) -> Vec<DefId> { bug!("exported_symbols") }

src/librustc_metadata/cstore_impl.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,14 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore {
306306
})
307307
}
308308

309+
fn derive_registrar_fn(&self, cnum: CrateNum) -> Option<DefId>
310+
{
311+
self.get_crate_data(cnum).root.macro_derive_registrar.map(|index| DefId {
312+
krate: cnum,
313+
index: index
314+
})
315+
}
316+
309317
fn native_libraries(&self, cnum: CrateNum) -> Vec<NativeLibrary>
310318
{
311319
self.get_crate_data(cnum).get_native_libraries()

src/librustc_trans/back/linker.rs

Lines changed: 20 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,11 @@ use std::path::{Path, PathBuf};
1717
use std::process::Command;
1818

1919
use context::SharedCrateContext;
20-
use monomorphize::Instance;
2120

2221
use back::archive;
22+
use back::symbol_export::{self, ExportedSymbols};
2323
use middle::dependency_format::Linkage;
24-
use rustc::hir::def_id::CrateNum;
24+
use rustc::hir::def_id::{LOCAL_CRATE, CrateNum};
2525
use session::Session;
2626
use session::config::CrateType;
2727
use session::config;
@@ -34,7 +34,7 @@ pub struct LinkerInfo {
3434

3535
impl<'a, 'tcx> LinkerInfo {
3636
pub fn new(scx: &SharedCrateContext<'a, 'tcx>,
37-
exports: &[String]) -> LinkerInfo {
37+
exports: &ExportedSymbols) -> LinkerInfo {
3838
LinkerInfo {
3939
exports: scx.sess().crate_types.borrow().iter().map(|&c| {
4040
(c, exported_symbols(scx, exports, c))
@@ -473,43 +473,29 @@ impl<'a> Linker for MsvcLinker<'a> {
473473
}
474474

475475
fn exported_symbols(scx: &SharedCrateContext,
476-
exported_symbols: &[String],
476+
exported_symbols: &ExportedSymbols,
477477
crate_type: CrateType)
478478
-> Vec<String> {
479-
// See explanation in GnuLinker::export_symbols, for
480-
// why we don't ever need dylib symbols on non-MSVC.
481-
if crate_type == CrateType::CrateTypeDylib ||
482-
crate_type == CrateType::CrateTypeProcMacro {
483-
if !scx.sess().target.target.options.is_like_msvc {
484-
return vec![];
485-
}
486-
}
487-
488-
let mut symbols = exported_symbols.to_vec();
479+
let export_threshold = symbol_export::crate_export_threshold(crate_type);
489480

490-
// If we're producing anything other than a dylib then the `reachable` array
491-
// above is the exhaustive set of symbols we should be exporting.
492-
//
493-
// For dylibs, however, we need to take a look at how all upstream crates
494-
// are linked into this dynamic library. For all statically linked
495-
// libraries we take all their reachable symbols and emit them as well.
496-
if crate_type != CrateType::CrateTypeDylib {
497-
return symbols
498-
}
481+
let mut symbols = Vec::new();
482+
exported_symbols.for_each_exported_symbol(LOCAL_CRATE, export_threshold, |name, _| {
483+
symbols.push(name.to_owned());
484+
});
499485

500-
let cstore = &scx.sess().cstore;
501486
let formats = scx.sess().dependency_formats.borrow();
502487
let deps = formats[&crate_type].iter();
503-
symbols.extend(deps.enumerate().filter_map(|(i, f)| {
504-
if *f == Linkage::Static {
505-
Some(CrateNum::new(i + 1))
506-
} else {
507-
None
488+
489+
for (index, dep_format) in deps.enumerate() {
490+
let cnum = CrateNum::new(index + 1);
491+
// For each dependency that we are linking to statically ...
492+
if *dep_format == Linkage::Static {
493+
// ... we add its symbol list to our export list.
494+
exported_symbols.for_each_exported_symbol(cnum, export_threshold, |name, _| {
495+
symbols.push(name.to_owned());
496+
})
508497
}
509-
}).flat_map(|cnum| {
510-
cstore.exported_symbols(cnum)
511-
}).map(|did| -> String {
512-
Instance::mono(scx, did).symbol_name(scx)
513-
}));
498+
}
499+
514500
symbols
515501
}

src/librustc_trans/back/lto.rs

Lines changed: 50 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,16 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
use super::link;
12-
use super::write;
11+
use back::link;
12+
use back::write;
13+
use back::symbol_export::{self, ExportedSymbols};
1314
use rustc::session::{self, config};
1415
use llvm;
1516
use llvm::archive_ro::ArchiveRO;
1617
use llvm::{ModuleRef, TargetMachineRef, True, False};
1718
use rustc::util::common::time;
1819
use rustc::util::common::path2cstr;
20+
use rustc::hir::def_id::LOCAL_CRATE;
1921
use back::write::{ModuleConfig, with_llvm_pmb};
2022

2123
use libc;
@@ -24,8 +26,23 @@ use flate;
2426
use std::ffi::CString;
2527
use std::path::Path;
2628

27-
pub fn run(sess: &session::Session, llmod: ModuleRef,
28-
tm: TargetMachineRef, exported_symbols: &[String],
29+
pub fn crate_type_allows_lto(crate_type: config::CrateType) -> bool {
30+
match crate_type {
31+
config::CrateTypeExecutable |
32+
config::CrateTypeStaticlib |
33+
config::CrateTypeCdylib => true,
34+
35+
config::CrateTypeDylib |
36+
config::CrateTypeRlib |
37+
config::CrateTypeMetadata |
38+
config::CrateTypeProcMacro => false,
39+
}
40+
}
41+
42+
pub fn run(sess: &session::Session,
43+
llmod: ModuleRef,
44+
tm: TargetMachineRef,
45+
exported_symbols: &ExportedSymbols,
2946
config: &ModuleConfig,
3047
temp_no_opt_bc_filename: &Path) {
3148
if sess.opts.cg.prefer_dynamic {
@@ -38,17 +55,31 @@ pub fn run(sess: &session::Session, llmod: ModuleRef,
3855

3956
// Make sure we actually can run LTO
4057
for crate_type in sess.crate_types.borrow().iter() {
41-
match *crate_type {
42-
config::CrateTypeExecutable |
43-
config::CrateTypeCdylib |
44-
config::CrateTypeStaticlib => {}
45-
_ => {
46-
sess.fatal("lto can only be run for executables and \
58+
if !crate_type_allows_lto(*crate_type) {
59+
sess.fatal("lto can only be run for executables and \
4760
static library outputs");
48-
}
4961
}
5062
}
5163

64+
let export_threshold =
65+
symbol_export::crates_export_threshold(&sess.crate_types.borrow()[..]);
66+
67+
let symbol_filter = &|&(ref name, level): &(String, _)| {
68+
if symbol_export::is_below_threshold(level, export_threshold) {
69+
let mut bytes = Vec::with_capacity(name.len() + 1);
70+
bytes.extend(name.bytes());
71+
Some(CString::new(bytes).unwrap())
72+
} else {
73+
None
74+
}
75+
};
76+
77+
let mut symbol_white_list: Vec<CString> = exported_symbols
78+
.exported_symbols(LOCAL_CRATE)
79+
.iter()
80+
.filter_map(symbol_filter)
81+
.collect();
82+
5283
// For each of our upstream dependencies, find the corresponding rlib and
5384
// load the bitcode from the archive. Then merge it into the current LLVM
5485
// module that we've got.
@@ -58,6 +89,11 @@ pub fn run(sess: &session::Session, llmod: ModuleRef,
5889
return;
5990
}
6091

92+
symbol_white_list.extend(
93+
exported_symbols.exported_symbols(cnum)
94+
.iter()
95+
.filter_map(symbol_filter));
96+
6197
let archive = ArchiveRO::open(&path).expect("wanted an rlib");
6298
let bytecodes = archive.iter().filter_map(|child| {
6399
child.ok().and_then(|c| c.name().map(|name| (name, c)))
@@ -119,10 +155,9 @@ pub fn run(sess: &session::Session, llmod: ModuleRef,
119155
});
120156

121157
// Internalize everything but the exported symbols of the current module
122-
let cstrs: Vec<CString> = exported_symbols.iter().map(|s| {
123-
CString::new(s.clone()).unwrap()
124-
}).collect();
125-
let arr: Vec<*const libc::c_char> = cstrs.iter().map(|c| c.as_ptr()).collect();
158+
let arr: Vec<*const libc::c_char> = symbol_white_list.iter()
159+
.map(|c| c.as_ptr())
160+
.collect();
126161
let ptr = arr.as_ptr();
127162
unsafe {
128163
llvm::LLVMRustRunRestrictionPass(llmod,

0 commit comments

Comments
 (0)