]> git.lizzy.rs Git - rust.git/blob - src/librustc_metadata/cstore.rs
543d257018d0aaf0b03dd3735d9c2a728daba439
[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 schema::{self, Tracked};
15
16 use rustc::dep_graph::DepGraph;
17 use rustc::hir::def_id::{CRATE_DEF_INDEX, CrateNum, DefIndex, DefId};
18 use rustc::hir::map::definitions::{DefPathTable, GlobalMetaDataKind};
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};
24
25 use std::cell::{RefCell, Cell};
26 use std::rc::Rc;
27 use owning_ref::ErasedBoxRef;
28 use syntax::{ast, attr};
29 use syntax::ext::base::SyntaxExtension;
30 use syntax::symbol::Symbol;
31 use syntax_pos;
32
33 pub use rustc::middle::cstore::{NativeLibrary, NativeLibraryKind, LinkagePreference};
34 pub use rustc::middle::cstore::NativeLibraryKind::*;
35 pub use rustc::middle::cstore::{CrateSource, LibSource};
36
37 pub use cstore_impl::{provide, provide_local};
38
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
42 // own crate numbers.
43 pub type CrateNumMap = IndexVec<CrateNum, CrateNum>;
44
45 pub struct MetadataBlob(pub ErasedBoxRef<[u8]>);
46
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>,
56 }
57
58 pub struct CrateMetadata {
59     pub name: Symbol,
60
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>>,
65
66     pub blob: MetadataBlob,
67     pub cnum_map: RefCell<CrateNumMap>,
68     pub cnum: CrateNum,
69     pub codemap_import_info: RefCell<Vec<ImportedFileMap>>,
70     pub attribute_cache: RefCell<[Vec<Option<Rc<[ast::Attribute]>>>; 2]>,
71
72     pub root: schema::CrateRoot,
73
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: Rc<DefPathTable>,
80
81     pub exported_symbols: Tracked<FxHashSet<DefIndex>>,
82
83     pub trait_impls: Tracked<FxHashMap<(u32, DefIndex), schema::LazySeq<DefIndex>>>,
84
85     pub dep_kind: Cell<DepKind>,
86     pub source: CrateSource,
87
88     pub proc_macros: Option<Vec<(ast::Name, Rc<SyntaxExtension>)>>,
89     // Foreign items imported from a dylib (Windows only)
90     pub dllimport_foreign_items: Tracked<FxHashSet<DefIndex>>,
91 }
92
93 pub struct CStore {
94     pub dep_graph: DepGraph,
95     metas: RefCell<FxHashMap<CrateNum, Rc<CrateMetadata>>>,
96     /// Map from NodeId's of local extern crate statements to crate numbers
97     extern_mod_crate_map: RefCell<NodeMap<CrateNum>>,
98     pub visible_parent_map: RefCell<DefIdMap<DefId>>,
99     pub metadata_loader: Box<MetadataLoader>,
100 }
101
102 impl CStore {
103     pub fn new(dep_graph: &DepGraph, metadata_loader: Box<MetadataLoader>) -> CStore {
104         CStore {
105             dep_graph: dep_graph.clone(),
106             metas: RefCell::new(FxHashMap()),
107             extern_mod_crate_map: RefCell::new(FxHashMap()),
108             visible_parent_map: RefCell::new(FxHashMap()),
109             metadata_loader,
110         }
111     }
112
113     pub fn next_crate_num(&self) -> CrateNum {
114         CrateNum::new(self.metas.borrow().len() + 1)
115     }
116
117     pub fn get_crate_data(&self, cnum: CrateNum) -> Rc<CrateMetadata> {
118         self.metas.borrow().get(&cnum).unwrap().clone()
119     }
120
121     pub fn set_crate_data(&self, cnum: CrateNum, data: Rc<CrateMetadata>) {
122         self.metas.borrow_mut().insert(cnum, data);
123     }
124
125     pub fn iter_crate_data<I>(&self, mut i: I)
126         where I: FnMut(CrateNum, &Rc<CrateMetadata>)
127     {
128         for (&k, v) in self.metas.borrow().iter() {
129             i(k, v);
130         }
131     }
132
133     pub fn crate_dependencies_in_rpo(&self, krate: CrateNum) -> Vec<CrateNum> {
134         let mut ordering = Vec::new();
135         self.push_dependencies_in_postorder(&mut ordering, krate);
136         ordering.reverse();
137         ordering
138     }
139
140     pub fn push_dependencies_in_postorder(&self, ordering: &mut Vec<CrateNum>, krate: CrateNum) {
141         if ordering.contains(&krate) {
142             return;
143         }
144
145         let data = self.get_crate_data(krate);
146         for &dep in data.cnum_map.borrow().iter() {
147             if dep != krate {
148                 self.push_dependencies_in_postorder(ordering, dep);
149             }
150         }
151
152         ordering.push(krate);
153     }
154
155     // This method is used when generating the command line to pass through to
156     // system linker. The linker expects undefined symbols on the left of the
157     // command line to be defined in libraries on the right, not the other way
158     // around. For more info, see some comments in the add_used_library function
159     // below.
160     //
161     // In order to get this left-to-right dependency ordering, we perform a
162     // topological sort of all crates putting the leaves at the right-most
163     // positions.
164     pub fn do_get_used_crates(&self,
165                               prefer: LinkagePreference)
166                               -> Vec<(CrateNum, LibSource)> {
167         let mut ordering = Vec::new();
168         for (&num, _) in self.metas.borrow().iter() {
169             self.push_dependencies_in_postorder(&mut ordering, num);
170         }
171         info!("topological ordering: {:?}", ordering);
172         ordering.reverse();
173         let mut libs = self.metas
174             .borrow()
175             .iter()
176             .filter_map(|(&cnum, data)| {
177                 if data.dep_kind.get().macros_only() { return None; }
178                 let path = match prefer {
179                     LinkagePreference::RequireDynamic => data.source.dylib.clone().map(|p| p.0),
180                     LinkagePreference::RequireStatic => data.source.rlib.clone().map(|p| p.0),
181                 };
182                 let path = match path {
183                     Some(p) => LibSource::Some(p),
184                     None => {
185                         if data.source.rmeta.is_some() {
186                             LibSource::MetadataOnly
187                         } else {
188                             LibSource::None
189                         }
190                     }
191                 };
192                 Some((cnum, path))
193             })
194             .collect::<Vec<_>>();
195         libs.sort_by(|&(a, _), &(b, _)| {
196             let a = ordering.iter().position(|x| *x == a);
197             let b = ordering.iter().position(|x| *x == b);
198             a.cmp(&b)
199         });
200         libs
201     }
202
203     pub fn add_extern_mod_stmt_cnum(&self, emod_id: ast::NodeId, cnum: CrateNum) {
204         self.extern_mod_crate_map.borrow_mut().insert(emod_id, cnum);
205     }
206
207     pub fn do_extern_mod_stmt_cnum(&self, emod_id: ast::NodeId) -> Option<CrateNum> {
208         self.extern_mod_crate_map.borrow().get(&emod_id).cloned()
209     }
210
211     pub fn read_dep_node(&self, def_id: DefId) {
212         use rustc::middle::cstore::CrateStore;
213         let def_path_hash = self.def_path_hash(def_id);
214         let dep_node = def_path_hash.to_dep_node(::rustc::dep_graph::DepKind::MetaData);
215         self.dep_graph.read(dep_node);
216     }
217 }
218
219 impl CrateMetadata {
220     pub fn name(&self) -> Symbol {
221         self.root.name
222     }
223     pub fn hash(&self) -> Svh {
224         self.root.hash
225     }
226     pub fn disambiguator(&self) -> Symbol {
227         self.root.disambiguator
228     }
229
230     pub fn needs_allocator(&self, dep_graph: &DepGraph) -> bool {
231         let attrs = self.get_item_attrs(CRATE_DEF_INDEX, dep_graph);
232         attr::contains_name(&attrs, "needs_allocator")
233     }
234
235     pub fn has_global_allocator(&self, dep_graph: &DepGraph) -> bool {
236         let dep_node = self.metadata_dep_node(GlobalMetaDataKind::Krate);
237         self.root
238             .has_global_allocator
239             .get(dep_graph, dep_node)
240             .clone()
241     }
242
243     pub fn has_default_lib_allocator(&self, dep_graph: &DepGraph) -> bool {
244         let dep_node = self.metadata_dep_node(GlobalMetaDataKind::Krate);
245         self.root
246             .has_default_lib_allocator
247             .get(dep_graph, dep_node)
248             .clone()
249     }
250
251     pub fn is_panic_runtime(&self, dep_graph: &DepGraph) -> bool {
252         let attrs = self.get_item_attrs(CRATE_DEF_INDEX, dep_graph);
253         attr::contains_name(&attrs, "panic_runtime")
254     }
255
256     pub fn needs_panic_runtime(&self, dep_graph: &DepGraph) -> bool {
257         let attrs = self.get_item_attrs(CRATE_DEF_INDEX, dep_graph);
258         attr::contains_name(&attrs, "needs_panic_runtime")
259     }
260
261     pub fn is_compiler_builtins(&self, dep_graph: &DepGraph) -> bool {
262         let attrs = self.get_item_attrs(CRATE_DEF_INDEX, dep_graph);
263         attr::contains_name(&attrs, "compiler_builtins")
264     }
265
266     pub fn is_sanitizer_runtime(&self, dep_graph: &DepGraph) -> bool {
267         let attrs = self.get_item_attrs(CRATE_DEF_INDEX, dep_graph);
268         attr::contains_name(&attrs, "sanitizer_runtime")
269     }
270
271     pub fn is_profiler_runtime(&self, dep_graph: &DepGraph) -> bool {
272         let attrs = self.get_item_attrs(CRATE_DEF_INDEX, dep_graph);
273         attr::contains_name(&attrs, "profiler_runtime")
274     }
275
276     pub fn is_no_builtins(&self, dep_graph: &DepGraph) -> bool {
277         let attrs = self.get_item_attrs(CRATE_DEF_INDEX, dep_graph);
278         attr::contains_name(&attrs, "no_builtins")
279     }
280
281     pub fn panic_strategy(&self, dep_graph: &DepGraph) -> PanicStrategy {
282         let dep_node = self.metadata_dep_node(GlobalMetaDataKind::Krate);
283         self.root
284             .panic_strategy
285             .get(dep_graph, dep_node)
286             .clone()
287     }
288 }