diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index 3a534ef93ad..bfbf280d6dd 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 a7d874386d1..bea6ef4dc11 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 7f03f8a5a29..230878f8545 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 af5c37e0f16..fb0cdab0b6a 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 75c20a25131..dd6d90503ef 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 689f9f5b244..1c4f1c63486 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 1eb3e86a15b..239b488fabe 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 125b07a9505..aa13e4aa196 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 01b8db557bd..844442edbc8 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(); +pub fn threshold(tcx: TyCtxt) -> SymbolExportLevel { + crates_export_threshold(&tcx.sess.crate_types.borrow()) +} - 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 metadata_symbol_name(tcx: TyCtxt) -> String { + format!("rust_metadata_{}_{}", + tcx.crate_name(LOCAL_CRATE), + tcx.crate_disambiguator(LOCAL_CRATE)) +} - const INVALID_DEF_ID: DefId = DefId { - krate: INVALID_CRATE, - index: CRATE_DEF_INDEX, +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, + } +} + +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 + } +} + +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 let Some(_) = *tcx.sess.entry_fn.borrow() { - local_crate.push(("main".to_string(), - INVALID_DEF_ID, - SymbolExportLevel::C)); - } + 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) + }) + }; - if tcx.sess.allocator_kind.get().is_some() { - for method in ALLOCATOR_METHODS { - local_crate.push((format!("__rust_{}", method.name), + 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)); + } + + 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)); + } + } + + 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)); } - } - - 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); - } - - if tcx.sess.crate_types.borrow().contains(&config::CrateTypeDylib) { - local_crate.push((metadata_symbol_name(tcx), - INVALID_DEF_ID, - SymbolExportLevel::Rust)); - } - - let mut exports = FxHashMap(); - exports.insert(LOCAL_CRATE, local_crate); - - for &cnum in tcx.crates().iter() { - debug_assert!(cnum != LOCAL_CRATE); + 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 - } - } + Arc::new(crate_exports) + }; } -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, - } -} - -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 d241edca0ea..c8925ceb478 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 7d0e7c21074..7941134cc7b 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 ffdd76dd687..a904aa7ed87 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 a45bcb51ab5..6fa69de74b0 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 4f78e77fc69..78ece020d1d 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 7a2db29705d..62dadce76f0 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 7529139c05a..ad4fdfca726 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 42c3e620baa..d06c769458a 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 d4aecb9e56c..65cf24e8c6e 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);