mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-28 02:57:37 +00:00
Compute symbol names more lazily.
This commit is contained in:
parent
33d5da1ee4
commit
aec6c85b0c
@ -8,6 +8,10 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use hir::def_id::DefId;
|
||||
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.
|
||||
@ -34,3 +38,52 @@ impl SymbolExportLevel {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Eq, PartialEq, Debug, Copy, Clone)]
|
||||
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)
|
||||
});
|
||||
|
@ -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};
|
||||
@ -358,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>>>>),
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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());
|
||||
|
@ -15,9 +15,9 @@ 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};
|
||||
use rustc::session::config;
|
||||
use rustc::ty::TyCtxt;
|
||||
use rustc::ty::{TyCtxt, SymbolName};
|
||||
use rustc::ty::maps::Providers;
|
||||
use rustc::util::nodemap::{FxHashMap, DefIdSet};
|
||||
use rustc_allocator::ALLOCATOR_METHODS;
|
||||
@ -25,7 +25,7 @@ use syntax::attr;
|
||||
|
||||
pub type ExportedSymbols = FxHashMap<
|
||||
CrateNum,
|
||||
Arc<Vec<(String, Option<DefId>, SymbolExportLevel)>>,
|
||||
Arc<Vec<(String, SymbolExportLevel)>>,
|
||||
>;
|
||||
|
||||
pub fn threshold(tcx: TyCtxt) -> SymbolExportLevel {
|
||||
@ -78,9 +78,10 @@ fn reachable_non_generics_provider<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
let reachable_non_generics = tcx
|
||||
.exported_symbols(LOCAL_CRATE)
|
||||
.iter()
|
||||
.filter_map(|&(_, opt_def_id, level)| {
|
||||
if let Some(def_id) = opt_def_id {
|
||||
if level.is_below_threshold(export_threshold) {
|
||||
.filter_map(|&(exported_symbol, _)| {
|
||||
if let ExportedSymbol::NonGeneric(def_id) = exported_symbol {
|
||||
if tcx.symbol_export_level(def_id)
|
||||
.is_below_threshold(export_threshold) {
|
||||
return Some(def_id)
|
||||
}
|
||||
}
|
||||
@ -100,8 +101,7 @@ fn is_reachable_non_generic_provider<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
|
||||
fn exported_symbols_provider_local<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
cnum: CrateNum)
|
||||
-> Arc<Vec<(String,
|
||||
Option<DefId>,
|
||||
-> Arc<Vec<(ExportedSymbol,
|
||||
SymbolExportLevel)>>
|
||||
{
|
||||
assert_eq!(cnum, LOCAL_CRATE);
|
||||
@ -176,34 +176,40 @@ fn exported_symbols_provider_local<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
let mut symbols: Vec<_> = reachable_non_generics
|
||||
.iter()
|
||||
.map(|&def_id| {
|
||||
let name = tcx.symbol_name(Instance::mono(tcx, def_id));
|
||||
let export_level = tcx.symbol_export_level(def_id);
|
||||
debug!("EXPORTED SYMBOL (local): {} ({:?})", name, export_level);
|
||||
(str::to_owned(&name), Some(def_id), export_level)
|
||||
debug!("EXPORTED SYMBOL (local): {} ({:?})",
|
||||
tcx.symbol_name(Instance::mono(tcx, def_id)),
|
||||
export_level);
|
||||
(ExportedSymbol::NonGeneric(def_id), export_level)
|
||||
})
|
||||
.collect();
|
||||
|
||||
if let Some(_) = *tcx.sess.entry_fn.borrow() {
|
||||
symbols.push(("main".to_string(), None, SymbolExportLevel::C));
|
||||
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 {
|
||||
symbols.push((format!("__rust_{}", method.name),
|
||||
None,
|
||||
SymbolExportLevel::Rust));
|
||||
let symbol_name = format!("__rust_{}", method.name);
|
||||
let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new(&symbol_name));
|
||||
|
||||
symbols.push((exported_symbol, SymbolExportLevel::Rust));
|
||||
}
|
||||
}
|
||||
|
||||
if tcx.sess.crate_types.borrow().contains(&config::CrateTypeDylib) {
|
||||
symbols.push((metadata_symbol_name(tcx),
|
||||
None,
|
||||
SymbolExportLevel::Rust));
|
||||
let symbol_name = metadata_symbol_name(tcx);
|
||||
let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new(&symbol_name));
|
||||
|
||||
symbols.push((exported_symbol, SymbolExportLevel::Rust));
|
||||
}
|
||||
|
||||
// Sort so we get a stable incr. comp. hash.
|
||||
symbols.sort_unstable_by(|&(ref name1, ..), &(ref name2, ..)| {
|
||||
name1.cmp(name2)
|
||||
symbols.sort_unstable_by(|&(ref symbol1, ..), &(ref symbol2, ..)| {
|
||||
symbol1.compare_stable(tcx, symbol2)
|
||||
});
|
||||
|
||||
Arc::new(symbols)
|
||||
@ -218,8 +224,7 @@ pub fn provide(providers: &mut Providers) {
|
||||
|
||||
fn exported_symbols_provider_extern<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
cnum: CrateNum)
|
||||
-> Arc<Vec<(String,
|
||||
Option<DefId>,
|
||||
-> Arc<Vec<(ExportedSymbol,
|
||||
SymbolExportLevel)>>
|
||||
{
|
||||
// If this crate is a plugin and/or a custom derive crate, then
|
||||
@ -243,8 +248,8 @@ fn exported_symbols_provider_extern<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
.reachable_non_generics(cnum)
|
||||
.iter()
|
||||
.map(|&def_id| {
|
||||
let name = tcx.symbol_name(Instance::mono(tcx, 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
|
||||
@ -262,14 +267,18 @@ fn exported_symbols_provider_extern<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
} else {
|
||||
tcx.symbol_export_level(def_id)
|
||||
};
|
||||
debug!("EXPORTED SYMBOL (re-export): {} ({:?})", name, export_level);
|
||||
(str::to_owned(&name), Some(def_id), export_level)
|
||||
|
||||
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 name1, ..), &(ref name2, ..)| {
|
||||
name1.cmp(name2)
|
||||
crate_exports.sort_unstable_by(|&(ref symbol1, ..), &(ref symbol2, ..)| {
|
||||
symbol1.compare_stable(tcx, symbol2)
|
||||
});
|
||||
|
||||
Arc::new(crate_exports)
|
||||
|
@ -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))
|
||||
}
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user