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