Skip to content

Commit 994e813

Browse files
Don't recompute SymbolExportLevel for upstream crates.
1 parent b6d5448 commit 994e813

File tree

7 files changed

+115
-105
lines changed

7 files changed

+115
-105
lines changed

src/librustc/middle/exported_symbols.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use ty;
1717
/// kind of crate, including cdylibs which export very few things.
1818
/// `Rust` will only be exported if the crate produced is a Rust
1919
/// dylib.
20-
#[derive(Eq, PartialEq, Debug, Copy, Clone)]
20+
#[derive(Eq, PartialEq, Debug, Copy, Clone, RustcEncodable, RustcDecodable)]
2121
pub enum SymbolExportLevel {
2222
C,
2323
Rust,
@@ -39,7 +39,7 @@ impl SymbolExportLevel {
3939
}
4040
}
4141

42-
#[derive(Eq, PartialEq, Debug, Copy, Clone)]
42+
#[derive(Eq, PartialEq, Debug, Copy, Clone, RustcEncodable, RustcDecodable)]
4343
pub enum ExportedSymbol {
4444
NonGeneric(DefId),
4545
NoDefId(ty::SymbolName),

src/librustc/ty/context.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2404,4 +2404,12 @@ pub fn provide(providers: &mut ty::maps::Providers) {
24042404
providers.fully_normalize_monormophic_ty = |tcx, ty| {
24052405
tcx.fully_normalize_associated_types_in(&ty)
24062406
};
2407+
providers.is_panic_runtime = |tcx, cnum| {
2408+
assert_eq!(cnum, LOCAL_CRATE);
2409+
attr::contains_name(tcx.hir.krate_attrs(), "panic_runtime")
2410+
};
2411+
providers.is_compiler_builtins = |tcx, cnum| {
2412+
assert_eq!(cnum, LOCAL_CRATE);
2413+
attr::contains_name(tcx.hir.krate_attrs(), "compiler_builtins")
2414+
};
24072415
}

src/librustc_metadata/cstore_impl.rs

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use rustc::ty::maps::QueryConfig;
1818
use rustc::middle::cstore::{CrateStore, DepKind,
1919
MetadataLoader, LinkMeta,
2020
LoadedMacro, EncodedMetadata, NativeLibraryKind};
21+
use rustc::middle::exported_symbols::{SymbolExportLevel, ExportedSymbol};
2122
use rustc::middle::stability::DeprecationEntry;
2223
use rustc::hir::def;
2324
use rustc::session::{CrateDisambiguator, Session};
@@ -28,9 +29,11 @@ use rustc::hir::map::{DefKey, DefPath, DefPathHash};
2829
use rustc::hir::map::blocks::FnLikeNode;
2930
use rustc::hir::map::definitions::DefPathTable;
3031
use rustc::util::nodemap::DefIdMap;
32+
use rustc_back::LinkerFlavor;
3133

3234
use std::any::Any;
3335
use std::rc::Rc;
36+
use std::sync::Arc;
3437

3538
use syntax::ast;
3639
use syntax::attr;
@@ -176,7 +179,21 @@ provide! { <'tcx> tcx, def_id, other, cdata,
176179
extern_crate => { Rc::new(cdata.extern_crate.get()) }
177180
is_no_builtins => { cdata.is_no_builtins(tcx.sess) }
178181
impl_defaultness => { cdata.get_impl_defaultness(def_id.index) }
179-
reachable_non_generics => { Rc::new(cdata.reachable_non_generics()) }
182+
reachable_non_generics => {
183+
let reachable_non_generics = tcx
184+
.exported_symbols(cdata.cnum)
185+
.iter()
186+
.filter_map(|&(exported_symbol, _)| {
187+
if let ExportedSymbol::NonGeneric(def_id) = exported_symbol {
188+
return Some(def_id)
189+
} else {
190+
None
191+
}
192+
})
193+
.collect();
194+
195+
Rc::new(reachable_non_generics)
196+
}
180197
native_libraries => { Rc::new(cdata.get_native_libraries(tcx.sess)) }
181198
plugin_registrar_fn => {
182199
cdata.root.plugin_registrar_fn.map(|index| {
@@ -235,6 +252,43 @@ provide! { <'tcx> tcx, def_id, other, cdata,
235252

236253
has_copy_closures => { cdata.has_copy_closures(tcx.sess) }
237254
has_clone_closures => { cdata.has_clone_closures(tcx.sess) }
255+
256+
exported_symbols => {
257+
let cnum = cdata.cnum;
258+
assert!(cnum != LOCAL_CRATE);
259+
260+
// If this crate is a plugin and/or a custom derive crate, then
261+
// we're not even going to link those in so we skip those crates.
262+
if cdata.root.plugin_registrar_fn.is_some() ||
263+
cdata.root.macro_derive_registrar.is_some() {
264+
return Arc::new(Vec::new())
265+
}
266+
267+
let mut crate_exports: Vec<_> = cdata.exported_symbols();
268+
269+
// Dealing with compiler-builtins and wasm right now is super janky.
270+
// There's no linker! As a result we need all of the compiler-builtins
271+
// exported symbols to make their way through all the way to the end of
272+
// compilation. We want to make sure that LLVM doesn't remove them as
273+
// well because we may or may not need them in the final output
274+
// artifact. For now just force them to always get exported at the C
275+
// layer, and we'll worry about gc'ing them later.
276+
let compiler_builtins_and_binaryen =
277+
cdata.is_compiler_builtins(tcx.sess) &&
278+
tcx.sess.linker_flavor() == LinkerFlavor::Binaryen;
279+
280+
if compiler_builtins_and_binaryen {
281+
for &mut (ref exported_symbol, ref mut level) in crate_exports.iter_mut() {
282+
if let &ExportedSymbol::NonGeneric(def_id) = exported_symbol {
283+
if tcx.contains_extern_indicator(def_id) {
284+
*level = SymbolExportLevel::C
285+
}
286+
}
287+
}
288+
}
289+
290+
Arc::new(crate_exports)
291+
}
238292
}
239293

240294
pub fn provide<'tcx>(providers: &mut Providers<'tcx>) {

src/librustc_metadata/decoder.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ use rustc::hir::map::{DefKey, DefPath, DefPathData, DefPathHash};
1717
use rustc::hir;
1818
use rustc::middle::cstore::{LinkagePreference, ExternConstBody,
1919
ExternBodyNestedBodies};
20+
use rustc::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel};
2021
use rustc::hir::def::{self, Def, CtorKind};
2122
use rustc::hir::def_id::{CrateNum, DefId, DefIndex,
2223
CRATE_DEF_INDEX, LOCAL_CRATE};
@@ -26,7 +27,6 @@ use rustc::mir;
2627
use rustc::session::Session;
2728
use rustc::ty::{self, Ty, TyCtxt};
2829
use rustc::ty::codec::TyDecoder;
29-
use rustc::util::nodemap::DefIdSet;
3030
use rustc::mir::Mir;
3131

3232
use std::cell::Ref;
@@ -1006,11 +1006,10 @@ impl<'a, 'tcx> CrateMetadata {
10061006
arg_names.decode(self).collect()
10071007
}
10081008

1009-
pub fn reachable_non_generics(&self) -> DefIdSet {
1009+
pub fn exported_symbols(&self) -> Vec<(ExportedSymbol, SymbolExportLevel)> {
10101010
self.root
1011-
.reachable_non_generics
1011+
.exported_symbols
10121012
.decode(self)
1013-
.map(|index| self.local_def_id(index))
10141013
.collect()
10151014
}
10161015

src/librustc_metadata/encoder.rs

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,15 @@ use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefIndex, DefId, LOCAL_CRATE
2020
use rustc::hir::map::definitions::DefPathTable;
2121
use rustc::ich::Fingerprint;
2222
use rustc::middle::dependency_format::Linkage;
23+
use rustc::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel};
2324
use rustc::middle::lang_items;
2425
use rustc::mir;
2526
use rustc::traits::specialization_graph;
2627
use rustc::ty::{self, Ty, TyCtxt, ReprOptions};
2728
use rustc::ty::codec::{self as ty_codec, TyEncoder};
2829

2930
use rustc::session::config::{self, CrateTypeProcMacro};
30-
use rustc::util::nodemap::{FxHashMap, DefIdSet};
31+
use rustc::util::nodemap::FxHashMap;
3132

3233
use rustc_data_structures::stable_hasher::StableHasher;
3334
use rustc_serialize::{Encodable, Encoder, SpecializedEncoder, opaque};
@@ -394,11 +395,11 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
394395

395396
// Encode exported symbols info.
396397
i = self.position();
397-
let reachable_non_generics = self.tcx.reachable_non_generics(LOCAL_CRATE);
398-
let reachable_non_generics = self.tracked(
399-
IsolatedEncoder::encode_reachable_non_generics,
400-
&reachable_non_generics);
401-
let reachable_non_generics_bytes = self.position() - i;
398+
let exported_symbols = self.tcx.exported_symbols(LOCAL_CRATE);
399+
let exported_symbols = self.tracked(
400+
IsolatedEncoder::encode_exported_symbols,
401+
&exported_symbols);
402+
let exported_symbols_bytes = self.position() - i;
402403

403404
// Encode and index the items.
404405
i = self.position();
@@ -442,7 +443,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
442443
codemap,
443444
def_path_table,
444445
impls,
445-
reachable_non_generics,
446+
exported_symbols,
446447
index,
447448
});
448449

@@ -462,7 +463,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
462463
println!(" native bytes: {}", native_lib_bytes);
463464
println!(" codemap bytes: {}", codemap_bytes);
464465
println!(" impl bytes: {}", impl_bytes);
465-
println!(" exp. symbols bytes: {}", reachable_non_generics_bytes);
466+
println!(" exp. symbols bytes: {}", exported_symbols_bytes);
466467
println!(" def-path table bytes: {}", def_path_table_bytes);
467468
println!(" item bytes: {}", item_bytes);
468469
println!(" index bytes: {}", index_bytes);
@@ -1388,13 +1389,10 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
13881389
// middle::reachable module but filters out items that either don't have a
13891390
// symbol associated with them (they weren't translated) or if they're an FFI
13901391
// definition (as that's not defined in this crate).
1391-
fn encode_reachable_non_generics(&mut self,
1392-
reachable_non_generics: &DefIdSet)
1393-
-> LazySeq<DefIndex> {
1394-
self.lazy_seq(reachable_non_generics.iter().map(|def_id| {
1395-
debug_assert!(def_id.is_local());
1396-
def_id.index
1397-
}))
1392+
fn encode_exported_symbols(&mut self,
1393+
exported_symbols: &[(ExportedSymbol, SymbolExportLevel)])
1394+
-> LazySeq<(ExportedSymbol, SymbolExportLevel)> {
1395+
self.lazy_seq(exported_symbols.iter().cloned())
13981396
}
13991397

14001398
fn encode_dylib_dependency_formats(&mut self, _: ()) -> LazySeq<Option<LinkagePreference>> {

src/librustc_metadata/schema.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use rustc::hir::def::{self, CtorKind};
1616
use rustc::hir::def_id::{DefIndex, DefId, CrateNum};
1717
use rustc::ich::StableHashingContext;
1818
use rustc::middle::cstore::{DepKind, LinkagePreference, NativeLibrary};
19+
use rustc::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel};
1920
use rustc::middle::lang_items;
2021
use rustc::mir;
2122
use rustc::session::CrateDisambiguator;
@@ -202,7 +203,8 @@ pub struct CrateRoot {
202203
pub codemap: LazySeq<syntax_pos::FileMap>,
203204
pub def_path_table: Lazy<hir::map::definitions::DefPathTable>,
204205
pub impls: LazySeq<TraitImpls>,
205-
pub reachable_non_generics: LazySeq<DefIndex>,
206+
pub exported_symbols: LazySeq<(ExportedSymbol, SymbolExportLevel)>,
207+
206208
pub index: LazySeq<index::Index>,
207209
}
208210

src/librustc_trans/back/symbol_export.rs

Lines changed: 31 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ use rustc::ty::{TyCtxt, SymbolName};
2121
use rustc::ty::maps::Providers;
2222
use rustc::util::nodemap::{FxHashMap, DefIdSet};
2323
use rustc_allocator::ALLOCATOR_METHODS;
24-
use rustc_back::LinkerFlavor;
2524
use syntax::attr;
2625

2726
pub type ExportedSymbols = FxHashMap<
@@ -79,10 +78,9 @@ fn reachable_non_generics_provider<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
7978
let reachable_non_generics = tcx
8079
.exported_symbols(LOCAL_CRATE)
8180
.iter()
82-
.filter_map(|&(exported_symbol, _)| {
81+
.filter_map(|&(exported_symbol, level)| {
8382
if let ExportedSymbol::NonGeneric(def_id) = exported_symbol {
84-
if tcx.symbol_export_level(def_id)
85-
.is_below_threshold(export_threshold) {
83+
if level.is_below_threshold(export_threshold) {
8684
return Some(def_id)
8785
}
8886
}
@@ -111,6 +109,16 @@ fn exported_symbols_provider_local<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
111109
return Arc::new(vec![])
112110
}
113111

112+
// Check to see if this crate is a "special runtime crate". These
113+
// crates, implementation details of the standard library, typically
114+
// have a bunch of `pub extern` and `#[no_mangle]` functions as the
115+
// ABI between them. We don't want their symbols to have a `C`
116+
// export level, however, as they're just implementation details.
117+
// Down below we'll hardwire all of the symbols to the `Rust` export
118+
// level instead.
119+
let special_runtime_crate = tcx.is_panic_runtime(LOCAL_CRATE) ||
120+
tcx.is_compiler_builtins(LOCAL_CRATE);
121+
114122
let mut reachable_non_generics: DefIdSet = tcx.reachable_set(LOCAL_CRATE).0
115123
.iter()
116124
.filter_map(|&node_id| {
@@ -177,7 +185,25 @@ fn exported_symbols_provider_local<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
177185
let mut symbols: Vec<_> = reachable_non_generics
178186
.iter()
179187
.map(|&def_id| {
180-
let export_level = tcx.symbol_export_level(def_id);
188+
let export_level = if special_runtime_crate {
189+
let name = tcx.symbol_name(Instance::mono(tcx, def_id));
190+
// We can probably do better here by just ensuring that
191+
// it has hidden visibility rather than public
192+
// visibility, as this is primarily here to ensure it's
193+
// not stripped during LTO.
194+
//
195+
// In general though we won't link right if these
196+
// symbols are stripped, and LTO currently strips them.
197+
if &*name == "rust_eh_personality" ||
198+
&*name == "rust_eh_register_frames" ||
199+
&*name == "rust_eh_unregister_frames" {
200+
SymbolExportLevel::C
201+
} else {
202+
SymbolExportLevel::Rust
203+
}
204+
} else {
205+
tcx.symbol_export_level(def_id)
206+
};
181207
debug!("EXPORTED SYMBOL (local): {} ({:?})",
182208
tcx.symbol_name(Instance::mono(tcx, def_id)),
183209
export_level);
@@ -223,84 +249,7 @@ pub fn provide(providers: &mut Providers) {
223249
providers.symbol_export_level = symbol_export_level_provider;
224250
}
225251

226-
fn exported_symbols_provider_extern<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
227-
cnum: CrateNum)
228-
-> Arc<Vec<(ExportedSymbol,
229-
SymbolExportLevel)>>
230-
{
231-
// If this crate is a plugin and/or a custom derive crate, then
232-
// we're not even going to link those in so we skip those crates.
233-
if tcx.plugin_registrar_fn(cnum).is_some() ||
234-
tcx.derive_registrar_fn(cnum).is_some() {
235-
return Arc::new(Vec::new())
236-
}
237-
238-
// Check to see if this crate is a "special runtime crate". These
239-
// crates, implementation details of the standard library, typically
240-
// have a bunch of `pub extern` and `#[no_mangle]` functions as the
241-
// ABI between them. We don't want their symbols to have a `C`
242-
// export level, however, as they're just implementation details.
243-
// Down below we'll hardwire all of the symbols to the `Rust` export
244-
// level instead.
245-
let special_runtime_crate =
246-
tcx.is_panic_runtime(cnum) || tcx.is_compiler_builtins(cnum);
247-
248-
// Dealing with compiler-builtins and wasm right now is super janky.
249-
// There's no linker! As a result we need all of the compiler-builtins
250-
// exported symbols to make their way through all the way to the end of
251-
// compilation. We want to make sure that LLVM doesn't remove them as
252-
// well because we may or may not need them in the final output
253-
// artifact. For now just force them to always get exported at the C
254-
// layer, and we'll worry about gc'ing them later.
255-
let compiler_builtins_and_binaryen =
256-
tcx.is_compiler_builtins(cnum) &&
257-
tcx.sess.linker_flavor() == LinkerFlavor::Binaryen;
258-
259-
let mut crate_exports: Vec<_> = tcx
260-
.reachable_non_generics(cnum)
261-
.iter()
262-
.map(|&def_id| {
263-
let export_level = if compiler_builtins_and_binaryen &&
264-
tcx.contains_extern_indicator(def_id) {
265-
SymbolExportLevel::C
266-
} else if special_runtime_crate {
267-
let name = tcx.symbol_name(Instance::mono(tcx, def_id));
268-
// We can probably do better here by just ensuring that
269-
// it has hidden visibility rather than public
270-
// visibility, as this is primarily here to ensure it's
271-
// not stripped during LTO.
272-
//
273-
// In general though we won't link right if these
274-
// symbols are stripped, and LTO currently strips them.
275-
if &*name == "rust_eh_personality" ||
276-
&*name == "rust_eh_register_frames" ||
277-
&*name == "rust_eh_unregister_frames" {
278-
SymbolExportLevel::C
279-
} else {
280-
SymbolExportLevel::Rust
281-
}
282-
} else {
283-
tcx.symbol_export_level(def_id)
284-
};
285-
286-
debug!("EXPORTED SYMBOL (re-export): {} ({:?})",
287-
tcx.symbol_name(Instance::mono(tcx, def_id)),
288-
export_level);
289-
290-
(ExportedSymbol::NonGeneric(def_id), export_level)
291-
})
292-
.collect();
293-
294-
// Sort so we get a stable incr. comp. hash.
295-
crate_exports.sort_unstable_by(|&(ref symbol1, ..), &(ref symbol2, ..)| {
296-
symbol1.compare_stable(tcx, symbol2)
297-
});
298-
299-
Arc::new(crate_exports)
300-
}
301-
302252
pub fn provide_extern(providers: &mut Providers) {
303-
providers.exported_symbols = exported_symbols_provider_extern;
304253
providers.is_reachable_non_generic = is_reachable_non_generic_provider;
305254
providers.symbol_export_level = symbol_export_level_provider;
306255
}

0 commit comments

Comments
 (0)