]>
Commit | Line | Data |
---|---|---|
3b2f2976 XL |
1 | //! the rustc crate store interface. This also includes types that |
2 | //! are *mostly* used as a part of that interface, but these should | |
3 | //! probably get a better home if someone can find one. | |
92a42be0 | 4 | |
dfeec247 | 5 | use crate::ty::TyCtxt; |
32a655c1 | 6 | |
74b04a01 XL |
7 | use rustc_ast::ast; |
8 | use rustc_ast::expand::allocator::AllocatorKind; | |
dfeec247 XL |
9 | use rustc_data_structures::svh::Svh; |
10 | use rustc_data_structures::sync::{self, MetadataRef}; | |
11 | use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; | |
ba9703b0 | 12 | use rustc_hir::definitions::{DefKey, DefPath, DefPathHash, DefPathTable}; |
dfeec247 | 13 | use rustc_macros::HashStable; |
ba9703b0 | 14 | use rustc_session::search_paths::PathKind; |
f9f354fc | 15 | use rustc_session::utils::NativeLibKind; |
ba9703b0 | 16 | use rustc_session::CrateDisambiguator; |
dfeec247 XL |
17 | use rustc_span::symbol::Symbol; |
18 | use rustc_span::Span; | |
19 | use rustc_target::spec::Target; | |
ba9703b0 | 20 | |
8bb4bdeb | 21 | use std::any::Any; |
7cac9316 | 22 | use std::path::{Path, PathBuf}; |
92a42be0 | 23 | |
92a42be0 SL |
24 | // lonely orphan structs and enums looking for a better home |
25 | ||
3b2f2976 XL |
26 | /// Where a crate came from on the local filesystem. One of these three options |
27 | /// must be non-None. | |
dfeec247 | 28 | #[derive(PartialEq, Clone, Debug, HashStable, RustcEncodable, RustcDecodable)] |
92a42be0 SL |
29 | pub struct CrateSource { |
30 | pub dylib: Option<(PathBuf, PathKind)>, | |
31 | pub rlib: Option<(PathBuf, PathKind)>, | |
476ff2be SL |
32 | pub rmeta: Option<(PathBuf, PathKind)>, |
33 | } | |
34 | ||
e74abb32 XL |
35 | impl CrateSource { |
36 | pub fn paths(&self) -> impl Iterator<Item = &PathBuf> { | |
37 | self.dylib.iter().chain(self.rlib.iter()).chain(self.rmeta.iter()).map(|p| &p.0) | |
38 | } | |
39 | } | |
40 | ||
ba9703b0 XL |
41 | #[derive(RustcEncodable, RustcDecodable, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Debug)] |
42 | #[derive(HashStable)] | |
476ff2be | 43 | pub enum DepKind { |
476ff2be SL |
44 | /// A dependency that is only used for its macros. |
45 | MacrosOnly, | |
46 | /// A dependency that is always injected into the dependency list and so | |
0731742a | 47 | /// doesn't need to be linked to an rlib, e.g., the injected allocator. |
476ff2be SL |
48 | Implicit, |
49 | /// A dependency that is required by an rlib version of this crate. | |
50 | /// Ordinary `extern crate`s result in `Explicit` dependencies. | |
51 | Explicit, | |
52 | } | |
53 | ||
54 | impl DepKind { | |
55 | pub fn macros_only(self) -> bool { | |
56 | match self { | |
74b04a01 | 57 | DepKind::MacrosOnly => true, |
476ff2be SL |
58 | DepKind::Implicit | DepKind::Explicit => false, |
59 | } | |
60 | } | |
61 | } | |
62 | ||
dfeec247 | 63 | #[derive(PartialEq, Clone, Debug, RustcEncodable, RustcDecodable)] |
476ff2be SL |
64 | pub enum LibSource { |
65 | Some(PathBuf), | |
66 | MetadataOnly, | |
67 | None, | |
68 | } | |
69 | ||
70 | impl LibSource { | |
71 | pub fn is_some(&self) -> bool { | |
dfeec247 | 72 | if let LibSource::Some(_) = *self { true } else { false } |
476ff2be SL |
73 | } |
74 | ||
75 | pub fn option(&self) -> Option<PathBuf> { | |
76 | match *self { | |
77 | LibSource::Some(ref p) => Some(p.clone()), | |
78 | LibSource::MetadataOnly | LibSource::None => None, | |
79 | } | |
80 | } | |
92a42be0 SL |
81 | } |
82 | ||
532ac7d7 | 83 | #[derive(Copy, Debug, PartialEq, Clone, RustcEncodable, RustcDecodable, HashStable)] |
92a42be0 SL |
84 | pub enum LinkagePreference { |
85 | RequireDynamic, | |
86 | RequireStatic, | |
87 | } | |
88 | ||
416331ca | 89 | #[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)] |
f9f354fc XL |
90 | pub struct NativeLib { |
91 | pub kind: NativeLibKind, | |
8faf50e0 | 92 | pub name: Option<Symbol>, |
476ff2be | 93 | pub cfg: Option<ast::MetaItem>, |
0531ce1d | 94 | pub foreign_module: Option<DefId>, |
8faf50e0 | 95 | pub wasm_import_module: Option<Symbol>, |
0531ce1d XL |
96 | } |
97 | ||
e74abb32 | 98 | #[derive(Clone, RustcEncodable, RustcDecodable, HashStable)] |
0531ce1d | 99 | pub struct ForeignModule { |
ea8adc8c | 100 | pub foreign_items: Vec<DefId>, |
0531ce1d | 101 | pub def_id: DefId, |
476ff2be SL |
102 | } |
103 | ||
532ac7d7 | 104 | #[derive(Copy, Clone, Debug, HashStable)] |
54a0048b | 105 | pub struct ExternCrate { |
83c7162d | 106 | pub src: ExternCrateSource, |
54a0048b SL |
107 | |
108 | /// span of the extern crate that caused this to be loaded | |
109 | pub span: Span, | |
110 | ||
83c7162d XL |
111 | /// Number of links to reach the extern; |
112 | /// used to select the extern with the shortest path | |
113 | pub path_len: usize, | |
114 | ||
e74abb32 XL |
115 | /// Crate that depends on this crate |
116 | pub dependency_of: CrateNum, | |
117 | } | |
118 | ||
119 | impl ExternCrate { | |
54a0048b SL |
120 | /// If true, then this crate is the crate named by the extern |
121 | /// crate referenced above. If false, then this crate is a dep | |
122 | /// of the crate. | |
e74abb32 XL |
123 | pub fn is_direct(&self) -> bool { |
124 | self.dependency_of == LOCAL_CRATE | |
125 | } | |
60c5eb7d XL |
126 | |
127 | pub fn rank(&self) -> impl PartialOrd { | |
128 | // Prefer: | |
129 | // - direct extern crate to indirect | |
130 | // - shorter paths to longer | |
131 | (self.is_direct(), !self.path_len) | |
132 | } | |
83c7162d | 133 | } |
54a0048b | 134 | |
532ac7d7 | 135 | #[derive(Copy, Clone, Debug, HashStable)] |
83c7162d XL |
136 | pub enum ExternCrateSource { |
137 | /// Crate is loaded by `extern crate`. | |
138 | Extern( | |
139 | /// def_id of the item in the current crate that caused | |
140 | /// this crate to be loaded; note that there could be multiple | |
141 | /// such ids | |
142 | DefId, | |
143 | ), | |
e74abb32 | 144 | /// Crate is implicitly loaded by a path resolving through extern prelude. |
83c7162d | 145 | Path, |
54a0048b SL |
146 | } |
147 | ||
dfeec247 | 148 | #[derive(RustcEncodable, RustcDecodable)] |
cc61c64b | 149 | pub struct EncodedMetadata { |
dfeec247 | 150 | pub raw_data: Vec<u8>, |
7cac9316 XL |
151 | } |
152 | ||
153 | impl EncodedMetadata { | |
154 | pub fn new() -> EncodedMetadata { | |
dfeec247 | 155 | EncodedMetadata { raw_data: Vec::new() } |
7cac9316 | 156 | } |
cc61c64b XL |
157 | } |
158 | ||
7cac9316 XL |
159 | /// The backend's way to give the crate store access to the metadata in a library. |
160 | /// Note that it returns the raw metadata bytes stored in the library file, whether | |
161 | /// it is compressed, uncompressed, some weird mix, etc. | |
162 | /// rmeta files are backend independent and not handled here. | |
163 | /// | |
164 | /// At the time of this writing, there is only one backend and one way to store | |
165 | /// metadata in library -- this trait just serves to decouple rustc_metadata from | |
166 | /// the archive reader, which depends on LLVM. | |
167 | pub trait MetadataLoader { | |
dfeec247 XL |
168 | fn get_rlib_metadata(&self, target: &Target, filename: &Path) -> Result<MetadataRef, String>; |
169 | fn get_dylib_metadata(&self, target: &Target, filename: &Path) -> Result<MetadataRef, String>; | |
7cac9316 XL |
170 | } |
171 | ||
e74abb32 XL |
172 | pub type MetadataLoaderDyn = dyn MetadataLoader + Sync; |
173 | ||
e1599b0c | 174 | /// A store of Rust crates, through which their metadata can be accessed. |
ea8adc8c XL |
175 | /// |
176 | /// Note that this trait should probably not be expanding today. All new | |
177 | /// functionality should be driven through queries instead! | |
178 | /// | |
179 | /// If you find a method on this trait named `{name}_untracked` it signifies | |
180 | /// that it's *not* tracked for dependency information throughout compilation | |
181 | /// (it'd break incremental compilation) and should only be called pre-HIR (e.g. | |
182 | /// during resolve) | |
8bb4bdeb | 183 | pub trait CrateStore { |
60c5eb7d | 184 | fn as_any(&self) -> &dyn Any; |
8bb4bdeb | 185 | |
92a42be0 | 186 | // resolve |
32a655c1 | 187 | fn def_key(&self, def: DefId) -> DefKey; |
ba9703b0 XL |
188 | fn def_path(&self, def: DefId) -> DefPath; |
189 | fn def_path_hash(&self, def: DefId) -> DefPathHash; | |
e74abb32 | 190 | fn def_path_table(&self, cnum: CrateNum) -> &DefPathTable; |
92a42be0 | 191 | |
ea8adc8c | 192 | // "queries" used in resolve that aren't tracked for incremental compilation |
ea8adc8c | 193 | fn crate_name_untracked(&self, cnum: CrateNum) -> Symbol; |
48663c56 | 194 | fn crate_is_private_dep_untracked(&self, cnum: CrateNum) -> bool; |
abe05a73 | 195 | fn crate_disambiguator_untracked(&self, cnum: CrateNum) -> CrateDisambiguator; |
ea8adc8c | 196 | fn crate_hash_untracked(&self, cnum: CrateNum) -> Svh; |
7453a54e | 197 | |
92a42be0 SL |
198 | // This is basically a 1-based range of ints, which is a little |
199 | // silly - I may fix that. | |
ea8adc8c | 200 | fn crates_untracked(&self) -> Vec<CrateNum>; |
92a42be0 SL |
201 | |
202 | // utility functions | |
416331ca | 203 | fn encode_metadata(&self, tcx: TyCtxt<'_>) -> EncodedMetadata; |
92a42be0 | 204 | fn metadata_encoding_version(&self) -> &[u8]; |
60c5eb7d | 205 | fn allocator_kind(&self) -> Option<AllocatorKind>; |
92a42be0 SL |
206 | } |
207 | ||
8faf50e0 | 208 | pub type CrateStoreDyn = dyn CrateStore + sync::Sync; |
94b46f34 | 209 | |
ea8adc8c XL |
210 | // This method is used when generating the command line to pass through to |
211 | // system linker. The linker expects undefined symbols on the left of the | |
212 | // command line to be defined in libraries on the right, not the other way | |
213 | // around. For more info, see some comments in the add_used_library function | |
214 | // below. | |
215 | // | |
216 | // In order to get this left-to-right dependency ordering, we perform a | |
217 | // topological sort of all crates putting the leaves at the right-most | |
218 | // positions. | |
dc9dc135 | 219 | pub fn used_crates(tcx: TyCtxt<'_>, prefer: LinkagePreference) -> Vec<(CrateNum, LibSource)> { |
dfeec247 XL |
220 | let mut libs = tcx |
221 | .crates() | |
ea8adc8c XL |
222 | .iter() |
223 | .cloned() | |
224 | .filter_map(|cnum| { | |
225 | if tcx.dep_kind(cnum).macros_only() { | |
dfeec247 | 226 | return None; |
ea8adc8c XL |
227 | } |
228 | let source = tcx.used_crate_source(cnum); | |
229 | let path = match prefer { | |
230 | LinkagePreference::RequireDynamic => source.dylib.clone().map(|p| p.0), | |
231 | LinkagePreference::RequireStatic => source.rlib.clone().map(|p| p.0), | |
232 | }; | |
233 | let path = match path { | |
234 | Some(p) => LibSource::Some(p), | |
235 | None => { | |
236 | if source.rmeta.is_some() { | |
237 | LibSource::MetadataOnly | |
238 | } else { | |
239 | LibSource::None | |
240 | } | |
241 | } | |
242 | }; | |
243 | Some((cnum, path)) | |
244 | }) | |
245 | .collect::<Vec<_>>(); | |
dc9dc135 XL |
246 | let mut ordering = tcx.postorder_cnums(LOCAL_CRATE).to_owned(); |
247 | ordering.reverse(); | |
dfeec247 | 248 | libs.sort_by_cached_key(|&(a, _)| ordering.iter().position(|x| *x == a)); |
ea8adc8c XL |
249 | libs |
250 | } |