This commit removes the `use_crates` and `used_crate_source` methods in favor of
a mix of queries and helper methods being used now instead.
[] VisibleParentMap,
[] IsDirectExternCrate(CrateNum),
[] MissingExternCrateItem(CrateNum),
+ [] UsedCrateSource(CrateNum),
+ [] PostorderCnums,
);
trait DepNodeParams<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> : fmt::Debug {
//! probably get a better home if someone can find one.
use hir::def;
-use hir::def_id::{CrateNum, DefId, DefIndex};
+use hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE};
use hir::map as hir_map;
use hir::map::definitions::{Definitions, DefKey, DefPathTable};
use hir::svh::Svh;
fn extern_mod_stmt_cnum_untracked(&self, emod_id: ast::NodeId) -> Option<CrateNum>;
fn item_generics_cloned_untracked(&self, def: DefId) -> ty::Generics;
fn associated_item_cloned_untracked(&self, def: DefId) -> ty::AssociatedItem;
+ fn postorder_cnums_untracked(&self) -> Vec<CrateNum>;
// This is basically a 1-based range of ints, which is a little
// silly - I may fix that.
fn crates(&self) -> Vec<CrateNum>;
// utility functions
- fn used_crates(&self, prefer: LinkagePreference) -> Vec<(CrateNum, LibSource)>;
- fn used_crate_source(&self, cnum: CrateNum) -> CrateSource;
fn encode_metadata<'a, 'tcx>(&self,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
link_meta: &LinkMeta,
fn crates(&self) -> Vec<CrateNum> { vec![] }
// utility functions
- fn used_crates(&self, prefer: LinkagePreference) -> Vec<(CrateNum, LibSource)>
- { vec![] }
- fn used_crate_source(&self, cnum: CrateNum) -> CrateSource { bug!("used_crate_source") }
fn extern_mod_stmt_cnum_untracked(&self, emod_id: ast::NodeId) -> Option<CrateNum> { None }
fn encode_metadata<'a, 'tcx>(&self,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
bug!("encode_metadata")
}
fn metadata_encoding_version(&self) -> &[u8] { bug!("metadata_encoding_version") }
+ fn postorder_cnums_untracked(&self) -> Vec<CrateNum> { bug!("postorder_cnums_untracked") }
// access to the metadata loader
fn metadata_loader(&self) -> &MetadataLoader { bug!("metadata_loader") }
fn process_item(&mut self, item: &ast::Item, defs: &Definitions);
fn postprocess(&mut self, krate: &ast::Crate);
}
+
+// This method is used when generating the command line to pass through to
+// system linker. The linker expects undefined symbols on the left of the
+// command line to be defined in libraries on the right, not the other way
+// around. For more info, see some comments in the add_used_library function
+// below.
+//
+// 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)> {
+ let mut libs = tcx.sess.cstore.crates()
+ .into_iter()
+ .filter_map(|cnum| {
+ if tcx.dep_kind(cnum).macros_only() {
+ return None
+ }
+ let source = tcx.used_crate_source(cnum);
+ let path = match prefer {
+ LinkagePreference::RequireDynamic => source.dylib.clone().map(|p| p.0),
+ LinkagePreference::RequireStatic => source.rlib.clone().map(|p| p.0),
+ };
+ let path = match path {
+ Some(p) => LibSource::Some(p),
+ None => {
+ if source.rmeta.is_some() {
+ LibSource::MetadataOnly
+ } else {
+ LibSource::None
+ }
+ }
+ };
+ Some((cnum, path))
+ })
+ .collect::<Vec<_>>();
+ let mut ordering = tcx.postorder_cnums(LOCAL_CRATE);
+ Rc::make_mut(&mut ordering).reverse();
+ libs.sort_by_key(|&(a, _)| {
+ ordering.iter().position(|x| *x == a)
+ });
+ libs
+}
use session;
use session::config;
use ty::TyCtxt;
-use middle::cstore::DepKind;
+use middle::cstore::{self, DepKind};
use middle::cstore::LinkagePreference::{self, RequireStatic, RequireDynamic};
use util::nodemap::FxHashMap;
use rustc_back::PanicStrategy;
}
for cnum in sess.cstore.crates() {
if tcx.dep_kind(cnum).macros_only() { continue }
- let src = sess.cstore.used_crate_source(cnum);
+ let src = tcx.used_crate_source(cnum);
if src.rlib.is_some() { continue }
sess.err(&format!("dependency `{}` not found in rlib format",
tcx.crate_name(cnum)));
for cnum in sess.cstore.crates() {
if tcx.dep_kind(cnum).macros_only() { continue }
let name = tcx.crate_name(cnum);
- let src = sess.cstore.used_crate_source(cnum);
+ let src = tcx.used_crate_source(cnum);
if src.dylib.is_some() {
info!("adding dylib: {}", name);
add_library(tcx, cnum, RequireDynamic, &mut formats);
// If the crate hasn't been included yet and it's not actually required
// (e.g. it's an allocator) then we skip it here as well.
for cnum in sess.cstore.crates() {
- let src = sess.cstore.used_crate_source(cnum);
+ let src = tcx.used_crate_source(cnum);
if src.dylib.is_none() &&
!formats.contains_key(&cnum) &&
tcx.dep_kind(cnum) == DepKind::Explicit {
// making sure that everything is available in the requested format.
for (cnum, kind) in ret.iter().enumerate() {
let cnum = CrateNum::new(cnum + 1);
- let src = sess.cstore.used_crate_source(cnum);
+ let src = tcx.used_crate_source(cnum);
match *kind {
Linkage::NotLinked |
Linkage::IncludedFromDylib => {}
fn attempt_static<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Option<DependencyList> {
let sess = &tcx.sess;
- let crates = sess.cstore.used_crates(RequireStatic);
+ let crates = cstore::used_crates(tcx, RequireStatic);
if !crates.iter().by_ref().all(|&(_, ref p)| p.is_some()) {
return None
}
use lint;
use middle::const_val;
use middle::cstore::{ExternCrate, LinkagePreference, NativeLibrary};
-use middle::cstore::{NativeLibraryKind, DepKind};
+use middle::cstore::{NativeLibraryKind, DepKind, CrateSource};
use middle::privacy::AccessLevels;
use middle::region;
use middle::region::RegionMaps;
}
}
+impl<'tcx> QueryDescription for queries::used_crate_source<'tcx> {
+ fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
+ format!("looking at the source for a crate")
+ }
+}
+
+impl<'tcx> QueryDescription for queries::postorder_cnums<'tcx> {
+ fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
+ format!("generating a postorder list of CrateNums")
+ }
+}
+
// If enabled, send a message to the profile-queries thread
macro_rules! profq_msg {
($tcx:expr, $msg:expr) => {
[] visible_parent_map: visible_parent_map_node(CrateNum)
-> Rc<DefIdMap<DefId>>,
[] missing_extern_crate_item: MissingExternCrateItem(CrateNum) -> bool,
+ [] used_crate_source: UsedCrateSource(CrateNum) -> Rc<CrateSource>,
+ [] postorder_cnums: postorder_cnums_node(CrateNum) -> Rc<Vec<CrateNum>>,
}
fn type_param_predicates<'tcx>((item_id, param_id): (DefId, DefId)) -> DepConstructor<'tcx> {
fn visible_parent_map_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> {
DepConstructor::VisibleParentMap
}
+
+fn postorder_cnums_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> {
+ DepConstructor::PostorderCnums
+}
use rustc_back::PanicStrategy;
use rustc::session::search_paths::PathKind;
use rustc::middle;
-use rustc::middle::cstore::{CrateStore, validate_crate_name, ExternCrate};
+use rustc::middle::cstore::{validate_crate_name, ExternCrate};
use rustc::util::common::record_time;
use rustc::util::nodemap::FxHashSet;
use rustc::hir::map::Definitions;
// We're also sure to compare *paths*, not actual byte slices. The
// `source` stores paths which are normalized which may be different
// from the strings on the command line.
- let source = self.cstore.used_crate_source(cnum);
+ let source = &self.cstore.get_crate_data(cnum).source;
if let Some(locs) = self.sess.opts.externs.get(&*name.as_str()) {
let found = locs.iter().any(|l| {
let l = fs::canonicalize(l).ok();
ordering.push(krate);
}
- // This method is used when generating the command line to pass through to
- // system linker. The linker expects undefined symbols on the left of the
- // command line to be defined in libraries on the right, not the other way
- // around. For more info, see some comments in the add_used_library function
- // below.
- //
- // 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 do_get_used_crates(&self,
- prefer: LinkagePreference)
- -> Vec<(CrateNum, LibSource)> {
+ pub fn do_postorder_cnums_untracked(&self) -> Vec<CrateNum> {
let mut ordering = Vec::new();
for (&num, _) in self.metas.borrow().iter() {
self.push_dependencies_in_postorder(&mut ordering, num);
}
- info!("topological ordering: {:?}", ordering);
- ordering.reverse();
- let mut libs = self.metas
- .borrow()
- .iter()
- .filter_map(|(&cnum, data)| {
- if data.dep_kind.get().macros_only() { return None; }
- let path = match prefer {
- LinkagePreference::RequireDynamic => data.source.dylib.clone().map(|p| p.0),
- LinkagePreference::RequireStatic => data.source.rlib.clone().map(|p| p.0),
- };
- let path = match path {
- Some(p) => LibSource::Some(p),
- None => {
- if data.source.rmeta.is_some() {
- LibSource::MetadataOnly
- } else {
- LibSource::None
- }
- }
- };
- Some((cnum, path))
- })
- .collect::<Vec<_>>();
- libs.sort_by(|&(a, _), &(b, _)| {
- let a = ordering.iter().position(|x| *x == a);
- let b = ordering.iter().position(|x| *x == b);
- a.cmp(&b)
- });
- libs
+ return ordering
}
pub fn add_extern_mod_stmt_cnum(&self, emod_id: ast::NodeId, cnum: CrateNum) {
use schema;
use rustc::ty::maps::QueryConfig;
-use rustc::middle::cstore::{CrateStore, CrateSource, LibSource, DepKind,
+use rustc::middle::cstore::{CrateStore, DepKind,
MetadataLoader, LinkMeta,
- LinkagePreference, LoadedMacro, EncodedMetadata,
+ LoadedMacro, EncodedMetadata,
EncodedMetadataHashes, NativeLibraryKind};
use rustc::hir::def;
use rustc::session::Session;
_ => false,
}
}
+
+ used_crate_source => { Rc::new(cdata.source.clone()) }
}
pub fn provide_local<'tcx>(providers: &mut Providers<'tcx>) {
Rc::new(visible_parent_map)
},
+ postorder_cnums: |tcx, cnum| {
+ assert_eq!(cnum, LOCAL_CRATE);
+ Rc::new(tcx.sess.cstore.postorder_cnums_untracked())
+ },
+
..*providers
};
}
result
}
- fn used_crates(&self, prefer: LinkagePreference) -> Vec<(CrateNum, LibSource)>
- {
- self.do_get_used_crates(prefer)
- }
-
- fn used_crate_source(&self, cnum: CrateNum) -> CrateSource
- {
- self.get_crate_data(cnum).source.clone()
- }
-
fn extern_mod_stmt_cnum_untracked(&self, emod_id: ast::NodeId) -> Option<CrateNum>
{
self.do_extern_mod_stmt_cnum(emod_id)
}
+ fn postorder_cnums_untracked(&self) -> Vec<CrateNum> {
+ self.do_postorder_cnums_untracked()
+ }
+
fn encode_metadata<'a, 'tcx>(&self,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
link_meta: &LinkMeta,
use rustc::session::filesearch;
use rustc::session::search_paths::PathKind;
use rustc::session::Session;
-use rustc::middle::cstore::{LinkMeta, NativeLibrary, LibSource, LinkagePreference,
- NativeLibraryKind};
+use rustc::middle::cstore::{LinkMeta, NativeLibrary, LibSource, NativeLibraryKind};
use rustc::middle::dependency_format::Linkage;
use {CrateTranslation, CrateInfo};
use rustc::util::common::time;
pub fn each_linked_rlib(sess: &Session,
info: &CrateInfo,
f: &mut FnMut(CrateNum, &Path)) -> Result<(), String> {
- let crates = sess.cstore.used_crates(LinkagePreference::RequireStatic).into_iter();
+ let crates = info.used_crates_static.iter();
let fmts = sess.dependency_formats.borrow();
let fmts = fmts.get(&config::CrateTypeExecutable)
.or_else(|| fmts.get(&config::CrateTypeStaticlib))
Some(f) => f,
None => return Err(format!("could not find formats for rlibs"))
};
- for (cnum, path) in crates {
+ for &(cnum, ref path) in crates {
match fmts.get(cnum.as_usize() - 1) {
Some(&Linkage::NotLinked) |
Some(&Linkage::IncludedFromDylib) => continue,
None => return Err(format!("could not find formats for rlibs"))
}
let name = &info.crate_name[&cnum];
- let path = match path {
- LibSource::Some(p) => p,
+ let path = match *path {
+ LibSource::Some(ref p) => p,
LibSource::MetadataOnly => {
return Err(format!("could not find rlib for: `{}`, found rmeta (metadata) file",
name))
path
};
let mut rpath_config = RPathConfig {
- used_crates: sess.cstore.used_crates(LinkagePreference::RequireDynamic),
+ used_crates: &trans.crate_info.used_crates_dynamic,
out_filename: out_filename.to_path_buf(),
has_rpath: sess.target.target.options.has_rpath,
is_like_osx: sess.target.target.options.is_like_osx,
// Invoke get_used_crates to ensure that we get a topological sorting of
// crates.
- let deps = sess.cstore.used_crates(LinkagePreference::RequireDynamic);
+ let deps = &trans.crate_info.used_crates_dynamic;
let mut compiler_builtins = None;
- for &(cnum, _) in &deps {
+ for &(cnum, _) in deps.iter() {
// We may not pass all crates through to the linker. Some crates may
// appear statically in an existing dylib, meaning we'll pick up all the
// symbols from the dylib.
- let src = sess.cstore.used_crate_source(cnum);
+ let src = &trans.crate_info.used_crate_source[&cnum];
match data[cnum.as_usize() - 1] {
_ if trans.crate_info.profiler_runtime == Some(cnum) => {
add_static_crate(cmd, sess, trans, tmpdir, crate_type, cnum);
}
_ if trans.crate_info.sanitizer_runtime == Some(cnum) => {
- link_sanitizer_runtime(cmd, sess, tmpdir, cnum);
+ link_sanitizer_runtime(cmd, sess, trans, tmpdir, cnum);
}
// compiler-builtins are always placed last to ensure that they're
// linked correctly.
add_static_crate(cmd, sess, trans, tmpdir, crate_type, cnum);
}
Linkage::Dynamic => {
- add_dynamic_crate(cmd, sess, &src.dylib.unwrap().0)
+ add_dynamic_crate(cmd, sess, &src.dylib.as_ref().unwrap().0)
}
}
}
// linking it.
fn link_sanitizer_runtime(cmd: &mut Linker,
sess: &Session,
+ trans: &CrateTranslation,
tmpdir: &Path,
cnum: CrateNum) {
- let src = sess.cstore.used_crate_source(cnum);
- let cratepath = &src.rlib.unwrap().0;
+ let src = &trans.crate_info.used_crate_source[&cnum];
+ let cratepath = &src.rlib.as_ref().unwrap().0;
if sess.target.target.options.is_like_osx {
// On Apple platforms, the sanitizer is always built as a dylib, and
tmpdir: &Path,
crate_type: config::CrateType,
cnum: CrateNum) {
- let src = sess.cstore.used_crate_source(cnum);
- let cratepath = &src.rlib.unwrap().0;
+ let src = &trans.crate_info.used_crate_source[&cnum];
+ let cratepath = &src.rlib.as_ref().unwrap().0;
// See the comment above in `link_staticlib` and `link_rlib` for why if
// there's a static library that's not relevant we skip all object
let formats = sess.dependency_formats.borrow();
let data = formats.get(&crate_type).unwrap();
- let crates = sess.cstore.used_crates(LinkagePreference::RequireStatic);
- for (cnum, _) in crates {
+ let crates = &trans.crate_info.used_crates_static;
+ for &(cnum, _) in crates {
for lib in trans.crate_info.native_libraries[&cnum].iter() {
if !relevant_lib(sess, &lib) {
continue
use rustc::middle::cstore::LibSource;
pub struct RPathConfig<'a> {
- pub used_crates: Vec<(CrateNum, LibSource)>,
+ pub used_crates: &'a [(CrateNum, LibSource)],
pub out_filename: PathBuf,
pub is_like_osx: bool,
pub has_rpath: bool,
debug!("preparing the RPATH!");
let libs = config.used_crates.clone();
- let libs = libs.into_iter().filter_map(|(_, l)| l.option()).collect::<Vec<_>>();
+ let libs = libs.iter().filter_map(|&(_, ref l)| l.option()).collect::<Vec<_>>();
let rpaths = get_rpaths(config, &libs);
flags.extend_from_slice(&rpaths_to_flags(&rpaths));
use rustc::middle::cstore::{EncodedMetadata, EncodedMetadataHashes};
use rustc::ty::{self, Ty, TyCtxt};
use rustc::dep_graph::AssertDepGraphSafe;
-use rustc::middle::cstore::LinkMeta;
+use rustc::middle::cstore::{self, LinkMeta, LinkagePreference};
use rustc::hir::map as hir_map;
use rustc::util::common::{time, print_time_passes_entry};
use rustc::session::config::{self, NoDebugInfo, OutputFilenames, OutputType};
}
impl CrateInfo {
- pub fn new(tcx: TyCtxt) -> CrateInfo {
+ pub fn new<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> CrateInfo {
let mut info = CrateInfo {
panic_runtime: None,
compiler_builtins: None,
used_libraries: tcx.native_libraries(LOCAL_CRATE),
link_args: tcx.link_args(LOCAL_CRATE),
crate_name: FxHashMap(),
+ used_crates_dynamic: cstore::used_crates(tcx, LinkagePreference::RequireDynamic),
+ used_crates_static: cstore::used_crates(tcx, LinkagePreference::RequireStatic),
+ used_crate_source: FxHashMap(),
};
for cnum in tcx.sess.cstore.crates() {
info.native_libraries.insert(cnum, tcx.native_libraries(cnum));
info.crate_name.insert(cnum, tcx.crate_name(cnum).to_string());
+ info.used_crate_source.insert(cnum, tcx.used_crate_source(cnum));
if tcx.is_panic_runtime(cnum) {
info.panic_runtime = Some(cnum);
}
use rustc::hir::def_id::CrateNum;
use rustc::util::nodemap::{FxHashSet, FxHashMap};
-use rustc::middle::cstore::NativeLibrary;
+use rustc::middle::cstore::{NativeLibrary, CrateSource, LibSource};
pub mod back {
mod archive;
crate_name: FxHashMap<CrateNum, String>,
used_libraries: Rc<Vec<NativeLibrary>>,
link_args: Rc<Vec<String>>,
+ used_crate_source: FxHashMap<CrateNum, Rc<CrateSource>>,
+ used_crates_static: Vec<(CrateNum, LibSource)>,
+ used_crates_dynamic: Vec<(CrateNum, LibSource)>,
}
__build_diagnostic_array! { librustc_trans, DIAGNOSTICS }