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.
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.
11 // The crate store - a central repo for information collected about external
12 // crates and libraries
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}
;
26 use std
::cell
::{RefCell, Cell}
;
29 use syntax
::{ast, attr}
;
30 use syntax
::ext
::base
::SyntaxExtension
;
31 use syntax
::symbol
::Symbol
;
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}
;
38 pub use cstore_impl
::provide
;
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
44 pub type CrateNumMap
= IndexVec
<CrateNum
, CrateNum
>;
46 pub enum MetadataBlob
{
48 Archive(locator
::ArchiveMetadata
),
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
>,
63 pub struct CrateMetadata
{
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
>>,
71 pub blob
: MetadataBlob
,
72 pub cnum_map
: RefCell
<CrateNumMap
>,
74 pub codemap_import_info
: RefCell
<Vec
<ImportedFileMap
>>,
76 pub root
: schema
::CrateRoot
,
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
,
85 pub exported_symbols
: FxHashSet
<DefIndex
>,
87 pub dep_kind
: Cell
<DepKind
>,
88 pub source
: CrateSource
,
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
>,
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
>>,
108 pub fn new(dep_graph
: &DepGraph
) -> 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()),
121 pub fn next_crate_num(&self) -> CrateNum
{
122 CrateNum
::new(self.metas
.borrow().len() + 1)
125 pub fn get_crate_data(&self, cnum
: CrateNum
) -> Rc
<CrateMetadata
> {
126 self.metas
.borrow().get(&cnum
).unwrap().clone()
129 pub fn get_crate_hash(&self, cnum
: CrateNum
) -> Svh
{
130 self.get_crate_data(cnum
).hash()
133 pub fn set_crate_data(&self, cnum
: CrateNum
, data
: Rc
<CrateMetadata
>) {
134 self.metas
.borrow_mut().insert(cnum
, data
);
137 pub fn iter_crate_data
<I
>(&self, mut i
: I
)
138 where I
: FnMut(CrateNum
, &Rc
<CrateMetadata
>)
140 for (&k
, v
) in self.metas
.borrow().iter() {
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();
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
);
160 pub fn push_dependencies_in_postorder(&self, ordering
: &mut Vec
<CrateNum
>, krate
: CrateNum
) {
161 if ordering
.contains(&krate
) {
165 let data
= self.get_crate_data(krate
);
166 for &dep
in data
.cnum_map
.borrow().iter() {
168 self.push_dependencies_in_postorder(ordering
, dep
);
172 ordering
.push(krate
);
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
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
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
);
191 info
!("topological ordering: {:?}", ordering
);
193 let mut libs
= self.metas
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),
202 let path
= match path
{
203 Some(p
) => LibSource
::Some(p
),
205 if data
.source
.rmeta
.is_some() {
206 LibSource
::MetadataOnly
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
);
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
);
228 pub fn get_used_libraries(&self) -> &RefCell
<Vec
<NativeLibrary
>> {
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());
238 pub fn get_used_link_args
<'a
>(&'a
self) -> &'a RefCell
<Vec
<String
>> {
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
);
246 pub fn add_statically_included_foreign_item(&self, id
: DefIndex
) {
247 self.statically_included_foreign_items
.borrow_mut().insert(id
);
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
)
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()
261 pub fn name(&self) -> Symbol
{
264 pub fn hash(&self) -> Svh
{
267 pub fn disambiguator(&self) -> Symbol
{
268 self.root
.disambiguator
271 pub fn is_staged_api(&self) -> bool
{
272 self.get_item_attrs(CRATE_DEF_INDEX
)
274 .any(|attr
| attr
.name() == "stable" || attr
.name() == "unstable")
277 pub fn is_allocator(&self) -> bool
{
278 let attrs
= self.get_item_attrs(CRATE_DEF_INDEX
);
279 attr
::contains_name(&attrs
, "allocator")
282 pub fn needs_allocator(&self) -> bool
{
283 let attrs
= self.get_item_attrs(CRATE_DEF_INDEX
);
284 attr
::contains_name(&attrs
, "needs_allocator")
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")
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")
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")
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")
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")
312 pub fn panic_strategy(&self) -> PanicStrategy
{
313 self.root
.panic_strategy
.clone()