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