]> git.lizzy.rs Git - rust.git/blob - src/librustc_metadata/cstore.rs
Auto merge of #56642 - nikic:llvm-6, r=alexcrichton
[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;
15 use rustc::hir::def_id::{CrateNum, DefIndex};
16 use rustc::hir::map::definitions::DefPathTable;
17 use rustc::middle::cstore::{DepKind, ExternCrate, MetadataLoader};
18 use rustc::mir::interpret::AllocDecodingState;
19 use rustc_data_structures::indexed_vec::IndexVec;
20 use rustc::util::nodemap::{FxHashMap, NodeMap};
21
22 use rustc_data_structures::sync::{Lrc, RwLock, Lock};
23 use syntax::ast;
24 use syntax::ext::base::SyntaxExtension;
25 use syntax::symbol::Symbol;
26 use syntax_pos;
27
28 pub use rustc::middle::cstore::{NativeLibrary, NativeLibraryKind, LinkagePreference};
29 pub use rustc::middle::cstore::NativeLibraryKind::*;
30 pub use rustc::middle::cstore::{CrateSource, LibSource, ForeignModule};
31
32 pub use cstore_impl::{provide, provide_extern};
33
34 // A map from external crate numbers (as decoded from some crate file) to
35 // local crate numbers (as generated during this session). Each external
36 // crate may refer to types in other external crates, and each has their
37 // own crate numbers.
38 pub type CrateNumMap = IndexVec<CrateNum, CrateNum>;
39
40 pub use rustc_data_structures::sync::MetadataRef;
41
42 pub struct MetadataBlob(pub MetadataRef);
43
44 /// Holds information about a syntax_pos::SourceFile imported from another crate.
45 /// See `imported_source_files()` for more information.
46 pub struct ImportedSourceFile {
47     /// This SourceFile's byte-offset within the source_map of its original crate
48     pub original_start_pos: syntax_pos::BytePos,
49     /// The end of this SourceFile within the source_map of its original crate
50     pub original_end_pos: syntax_pos::BytePos,
51     /// The imported SourceFile's representation within the local source_map
52     pub translated_source_file: Lrc<syntax_pos::SourceFile>,
53 }
54
55 pub struct CrateMetadata {
56     /// Original name of the crate.
57     pub name: Symbol,
58
59     /// Name of the crate as imported.  I.e., if imported with
60     /// `extern crate foo as bar;` this will be `bar`.
61     pub imported_name: Symbol,
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: Lock<Option<ExternCrate>>,
67
68     pub blob: MetadataBlob,
69     pub cnum_map: CrateNumMap,
70     pub cnum: CrateNum,
71     pub dependencies: Lock<Vec<CrateNum>>,
72     pub source_map_import_info: RwLock<Vec<ImportedSourceFile>>,
73
74     /// Used for decoding interpret::AllocIds in a cached & thread-safe manner.
75     pub alloc_decoding_state: AllocDecodingState,
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: Lrc<DefPathTable>,
85
86     pub trait_impls: FxHashMap<(u32, DefIndex), schema::LazySeq<DefIndex>>,
87
88     pub dep_kind: Lock<DepKind>,
89     pub source: CrateSource,
90
91     pub proc_macros: Option<Vec<(ast::Name, Lrc<SyntaxExtension>)>>,
92 }
93
94 pub struct CStore {
95     metas: RwLock<IndexVec<CrateNum, Option<Lrc<CrateMetadata>>>>,
96     /// Map from NodeId's of local extern crate statements to crate numbers
97     extern_mod_crate_map: Lock<NodeMap<CrateNum>>,
98     pub metadata_loader: Box<dyn MetadataLoader + Sync>,
99 }
100
101 pub enum LoadedMacro {
102     MacroDef(ast::Item),
103     ProcMacro(Lrc<SyntaxExtension>),
104 }
105
106 impl CStore {
107     pub fn new(metadata_loader: Box<dyn MetadataLoader + Sync>) -> CStore {
108         CStore {
109             // We add an empty entry for LOCAL_CRATE (which maps to zero) in
110             // order to make array indices in `metas` match with the
111             // corresponding `CrateNum`. This first entry will always remain
112             // `None`.
113             metas: RwLock::new(IndexVec::from_elem_n(None, 1)),
114             extern_mod_crate_map: Default::default(),
115             metadata_loader,
116         }
117     }
118
119     pub(super) fn alloc_new_crate_num(&self) -> CrateNum {
120         let mut metas = self.metas.borrow_mut();
121         let cnum = CrateNum::new(metas.len());
122         metas.push(None);
123         cnum
124     }
125
126     pub(super) fn get_crate_data(&self, cnum: CrateNum) -> Lrc<CrateMetadata> {
127         self.metas.borrow()[cnum].clone().unwrap()
128     }
129
130     pub(super) fn set_crate_data(&self, cnum: CrateNum, data: Lrc<CrateMetadata>) {
131         let mut metas = self.metas.borrow_mut();
132         assert!(metas[cnum].is_none(), "Overwriting crate metadata entry");
133         metas[cnum] = Some(data);
134     }
135
136     pub(super) fn iter_crate_data<I>(&self, mut i: I)
137         where I: FnMut(CrateNum, &Lrc<CrateMetadata>)
138     {
139         for (k, v) in self.metas.borrow().iter_enumerated() {
140             if let &Some(ref v) = v {
141                 i(k, v);
142             }
143         }
144     }
145
146     pub(super) fn crate_dependencies_in_rpo(&self, krate: CrateNum) -> Vec<CrateNum> {
147         let mut ordering = Vec::new();
148         self.push_dependencies_in_postorder(&mut ordering, krate);
149         ordering.reverse();
150         ordering
151     }
152
153     pub(super) fn push_dependencies_in_postorder(&self,
154                                                  ordering: &mut Vec<CrateNum>,
155                                                  krate: CrateNum) {
156         if ordering.contains(&krate) {
157             return;
158         }
159
160         let data = self.get_crate_data(krate);
161         for &dep in data.dependencies.borrow().iter() {
162             if dep != krate {
163                 self.push_dependencies_in_postorder(ordering, dep);
164             }
165         }
166
167         ordering.push(krate);
168     }
169
170     pub(super) fn do_postorder_cnums_untracked(&self) -> Vec<CrateNum> {
171         let mut ordering = Vec::new();
172         for (num, v) in self.metas.borrow().iter_enumerated() {
173             if let &Some(_) = v {
174                 self.push_dependencies_in_postorder(&mut ordering, num);
175             }
176         }
177         return ordering
178     }
179
180     pub(super) fn add_extern_mod_stmt_cnum(&self, emod_id: ast::NodeId, cnum: CrateNum) {
181         self.extern_mod_crate_map.borrow_mut().insert(emod_id, cnum);
182     }
183
184     pub(super) fn do_extern_mod_stmt_cnum(&self, emod_id: ast::NodeId) -> Option<CrateNum> {
185         self.extern_mod_crate_map.borrow().get(&emod_id).cloned()
186     }
187 }