1 // Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 // The crate store - a central repo for information collected about external
12 // crates and libraries
14 use schema::{self, Tracked};
16 use rustc::dep_graph::{DepGraph, DepNode, GlobalMetaDataKind};
17 use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, CrateNum, DefIndex, DefId};
18 use rustc::hir::map::definitions::DefPathTable;
19 use rustc::hir::svh::Svh;
20 use rustc::middle::cstore::{DepKind, ExternCrate, MetadataLoader};
21 use rustc_back::PanicStrategy;
22 use rustc_data_structures::indexed_vec::IndexVec;
23 use rustc::util::nodemap::{FxHashMap, FxHashSet, NodeMap, DefIdMap};
25 use std::cell::{RefCell, Cell};
27 use owning_ref::ErasedBoxRef;
28 use syntax::{ast, attr};
29 use syntax::ext::base::SyntaxExtension;
30 use syntax::symbol::Symbol;
33 pub use rustc::middle::cstore::{NativeLibrary, NativeLibraryKind, LinkagePreference};
34 pub use rustc::middle::cstore::NativeLibraryKind::*;
35 pub use rustc::middle::cstore::{CrateSource, LinkMeta, LibSource};
37 pub use cstore_impl::provide;
39 // A map from external crate numbers (as decoded from some crate file) to
40 // local crate numbers (as generated during this session). Each external
41 // crate may refer to types in other external crates, and each has their
43 pub type CrateNumMap = IndexVec<CrateNum, CrateNum>;
45 pub struct MetadataBlob(pub ErasedBoxRef<[u8]>);
47 /// Holds information about a syntax_pos::FileMap imported from another crate.
48 /// See `imported_filemaps()` for more information.
49 pub struct ImportedFileMap {
50 /// This FileMap's byte-offset within the codemap of its original crate
51 pub original_start_pos: syntax_pos::BytePos,
52 /// The end of this FileMap within the codemap of its original crate
53 pub original_end_pos: syntax_pos::BytePos,
54 /// The imported FileMap's representation within the local codemap
55 pub translated_filemap: Rc<syntax_pos::FileMap>,
58 pub struct CrateMetadata {
61 /// Information about the extern crate that caused this crate to
62 /// be loaded. If this is `None`, then the crate was injected
63 /// (e.g., by the allocator)
64 pub extern_crate: Cell<Option<ExternCrate>>,
66 pub blob: MetadataBlob,
67 pub cnum_map: RefCell<CrateNumMap>,
69 pub codemap_import_info: RefCell<Vec<ImportedFileMap>>,
70 pub attribute_cache: RefCell<[Vec<Option<Rc<[ast::Attribute]>>>; 2]>,
72 pub root: schema::CrateRoot,
74 /// For each public item in this crate, we encode a key. When the
75 /// crate is loaded, we read all the keys and put them in this
76 /// hashmap, which gives the reverse mapping. This allows us to
77 /// quickly retrace a `DefPath`, which is needed for incremental
78 /// compilation support.
79 pub def_path_table: DefPathTable,
81 pub exported_symbols: Tracked<FxHashSet<DefIndex>>,
83 pub dep_kind: Cell<DepKind>,
84 pub source: CrateSource,
86 pub proc_macros: Option<Vec<(ast::Name, Rc<SyntaxExtension>)>>,
87 // Foreign items imported from a dylib (Windows only)
88 pub dllimport_foreign_items: Tracked<FxHashSet<DefIndex>>,
92 pub dep_graph: DepGraph,
93 metas: RefCell<FxHashMap<CrateNum, Rc<CrateMetadata>>>,
94 /// Map from NodeId's of local extern crate statements to crate numbers
95 extern_mod_crate_map: RefCell<NodeMap<CrateNum>>,
96 used_libraries: RefCell<Vec<NativeLibrary>>,
97 used_link_args: RefCell<Vec<String>>,
98 statically_included_foreign_items: RefCell<FxHashSet<DefIndex>>,
99 pub dllimport_foreign_items: RefCell<FxHashSet<DefIndex>>,
100 pub visible_parent_map: RefCell<DefIdMap<DefId>>,
101 pub metadata_loader: Box<MetadataLoader>,
105 pub fn new(dep_graph: &DepGraph, metadata_loader: Box<MetadataLoader>) -> CStore {
107 dep_graph: dep_graph.clone(),
108 metas: RefCell::new(FxHashMap()),
109 extern_mod_crate_map: RefCell::new(FxHashMap()),
110 used_libraries: RefCell::new(Vec::new()),
111 used_link_args: RefCell::new(Vec::new()),
112 statically_included_foreign_items: RefCell::new(FxHashSet()),
113 dllimport_foreign_items: RefCell::new(FxHashSet()),
114 visible_parent_map: RefCell::new(FxHashMap()),
115 metadata_loader: metadata_loader,
119 pub fn next_crate_num(&self) -> CrateNum {
120 CrateNum::new(self.metas.borrow().len() + 1)
123 pub fn get_crate_data(&self, cnum: CrateNum) -> Rc<CrateMetadata> {
124 self.metas.borrow().get(&cnum).unwrap().clone()
127 pub fn get_crate_hash(&self, cnum: CrateNum) -> Svh {
128 self.get_crate_data(cnum).hash()
131 pub fn set_crate_data(&self, cnum: CrateNum, data: Rc<CrateMetadata>) {
132 self.metas.borrow_mut().insert(cnum, data);
135 pub fn iter_crate_data<I>(&self, mut i: I)
136 where I: FnMut(CrateNum, &Rc<CrateMetadata>)
138 for (&k, v) in self.metas.borrow().iter() {
143 pub fn reset(&self) {
144 self.metas.borrow_mut().clear();
145 self.extern_mod_crate_map.borrow_mut().clear();
146 self.used_libraries.borrow_mut().clear();
147 self.used_link_args.borrow_mut().clear();
148 self.statically_included_foreign_items.borrow_mut().clear();
151 pub fn crate_dependencies_in_rpo(&self, krate: CrateNum) -> Vec<CrateNum> {
152 let mut ordering = Vec::new();
153 self.push_dependencies_in_postorder(&mut ordering, krate);
158 pub fn push_dependencies_in_postorder(&self, ordering: &mut Vec<CrateNum>, krate: CrateNum) {
159 if ordering.contains(&krate) {
163 let data = self.get_crate_data(krate);
164 for &dep in data.cnum_map.borrow().iter() {
166 self.push_dependencies_in_postorder(ordering, dep);
170 ordering.push(krate);
173 // This method is used when generating the command line to pass through to
174 // system linker. The linker expects undefined symbols on the left of the
175 // command line to be defined in libraries on the right, not the other way
176 // around. For more info, see some comments in the add_used_library function
179 // In order to get this left-to-right dependency ordering, we perform a
180 // topological sort of all crates putting the leaves at the right-most
182 pub fn do_get_used_crates(&self,
183 prefer: LinkagePreference)
184 -> Vec<(CrateNum, LibSource)> {
185 let mut ordering = Vec::new();
186 for (&num, _) in self.metas.borrow().iter() {
187 self.push_dependencies_in_postorder(&mut ordering, num);
189 info!("topological ordering: {:?}", ordering);
191 let mut libs = self.metas
194 .filter_map(|(&cnum, data)| {
195 if data.dep_kind.get().macros_only() { return None; }
196 let path = match prefer {
197 LinkagePreference::RequireDynamic => data.source.dylib.clone().map(|p| p.0),
198 LinkagePreference::RequireStatic => data.source.rlib.clone().map(|p| p.0),
200 let path = match path {
201 Some(p) => LibSource::Some(p),
203 if data.source.rmeta.is_some() {
204 LibSource::MetadataOnly
212 .collect::<Vec<_>>();
213 libs.sort_by(|&(a, _), &(b, _)| {
214 let a = ordering.iter().position(|x| *x == a);
215 let b = ordering.iter().position(|x| *x == b);
221 pub fn add_used_library(&self, lib: NativeLibrary) {
222 assert!(!lib.name.as_str().is_empty());
223 self.used_libraries.borrow_mut().push(lib);
226 pub fn get_used_libraries(&self) -> &RefCell<Vec<NativeLibrary>> {
230 pub fn add_used_link_args(&self, args: &str) {
231 for s in args.split(' ').filter(|s| !s.is_empty()) {
232 self.used_link_args.borrow_mut().push(s.to_string());
236 pub fn get_used_link_args<'a>(&'a self) -> &'a RefCell<Vec<String>> {
240 pub fn add_extern_mod_stmt_cnum(&self, emod_id: ast::NodeId, cnum: CrateNum) {
241 self.extern_mod_crate_map.borrow_mut().insert(emod_id, cnum);
244 pub fn add_statically_included_foreign_item(&self, id: DefIndex) {
245 self.statically_included_foreign_items.borrow_mut().insert(id);
248 pub fn do_is_statically_included_foreign_item(&self, def_id: DefId) -> bool {
249 assert!(def_id.krate == LOCAL_CRATE);
250 self.statically_included_foreign_items.borrow().contains(&def_id.index)
253 pub fn do_extern_mod_stmt_cnum(&self, emod_id: ast::NodeId) -> Option<CrateNum> {
254 self.extern_mod_crate_map.borrow().get(&emod_id).cloned()
259 pub fn name(&self) -> Symbol {
262 pub fn hash(&self) -> Svh {
265 pub fn disambiguator(&self) -> Symbol {
266 self.root.disambiguator
269 pub fn is_allocator(&self, dep_graph: &DepGraph) -> bool {
270 let attrs = self.get_item_attrs(CRATE_DEF_INDEX, dep_graph);
271 attr::contains_name(&attrs, "allocator")
274 pub fn needs_allocator(&self, dep_graph: &DepGraph) -> bool {
275 let attrs = self.get_item_attrs(CRATE_DEF_INDEX, dep_graph);
276 attr::contains_name(&attrs, "needs_allocator")
279 pub fn is_panic_runtime(&self, dep_graph: &DepGraph) -> bool {
280 let attrs = self.get_item_attrs(CRATE_DEF_INDEX, dep_graph);
281 attr::contains_name(&attrs, "panic_runtime")
284 pub fn needs_panic_runtime(&self, dep_graph: &DepGraph) -> bool {
285 let attrs = self.get_item_attrs(CRATE_DEF_INDEX, dep_graph);
286 attr::contains_name(&attrs, "needs_panic_runtime")
289 pub fn is_compiler_builtins(&self, dep_graph: &DepGraph) -> bool {
290 let attrs = self.get_item_attrs(CRATE_DEF_INDEX, dep_graph);
291 attr::contains_name(&attrs, "compiler_builtins")
294 pub fn is_sanitizer_runtime(&self, dep_graph: &DepGraph) -> bool {
295 let attrs = self.get_item_attrs(CRATE_DEF_INDEX, dep_graph);
296 attr::contains_name(&attrs, "sanitizer_runtime")
299 pub fn is_no_builtins(&self, dep_graph: &DepGraph) -> bool {
300 let attrs = self.get_item_attrs(CRATE_DEF_INDEX, dep_graph);
301 attr::contains_name(&attrs, "no_builtins")
304 pub fn panic_strategy(&self, dep_graph: &DepGraph) -> PanicStrategy {
307 index: CRATE_DEF_INDEX,
309 let dep_node = DepNode::GlobalMetaData(def_id, GlobalMetaDataKind::Krate);
313 .get(dep_graph, dep_node)