]> git.proxmox.com Git - rustc.git/blame - src/librustc_metadata/cstore.rs
New upstream version 1.13.0+dfsg1
[rustc.git] / src / librustc_metadata / cstore.rs
CommitLineData
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 14use loader;
9e0c209e 15use schema;
92a42be0 16
a7813a04 17use rustc::dep_graph::DepGraph;
9e0c209e 18use rustc::hir::def_id::{CRATE_DEF_INDEX, CrateNum, DefIndex, DefId};
a7813a04 19use rustc::hir::map::DefKey;
54a0048b 20use rustc::hir::svh::Svh;
5bcae85e 21use rustc::middle::cstore::ExternCrate;
a7813a04 22use rustc::session::config::PanicStrategy;
3157f602 23use rustc_data_structures::indexed_vec::IndexVec;
9e0c209e 24use rustc::util::nodemap::{FnvHashMap, NodeMap, NodeSet, DefIdMap, FnvHashSet};
223e47cc 25
9e0c209e 26use std::cell::{RefCell, Cell};
1a4d82fc 27use std::rc::Rc;
c34b1796 28use std::path::PathBuf;
1a4d82fc 29use flate::Bytes;
9e0c209e 30use syntax::ast::{self, Ident};
b039eaaf 31use syntax::attr;
3157f602 32use syntax_pos;
92a42be0 33
9e0c209e
SL
34pub use rustc::middle::cstore::{NativeLibraryKind, LinkagePreference};
35pub use rustc::middle::cstore::{NativeStatic, NativeFramework, NativeUnknown};
36pub 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 42pub type CrateNumMap = IndexVec<CrateNum, CrateNum>;
223e47cc 43
1a4d82fc 44pub 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
51pub 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 60pub 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
89pub 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 96pub 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
111impl 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 290impl 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}