about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorAlex Crichton <alex@alexcrichton.com>2017-08-28 15:55:32 -0700
committerAlex Crichton <alex@alexcrichton.com>2017-09-05 07:37:11 -0700
commitdff0c074e467a1fbbeab44ffbd8da4882683b694 (patch)
tree08c1104e31ab1dde70b97eb6eaedd7f97dc3bfa1 /src
parent2f1ef9ef1181298d46e79d5dde6bafeb6483926f (diff)
downloadrust-dff0c074e467a1fbbeab44ffbd8da4882683b694.tar.gz
rust-dff0c074e467a1fbbeab44ffbd8da4882683b694.zip
rustc: Move a few more cstore methods to queries
This comit applies the following changes:

* Deletes the `is_allocator` query as it's no longer used
* Moves the `is_sanitizer_runtime` method to a query
* Moves the `is_profiler_runtime` method to a query
* Moves the `panic_strategy` method to a query
* Moves the `is_no_builtins` method to a query
* Deletes the cstore method of `is_compiler_builtins`. The query was added in
  #42588 but the `CrateStore` method was not deleted

A good bit of these methods were used late in linking during trans so a new
dedicated structure was created to ship a calculated form of this information
over to the linker rather than having to ship the whole of `TyCtxt` over to
linking.
Diffstat (limited to 'src')
-rw-r--r--src/librustc/dep_graph/dep_node.rs13
-rw-r--r--src/librustc/middle/cstore.rs13
-rw-r--r--src/librustc/middle/dependency_format.rs14
-rw-r--r--src/librustc/ty/maps.rs57
-rw-r--r--src/librustc_metadata/cstore_impl.rs44
-rw-r--r--src/librustc_trans/back/link.rs30
-rw-r--r--src/librustc_trans/back/symbol_export.rs3
-rw-r--r--src/librustc_trans/back/write.rs9
-rw-r--r--src/librustc_trans/base.rs36
-rw-r--r--src/librustc_trans/lib.rs14
-rw-r--r--src/librustc_typeck/check_unused.rs2
11 files changed, 150 insertions, 85 deletions
diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs
index c438944cf01..6000740f2b0 100644
--- a/src/librustc/dep_graph/dep_node.rs
+++ b/src/librustc/dep_graph/dep_node.rs
@@ -521,16 +521,19 @@ define_dep_nodes!( <'tcx>
     [] IsMirAvailable(DefId),
     [] ItemAttrs(DefId),
     [] FnArgNames(DefId),
-    [] DylibDepFormats(DefId),
-    [] IsAllocator(DefId),
-    [] IsPanicRuntime(DefId),
-    [] IsCompilerBuiltins(DefId),
-    [] HasGlobalAllocator(DefId),
+    [] DylibDepFormats(CrateNum),
+    [] IsPanicRuntime(CrateNum),
+    [] IsCompilerBuiltins(CrateNum),
+    [] HasGlobalAllocator(CrateNum),
     [] ExternCrate(DefId),
     [] LintLevels,
     [] Specializes { impl1: DefId, impl2: DefId },
     [] InScopeTraits(HirId),
     [] ModuleExports(HirId),
+    [] IsSanitizerRuntime(CrateNum),
+    [] IsProfilerRuntime(CrateNum),
+    [] GetPanicStrategy(CrateNum),
+    [] IsNoBuiltins(CrateNum),
 );
 
 trait DepNodeParams<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> : fmt::Debug {
diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs
index 288390cb5e7..163c75fe97d 100644
--- a/src/librustc/middle/cstore.rs
+++ b/src/librustc/middle/cstore.rs
@@ -44,7 +44,6 @@ use syntax::symbol::Symbol;
 use syntax_pos::Span;
 use rustc_back::target::Target;
 use hir;
-use rustc_back::PanicStrategy;
 
 pub use self::NativeLibraryKind::*;
 
@@ -252,10 +251,6 @@ pub trait CrateStore {
     fn export_macros(&self, cnum: CrateNum);
     fn lang_items(&self, cnum: CrateNum) -> Vec<(DefIndex, usize)>;
     fn missing_lang_items(&self, cnum: CrateNum) -> Vec<lang_items::LangItem>;
-    fn is_compiler_builtins(&self, cnum: CrateNum) -> bool;
-    fn is_sanitizer_runtime(&self, cnum: CrateNum) -> bool;
-    fn is_profiler_runtime(&self, cnum: CrateNum) -> bool;
-    fn panic_strategy(&self, cnum: CrateNum) -> PanicStrategy;
     /// The name of the crate as it is referred to in source code of the current
     /// crate.
     fn crate_name(&self, cnum: CrateNum) -> Symbol;
@@ -267,7 +262,6 @@ pub trait CrateStore {
     fn derive_registrar_fn(&self, cnum: CrateNum) -> Option<DefId>;
     fn native_libraries(&self, cnum: CrateNum) -> Vec<NativeLibrary>;
     fn exported_symbols(&self, cnum: CrateNum) -> Vec<DefId>;
-    fn is_no_builtins(&self, cnum: CrateNum) -> bool;
 
     // resolve
     fn def_key(&self, def: DefId) -> DefKey;
@@ -366,12 +360,6 @@ impl CrateStore for DummyCrateStore {
         { bug!("missing_lang_items") }
     fn dep_kind(&self, cnum: CrateNum) -> DepKind { bug!("is_explicitly_linked") }
     fn export_macros(&self, cnum: CrateNum) { bug!("export_macros") }
-    fn is_compiler_builtins(&self, cnum: CrateNum) -> bool { bug!("is_compiler_builtins") }
-    fn is_profiler_runtime(&self, cnum: CrateNum) -> bool { bug!("is_profiler_runtime") }
-    fn is_sanitizer_runtime(&self, cnum: CrateNum) -> bool { bug!("is_sanitizer_runtime") }
-    fn panic_strategy(&self, cnum: CrateNum) -> PanicStrategy {
-        bug!("panic_strategy")
-    }
     fn crate_name(&self, cnum: CrateNum) -> Symbol { bug!("crate_name") }
     fn original_crate_name(&self, cnum: CrateNum) -> Symbol {
         bug!("original_crate_name")
@@ -386,7 +374,6 @@ impl CrateStore for DummyCrateStore {
     fn native_libraries(&self, cnum: CrateNum) -> Vec<NativeLibrary>
         { bug!("native_libraries") }
     fn exported_symbols(&self, cnum: CrateNum) -> Vec<DefId> { bug!("exported_symbols") }
-    fn is_no_builtins(&self, cnum: CrateNum) -> bool { bug!("is_no_builtins") }
 
     // resolve
     fn def_key(&self, def: DefId) -> DefKey { bug!("def_key") }
diff --git a/src/librustc/middle/dependency_format.rs b/src/librustc/middle/dependency_format.rs
index 837ab4fd4a3..323c069ef0c 100644
--- a/src/librustc/middle/dependency_format.rs
+++ b/src/librustc/middle/dependency_format.rs
@@ -172,7 +172,7 @@ fn calculate_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         if src.dylib.is_some() {
             info!("adding dylib: {}", name);
             add_library(sess, cnum, RequireDynamic, &mut formats);
-            let deps = tcx.dylib_dependency_formats(cnum.as_def_id());
+            let deps = tcx.dylib_dependency_formats(cnum);
             for &(depnum, style) in deps.iter() {
                 info!("adding {:?}: {}", style,
                       sess.cstore.crate_name(depnum));
@@ -215,7 +215,7 @@ fn calculate_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     // Things like allocators and panic runtimes may not have been activated
     // quite yet, so do so here.
     activate_injected_dep(sess.injected_panic_runtime.get(), &mut ret,
-                          &|cnum| tcx.is_panic_runtime(cnum.as_def_id()));
+                          &|cnum| tcx.is_panic_runtime(cnum));
     activate_injected_allocator(sess, &mut ret);
 
     // When dylib B links to dylib A, then when using B we must also link to A.
@@ -295,7 +295,7 @@ fn attempt_static<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Option<DependencyLis
     // explicitly linked, which is the case for any injected dependency. Handle
     // that here and activate them.
     activate_injected_dep(sess.injected_panic_runtime.get(), &mut ret,
-                          &|cnum| tcx.is_panic_runtime(cnum.as_def_id()));
+                          &|cnum| tcx.is_panic_runtime(cnum));
     activate_injected_allocator(sess, &mut ret);
 
     Some(ret)
@@ -355,7 +355,7 @@ fn verify_ok<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, list: &[Linkage]) {
         }
         let cnum = CrateNum::new(i + 1);
 
-        if tcx.is_panic_runtime(cnum.as_def_id()) {
+        if tcx.is_panic_runtime(cnum) {
             if let Some((prev, _)) = panic_runtime {
                 let prev_name = sess.cstore.crate_name(prev);
                 let cur_name = sess.cstore.crate_name(cnum);
@@ -363,7 +363,7 @@ fn verify_ok<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, list: &[Linkage]) {
                                    panic runtimes: {} and {}",
                                   prev_name, cur_name));
             }
-            panic_runtime = Some((cnum, sess.cstore.panic_strategy(cnum)));
+            panic_runtime = Some((cnum, tcx.panic_strategy(cnum)));
         }
     }
 
@@ -395,8 +395,8 @@ fn verify_ok<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, list: &[Linkage]) {
                 continue
             }
             let cnum = CrateNum::new(i + 1);
-            let found_strategy = sess.cstore.panic_strategy(cnum);
-            let is_compiler_builtins = sess.cstore.is_compiler_builtins(cnum);
+            let found_strategy = tcx.panic_strategy(cnum);
+            let is_compiler_builtins = tcx.is_compiler_builtins(cnum);
             if is_compiler_builtins || desired_strategy == found_strategy {
                 continue
             }
diff --git a/src/librustc/ty/maps.rs b/src/librustc/ty/maps.rs
index 5a372dbf89f..20b082552d5 100644
--- a/src/librustc/ty/maps.rs
+++ b/src/librustc/ty/maps.rs
@@ -32,6 +32,7 @@ use util::nodemap::{DefIdSet, NodeSet};
 use util::common::{profq_msg, ProfileQueriesMsg};
 
 use rustc_data_structures::indexed_set::IdxSetBuf;
+use rustc_back::PanicStrategy;
 use rustc_data_structures::indexed_vec::IndexVec;
 use rustc_data_structures::fx::FxHashMap;
 use std::cell::{RefCell, RefMut, Cell};
@@ -509,31 +510,25 @@ impl<'tcx> QueryDescription for queries::is_const_fn<'tcx> {
 }
 
 impl<'tcx> QueryDescription for queries::dylib_dependency_formats<'tcx> {
-    fn describe(_: TyCtxt, _: DefId) -> String {
+    fn describe(_: TyCtxt, _: CrateNum) -> String {
         "dylib dependency formats of crate".to_string()
     }
 }
 
-impl<'tcx> QueryDescription for queries::is_allocator<'tcx> {
-    fn describe(_: TyCtxt, _: DefId) -> String {
-        "checking if the crate is_allocator".to_string()
-    }
-}
-
 impl<'tcx> QueryDescription for queries::is_panic_runtime<'tcx> {
-    fn describe(_: TyCtxt, _: DefId) -> String {
+    fn describe(_: TyCtxt, _: CrateNum) -> String {
         "checking if the crate is_panic_runtime".to_string()
     }
 }
 
 impl<'tcx> QueryDescription for queries::is_compiler_builtins<'tcx> {
-    fn describe(_: TyCtxt, _: DefId) -> String {
+    fn describe(_: TyCtxt, _: CrateNum) -> String {
         "checking if the crate is_compiler_builtins".to_string()
     }
 }
 
 impl<'tcx> QueryDescription for queries::has_global_allocator<'tcx> {
-    fn describe(_: TyCtxt, _: DefId) -> String {
+    fn describe(_: TyCtxt, _: CrateNum) -> String {
         "checking if the crate has_global_allocator".to_string()
     }
 }
@@ -568,6 +563,30 @@ impl<'tcx> QueryDescription for queries::module_exports<'tcx> {
     }
 }
 
+impl<'tcx> QueryDescription for queries::is_no_builtins<'tcx> {
+    fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
+        format!("test whether a crate has #![no_builtins]")
+    }
+}
+
+impl<'tcx> QueryDescription for queries::panic_strategy<'tcx> {
+    fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
+        format!("query a crate's configured panic strategy")
+    }
+}
+
+impl<'tcx> QueryDescription for queries::is_profiler_runtime<'tcx> {
+    fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
+        format!("query a crate is #![profiler_runtime]")
+    }
+}
+
+impl<'tcx> QueryDescription for queries::is_sanitizer_runtime<'tcx> {
+    fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
+        format!("query a crate is #![sanitizer_runtime]")
+    }
+}
+
 // If enabled, send a message to the profile-queries thread
 macro_rules! profq_msg {
     ($tcx:expr, $msg:expr) => {
@@ -1125,21 +1144,23 @@ define_maps! { <'tcx>
     [] fn layout_raw: layout_dep_node(ty::ParamEnvAnd<'tcx, Ty<'tcx>>)
                                   -> Result<&'tcx Layout, LayoutError<'tcx>>,
 
-    [] fn dylib_dependency_formats: DylibDepFormats(DefId)
+    [] fn dylib_dependency_formats: DylibDepFormats(CrateNum)
                                     -> Rc<Vec<(CrateNum, LinkagePreference)>>,
 
-    [] fn is_allocator: IsAllocator(DefId) -> bool,
-    [] fn is_panic_runtime: IsPanicRuntime(DefId) -> bool,
-    [] fn is_compiler_builtins: IsCompilerBuiltins(DefId) -> bool,
-    [] fn has_global_allocator: HasGlobalAllocator(DefId) -> bool,
+    [] fn is_panic_runtime: IsPanicRuntime(CrateNum) -> bool,
+    [] fn is_compiler_builtins: IsCompilerBuiltins(CrateNum) -> bool,
+    [] fn has_global_allocator: HasGlobalAllocator(CrateNum) -> bool,
+    [] fn is_sanitizer_runtime: IsSanitizerRuntime(CrateNum) -> bool,
+    [] fn is_profiler_runtime: IsProfilerRuntime(CrateNum) -> bool,
+    [] fn panic_strategy: GetPanicStrategy(CrateNum) -> PanicStrategy,
+    [] fn is_no_builtins: IsNoBuiltins(CrateNum) -> bool,
 
     [] fn extern_crate: ExternCrate(DefId) -> Rc<Option<ExternCrate>>,
 
-    [] fn lint_levels: lint_levels(CrateNum) -> Rc<lint::LintLevelMap>,
-
     [] fn specializes: specializes_node((DefId, DefId)) -> bool,
     [] fn in_scope_traits: InScopeTraits(HirId) -> Option<Rc<Vec<TraitCandidate>>>,
     [] fn module_exports: ModuleExports(HirId) -> Option<Rc<Vec<Export>>>,
+    [] fn lint_levels: lint_levels_node(CrateNum) -> Rc<lint::LintLevelMap>,
 }
 
 fn type_param_predicates<'tcx>((item_id, param_id): (DefId, DefId)) -> DepConstructor<'tcx> {
@@ -1212,7 +1233,7 @@ fn layout_dep_node<'tcx>(_: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> DepConstructor<'
     DepConstructor::Layout
 }
 
-fn lint_levels<'tcx>(_: CrateNum) -> DepConstructor<'tcx> {
+fn lint_levels_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> {
     DepConstructor::LintLevels
 }
 
diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs
index 537e1208614..76051f382cc 100644
--- a/src/librustc_metadata/cstore_impl.rs
+++ b/src/librustc_metadata/cstore_impl.rs
@@ -27,7 +27,6 @@ use rustc::hir::map::{DefKey, DefPath, DefPathHash};
 use rustc::hir::map::blocks::FnLikeNode;
 use rustc::hir::map::definitions::{DefPathTable, GlobalMetaDataKind};
 use rustc::util::nodemap::{NodeSet, DefIdMap};
-use rustc_back::PanicStrategy;
 
 use std::any::Any;
 use std::rc::Rc;
@@ -45,9 +44,12 @@ use rustc::hir;
 macro_rules! provide {
     (<$lt:tt> $tcx:ident, $def_id:ident, $cdata:ident, $($name:ident => $compute:block)*) => {
         pub fn provide<$lt>(providers: &mut Providers<$lt>) {
-            $(fn $name<'a, $lt:$lt>($tcx: TyCtxt<'a, $lt, $lt>, $def_id: DefId)
+            $(fn $name<'a, $lt:$lt, T>($tcx: TyCtxt<'a, $lt, $lt>, def_id_arg: T)
                                     -> <ty::queries::$name<$lt> as
-                                        QueryConfig>::Value {
+                                        QueryConfig>::Value
+                where T: IntoDefId,
+            {
+                let $def_id = def_id_arg.into_def_id();
                 assert!(!$def_id.is_local());
 
                 let def_path_hash = $tcx.def_path_hash($def_id);
@@ -69,6 +71,18 @@ macro_rules! provide {
     }
 }
 
+trait IntoDefId {
+    fn into_def_id(self) -> DefId;
+}
+
+impl IntoDefId for DefId {
+    fn into_def_id(self) -> DefId { self }
+}
+
+impl IntoDefId for CrateNum {
+    fn into_def_id(self) -> DefId { self.as_def_id() }
+}
+
 provide! { <'tcx> tcx, def_id, cdata,
     type_of => { cdata.get_type(def_id.index, tcx) }
     generics_of => { tcx.alloc_generics(cdata.get_generics(def_id.index)) }
@@ -143,7 +157,11 @@ provide! { <'tcx> tcx, def_id, cdata,
     is_panic_runtime => { cdata.is_panic_runtime(&tcx.dep_graph) }
     is_compiler_builtins => { cdata.is_compiler_builtins(&tcx.dep_graph) }
     has_global_allocator => { cdata.has_global_allocator(&tcx.dep_graph) }
+    is_sanitizer_runtime => { cdata.is_sanitizer_runtime(&tcx.dep_graph) }
+    is_profiler_runtime => { cdata.is_profiler_runtime(&tcx.dep_graph) }
+    panic_strategy => { cdata.panic_strategy(&tcx.dep_graph) }
     extern_crate => { Rc::new(cdata.extern_crate.get()) }
+    is_no_builtins => { cdata.is_no_builtins(&tcx.dep_graph) }
 }
 
 pub fn provide_local<'tcx>(providers: &mut Providers<'tcx>) {
@@ -248,22 +266,6 @@ impl CrateStore for cstore::CStore {
         self.get_crate_data(cnum).get_missing_lang_items(&self.dep_graph)
     }
 
-    fn is_compiler_builtins(&self, cnum: CrateNum) -> bool {
-        self.get_crate_data(cnum).is_compiler_builtins(&self.dep_graph)
-    }
-
-    fn is_sanitizer_runtime(&self, cnum: CrateNum) -> bool {
-        self.get_crate_data(cnum).is_sanitizer_runtime(&self.dep_graph)
-    }
-
-    fn is_profiler_runtime(&self, cnum: CrateNum) -> bool {
-        self.get_crate_data(cnum).is_profiler_runtime(&self.dep_graph)
-    }
-
-    fn panic_strategy(&self, cnum: CrateNum) -> PanicStrategy {
-        self.get_crate_data(cnum).panic_strategy(&self.dep_graph)
-    }
-
     fn crate_name(&self, cnum: CrateNum) -> Symbol
     {
         self.get_crate_data(cnum).name
@@ -310,10 +312,6 @@ impl CrateStore for cstore::CStore {
         self.get_crate_data(cnum).get_exported_symbols(&self.dep_graph)
     }
 
-    fn is_no_builtins(&self, cnum: CrateNum) -> bool {
-        self.get_crate_data(cnum).is_no_builtins(&self.dep_graph)
-    }
-
     /// Returns the `DefKey` for a given `DefId`. This indicates the
     /// parent `DefId` as well as some idea of what kind of data the
     /// `DefId` refers to.
diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs
index 4b56376ad9b..e69a2322aaa 100644
--- a/src/librustc_trans/back/link.rs
+++ b/src/librustc_trans/back/link.rs
@@ -22,7 +22,7 @@ use rustc::session::Session;
 use rustc::middle::cstore::{LinkMeta, NativeLibrary, LibSource, LinkagePreference,
                             NativeLibraryKind};
 use rustc::middle::dependency_format::Linkage;
-use CrateTranslation;
+use {CrateTranslation, CrateInfo};
 use rustc::util::common::time;
 use rustc::util::fs::fix_windows_verbatim_for_gcc;
 use rustc::dep_graph::{DepKind, DepNode};
@@ -260,12 +260,12 @@ pub fn each_linked_rlib(sess: &Session,
 /// It's unusual for a crate to not participate in LTO. Typically only
 /// compiler-specific and unstable crates have a reason to not participate in
 /// LTO.
-pub fn ignored_for_lto(sess: &Session, cnum: CrateNum) -> bool {
+pub fn ignored_for_lto(info: &CrateInfo, cnum: CrateNum) -> bool {
     // `#![no_builtins]` crates don't participate in LTO because the state
     // of builtins gets messed up (our crate isn't tagged with no builtins).
     // Similarly `#![compiler_builtins]` doesn't participate because we want
     // those builtins!
-    sess.cstore.is_no_builtins(cnum) || sess.cstore.is_compiler_builtins(cnum)
+    info.is_no_builtins.contains(&cnum) || info.compiler_builtins == Some(cnum)
 }
 
 fn out_filename(sess: &Session,
@@ -634,7 +634,7 @@ fn link_staticlib(sess: &Session,
         });
         ab.add_rlib(path,
                     &name.as_str(),
-                    sess.lto() && !ignored_for_lto(sess, cnum),
+                    sess.lto() && !ignored_for_lto(&trans.crate_info, cnum),
                     skip_object_files).unwrap();
 
         all_native_libs.extend(sess.cstore.native_libraries(cnum));
@@ -1001,7 +1001,7 @@ fn link_args(cmd: &mut Linker,
     // in this DAG so far because they're only dylibs and dylibs can only depend
     // on other dylibs (e.g. other native deps).
     add_local_native_libraries(cmd, sess);
-    add_upstream_rust_crates(cmd, sess, crate_type, tmpdir);
+    add_upstream_rust_crates(cmd, sess, trans, crate_type, tmpdir);
     add_upstream_native_libraries(cmd, sess, crate_type);
 
     // Tell the linker what we're doing.
@@ -1088,6 +1088,7 @@ fn add_local_native_libraries(cmd: &mut Linker, sess: &Session) {
 // the intermediate rlib version)
 fn add_upstream_rust_crates(cmd: &mut Linker,
                             sess: &Session,
+                            trans: &CrateTranslation,
                             crate_type: config::CrateType,
                             tmpdir: &Path) {
     // All of the heavy lifting has previously been accomplished by the
@@ -1113,22 +1114,22 @@ fn add_upstream_rust_crates(cmd: &mut Linker,
         // symbols from the dylib.
         let src = sess.cstore.used_crate_source(cnum);
         match data[cnum.as_usize() - 1] {
-            _ if sess.cstore.is_profiler_runtime(cnum) => {
-                add_static_crate(cmd, sess, tmpdir, crate_type, cnum);
+            _ if trans.crate_info.profiler_runtime == Some(cnum) => {
+                add_static_crate(cmd, sess, trans, tmpdir, crate_type, cnum);
             }
-            _ if sess.cstore.is_sanitizer_runtime(cnum) => {
+            _ if trans.crate_info.sanitizer_runtime == Some(cnum) => {
                 link_sanitizer_runtime(cmd, sess, tmpdir, cnum);
             }
             // compiler-builtins are always placed last to ensure that they're
             // linked correctly.
-            _ if sess.cstore.is_compiler_builtins(cnum) => {
+            _ if trans.crate_info.compiler_builtins == Some(cnum) => {
                 assert!(compiler_builtins.is_none());
                 compiler_builtins = Some(cnum);
             }
             Linkage::NotLinked |
             Linkage::IncludedFromDylib => {}
             Linkage::Static => {
-                add_static_crate(cmd, sess, tmpdir, crate_type, cnum);
+                add_static_crate(cmd, sess, trans, tmpdir, crate_type, cnum);
             }
             Linkage::Dynamic => {
                 add_dynamic_crate(cmd, sess, &src.dylib.unwrap().0)
@@ -1142,7 +1143,7 @@ fn add_upstream_rust_crates(cmd: &mut Linker,
     // was already "included" in a dylib (e.g. `libstd` when `-C prefer-dynamic`
     // is used)
     if let Some(cnum) = compiler_builtins {
-        add_static_crate(cmd, sess, tmpdir, crate_type, cnum);
+        add_static_crate(cmd, sess, trans, tmpdir, crate_type, cnum);
     }
 
     // Converts a library file-stem into a cc -l argument
@@ -1228,6 +1229,7 @@ fn add_upstream_rust_crates(cmd: &mut Linker,
     // we're at the end of the dependency chain.
     fn add_static_crate(cmd: &mut Linker,
                         sess: &Session,
+                        trans: &CrateTranslation,
                         tmpdir: &Path,
                         crate_type: config::CrateType,
                         cnum: CrateNum) {
@@ -1242,7 +1244,7 @@ fn add_upstream_rust_crates(cmd: &mut Linker,
             lib.kind == NativeLibraryKind::NativeStatic && !relevant_lib(sess, lib)
         });
 
-        if (!sess.lto() || ignored_for_lto(sess, cnum)) &&
+        if (!sess.lto() || ignored_for_lto(&trans.crate_info, cnum)) &&
            crate_type != config::CrateTypeDylib &&
            !skip_native {
             cmd.link_rlib(&fix_windows_verbatim_for_gcc(cratepath));
@@ -1284,7 +1286,7 @@ fn add_upstream_rust_crates(cmd: &mut Linker,
                 // LTO module. Note that `#![no_builtins]` is excluded from LTO,
                 // though, so we let that object file slide.
                 let skip_because_lto = sess.lto() && is_rust_object &&
-                                        !sess.cstore.is_no_builtins(cnum);
+                                        !trans.crate_info.is_no_builtins.contains(&cnum);
 
                 if skip_because_cfg_say_so || skip_because_lto {
                     archive.remove_file(&f);
@@ -1306,7 +1308,7 @@ fn add_upstream_rust_crates(cmd: &mut Linker,
             // compiler-builtins crate (e.g. compiler-rt) because it'll get
             // repeatedly linked anyway.
             if crate_type == config::CrateTypeDylib &&
-               !sess.cstore.is_compiler_builtins(cnum) {
+                trans.crate_info.compiler_builtins != Some(cnum) {
                 cmd.link_whole_rlib(&fix_windows_verbatim_for_gcc(&dst));
             } else {
                 cmd.link_rlib(&fix_windows_verbatim_for_gcc(&dst));
diff --git a/src/librustc_trans/back/symbol_export.rs b/src/librustc_trans/back/symbol_export.rs
index 971483e91b6..729573a0f3a 100644
--- a/src/librustc_trans/back/symbol_export.rs
+++ b/src/librustc_trans/back/symbol_export.rs
@@ -128,8 +128,7 @@ impl ExportedSymbols {
             // Down below we'll hardwire all of the symbols to the `Rust` export
             // level instead.
             let special_runtime_crate =
-                tcx.is_panic_runtime(cnum.as_def_id()) ||
-                tcx.sess.cstore.is_compiler_builtins(cnum);
+                tcx.is_panic_runtime(cnum) || tcx.is_compiler_builtins(cnum);
 
             let crate_exports = tcx
                 .sess
diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs
index 3f9b28d3d61..ed7a745e440 100644
--- a/src/librustc_trans/back/write.rs
+++ b/src/librustc_trans/back/write.rs
@@ -22,6 +22,7 @@ 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::util::common::{time, time_depth, set_time_depth, path2cstr, print_time_passes_entry};
 use rustc::util::fs::{link_or_copy, rename_or_copy_remove};
@@ -675,6 +676,7 @@ pub fn start_async_translation(sess: &Session,
                                no_builtins: bool,
                                windows_subsystem: Option<String>,
                                linker_info: LinkerInfo,
+                               crate_info: CrateInfo,
                                no_integrated_as: bool)
                                -> OngoingCrateTranslation {
     let output_types_override = if no_integrated_as {
@@ -774,6 +776,7 @@ pub fn start_async_translation(sess: &Session,
     let (coordinator_send, coordinator_receive) = channel();
 
     let coordinator_thread = start_executing_work(sess,
+                                                  &crate_info,
                                                   shared_emitter,
                                                   trans_worker_send,
                                                   coordinator_send.clone(),
@@ -788,6 +791,7 @@ pub fn start_async_translation(sess: &Session,
         windows_subsystem,
         linker_info,
         no_integrated_as,
+        crate_info,
 
         regular_module_config: modules_config,
         metadata_module_config: metadata_config,
@@ -1101,6 +1105,7 @@ enum MainThreadWorkerState {
 }
 
 fn start_executing_work(sess: &Session,
+                        crate_info: &CrateInfo,
                         shared_emitter: SharedEmitter,
                         trans_worker_send: Sender<Message>,
                         coordinator_send: Sender<Message>,
@@ -1126,7 +1131,7 @@ fn start_executing_work(sess: &Session,
 
     let mut each_linked_rlib_for_lto = Vec::new();
     drop(link::each_linked_rlib(sess, &mut |cnum, path| {
-        if link::ignored_for_lto(sess, cnum) {
+        if link::ignored_for_lto(crate_info, cnum) {
             return
         }
         each_linked_rlib_for_lto.push((cnum, path.to_path_buf()));
@@ -1802,6 +1807,7 @@ pub struct OngoingCrateTranslation {
     windows_subsystem: Option<String>,
     linker_info: LinkerInfo,
     no_integrated_as: bool,
+    crate_info: CrateInfo,
 
     output_filenames: OutputFilenames,
     regular_module_config: ModuleConfig,
@@ -1850,6 +1856,7 @@ impl OngoingCrateTranslation {
             metadata: self.metadata,
             windows_subsystem: self.windows_subsystem,
             linker_info: self.linker_info,
+            crate_info: self.crate_info,
 
             modules: compiled_modules.modules,
             allocator_module: compiled_modules.allocator_module,
diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs
index a6c6b0efcfa..3da8d07f9d7 100644
--- a/src/librustc_trans/base.rs
+++ b/src/librustc_trans/base.rs
@@ -75,6 +75,7 @@ use type_::Type;
 use type_of;
 use value::Value;
 use rustc::util::nodemap::{NodeSet, FxHashMap, FxHashSet};
+use CrateInfo;
 
 use libc::c_uint;
 use std::ffi::{CStr, CString};
@@ -970,6 +971,7 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     } 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 ||
@@ -987,6 +989,7 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             no_builtins,
             None,
             linker_info,
+            crate_info,
             false);
 
         ongoing_translation.submit_pre_translated_module_to_llvm(tcx.sess, metadata_module, true);
@@ -1039,6 +1042,7 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         no_builtins,
         windows_subsystem,
         linker_info,
+        crate_info,
         no_integrated_as);
 
     // Translate an allocator shim, if any
@@ -1502,3 +1506,35 @@ fn collect_and_partition_translation_items<'a, 'tcx>(scx: &SharedCrateContext<'a
 
     (translation_items, codegen_units)
 }
+
+impl CrateInfo {
+    pub fn new(tcx: TyCtxt) -> CrateInfo {
+        let mut info = CrateInfo {
+            panic_runtime: None,
+            compiler_builtins: None,
+            profiler_runtime: None,
+            sanitizer_runtime: None,
+            is_no_builtins: FxHashSet(),
+        };
+
+        for cnum in tcx.sess.cstore.crates() {
+            if tcx.is_panic_runtime(cnum) {
+                info.panic_runtime = Some(cnum);
+            }
+            if tcx.is_compiler_builtins(cnum) {
+                info.compiler_builtins = Some(cnum);
+            }
+            if tcx.is_profiler_runtime(cnum) {
+                info.profiler_runtime = Some(cnum);
+            }
+            if tcx.is_sanitizer_runtime(cnum) {
+                info.sanitizer_runtime = Some(cnum);
+            }
+            if tcx.is_no_builtins(cnum) {
+                info.is_no_builtins.insert(cnum);
+            }
+        }
+
+        return info
+    }
+}
diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs
index 1758e331129..42aa47436c8 100644
--- a/src/librustc_trans/lib.rs
+++ b/src/librustc_trans/lib.rs
@@ -65,6 +65,8 @@ pub use back::symbol_names::provide;
 
 pub use metadata::LlvmMetadataLoader;
 pub use llvm_util::{init, target_features, print_version, print_passes, print, enable_llvm_debug};
+use rustc::hir::def_id::CrateNum;
+use rustc::util::nodemap::FxHashSet;
 
 pub mod back {
     mod archive;
@@ -216,7 +218,17 @@ pub struct CrateTranslation {
     pub link: rustc::middle::cstore::LinkMeta,
     pub metadata: rustc::middle::cstore::EncodedMetadata,
     windows_subsystem: Option<String>,
-    linker_info: back::linker::LinkerInfo
+    linker_info: back::linker::LinkerInfo,
+    crate_info: CrateInfo,
+}
+
+// Misc info we load from metadata to persist beyond the tcx
+pub struct CrateInfo {
+    panic_runtime: Option<CrateNum>,
+    compiler_builtins: Option<CrateNum>,
+    profiler_runtime: Option<CrateNum>,
+    sanitizer_runtime: Option<CrateNum>,
+    is_no_builtins: FxHashSet<CrateNum>,
 }
 
 __build_diagnostic_array! { librustc_trans, DIAGNOSTICS }
diff --git a/src/librustc_typeck/check_unused.rs b/src/librustc_typeck/check_unused.rs
index 3da154e0689..eca7aabb46d 100644
--- a/src/librustc_typeck/check_unused.rs
+++ b/src/librustc_typeck/check_unused.rs
@@ -74,7 +74,7 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
     tcx.hir.krate().visit_all_item_likes(&mut visitor);
 
     for &(id, span) in &tcx.maybe_unused_extern_crates {
-        let cnum = tcx.sess.cstore.extern_mod_stmt_cnum(id).unwrap().as_def_id();
+        let cnum = tcx.sess.cstore.extern_mod_stmt_cnum(id).unwrap();
         if !tcx.is_compiler_builtins(cnum)
             && !tcx.is_panic_runtime(cnum)
             && !tcx.has_global_allocator(cnum) {