]> git.lizzy.rs Git - rust.git/blob - src/librustc_metadata/cstore.rs
37853b7473a6500d05e3e42b7f346fdf5b574d33
[rust.git] / src / librustc_metadata / cstore.rs
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.
4 //
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.
10
11 // The crate store - a central repo for information collected about external
12 // crates and libraries
13
14 use locator;
15 use schema;
16
17 use rustc::dep_graph::DepGraph;
18 use rustc::hir::def_id::{CRATE_DEF_INDEX, CrateNum, DefIndex, DefId};
19 use rustc::hir::map::DefKey;
20 use rustc::hir::svh::Svh;
21 use rustc::middle::cstore::{DepKind, ExternCrate};
22 use rustc_back::PanicStrategy;
23 use rustc_data_structures::indexed_vec::IndexVec;
24 use rustc::util::nodemap::{FxHashMap, NodeMap, NodeSet, DefIdMap};
25
26 use std::cell::{RefCell, Cell};
27 use std::rc::Rc;
28 use std::path::PathBuf;
29 use flate::Bytes;
30 use syntax::{ast, attr};
31 use syntax::ext::base::SyntaxExtension;
32 use syntax_pos;
33
34 pub use rustc::middle::cstore::{NativeLibrary, LinkagePreference};
35 pub use rustc::middle::cstore::{NativeStatic, NativeFramework, NativeUnknown};
36 pub use rustc::middle::cstore::{CrateSource, LinkMeta};
37
38 // A map from external crate numbers (as decoded from some crate file) to
39 // local crate numbers (as generated during this session). Each external
40 // crate may refer to types in other external crates, and each has their
41 // own crate numbers.
42 pub type CrateNumMap = IndexVec<CrateNum, CrateNum>;
43
44 pub enum MetadataBlob {
45     Inflated(Bytes),
46     Archive(locator::ArchiveMetadata),
47 }
48
49 /// Holds information about a syntax_pos::FileMap imported from another crate.
50 /// See `imported_filemaps()` for more information.
51 pub struct ImportedFileMap {
52     /// This FileMap's byte-offset within the codemap of its original crate
53     pub original_start_pos: syntax_pos::BytePos,
54     /// The end of this FileMap within the codemap of its original crate
55     pub original_end_pos: syntax_pos::BytePos,
56     /// The imported FileMap's representation within the local codemap
57     pub translated_filemap: Rc<syntax_pos::FileMap>,
58 }
59
60 pub struct CrateMetadata {
61     pub name: String,
62
63     /// Information about the extern crate that caused this crate to
64     /// be loaded. If this is `None`, then the crate was injected
65     /// (e.g., by the allocator)
66     pub extern_crate: Cell<Option<ExternCrate>>,
67
68     pub blob: MetadataBlob,
69     pub cnum_map: RefCell<CrateNumMap>,
70     pub cnum: CrateNum,
71     pub codemap_import_info: RefCell<Vec<ImportedFileMap>>,
72
73     pub root: schema::CrateRoot,
74
75     /// For each public item in this crate, we encode a key.  When the
76     /// crate is loaded, we read all the keys and put them in this
77     /// hashmap, which gives the reverse mapping.  This allows us to
78     /// quickly retrace a `DefPath`, which is needed for incremental
79     /// compilation support.
80     pub key_map: FxHashMap<DefKey, DefIndex>,
81
82     pub dep_kind: Cell<DepKind>,
83     pub source: CrateSource,
84
85     pub proc_macros: Option<Vec<(ast::Name, Rc<SyntaxExtension>)>>,
86 }
87
88 pub struct CachedInlinedItem {
89     /// The NodeId of the RootInlinedParent HIR map entry
90     pub inlined_root: ast::NodeId,
91     /// The local NodeId of the inlined entity
92     pub item_id: ast::NodeId,
93 }
94
95 pub struct CStore {
96     pub dep_graph: DepGraph,
97     metas: RefCell<FxHashMap<CrateNum, Rc<CrateMetadata>>>,
98     /// Map from NodeId's of local extern crate statements to crate numbers
99     extern_mod_crate_map: RefCell<NodeMap<CrateNum>>,
100     used_libraries: RefCell<Vec<NativeLibrary>>,
101     used_link_args: RefCell<Vec<String>>,
102     statically_included_foreign_items: RefCell<NodeSet>,
103     pub inlined_item_cache: RefCell<DefIdMap<Option<CachedInlinedItem>>>,
104     pub defid_for_inlined_node: RefCell<NodeMap<DefId>>,
105     pub visible_parent_map: RefCell<DefIdMap<DefId>>,
106 }
107
108 impl CStore {
109     pub fn new(dep_graph: &DepGraph) -> CStore {
110         CStore {
111             dep_graph: dep_graph.clone(),
112             metas: RefCell::new(FxHashMap()),
113             extern_mod_crate_map: RefCell::new(FxHashMap()),
114             used_libraries: RefCell::new(Vec::new()),
115             used_link_args: RefCell::new(Vec::new()),
116             statically_included_foreign_items: RefCell::new(NodeSet()),
117             visible_parent_map: RefCell::new(FxHashMap()),
118             inlined_item_cache: RefCell::new(FxHashMap()),
119             defid_for_inlined_node: RefCell::new(FxHashMap()),
120         }
121     }
122
123     pub fn next_crate_num(&self) -> CrateNum {
124         CrateNum::new(self.metas.borrow().len() + 1)
125     }
126
127     pub fn get_crate_data(&self, cnum: CrateNum) -> Rc<CrateMetadata> {
128         self.metas.borrow().get(&cnum).unwrap().clone()
129     }
130
131     pub fn get_crate_hash(&self, cnum: CrateNum) -> Svh {
132         self.get_crate_data(cnum).hash()
133     }
134
135     pub fn set_crate_data(&self, cnum: CrateNum, data: Rc<CrateMetadata>) {
136         self.metas.borrow_mut().insert(cnum, data);
137     }
138
139     pub fn iter_crate_data<I>(&self, mut i: I)
140         where I: FnMut(CrateNum, &Rc<CrateMetadata>)
141     {
142         for (&k, v) in self.metas.borrow().iter() {
143             i(k, v);
144         }
145     }
146
147     pub fn reset(&self) {
148         self.metas.borrow_mut().clear();
149         self.extern_mod_crate_map.borrow_mut().clear();
150         self.used_libraries.borrow_mut().clear();
151         self.used_link_args.borrow_mut().clear();
152         self.statically_included_foreign_items.borrow_mut().clear();
153     }
154
155     pub fn crate_dependencies_in_rpo(&self, krate: CrateNum) -> Vec<CrateNum> {
156         let mut ordering = Vec::new();
157         self.push_dependencies_in_postorder(&mut ordering, krate);
158         ordering.reverse();
159         ordering
160     }
161
162     pub fn push_dependencies_in_postorder(&self, ordering: &mut Vec<CrateNum>, krate: CrateNum) {
163         if ordering.contains(&krate) {
164             return;
165         }
166
167         let data = self.get_crate_data(krate);
168         for &dep in data.cnum_map.borrow().iter() {
169             if dep != krate {
170                 self.push_dependencies_in_postorder(ordering, dep);
171             }
172         }
173
174         ordering.push(krate);
175     }
176
177     // This method is used when generating the command line to pass through to
178     // system linker. The linker expects undefined symbols on the left of the
179     // command line to be defined in libraries on the right, not the other way
180     // around. For more info, see some comments in the add_used_library function
181     // below.
182     //
183     // In order to get this left-to-right dependency ordering, we perform a
184     // topological sort of all crates putting the leaves at the right-most
185     // positions.
186     pub fn do_get_used_crates(&self,
187                               prefer: LinkagePreference)
188                               -> Vec<(CrateNum, Option<PathBuf>)> {
189         let mut ordering = Vec::new();
190         for (&num, _) in self.metas.borrow().iter() {
191             self.push_dependencies_in_postorder(&mut ordering, num);
192         }
193         info!("topological ordering: {:?}", ordering);
194         ordering.reverse();
195         let mut libs = self.metas
196             .borrow()
197             .iter()
198             .filter_map(|(&cnum, data)| {
199                 if data.dep_kind.get() == DepKind::MacrosOnly { return None; }
200                 let path = match prefer {
201                     LinkagePreference::RequireDynamic => data.source.dylib.clone().map(|p| p.0),
202                     LinkagePreference::RequireStatic => data.source.rlib.clone().map(|p| p.0),
203                 };
204                 Some((cnum, path))
205             })
206             .collect::<Vec<_>>();
207         libs.sort_by(|&(a, _), &(b, _)| {
208             let a = ordering.iter().position(|x| *x == a);
209             let b = ordering.iter().position(|x| *x == b);
210             a.cmp(&b)
211         });
212         libs
213     }
214
215     pub fn add_used_library(&self, lib: NativeLibrary) {
216         assert!(!lib.name.is_empty());
217         self.used_libraries.borrow_mut().push(lib);
218     }
219
220     pub fn get_used_libraries(&self) -> &RefCell<Vec<NativeLibrary>> {
221         &self.used_libraries
222     }
223
224     pub fn add_used_link_args(&self, args: &str) {
225         for s in args.split(' ').filter(|s| !s.is_empty()) {
226             self.used_link_args.borrow_mut().push(s.to_string());
227         }
228     }
229
230     pub fn get_used_link_args<'a>(&'a self) -> &'a RefCell<Vec<String>> {
231         &self.used_link_args
232     }
233
234     pub fn add_extern_mod_stmt_cnum(&self, emod_id: ast::NodeId, cnum: CrateNum) {
235         self.extern_mod_crate_map.borrow_mut().insert(emod_id, cnum);
236     }
237
238     pub fn add_statically_included_foreign_item(&self, id: ast::NodeId) {
239         self.statically_included_foreign_items.borrow_mut().insert(id);
240     }
241
242     pub fn do_is_statically_included_foreign_item(&self, id: ast::NodeId) -> bool {
243         self.statically_included_foreign_items.borrow().contains(&id)
244     }
245
246     pub fn do_extern_mod_stmt_cnum(&self, emod_id: ast::NodeId) -> Option<CrateNum> {
247         self.extern_mod_crate_map.borrow().get(&emod_id).cloned()
248     }
249 }
250
251 impl CrateMetadata {
252     pub fn name(&self) -> &str {
253         &self.root.name
254     }
255     pub fn hash(&self) -> Svh {
256         self.root.hash
257     }
258     pub fn disambiguator(&self) -> &str {
259         &self.root.disambiguator
260     }
261
262     pub fn is_staged_api(&self) -> bool {
263         self.get_item_attrs(CRATE_DEF_INDEX)
264             .iter()
265             .any(|attr| attr.name() == "stable" || attr.name() == "unstable")
266     }
267
268     pub fn is_allocator(&self) -> bool {
269         let attrs = self.get_item_attrs(CRATE_DEF_INDEX);
270         attr::contains_name(&attrs, "allocator")
271     }
272
273     pub fn needs_allocator(&self) -> bool {
274         let attrs = self.get_item_attrs(CRATE_DEF_INDEX);
275         attr::contains_name(&attrs, "needs_allocator")
276     }
277
278     pub fn is_panic_runtime(&self) -> bool {
279         let attrs = self.get_item_attrs(CRATE_DEF_INDEX);
280         attr::contains_name(&attrs, "panic_runtime")
281     }
282
283     pub fn needs_panic_runtime(&self) -> bool {
284         let attrs = self.get_item_attrs(CRATE_DEF_INDEX);
285         attr::contains_name(&attrs, "needs_panic_runtime")
286     }
287
288     pub fn is_compiler_builtins(&self) -> bool {
289         let attrs = self.get_item_attrs(CRATE_DEF_INDEX);
290         attr::contains_name(&attrs, "compiler_builtins")
291     }
292
293     pub fn is_no_builtins(&self) -> bool {
294         let attrs = self.get_item_attrs(CRATE_DEF_INDEX);
295         attr::contains_name(&attrs, "no_builtins")
296     }
297
298     pub fn panic_strategy(&self) -> PanicStrategy {
299         self.root.panic_strategy.clone()
300     }
301 }