]> git.proxmox.com Git - rustc.git/blob - src/librustc_metadata/cstore.rs
New upstream version 1.17.0+dfsg1
[rustc.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
76 pub root: schema::CrateRoot,
77
78 /// For each public item in this crate, we encode a key. When the
79 /// crate is loaded, we read all the keys and put them in this
80 /// hashmap, which gives the reverse mapping. This allows us to
81 /// quickly retrace a `DefPath`, which is needed for incremental
82 /// compilation support.
83 pub def_path_table: DefPathTable,
84
85 pub exported_symbols: FxHashSet<DefIndex>,
86
87 pub dep_kind: Cell<DepKind>,
88 pub source: CrateSource,
89
90 pub proc_macros: Option<Vec<(ast::Name, Rc<SyntaxExtension>)>>,
91 // Foreign items imported from a dylib (Windows only)
92 pub dllimport_foreign_items: FxHashSet<DefIndex>,
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<FxHashSet<DefIndex>>,
103 pub dllimport_foreign_items: RefCell<FxHashSet<DefIndex>>,
104 pub visible_parent_map: RefCell<DefIdMap<DefId>>,
105 }
106
107 impl CStore {
108 pub fn new(dep_graph: &DepGraph) -> CStore {
109 CStore {
110 dep_graph: dep_graph.clone(),
111 metas: RefCell::new(FxHashMap()),
112 extern_mod_crate_map: RefCell::new(FxHashMap()),
113 used_libraries: RefCell::new(Vec::new()),
114 used_link_args: RefCell::new(Vec::new()),
115 statically_included_foreign_items: RefCell::new(FxHashSet()),
116 dllimport_foreign_items: RefCell::new(FxHashSet()),
117 visible_parent_map: RefCell::new(FxHashMap()),
118 }
119 }
120
121 pub fn next_crate_num(&self) -> CrateNum {
122 CrateNum::new(self.metas.borrow().len() + 1)
123 }
124
125 pub fn get_crate_data(&self, cnum: CrateNum) -> Rc<CrateMetadata> {
126 self.metas.borrow().get(&cnum).unwrap().clone()
127 }
128
129 pub fn get_crate_hash(&self, cnum: CrateNum) -> Svh {
130 self.get_crate_data(cnum).hash()
131 }
132
133 pub fn set_crate_data(&self, cnum: CrateNum, data: Rc<CrateMetadata>) {
134 self.metas.borrow_mut().insert(cnum, data);
135 }
136
137 pub fn iter_crate_data<I>(&self, mut i: I)
138 where I: FnMut(CrateNum, &Rc<CrateMetadata>)
139 {
140 for (&k, v) in self.metas.borrow().iter() {
141 i(k, v);
142 }
143 }
144
145 pub fn reset(&self) {
146 self.metas.borrow_mut().clear();
147 self.extern_mod_crate_map.borrow_mut().clear();
148 self.used_libraries.borrow_mut().clear();
149 self.used_link_args.borrow_mut().clear();
150 self.statically_included_foreign_items.borrow_mut().clear();
151 }
152
153 pub fn crate_dependencies_in_rpo(&self, krate: CrateNum) -> Vec<CrateNum> {
154 let mut ordering = Vec::new();
155 self.push_dependencies_in_postorder(&mut ordering, krate);
156 ordering.reverse();
157 ordering
158 }
159
160 pub fn push_dependencies_in_postorder(&self, ordering: &mut Vec<CrateNum>, krate: CrateNum) {
161 if ordering.contains(&krate) {
162 return;
163 }
164
165 let data = self.get_crate_data(krate);
166 for &dep in data.cnum_map.borrow().iter() {
167 if dep != krate {
168 self.push_dependencies_in_postorder(ordering, dep);
169 }
170 }
171
172 ordering.push(krate);
173 }
174
175 // This method is used when generating the command line to pass through to
176 // system linker. The linker expects undefined symbols on the left of the
177 // command line to be defined in libraries on the right, not the other way
178 // around. For more info, see some comments in the add_used_library function
179 // below.
180 //
181 // In order to get this left-to-right dependency ordering, we perform a
182 // topological sort of all crates putting the leaves at the right-most
183 // positions.
184 pub fn do_get_used_crates(&self,
185 prefer: LinkagePreference)
186 -> Vec<(CrateNum, LibSource)> {
187 let mut ordering = Vec::new();
188 for (&num, _) in self.metas.borrow().iter() {
189 self.push_dependencies_in_postorder(&mut ordering, num);
190 }
191 info!("topological ordering: {:?}", ordering);
192 ordering.reverse();
193 let mut libs = self.metas
194 .borrow()
195 .iter()
196 .filter_map(|(&cnum, data)| {
197 if data.dep_kind.get().macros_only() { return None; }
198 let path = match prefer {
199 LinkagePreference::RequireDynamic => data.source.dylib.clone().map(|p| p.0),
200 LinkagePreference::RequireStatic => data.source.rlib.clone().map(|p| p.0),
201 };
202 let path = match path {
203 Some(p) => LibSource::Some(p),
204 None => {
205 if data.source.rmeta.is_some() {
206 LibSource::MetadataOnly
207 } else {
208 LibSource::None
209 }
210 }
211 };
212 Some((cnum, path))
213 })
214 .collect::<Vec<_>>();
215 libs.sort_by(|&(a, _), &(b, _)| {
216 let a = ordering.iter().position(|x| *x == a);
217 let b = ordering.iter().position(|x| *x == b);
218 a.cmp(&b)
219 });
220 libs
221 }
222
223 pub fn add_used_library(&self, lib: NativeLibrary) {
224 assert!(!lib.name.as_str().is_empty());
225 self.used_libraries.borrow_mut().push(lib);
226 }
227
228 pub fn get_used_libraries(&self) -> &RefCell<Vec<NativeLibrary>> {
229 &self.used_libraries
230 }
231
232 pub fn add_used_link_args(&self, args: &str) {
233 for s in args.split(' ').filter(|s| !s.is_empty()) {
234 self.used_link_args.borrow_mut().push(s.to_string());
235 }
236 }
237
238 pub fn get_used_link_args<'a>(&'a self) -> &'a RefCell<Vec<String>> {
239 &self.used_link_args
240 }
241
242 pub fn add_extern_mod_stmt_cnum(&self, emod_id: ast::NodeId, cnum: CrateNum) {
243 self.extern_mod_crate_map.borrow_mut().insert(emod_id, cnum);
244 }
245
246 pub fn add_statically_included_foreign_item(&self, id: DefIndex) {
247 self.statically_included_foreign_items.borrow_mut().insert(id);
248 }
249
250 pub fn do_is_statically_included_foreign_item(&self, def_id: DefId) -> bool {
251 assert!(def_id.krate == LOCAL_CRATE);
252 self.statically_included_foreign_items.borrow().contains(&def_id.index)
253 }
254
255 pub fn do_extern_mod_stmt_cnum(&self, emod_id: ast::NodeId) -> Option<CrateNum> {
256 self.extern_mod_crate_map.borrow().get(&emod_id).cloned()
257 }
258 }
259
260 impl CrateMetadata {
261 pub fn name(&self) -> Symbol {
262 self.root.name
263 }
264 pub fn hash(&self) -> Svh {
265 self.root.hash
266 }
267 pub fn disambiguator(&self) -> Symbol {
268 self.root.disambiguator
269 }
270
271 pub fn is_staged_api(&self) -> bool {
272 self.get_item_attrs(CRATE_DEF_INDEX)
273 .iter()
274 .any(|attr| attr.name() == "stable" || attr.name() == "unstable")
275 }
276
277 pub fn is_allocator(&self) -> bool {
278 let attrs = self.get_item_attrs(CRATE_DEF_INDEX);
279 attr::contains_name(&attrs, "allocator")
280 }
281
282 pub fn needs_allocator(&self) -> bool {
283 let attrs = self.get_item_attrs(CRATE_DEF_INDEX);
284 attr::contains_name(&attrs, "needs_allocator")
285 }
286
287 pub fn is_panic_runtime(&self) -> bool {
288 let attrs = self.get_item_attrs(CRATE_DEF_INDEX);
289 attr::contains_name(&attrs, "panic_runtime")
290 }
291
292 pub fn needs_panic_runtime(&self) -> bool {
293 let attrs = self.get_item_attrs(CRATE_DEF_INDEX);
294 attr::contains_name(&attrs, "needs_panic_runtime")
295 }
296
297 pub fn is_compiler_builtins(&self) -> bool {
298 let attrs = self.get_item_attrs(CRATE_DEF_INDEX);
299 attr::contains_name(&attrs, "compiler_builtins")
300 }
301
302 pub fn is_sanitizer_runtime(&self) -> bool {
303 let attrs = self.get_item_attrs(CRATE_DEF_INDEX);
304 attr::contains_name(&attrs, "sanitizer_runtime")
305 }
306
307 pub fn is_no_builtins(&self) -> bool {
308 let attrs = self.get_item_attrs(CRATE_DEF_INDEX);
309 attr::contains_name(&attrs, "no_builtins")
310 }
311
312 pub fn panic_strategy(&self) -> PanicStrategy {
313 self.root.panic_strategy.clone()
314 }
315 }