]> git.proxmox.com Git - rustc.git/blame - src/librustc_metadata/creader.rs
New upstream version 1.13.0+dfsg1
[rustc.git] / src / librustc_metadata / creader.rs
CommitLineData
85aaf69f 1// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
223e47cc
LB
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
1a4d82fc 11//! Validates all used crates and extern libraries and loads their metadata
223e47cc 12
92a42be0 13use cstore::{self, CStore, CrateSource, MetadataBlob};
92a42be0 14use loader::{self, CratePaths};
9e0c209e
SL
15use macro_import;
16use schema::CrateRoot;
92a42be0 17
9e0c209e 18use rustc::hir::def_id::{CrateNum, DefIndex};
54a0048b 19use rustc::hir::svh::Svh;
9e0c209e 20use rustc::middle::cstore::LoadedMacro;
92a42be0 21use rustc::session::{config, Session};
a7813a04 22use rustc::session::config::PanicStrategy;
92a42be0 23use rustc::session::search_paths::PathKind;
9e0c209e 24use rustc::middle;
54a0048b 25use rustc::middle::cstore::{CrateStore, validate_crate_name, ExternCrate};
3157f602 26use rustc::util::nodemap::{FnvHashMap, FnvHashSet};
54a0048b 27use rustc::hir::map as hir_map;
223e47cc 28
e9174d1e 29use std::cell::{RefCell, Cell};
9e0c209e 30use std::ops::Deref;
d9579d0f 31use std::path::PathBuf;
1a4d82fc 32use std::rc::Rc;
d9579d0f
AL
33use std::fs;
34
1a4d82fc 35use syntax::ast;
7453a54e 36use syntax::abi::Abi;
1a4d82fc 37use syntax::parse;
e9174d1e 38use syntax::attr;
1a4d82fc 39use syntax::parse::token::InternedString;
9e0c209e 40use syntax_pos::{self, Span, mk_sp};
1a4d82fc 41use log;
223e47cc 42
9e0c209e
SL
43pub struct CrateLoader<'a> {
44 pub sess: &'a Session,
45 pub creader: CrateReader<'a>,
92a42be0 46 cstore: &'a CStore,
e9174d1e
SL
47}
48
1a4d82fc
JJ
49pub struct CrateReader<'a> {
50 sess: &'a Session,
92a42be0 51 cstore: &'a CStore,
9e0c209e 52 next_crate_num: CrateNum,
e9174d1e 53 foreign_item_map: FnvHashMap<String, Vec<ast::NodeId>>,
54a0048b 54 local_crate_name: String,
5bcae85e 55 local_crate_config: ast::CrateConfig,
223e47cc
LB
56}
57
1a4d82fc 58fn dump_crates(cstore: &CStore) {
e9174d1e 59 info!("resolved crates:");
1a4d82fc 60 cstore.iter_crate_data_origins(|_, data, opt_source| {
e9174d1e
SL
61 info!(" name: {}", data.name());
62 info!(" cnum: {}", data.cnum);
63 info!(" hash: {}", data.hash());
64 info!(" reqd: {}", data.explicitly_linked.get());
1a4d82fc
JJ
65 opt_source.map(|cs| {
66 let CrateSource { dylib, rlib, cnum: _ } = cs;
e9174d1e
SL
67 dylib.map(|dl| info!(" dylib: {}", dl.0.display()));
68 rlib.map(|rl| info!(" rlib: {}", rl.0.display()));
1a4d82fc
JJ
69 });
70 })
223e47cc
LB
71}
72
85aaf69f 73fn should_link(i: &ast::Item) -> bool {
c34b1796 74 !attr::contains_name(&i.attrs, "no_link")
1a4d82fc 75}
e9174d1e 76
a7813a04 77#[derive(Debug)]
9e0c209e 78struct ExternCrateInfo {
1a4d82fc
JJ
79 ident: String,
80 name: String,
81 id: ast::NodeId,
82 should_link: bool,
83}
223e47cc 84
1a4d82fc 85fn register_native_lib(sess: &Session,
92a42be0 86 cstore: &CStore,
1a4d82fc
JJ
87 span: Option<Span>,
88 name: String,
89 kind: cstore::NativeLibraryKind) {
90 if name.is_empty() {
91 match span {
92 Some(span) => {
9e0c209e
SL
93 struct_span_err!(sess, span, E0454,
94 "#[link(name = \"\")] given with empty name")
95 .span_label(span, &format!("empty name given"))
96 .emit();
970d7e83 97 }
1a4d82fc
JJ
98 None => {
99 sess.err("empty library name given via `-l`");
223e47cc
LB
100 }
101 }
1a4d82fc 102 return
223e47cc 103 }
1a4d82fc
JJ
104 let is_osx = sess.target.target.options.is_like_osx;
105 if kind == cstore::NativeFramework && !is_osx {
106 let msg = "native frameworks are only available on OSX targets";
107 match span {
b039eaaf
SL
108 Some(span) => {
109 span_err!(sess, span, E0455,
110 "{}", msg)
111 }
1a4d82fc
JJ
112 None => sess.err(msg),
113 }
114 }
92a42be0 115 cstore.add_used_library(name, kind);
223e47cc
LB
116}
117
85aaf69f
SL
118// Extra info about a crate loaded for plugins or exported macros.
119struct ExtensionCrate {
1a4d82fc 120 metadata: PMDSource,
c34b1796 121 dylib: Option<PathBuf>,
1a4d82fc 122 target_only: bool,
9e0c209e
SL
123
124 ident: String,
125 name: String,
126 span: Span,
127 should_link: bool,
223e47cc
LB
128}
129
1a4d82fc 130enum PMDSource {
3157f602 131 Registered(Rc<cstore::CrateMetadata>),
9e0c209e 132 Owned(loader::Library),
1a4d82fc 133}
223e47cc 134
9e0c209e
SL
135impl Deref for PMDSource {
136 type Target = MetadataBlob;
137
138 fn deref(&self) -> &MetadataBlob {
1a4d82fc 139 match *self {
9e0c209e
SL
140 PMDSource::Registered(ref cmd) => &cmd.blob,
141 PMDSource::Owned(ref lib) => &lib.metadata
223e47cc
LB
142 }
143 }
144}
145
a7813a04 146enum LoadResult {
9e0c209e 147 Previous(CrateNum),
a7813a04
XL
148 Loaded(loader::Library),
149}
150
9e0c209e
SL
151pub struct Macros {
152 pub macro_rules: Vec<ast::MacroDef>,
153
154 /// An array of pairs where the first element is the name of the custom
155 /// derive (e.g. the trait being derived) and the second element is the
156 /// index of the definition.
157 pub custom_derive_registrar: Option<DefIndex>,
158 pub svh: Svh,
159 pub dylib: Option<PathBuf>,
160}
161
1a4d82fc 162impl<'a> CrateReader<'a> {
54a0048b
SL
163 pub fn new(sess: &'a Session,
164 cstore: &'a CStore,
5bcae85e
SL
165 local_crate_name: &str,
166 local_crate_config: ast::CrateConfig)
167 -> CrateReader<'a> {
1a4d82fc
JJ
168 CrateReader {
169 sess: sess,
92a42be0
SL
170 cstore: cstore,
171 next_crate_num: cstore.next_crate_num(),
e9174d1e 172 foreign_item_map: FnvHashMap(),
54a0048b 173 local_crate_name: local_crate_name.to_owned(),
5bcae85e 174 local_crate_config: local_crate_config,
223e47cc 175 }
223e47cc 176 }
223e47cc 177
9e0c209e 178 fn extract_crate_info(&self, i: &ast::Item) -> Option<ExternCrateInfo> {
1a4d82fc 179 match i.node {
7453a54e 180 ast::ItemKind::ExternCrate(ref path_opt) => {
1a4d82fc 181 debug!("resolving extern crate stmt. ident: {} path_opt: {:?}",
c1a9b12d 182 i.ident, path_opt);
1a4d82fc 183 let name = match *path_opt {
c34b1796 184 Some(name) => {
c1a9b12d 185 validate_crate_name(Some(self.sess), &name.as_str(),
1a4d82fc 186 Some(i.span));
c1a9b12d 187 name.to_string()
1a4d82fc 188 }
c1a9b12d 189 None => i.ident.to_string(),
1a4d82fc 190 };
9e0c209e 191 Some(ExternCrateInfo {
c1a9b12d 192 ident: i.ident.to_string(),
1a4d82fc 193 name: name,
85aaf69f 194 id: i.id,
1a4d82fc
JJ
195 should_link: should_link(i),
196 })
197 }
198 _ => None
199 }
200 }
223e47cc 201
85aaf69f 202 fn existing_match(&self, name: &str, hash: Option<&Svh>, kind: PathKind)
9e0c209e 203 -> Option<CrateNum> {
1a4d82fc 204 let mut ret = None;
92a42be0 205 self.cstore.iter_crate_data(|cnum, data| {
1a4d82fc 206 if data.name != name { return }
223e47cc 207
1a4d82fc
JJ
208 match hash {
209 Some(hash) if *hash == data.hash() => { ret = Some(cnum); return }
210 Some(..) => return,
211 None => {}
212 }
223e47cc 213
85aaf69f
SL
214 // When the hash is None we're dealing with a top-level dependency
215 // in which case we may have a specification on the command line for
216 // this library. Even though an upstream library may have loaded
217 // something of the same name, we have to make sure it was loaded
218 // from the exact same location as well.
1a4d82fc
JJ
219 //
220 // We're also sure to compare *paths*, not actual byte slices. The
221 // `source` stores paths which are normalized which may be different
222 // from the strings on the command line.
92a42be0 223 let source = self.cstore.used_crate_source(cnum);
85aaf69f
SL
224 if let Some(locs) = self.sess.opts.externs.get(name) {
225 let found = locs.iter().any(|l| {
d9579d0f 226 let l = fs::canonicalize(l).ok();
85aaf69f
SL
227 source.dylib.as_ref().map(|p| &p.0) == l.as_ref() ||
228 source.rlib.as_ref().map(|p| &p.0) == l.as_ref()
229 });
230 if found {
231 ret = Some(cnum);
1a4d82fc 232 }
85aaf69f
SL
233 return
234 }
235
236 // Alright, so we've gotten this far which means that `data` has the
237 // right name, we don't have a hash, and we don't have a --extern
238 // pointing for ourselves. We're still not quite yet done because we
239 // have to make sure that this crate was found in the crate lookup
240 // path (this is a top-level dependency) as we don't want to
241 // implicitly load anything inside the dependency lookup path.
242 let prev_kind = source.dylib.as_ref().or(source.rlib.as_ref())
243 .unwrap().1;
244 if ret.is_none() && (prev_kind == kind || prev_kind == PathKind::All) {
245 ret = Some(cnum);
1a4d82fc
JJ
246 }
247 });
248 return ret;
249 }
223e47cc 250
54a0048b
SL
251 fn verify_no_symbol_conflicts(&self,
252 span: Span,
9e0c209e 253 root: &CrateRoot) {
54a0048b 254 // Check for (potential) conflicts with the local crate
9e0c209e
SL
255 if self.local_crate_name == root.name &&
256 self.sess.local_crate_disambiguator() == &root.disambiguator[..] {
54a0048b
SL
257 span_fatal!(self.sess, span, E0519,
258 "the current crate is indistinguishable from one of its \
259 dependencies: it has the same crate-name `{}` and was \
260 compiled with the same `-C metadata` arguments. This \
261 will result in symbol conflicts between the two.",
9e0c209e 262 root.name)
54a0048b
SL
263 }
264
54a0048b
SL
265 // Check for conflicts with any crate loaded so far
266 self.cstore.iter_crate_data(|_, other| {
9e0c209e
SL
267 if other.name() == root.name && // same crate-name
268 other.disambiguator() == root.disambiguator && // same crate-disambiguator
269 other.hash() != root.hash { // but different SVH
54a0048b
SL
270 span_fatal!(self.sess, span, E0523,
271 "found two different crates with name `{}` that are \
272 not distinguished by differing `-C metadata`. This \
273 will result in symbol conflicts between the two.",
9e0c209e 274 root.name)
54a0048b
SL
275 }
276 });
277 }
278
1a4d82fc
JJ
279 fn register_crate(&mut self,
280 root: &Option<CratePaths>,
281 ident: &str,
282 name: &str,
283 span: Span,
e9174d1e
SL
284 lib: loader::Library,
285 explicitly_linked: bool)
9e0c209e 286 -> (CrateNum, Rc<cstore::CrateMetadata>,
1a4d82fc 287 cstore::CrateSource) {
9e0c209e
SL
288 info!("register crate `extern crate {} as {}`", name, ident);
289 let crate_root = lib.metadata.get_root();
290 self.verify_no_symbol_conflicts(span, &crate_root);
b039eaaf 291
223e47cc 292 // Claim this crate number and cache it
1a4d82fc 293 let cnum = self.next_crate_num;
9e0c209e 294 self.next_crate_num = CrateNum::from_u32(cnum.as_u32() + 1);
1a4d82fc
JJ
295
296 // Stash paths for top-most crate locally if necessary.
297 let crate_paths = if root.is_none() {
298 Some(CratePaths {
299 ident: ident.to_string(),
85aaf69f
SL
300 dylib: lib.dylib.clone().map(|p| p.0),
301 rlib: lib.rlib.clone().map(|p| p.0),
1a4d82fc
JJ
302 })
303 } else {
304 None
305 };
306 // Maintain a reference to the top most crate.
307 let root = if root.is_some() { root } else { &crate_paths };
308
c34b1796 309 let loader::Library { dylib, rlib, metadata } = lib;
1a4d82fc 310
9e0c209e
SL
311 let cnum_map = self.resolve_crate_deps(root, &crate_root, &metadata, cnum, span);
312
313 if crate_root.macro_derive_registrar.is_some() {
314 self.sess.span_err(span, "crates of the `rustc-macro` crate type \
315 cannot be linked at runtime");
316 }
1a4d82fc 317
3157f602 318 let cmeta = Rc::new(cstore::CrateMetadata {
1a4d82fc 319 name: name.to_string(),
54a0048b 320 extern_crate: Cell::new(None),
9e0c209e
SL
321 key_map: metadata.load_key_map(crate_root.index),
322 root: crate_root,
323 blob: metadata,
e9174d1e 324 cnum_map: RefCell::new(cnum_map),
223e47cc 325 cnum: cnum,
62682a34 326 codemap_import_info: RefCell::new(vec![]),
e9174d1e 327 explicitly_linked: Cell::new(explicitly_linked),
223e47cc 328 });
1a4d82fc
JJ
329
330 let source = cstore::CrateSource {
331 dylib: dylib,
332 rlib: rlib,
333 cnum: cnum,
334 };
335
92a42be0
SL
336 self.cstore.set_crate_data(cnum, cmeta.clone());
337 self.cstore.add_used_crate_source(source.clone());
1a4d82fc
JJ
338 (cnum, cmeta, source)
339 }
340
341 fn resolve_crate(&mut self,
342 root: &Option<CratePaths>,
343 ident: &str,
344 name: &str,
345 hash: Option<&Svh>,
346 span: Span,
e9174d1e
SL
347 kind: PathKind,
348 explicitly_linked: bool)
9e0c209e
SL
349 -> (CrateNum, Rc<cstore::CrateMetadata>, cstore::CrateSource) {
350 info!("resolving crate `extern crate {} as {}`", name, ident);
92a42be0 351 let result = match self.existing_match(name, hash, kind) {
a7813a04 352 Some(cnum) => LoadResult::Previous(cnum),
1a4d82fc 353 None => {
9e0c209e 354 info!("falling back to a load");
1a4d82fc
JJ
355 let mut load_ctxt = loader::Context {
356 sess: self.sess,
357 span: span,
358 ident: ident,
359 crate_name: name,
360 hash: hash.map(|a| &*a),
361 filesearch: self.sess.target_filesearch(kind),
85aaf69f 362 target: &self.sess.target.target,
c34b1796 363 triple: &self.sess.opts.target_triple,
1a4d82fc
JJ
364 root: root,
365 rejected_via_hash: vec!(),
366 rejected_via_triple: vec!(),
85aaf69f 367 rejected_via_kind: vec!(),
a7813a04 368 rejected_via_version: vec!(),
1a4d82fc
JJ
369 should_match_name: true,
370 };
a7813a04
XL
371 match self.load(&mut load_ctxt) {
372 Some(result) => result,
373 None => load_ctxt.report_load_errs(),
374 }
e9174d1e 375 }
92a42be0
SL
376 };
377
378 match result {
a7813a04 379 LoadResult::Previous(cnum) => {
92a42be0 380 let data = self.cstore.get_crate_data(cnum);
e9174d1e
SL
381 if explicitly_linked && !data.explicitly_linked.get() {
382 data.explicitly_linked.set(explicitly_linked);
383 }
92a42be0
SL
384 (cnum, data, self.cstore.used_crate_source(cnum))
385 }
a7813a04 386 LoadResult::Loaded(library) => {
92a42be0
SL
387 self.register_crate(root, ident, name, span, library,
388 explicitly_linked)
1a4d82fc 389 }
1a4d82fc
JJ
390 }
391 }
392
a7813a04
XL
393 fn load(&mut self, loader: &mut loader::Context) -> Option<LoadResult> {
394 let library = match loader.maybe_load_library_crate() {
395 Some(lib) => lib,
396 None => return None,
397 };
398
399 // In the case that we're loading a crate, but not matching
400 // against a hash, we could load a crate which has the same hash
401 // as an already loaded crate. If this is the case prevent
402 // duplicates by just using the first crate.
403 //
404 // Note that we only do this for target triple crates, though, as we
405 // don't want to match a host crate against an equivalent target one
406 // already loaded.
9e0c209e 407 let root = library.metadata.get_root();
a7813a04 408 if loader.triple == self.sess.opts.target_triple {
a7813a04
XL
409 let mut result = LoadResult::Loaded(library);
410 self.cstore.iter_crate_data(|cnum, data| {
9e0c209e 411 if data.name() == root.name && root.hash == data.hash() {
a7813a04 412 assert!(loader.hash.is_none());
9e0c209e 413 info!("load success, going to previous cnum: {}", cnum);
a7813a04
XL
414 result = LoadResult::Previous(cnum);
415 }
416 });
417 Some(result)
418 } else {
419 Some(LoadResult::Loaded(library))
420 }
421 }
422
54a0048b 423 fn update_extern_crate(&mut self,
9e0c209e 424 cnum: CrateNum,
3157f602 425 mut extern_crate: ExternCrate,
9e0c209e 426 visited: &mut FnvHashSet<(CrateNum, bool)>)
54a0048b 427 {
3157f602
XL
428 if !visited.insert((cnum, extern_crate.direct)) { return }
429
54a0048b
SL
430 let cmeta = self.cstore.get_crate_data(cnum);
431 let old_extern_crate = cmeta.extern_crate.get();
432
433 // Prefer:
434 // - something over nothing (tuple.0);
435 // - direct extern crate to indirect (tuple.1);
436 // - shorter paths to longer (tuple.2).
437 let new_rank = (true, extern_crate.direct, !extern_crate.path_len);
438 let old_rank = match old_extern_crate {
439 None => (false, false, !0),
440 Some(ref c) => (true, c.direct, !c.path_len),
441 };
442
443 if old_rank >= new_rank {
444 return; // no change needed
445 }
446
447 cmeta.extern_crate.set(Some(extern_crate));
54a0048b
SL
448 // Propagate the extern crate info to dependencies.
449 extern_crate.direct = false;
3157f602
XL
450 for &dep_cnum in cmeta.cnum_map.borrow().iter() {
451 self.update_extern_crate(dep_cnum, extern_crate, visited);
54a0048b
SL
452 }
453 }
454
1a4d82fc
JJ
455 // Go through the crate metadata and load any crates that it references
456 fn resolve_crate_deps(&mut self,
457 root: &Option<CratePaths>,
9e0c209e
SL
458 crate_root: &CrateRoot,
459 metadata: &MetadataBlob,
460 krate: CrateNum,
3157f602
XL
461 span: Span)
462 -> cstore::CrateNumMap {
1a4d82fc
JJ
463 debug!("resolving deps of external crate");
464 // The map from crate numbers in the crate we're resolving to local crate
465 // numbers
9e0c209e
SL
466 let deps = crate_root.crate_deps.decode(metadata);
467 let map: FnvHashMap<_, _> = deps.enumerate().map(|(crate_num, dep)| {
1a4d82fc 468 debug!("resolving dep crate {} hash: `{}`", dep.name, dep.hash);
9e0c209e
SL
469 let (local_cnum, ..) = self.resolve_crate(root,
470 &dep.name.as_str(),
471 &dep.name.as_str(),
54a0048b
SL
472 Some(&dep.hash),
473 span,
474 PathKind::Dependency,
475 dep.explicitly_linked);
9e0c209e 476 (CrateNum::new(crate_num + 1), local_cnum)
3157f602
XL
477 }).collect();
478
9e0c209e 479 let max_cnum = map.values().cloned().max().map(|cnum| cnum.as_u32()).unwrap_or(0);
3157f602
XL
480
481 // we map 0 and all other holes in the map to our parent crate. The "additional"
482 // self-dependencies should be harmless.
9e0c209e
SL
483 (0..max_cnum+1).map(|cnum| {
484 map.get(&CrateNum::from_u32(cnum)).cloned().unwrap_or(krate)
485 }).collect()
1a4d82fc
JJ
486 }
487
9e0c209e
SL
488 fn read_extension_crate(&mut self, span: Span, info: &ExternCrateInfo) -> ExtensionCrate {
489 info!("read extension crate {} `extern crate {} as {}` linked={}",
490 info.id, info.name, info.ident, info.should_link);
c34b1796 491 let target_triple = &self.sess.opts.target_triple[..];
1a4d82fc
JJ
492 let is_cross = target_triple != config::host_triple();
493 let mut should_link = info.should_link && !is_cross;
494 let mut target_only = false;
495 let ident = info.ident.clone();
496 let name = info.name.clone();
497 let mut load_ctxt = loader::Context {
498 sess: self.sess,
499 span: span,
85aaf69f
SL
500 ident: &ident[..],
501 crate_name: &name[..],
1a4d82fc
JJ
502 hash: None,
503 filesearch: self.sess.host_filesearch(PathKind::Crate),
85aaf69f 504 target: &self.sess.host,
1a4d82fc
JJ
505 triple: config::host_triple(),
506 root: &None,
507 rejected_via_hash: vec!(),
508 rejected_via_triple: vec!(),
85aaf69f 509 rejected_via_kind: vec!(),
a7813a04 510 rejected_via_version: vec!(),
1a4d82fc
JJ
511 should_match_name: true,
512 };
a7813a04
XL
513 let library = self.load(&mut load_ctxt).or_else(|| {
514 if !is_cross {
515 return None
1a4d82fc 516 }
a7813a04
XL
517 // Try loading from target crates. This will abort later if we
518 // try to load a plugin registrar function,
519 target_only = true;
520 should_link = info.should_link;
521
522 load_ctxt.target = &self.sess.target.target;
523 load_ctxt.triple = target_triple;
524 load_ctxt.filesearch = self.sess.target_filesearch(PathKind::Crate);
525
526 self.load(&mut load_ctxt)
527 });
528 let library = match library {
529 Some(l) => l,
530 None => load_ctxt.report_load_errs(),
223e47cc
LB
531 };
532
a7813a04
XL
533 let (dylib, metadata) = match library {
534 LoadResult::Previous(cnum) => {
535 let dylib = self.cstore.opt_used_crate_source(cnum).unwrap().dylib;
536 let data = self.cstore.get_crate_data(cnum);
537 (dylib, PMDSource::Registered(data))
538 }
539 LoadResult::Loaded(library) => {
540 let dylib = library.dylib.clone();
9e0c209e 541 let metadata = PMDSource::Owned(library);
a7813a04
XL
542 (dylib, metadata)
543 }
1a4d82fc
JJ
544 };
545
85aaf69f 546 ExtensionCrate {
1a4d82fc 547 metadata: metadata,
85aaf69f 548 dylib: dylib.map(|p| p.0),
1a4d82fc 549 target_only: target_only,
9e0c209e
SL
550 name: info.name.to_string(),
551 ident: info.ident.to_string(),
552 span: span,
553 should_link: should_link,
1a4d82fc 554 }
223e47cc 555 }
223e47cc 556
9e0c209e 557 pub fn read_macros(&mut self, item: &ast::Item) -> Macros {
e9174d1e
SL
558 let ci = self.extract_crate_info(item).unwrap();
559 let ekrate = self.read_extension_crate(item.span, &ci);
1a4d82fc 560
9e0c209e 561 let root = ekrate.metadata.get_root();
e9174d1e 562 let source_name = format!("<{} macros>", item.ident);
9e0c209e
SL
563 let mut ret = Macros {
564 macro_rules: Vec::new(),
565 custom_derive_registrar: None,
566 svh: root.hash,
567 dylib: None,
568 };
569 for def in root.macro_defs.decode(&*ekrate.metadata) {
570 // NB: Don't use parse::parse_tts_from_source_str because it parses with
571 // quote_depth > 0.
572 let mut p = parse::new_parser_from_source_str(&self.sess.parse_sess,
573 self.local_crate_config.clone(),
574 source_name.clone(),
575 def.body);
576 let lo = p.span.lo;
577 let body = match p.parse_all_token_trees() {
578 Ok(body) => body,
579 Err(mut err) => {
580 err.emit();
581 self.sess.abort_if_errors();
582 unreachable!();
b039eaaf 583 }
9e0c209e
SL
584 };
585 let local_span = mk_sp(lo, p.last_span.hi);
b039eaaf 586
9e0c209e
SL
587 // Mark the attrs as used
588 for attr in &def.attrs {
589 attr::mark_used(attr);
1a4d82fc 590 }
9e0c209e
SL
591
592 ret.macro_rules.push(ast::MacroDef {
593 ident: ast::Ident::with_empty_ctxt(def.name),
594 attrs: def.attrs,
595 id: ast::DUMMY_NODE_ID,
596 span: local_span,
597 imported_from: Some(item.ident),
598 // overridden in plugin/load.rs
599 export: false,
600 use_locally: false,
601 allow_internal_unstable: false,
602
603 body: body,
604 });
605 self.sess.imported_macro_spans.borrow_mut()
606 .insert(local_span, (def.name.as_str().to_string(), def.span));
607 }
608
609 match root.macro_derive_registrar {
610 Some(id) => ret.custom_derive_registrar = Some(id),
611
612 // If this crate is not a rustc-macro crate then we might be able to
613 // register it with the local crate store to prevent loading the
614 // metadata twice.
615 //
616 // If it's a rustc-macro crate, though, then we definitely don't
617 // want to register it with the local crate store as we're just
618 // going to use it as we would a plugin.
619 None => {
620 ekrate.register(self);
621 return ret
622 }
623 }
624
625 self.cstore.add_used_for_derive_macros(item);
626 ret.dylib = ekrate.dylib.clone();
627 if ret.dylib.is_none() {
628 span_bug!(item.span, "rustc-macro crate not dylib");
629 }
630
631 if ekrate.target_only {
632 let message = format!("rustc-macro crate is not available for \
633 triple `{}` (only found {})",
634 config::host_triple(),
635 self.sess.opts.target_triple);
636 self.sess.span_fatal(item.span, &message);
637 }
638
639 return ret
1a4d82fc
JJ
640 }
641
3157f602
XL
642 /// Look for a plugin registrar. Returns library path, crate
643 /// SVH and DefIndex of the registrar function.
c34b1796 644 pub fn find_plugin_registrar(&mut self, span: Span, name: &str)
3157f602 645 -> Option<(PathBuf, Svh, DefIndex)> {
9e0c209e 646 let ekrate = self.read_extension_crate(span, &ExternCrateInfo {
85aaf69f
SL
647 name: name.to_string(),
648 ident: name.to_string(),
649 id: ast::DUMMY_NODE_ID,
650 should_link: false,
651 });
652
653 if ekrate.target_only {
1a4d82fc 654 // Need to abort before syntax expansion.
85aaf69f 655 let message = format!("plugin `{}` is not available for triple `{}` \
1a4d82fc 656 (only found {})",
85aaf69f 657 name,
1a4d82fc
JJ
658 config::host_triple(),
659 self.sess.opts.target_triple);
7453a54e 660 span_fatal!(self.sess, span, E0456, "{}", &message[..]);
1a4d82fc
JJ
661 }
662
9e0c209e
SL
663 let root = ekrate.metadata.get_root();
664 match (ekrate.dylib.as_ref(), root.plugin_registrar_fn) {
3157f602 665 (Some(dylib), Some(reg)) => {
9e0c209e 666 Some((dylib.to_path_buf(), root.hash, reg))
3157f602 667 }
1a4d82fc 668 (None, Some(_)) => {
b039eaaf
SL
669 span_err!(self.sess, span, E0457,
670 "plugin `{}` only found in rlib format, but must be available \
671 in dylib format",
672 name);
1a4d82fc
JJ
673 // No need to abort because the loading code will just ignore this
674 // empty dylib.
675 None
676 }
677 _ => None,
223e47cc
LB
678 }
679 }
e9174d1e
SL
680
681 fn register_statically_included_foreign_items(&mut self) {
92a42be0 682 let libs = self.cstore.get_used_libraries();
e9174d1e
SL
683 for (lib, list) in self.foreign_item_map.iter() {
684 let is_static = libs.borrow().iter().any(|&(ref name, kind)| {
685 lib == name && kind == cstore::NativeStatic
686 });
687 if is_static {
688 for id in list {
92a42be0 689 self.cstore.add_statically_included_foreign_item(*id);
e9174d1e
SL
690 }
691 }
692 }
693 }
694
a7813a04
XL
695 fn inject_panic_runtime(&mut self, krate: &ast::Crate) {
696 // If we're only compiling an rlib, then there's no need to select a
697 // panic runtime, so we just skip this section entirely.
698 let any_non_rlib = self.sess.crate_types.borrow().iter().any(|ct| {
699 *ct != config::CrateTypeRlib
700 });
701 if !any_non_rlib {
702 info!("panic runtime injection skipped, only generating rlib");
703 return
704 }
705
706 // If we need a panic runtime, we try to find an existing one here. At
707 // the same time we perform some general validation of the DAG we've got
708 // going such as ensuring everything has a compatible panic strategy.
709 //
710 // The logic for finding the panic runtime here is pretty much the same
711 // as the allocator case with the only addition that the panic strategy
712 // compilation mode also comes into play.
713 let desired_strategy = self.sess.opts.cg.panic.clone();
714 let mut runtime_found = false;
715 let mut needs_panic_runtime = attr::contains_name(&krate.attrs,
716 "needs_panic_runtime");
717 self.cstore.iter_crate_data(|cnum, data| {
718 needs_panic_runtime = needs_panic_runtime || data.needs_panic_runtime();
719 if data.is_panic_runtime() {
720 // Inject a dependency from all #![needs_panic_runtime] to this
721 // #![panic_runtime] crate.
722 self.inject_dependency_if(cnum, "a panic runtime",
723 &|data| data.needs_panic_runtime());
724 runtime_found = runtime_found || data.explicitly_linked.get();
725 }
726 });
727
728 // If an explicitly linked and matching panic runtime was found, or if
729 // we just don't need one at all, then we're done here and there's
730 // nothing else to do.
731 if !needs_panic_runtime || runtime_found {
732 return
733 }
734
735 // By this point we know that we (a) need a panic runtime and (b) no
736 // panic runtime was explicitly linked. Here we just load an appropriate
737 // default runtime for our panic strategy and then inject the
738 // dependencies.
739 //
740 // We may resolve to an already loaded crate (as the crate may not have
741 // been explicitly linked prior to this) and we may re-inject
742 // dependencies again, but both of those situations are fine.
743 //
744 // Also note that we have yet to perform validation of the crate graph
745 // in terms of everyone has a compatible panic runtime format, that's
746 // performed later as part of the `dependency_format` module.
747 let name = match desired_strategy {
748 PanicStrategy::Unwind => "panic_unwind",
749 PanicStrategy::Abort => "panic_abort",
750 };
751 info!("panic runtime not found -- loading {}", name);
752
753 let (cnum, data, _) = self.resolve_crate(&None, name, name, None,
3157f602 754 syntax_pos::DUMMY_SP,
a7813a04
XL
755 PathKind::Crate, false);
756
757 // Sanity check the loaded crate to ensure it is indeed a panic runtime
758 // and the panic strategy is indeed what we thought it was.
759 if !data.is_panic_runtime() {
760 self.sess.err(&format!("the crate `{}` is not a panic runtime",
761 name));
762 }
763 if data.panic_strategy() != desired_strategy {
764 self.sess.err(&format!("the crate `{}` does not have the panic \
765 strategy `{}`",
766 name, desired_strategy.desc()));
767 }
768
769 self.sess.injected_panic_runtime.set(Some(cnum));
770 self.inject_dependency_if(cnum, "a panic runtime",
771 &|data| data.needs_panic_runtime());
772 }
773
e9174d1e
SL
774 fn inject_allocator_crate(&mut self) {
775 // Make sure that we actually need an allocator, if none of our
776 // dependencies need one then we definitely don't!
777 //
778 // Also, if one of our dependencies has an explicit allocator, then we
779 // also bail out as we don't need to implicitly inject one.
780 let mut needs_allocator = false;
781 let mut found_required_allocator = false;
92a42be0 782 self.cstore.iter_crate_data(|cnum, data| {
e9174d1e
SL
783 needs_allocator = needs_allocator || data.needs_allocator();
784 if data.is_allocator() {
a7813a04
XL
785 info!("{} required by rlib and is an allocator", data.name());
786 self.inject_dependency_if(cnum, "an allocator",
787 &|data| data.needs_allocator());
e9174d1e
SL
788 found_required_allocator = found_required_allocator ||
789 data.explicitly_linked.get();
790 }
791 });
792 if !needs_allocator || found_required_allocator { return }
793
794 // At this point we've determined that we need an allocator and no
795 // previous allocator has been activated. We look through our outputs of
796 // crate types to see what kind of allocator types we may need.
797 //
798 // The main special output type here is that rlibs do **not** need an
799 // allocator linked in (they're just object files), only final products
800 // (exes, dylibs, staticlibs) need allocators.
801 let mut need_lib_alloc = false;
802 let mut need_exe_alloc = false;
803 for ct in self.sess.crate_types.borrow().iter() {
804 match *ct {
805 config::CrateTypeExecutable => need_exe_alloc = true,
806 config::CrateTypeDylib |
9e0c209e 807 config::CrateTypeRustcMacro |
a7813a04 808 config::CrateTypeCdylib |
e9174d1e
SL
809 config::CrateTypeStaticlib => need_lib_alloc = true,
810 config::CrateTypeRlib => {}
811 }
812 }
813 if !need_lib_alloc && !need_exe_alloc { return }
814
815 // The default allocator crate comes from the custom target spec, and we
816 // choose between the standard library allocator or exe allocator. This
817 // distinction exists because the default allocator for binaries (where
818 // the world is Rust) is different than library (where the world is
819 // likely *not* Rust).
820 //
821 // If a library is being produced, but we're also flagged with `-C
822 // prefer-dynamic`, then we interpret this as a *Rust* dynamic library
823 // is being produced so we use the exe allocator instead.
824 //
825 // What this boils down to is:
826 //
827 // * Binaries use jemalloc
828 // * Staticlibs and Rust dylibs use system malloc
829 // * Rust dylibs used as dependencies to rust use jemalloc
830 let name = if need_lib_alloc && !self.sess.opts.cg.prefer_dynamic {
831 &self.sess.target.target.options.lib_allocation_crate
832 } else {
833 &self.sess.target.target.options.exe_allocation_crate
834 };
835 let (cnum, data, _) = self.resolve_crate(&None, name, name, None,
3157f602 836 syntax_pos::DUMMY_SP,
e9174d1e
SL
837 PathKind::Crate, false);
838
a7813a04
XL
839 // Sanity check the crate we loaded to ensure that it is indeed an
840 // allocator.
e9174d1e
SL
841 if !data.is_allocator() {
842 self.sess.err(&format!("the allocator crate `{}` is not tagged \
843 with #![allocator]", data.name()));
844 }
845
846 self.sess.injected_allocator.set(Some(cnum));
a7813a04
XL
847 self.inject_dependency_if(cnum, "an allocator",
848 &|data| data.needs_allocator());
e9174d1e
SL
849 }
850
a7813a04 851 fn inject_dependency_if(&self,
9e0c209e 852 krate: CrateNum,
a7813a04 853 what: &str,
3157f602 854 needs_dep: &Fn(&cstore::CrateMetadata) -> bool) {
a7813a04
XL
855 // don't perform this validation if the session has errors, as one of
856 // those errors may indicate a circular dependency which could cause
857 // this to stack overflow.
858 if self.sess.has_errors() {
859 return
860 }
861
e9174d1e 862 // Before we inject any dependencies, make sure we don't inject a
a7813a04
XL
863 // circular dependency by validating that this crate doesn't
864 // transitively depend on any crates satisfying `needs_dep`.
3157f602
XL
865 for dep in self.cstore.crate_dependencies_in_rpo(krate) {
866 let data = self.cstore.get_crate_data(dep);
867 if needs_dep(&data) {
868 self.sess.err(&format!("the crate `{}` cannot depend \
869 on a crate that needs {}, but \
870 it depends on `{}`",
871 self.cstore.get_crate_data(krate).name(),
872 what,
873 data.name()));
874 }
875 }
a7813a04
XL
876
877 // All crates satisfying `needs_dep` do not explicitly depend on the
878 // crate provided for this compile, but in order for this compilation to
879 // be successfully linked we need to inject a dependency (to order the
880 // crates on the command line correctly).
92a42be0 881 self.cstore.iter_crate_data(|cnum, data| {
a7813a04 882 if !needs_dep(data) {
e9174d1e
SL
883 return
884 }
885
a7813a04 886 info!("injecting a dep from {} to {}", cnum, krate);
3157f602 887 data.cnum_map.borrow_mut().push(krate);
e9174d1e 888 });
e9174d1e
SL
889 }
890}
891
9e0c209e
SL
892impl ExtensionCrate {
893 fn register(self, creader: &mut CrateReader) {
894 if !self.should_link {
895 return
e9174d1e
SL
896 }
897
9e0c209e
SL
898 let library = match self.metadata {
899 PMDSource::Owned(lib) => lib,
900 PMDSource::Registered(_) => return,
901 };
e9174d1e 902
9e0c209e
SL
903 // Register crate now to avoid double-reading metadata
904 creader.register_crate(&None,
905 &self.ident,
906 &self.name,
907 self.span,
908 library,
909 true);
e9174d1e 910 }
9e0c209e 911}
e9174d1e 912
9e0c209e
SL
913impl<'a> CrateLoader<'a> {
914 pub fn new(sess: &'a Session, cstore: &'a CStore, krate: &ast::Crate, crate_name: &str)
915 -> Self {
916 let loader = CrateLoader {
917 sess: sess,
918 cstore: cstore,
919 creader: CrateReader::new(sess, cstore, crate_name, krate.config.clone()),
920 };
e9174d1e 921
9e0c209e
SL
922 for attr in krate.attrs.iter().filter(|m| m.name() == "link_args") {
923 if let Some(ref linkarg) = attr.value_str() {
924 loader.cstore.add_used_link_args(&linkarg);
e9174d1e 925 }
e9174d1e 926 }
9e0c209e
SL
927
928 loader
e9174d1e
SL
929 }
930
a7813a04 931 fn process_foreign_mod(&mut self, i: &ast::Item, fm: &ast::ForeignMod) {
7453a54e 932 if fm.abi == Abi::Rust || fm.abi == Abi::RustIntrinsic || fm.abi == Abi::PlatformIntrinsic {
e9174d1e
SL
933 return;
934 }
935
936 // First, add all of the custom #[link_args] attributes
937 for m in i.attrs.iter().filter(|a| a.check_name("link_args")) {
938 if let Some(linkarg) = m.value_str() {
92a42be0 939 self.cstore.add_used_link_args(&linkarg);
e9174d1e
SL
940 }
941 }
942
943 // Next, process all of the #[link(..)]-style arguments
944 for m in i.attrs.iter().filter(|a| a.check_name("link")) {
945 let items = match m.meta_item_list() {
946 Some(item) => item,
947 None => continue,
948 };
949 let kind = items.iter().find(|k| {
950 k.check_name("kind")
951 }).and_then(|a| a.value_str());
952 let kind = match kind.as_ref().map(|s| &s[..]) {
953 Some("static") => cstore::NativeStatic,
954 Some("dylib") => cstore::NativeUnknown,
955 Some("framework") => cstore::NativeFramework,
956 Some(k) => {
9e0c209e
SL
957 struct_span_err!(self.sess, m.span, E0458,
958 "unknown kind: `{}`", k)
959 .span_label(m.span, &format!("unknown kind")).emit();
e9174d1e
SL
960 cstore::NativeUnknown
961 }
962 None => cstore::NativeUnknown
963 };
964 let n = items.iter().find(|n| {
965 n.check_name("name")
966 }).and_then(|a| a.value_str());
967 let n = match n {
968 Some(n) => n,
969 None => {
9e0c209e
SL
970 struct_span_err!(self.sess, m.span, E0459,
971 "#[link(...)] specified without `name = \"foo\"`")
972 .span_label(m.span, &format!("missing `name` argument")).emit();
e9174d1e
SL
973 InternedString::new("foo")
974 }
975 };
92a42be0 976 register_native_lib(self.sess, self.cstore, Some(m.span), n.to_string(), kind);
e9174d1e
SL
977 }
978
979 // Finally, process the #[linked_from = "..."] attribute
980 for m in i.attrs.iter().filter(|a| a.check_name("linked_from")) {
981 let lib_name = match m.value_str() {
982 Some(name) => name,
983 None => continue,
984 };
985 let list = self.creader.foreign_item_map.entry(lib_name.to_string())
986 .or_insert(Vec::new());
987 list.extend(fm.items.iter().map(|it| it.id));
988 }
989 }
223e47cc 990}
c34b1796 991
9e0c209e
SL
992impl<'a> middle::cstore::CrateLoader for CrateLoader<'a> {
993 fn postprocess(&mut self, krate: &ast::Crate) {
994 self.creader.inject_allocator_crate();
995 self.creader.inject_panic_runtime(krate);
c34b1796 996
9e0c209e
SL
997 if log_enabled!(log::INFO) {
998 dump_crates(&self.cstore);
c34b1796 999 }
c34b1796 1000
9e0c209e
SL
1001 for &(ref name, kind) in &self.sess.opts.libs {
1002 register_native_lib(self.sess, self.cstore, None, name.clone(), kind);
c34b1796 1003 }
9e0c209e
SL
1004 self.creader.register_statically_included_foreign_items();
1005 }
c34b1796 1006
9e0c209e
SL
1007 fn process_item(&mut self, item: &ast::Item, definitions: &hir_map::Definitions) {
1008 match item.node {
1009 ast::ItemKind::ExternCrate(_) => {}
1010 ast::ItemKind::ForeignMod(ref fm) => return self.process_foreign_mod(item, fm),
1011 _ => return,
c34b1796
AL
1012 }
1013
9e0c209e
SL
1014 // If this `extern crate` item has `#[macro_use]` then we can safely skip it.
1015 // These annotations were processed during macro expansion and are already loaded
1016 // (if necessary) into our crate store.
1017 //
1018 // Note that it's important we *don't* fall through below as some `#[macro_use]`
1019 // crates are explicitly not linked (e.g. macro crates) so we want to ensure
1020 // we avoid `resolve_crate` with those.
1021 if attr::contains_name(&item.attrs, "macro_use") {
1022 if self.cstore.was_used_for_derive_macros(item) {
1023 return
c34b1796
AL
1024 }
1025 }
1026
9e0c209e
SL
1027 if let Some(info) = self.creader.extract_crate_info(item) {
1028 if !info.should_link {
1029 return;
1030 }
c34b1796 1031
9e0c209e
SL
1032 let (cnum, ..) = self.creader.resolve_crate(
1033 &None, &info.ident, &info.name, None, item.span, PathKind::Crate, true,
1034 );
c34b1796 1035
9e0c209e
SL
1036 let def_id = definitions.opt_local_def_id(item.id).unwrap();
1037 let len = definitions.def_path(def_id.index).data.len();
1038
1039 let extern_crate =
1040 ExternCrate { def_id: def_id, span: item.span, direct: true, path_len: len };
1041 self.creader.update_extern_crate(cnum, extern_crate, &mut FnvHashSet());
1042
1043 self.cstore.add_extern_mod_stmt_cnum(info.id, cnum);
c34b1796 1044 }
9e0c209e 1045 }
c34b1796 1046
9e0c209e
SL
1047 fn load_macros(&mut self, extern_crate: &ast::Item, allows_macros: bool) -> Vec<LoadedMacro> {
1048 macro_import::load_macros(self, extern_crate, allows_macros)
c34b1796
AL
1049 }
1050}