summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2018-03-06 11:52:16 +0000
committerbors <bors@rust-lang.org>2018-03-06 11:52:16 +0000
commitb977e044a7485a95852bfce12f1054bcc673355d (patch)
treed3fd34041981c111b25ac0afd73d0fce69f0a699
parent6f2100b92cb14fbea2102701af6a3ac5814bd06c (diff)
parentf5ab4d4cdd1a8eda860628e97b619da8c10ac7b3 (diff)
downloadrust-b977e044a7485a95852bfce12f1054bcc673355d.tar.gz
Auto merge of #48611 - michaelwoerister:share-generics2, r=alexcrichton
Don't recompute SymbolExportLevel for upstream crates. The data collected in #48373 suggests that we can avoid generating up to 30% of the LLVM definitions by only instantiating function monomorphizations once with a given crate graph. Some more data, collected with a [proof-of-concept implementation](https://github.com/michaelwoerister/rust/commits/share-generics) of re-using monomorphizations, which is less efficient than the MIR-only RLIB approach, suggests that it's still around 25% LLVM definitions that we can save. So far, this PR only cleans up handling of symbol export status. Too early to review still.
-rw-r--r--src/librustc/dep_graph/dep_node.rs4
-rw-r--r--src/librustc/middle/cstore.rs7
-rw-r--r--src/librustc/middle/exported_symbols.rs61
-rw-r--r--src/librustc/ty/context.rs14
-rw-r--r--src/librustc/ty/maps/config.rs6
-rw-r--r--src/librustc/ty/maps/mod.rs23
-rw-r--r--src/librustc/ty/maps/plumbing.rs4
-rw-r--r--src/librustc/ty/mod.rs16
-rw-r--r--src/librustc_metadata/creader.rs4
-rw-r--r--src/librustc_metadata/cstore.rs2
-rw-r--r--src/librustc_metadata/cstore_impl.rs41
-rw-r--r--src/librustc_metadata/decoder.rs10
-rw-r--r--src/librustc_metadata/encoder.rs36
-rw-r--r--src/librustc_metadata/schema.rs4
-rw-r--r--src/librustc_mir/monomorphize/collector.rs4
-rw-r--r--src/librustc_mir/monomorphize/partitioning.rs6
-rw-r--r--src/librustc_trans/back/linker.rs8
-rw-r--r--src/librustc_trans/back/lto.rs2
-rw-r--r--src/librustc_trans/back/symbol_export.rs315
-rw-r--r--src/librustc_trans/back/write.rs37
-rw-r--r--src/librustc_trans/base.rs16
-rw-r--r--src/librustc_trans/callee.rs2
-rw-r--r--src/librustc_trans/consts.rs2
-rw-r--r--src/librustc_trans/debuginfo/utils.rs2
-rw-r--r--src/librustc_trans_utils/lib.rs55
-rw-r--r--src/librustc_trans_utils/trans_crate.rs3
26 files changed, 413 insertions, 271 deletions
diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs
index 5f6a7c452c4..84fdeba4ab3 100644
--- a/src/librustc/dep_graph/dep_node.rs
+++ b/src/librustc/dep_graph/dep_node.rs
@@ -556,7 +556,7 @@ define_dep_nodes!( <'tcx>
[] RvaluePromotableMap(DefId),
[] ImplParent(DefId),
[] TraitOfItem(DefId),
- [] IsExportedSymbol(DefId),
+ [] IsReachableNonGeneric(DefId),
[] IsMirAvailable(DefId),
[] ItemAttrs(DefId),
[] FnArgNames(DefId),
@@ -574,7 +574,7 @@ define_dep_nodes!( <'tcx>
[] GetPanicStrategy(CrateNum),
[] IsNoBuiltins(CrateNum),
[] ImplDefaultness(DefId),
- [] ExportedSymbolIds(CrateNum),
+ [] ReachableNonGenerics(CrateNum),
[] NativeLibraries(CrateNum),
[] PluginRegistrarFn(CrateNum),
[] DeriveRegistrarFn(CrateNum),
diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs
index bdb5ad525a7..5dbe2ef516c 100644
--- a/src/librustc/middle/cstore.rs
+++ b/src/librustc/middle/cstore.rs
@@ -32,7 +32,6 @@ use ich;
use ty::{self, TyCtxt};
use session::{Session, CrateDisambiguator};
use session::search_paths::PathKind;
-use util::nodemap::NodeSet;
use std::any::Any;
use std::collections::BTreeMap;
@@ -258,8 +257,7 @@ pub trait CrateStore {
// utility functions
fn encode_metadata<'a, 'tcx>(&self,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
- link_meta: &LinkMeta,
- reachable: &NodeSet)
+ link_meta: &LinkMeta)
-> EncodedMetadata;
fn metadata_encoding_version(&self) -> &[u8];
}
@@ -342,8 +340,7 @@ impl CrateStore for DummyCrateStore {
fn extern_mod_stmt_cnum_untracked(&self, emod_id: ast::NodeId) -> Option<CrateNum> { None }
fn encode_metadata<'a, 'tcx>(&self,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
- link_meta: &LinkMeta,
- reachable: &NodeSet)
+ link_meta: &LinkMeta)
-> EncodedMetadata {
bug!("encode_metadata")
}
diff --git a/src/librustc/middle/exported_symbols.rs b/src/librustc/middle/exported_symbols.rs
index d650dbe88b5..b1418792490 100644
--- a/src/librustc/middle/exported_symbols.rs
+++ b/src/librustc/middle/exported_symbols.rs
@@ -8,12 +8,16 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use hir::def_id::{DefId, LOCAL_CRATE};
+use std::cmp;
+use ty;
+
/// The SymbolExportLevel of a symbols specifies from which kinds of crates
/// the symbol will be exported. `C` symbols will be exported from any
/// 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,
@@ -34,3 +38,58 @@ impl SymbolExportLevel {
}
}
}
+
+#[derive(Eq, PartialEq, Debug, Copy, Clone, RustcEncodable, RustcDecodable)]
+pub enum ExportedSymbol {
+ NonGeneric(DefId),
+ NoDefId(ty::SymbolName),
+}
+
+impl ExportedSymbol {
+ pub fn symbol_name(&self, tcx: ty::TyCtxt) -> ty::SymbolName {
+ match *self {
+ ExportedSymbol::NonGeneric(def_id) => {
+ tcx.symbol_name(ty::Instance::mono(tcx, def_id))
+ }
+ ExportedSymbol::NoDefId(symbol_name) => {
+ symbol_name
+ }
+ }
+ }
+
+ pub fn compare_stable(&self, tcx: ty::TyCtxt, other: &ExportedSymbol) -> cmp::Ordering {
+ match *self {
+ ExportedSymbol::NonGeneric(self_def_id) => {
+ match *other {
+ ExportedSymbol::NonGeneric(other_def_id) => {
+ tcx.def_path_hash(self_def_id).cmp(&tcx.def_path_hash(other_def_id))
+ }
+ ExportedSymbol::NoDefId(_) => {
+ cmp::Ordering::Less
+ }
+ }
+ }
+ ExportedSymbol::NoDefId(self_symbol_name) => {
+ match *other {
+ ExportedSymbol::NonGeneric(_) => {
+ cmp::Ordering::Greater
+ }
+ ExportedSymbol::NoDefId(ref other_symbol_name) => {
+ self_symbol_name.cmp(other_symbol_name)
+ }
+ }
+ }
+ }
+ }
+}
+
+impl_stable_hash_for!(enum self::ExportedSymbol {
+ NonGeneric(def_id),
+ NoDefId(symbol_name)
+});
+
+pub fn metadata_symbol_name(tcx: ty::TyCtxt) -> String {
+ format!("rust_metadata_{}_{}",
+ tcx.original_crate_name(LOCAL_CRATE),
+ tcx.crate_disambiguator(LOCAL_CRATE).to_fingerprint().to_hex())
+}
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index a7f065d57ae..47a3580e867 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -46,7 +46,7 @@ use ty::layout::{LayoutDetails, TargetDataLayout};
use ty::maps;
use ty::steal::Steal;
use ty::BindingMode;
-use util::nodemap::{NodeMap, NodeSet, DefIdSet, ItemLocalMap};
+use util::nodemap::{NodeMap, DefIdSet, ItemLocalMap};
use util::nodemap::{FxHashMap, FxHashSet};
use rustc_data_structures::accumulate_vec::AccumulateVec;
use rustc_data_structures::stable_hasher::{HashStable, hash_stable_hashmap,
@@ -1417,10 +1417,10 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
}
impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
- pub fn encode_metadata(self, link_meta: &LinkMeta, reachable: &NodeSet)
+ pub fn encode_metadata(self, link_meta: &LinkMeta)
-> EncodedMetadata
{
- self.cstore.encode_metadata(self, link_meta, reachable)
+ self.cstore.encode_metadata(self, link_meta)
}
}
@@ -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")
+ };
}
diff --git a/src/librustc/ty/maps/config.rs b/src/librustc/ty/maps/config.rs
index c91b30440e5..cfc552bdc85 100644
--- a/src/librustc/ty/maps/config.rs
+++ b/src/librustc/ty/maps/config.rs
@@ -212,9 +212,9 @@ impl<'tcx> QueryDescription<'tcx> for queries::item_attrs<'tcx> {
}
}
-impl<'tcx> QueryDescription<'tcx> for queries::is_exported_symbol<'tcx> {
+impl<'tcx> QueryDescription<'tcx> for queries::is_reachable_non_generic<'tcx> {
fn describe(_: TyCtxt, _: DefId) -> String {
- bug!("is_exported_symbol")
+ bug!("is_reachable_non_generic")
}
}
@@ -383,7 +383,7 @@ impl<'tcx> QueryDescription<'tcx> for queries::is_sanitizer_runtime<'tcx> {
}
}
-impl<'tcx> QueryDescription<'tcx> for queries::exported_symbol_ids<'tcx> {
+impl<'tcx> QueryDescription<'tcx> for queries::reachable_non_generics<'tcx> {
fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
format!("looking up the exported symbols of a crate")
}
diff --git a/src/librustc/ty/maps/mod.rs b/src/librustc/ty/maps/mod.rs
index c211713db6b..2ef97b2673d 100644
--- a/src/librustc/ty/maps/mod.rs
+++ b/src/librustc/ty/maps/mod.rs
@@ -26,7 +26,7 @@ use middle::region;
use middle::resolve_lifetime::{ResolveLifetimes, Region, ObjectLifetimeDefault};
use middle::stability::{self, DeprecationEntry};
use middle::lang_items::{LanguageItems, LangItem};
-use middle::exported_symbols::SymbolExportLevel;
+use middle::exported_symbols::{SymbolExportLevel, ExportedSymbol};
use mir::mono::{CodegenUnit, Stats};
use mir;
use session::{CompileResult, CrateDisambiguator};
@@ -238,7 +238,6 @@ define_maps! { <'tcx>
[] fn fn_arg_names: FnArgNames(DefId) -> Vec<ast::Name>,
[] fn impl_parent: ImplParent(DefId) -> Option<DefId>,
[] fn trait_of_item: TraitOfItem(DefId) -> Option<DefId>,
- [] fn is_exported_symbol: IsExportedSymbol(DefId) -> bool,
[] fn item_body_nested_bodies: ItemBodyNestedBodies(DefId) -> ExternBodyNestedBodies,
[] fn const_is_rvalue_promotable_to_static: ConstIsRvaluePromotableToStatic(DefId) -> bool,
[] fn rvalue_promotable_map: RvaluePromotableMap(DefId) -> Lrc<ItemLocalSet>,
@@ -290,7 +289,23 @@ define_maps! { <'tcx>
[] fn lint_levels: lint_levels_node(CrateNum) -> Lrc<lint::LintLevelMap>,
[] fn impl_defaultness: ImplDefaultness(DefId) -> hir::Defaultness,
- [] fn exported_symbol_ids: ExportedSymbolIds(CrateNum) -> Lrc<DefIdSet>,
+
+ // The DefIds of all non-generic functions and statics in the given crate
+ // that can be reached from outside the crate.
+ //
+ // We expect this items to be available for being linked to.
+ //
+ // This query can also be called for LOCAL_CRATE. In this case it will
+ // compute which items will be reachable to other crates, taking into account
+ // the kind of crate that is currently compiled. Crates with only a
+ // C interface have fewer reachable things.
+ //
+ // Does not include external symbols that don't have a corresponding DefId,
+ // like the compiler-generated `main` function and so on.
+ [] fn reachable_non_generics: ReachableNonGenerics(CrateNum) -> Lrc<DefIdSet>,
+ [] fn is_reachable_non_generic: IsReachableNonGeneric(DefId) -> bool,
+
+
[] fn native_libraries: NativeLibraries(CrateNum) -> Lrc<Vec<NativeLibrary>>,
[] fn plugin_registrar_fn: PluginRegistrarFn(CrateNum) -> Option<DefId>,
[] fn derive_registrar_fn: DeriveRegistrarFn(CrateNum) -> Option<DefId>,
@@ -343,7 +358,7 @@ define_maps! { <'tcx>
[] fn all_crate_nums: all_crate_nums_node(CrateNum) -> Lrc<Vec<CrateNum>>,
[] fn exported_symbols: ExportedSymbols(CrateNum)
- -> Arc<Vec<(String, Option<DefId>, SymbolExportLevel)>>,
+ -> Arc<Vec<(ExportedSymbol, SymbolExportLevel)>>,
[] fn collect_and_partition_translation_items:
collect_and_partition_translation_items_node(CrateNum)
-> (Arc<DefIdSet>, Arc<Vec<Arc<CodegenUnit<'tcx>>>>),
diff --git a/src/librustc/ty/maps/plumbing.rs b/src/librustc/ty/maps/plumbing.rs
index 3443b9b61b2..13f286d6a26 100644
--- a/src/librustc/ty/maps/plumbing.rs
+++ b/src/librustc/ty/maps/plumbing.rs
@@ -851,7 +851,7 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>,
DepKind::RvaluePromotableMap => { force!(rvalue_promotable_map, def_id!()); }
DepKind::ImplParent => { force!(impl_parent, def_id!()); }
DepKind::TraitOfItem => { force!(trait_of_item, def_id!()); }
- DepKind::IsExportedSymbol => { force!(is_exported_symbol, def_id!()); }
+ DepKind::IsReachableNonGeneric => { force!(is_reachable_non_generic, def_id!()); }
DepKind::IsMirAvailable => { force!(is_mir_available, def_id!()); }
DepKind::ItemAttrs => { force!(item_attrs, def_id!()); }
DepKind::FnArgNames => { force!(fn_arg_names, def_id!()); }
@@ -868,7 +868,7 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>,
DepKind::GetPanicStrategy => { force!(panic_strategy, krate!()); }
DepKind::IsNoBuiltins => { force!(is_no_builtins, krate!()); }
DepKind::ImplDefaultness => { force!(impl_defaultness, def_id!()); }
- DepKind::ExportedSymbolIds => { force!(exported_symbol_ids, krate!()); }
+ DepKind::ReachableNonGenerics => { force!(reachable_non_generics, krate!()); }
DepKind::NativeLibraries => { force!(native_libraries, krate!()); }
DepKind::PluginRegistrarFn => { force!(plugin_registrar_fn, krate!()); }
DepKind::DeriveRegistrarFn => { force!(derive_registrar_fn, krate!()); }
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index f6f4e1ceb15..a7c55880e2e 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -2806,7 +2806,7 @@ impl<'tcx> DtorckConstraint<'tcx> {
}
}
-#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, RustcEncodable, RustcDecodable)]
pub struct SymbolName {
// FIXME: we don't rely on interning or equality here - better have
// this be a `&'tcx str`.
@@ -2817,6 +2817,14 @@ impl_stable_hash_for!(struct self::SymbolName {
name
});
+impl SymbolName {
+ pub fn new(name: &str) -> SymbolName {
+ SymbolName {
+ name: Symbol::intern(name).as_str()
+ }
+ }
+}
+
impl Deref for SymbolName {
type Target = str;
@@ -2828,3 +2836,9 @@ impl fmt::Display for SymbolName {
fmt::Display::fmt(&self.name, fmt)
}
}
+
+impl fmt::Debug for SymbolName {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ fmt::Display::fmt(&self.name, fmt)
+ }
+}
diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs
index 876e7e8dc31..789ecd0f613 100644
--- a/src/librustc_metadata/creader.rs
+++ b/src/librustc_metadata/creader.rs
@@ -225,9 +225,6 @@ impl<'a> CrateLoader<'a> {
crate_root.def_path_table.decode((&metadata, self.sess))
});
- let exported_symbols = crate_root.exported_symbols
- .decode((&metadata, self.sess))
- .collect();
let trait_impls = crate_root
.impls
.decode((&metadata, self.sess))
@@ -238,7 +235,6 @@ impl<'a> CrateLoader<'a> {
name,
extern_crate: Cell::new(None),
def_path_table: Lrc::new(def_path_table),
- exported_symbols,
trait_impls,
proc_macros: crate_root.macro_derive_registrar.map(|_| {
self.load_derive_macros(&crate_root, dylib.clone().map(|p| p.0), span)
diff --git a/src/librustc_metadata/cstore.rs b/src/librustc_metadata/cstore.rs
index 8b59eec0190..2e95c23b4ae 100644
--- a/src/librustc_metadata/cstore.rs
+++ b/src/librustc_metadata/cstore.rs
@@ -78,8 +78,6 @@ pub struct CrateMetadata {
/// compilation support.
pub def_path_table: Lrc<DefPathTable>,
- pub exported_symbols: FxHashSet<DefIndex>,
-
pub trait_impls: FxHashMap<(u32, DefIndex), schema::LazySeq<DefIndex>>,
pub dep_kind: Cell<DepKind>,
diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs
index 7b8194d9eab..0b50f5c4496 100644
--- a/src/librustc_metadata/cstore_impl.rs
+++ b/src/librustc_metadata/cstore_impl.rs
@@ -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};
@@ -27,10 +28,11 @@ use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE, CRATE_DEF_INDEX};
use rustc::hir::map::{DefKey, DefPath, DefPathHash};
use rustc::hir::map::blocks::FnLikeNode;
use rustc::hir::map::definitions::DefPathTable;
-use rustc::util::nodemap::{NodeSet, DefIdMap};
+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;
@@ -160,9 +162,6 @@ provide! { <'tcx> tcx, def_id, other, cdata,
fn_arg_names => { cdata.get_fn_arg_names(def_id.index) }
impl_parent => { cdata.get_parent_impl(def_id.index) }
trait_of_item => { cdata.get_trait_of_item(def_id.index) }
- is_exported_symbol => {
- cdata.exported_symbols.contains(&def_id.index)
- }
item_body_nested_bodies => { cdata.item_body_nested_bodies(def_id.index) }
const_is_rvalue_promotable_to_static => {
cdata.const_is_rvalue_promotable_to_static(def_id.index)
@@ -179,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) }
- exported_symbol_ids => { Lrc::new(cdata.get_exported_symbols()) }
+ 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| {
@@ -238,6 +251,19 @@ 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 custom derive crate, then we're not even going to
+ // link those in so we skip those crates.
+ if 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>) {
@@ -520,11 +546,10 @@ impl CrateStore for cstore::CStore {
fn encode_metadata<'a, 'tcx>(&self,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
- link_meta: &LinkMeta,
- reachable: &NodeSet)
+ link_meta: &LinkMeta)
-> EncodedMetadata
{
- encoder::encode_metadata(tcx, link_meta, reachable)
+ encoder::encode_metadata(tcx, link_meta)
}
fn metadata_encoding_version(&self) -> &[u8]
diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs
index 0c6a286e227..60a0d4e03b5 100644
--- a/src/librustc_metadata/decoder.rs
+++ b/src/librustc_metadata/decoder.rs
@@ -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,10 +1006,10 @@ impl<'a, 'tcx> CrateMetadata {
arg_names.decode(self).collect()
}
- pub fn get_exported_symbols(&self) -> DefIdSet {
- self.exported_symbols
- .iter()
- .map(|&index| self.local_def_id(index))
+ pub fn exported_symbols(&self) -> Vec<(ExportedSymbol, SymbolExportLevel)> {
+ self.root
+ .exported_symbols
+ .decode(self)
.collect()
}
diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs
index d3f046c5544..d19ab894591 100644
--- a/src/librustc_metadata/encoder.rs
+++ b/src/librustc_metadata/encoder.rs
@@ -20,14 +20,16 @@ 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,
+ metadata_symbol_name};
use rustc::middle::lang_items;
use rustc::mir;
use rustc::traits::specialization_graph;
-use rustc::ty::{self, Ty, TyCtxt, ReprOptions};
+use rustc::ty::{self, Ty, TyCtxt, ReprOptions, SymbolName};
use rustc::ty::codec::{self as ty_codec, TyEncoder};
use rustc::session::config::{self, CrateTypeProcMacro};
-use rustc::util::nodemap::{FxHashMap, NodeSet};
+use rustc::util::nodemap::FxHashMap;
use rustc_data_structures::stable_hasher::StableHasher;
use rustc_serialize::{Encodable, Encoder, SpecializedEncoder, opaque};
@@ -53,7 +55,6 @@ pub struct EncodeContext<'a, 'tcx: 'a> {
opaque: opaque::Encoder<'a>,
pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
link_meta: &'a LinkMeta,
- exported_symbols: &'a NodeSet,
lazy_state: LazyState,
type_shorthands: FxHashMap<Ty<'tcx>, usize>,
@@ -395,9 +396,10 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
// Encode exported symbols info.
i = self.position();
+ let exported_symbols = self.tcx.exported_symbols(LOCAL_CRATE);
let exported_symbols = self.tracked(
IsolatedEncoder::encode_exported_symbols,
- self.exported_symbols);
+ &exported_symbols);
let exported_symbols_bytes = self.position() - i;
// Encode and index the items.
@@ -1388,9 +1390,25 @@ 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_exported_symbols(&mut self, exported_symbols: &NodeSet) -> LazySeq<DefIndex> {
- let tcx = self.tcx;
- self.lazy_seq(exported_symbols.iter().map(|&id| tcx.hir.local_def_id(id).index))
+ fn encode_exported_symbols(&mut self,
+ exported_symbols: &[(ExportedSymbol, SymbolExportLevel)])
+ -> LazySeq<(ExportedSymbol, SymbolExportLevel)> {
+
+ // The metadata symbol name is special. It should not show up in
+ // downstream crates.
+ let metadata_symbol_name = SymbolName::new(&metadata_symbol_name(self.tcx));
+
+ self.lazy_seq(exported_symbols
+ .iter()
+ .filter(|&&(ref exported_symbol, _)| {
+ match *exported_symbol {
+ ExportedSymbol::NoDefId(symbol_name) => {
+ symbol_name != metadata_symbol_name
+ },
+ _ => true,
+ }
+ })
+ .cloned())
}
fn encode_dylib_dependency_formats(&mut self, _: ()) -> LazySeq<Option<LinkagePreference>> {
@@ -1663,8 +1681,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for ImplVisitor<'a, 'tcx> {
// generated regardless of trailing bytes that end up in it.
pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
- link_meta: &LinkMeta,
- exported_symbols: &NodeSet)
+ link_meta: &LinkMeta)
-> EncodedMetadata
{
let mut cursor = Cursor::new(vec![]);
@@ -1678,7 +1695,6 @@ pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
opaque: opaque::Encoder::new(&mut cursor),
tcx,
link_meta,
- exported_symbols,
lazy_state: LazyState::NoNode,
type_shorthands: Default::default(),
predicate_shorthands: Default::default(),
diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs
index c542f65dcec..ce94e4f912f 100644
--- a/src/librustc_metadata/schema.rs
+++ b/src/librustc_metadata/schema.rs
@@ -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 exported_symbols: LazySeq<DefIndex>,
+ pub exported_symbols: LazySeq<(ExportedSymbol, SymbolExportLevel)>,
+
pub index: LazySeq<index::Index>,
}
diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs
index eb4ba21489c..10c2f9f758f 100644
--- a/src/librustc_mir/monomorphize/collector.rs
+++ b/src/librustc_mir/monomorphize/collector.rs
@@ -736,7 +736,7 @@ fn should_monomorphize_locally<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, instance:
}
Some(_) => true,
None => {
- if tcx.is_exported_symbol(def_id) ||
+ if tcx.is_reachable_non_generic(def_id) ||
tcx.is_foreign_item(def_id)
{
// We can link to the item in question, no instance needed
@@ -984,7 +984,7 @@ impl<'b, 'a, 'v> RootCollector<'b, 'a, 'v> {
}
MonoItemCollectionMode::Lazy => {
self.entry_fn == Some(def_id) ||
- self.tcx.is_exported_symbol(def_id) ||
+ self.tcx.is_reachable_non_generic(def_id) ||
attr::contains_name(&self.tcx.get_attrs(def_id),
"rustc_std_internal_symbol")
}
diff --git a/src/librustc_mir/monomorphize/partitioning.rs b/src/librustc_mir/monomorphize/partitioning.rs
index 2b558e71483..d65c1e03298 100644
--- a/src/librustc_mir/monomorphize/partitioning.rs
+++ b/src/librustc_mir/monomorphize/partitioning.rs
@@ -363,7 +363,7 @@ fn place_root_translation_items<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
can_be_internalized = false;
Visibility::Hidden
} else if def_id.is_local() {
- if tcx.is_exported_symbol(def_id) {
+ if tcx.is_reachable_non_generic(def_id) {
can_be_internalized = false;
default_visibility(def_id)
} else {
@@ -385,7 +385,7 @@ fn place_root_translation_items<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
(Linkage::External, visibility)
}
MonoItem::Static(def_id) => {
- let visibility = if tcx.is_exported_symbol(def_id) {
+ let visibility = if tcx.is_reachable_non_generic(def_id) {
can_be_internalized = false;
default_visibility(def_id)
} else {
@@ -395,7 +395,7 @@ fn place_root_translation_items<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
}
MonoItem::GlobalAsm(node_id) => {
let def_id = tcx.hir.local_def_id(node_id);
- let visibility = if tcx.is_exported_symbol(def_id) {
+ let visibility = if tcx.is_reachable_non_generic(def_id) {
can_be_internalized = false;
default_visibility(def_id)
} else {
diff --git a/src/librustc_trans/back/linker.rs b/src/librustc_trans/back/linker.rs
index a3ff39a47a2..3fe667f1543 100644
--- a/src/librustc_trans/back/linker.rs
+++ b/src/librustc_trans/back/linker.rs
@@ -768,9 +768,9 @@ fn exported_symbols(tcx: TyCtxt, crate_type: CrateType) -> Vec<String> {
let mut symbols = Vec::new();
let export_threshold = symbol_export::crates_export_threshold(&[crate_type]);
- for &(ref name, _, level) in tcx.exported_symbols(LOCAL_CRATE).iter() {
+ for &(symbol, level) in tcx.exported_symbols(LOCAL_CRATE).iter() {
if level.is_below_threshold(export_threshold) {
- symbols.push(name.clone());
+ symbols.push(symbol.symbol_name(tcx).to_string());
}
}
@@ -782,9 +782,9 @@ fn exported_symbols(tcx: TyCtxt, crate_type: CrateType) -> Vec<String> {
// For each dependency that we are linking to statically ...
if *dep_format == Linkage::Static {
// ... we add its symbol list to our export list.
- for &(ref name, _, level) in tcx.exported_symbols(cnum).iter() {
+ for &(symbol, level) in tcx.exported_symbols(cnum).iter() {
if level.is_below_threshold(export_threshold) {
- symbols.push(name.clone());
+ symbols.push(symbol.symbol_name(tcx).to_string());
}
}
}
diff --git a/src/librustc_trans/back/lto.rs b/src/librustc_trans/back/lto.rs
index 3f9e9191cf0..f79651cef3e 100644
--- a/src/librustc_trans/back/lto.rs
+++ b/src/librustc_trans/back/lto.rs
@@ -113,7 +113,7 @@ pub(crate) fn run(cgcx: &CodegenContext,
Lto::No => panic!("didn't request LTO but we're doing LTO"),
};
- let symbol_filter = &|&(ref name, _, level): &(String, _, SymbolExportLevel)| {
+ let symbol_filter = &|&(ref name, level): &(String, SymbolExportLevel)| {
if level.is_below_threshold(export_threshold) {
let mut bytes = Vec::with_capacity(name.len() + 1);
bytes.extend(name.bytes());
diff --git a/src/librustc_trans/back/symbol_export.rs b/src/librustc_trans/back/symbol_export.rs
index 55ef4e7ed3a..739ae768ca2 100644
--- a/src/librustc_trans/back/symbol_export.rs
+++ b/src/librustc_trans/back/symbol_export.rs
@@ -11,33 +11,27 @@
use rustc_data_structures::sync::Lrc;
use std::sync::Arc;
-use base;
use monomorphize::Instance;
+use rustc::hir;
use rustc::hir::def_id::CrateNum;
use rustc::hir::def_id::{DefId, LOCAL_CRATE};
-use rustc::middle::exported_symbols::SymbolExportLevel;
+use rustc::middle::exported_symbols::{SymbolExportLevel, ExportedSymbol, metadata_symbol_name};
use rustc::session::config;
-use rustc::ty::TyCtxt;
+use rustc::ty::{TyCtxt, SymbolName};
use rustc::ty::maps::Providers;
-use rustc::util::nodemap::FxHashMap;
+use rustc::util::nodemap::{FxHashMap, DefIdSet};
use rustc_allocator::ALLOCATOR_METHODS;
use syntax::attr;
pub type ExportedSymbols = FxHashMap<
CrateNum,
- Arc<Vec<(String, Option<DefId>, SymbolExportLevel)>>,
+ Arc<Vec<(String, SymbolExportLevel)>>,
>;
pub fn threshold(tcx: TyCtxt) -> SymbolExportLevel {
crates_export_threshold(&tcx.sess.crate_types.borrow())
}
-pub fn metadata_symbol_name(tcx: TyCtxt) -> String {
- format!("rust_metadata_{}_{}",
- tcx.crate_name(LOCAL_CRATE),
- tcx.crate_disambiguator(LOCAL_CRATE).to_fingerprint().to_hex())
-}
-
fn crate_export_threshold(crate_type: config::CrateType) -> SymbolExportLevel {
match crate_type {
config::CrateTypeExecutable |
@@ -60,140 +54,203 @@ pub fn crates_export_threshold(crate_types: &[config::CrateType])
}
}
-pub fn provide(providers: &mut Providers) {
- providers.exported_symbol_ids = |tcx, cnum| {
- let export_threshold = threshold(tcx);
- Lrc::new(tcx.exported_symbols(cnum)
- .iter()
- .filter_map(|&(_, id, level)| {
- id.and_then(|id| {
- if level.is_below_threshold(export_threshold) {
- Some(id)
+fn reachable_non_generics_provider<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+ cnum: CrateNum)
+ -> Lrc<DefIdSet>
+{
+ assert_eq!(cnum, LOCAL_CRATE);
+
+ if !tcx.sess.opts.output_types.should_trans() {
+ return Lrc::new(DefIdSet())
+ }
+
+ let export_threshold = threshold(tcx);
+
+ // We already collect all potentially reachable non-generic items for
+ // `exported_symbols`. Now we just filter them down to what is actually
+ // exported for the given crate we are compiling.
+ let reachable_non_generics = tcx
+ .exported_symbols(LOCAL_CRATE)
+ .iter()
+ .filter_map(|&(exported_symbol, level)| {
+ if let ExportedSymbol::NonGeneric(def_id) = exported_symbol {
+ if level.is_below_threshold(export_threshold) {
+ return Some(def_id)
+ }
+ }
+
+ None
+ })
+ .collect();
+
+ Lrc::new(reachable_non_generics)
+}
+
+fn is_reachable_non_generic_provider<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+ def_id: DefId)
+ -> bool {
+ tcx.reachable_non_generics(def_id.krate).contains(&def_id)
+}
+
+fn exported_symbols_provider_local<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+ cnum: CrateNum)
+ -> Arc<Vec<(ExportedSymbol,
+ SymbolExportLevel)>>
+{
+ assert_eq!(cnum, LOCAL_CRATE);
+
+ if !tcx.sess.opts.output_types.should_trans() {
+ 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 reachable_non_generics: DefIdSet = tcx.reachable_set(LOCAL_CRATE).0
+ .iter()
+ .filter_map(|&node_id| {
+ // We want to ignore some FFI functions that are not exposed from
+ // this crate. Reachable FFI functions can be lumped into two
+ // categories:
+ //
+ // 1. Those that are included statically via a static library
+ // 2. Those included otherwise (e.g. dynamically or via a framework)
+ //
+ // Although our LLVM module is not literally emitting code for the
+ // statically included symbols, it's an export of our library which
+ // needs to be passed on to the linker and encoded in the metadata.
+ //
+ // As a result, if this id is an FFI item (foreign item) then we only
+ // let it through if it's included statically.
+ match tcx.hir.get(node_id) {
+ hir::map::NodeForeignItem(..) => {
+ let def_id = tcx.hir.local_def_id(node_id);
+ if tcx.is_statically_included_foreign_item(def_id) {
+ Some(def_id)
} else {
None
}
- })
- })
- .collect())
- };
-
- providers.is_exported_symbol = |tcx, id| {
- tcx.exported_symbol_ids(id.krate).contains(&id)
- };
-
- providers.exported_symbols = |tcx, cnum| {
- assert_eq!(cnum, LOCAL_CRATE);
- let local_exported_symbols = base::find_exported_symbols(tcx);
-
- let mut local_crate: Vec<_> = local_exported_symbols
- .iter()
- .map(|&node_id| {
- tcx.hir.local_def_id(node_id)
- })
- .map(|def_id| {
- let name = tcx.symbol_name(Instance::mono(tcx, def_id));
- let export_level = export_level(tcx, def_id);
- debug!("EXPORTED SYMBOL (local): {} ({:?})", name, export_level);
- (str::to_owned(&name), Some(def_id), export_level)
- })
- .collect();
-
- if let Some(_) = *tcx.sess.entry_fn.borrow() {
- local_crate.push(("main".to_string(),
- None,
- SymbolExportLevel::C));
- }
+ }
+
+ // Only consider nodes that actually have exported symbols.
+ hir::map::NodeItem(&hir::Item {
+ node: hir::ItemStatic(..),
+ ..
+ }) |
+ hir::map::NodeItem(&hir::Item {
+ node: hir::ItemFn(..), ..
+ }) |
+ hir::map::NodeImplItem(&hir::ImplItem {
+ node: hir::ImplItemKind::Method(..),
+ ..
+ }) => {
+ let def_id = tcx.hir.local_def_id(node_id);
+ let generics = tcx.generics_of(def_id);
+ if (generics.parent_types == 0 && generics.types.is_empty()) &&
+ // Functions marked with #[inline] are only ever translated
+ // with "internal" linkage and are never exported.
+ !Instance::mono(tcx, def_id).def.requires_local(tcx) {
+ Some(def_id)
+ } else {
+ None
+ }
+ }
- if tcx.sess.allocator_kind.get().is_some() {
- for method in ALLOCATOR_METHODS {
- local_crate.push((format!("__rust_{}", method.name),
- None,
- SymbolExportLevel::Rust));
+ _ => None
}
- }
+ })
+ .collect();
- if let Some(id) = tcx.sess.derive_registrar_fn.get() {
- let def_id = tcx.hir.local_def_id(id);
- let disambiguator = tcx.sess.local_crate_disambiguator();
- let registrar = tcx.sess.generate_derive_registrar_symbol(disambiguator);
- local_crate.push((registrar, Some(def_id), SymbolExportLevel::C));
- }
+ let mut symbols: Vec<_> = reachable_non_generics
+ .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 (local): {} ({:?})",
+ tcx.symbol_name(Instance::mono(tcx, def_id)),
+ export_level);
+ (ExportedSymbol::NonGeneric(def_id), export_level)
+ })
+ .collect();
+
+ if let Some(id) = tcx.sess.derive_registrar_fn.get() {
+ let def_id = tcx.hir.local_def_id(id);
+ symbols.push((ExportedSymbol::NonGeneric(def_id), SymbolExportLevel::C));
+ }
+
+ if let Some(id) = tcx.sess.plugin_registrar_fn.get() {
+ let def_id = tcx.hir.local_def_id(id);
+ symbols.push((ExportedSymbol::NonGeneric(def_id), SymbolExportLevel::C));
+ }
+
+ if let Some(_) = *tcx.sess.entry_fn.borrow() {
+ let symbol_name = "main".to_string();
+ let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new(&symbol_name));
+
+ symbols.push((exported_symbol, SymbolExportLevel::C));
+ }
+
+ if tcx.sess.allocator_kind.get().is_some() {
+ for method in ALLOCATOR_METHODS {
+ let symbol_name = format!("__rust_{}", method.name);
+ let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new(&symbol_name));
- if tcx.sess.crate_types.borrow().contains(&config::CrateTypeDylib) {
- local_crate.push((metadata_symbol_name(tcx),
- None,
- SymbolExportLevel::Rust));
+ symbols.push((exported_symbol, SymbolExportLevel::Rust));
}
+ }
+
+ if tcx.sess.crate_types.borrow().contains(&config::CrateTypeDylib) {
+ let symbol_name = metadata_symbol_name(tcx);
+ let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new(&symbol_name));
- // Sort so we get a stable incr. comp. hash.
- local_crate.sort_unstable_by(|&(ref name1, ..), &(ref name2, ..)| {
- name1.cmp(name2)
- });
+ symbols.push((exported_symbol, SymbolExportLevel::Rust));
+ }
- Arc::new(local_crate)
- };
+ // Sort so we get a stable incr. comp. hash.
+ symbols.sort_unstable_by(|&(ref symbol1, ..), &(ref symbol2, ..)| {
+ symbol1.compare_stable(tcx, symbol2)
+ });
- providers.symbol_export_level = export_level;
+ Arc::new(symbols)
}
-pub fn provide_extern(providers: &mut Providers) {
- providers.exported_symbols = |tcx, cnum| {
- // 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())
- }
+pub fn provide(providers: &mut Providers) {
+ providers.reachable_non_generics = reachable_non_generics_provider;
+ providers.is_reachable_non_generic = is_reachable_non_generic_provider;
+ providers.exported_symbols = exported_symbols_provider_local;
+ providers.symbol_export_level = symbol_export_level_provider;
+}
- // 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
- .exported_symbol_ids(cnum)
- .iter()
- .map(|&def_id| {
- let name = tcx.symbol_name(Instance::mono(tcx, def_id));
- let export_level = if special_runtime_crate {
- // 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 {
- export_level(tcx, def_id)
- };
- debug!("EXPORTED SYMBOL (re-export): {} ({:?})", name, export_level);
- (str::to_owned(&name), Some(def_id), export_level)
- })
- .collect();
-
- // Sort so we get a stable incr. comp. hash.
- crate_exports.sort_unstable_by(|&(ref name1, ..), &(ref name2, ..)| {
- name1.cmp(name2)
- });
-
- Arc::new(crate_exports)
- };
- providers.symbol_export_level = export_level;
+pub fn provide_extern(providers: &mut Providers) {
+ providers.is_reachable_non_generic = is_reachable_non_generic_provider;
+ providers.symbol_export_level = symbol_export_level_provider;
}
-fn export_level(tcx: TyCtxt, sym_def_id: DefId) -> SymbolExportLevel {
+fn symbol_export_level_provider(tcx: TyCtxt, sym_def_id: DefId) -> SymbolExportLevel {
// We export anything that's not mangled at the "C" layer as it probably has
// to do with ABI concerns. We do not, however, apply such treatment to
// special symbols in the standard library for various plumbing between
diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs
index 78b26a37485..c0561ff0c17 100644
--- a/src/librustc_trans/back/write.rs
+++ b/src/librustc_trans/back/write.rs
@@ -1332,20 +1332,31 @@ fn start_executing_work(tcx: TyCtxt,
let coordinator_send = tcx.tx_to_llvm_workers.clone();
let sess = tcx.sess;
- let exported_symbols = match sess.lto() {
- Lto::No => None,
- Lto::ThinLocal => {
- let mut exported_symbols = FxHashMap();
- exported_symbols.insert(LOCAL_CRATE, tcx.exported_symbols(LOCAL_CRATE));
- Some(Arc::new(exported_symbols))
- }
- Lto::Yes | Lto::Fat | Lto::Thin => {
- let mut exported_symbols = FxHashMap();
- exported_symbols.insert(LOCAL_CRATE, tcx.exported_symbols(LOCAL_CRATE));
- for &cnum in tcx.crates().iter() {
- exported_symbols.insert(cnum, tcx.exported_symbols(cnum));
+ // Compute the set of symbols we need to retain when doing LTO (if we need to)
+ let exported_symbols = {
+ let mut exported_symbols = FxHashMap();
+
+ let copy_symbols = |cnum| {
+ let symbols = tcx.exported_symbols(cnum)
+ .iter()
+ .map(|&(s, lvl)| (s.symbol_name(tcx).to_string(), lvl))
+ .collect();
+ Arc::new(symbols)
+ };
+
+ match sess.lto() {
+ Lto::No => None,
+ Lto::ThinLocal => {
+ exported_symbols.insert(LOCAL_CRATE, copy_symbols(LOCAL_CRATE));
+ Some(Arc::new(exported_symbols))
+ }
+ Lto::Yes | Lto::Fat | Lto::Thin => {
+ exported_symbols.insert(LOCAL_CRATE, copy_symbols(LOCAL_CRATE));
+ for &cnum in tcx.crates().iter() {
+ exported_symbols.insert(cnum, copy_symbols(cnum));
+ }
+ Some(Arc::new(exported_symbols))
}
- Some(Arc::new(exported_symbols))
}
};
diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs
index c0785f53937..beb7a091bdc 100644
--- a/src/librustc_trans/base.rs
+++ b/src/librustc_trans/base.rs
@@ -30,7 +30,6 @@ use super::ModuleKind;
use abi;
use back::link;
-use back::symbol_export;
use back::write::{self, OngoingCrateTranslation, create_target_machine};
use llvm::{ContextRef, ModuleRef, ValueRef, Vector, get_param};
use llvm;
@@ -45,6 +44,7 @@ use rustc::ty::maps::Providers;
use rustc::dep_graph::{DepNode, DepConstructor};
use rustc::ty::subst::Kind;
use rustc::middle::cstore::{self, LinkMeta, LinkagePreference};
+use rustc::middle::exported_symbols;
use rustc::util::common::{time, print_time_passes_entry};
use rustc::session::config::{self, NoDebugInfo};
use rustc::session::Session;
@@ -70,7 +70,7 @@ use time_graph;
use trans_item::{MonoItem, BaseMonoItemExt, MonoItemExt, DefPathBasedNames};
use type_::Type;
use type_of::LayoutLlvmExt;
-use rustc::util::nodemap::{NodeSet, FxHashMap, FxHashSet, DefIdSet};
+use rustc::util::nodemap::{FxHashMap, FxHashSet, DefIdSet};
use CrateInfo;
use std::any::Any;
@@ -89,7 +89,7 @@ use syntax::ast;
use mir::operand::OperandValue;
-pub use rustc_trans_utils::{find_exported_symbols, check_for_rustc_errors_attr};
+pub use rustc_trans_utils::check_for_rustc_errors_attr;
pub use rustc_mir::monomorphize::item::linkage_by_name;
pub struct StatRecorder<'a, 'tcx: 'a> {
@@ -606,8 +606,7 @@ fn contains_null(s: &str) -> bool {
fn write_metadata<'a, 'gcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>,
llmod_id: &str,
- link_meta: &LinkMeta,
- exported_symbols: &NodeSet)
+ link_meta: &LinkMeta)
-> (ContextRef, ModuleRef, EncodedMetadata) {
use std::io::Write;
use flate2::Compression;
@@ -643,7 +642,7 @@ fn write_metadata<'a, 'gcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>,
EncodedMetadata::new());
}
- let metadata = tcx.encode_metadata(link_meta, exported_symbols);
+ let metadata = tcx.encode_metadata(link_meta);
if kind == MetadataKind::Uncompressed {
return (metadata_llcx, metadata_llmod, metadata);
}
@@ -655,7 +654,7 @@ fn write_metadata<'a, 'gcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>,
let llmeta = C_bytes_in_context(metadata_llcx, &compressed);
let llconst = C_struct_in_context(metadata_llcx, &[llmeta], false);
- let name = symbol_export::metadata_symbol_name(tcx);
+ let name = exported_symbols::metadata_symbol_name(tcx);
let buf = CString::new(name).unwrap();
let llglobal = unsafe {
llvm::LLVMAddGlobal(metadata_llmod, val_ty(llconst).to_ref(), buf.as_ptr())
@@ -718,13 +717,12 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
let crate_hash = tcx.crate_hash(LOCAL_CRATE);
let link_meta = link::build_link_meta(crate_hash);
- let exported_symbol_node_ids = find_exported_symbols(tcx);
// Translate the metadata.
let llmod_id = "metadata";
let (metadata_llcx, metadata_llmod, metadata) =
time(tcx.sess.time_passes(), "write metadata", || {
- write_metadata(tcx, llmod_id, &link_meta, &exported_symbol_node_ids)
+ write_metadata(tcx, llmod_id, &link_meta)
});
let metadata_module = ModuleTranslation {
diff --git a/src/librustc_trans/callee.rs b/src/librustc_trans/callee.rs
index 8c40aa6a2ac..54cc561e804 100644
--- a/src/librustc_trans/callee.rs
+++ b/src/librustc_trans/callee.rs
@@ -151,7 +151,7 @@ pub fn get_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
if cx.tcx.is_translated_item(instance_def_id) {
if instance_def_id.is_local() {
- if !cx.tcx.is_exported_symbol(instance_def_id) {
+ if !cx.tcx.is_reachable_non_generic(instance_def_id) {
llvm::LLVMRustSetVisibility(llfn, llvm::Visibility::Hidden);
}
} else {
diff --git a/src/librustc_trans/consts.rs b/src/librustc_trans/consts.rs
index 1608c4a87bf..fd9cb8c5a6b 100644
--- a/src/librustc_trans/consts.rs
+++ b/src/librustc_trans/consts.rs
@@ -134,7 +134,7 @@ pub fn get_static(cx: &CodegenCx, def_id: DefId) -> ValueRef {
let g = declare::define_global(cx, &sym[..], llty).unwrap();
- if !cx.tcx.is_exported_symbol(def_id) {
+ if !cx.tcx.is_reachable_non_generic(def_id) {
unsafe {
llvm::LLVMRustSetVisibility(g, llvm::Visibility::Hidden);
}
diff --git a/src/librustc_trans/debuginfo/utils.rs b/src/librustc_trans/debuginfo/utils.rs
index 9559cd4d9ea..0a3f06b55f1 100644
--- a/src/librustc_trans/debuginfo/utils.rs
+++ b/src/librustc_trans/debuginfo/utils.rs
@@ -32,7 +32,7 @@ pub fn is_node_local_to_unit(cx: &CodegenCx, def_id: DefId) -> bool
// visible). It might better to use the `exported_items` set from
// `driver::CrateAnalysis` in the future, but (atm) this set is not
// available in the translation pass.
- !cx.tcx.is_exported_symbol(def_id)
+ !cx.tcx.is_reachable_non_generic(def_id)
}
#[allow(non_snake_case)]
diff --git a/src/librustc_trans_utils/lib.rs b/src/librustc_trans_utils/lib.rs
index bfecb201983..d636a5f2e64 100644
--- a/src/librustc_trans_utils/lib.rs
+++ b/src/librustc_trans_utils/lib.rs
@@ -44,11 +44,7 @@ extern crate rustc_data_structures;
pub extern crate rustc as __rustc;
-use rustc::ty::{TyCtxt, Instance};
-use rustc::hir;
-use rustc::hir::def_id::LOCAL_CRATE;
-use rustc::hir::map as hir_map;
-use rustc::util::nodemap::NodeSet;
+use rustc::ty::TyCtxt;
pub mod diagnostics;
pub mod link;
@@ -70,53 +66,4 @@ pub fn check_for_rustc_errors_attr(tcx: TyCtxt) {
}
}
-/// The context provided lists a set of reachable ids as calculated by
-/// middle::reachable, but this contains far more ids and symbols than we're
-/// actually exposing from the object file. This function will filter the set in
-/// the context to the set of ids which correspond to symbols that are exposed
-/// from the object file being generated.
-///
-/// This list is later used by linkers to determine the set of symbols needed to
-/// be exposed from a dynamic library and it's also encoded into the metadata.
-pub fn find_exported_symbols<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> NodeSet {
- tcx.reachable_set(LOCAL_CRATE).0.iter().cloned().filter(|&id| {
- // Next, we want to ignore some FFI functions that are not exposed from
- // this crate. Reachable FFI functions can be lumped into two
- // categories:
- //
- // 1. Those that are included statically via a static library
- // 2. Those included otherwise (e.g. dynamically or via a framework)
- //
- // Although our LLVM module is not literally emitting code for the
- // statically included symbols, it's an export of our library which
- // needs to be passed on to the linker and encoded in the metadata.
- //
- // As a result, if this id is an FFI item (foreign item) then we only
- // let it through if it's included statically.
- match tcx.hir.get(id) {
- hir_map::NodeForeignItem(..) => {
- let def_id = tcx.hir.local_def_id(id);
- tcx.is_statically_included_foreign_item(def_id)
- }
-
- // Only consider nodes that actually have exported symbols.
- hir_map::NodeItem(&hir::Item {
- node: hir::ItemStatic(..), .. }) |
- hir_map::NodeItem(&hir::Item {
- node: hir::ItemFn(..), .. }) |
- hir_map::NodeImplItem(&hir::ImplItem {
- node: hir::ImplItemKind::Method(..), .. }) => {
- let def_id = tcx.hir.local_def_id(id);
- let generics = tcx.generics_of(def_id);
- (generics.parent_types == 0 && generics.types.is_empty()) &&
- // Functions marked with #[inline] are only ever translated
- // with "internal" linkage and are never exported.
- !Instance::mono(tcx, def_id).def.requires_local(tcx)
- }
-
- _ => false
- }
- }).collect()
-}
-
__build_diagnostic_array! { librustc_trans_utils, DIAGNOSTICS }
diff --git a/src/librustc_trans_utils/trans_crate.rs b/src/librustc_trans_utils/trans_crate.rs
index 419371ba3e3..7b2cbe140ae 100644
--- a/src/librustc_trans_utils/trans_crate.rs
+++ b/src/librustc_trans_utils/trans_crate.rs
@@ -247,8 +247,7 @@ impl TransCrate for MetadataOnlyTransCrate {
tcx.sess.abort_if_errors();
let link_meta = build_link_meta(tcx.crate_hash(LOCAL_CRATE));
- let exported_symbols = ::find_exported_symbols(tcx);
- let metadata = tcx.encode_metadata(&link_meta, &exported_symbols);
+ let metadata = tcx.encode_metadata(&link_meta);
box OngoingCrateTranslation {
metadata: metadata,