From afb85cfd33a6ef52edf8707aea12d952a64bb84c Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 13 Sep 2017 13:22:20 -0700 Subject: [PATCH] rustc: Mostly remove `ExportedSymbols` This is a big map that ends up inside of a `CrateContext` during translation for all codegen units. This means that any change to the map may end up causing an incremental recompilation of a codegen unit! In order to reduce the amount of dependencies here between codegen units and the actual input crate this commit refactors dealing with exported symbols and such into various queries. The new queries are largely based on existing queries with filled out implementations for the local crate in addition to external crates, but the main idea is that while translating codegen untis no unit needs the entire set of exported symbols, instead they only need queries about particulare `DefId` instances every now and then. The linking stage, however, still generates a full list of all exported symbols from all crates, but that's going to always happen unconditionally anyway, so no news there! --- src/librustc/dep_graph/dep_node.rs | 2 +- src/librustc/middle/cstore.rs | 5 +- src/librustc/middle/exported_symbols.rs | 60 +------ src/librustc/ty/context.rs | 6 - src/librustc/ty/maps.rs | 16 +- src/librustc_metadata/decoder.rs | 3 +- src/librustc_trans/back/linker.rs | 49 ++--- src/librustc_trans/back/lto.rs | 15 +- src/librustc_trans/back/symbol_export.rs | 216 +++++++++++++---------- src/librustc_trans/back/write.rs | 46 +++-- src/librustc_trans/base.rs | 71 ++------ src/librustc_trans/callee.rs | 4 +- src/librustc_trans/collector.rs | 12 +- src/librustc_trans/consts.rs | 2 +- src/librustc_trans/context.rs | 12 +- src/librustc_trans/debuginfo/utils.rs | 3 +- src/librustc_trans/lib.rs | 9 +- src/librustc_trans/partitioning.rs | 15 +- 18 files changed, 233 insertions(+), 313 deletions(-) diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index 3a534ef93ad6d..bfbf280d6ddba 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -575,7 +575,7 @@ define_dep_nodes!( <'tcx> [] MaybeUnusedExternCrates, [] StabilityIndex, [] AllCrateNums, - [] ExportedSymbols, + [] ExportedSymbols(CrateNum), [] CollectAndPartitionTranslationItems, [] ExportName(DefId), [] ContainsExternIndicator(DefId), diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index a7d874386d1c9..bea6ef4dc11ce 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -366,8 +366,9 @@ pub trait CrateLoader { // In order to get this left-to-right dependency ordering, we perform a // topological sort of all crates putting the leaves at the right-most // positions. -pub fn used_crates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - prefer: LinkagePreference) -> Vec<(CrateNum, LibSource)> { +pub fn used_crates(tcx: TyCtxt, prefer: LinkagePreference) + -> Vec<(CrateNum, LibSource)> +{ let mut libs = tcx.crates() .iter() .cloned() diff --git a/src/librustc/middle/exported_symbols.rs b/src/librustc/middle/exported_symbols.rs index 7f03f8a5a2986..230878f854595 100644 --- a/src/librustc/middle/exported_symbols.rs +++ b/src/librustc/middle/exported_symbols.rs @@ -8,9 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use util::nodemap::{FxHashMap, NodeSet}; -use hir::def_id::{DefId, CrateNum}; - /// 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. @@ -22,56 +19,13 @@ pub enum SymbolExportLevel { Rust, } -/// The set of symbols exported from each crate in the crate graph. -#[derive(Debug)] -pub struct ExportedSymbols { - pub export_threshold: SymbolExportLevel, - exports: FxHashMap>, - local_exports: NodeSet, -} - -impl ExportedSymbols { - pub fn new(export_threshold: SymbolExportLevel, - exports: FxHashMap>, - local_exports: NodeSet) -> ExportedSymbols { - ExportedSymbols { - export_threshold, - exports, - local_exports, - } - } - - pub fn local_exports(&self) -> &NodeSet { - &self.local_exports - } - - pub fn exported_symbols(&self, cnum: CrateNum) - -> &[(String, DefId, SymbolExportLevel)] - { - match self.exports.get(&cnum) { - Some(exports) => exports, - None => &[] - } - } - - pub fn for_each_exported_symbol(&self, cnum: CrateNum, mut f: F) - where F: FnMut(&str, DefId, SymbolExportLevel) - { - for &(ref name, def_id, export_level) in self.exported_symbols(cnum) { - if is_below_threshold(export_level, self.export_threshold) { - f(&name, def_id, export_level) - } +impl SymbolExportLevel { + pub fn is_below_threshold(self, threshold: SymbolExportLevel) -> bool { + if threshold == SymbolExportLevel::Rust { + // We export everything from Rust dylibs + true + } else { + self == SymbolExportLevel::C } } } - -pub fn is_below_threshold(level: SymbolExportLevel, - threshold: SymbolExportLevel) - -> bool { - if threshold == SymbolExportLevel::Rust { - // We export everything from Rust dylibs - true - } else { - level == SymbolExportLevel::C - } -} diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index af5c37e0f1605..fb0cdab0b6a0f 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -27,7 +27,6 @@ use middle::cstore::EncodedMetadata; use middle::free_region::FreeRegionMap; use middle::lang_items; use middle::resolve_lifetime::{self, ObjectLifetimeDefault}; -use middle::exported_symbols::ExportedSymbols; use middle::stability; use mir::Mir; use mir::transform::Passes; @@ -65,7 +64,6 @@ use std::mem; use std::ops::Deref; use std::iter; use std::rc::Rc; -use std::sync::Arc; use syntax::abi; use syntax::ast::{self, Name, NodeId}; use syntax::attr; @@ -1220,10 +1218,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { pub fn crate_data_as_rc_any(self, cnum: CrateNum) -> Rc { self.cstore.crate_data_as_rc_any(cnum) } - - pub fn exported_symbols(self) -> Arc { - self.exported_symbol_set(LOCAL_CRATE) - } } impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> { diff --git a/src/librustc/ty/maps.rs b/src/librustc/ty/maps.rs index 75c20a25131ab..dd6d90503ef1b 100644 --- a/src/librustc/ty/maps.rs +++ b/src/librustc/ty/maps.rs @@ -23,7 +23,7 @@ use middle::region; use middle::resolve_lifetime::{Region, ObjectLifetimeDefault}; use middle::stability::{self, DeprecationEntry}; use middle::lang_items::{LanguageItems, LangItem}; -use middle::exported_symbols::ExportedSymbols; +use middle::exported_symbols::SymbolExportLevel; use middle::trans::{TransItem, CodegenUnit}; use mir; use mir::transform::{MirSuite, MirPassIndex}; @@ -748,9 +748,9 @@ impl<'tcx> QueryDescription for queries::all_crate_nums<'tcx> { } } -impl<'tcx> QueryDescription for queries::exported_symbol_set<'tcx> { +impl<'tcx> QueryDescription for queries::exported_symbols<'tcx> { fn describe(_tcx: TyCtxt, _: CrateNum) -> String { - format!("exported symbol set") + format!("exported_symbols") } } @@ -1337,7 +1337,7 @@ define_maps! { <'tcx> [] fn lint_levels: lint_levels_node(CrateNum) -> Rc, [] fn impl_defaultness: ImplDefaultness(DefId) -> hir::Defaultness, - [] fn exported_symbol_ids: ExportedSymbolIds(CrateNum) -> Rc>, + [] fn exported_symbol_ids: ExportedSymbolIds(CrateNum) -> Rc, [] fn native_libraries: NativeLibraries(CrateNum) -> Rc>, [] fn plugin_registrar_fn: PluginRegistrarFn(CrateNum) -> Option, [] fn derive_registrar_fn: DeriveRegistrarFn(CrateNum) -> Option, @@ -1387,8 +1387,8 @@ define_maps! { <'tcx> [] fn stability_index: stability_index_node(CrateNum) -> Rc>, [] fn all_crate_nums: all_crate_nums_node(CrateNum) -> Rc>, - [] fn exported_symbol_set: exported_symbol_set_node(CrateNum) - -> Arc, + [] fn exported_symbols: ExportedSymbols(CrateNum) + -> Arc>, [] fn collect_and_partition_translation_items: collect_and_partition_translation_items_node(CrateNum) -> (Arc>>, Vec>>), @@ -1508,10 +1508,6 @@ fn all_crate_nums_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> { DepConstructor::AllCrateNums } -fn exported_symbol_set_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> { - DepConstructor::ExportedSymbols -} - fn collect_and_partition_translation_items_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> { DepConstructor::CollectAndPartitionTranslationItems } diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 689f9f5b24430..1c4f1c6348689 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -24,6 +24,7 @@ use rustc::middle::lang_items; use rustc::session::Session; use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::subst::Substs; +use rustc::util::nodemap::DefIdSet; use rustc::mir::Mir; @@ -1017,7 +1018,7 @@ impl<'a, 'tcx> CrateMetadata { arg_names.decode(self).collect() } - pub fn get_exported_symbols(&self) -> Vec { + pub fn get_exported_symbols(&self) -> DefIdSet { self.exported_symbols .iter() .map(|&index| self.local_def_id(index)) diff --git a/src/librustc_trans/back/linker.rs b/src/librustc_trans/back/linker.rs index 1eb3e86a15b81..239b488fabe0f 100644 --- a/src/librustc_trans/back/linker.rs +++ b/src/librustc_trans/back/linker.rs @@ -15,16 +15,15 @@ use std::io::prelude::*; use std::io::{self, BufWriter}; use std::path::{Path, PathBuf}; -use context::SharedCrateContext; - use back::archive; use back::command::Command; -use rustc::middle::dependency_format::Linkage; -use rustc::middle::exported_symbols::ExportedSymbols; +use back::symbol_export; use rustc::hir::def_id::{LOCAL_CRATE, CrateNum}; -use rustc_back::LinkerFlavor; +use rustc::middle::dependency_format::Linkage; use rustc::session::Session; use rustc::session::config::{self, CrateType, OptLevel, DebugInfoLevel}; +use rustc::ty::TyCtxt; +use rustc_back::LinkerFlavor; use serialize::{json, Encoder}; /// For all the linkers we support, and information they might @@ -33,19 +32,18 @@ pub struct LinkerInfo { exports: HashMap>, } -impl<'a, 'tcx> LinkerInfo { - pub fn new(scx: &SharedCrateContext<'a, 'tcx>) -> LinkerInfo { - let exports = scx.tcx().exported_symbols(); +impl LinkerInfo { + pub fn new(tcx: TyCtxt) -> LinkerInfo { LinkerInfo { - exports: scx.sess().crate_types.borrow().iter().map(|&c| { - (c, exported_symbols(scx, &exports, c)) + exports: tcx.sess.crate_types.borrow().iter().map(|&c| { + (c, exported_symbols(tcx, c)) }).collect(), } } - pub fn to_linker(&'a self, - cmd: Command, - sess: &'a Session) -> Box { + pub fn to_linker<'a>(&'a self, + cmd: Command, + sess: &'a Session) -> Box { match sess.linker_flavor() { LinkerFlavor::Msvc => { Box::new(MsvcLinker { @@ -734,16 +732,17 @@ impl<'a> Linker for EmLinker<'a> { } } -fn exported_symbols(scx: &SharedCrateContext, - exported_symbols: &ExportedSymbols, - crate_type: CrateType) - -> Vec { +fn exported_symbols(tcx: TyCtxt, crate_type: CrateType) -> Vec { let mut symbols = Vec::new(); - exported_symbols.for_each_exported_symbol(LOCAL_CRATE, |name, _, _| { - symbols.push(name.to_owned()); - }); - let formats = scx.sess().dependency_formats.borrow(); + let export_threshold = symbol_export::threshold(tcx); + for &(ref name, _, level) in tcx.exported_symbols(LOCAL_CRATE).iter() { + if level.is_below_threshold(export_threshold) { + symbols.push(name.clone()); + } + } + + let formats = tcx.sess.dependency_formats.borrow(); let deps = formats[&crate_type].iter(); for (index, dep_format) in deps.enumerate() { @@ -751,9 +750,11 @@ fn exported_symbols(scx: &SharedCrateContext, // For each dependency that we are linking to statically ... if *dep_format == Linkage::Static { // ... we add its symbol list to our export list. - exported_symbols.for_each_exported_symbol(cnum, |name, _, _| { - symbols.push(name.to_owned()); - }) + for &(ref name, _, level) in tcx.exported_symbols(cnum).iter() { + if level.is_below_threshold(export_threshold) { + symbols.push(name.clone()); + } + } } } diff --git a/src/librustc_trans/back/lto.rs b/src/librustc_trans/back/lto.rs index 125b07a9505b1..aa13e4aa196ee 100644 --- a/src/librustc_trans/back/lto.rs +++ b/src/librustc_trans/back/lto.rs @@ -16,7 +16,7 @@ use errors::{FatalError, Handler}; use llvm; use llvm::archive_ro::ArchiveRO; use llvm::{ModuleRef, TargetMachineRef, True, False}; -use rustc::middle::exported_symbols; +use rustc::middle::exported_symbols::SymbolExportLevel; use rustc::util::common::time; use rustc::util::common::path2cstr; use rustc::hir::def_id::LOCAL_CRATE; @@ -68,8 +68,8 @@ pub fn run(cgcx: &CodegenContext, let export_threshold = symbol_export::crates_export_threshold(&cgcx.crate_types); - let symbol_filter = &|&(ref name, _, level): &(String, _, _)| { - if exported_symbols::is_below_threshold(level, export_threshold) { + 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()); Some(CString::new(bytes).unwrap()) @@ -78,8 +78,7 @@ pub fn run(cgcx: &CodegenContext, } }; - let mut symbol_white_list: Vec = cgcx.exported_symbols - .exported_symbols(LOCAL_CRATE) + let mut symbol_white_list: Vec = cgcx.exported_symbols[&LOCAL_CRATE] .iter() .filter_map(symbol_filter) .collect(); @@ -89,9 +88,9 @@ pub fn run(cgcx: &CodegenContext, // module that we've got. for &(cnum, ref path) in cgcx.each_linked_rlib_for_lto.iter() { symbol_white_list.extend( - cgcx.exported_symbols.exported_symbols(cnum) - .iter() - .filter_map(symbol_filter)); + cgcx.exported_symbols[&cnum] + .iter() + .filter_map(symbol_filter)); let archive = ArchiveRO::open(&path).expect("wanted an rlib"); let bytecodes = archive.iter().filter_map(|child| { diff --git a/src/librustc_trans/back/symbol_export.rs b/src/librustc_trans/back/symbol_export.rs index 01b8db557bd1b..844442edbc872 100644 --- a/src/librustc_trans/back/symbol_export.rs +++ b/src/librustc_trans/back/symbol_export.rs @@ -8,89 +8,140 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::rc::Rc; +use std::sync::Arc; + use base; use monomorphize::Instance; -use rustc::util::nodemap::{FxHashMap, NodeSet}; +use rustc::hir::def_id::CrateNum; use rustc::hir::def_id::{DefId, LOCAL_CRATE, INVALID_CRATE, CRATE_DEF_INDEX}; +use rustc::middle::exported_symbols::SymbolExportLevel; use rustc::session::config; use rustc::ty::TyCtxt; +use rustc::ty::maps::Providers; +use rustc::util::nodemap::FxHashMap; use rustc_allocator::ALLOCATOR_METHODS; -use rustc::middle::exported_symbols::{ExportedSymbols, SymbolExportLevel}; -use rustc::middle::exported_symbols::is_below_threshold; -pub fn compute<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> ExportedSymbols { - let export_threshold = crates_export_threshold(&tcx.sess.crate_types.borrow()); - let local_exported_symbols = base::find_exported_symbols(tcx); +pub type ExportedSymbols = FxHashMap< + CrateNum, + Arc>, +>; - 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), def_id, export_level) - }) - .collect(); - - let mut local_exports = local_crate - .iter() - .filter_map(|&(_, def_id, level)| { - if is_below_threshold(level, export_threshold) { - tcx.hir.as_local_node_id(def_id) - } else { - None - } - }) - .collect::(); +pub fn threshold(tcx: TyCtxt) -> SymbolExportLevel { + crates_export_threshold(&tcx.sess.crate_types.borrow()) +} - const INVALID_DEF_ID: DefId = DefId { - krate: INVALID_CRATE, - index: CRATE_DEF_INDEX, - }; +pub fn metadata_symbol_name(tcx: TyCtxt) -> String { + format!("rust_metadata_{}_{}", + tcx.crate_name(LOCAL_CRATE), + tcx.crate_disambiguator(LOCAL_CRATE)) +} - if let Some(_) = *tcx.sess.entry_fn.borrow() { - local_crate.push(("main".to_string(), - INVALID_DEF_ID, - SymbolExportLevel::C)); +fn crate_export_threshold(crate_type: config::CrateType) -> SymbolExportLevel { + match crate_type { + config::CrateTypeExecutable | + config::CrateTypeStaticlib | + config::CrateTypeProcMacro | + config::CrateTypeCdylib => SymbolExportLevel::C, + config::CrateTypeRlib | + config::CrateTypeDylib => SymbolExportLevel::Rust, } +} - if tcx.sess.allocator_kind.get().is_some() { - for method in ALLOCATOR_METHODS { - local_crate.push((format!("__rust_{}", method.name), - INVALID_DEF_ID, - SymbolExportLevel::Rust)); - } +pub fn crates_export_threshold(crate_types: &[config::CrateType]) + -> SymbolExportLevel { + if crate_types.iter().any(|&crate_type| { + crate_export_threshold(crate_type) == SymbolExportLevel::Rust + }) { + SymbolExportLevel::Rust + } else { + SymbolExportLevel::C } +} - if let Some(id) = tcx.sess.derive_registrar_fn.get() { - let def_id = tcx.hir.local_def_id(id); - let idx = def_id.index; - let disambiguator = tcx.sess.local_crate_disambiguator(); - let registrar = tcx.sess.generate_derive_registrar_symbol(disambiguator, idx); - local_crate.push((registrar, def_id, SymbolExportLevel::C)); - local_exports.insert(id); - } +pub fn provide_local(providers: &mut Providers) { + providers.exported_symbol_ids = |tcx, cnum| { + let export_threshold = threshold(tcx); + Rc::new(tcx.exported_symbols(cnum) + .iter() + .filter_map(|&(_, id, level)| { + if level.is_below_threshold(export_threshold) { + Some(id) + } else { + None + } + }) + .collect()) + }; - if tcx.sess.crate_types.borrow().contains(&config::CrateTypeDylib) { - local_crate.push((metadata_symbol_name(tcx), - INVALID_DEF_ID, - SymbolExportLevel::Rust)); - } + providers.is_exported_symbol = |tcx, id| { + // FIXME(#42293) needs red/green to not break a bunch of incremental + // tests + tcx.dep_graph.with_ignore(|| { + 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), def_id, export_level) + }) + .collect(); + + const INVALID_DEF_ID: DefId = DefId { + krate: INVALID_CRATE, + index: CRATE_DEF_INDEX, + }; + + if let Some(_) = *tcx.sess.entry_fn.borrow() { + local_crate.push(("main".to_string(), + INVALID_DEF_ID, + SymbolExportLevel::C)); + } - let mut exports = FxHashMap(); - exports.insert(LOCAL_CRATE, local_crate); + if tcx.sess.allocator_kind.get().is_some() { + for method in ALLOCATOR_METHODS { + local_crate.push((format!("__rust_{}", method.name), + INVALID_DEF_ID, + SymbolExportLevel::Rust)); + } + } - for &cnum in tcx.crates().iter() { - debug_assert!(cnum != LOCAL_CRATE); + if let Some(id) = tcx.sess.derive_registrar_fn.get() { + let def_id = tcx.hir.local_def_id(id); + let idx = def_id.index; + let disambiguator = tcx.sess.local_crate_disambiguator(); + let registrar = tcx.sess.generate_derive_registrar_symbol(disambiguator, idx); + local_crate.push((registrar, def_id, SymbolExportLevel::C)); + } + if tcx.sess.crate_types.borrow().contains(&config::CrateTypeDylib) { + local_crate.push((metadata_symbol_name(tcx), + INVALID_DEF_ID, + SymbolExportLevel::Rust)); + } + Arc::new(local_crate) + }; +} + +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() { - continue; + return Arc::new(Vec::new()) } // Check to see if this crate is a "special runtime crate". These @@ -131,45 +182,14 @@ pub fn compute<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> ExportedSymbols { }) .collect(); - exports.insert(cnum, crate_exports); - } - - return ExportedSymbols::new(export_threshold, exports, local_exports); - - fn export_level(tcx: TyCtxt, sym_def_id: DefId) -> SymbolExportLevel { - if tcx.contains_extern_indicator(sym_def_id) { - SymbolExportLevel::C - } else { - SymbolExportLevel::Rust - } - } -} - -pub fn metadata_symbol_name(tcx: TyCtxt) -> String { - format!("rust_metadata_{}_{}", - tcx.crate_name(LOCAL_CRATE), - tcx.crate_disambiguator(LOCAL_CRATE)) -} - -pub fn crate_export_threshold(crate_type: config::CrateType) - -> SymbolExportLevel { - match crate_type { - config::CrateTypeExecutable | - config::CrateTypeStaticlib | - config::CrateTypeProcMacro | - config::CrateTypeCdylib => SymbolExportLevel::C, - config::CrateTypeRlib | - config::CrateTypeDylib => SymbolExportLevel::Rust, - } + Arc::new(crate_exports) + }; } -pub fn crates_export_threshold(crate_types: &[config::CrateType]) - -> SymbolExportLevel { - if crate_types.iter().any(|&crate_type| { - crate_export_threshold(crate_type) == SymbolExportLevel::Rust - }) { - SymbolExportLevel::Rust - } else { +fn export_level(tcx: TyCtxt, sym_def_id: DefId) -> SymbolExportLevel { + if tcx.contains_extern_indicator(sym_def_id) { SymbolExportLevel::C + } else { + SymbolExportLevel::Rust } } diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs index d241edca0ead7..c8925ceb478ce 100644 --- a/src/librustc_trans/back/write.rs +++ b/src/librustc_trans/back/write.rs @@ -11,24 +11,27 @@ use back::lto; use back::link::{self, get_linker, remove}; use back::linker::LinkerInfo; -use rustc::middle::exported_symbols::ExportedSymbols; +use back::symbol_export::ExportedSymbols; use rustc_incremental::{save_trans_partition, in_incr_comp_dir}; use rustc::dep_graph::DepGraph; use rustc::middle::cstore::{LinkMeta, EncodedMetadata}; use rustc::session::config::{self, OutputFilenames, OutputType, OutputTypes, Passes, SomePasses, AllPasses, Sanitizer}; use rustc::session::Session; +use rustc::util::nodemap::FxHashMap; use time_graph::{self, TimeGraph}; use llvm; use llvm::{ModuleRef, TargetMachineRef, PassManagerRef, DiagnosticInfoRef}; use llvm::SMDiagnosticRef; use {CrateTranslation, ModuleSource, ModuleTranslation, CompiledModule, ModuleKind}; use CrateInfo; -use rustc::hir::def_id::CrateNum; +use rustc::hir::def_id::{CrateNum, LOCAL_CRATE}; +use rustc::ty::TyCtxt; use rustc::util::common::{time, time_depth, set_time_depth, path2cstr, print_time_passes_entry}; use rustc::util::fs::{link_or_copy, rename_or_copy_remove}; use errors::{self, Handler, Level, DiagnosticBuilder, FatalError}; use errors::emitter::{Emitter}; +use syntax::attr; use syntax::ext::hygiene::Mark; use syntax_pos::MultiSpan; use syntax_pos::symbol::Symbol; @@ -667,19 +670,40 @@ fn need_crate_bitcode_for_rlib(sess: &Session) -> bool { sess.opts.output_types.contains_key(&OutputType::Exe) } -pub fn start_async_translation(sess: &Session, +pub fn start_async_translation(tcx: TyCtxt, crate_output: &OutputFilenames, time_graph: Option, - crate_name: Symbol, link: LinkMeta, - metadata: EncodedMetadata, - exported_symbols: Arc, - no_builtins: bool, - windows_subsystem: Option, - linker_info: LinkerInfo, - crate_info: CrateInfo, - no_integrated_as: bool) + metadata: EncodedMetadata) -> OngoingCrateTranslation { + let sess = tcx.sess; + let crate_name = tcx.crate_name(LOCAL_CRATE); + let no_builtins = attr::contains_name(&tcx.hir.krate().attrs, "no_builtins"); + let subsystem = attr::first_attr_value_str_by_name(&tcx.hir.krate().attrs, + "windows_subsystem"); + let windows_subsystem = subsystem.map(|subsystem| { + if subsystem != "windows" && subsystem != "console" { + tcx.sess.fatal(&format!("invalid windows subsystem `{}`, only \ + `windows` and `console` are allowed", + subsystem)); + } + subsystem.to_string() + }); + + let no_integrated_as = tcx.sess.opts.cg.no_integrated_as || + (tcx.sess.target.target.options.no_integrated_as && + (crate_output.outputs.contains_key(&OutputType::Object) || + crate_output.outputs.contains_key(&OutputType::Exe))); + let linker_info = LinkerInfo::new(tcx); + let crate_info = CrateInfo::new(tcx); + + 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)); + } + let exported_symbols = Arc::new(exported_symbols); + let output_types_override = if no_integrated_as { OutputTypes::new(&[(OutputType::Assembly, None)]) } else { diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index 7d0e7c210746b..7941134cc7b07 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -30,7 +30,6 @@ use super::ModuleKind; use assert_module_sources; use back::link; -use back::linker::LinkerInfo; use back::symbol_export; use back::write::{self, OngoingCrateTranslation}; use llvm::{ContextRef, ModuleRef, ValueRef, Vector, get_param}; @@ -44,10 +43,9 @@ use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::maps::Providers; use rustc::dep_graph::AssertDepGraphSafe; use rustc::middle::cstore::{self, LinkMeta, LinkagePreference}; -use rustc::middle::exported_symbols::ExportedSymbols; use rustc::hir::map as hir_map; use rustc::util::common::{time, print_time_passes_entry}; -use rustc::session::config::{self, NoDebugInfo, OutputFilenames, OutputType}; +use rustc::session::config::{self, NoDebugInfo, OutputFilenames}; use rustc::session::Session; use rustc_incremental::{self, IncrementalHashesMap}; use abi; @@ -939,11 +937,6 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, -> OngoingCrateTranslation { check_for_rustc_errors_attr(tcx); - // Be careful with this krate: obviously it gives access to the - // entire contents of the krate. So if you push any subtasks of - // `TransCrate`, you need to be careful to register "reads" of the - // particular items that will be processed. - let krate = tcx.hir.krate(); let check_overflow = tcx.sess.overflow_checks(); let link_meta = link::build_link_meta(&incremental_hashes_map); let exported_symbol_node_ids = find_exported_symbols(tcx); @@ -967,31 +960,21 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, kind: ModuleKind::Metadata, }; - let no_builtins = attr::contains_name(&krate.attrs, "no_builtins"); let time_graph = if tcx.sess.opts.debugging_opts.trans_time_graph { Some(time_graph::TimeGraph::new()) } else { None }; - let crate_info = CrateInfo::new(tcx); // Skip crate items and just output metadata in -Z no-trans mode. if tcx.sess.opts.debugging_opts.no_trans || !tcx.sess.opts.output_types.should_trans() { - let linker_info = LinkerInfo::new(&shared_ccx); let ongoing_translation = write::start_async_translation( - tcx.sess, + tcx, output_filenames, time_graph.clone(), - tcx.crate_name(LOCAL_CRATE), link_meta, - metadata, - shared_ccx.tcx().exported_symbols(), - no_builtins, - None, - linker_info, - crate_info, - false); + metadata); ongoing_translation.submit_pre_translated_module_to_llvm(tcx.sess, metadata_module, true); @@ -1012,36 +995,12 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, assert!(codegen_units.len() <= 1 || !tcx.sess.lto()); - let linker_info = LinkerInfo::new(&shared_ccx); - let subsystem = attr::first_attr_value_str_by_name(&krate.attrs, - "windows_subsystem"); - let windows_subsystem = subsystem.map(|subsystem| { - if subsystem != "windows" && subsystem != "console" { - tcx.sess.fatal(&format!("invalid windows subsystem `{}`, only \ - `windows` and `console` are allowed", - subsystem)); - } - subsystem.to_string() - }); - - let no_integrated_as = tcx.sess.opts.cg.no_integrated_as || - (tcx.sess.target.target.options.no_integrated_as && - (output_filenames.outputs.contains_key(&OutputType::Object) || - output_filenames.outputs.contains_key(&OutputType::Exe))); - let ongoing_translation = write::start_async_translation( - tcx.sess, + tcx, output_filenames, time_graph.clone(), - tcx.crate_name(LOCAL_CRATE), link_meta, - metadata, - tcx.exported_symbols(), - no_builtins, - windows_subsystem, - linker_info, - crate_info, - no_integrated_as); + metadata); // Translate an allocator shim, if any // @@ -1118,8 +1077,7 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, tcx.dep_graph.with_task(dep_node, AssertDepGraphSafe(&shared_ccx), AssertDepGraphSafe((cgu, - translation_items.clone(), - tcx.exported_symbols())), + translation_items.clone())), module_translation); all_stats.extend(stats); @@ -1161,13 +1119,12 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, fn module_translation<'a, 'tcx>( scx: AssertDepGraphSafe<&SharedCrateContext<'a, 'tcx>>, args: AssertDepGraphSafe<(Arc>, - Arc>>, - Arc)>) + Arc>>)>) -> (Stats, ModuleTranslation) { // FIXME(#40304): We ought to be using the id as a key and some queries, I think. let AssertDepGraphSafe(scx) = scx; - let AssertDepGraphSafe((cgu, crate_trans_items, exported_symbols)) = args; + let AssertDepGraphSafe((cgu, crate_trans_items)) = args; let cgu_name = cgu.name().to_string(); let cgu_id = cgu.work_product_id(); @@ -1207,7 +1164,7 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } // Instantiate translation items without filling out definitions yet... - let lcx = LocalCrateContext::new(scx, cgu, crate_trans_items, exported_symbols); + let lcx = LocalCrateContext::new(scx, cgu, crate_trans_items); let module = { let ccx = CrateContext::new(scx, &lcx); let trans_items = ccx.codegen_unit() @@ -1400,7 +1357,6 @@ fn collect_and_partition_translation_items<'a, 'tcx>( { assert_eq!(cnum, LOCAL_CRATE); let time_passes = tcx.sess.time_passes(); - let exported_symbols = tcx.exported_symbols(); let collection_mode = match tcx.sess.opts.debugging_opts.print_trans_items { Some(ref s) => { @@ -1424,9 +1380,7 @@ fn collect_and_partition_translation_items<'a, 'tcx>( let (items, inlining_map) = time(time_passes, "translation item collection", || { - collector::collect_crate_translation_items(tcx, - &exported_symbols, - collection_mode) + collector::collect_crate_translation_items(tcx, collection_mode) }); assert_symbols_are_distinct(tcx, items.iter()); @@ -1441,8 +1395,7 @@ fn collect_and_partition_translation_items<'a, 'tcx>( partitioning::partition(tcx, items.iter().cloned(), strategy, - &inlining_map, - &exported_symbols) + &inlining_map) .into_iter() .map(Arc::new) .collect::>() @@ -1510,7 +1463,7 @@ fn collect_and_partition_translation_items<'a, 'tcx>( } impl CrateInfo { - pub fn new<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> CrateInfo { + pub fn new(tcx: TyCtxt) -> CrateInfo { let mut info = CrateInfo { panic_runtime: None, compiler_builtins: None, diff --git a/src/librustc_trans/callee.rs b/src/librustc_trans/callee.rs index ffdd76dd68731..a904aa7ed876a 100644 --- a/src/librustc_trans/callee.rs +++ b/src/librustc_trans/callee.rs @@ -114,8 +114,8 @@ pub fn get_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, llvm::LLVMRustSetLinkage(llfn, llvm::Linkage::ExternalLinkage); if ccx.crate_trans_items().contains(&TransItem::Fn(instance)) { - if let Some(node_id) = tcx.hir.as_local_node_id(instance_def_id) { - if !ccx.exported_symbols().local_exports().contains(&node_id) { + if instance_def_id.is_local() { + if !ccx.tcx().is_exported_symbol(instance_def_id) { llvm::LLVMRustSetVisibility(llfn, llvm::Visibility::Hidden); } } else { diff --git a/src/librustc_trans/collector.rs b/src/librustc_trans/collector.rs index a45bcb51ab594..6fa69de74b0a1 100644 --- a/src/librustc_trans/collector.rs +++ b/src/librustc_trans/collector.rs @@ -194,7 +194,6 @@ use rustc::hir::itemlikevisit::ItemLikeVisitor; use rustc::hir::map as hir_map; use rustc::hir::def_id::DefId; use rustc::middle::const_val::ConstVal; -use rustc::middle::exported_symbols::ExportedSymbols; use rustc::middle::lang_items::{ExchangeMallocFnLangItem}; use rustc::traits; use rustc::ty::subst::Substs; @@ -294,14 +293,13 @@ impl<'tcx> InliningMap<'tcx> { } pub fn collect_crate_translation_items<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - exported_symbols: &ExportedSymbols, mode: TransItemCollectionMode) -> (FxHashSet>, InliningMap<'tcx>) { // We are not tracking dependencies of this pass as it has to be re-executed // every time no matter what. tcx.dep_graph.with_ignore(|| { - let roots = collect_roots(tcx, exported_symbols, mode); + let roots = collect_roots(tcx, mode); debug!("Building translation item graph, beginning at roots"); let mut visited = FxHashSet(); @@ -323,7 +321,6 @@ pub fn collect_crate_translation_items<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // Find all non-generic items by walking the HIR. These items serve as roots to // start monomorphizing from. fn collect_roots<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - exported_symbols: &ExportedSymbols, mode: TransItemCollectionMode) -> Vec> { debug!("Collecting roots"); @@ -333,7 +330,6 @@ fn collect_roots<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let mut visitor = RootCollector { tcx, mode, - exported_symbols, output: &mut roots, }; @@ -865,7 +861,6 @@ fn create_trans_items_for_vtable_methods<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, struct RootCollector<'b, 'a: 'b, 'tcx: 'a + 'b> { tcx: TyCtxt<'a, 'tcx, 'tcx>, - exported_symbols: &'b ExportedSymbols, mode: TransItemCollectionMode, output: &'b mut Vec>, } @@ -926,8 +921,7 @@ impl<'b, 'a, 'v> ItemLikeVisitor<'v> for RootCollector<'b, 'a, 'v> { let def_id = tcx.hir.local_def_id(item.id); if (self.mode == TransItemCollectionMode::Eager || - !tcx.is_const_fn(def_id) || - self.exported_symbols.local_exports().contains(&item.id)) && + !tcx.is_const_fn(def_id) || tcx.is_exported_symbol(def_id)) && !item_has_type_parameters(tcx, def_id) { debug!("RootCollector: ItemFn({})", @@ -953,7 +947,7 @@ impl<'b, 'a, 'v> ItemLikeVisitor<'v> for RootCollector<'b, 'a, 'v> { if (self.mode == TransItemCollectionMode::Eager || !tcx.is_const_fn(def_id) || - self.exported_symbols.local_exports().contains(&ii.id)) && + tcx.is_exported_symbol(def_id)) && !item_has_type_parameters(tcx, def_id) { debug!("RootCollector: MethodImplItem({})", def_id_to_string(tcx, def_id)); diff --git a/src/librustc_trans/consts.rs b/src/librustc_trans/consts.rs index 4f78e77fc690c..78ece020d1d6b 100644 --- a/src/librustc_trans/consts.rs +++ b/src/librustc_trans/consts.rs @@ -130,7 +130,7 @@ pub fn get_static(ccx: &CrateContext, def_id: DefId) -> ValueRef { let g = declare::define_global(ccx, &sym[..], llty).unwrap(); - if !ccx.exported_symbols().local_exports().contains(&id) { + if !ccx.tcx().is_exported_symbol(def_id) { unsafe { llvm::LLVMRustSetVisibility(g, llvm::Visibility::Hidden); } diff --git a/src/librustc_trans/context.rs b/src/librustc_trans/context.rs index 7a2db29705d83..62dadce76f0e7 100644 --- a/src/librustc_trans/context.rs +++ b/src/librustc_trans/context.rs @@ -14,7 +14,6 @@ use llvm::{ContextRef, ModuleRef, ValueRef}; use rustc::dep_graph::{DepGraph, DepGraphSafe}; use rustc::hir; use rustc::hir::def_id::DefId; -use rustc::middle::exported_symbols::ExportedSymbols; use rustc::traits; use debuginfo; use callee; @@ -98,9 +97,6 @@ pub struct LocalCrateContext<'a, 'tcx: 'a> { /// The translation items of the whole crate. crate_trans_items: Arc>>, - /// Information about which symbols are exported from the crate. - exported_symbols: Arc, - /// Cache instances of monomorphic and polymorphic items instances: RefCell, ValueRef>>, /// Cache generated vtables @@ -354,8 +350,7 @@ impl<'b, 'tcx> SharedCrateContext<'b, 'tcx> { impl<'a, 'tcx> LocalCrateContext<'a, 'tcx> { pub fn new(shared: &SharedCrateContext<'a, 'tcx>, codegen_unit: Arc>, - crate_trans_items: Arc>>, - exported_symbols: Arc,) + crate_trans_items: Arc>>) -> LocalCrateContext<'a, 'tcx> { unsafe { // Append ".rs" to LLVM module identifier. @@ -388,7 +383,6 @@ impl<'a, 'tcx> LocalCrateContext<'a, 'tcx> { stats: Stats::default(), codegen_unit, crate_trans_items, - exported_symbols, instances: RefCell::new(FxHashMap()), vtables: RefCell::new(FxHashMap()), const_cstr_cache: RefCell::new(FxHashMap()), @@ -499,10 +493,6 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> { &self.local().crate_trans_items } - pub fn exported_symbols(&self) -> &ExportedSymbols { - &self.local().exported_symbols - } - pub fn td(&self) -> llvm::TargetDataRef { unsafe { llvm::LLVMRustGetModuleDataLayout(self.llmod()) } } diff --git a/src/librustc_trans/debuginfo/utils.rs b/src/librustc_trans/debuginfo/utils.rs index 7529139c05aac..ad4fdfca7261f 100644 --- a/src/librustc_trans/debuginfo/utils.rs +++ b/src/librustc_trans/debuginfo/utils.rs @@ -37,7 +37,8 @@ pub fn is_node_local_to_unit(cx: &CrateContext, node_id: ast::NodeId) -> 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.exported_symbols().local_exports().contains(&node_id) + let def_id = cx.tcx().hir.local_def_id(node_id); + !cx.tcx().is_exported_symbol(def_id) } #[allow(non_snake_case)] diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs index 42c3e620baa7f..d06c769458a74 100644 --- a/src/librustc_trans/lib.rs +++ b/src/librustc_trans/lib.rs @@ -69,9 +69,8 @@ pub use metadata::LlvmMetadataLoader; pub use llvm_util::{init, target_features, print_version, print_passes, print, enable_llvm_debug}; use std::rc::Rc; -use std::sync::Arc; -use rustc::hir::def_id::{CrateNum, LOCAL_CRATE}; +use rustc::hir::def_id::CrateNum; use rustc::middle::cstore::{NativeLibrary, CrateSource, LibSource}; use rustc::ty::maps::Providers; use rustc::util::nodemap::{FxHashSet, FxHashMap}; @@ -251,13 +250,11 @@ __build_diagnostic_array! { librustc_trans, DIAGNOSTICS } pub fn provide_local(providers: &mut Providers) { back::symbol_names::provide(providers); + back::symbol_export::provide_local(providers); base::provide(providers); - providers.exported_symbol_set = |tcx, cnum| { - assert_eq!(cnum, LOCAL_CRATE); - Arc::new(back::symbol_export::compute(tcx)) - }; } pub fn provide_extern(providers: &mut Providers) { back::symbol_names::provide(providers); + back::symbol_export::provide_extern(providers); } diff --git a/src/librustc_trans/partitioning.rs b/src/librustc_trans/partitioning.rs index d4aecb9e56caa..65cf24e8c6e03 100644 --- a/src/librustc_trans/partitioning.rs +++ b/src/librustc_trans/partitioning.rs @@ -108,7 +108,6 @@ use context::SharedCrateContext; use rustc::dep_graph::{DepNode, WorkProductId}; use rustc::hir::def_id::DefId; use rustc::hir::map::DefPathData; -use rustc::middle::exported_symbols::ExportedSymbols; use rustc::middle::trans::{Linkage, Visibility}; use rustc::session::config::NUMBERED_CODEGEN_UNIT_MARKER; use rustc::ty::{self, TyCtxt, InstanceDef}; @@ -212,8 +211,7 @@ const FALLBACK_CODEGEN_UNIT: &'static str = "__rustc_fallback_codegen_unit"; pub fn partition<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>, trans_items: I, strategy: PartitioningStrategy, - inlining_map: &InliningMap<'tcx>, - exported_symbols: &ExportedSymbols) + inlining_map: &InliningMap<'tcx>) -> Vec> where I: Iterator> { @@ -221,7 +219,6 @@ pub fn partition<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // respective 'home' codegen unit. Regular translation items are all // functions and statics defined in the local crate. let mut initial_partitioning = place_root_translation_items(tcx, - exported_symbols, trans_items); debug_dump(tcx, "INITIAL PARTITIONING:", initial_partitioning.codegen_units.iter()); @@ -291,13 +288,10 @@ struct PostInliningPartitioning<'tcx> { } fn place_root_translation_items<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - exported_symbols: &ExportedSymbols, trans_items: I) -> PreInliningPartitioning<'tcx> where I: Iterator> { - let exported_symbols = exported_symbols.local_exports(); - let mut roots = FxHashSet(); let mut codegen_units = FxHashMap(); let is_incremental_build = tcx.sess.opts.incremental.is_some(); @@ -330,8 +324,8 @@ fn place_root_translation_items<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>, TransItem::Fn(ref instance) => { let visibility = match instance.def { InstanceDef::Item(def_id) => { - if let Some(node_id) = tcx.hir.as_local_node_id(def_id) { - if exported_symbols.contains(&node_id) { + if def_id.is_local() { + if tcx.is_exported_symbol(def_id) { Visibility::Default } else { internalization_candidates.insert(trans_item); @@ -357,7 +351,8 @@ fn place_root_translation_items<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } TransItem::Static(node_id) | TransItem::GlobalAsm(node_id) => { - let visibility = if exported_symbols.contains(&node_id) { + let def_id = tcx.hir.local_def_id(node_id); + let visibility = if tcx.is_exported_symbol(def_id) { Visibility::Default } else { internalization_candidates.insert(trans_item);