about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc/dep_graph/dep_node.rs2
-rw-r--r--src/librustc/middle/cstore.rs5
-rw-r--r--src/librustc/middle/exported_symbols.rs60
-rw-r--r--src/librustc/ty/context.rs6
-rw-r--r--src/librustc/ty/maps.rs16
-rw-r--r--src/librustc_metadata/decoder.rs3
-rw-r--r--src/librustc_trans/back/linker.rs49
-rw-r--r--src/librustc_trans/back/lto.rs15
-rw-r--r--src/librustc_trans/back/symbol_export.rs216
-rw-r--r--src/librustc_trans/back/write.rs46
-rw-r--r--src/librustc_trans/base.rs71
-rw-r--r--src/librustc_trans/callee.rs4
-rw-r--r--src/librustc_trans/collector.rs12
-rw-r--r--src/librustc_trans/consts.rs2
-rw-r--r--src/librustc_trans/context.rs12
-rw-r--r--src/librustc_trans/debuginfo/utils.rs3
-rw-r--r--src/librustc_trans/lib.rs9
-rw-r--r--src/librustc_trans/partitioning.rs15
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 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<CrateNum, Vec<(String, DefId, SymbolExportLevel)>>,
-    local_exports: NodeSet,
-}
-
-impl ExportedSymbols {
-    pub fn new(export_threshold: SymbolExportLevel,
-               exports: FxHashMap<CrateNum, Vec<(String, DefId, SymbolExportLevel)>>,
-               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<F>(&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<Any> {
         self.cstore.crate_data_as_rc_any(cnum)
     }
-
-    pub fn exported_symbols(self) -> Arc<ExportedSymbols> {
-        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<lint::LintLevelMap>,
 
     [] fn impl_defaultness: ImplDefaultness(DefId) -> hir::Defaultness,
-    [] fn exported_symbol_ids: ExportedSymbolIds(CrateNum) -> Rc<Vec<DefId>>,
+    [] fn exported_symbol_ids: ExportedSymbolIds(CrateNum) -> Rc<DefIdSet>,
     [] fn native_libraries: NativeLibraries(CrateNum) -> Rc<Vec<NativeLibrary>>,
     [] fn plugin_registrar_fn: PluginRegistrarFn(CrateNum) -> Option<DefId>,
     [] fn derive_registrar_fn: DeriveRegistrarFn(CrateNum) -> Option<DefId>,
@@ -1387,8 +1387,8 @@ define_maps! { <'tcx>
     [] fn stability_index: stability_index_node(CrateNum) -> Rc<stability::Index<'tcx>>,
     [] fn all_crate_nums: all_crate_nums_node(CrateNum) -> Rc<Vec<CrateNum>>,
 
-    [] fn exported_symbol_set: exported_symbol_set_node(CrateNum)
-        -> Arc<ExportedSymbols>,
+    [] fn exported_symbols: ExportedSymbols(CrateNum)
+        -> Arc<Vec<(String, DefId, SymbolExportLevel)>>,
     [] fn collect_and_partition_translation_items:
         collect_and_partition_translation_items_node(CrateNum)
         -> (Arc<FxHashSet<TransItem<'tcx>>>, Vec<Arc<CodegenUnit<'tcx>>>),
@@ -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<DefId> {
+    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<CrateType, Vec<String>>,
 }
 
-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<Linker+'a> {
+    pub fn to_linker<'a>(&'a self,
+                         cmd: Command,
+                         sess: &'a Session) -> Box<Linker+'a> {
         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<String> {
+fn exported_symbols(tcx: TyCtxt, crate_type: CrateType) -> Vec<String> {
     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<CString> = cgcx.exported_symbols
-        .exported_symbols(LOCAL_CRATE)
+    let mut symbol_white_list: Vec<CString> = 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<Vec<(String, DefId, SymbolExportLevel)>>,
+>;
 
-    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::<NodeSet>();
+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 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<TimeGraph>,
-                               crate_name: Symbol,
                                link: LinkMeta,
-                               metadata: EncodedMetadata,
-                               exported_symbols: Arc<ExportedSymbols>,
-                               no_builtins: bool,
-                               windows_subsystem: Option<String>,
-                               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<CodegenUnit<'tcx>>,
-                                  Arc<FxHashSet<TransItem<'tcx>>>,
-                                  Arc<ExportedSymbols>)>)
+                                  Arc<FxHashSet<TransItem<'tcx>>>)>)
         -> (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::<Vec<_>>()
@@ -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<TransItem<'tcx>>,
                                                      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<TransItem<'tcx>> {
     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<TransItem<'tcx>>,
 }
@@ -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<FxHashSet<TransItem<'tcx>>>,
 
-    /// Information about which symbols are exported from the crate.
-    exported_symbols: Arc<ExportedSymbols>,
-
     /// Cache instances of monomorphic and polymorphic items
     instances: RefCell<FxHashMap<Instance<'tcx>, 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<CodegenUnit<'tcx>>,
-               crate_trans_items: Arc<FxHashSet<TransItem<'tcx>>>,
-               exported_symbols: Arc<ExportedSymbols>,)
+               crate_trans_items: Arc<FxHashSet<TransItem<'tcx>>>)
                -> 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<CodegenUnit<'tcx>>
     where I: Iterator<Item = TransItem<'tcx>>
 {
@@ -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<Item = TransItem<'tcx>>
 {
-    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);