]>
Commit | Line | Data |
---|---|---|
1a4d82fc | 1 | // Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT |
223e47cc LB |
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 | ||
223e47cc LB |
11 | // The crate store - a central repo for information collected about external |
12 | // crates and libraries | |
13 | ||
92a42be0 | 14 | use loader; |
9e0c209e | 15 | use schema; |
92a42be0 | 16 | |
a7813a04 | 17 | use rustc::dep_graph::DepGraph; |
9e0c209e | 18 | use rustc::hir::def_id::{CRATE_DEF_INDEX, CrateNum, DefIndex, DefId}; |
a7813a04 | 19 | use rustc::hir::map::DefKey; |
54a0048b | 20 | use rustc::hir::svh::Svh; |
5bcae85e | 21 | use rustc::middle::cstore::ExternCrate; |
a7813a04 | 22 | use rustc::session::config::PanicStrategy; |
3157f602 | 23 | use rustc_data_structures::indexed_vec::IndexVec; |
9e0c209e | 24 | use rustc::util::nodemap::{FnvHashMap, NodeMap, NodeSet, DefIdMap, FnvHashSet}; |
223e47cc | 25 | |
9e0c209e | 26 | use std::cell::{RefCell, Cell}; |
1a4d82fc | 27 | use std::rc::Rc; |
c34b1796 | 28 | use std::path::PathBuf; |
1a4d82fc | 29 | use flate::Bytes; |
9e0c209e | 30 | use syntax::ast::{self, Ident}; |
b039eaaf | 31 | use syntax::attr; |
3157f602 | 32 | use syntax_pos; |
92a42be0 | 33 | |
9e0c209e SL |
34 | pub use rustc::middle::cstore::{NativeLibraryKind, LinkagePreference}; |
35 | pub use rustc::middle::cstore::{NativeStatic, NativeFramework, NativeUnknown}; | |
36 | pub use rustc::middle::cstore::{CrateSource, LinkMeta}; | |
223e47cc LB |
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. | |
9e0c209e | 42 | pub type CrateNumMap = IndexVec<CrateNum, CrateNum>; |
223e47cc | 43 | |
1a4d82fc | 44 | pub enum MetadataBlob { |
9e0c209e SL |
45 | Inflated(Bytes), |
46 | Archive(loader::ArchiveMetadata), | |
223e47cc LB |
47 | } |
48 | ||
3157f602 | 49 | /// Holds information about a syntax_pos::FileMap imported from another crate. |
9e0c209e | 50 | /// See `imported_filemaps()` for more information. |
c34b1796 AL |
51 | pub struct ImportedFileMap { |
52 | /// This FileMap's byte-offset within the codemap of its original crate | |
3157f602 | 53 | pub original_start_pos: syntax_pos::BytePos, |
c34b1796 | 54 | /// The end of this FileMap within the codemap of its original crate |
3157f602 | 55 | pub original_end_pos: syntax_pos::BytePos, |
c34b1796 | 56 | /// The imported FileMap's representation within the local codemap |
3157f602 | 57 | pub translated_filemap: Rc<syntax_pos::FileMap> |
c34b1796 AL |
58 | } |
59 | ||
3157f602 | 60 | pub struct CrateMetadata { |
1a4d82fc | 61 | pub name: String, |
54a0048b SL |
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 | ||
9e0c209e | 68 | pub blob: MetadataBlob, |
3157f602 | 69 | pub cnum_map: RefCell<CrateNumMap>, |
9e0c209e | 70 | pub cnum: CrateNum, |
62682a34 | 71 | pub codemap_import_info: RefCell<Vec<ImportedFileMap>>, |
b039eaaf | 72 | |
9e0c209e | 73 | pub root: schema::CrateRoot, |
e9174d1e | 74 | |
a7813a04 XL |
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: FnvHashMap<DefKey, DefIndex>, | |
81 | ||
e9174d1e SL |
82 | /// Flag if this crate is required by an rlib version of this crate, or in |
83 | /// other words whether it was explicitly linked to. An example of a crate | |
84 | /// where this is false is when an allocator crate is injected into the | |
85 | /// dependency list, and therefore isn't actually needed to link an rlib. | |
86 | pub explicitly_linked: Cell<bool>, | |
223e47cc LB |
87 | } |
88 | ||
5bcae85e SL |
89 | pub struct CachedInlinedItem { |
90 | /// The NodeId of the RootInlinedParent HIR map entry | |
91 | pub inlined_root: ast::NodeId, | |
92 | /// The local NodeId of the inlined entity | |
93 | pub item_id: ast::NodeId, | |
94 | } | |
95 | ||
1a4d82fc | 96 | pub struct CStore { |
a7813a04 | 97 | pub dep_graph: DepGraph, |
9e0c209e | 98 | metas: RefCell<FnvHashMap<CrateNum, Rc<CrateMetadata>>>, |
1a4d82fc | 99 | /// Map from NodeId's of local extern crate statements to crate numbers |
9e0c209e | 100 | extern_mod_crate_map: RefCell<NodeMap<CrateNum>>, |
1a4d82fc JJ |
101 | used_crate_sources: RefCell<Vec<CrateSource>>, |
102 | used_libraries: RefCell<Vec<(String, NativeLibraryKind)>>, | |
103 | used_link_args: RefCell<Vec<String>>, | |
e9174d1e | 104 | statically_included_foreign_items: RefCell<NodeSet>, |
5bcae85e SL |
105 | pub inlined_item_cache: RefCell<DefIdMap<Option<CachedInlinedItem>>>, |
106 | pub defid_for_inlined_node: RefCell<NodeMap<DefId>>, | |
54a0048b | 107 | pub visible_parent_map: RefCell<DefIdMap<DefId>>, |
9e0c209e | 108 | pub used_for_derive_macro: RefCell<FnvHashSet<Ident>>, |
1a4d82fc JJ |
109 | } |
110 | ||
111 | impl CStore { | |
5bcae85e | 112 | pub fn new(dep_graph: &DepGraph) -> CStore { |
1a4d82fc | 113 | CStore { |
a7813a04 | 114 | dep_graph: dep_graph.clone(), |
85aaf69f SL |
115 | metas: RefCell::new(FnvHashMap()), |
116 | extern_mod_crate_map: RefCell::new(FnvHashMap()), | |
1a4d82fc JJ |
117 | used_crate_sources: RefCell::new(Vec::new()), |
118 | used_libraries: RefCell::new(Vec::new()), | |
119 | used_link_args: RefCell::new(Vec::new()), | |
e9174d1e | 120 | statically_included_foreign_items: RefCell::new(NodeSet()), |
54a0048b | 121 | visible_parent_map: RefCell::new(FnvHashMap()), |
5bcae85e SL |
122 | inlined_item_cache: RefCell::new(FnvHashMap()), |
123 | defid_for_inlined_node: RefCell::new(FnvHashMap()), | |
9e0c209e | 124 | used_for_derive_macro: RefCell::new(FnvHashSet()), |
1a4d82fc JJ |
125 | } |
126 | } | |
223e47cc | 127 | |
9e0c209e SL |
128 | pub fn next_crate_num(&self) -> CrateNum { |
129 | CrateNum::new(self.metas.borrow().len() + 1) | |
1a4d82fc | 130 | } |
223e47cc | 131 | |
9e0c209e | 132 | pub fn get_crate_data(&self, cnum: CrateNum) -> Rc<CrateMetadata> { |
c34b1796 | 133 | self.metas.borrow().get(&cnum).unwrap().clone() |
1a4d82fc | 134 | } |
223e47cc | 135 | |
9e0c209e SL |
136 | pub fn get_crate_hash(&self, cnum: CrateNum) -> Svh { |
137 | self.get_crate_data(cnum).hash() | |
223e47cc | 138 | } |
223e47cc | 139 | |
9e0c209e | 140 | pub fn set_crate_data(&self, cnum: CrateNum, data: Rc<CrateMetadata>) { |
1a4d82fc | 141 | self.metas.borrow_mut().insert(cnum, data); |
223e47cc | 142 | } |
223e47cc | 143 | |
1a4d82fc | 144 | pub fn iter_crate_data<I>(&self, mut i: I) where |
9e0c209e | 145 | I: FnMut(CrateNum, &Rc<CrateMetadata>), |
1a4d82fc | 146 | { |
62682a34 | 147 | for (&k, v) in self.metas.borrow().iter() { |
e9174d1e | 148 | i(k, v); |
1a4d82fc JJ |
149 | } |
150 | } | |
223e47cc | 151 | |
1a4d82fc JJ |
152 | /// Like `iter_crate_data`, but passes source paths (if available) as well. |
153 | pub fn iter_crate_data_origins<I>(&self, mut i: I) where | |
9e0c209e | 154 | I: FnMut(CrateNum, &CrateMetadata, Option<CrateSource>), |
1a4d82fc | 155 | { |
62682a34 | 156 | for (&k, v) in self.metas.borrow().iter() { |
92a42be0 | 157 | let origin = self.opt_used_crate_source(k); |
1a4d82fc | 158 | origin.as_ref().map(|cs| { assert!(k == cs.cnum); }); |
7453a54e | 159 | i(k, &v, origin); |
1a4d82fc JJ |
160 | } |
161 | } | |
223e47cc | 162 | |
1a4d82fc JJ |
163 | pub fn add_used_crate_source(&self, src: CrateSource) { |
164 | let mut used_crate_sources = self.used_crate_sources.borrow_mut(); | |
165 | if !used_crate_sources.contains(&src) { | |
166 | used_crate_sources.push(src); | |
167 | } | |
168 | } | |
223e47cc | 169 | |
9e0c209e | 170 | pub fn opt_used_crate_source(&self, cnum: CrateNum) |
92a42be0 | 171 | -> Option<CrateSource> { |
1a4d82fc | 172 | self.used_crate_sources.borrow_mut() |
85aaf69f | 173 | .iter().find(|source| source.cnum == cnum).cloned() |
1a4d82fc | 174 | } |
223e47cc | 175 | |
1a4d82fc JJ |
176 | pub fn reset(&self) { |
177 | self.metas.borrow_mut().clear(); | |
178 | self.extern_mod_crate_map.borrow_mut().clear(); | |
179 | self.used_crate_sources.borrow_mut().clear(); | |
180 | self.used_libraries.borrow_mut().clear(); | |
181 | self.used_link_args.borrow_mut().clear(); | |
e9174d1e | 182 | self.statically_included_foreign_items.borrow_mut().clear(); |
223e47cc | 183 | } |
223e47cc | 184 | |
9e0c209e | 185 | pub fn crate_dependencies_in_rpo(&self, krate: CrateNum) -> Vec<CrateNum> |
3157f602 XL |
186 | { |
187 | let mut ordering = Vec::new(); | |
188 | self.push_dependencies_in_postorder(&mut ordering, krate); | |
189 | ordering.reverse(); | |
190 | ordering | |
191 | } | |
192 | ||
193 | pub fn push_dependencies_in_postorder(&self, | |
9e0c209e SL |
194 | ordering: &mut Vec<CrateNum>, |
195 | krate: CrateNum) | |
3157f602 XL |
196 | { |
197 | if ordering.contains(&krate) { return } | |
198 | ||
199 | let data = self.get_crate_data(krate); | |
200 | for &dep in data.cnum_map.borrow().iter() { | |
201 | if dep != krate { | |
202 | self.push_dependencies_in_postorder(ordering, dep); | |
203 | } | |
204 | } | |
205 | ||
206 | ordering.push(krate); | |
207 | } | |
208 | ||
1a4d82fc JJ |
209 | // This method is used when generating the command line to pass through to |
210 | // system linker. The linker expects undefined symbols on the left of the | |
211 | // command line to be defined in libraries on the right, not the other way | |
212 | // around. For more info, see some comments in the add_used_library function | |
213 | // below. | |
214 | // | |
215 | // In order to get this left-to-right dependency ordering, we perform a | |
216 | // topological sort of all crates putting the leaves at the right-most | |
217 | // positions. | |
92a42be0 | 218 | pub fn do_get_used_crates(&self, prefer: LinkagePreference) |
9e0c209e | 219 | -> Vec<(CrateNum, Option<PathBuf>)> { |
1a4d82fc | 220 | let mut ordering = Vec::new(); |
62682a34 | 221 | for (&num, _) in self.metas.borrow().iter() { |
3157f602 | 222 | self.push_dependencies_in_postorder(&mut ordering, num); |
1a4d82fc | 223 | } |
e9174d1e | 224 | info!("topological ordering: {:?}", ordering); |
1a4d82fc JJ |
225 | ordering.reverse(); |
226 | let mut libs = self.used_crate_sources.borrow() | |
227 | .iter() | |
228 | .map(|src| (src.cnum, match prefer { | |
92a42be0 SL |
229 | LinkagePreference::RequireDynamic => src.dylib.clone().map(|p| p.0), |
230 | LinkagePreference::RequireStatic => src.rlib.clone().map(|p| p.0), | |
1a4d82fc | 231 | })) |
85aaf69f | 232 | .collect::<Vec<_>>(); |
1a4d82fc | 233 | libs.sort_by(|&(a, _), &(b, _)| { |
c1a9b12d SL |
234 | let a = ordering.iter().position(|x| *x == a); |
235 | let b = ordering.iter().position(|x| *x == b); | |
236 | a.cmp(&b) | |
1a4d82fc JJ |
237 | }); |
238 | libs | |
239 | } | |
223e47cc | 240 | |
1a4d82fc JJ |
241 | pub fn add_used_library(&self, lib: String, kind: NativeLibraryKind) { |
242 | assert!(!lib.is_empty()); | |
243 | self.used_libraries.borrow_mut().push((lib, kind)); | |
244 | } | |
223e47cc | 245 | |
1a4d82fc JJ |
246 | pub fn get_used_libraries<'a>(&'a self) |
247 | -> &'a RefCell<Vec<(String, | |
248 | NativeLibraryKind)>> { | |
249 | &self.used_libraries | |
250 | } | |
223e47cc | 251 | |
1a4d82fc JJ |
252 | pub fn add_used_link_args(&self, args: &str) { |
253 | for s in args.split(' ').filter(|s| !s.is_empty()) { | |
254 | self.used_link_args.borrow_mut().push(s.to_string()); | |
255 | } | |
256 | } | |
257 | ||
258 | pub fn get_used_link_args<'a>(&'a self) -> &'a RefCell<Vec<String> > { | |
259 | &self.used_link_args | |
223e47cc LB |
260 | } |
261 | ||
1a4d82fc JJ |
262 | pub fn add_extern_mod_stmt_cnum(&self, |
263 | emod_id: ast::NodeId, | |
9e0c209e | 264 | cnum: CrateNum) { |
1a4d82fc JJ |
265 | self.extern_mod_crate_map.borrow_mut().insert(emod_id, cnum); |
266 | } | |
223e47cc | 267 | |
e9174d1e SL |
268 | pub fn add_statically_included_foreign_item(&self, id: ast::NodeId) { |
269 | self.statically_included_foreign_items.borrow_mut().insert(id); | |
270 | } | |
271 | ||
92a42be0 | 272 | pub fn do_is_statically_included_foreign_item(&self, id: ast::NodeId) -> bool { |
e9174d1e SL |
273 | self.statically_included_foreign_items.borrow().contains(&id) |
274 | } | |
92a42be0 | 275 | |
9e0c209e | 276 | pub fn do_extern_mod_stmt_cnum(&self, emod_id: ast::NodeId) -> Option<CrateNum> |
92a42be0 SL |
277 | { |
278 | self.extern_mod_crate_map.borrow().get(&emod_id).cloned() | |
279 | } | |
9e0c209e SL |
280 | |
281 | pub fn was_used_for_derive_macros(&self, i: &ast::Item) -> bool { | |
282 | self.used_for_derive_macro.borrow().contains(&i.ident) | |
283 | } | |
284 | ||
285 | pub fn add_used_for_derive_macros(&self, i: &ast::Item) { | |
286 | self.used_for_derive_macro.borrow_mut().insert(i.ident); | |
287 | } | |
1a4d82fc | 288 | } |
223e47cc | 289 | |
3157f602 | 290 | impl CrateMetadata { |
9e0c209e SL |
291 | pub fn name(&self) -> &str { &self.root.name } |
292 | pub fn hash(&self) -> Svh { self.root.hash } | |
293 | pub fn disambiguator(&self) -> &str { &self.root.disambiguator } | |
294 | ||
295 | pub fn is_staged_api(&self) -> bool { | |
296 | self.get_item_attrs(CRATE_DEF_INDEX).iter().any(|attr| { | |
297 | attr.name() == "stable" || attr.name() == "unstable" | |
298 | }) | |
e9174d1e SL |
299 | } |
300 | ||
301 | pub fn is_allocator(&self) -> bool { | |
9e0c209e | 302 | let attrs = self.get_item_attrs(CRATE_DEF_INDEX); |
e9174d1e SL |
303 | attr::contains_name(&attrs, "allocator") |
304 | } | |
305 | ||
306 | pub fn needs_allocator(&self) -> bool { | |
9e0c209e | 307 | let attrs = self.get_item_attrs(CRATE_DEF_INDEX); |
e9174d1e SL |
308 | attr::contains_name(&attrs, "needs_allocator") |
309 | } | |
a7813a04 XL |
310 | |
311 | pub fn is_panic_runtime(&self) -> bool { | |
9e0c209e | 312 | let attrs = self.get_item_attrs(CRATE_DEF_INDEX); |
a7813a04 XL |
313 | attr::contains_name(&attrs, "panic_runtime") |
314 | } | |
315 | ||
316 | pub fn needs_panic_runtime(&self) -> bool { | |
9e0c209e | 317 | let attrs = self.get_item_attrs(CRATE_DEF_INDEX); |
a7813a04 XL |
318 | attr::contains_name(&attrs, "needs_panic_runtime") |
319 | } | |
320 | ||
9e0c209e SL |
321 | pub fn is_compiler_builtins(&self) -> bool { |
322 | let attrs = self.get_item_attrs(CRATE_DEF_INDEX); | |
323 | attr::contains_name(&attrs, "compiler_builtins") | |
a7813a04 | 324 | } |
1a4d82fc | 325 | |
9e0c209e SL |
326 | pub fn is_no_builtins(&self) -> bool { |
327 | let attrs = self.get_item_attrs(CRATE_DEF_INDEX); | |
328 | attr::contains_name(&attrs, "no_builtins") | |
a7813a04 XL |
329 | } |
330 | ||
9e0c209e SL |
331 | pub fn panic_strategy(&self) -> PanicStrategy { |
332 | self.root.panic_strategy.clone() | |
1a4d82fc | 333 | } |
223e47cc | 334 | } |