Don't recompute SymbolExportLevel for upstream crates.
This commit is contained in:
parent
aec6c85b0c
commit
8bc005c8bb
@ -17,7 +17,7 @@ use ty;
|
||||
/// kind of crate, including cdylibs which export very few things.
|
||||
/// `Rust` will only be exported if the crate produced is a Rust
|
||||
/// dylib.
|
||||
#[derive(Eq, PartialEq, Debug, Copy, Clone)]
|
||||
#[derive(Eq, PartialEq, Debug, Copy, Clone, RustcEncodable, RustcDecodable)]
|
||||
pub enum SymbolExportLevel {
|
||||
C,
|
||||
Rust,
|
||||
@ -39,7 +39,7 @@ impl SymbolExportLevel {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Eq, PartialEq, Debug, Copy, Clone)]
|
||||
#[derive(Eq, PartialEq, Debug, Copy, Clone, RustcEncodable, RustcDecodable)]
|
||||
pub enum ExportedSymbol {
|
||||
NonGeneric(DefId),
|
||||
NoDefId(ty::SymbolName),
|
||||
|
@ -2460,4 +2460,12 @@ pub fn provide(providers: &mut ty::maps::Providers) {
|
||||
assert_eq!(cnum, LOCAL_CRATE);
|
||||
Lrc::new(tcx.sess.features_untracked().clone())
|
||||
};
|
||||
providers.is_panic_runtime = |tcx, cnum| {
|
||||
assert_eq!(cnum, LOCAL_CRATE);
|
||||
attr::contains_name(tcx.hir.krate_attrs(), "panic_runtime")
|
||||
};
|
||||
providers.is_compiler_builtins = |tcx, cnum| {
|
||||
assert_eq!(cnum, LOCAL_CRATE);
|
||||
attr::contains_name(tcx.hir.krate_attrs(), "compiler_builtins")
|
||||
};
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ use rustc::ty::maps::QueryConfig;
|
||||
use rustc::middle::cstore::{CrateStore, DepKind,
|
||||
MetadataLoader, LinkMeta,
|
||||
LoadedMacro, EncodedMetadata, NativeLibraryKind};
|
||||
use rustc::middle::exported_symbols::ExportedSymbol;
|
||||
use rustc::middle::stability::DeprecationEntry;
|
||||
use rustc::hir::def;
|
||||
use rustc::session::{CrateDisambiguator, Session};
|
||||
@ -31,6 +32,7 @@ use rustc::util::nodemap::DefIdMap;
|
||||
|
||||
use std::any::Any;
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use std::sync::Arc;
|
||||
|
||||
use syntax::ast;
|
||||
use syntax::attr;
|
||||
@ -176,7 +178,21 @@ provide! { <'tcx> tcx, def_id, other, cdata,
|
||||
extern_crate => { Lrc::new(cdata.extern_crate.get()) }
|
||||
is_no_builtins => { cdata.is_no_builtins(tcx.sess) }
|
||||
impl_defaultness => { cdata.get_impl_defaultness(def_id.index) }
|
||||
reachable_non_generics => { Lrc::new(cdata.reachable_non_generics()) }
|
||||
reachable_non_generics => {
|
||||
let reachable_non_generics = tcx
|
||||
.exported_symbols(cdata.cnum)
|
||||
.iter()
|
||||
.filter_map(|&(exported_symbol, _)| {
|
||||
if let ExportedSymbol::NonGeneric(def_id) = exported_symbol {
|
||||
return Some(def_id)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
Lrc::new(reachable_non_generics)
|
||||
}
|
||||
native_libraries => { Lrc::new(cdata.get_native_libraries(tcx.sess)) }
|
||||
plugin_registrar_fn => {
|
||||
cdata.root.plugin_registrar_fn.map(|index| {
|
||||
@ -235,6 +251,20 @@ provide! { <'tcx> tcx, def_id, other, cdata,
|
||||
|
||||
has_copy_closures => { cdata.has_copy_closures(tcx.sess) }
|
||||
has_clone_closures => { cdata.has_clone_closures(tcx.sess) }
|
||||
|
||||
exported_symbols => {
|
||||
let cnum = cdata.cnum;
|
||||
assert!(cnum != LOCAL_CRATE);
|
||||
|
||||
// If this crate is a plugin and/or a custom derive crate, then
|
||||
// we're not even going to link those in so we skip those crates.
|
||||
if cdata.root.plugin_registrar_fn.is_some() ||
|
||||
cdata.root.macro_derive_registrar.is_some() {
|
||||
return Arc::new(Vec::new())
|
||||
}
|
||||
|
||||
Arc::new(cdata.exported_symbols())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn provide<'tcx>(providers: &mut Providers<'tcx>) {
|
||||
|
@ -18,6 +18,7 @@ use rustc::hir::map::{DefKey, DefPath, DefPathData, DefPathHash};
|
||||
use rustc::hir;
|
||||
use rustc::middle::cstore::{LinkagePreference, ExternConstBody,
|
||||
ExternBodyNestedBodies};
|
||||
use rustc::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel};
|
||||
use rustc::hir::def::{self, Def, CtorKind};
|
||||
use rustc::hir::def_id::{CrateNum, DefId, DefIndex,
|
||||
CRATE_DEF_INDEX, LOCAL_CRATE};
|
||||
@ -27,7 +28,6 @@ use rustc::mir;
|
||||
use rustc::session::Session;
|
||||
use rustc::ty::{self, Ty, TyCtxt};
|
||||
use rustc::ty::codec::TyDecoder;
|
||||
use rustc::util::nodemap::DefIdSet;
|
||||
use rustc::mir::Mir;
|
||||
|
||||
use std::cell::Ref;
|
||||
@ -1006,11 +1006,10 @@ impl<'a, 'tcx> CrateMetadata {
|
||||
arg_names.decode(self).collect()
|
||||
}
|
||||
|
||||
pub fn reachable_non_generics(&self) -> DefIdSet {
|
||||
pub fn exported_symbols(&self) -> Vec<(ExportedSymbol, SymbolExportLevel)> {
|
||||
self.root
|
||||
.reachable_non_generics
|
||||
.exported_symbols
|
||||
.decode(self)
|
||||
.map(|index| self.local_def_id(index))
|
||||
.collect()
|
||||
}
|
||||
|
||||
|
@ -20,6 +20,7 @@ use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefIndex, DefId, LOCAL_CRATE
|
||||
use rustc::hir::map::definitions::DefPathTable;
|
||||
use rustc::ich::Fingerprint;
|
||||
use rustc::middle::dependency_format::Linkage;
|
||||
use rustc::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel};
|
||||
use rustc::middle::lang_items;
|
||||
use rustc::mir;
|
||||
use rustc::traits::specialization_graph;
|
||||
@ -27,7 +28,7 @@ use rustc::ty::{self, Ty, TyCtxt, ReprOptions};
|
||||
use rustc::ty::codec::{self as ty_codec, TyEncoder};
|
||||
|
||||
use rustc::session::config::{self, CrateTypeProcMacro};
|
||||
use rustc::util::nodemap::{FxHashMap, DefIdSet};
|
||||
use rustc::util::nodemap::FxHashMap;
|
||||
|
||||
use rustc_data_structures::stable_hasher::StableHasher;
|
||||
use rustc_serialize::{Encodable, Encoder, SpecializedEncoder, opaque};
|
||||
@ -394,11 +395,11 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||
|
||||
// Encode exported symbols info.
|
||||
i = self.position();
|
||||
let reachable_non_generics = self.tcx.reachable_non_generics(LOCAL_CRATE);
|
||||
let reachable_non_generics = self.tracked(
|
||||
IsolatedEncoder::encode_reachable_non_generics,
|
||||
&reachable_non_generics);
|
||||
let reachable_non_generics_bytes = self.position() - i;
|
||||
let exported_symbols = self.tcx.exported_symbols(LOCAL_CRATE);
|
||||
let exported_symbols = self.tracked(
|
||||
IsolatedEncoder::encode_exported_symbols,
|
||||
&exported_symbols);
|
||||
let exported_symbols_bytes = self.position() - i;
|
||||
|
||||
// Encode and index the items.
|
||||
i = self.position();
|
||||
@ -442,7 +443,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||
codemap,
|
||||
def_path_table,
|
||||
impls,
|
||||
reachable_non_generics,
|
||||
exported_symbols,
|
||||
index,
|
||||
});
|
||||
|
||||
@ -462,7 +463,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||
println!(" native bytes: {}", native_lib_bytes);
|
||||
println!(" codemap bytes: {}", codemap_bytes);
|
||||
println!(" impl bytes: {}", impl_bytes);
|
||||
println!(" exp. symbols bytes: {}", reachable_non_generics_bytes);
|
||||
println!(" exp. symbols bytes: {}", exported_symbols_bytes);
|
||||
println!(" def-path table bytes: {}", def_path_table_bytes);
|
||||
println!(" item bytes: {}", item_bytes);
|
||||
println!(" index bytes: {}", index_bytes);
|
||||
@ -1388,13 +1389,10 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
|
||||
// middle::reachable module but filters out items that either don't have a
|
||||
// symbol associated with them (they weren't translated) or if they're an FFI
|
||||
// definition (as that's not defined in this crate).
|
||||
fn encode_reachable_non_generics(&mut self,
|
||||
reachable_non_generics: &DefIdSet)
|
||||
-> LazySeq<DefIndex> {
|
||||
self.lazy_seq(reachable_non_generics.iter().map(|def_id| {
|
||||
debug_assert!(def_id.is_local());
|
||||
def_id.index
|
||||
}))
|
||||
fn encode_exported_symbols(&mut self,
|
||||
exported_symbols: &[(ExportedSymbol, SymbolExportLevel)])
|
||||
-> LazySeq<(ExportedSymbol, SymbolExportLevel)> {
|
||||
self.lazy_seq(exported_symbols.iter().cloned())
|
||||
}
|
||||
|
||||
fn encode_dylib_dependency_formats(&mut self, _: ()) -> LazySeq<Option<LinkagePreference>> {
|
||||
|
@ -16,6 +16,7 @@ use rustc::hir::def::{self, CtorKind};
|
||||
use rustc::hir::def_id::{DefIndex, DefId, CrateNum};
|
||||
use rustc::ich::StableHashingContext;
|
||||
use rustc::middle::cstore::{DepKind, LinkagePreference, NativeLibrary};
|
||||
use rustc::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel};
|
||||
use rustc::middle::lang_items;
|
||||
use rustc::mir;
|
||||
use rustc::session::CrateDisambiguator;
|
||||
@ -202,7 +203,8 @@ pub struct CrateRoot {
|
||||
pub codemap: LazySeq<syntax_pos::FileMap>,
|
||||
pub def_path_table: Lazy<hir::map::definitions::DefPathTable>,
|
||||
pub impls: LazySeq<TraitImpls>,
|
||||
pub reachable_non_generics: LazySeq<DefIndex>,
|
||||
pub exported_symbols: LazySeq<(ExportedSymbol, SymbolExportLevel)>,
|
||||
|
||||
pub index: LazySeq<index::Index>,
|
||||
}
|
||||
|
||||
|
@ -78,10 +78,9 @@ fn reachable_non_generics_provider<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
let reachable_non_generics = tcx
|
||||
.exported_symbols(LOCAL_CRATE)
|
||||
.iter()
|
||||
.filter_map(|&(exported_symbol, _)| {
|
||||
.filter_map(|&(exported_symbol, level)| {
|
||||
if let ExportedSymbol::NonGeneric(def_id) = exported_symbol {
|
||||
if tcx.symbol_export_level(def_id)
|
||||
.is_below_threshold(export_threshold) {
|
||||
if level.is_below_threshold(export_threshold) {
|
||||
return Some(def_id)
|
||||
}
|
||||
}
|
||||
@ -110,6 +109,16 @@ fn exported_symbols_provider_local<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
return Arc::new(vec![])
|
||||
}
|
||||
|
||||
// Check to see if this crate is a "special runtime crate". These
|
||||
// crates, implementation details of the standard library, typically
|
||||
// have a bunch of `pub extern` and `#[no_mangle]` functions as the
|
||||
// ABI between them. We don't want their symbols to have a `C`
|
||||
// export level, however, as they're just implementation details.
|
||||
// Down below we'll hardwire all of the symbols to the `Rust` export
|
||||
// level instead.
|
||||
let special_runtime_crate = tcx.is_panic_runtime(LOCAL_CRATE) ||
|
||||
tcx.is_compiler_builtins(LOCAL_CRATE);
|
||||
|
||||
let mut reachable_non_generics: DefIdSet = tcx.reachable_set(LOCAL_CRATE).0
|
||||
.iter()
|
||||
.filter_map(|&node_id| {
|
||||
@ -176,7 +185,25 @@ fn exported_symbols_provider_local<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
let mut symbols: Vec<_> = reachable_non_generics
|
||||
.iter()
|
||||
.map(|&def_id| {
|
||||
let export_level = tcx.symbol_export_level(def_id);
|
||||
let export_level = if special_runtime_crate {
|
||||
let name = tcx.symbol_name(Instance::mono(tcx, def_id));
|
||||
// We can probably do better here by just ensuring that
|
||||
// it has hidden visibility rather than public
|
||||
// visibility, as this is primarily here to ensure it's
|
||||
// not stripped during LTO.
|
||||
//
|
||||
// In general though we won't link right if these
|
||||
// symbols are stripped, and LTO currently strips them.
|
||||
if &*name == "rust_eh_personality" ||
|
||||
&*name == "rust_eh_register_frames" ||
|
||||
&*name == "rust_eh_unregister_frames" {
|
||||
SymbolExportLevel::C
|
||||
} else {
|
||||
SymbolExportLevel::Rust
|
||||
}
|
||||
} else {
|
||||
tcx.symbol_export_level(def_id)
|
||||
};
|
||||
debug!("EXPORTED SYMBOL (local): {} ({:?})",
|
||||
tcx.symbol_name(Instance::mono(tcx, def_id)),
|
||||
export_level);
|
||||
@ -222,70 +249,7 @@ pub fn provide(providers: &mut Providers) {
|
||||
providers.symbol_export_level = symbol_export_level_provider;
|
||||
}
|
||||
|
||||
fn exported_symbols_provider_extern<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
cnum: CrateNum)
|
||||
-> Arc<Vec<(ExportedSymbol,
|
||||
SymbolExportLevel)>>
|
||||
{
|
||||
// If this crate is a plugin and/or a custom derive crate, then
|
||||
// we're not even going to link those in so we skip those crates.
|
||||
if tcx.plugin_registrar_fn(cnum).is_some() ||
|
||||
tcx.derive_registrar_fn(cnum).is_some() {
|
||||
return Arc::new(Vec::new())
|
||||
}
|
||||
|
||||
// Check to see if this crate is a "special runtime crate". These
|
||||
// crates, implementation details of the standard library, typically
|
||||
// have a bunch of `pub extern` and `#[no_mangle]` functions as the
|
||||
// ABI between them. We don't want their symbols to have a `C`
|
||||
// export level, however, as they're just implementation details.
|
||||
// Down below we'll hardwire all of the symbols to the `Rust` export
|
||||
// level instead.
|
||||
let special_runtime_crate =
|
||||
tcx.is_panic_runtime(cnum) || tcx.is_compiler_builtins(cnum);
|
||||
|
||||
let mut crate_exports: Vec<_> = tcx
|
||||
.reachable_non_generics(cnum)
|
||||
.iter()
|
||||
.map(|&def_id| {
|
||||
let export_level = if special_runtime_crate {
|
||||
let name = tcx.symbol_name(Instance::mono(tcx, def_id));
|
||||
// We can probably do better here by just ensuring that
|
||||
// it has hidden visibility rather than public
|
||||
// visibility, as this is primarily here to ensure it's
|
||||
// not stripped during LTO.
|
||||
//
|
||||
// In general though we won't link right if these
|
||||
// symbols are stripped, and LTO currently strips them.
|
||||
if &*name == "rust_eh_personality" ||
|
||||
&*name == "rust_eh_register_frames" ||
|
||||
&*name == "rust_eh_unregister_frames" {
|
||||
SymbolExportLevel::C
|
||||
} else {
|
||||
SymbolExportLevel::Rust
|
||||
}
|
||||
} else {
|
||||
tcx.symbol_export_level(def_id)
|
||||
};
|
||||
|
||||
debug!("EXPORTED SYMBOL (re-export): {} ({:?})",
|
||||
tcx.symbol_name(Instance::mono(tcx, def_id)),
|
||||
export_level);
|
||||
|
||||
(ExportedSymbol::NonGeneric(def_id), export_level)
|
||||
})
|
||||
.collect();
|
||||
|
||||
// Sort so we get a stable incr. comp. hash.
|
||||
crate_exports.sort_unstable_by(|&(ref symbol1, ..), &(ref symbol2, ..)| {
|
||||
symbol1.compare_stable(tcx, symbol2)
|
||||
});
|
||||
|
||||
Arc::new(crate_exports)
|
||||
}
|
||||
|
||||
pub fn provide_extern(providers: &mut Providers) {
|
||||
providers.exported_symbols = exported_symbols_provider_extern;
|
||||
providers.is_reachable_non_generic = is_reachable_non_generic_provider;
|
||||
providers.symbol_export_level = symbol_export_level_provider;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user