]> git.lizzy.rs Git - rust.git/blob - src/librustc_metadata/creader.rs
rustc_metadata: Merge `cstore.rs` into `creader.rs`
[rust.git] / src / librustc_metadata / creader.rs
1 //! Validates all used crates and extern libraries and loads their metadata
2
3 use crate::locator::{CrateLocator, CratePaths};
4 use crate::rmeta::{CrateMetadata, CrateNumMap, CrateRoot, CrateDep, MetadataBlob};
5
6 use rustc::hir::def_id::CrateNum;
7 use rustc_data_structures::svh::Svh;
8 use rustc_data_structures::sync::Lrc;
9 use rustc_index::vec::IndexVec;
10 use rustc::middle::cstore::DepKind;
11 use rustc::session::{Session, CrateDisambiguator};
12 use rustc::session::config::{Sanitizer, self};
13 use rustc_target::spec::{PanicStrategy, TargetTriple};
14 use rustc::session::search_paths::PathKind;
15 use rustc::middle::cstore::{CrateSource, ExternCrate, ExternCrateSource, MetadataLoaderDyn};
16 use rustc::util::nodemap::FxHashSet;
17 use rustc::hir::map::Definitions;
18 use rustc::hir::def_id::LOCAL_CRATE;
19
20 use std::path::Path;
21 use std::{cmp, fs};
22
23 use syntax::ast;
24 use syntax::attr;
25 use syntax::edition::Edition;
26 use syntax::expand::allocator::{global_allocator_spans, AllocatorKind};
27 use syntax::symbol::{Symbol, sym};
28 use syntax::span_fatal;
29 use syntax_expand::base::SyntaxExtension;
30 use syntax_pos::{Span, DUMMY_SP};
31 use log::{debug, info, log_enabled};
32 use proc_macro::bridge::client::ProcMacro;
33
34 use rustc_error_codes::*;
35
36 #[derive(Clone)]
37 pub struct CStore {
38     metas: IndexVec<CrateNum, Option<Lrc<CrateMetadata>>>,
39     crate injected_panic_runtime: Option<CrateNum>,
40     crate allocator_kind: Option<AllocatorKind>,
41 }
42
43 pub struct CrateLoader<'a> {
44     // Immutable configuration.
45     sess: &'a Session,
46     metadata_loader: &'a MetadataLoaderDyn,
47     local_crate_name: Symbol,
48     // Mutable output.
49     cstore: CStore,
50 }
51
52 pub enum LoadedMacro {
53     MacroDef(ast::Item, Edition),
54     ProcMacro(SyntaxExtension),
55 }
56
57 crate struct Library {
58     pub source: CrateSource,
59     pub metadata: MetadataBlob,
60 }
61
62 enum LoadResult {
63     Previous(CrateNum),
64     Loaded(Library),
65 }
66
67 enum LoadError<'a> {
68     LocatorError(CrateLocator<'a>),
69 }
70
71 impl<'a> LoadError<'a> {
72     fn report(self) -> ! {
73         match self {
74             LoadError::LocatorError(locator) => locator.report_errs(),
75         }
76     }
77 }
78
79 fn dump_crates(cstore: &CStore) {
80     info!("resolved crates:");
81     cstore.iter_crate_data(|cnum, data| {
82         info!("  name: {}", data.name());
83         info!("  cnum: {}", cnum);
84         info!("  hash: {}", data.hash());
85         info!("  reqd: {:?}", data.dep_kind());
86         let CrateSource { dylib, rlib, rmeta } = data.source();
87         dylib.as_ref().map(|dl| info!("  dylib: {}", dl.0.display()));
88         rlib.as_ref().map(|rl|  info!("   rlib: {}", rl.0.display()));
89         rmeta.as_ref().map(|rl| info!("   rmeta: {}", rl.0.display()));
90     });
91 }
92
93 impl CStore {
94     crate fn alloc_new_crate_num(&mut self) -> CrateNum {
95         self.metas.push(None);
96         CrateNum::new(self.metas.len() - 1)
97     }
98
99     crate fn get_crate_data(&self, cnum: CrateNum) -> &CrateMetadata {
100         self.metas[cnum].as_ref()
101             .unwrap_or_else(|| panic!("Failed to get crate data for {:?}", cnum))
102     }
103
104     crate fn set_crate_data(&mut self, cnum: CrateNum, data: CrateMetadata) {
105         assert!(self.metas[cnum].is_none(), "Overwriting crate metadata entry");
106         self.metas[cnum] = Some(Lrc::new(data));
107     }
108
109     crate fn iter_crate_data(&self, mut f: impl FnMut(CrateNum, &CrateMetadata)) {
110         for (cnum, data) in self.metas.iter_enumerated() {
111             if let Some(data) = data {
112                 f(cnum, data);
113             }
114         }
115     }
116
117     fn push_dependencies_in_postorder(&self, deps: &mut Vec<CrateNum>, cnum: CrateNum) {
118         if !deps.contains(&cnum) {
119             let data = self.get_crate_data(cnum);
120             for &dep in data.dependencies().iter() {
121                 if dep != cnum {
122                     self.push_dependencies_in_postorder(deps, dep);
123                 }
124             }
125
126             deps.push(cnum);
127         }
128     }
129
130     crate fn crate_dependencies_in_postorder(&self, cnum: CrateNum) -> Vec<CrateNum> {
131         let mut deps = Vec::new();
132         if cnum == LOCAL_CRATE {
133             self.iter_crate_data(|cnum, _| self.push_dependencies_in_postorder(&mut deps, cnum));
134         } else {
135             self.push_dependencies_in_postorder(&mut deps, cnum);
136         }
137         deps
138     }
139
140     crate fn crate_dependencies_in_reverse_postorder(&self, cnum: CrateNum) -> Vec<CrateNum> {
141         let mut deps = self.crate_dependencies_in_postorder(cnum);
142         deps.reverse();
143         deps
144     }
145 }
146
147 impl<'a> CrateLoader<'a> {
148     pub fn new(
149         sess: &'a Session,
150         metadata_loader: &'a MetadataLoaderDyn,
151         local_crate_name: &str,
152     ) -> Self {
153         CrateLoader {
154             sess,
155             metadata_loader,
156             local_crate_name: Symbol::intern(local_crate_name),
157             cstore: CStore {
158                 // We add an empty entry for LOCAL_CRATE (which maps to zero) in
159                 // order to make array indices in `metas` match with the
160                 // corresponding `CrateNum`. This first entry will always remain
161                 // `None`.
162                 metas: IndexVec::from_elem_n(None, 1),
163                 injected_panic_runtime: None,
164                 allocator_kind: None,
165             }
166         }
167     }
168
169     pub fn cstore(&self) -> &CStore {
170         &self.cstore
171     }
172
173     pub fn into_cstore(self) -> CStore {
174         self.cstore
175     }
176
177     fn existing_match(&self, name: Symbol, hash: Option<&Svh>, kind: PathKind)
178                       -> Option<CrateNum> {
179         let mut ret = None;
180         self.cstore.iter_crate_data(|cnum, data| {
181             if data.name() != name { return }
182
183             match hash {
184                 Some(hash) if *hash == data.hash() => { ret = Some(cnum); return }
185                 Some(..) => return,
186                 None => {}
187             }
188
189             // When the hash is None we're dealing with a top-level dependency
190             // in which case we may have a specification on the command line for
191             // this library. Even though an upstream library may have loaded
192             // something of the same name, we have to make sure it was loaded
193             // from the exact same location as well.
194             //
195             // We're also sure to compare *paths*, not actual byte slices. The
196             // `source` stores paths which are normalized which may be different
197             // from the strings on the command line.
198             let source = self.cstore.get_crate_data(cnum).source();
199             if let Some(entry) = self.sess.opts.externs.get(&name.as_str()) {
200                 // Only use `--extern crate_name=path` here, not `--extern crate_name`.
201                 let found = entry.locations.iter().filter_map(|l| l.as_ref()).any(|l| {
202                     let l = fs::canonicalize(l).ok();
203                     source.dylib.as_ref().map(|p| &p.0) == l.as_ref() ||
204                     source.rlib.as_ref().map(|p| &p.0) == l.as_ref()
205                 });
206                 if found {
207                     ret = Some(cnum);
208                 }
209                 return
210             }
211
212             // Alright, so we've gotten this far which means that `data` has the
213             // right name, we don't have a hash, and we don't have a --extern
214             // pointing for ourselves. We're still not quite yet done because we
215             // have to make sure that this crate was found in the crate lookup
216             // path (this is a top-level dependency) as we don't want to
217             // implicitly load anything inside the dependency lookup path.
218             let prev_kind = source.dylib.as_ref().or(source.rlib.as_ref())
219                                   .or(source.rmeta.as_ref())
220                                   .expect("No sources for crate").1;
221             if kind.matches(prev_kind) {
222                 ret = Some(cnum);
223             }
224         });
225         return ret;
226     }
227
228     fn verify_no_symbol_conflicts(&self,
229                                   span: Span,
230                                   root: &CrateRoot<'_>) {
231         // Check for (potential) conflicts with the local crate
232         if self.local_crate_name == root.name() &&
233            self.sess.local_crate_disambiguator() == root.disambiguator() {
234             span_fatal!(self.sess, span, E0519,
235                         "the current crate is indistinguishable from one of its \
236                          dependencies: it has the same crate-name `{}` and was \
237                          compiled with the same `-C metadata` arguments. This \
238                          will result in symbol conflicts between the two.",
239                         root.name())
240         }
241
242         // Check for conflicts with any crate loaded so far
243         self.cstore.iter_crate_data(|_, other| {
244             if other.name() == root.name() && // same crate-name
245                other.disambiguator() == root.disambiguator() &&  // same crate-disambiguator
246                other.hash() != root.hash() { // but different SVH
247                 span_fatal!(self.sess, span, E0523,
248                         "found two different crates with name `{}` that are \
249                          not distinguished by differing `-C metadata`. This \
250                          will result in symbol conflicts between the two.",
251                         root.name())
252             }
253         });
254     }
255
256     fn register_crate(
257         &mut self,
258         host_lib: Option<Library>,
259         root: Option<&CratePaths>,
260         span: Span,
261         lib: Library,
262         dep_kind: DepKind,
263         name: Symbol
264     ) -> CrateNum {
265         let _prof_timer = self.sess.prof.generic_activity("metadata_register_crate");
266
267         let Library { source, metadata } = lib;
268         let crate_root = metadata.get_root();
269         let host_hash = host_lib.as_ref().map(|lib| lib.metadata.get_root().hash());
270         self.verify_no_symbol_conflicts(span, &crate_root);
271
272         let private_dep = self.sess.opts.externs.get(&name.as_str())
273             .map(|e| e.is_private_dep)
274             .unwrap_or(false);
275
276         info!("register crate `{}` (private_dep = {})", crate_root.name(), private_dep);
277
278         // Claim this crate number and cache it
279         let cnum = self.cstore.alloc_new_crate_num();
280
281         // Maintain a reference to the top most crate.
282         // Stash paths for top-most crate locally if necessary.
283         let crate_paths;
284         let root = if let Some(root) = root {
285             root
286         } else {
287             crate_paths = CratePaths::new(crate_root.name(), source.clone());
288             &crate_paths
289         };
290
291         let cnum_map = self.resolve_crate_deps(root, &crate_root, &metadata, cnum, span, dep_kind);
292
293         let raw_proc_macros = if crate_root.is_proc_macro_crate() {
294             let temp_root;
295             let (dlsym_source, dlsym_root) = match &host_lib {
296                 Some(host_lib) =>
297                     (&host_lib.source, { temp_root = host_lib.metadata.get_root(); &temp_root }),
298                 None => (&source, &crate_root),
299             };
300             let dlsym_dylib = dlsym_source.dylib.as_ref().expect("no dylib for a proc-macro crate");
301             Some(self.dlsym_proc_macros(&dlsym_dylib.0, dlsym_root.disambiguator(), span))
302         } else {
303             None
304         };
305
306         self.cstore.set_crate_data(cnum, CrateMetadata::new(
307             self.sess,
308             metadata,
309             crate_root,
310             raw_proc_macros,
311             cnum,
312             cnum_map,
313             dep_kind,
314             source,
315             private_dep,
316             host_hash,
317         ));
318
319         cnum
320     }
321
322     fn load_proc_macro<'b>(
323         &self,
324         locator: &mut CrateLocator<'b>,
325         path_kind: PathKind,
326     ) -> Option<(LoadResult, Option<Library>)>
327     where
328         'a: 'b,
329     {
330         // Use a new crate locator so trying to load a proc macro doesn't affect the error
331         // message we emit
332         let mut proc_macro_locator = locator.clone();
333
334         // Try to load a proc macro
335         proc_macro_locator.is_proc_macro = Some(true);
336
337         // Load the proc macro crate for the target
338         let (locator, target_result) = if self.sess.opts.debugging_opts.dual_proc_macros {
339             proc_macro_locator.reset();
340             let result = match self.load(&mut proc_macro_locator)? {
341                 LoadResult::Previous(cnum) => return Some((LoadResult::Previous(cnum), None)),
342                 LoadResult::Loaded(library) => Some(LoadResult::Loaded(library))
343             };
344             locator.hash = locator.host_hash;
345             // Use the locator when looking for the host proc macro crate, as that is required
346             // so we want it to affect the error message
347             (locator, result)
348         } else {
349             (&mut proc_macro_locator, None)
350         };
351
352         // Load the proc macro crate for the host
353
354         locator.reset();
355         locator.is_proc_macro = Some(true);
356         locator.target = &self.sess.host;
357         locator.triple = TargetTriple::from_triple(config::host_triple());
358         locator.filesearch = self.sess.host_filesearch(path_kind);
359
360         let host_result = self.load(locator)?;
361
362         Some(if self.sess.opts.debugging_opts.dual_proc_macros {
363             let host_result = match host_result {
364                 LoadResult::Previous(..) => {
365                     panic!("host and target proc macros must be loaded in lock-step")
366                 }
367                 LoadResult::Loaded(library) => library
368             };
369             (target_result.unwrap(), Some(host_result))
370         } else {
371             (host_result, None)
372         })
373     }
374
375     fn resolve_crate<'b>(
376         &'b mut self,
377         name: Symbol,
378         span: Span,
379         dep_kind: DepKind,
380         dep: Option<(&'b CratePaths, &'b CrateDep)>,
381     ) -> CrateNum {
382         self.maybe_resolve_crate(name, span, dep_kind, dep).unwrap_or_else(|err| err.report())
383     }
384
385     fn maybe_resolve_crate<'b>(
386         &'b mut self,
387         name: Symbol,
388         span: Span,
389         mut dep_kind: DepKind,
390         dep: Option<(&'b CratePaths, &'b CrateDep)>,
391     ) -> Result<CrateNum, LoadError<'b>> {
392         info!("resolving crate `{}`", name);
393         let (root, hash, host_hash, extra_filename, path_kind) = match dep {
394             Some((root, dep)) => (
395                 Some(root),
396                 Some(&dep.hash),
397                 dep.host_hash.as_ref(),
398                 Some(&dep.extra_filename[..]),
399                 PathKind::Dependency
400             ),
401             None => (None, None, None, None, PathKind::Crate),
402         };
403         let result = if let Some(cnum) = self.existing_match(name, hash, path_kind) {
404             (LoadResult::Previous(cnum), None)
405         } else {
406             info!("falling back to a load");
407             let mut locator = CrateLocator::new(
408                 self.sess,
409                 self.metadata_loader,
410                 name,
411                 hash,
412                 host_hash,
413                 extra_filename,
414                 false, // is_host
415                 path_kind,
416                 span,
417                 root,
418                 Some(false), // is_proc_macro
419             );
420
421             self.load(&mut locator).map(|r| (r, None)).or_else(|| {
422                 dep_kind = DepKind::UnexportedMacrosOnly;
423                 self.load_proc_macro(&mut locator, path_kind)
424             }).ok_or_else(move || LoadError::LocatorError(locator))?
425         };
426
427         match result {
428             (LoadResult::Previous(cnum), None) => {
429                 let data = self.cstore.get_crate_data(cnum);
430                 if data.is_proc_macro_crate() {
431                     dep_kind = DepKind::UnexportedMacrosOnly;
432                 }
433                 data.update_dep_kind(|data_dep_kind| cmp::max(data_dep_kind, dep_kind));
434                 Ok(cnum)
435             }
436             (LoadResult::Loaded(library), host_library) => {
437                 Ok(self.register_crate(host_library, root, span, library, dep_kind, name))
438             }
439             _ => panic!()
440         }
441     }
442
443     fn load(&self, locator: &mut CrateLocator<'_>) -> Option<LoadResult> {
444         let library = locator.maybe_load_library_crate()?;
445
446         // In the case that we're loading a crate, but not matching
447         // against a hash, we could load a crate which has the same hash
448         // as an already loaded crate. If this is the case prevent
449         // duplicates by just using the first crate.
450         //
451         // Note that we only do this for target triple crates, though, as we
452         // don't want to match a host crate against an equivalent target one
453         // already loaded.
454         let root = library.metadata.get_root();
455         if locator.triple == self.sess.opts.target_triple {
456             let mut result = LoadResult::Loaded(library);
457             self.cstore.iter_crate_data(|cnum, data| {
458                 if data.name() == root.name() && root.hash() == data.hash() {
459                     assert!(locator.hash.is_none());
460                     info!("load success, going to previous cnum: {}", cnum);
461                     result = LoadResult::Previous(cnum);
462                 }
463             });
464             Some(result)
465         } else {
466             Some(LoadResult::Loaded(library))
467         }
468     }
469
470     fn update_extern_crate(&self,
471                            cnum: CrateNum,
472                            mut extern_crate: ExternCrate,
473                            visited: &mut FxHashSet<(CrateNum, bool)>)
474     {
475         if !visited.insert((cnum, extern_crate.is_direct())) { return }
476
477         let cmeta = self.cstore.get_crate_data(cnum);
478         if cmeta.update_extern_crate(extern_crate) {
479             // Propagate the extern crate info to dependencies.
480             extern_crate.dependency_of = cnum;
481             for &dep_cnum in cmeta.dependencies().iter() {
482                 self.update_extern_crate(dep_cnum, extern_crate, visited);
483             }
484         }
485     }
486
487     // Go through the crate metadata and load any crates that it references
488     fn resolve_crate_deps(&mut self,
489                           root: &CratePaths,
490                           crate_root: &CrateRoot<'_>,
491                           metadata: &MetadataBlob,
492                           krate: CrateNum,
493                           span: Span,
494                           dep_kind: DepKind)
495                           -> CrateNumMap {
496         debug!("resolving deps of external crate");
497         if crate_root.is_proc_macro_crate() {
498             return CrateNumMap::new();
499         }
500
501         // The map from crate numbers in the crate we're resolving to local crate numbers.
502         // We map 0 and all other holes in the map to our parent crate. The "additional"
503         // self-dependencies should be harmless.
504         std::iter::once(krate).chain(crate_root.decode_crate_deps(metadata).map(|dep| {
505             info!("resolving dep crate {} hash: `{}` extra filename: `{}`", dep.name, dep.hash,
506                   dep.extra_filename);
507             if dep.kind == DepKind::UnexportedMacrosOnly {
508                 return krate;
509             }
510             let dep_kind = match dep_kind {
511                 DepKind::MacrosOnly => DepKind::MacrosOnly,
512                 _ => dep.kind,
513             };
514             self.resolve_crate(dep.name, span, dep_kind, Some((root, &dep)))
515         })).collect()
516     }
517
518     fn dlsym_proc_macros(&self,
519                          path: &Path,
520                          disambiguator: CrateDisambiguator,
521                          span: Span
522     ) -> &'static [ProcMacro] {
523         use std::env;
524         use crate::dynamic_lib::DynamicLibrary;
525
526         // Make sure the path contains a / or the linker will search for it.
527         let path = env::current_dir().unwrap().join(path);
528         let lib = match DynamicLibrary::open(Some(&path)) {
529             Ok(lib) => lib,
530             Err(err) => self.sess.span_fatal(span, &err),
531         };
532
533         let sym = self.sess.generate_proc_macro_decls_symbol(disambiguator);
534         let decls = unsafe {
535             let sym = match lib.symbol(&sym) {
536                 Ok(f) => f,
537                 Err(err) => self.sess.span_fatal(span, &err),
538             };
539             *(sym as *const &[ProcMacro])
540         };
541
542         // Intentionally leak the dynamic library. We can't ever unload it
543         // since the library can make things that will live arbitrarily long.
544         std::mem::forget(lib);
545
546         decls
547     }
548
549     fn inject_panic_runtime(&mut self, krate: &ast::Crate) {
550         // If we're only compiling an rlib, then there's no need to select a
551         // panic runtime, so we just skip this section entirely.
552         let any_non_rlib = self.sess.crate_types.borrow().iter().any(|ct| {
553             *ct != config::CrateType::Rlib
554         });
555         if !any_non_rlib {
556             info!("panic runtime injection skipped, only generating rlib");
557             self.cstore.injected_panic_runtime = None;
558             return
559         }
560
561         // If we need a panic runtime, we try to find an existing one here. At
562         // the same time we perform some general validation of the DAG we've got
563         // going such as ensuring everything has a compatible panic strategy.
564         //
565         // The logic for finding the panic runtime here is pretty much the same
566         // as the allocator case with the only addition that the panic strategy
567         // compilation mode also comes into play.
568         let desired_strategy = self.sess.panic_strategy();
569         let mut runtime_found = false;
570         let mut needs_panic_runtime = attr::contains_name(&krate.attrs,
571                                                           sym::needs_panic_runtime);
572
573         self.cstore.iter_crate_data(|cnum, data| {
574             needs_panic_runtime = needs_panic_runtime || data.needs_panic_runtime();
575             if data.is_panic_runtime() {
576                 // Inject a dependency from all #![needs_panic_runtime] to this
577                 // #![panic_runtime] crate.
578                 self.inject_dependency_if(cnum, "a panic runtime",
579                                           &|data| data.needs_panic_runtime());
580                 runtime_found = runtime_found || data.dep_kind() == DepKind::Explicit;
581             }
582         });
583
584         // If an explicitly linked and matching panic runtime was found, or if
585         // we just don't need one at all, then we're done here and there's
586         // nothing else to do.
587         if !needs_panic_runtime || runtime_found {
588             self.cstore.injected_panic_runtime = None;
589             return
590         }
591
592         // By this point we know that we (a) need a panic runtime and (b) no
593         // panic runtime was explicitly linked. Here we just load an appropriate
594         // default runtime for our panic strategy and then inject the
595         // dependencies.
596         //
597         // We may resolve to an already loaded crate (as the crate may not have
598         // been explicitly linked prior to this) and we may re-inject
599         // dependencies again, but both of those situations are fine.
600         //
601         // Also note that we have yet to perform validation of the crate graph
602         // in terms of everyone has a compatible panic runtime format, that's
603         // performed later as part of the `dependency_format` module.
604         let name = match desired_strategy {
605             PanicStrategy::Unwind => Symbol::intern("panic_unwind"),
606             PanicStrategy::Abort => Symbol::intern("panic_abort"),
607         };
608         info!("panic runtime not found -- loading {}", name);
609
610         let cnum = self.resolve_crate(name, DUMMY_SP, DepKind::Implicit, None);
611         let data = self.cstore.get_crate_data(cnum);
612
613         // Sanity check the loaded crate to ensure it is indeed a panic runtime
614         // and the panic strategy is indeed what we thought it was.
615         if !data.is_panic_runtime() {
616             self.sess.err(&format!("the crate `{}` is not a panic runtime",
617                                    name));
618         }
619         if data.panic_strategy() != desired_strategy {
620             self.sess.err(&format!("the crate `{}` does not have the panic \
621                                     strategy `{}`",
622                                    name, desired_strategy.desc()));
623         }
624
625         self.cstore.injected_panic_runtime = Some(cnum);
626         self.inject_dependency_if(cnum, "a panic runtime",
627                                   &|data| data.needs_panic_runtime());
628     }
629
630     fn inject_sanitizer_runtime(&mut self) {
631         if let Some(ref sanitizer) = self.sess.opts.debugging_opts.sanitizer {
632             // Sanitizers can only be used on some tested platforms with
633             // executables linked to `std`
634             const ASAN_SUPPORTED_TARGETS: &[&str] = &["x86_64-unknown-linux-gnu",
635                                                       "x86_64-apple-darwin"];
636             const TSAN_SUPPORTED_TARGETS: &[&str] = &["x86_64-unknown-linux-gnu",
637                                                       "x86_64-apple-darwin"];
638             const LSAN_SUPPORTED_TARGETS: &[&str] = &["x86_64-unknown-linux-gnu"];
639             const MSAN_SUPPORTED_TARGETS: &[&str] = &["x86_64-unknown-linux-gnu"];
640
641             let supported_targets = match *sanitizer {
642                 Sanitizer::Address => ASAN_SUPPORTED_TARGETS,
643                 Sanitizer::Thread => TSAN_SUPPORTED_TARGETS,
644                 Sanitizer::Leak => LSAN_SUPPORTED_TARGETS,
645                 Sanitizer::Memory => MSAN_SUPPORTED_TARGETS,
646             };
647             if !supported_targets.contains(&&*self.sess.opts.target_triple.triple()) {
648                 self.sess.err(&format!("{:?}Sanitizer only works with the `{}` target",
649                     sanitizer,
650                     supported_targets.join("` or `")
651                 ));
652                 return
653             }
654
655             // firstyear 2017 - during testing I was unable to access an OSX machine
656             // to make this work on different crate types. As a result, today I have
657             // only been able to test and support linux as a target.
658             if self.sess.opts.target_triple.triple() == "x86_64-unknown-linux-gnu" {
659                 if !self.sess.crate_types.borrow().iter().all(|ct| {
660                     match *ct {
661                         // Link the runtime
662                         config::CrateType::Executable => true,
663                         // This crate will be compiled with the required
664                         // instrumentation pass
665                         config::CrateType::Staticlib |
666                         config::CrateType::Rlib |
667                         config::CrateType::Dylib |
668                         config::CrateType::Cdylib =>
669                             false,
670                         _ => {
671                             self.sess.err(&format!("Only executables, staticlibs, \
672                                 cdylibs, dylibs and rlibs can be compiled with \
673                                 `-Z sanitizer`"));
674                             false
675                         }
676                     }
677                 }) {
678                     return
679                 }
680             } else {
681                 if !self.sess.crate_types.borrow().iter().all(|ct| {
682                     match *ct {
683                         // Link the runtime
684                         config::CrateType::Executable => true,
685                         // This crate will be compiled with the required
686                         // instrumentation pass
687                         config::CrateType::Rlib => false,
688                         _ => {
689                             self.sess.err(&format!("Only executables and rlibs can be \
690                                                     compiled with `-Z sanitizer`"));
691                             false
692                         }
693                     }
694                 }) {
695                     return
696                 }
697             }
698
699             let mut uses_std = false;
700             self.cstore.iter_crate_data(|_, data| {
701                 if data.name() == sym::std {
702                     uses_std = true;
703                 }
704             });
705
706             if uses_std {
707                 let name = Symbol::intern(match sanitizer {
708                     Sanitizer::Address => "rustc_asan",
709                     Sanitizer::Leak => "rustc_lsan",
710                     Sanitizer::Memory => "rustc_msan",
711                     Sanitizer::Thread => "rustc_tsan",
712                 });
713                 info!("loading sanitizer: {}", name);
714
715                 let cnum = self.resolve_crate(name, DUMMY_SP, DepKind::Explicit, None);
716                 let data = self.cstore.get_crate_data(cnum);
717
718                 // Sanity check the loaded crate to ensure it is indeed a sanitizer runtime
719                 if !data.is_sanitizer_runtime() {
720                     self.sess.err(&format!("the crate `{}` is not a sanitizer runtime",
721                                            name));
722                 }
723             } else {
724                 self.sess.err("Must link std to be compiled with `-Z sanitizer`");
725             }
726         }
727     }
728
729     fn inject_profiler_runtime(&mut self) {
730         if self.sess.opts.debugging_opts.profile ||
731            self.sess.opts.cg.profile_generate.enabled()
732         {
733             info!("loading profiler");
734
735             let name = Symbol::intern("profiler_builtins");
736             let cnum = self.resolve_crate(name, DUMMY_SP, DepKind::Implicit, None);
737             let data = self.cstore.get_crate_data(cnum);
738
739             // Sanity check the loaded crate to ensure it is indeed a profiler runtime
740             if !data.is_profiler_runtime() {
741                 self.sess.err(&format!("the crate `profiler_builtins` is not \
742                                         a profiler runtime"));
743             }
744         }
745     }
746
747     fn inject_allocator_crate(&mut self, krate: &ast::Crate) {
748         let has_global_allocator = match &*global_allocator_spans(krate) {
749             [span1, span2, ..] => {
750                 self.sess.struct_span_err(*span2, "cannot define multiple global allocators")
751                     .span_label(*span2, "cannot define a new global allocator")
752                     .span_label(*span1, "previous global allocator is defined here")
753                     .emit();
754                 true
755             }
756             spans => !spans.is_empty()
757         };
758         self.sess.has_global_allocator.set(has_global_allocator);
759
760         // Check to see if we actually need an allocator. This desire comes
761         // about through the `#![needs_allocator]` attribute and is typically
762         // written down in liballoc.
763         let mut needs_allocator = attr::contains_name(&krate.attrs,
764                                                       sym::needs_allocator);
765         self.cstore.iter_crate_data(|_, data| {
766             needs_allocator = needs_allocator || data.needs_allocator();
767         });
768         if !needs_allocator {
769             self.cstore.allocator_kind = None;
770             return
771         }
772
773         // At this point we've determined that we need an allocator. Let's see
774         // if our compilation session actually needs an allocator based on what
775         // we're emitting.
776         let all_rlib = self.sess.crate_types.borrow()
777             .iter()
778             .all(|ct| {
779                 match *ct {
780                     config::CrateType::Rlib => true,
781                     _ => false,
782                 }
783             });
784         if all_rlib {
785             self.cstore.allocator_kind = None;
786             return
787         }
788
789         // Ok, we need an allocator. Not only that but we're actually going to
790         // create an artifact that needs one linked in. Let's go find the one
791         // that we're going to link in.
792         //
793         // First up we check for global allocators. Look at the crate graph here
794         // and see what's a global allocator, including if we ourselves are a
795         // global allocator.
796         let mut global_allocator = if has_global_allocator {
797             Some(None)
798         } else {
799             None
800         };
801         self.cstore.iter_crate_data(|_, data| {
802             if !data.has_global_allocator() {
803                 return
804             }
805             match global_allocator {
806                 Some(Some(other_crate)) => {
807                     self.sess.err(&format!("the `#[global_allocator]` in {} \
808                                             conflicts with this global \
809                                             allocator in: {}",
810                                            other_crate,
811                                            data.name()));
812                 }
813                 Some(None) => {
814                     self.sess.err(&format!("the `#[global_allocator]` in this \
815                                             crate conflicts with global \
816                                             allocator in: {}", data.name()));
817                 }
818                 None => global_allocator = Some(Some(data.name())),
819             }
820         });
821         if global_allocator.is_some() {
822             self.cstore.allocator_kind = Some(AllocatorKind::Global);
823             return
824         }
825
826         // Ok we haven't found a global allocator but we still need an
827         // allocator. At this point our allocator request is typically fulfilled
828         // by the standard library, denoted by the `#![default_lib_allocator]`
829         // attribute.
830         let mut has_default = attr::contains_name(&krate.attrs, sym::default_lib_allocator);
831         self.cstore.iter_crate_data(|_, data| {
832             if data.has_default_lib_allocator() {
833                 has_default = true;
834             }
835         });
836
837         if !has_default {
838             self.sess.err("no global memory allocator found but one is \
839                            required; link to std or \
840                            add `#[global_allocator]` to a static item \
841                            that implements the GlobalAlloc trait.");
842         }
843         self.cstore.allocator_kind = Some(AllocatorKind::DefaultLib);
844     }
845
846     fn inject_dependency_if(&self,
847                             krate: CrateNum,
848                             what: &str,
849                             needs_dep: &dyn Fn(&CrateMetadata) -> bool) {
850         // don't perform this validation if the session has errors, as one of
851         // those errors may indicate a circular dependency which could cause
852         // this to stack overflow.
853         if self.sess.has_errors() {
854             return
855         }
856
857         // Before we inject any dependencies, make sure we don't inject a
858         // circular dependency by validating that this crate doesn't
859         // transitively depend on any crates satisfying `needs_dep`.
860         for dep in self.cstore.crate_dependencies_in_reverse_postorder(krate) {
861             let data = self.cstore.get_crate_data(dep);
862             if needs_dep(&data) {
863                 self.sess.err(&format!("the crate `{}` cannot depend \
864                                         on a crate that needs {}, but \
865                                         it depends on `{}`",
866                                        self.cstore.get_crate_data(krate).name(),
867                                        what,
868                                        data.name()));
869             }
870         }
871
872         // All crates satisfying `needs_dep` do not explicitly depend on the
873         // crate provided for this compile, but in order for this compilation to
874         // be successfully linked we need to inject a dependency (to order the
875         // crates on the command line correctly).
876         self.cstore.iter_crate_data(|cnum, data| {
877             if !needs_dep(data) {
878                 return
879             }
880
881             info!("injecting a dep from {} to {}", cnum, krate);
882             data.add_dependency(krate);
883         });
884     }
885
886     pub fn postprocess(&mut self, krate: &ast::Crate) {
887         self.inject_sanitizer_runtime();
888         self.inject_profiler_runtime();
889         self.inject_allocator_crate(krate);
890         self.inject_panic_runtime(krate);
891
892         if log_enabled!(log::Level::Info) {
893             dump_crates(&self.cstore);
894         }
895     }
896
897     pub fn process_extern_crate(
898         &mut self,
899         item: &ast::Item,
900         definitions: &Definitions,
901     ) -> CrateNum {
902         match item.kind {
903             ast::ItemKind::ExternCrate(orig_name) => {
904                 debug!("resolving extern crate stmt. ident: {} orig_name: {:?}",
905                        item.ident, orig_name);
906                 let name = match orig_name {
907                     Some(orig_name) => {
908                         crate::validate_crate_name(Some(self.sess), &orig_name.as_str(),
909                                             Some(item.span));
910                         orig_name
911                     }
912                     None => item.ident.name,
913                 };
914                 let dep_kind = if attr::contains_name(&item.attrs, sym::no_link) {
915                     DepKind::UnexportedMacrosOnly
916                 } else {
917                     DepKind::Explicit
918                 };
919
920                 let cnum = self.resolve_crate(name, item.span, dep_kind, None);
921
922                 let def_id = definitions.opt_local_def_id(item.id).unwrap();
923                 let path_len = definitions.def_path(def_id.index).data.len();
924                 self.update_extern_crate(
925                     cnum,
926                     ExternCrate {
927                         src: ExternCrateSource::Extern(def_id),
928                         span: item.span,
929                         path_len,
930                         dependency_of: LOCAL_CRATE,
931                     },
932                     &mut FxHashSet::default(),
933                 );
934                 cnum
935             }
936             _ => bug!(),
937         }
938     }
939
940     pub fn process_path_extern(&mut self, name: Symbol, span: Span) -> CrateNum {
941         let cnum = self.resolve_crate(name, span, DepKind::Explicit, None);
942
943         self.update_extern_crate(
944             cnum,
945             ExternCrate {
946                 src: ExternCrateSource::Path,
947                 span,
948                 // to have the least priority in `update_extern_crate`
949                 path_len: usize::max_value(),
950                 dependency_of: LOCAL_CRATE,
951             },
952             &mut FxHashSet::default(),
953         );
954
955         cnum
956     }
957
958     pub fn maybe_process_path_extern(&mut self, name: Symbol, span: Span) -> Option<CrateNum> {
959         let cnum = self.maybe_resolve_crate(name, span, DepKind::Explicit, None).ok()?;
960
961         self.update_extern_crate(
962             cnum,
963             ExternCrate {
964                 src: ExternCrateSource::Path,
965                 span,
966                 // to have the least priority in `update_extern_crate`
967                 path_len: usize::max_value(),
968                 dependency_of: LOCAL_CRATE,
969             },
970             &mut FxHashSet::default(),
971         );
972
973         Some(cnum)
974     }
975 }