]> git.lizzy.rs Git - rust.git/commitdiff
Remove rustc_llvm dependency from rustc_metadata
authorRobin Kruppe <robin.kruppe@gmail.com>
Wed, 26 Apr 2017 21:22:45 +0000 (23:22 +0200)
committerRobin Kruppe <robin.kruppe@gmail.com>
Sun, 14 May 2017 18:30:22 +0000 (20:30 +0200)
Move the code for loading metadata from rlibs and dylibs from
rustc_metadata into rustc_trans, and introduce a trait to avoid
introducing a direct dependency on rustc_trans.

This means rustc_metadata is no longer rebuilt when LLVM changes.

22 files changed:
src/Cargo.lock
src/librustc/Cargo.toml
src/librustc/lib.rs
src/librustc/middle/cstore.rs
src/librustc_driver/lib.rs
src/librustc_driver/test.rs
src/librustc_metadata/Cargo.toml
src/librustc_metadata/creader.rs
src/librustc_metadata/cstore.rs
src/librustc_metadata/cstore_impl.rs
src/librustc_metadata/decoder.rs
src/librustc_metadata/lib.rs
src/librustc_metadata/locator.rs
src/librustc_trans/Cargo.toml
src/librustc_trans/back/archive.rs
src/librustc_trans/back/link.rs
src/librustc_trans/base.rs
src/librustc_trans/lib.rs
src/librustc_trans/metadata.rs [new file with mode: 0644]
src/librustdoc/core.rs
src/librustdoc/test.rs
src/test/run-make/issue-19371/foo.rs

index 776a268aa8de19fffaa826970bc303d8fe45b073..bd9fda42570fde504b0a6ef30d4c03d0893dbc5d 100644 (file)
@@ -316,6 +316,14 @@ name = "open"
 version = "1.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "owning_ref"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "panic_abort"
 version = "0.0.0"
@@ -442,6 +450,7 @@ dependencies = [
  "fmt_macros 0.0.0",
  "graphviz 0.0.0",
  "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc_back 0.0.0",
  "rustc_bitflags 0.0.0",
  "rustc_const_math 0.0.0",
@@ -626,13 +635,13 @@ version = "0.0.0"
 dependencies = [
  "flate 0.0.0",
  "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "proc_macro 0.0.0",
  "rustc 0.0.0",
  "rustc_back 0.0.0",
  "rustc_const_math 0.0.0",
  "rustc_data_structures 0.0.0",
  "rustc_errors 0.0.0",
- "rustc_llvm 0.0.0",
  "serialize 0.0.0",
  "syntax 0.0.0",
  "syntax_ext 0.0.0",
@@ -734,6 +743,7 @@ version = "0.0.0"
 dependencies = [
  "flate 0.0.0",
  "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc 0.0.0",
  "rustc_back 0.0.0",
  "rustc_bitflags 0.0.0",
@@ -820,6 +830,11 @@ dependencies = [
 name = "serialize"
 version = "0.0.0"
 
+[[package]]
+name = "stable_deref_trait"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
 [[package]]
 name = "std"
 version = "0.0.0"
@@ -1015,6 +1030,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "e1cbfa3781f3fe73dc05321bed52a06d2d491eaa764c52335cf4399f046ece99"
 "checksum num_cpus 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca313f1862c7ec3e0dfe8ace9fa91b1d9cb5c84ace3d00f5ec4216238e93c167"
 "checksum open 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3478ed1686bd1300c8a981a940abc92b06fac9cbef747f4c668d4e032ff7b842"
+"checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37"
 "checksum pest 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0a6dda33d67c26f0aac90d324ab2eb7239c819fc7b2552fe9faa4fe88441edc8"
 "checksum pulldown-cmark 0.0.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9ab1e588ef8efd702c7ed9d2bd774db5e6f4d878bb5a1a9f371828fbdff6973"
 "checksum pulldown-cmark 0.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "1058d7bb927ca067656537eec4e02c2b4b70eaaa129664c5b90c111e20326f41"
@@ -1026,6 +1042,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum rustc-serialize 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)" = "684ce48436d6465300c9ea783b6b14c4361d6b8dcbb1375b486a69cc19e2dfb0"
 "checksum serde 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)" = "a702319c807c016e51f672e5c77d6f0b46afddd744b5e437d6b8436b888b458f"
 "checksum serde_json 0.9.9 (registry+https://github.com/rust-lang/crates.io-index)" = "dbc45439552eb8fb86907a2c41c1fd0ef97458efb87ff7f878db466eb581824e"
+"checksum stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "15132e0e364248108c5e2c02e3ab539be8d6f5d52a01ca9bbf27ed657316f02b"
 "checksum strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d15c810519a91cf877e7e36e63fe068815c678181439f2f29e2562147c3694"
 "checksum term_size 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "07b6c1ac5b3fffd75073276bca1ceed01f67a28537097a2a9539e116e50fb21a"
 "checksum thread-id 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4437c97558c70d129e40629a5b385b3fb1ffac301e63941335e4d354081ec14a"
index fa217acd9f9bf5e4eed1ea2feaede465f4450cbd..3c762e43e9aa6e8e7c118e24518f53691f3b1f19 100644 (file)
@@ -13,6 +13,7 @@ arena = { path = "../libarena" }
 fmt_macros = { path = "../libfmt_macros" }
 graphviz = { path = "../libgraphviz" }
 log = "0.3"
+owning_ref = "0.3.3"
 rustc_back = { path = "../librustc_back" }
 rustc_bitflags = { path = "../librustc_bitflags" }
 rustc_const_math = { path = "../librustc_const_math" }
index 5cf26ea8bfca596db6575dc9ec4cc46066f1cc88..c979677ff717c277d6a120cd21b566ad52633a84 100644 (file)
@@ -54,6 +54,7 @@
 extern crate getopts;
 extern crate graphviz;
 extern crate libc;
+extern crate owning_ref;
 extern crate rustc_llvm as llvm;
 extern crate rustc_back;
 extern crate rustc_data_structures;
index 569b1aeeb09d7ca1a2e2323746295a89b24708c7..a68aca4600054ac2ba3e9d87b7df727ad2d0f09b 100644 (file)
@@ -36,8 +36,9 @@
 use util::nodemap::{NodeSet, DefIdMap};
 
 use std::any::Any;
-use std::path::PathBuf;
+use std::path::{Path, PathBuf};
 use std::rc::Rc;
+use owning_ref::ErasedBoxRef;
 use syntax::ast;
 use syntax::ext::base::SyntaxExtension;
 use syntax::symbol::Symbol;
@@ -201,11 +202,33 @@ pub fn new() -> EncodedMetadataHashes {
     }
 }
 
+/// The backend's way to give the crate store access to the metadata in a library.
+/// Note that it returns the raw metadata bytes stored in the library file, whether
+/// it is compressed, uncompressed, some weird mix, etc.
+/// rmeta files are backend independent and not handled here.
+///
+/// At the time of this writing, there is only one backend and one way to store
+/// metadata in library -- this trait just serves to decouple rustc_metadata from
+/// the archive reader, which depends on LLVM.
+pub trait MetadataLoader {
+    fn get_rlib_metadata(&self,
+                         target: &Target,
+                         filename: &Path)
+                         -> Result<ErasedBoxRef<[u8]>, String>;
+    fn get_dylib_metadata(&self,
+                          target: &Target,
+                          filename: &Path)
+                          -> Result<ErasedBoxRef<[u8]>, String>;
+}
+
 /// A store of Rust crates, through with their metadata
 /// can be accessed.
 pub trait CrateStore {
     fn crate_data_as_rc_any(&self, krate: CrateNum) -> Rc<Any>;
 
+    // access to the metadata loader
+    fn metadata_loader(&self) -> &MetadataLoader;
+
     // item info
     fn visibility(&self, def: DefId) -> ty::Visibility;
     fn visible_parent_map<'a>(&'a self) -> ::std::cell::Ref<'a, DefIdMap<DefId>>;
@@ -275,8 +298,6 @@ fn item_body<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
     fn used_link_args(&self) -> Vec<String>;
 
     // utility functions
-    fn metadata_filename(&self) -> &str;
-    fn metadata_section_name(&self, target: &Target) -> &str;
     fn used_crates(&self, prefer: LinkagePreference) -> Vec<(CrateNum, LibSource)>;
     fn used_crate_source(&self, cnum: CrateNum) -> CrateSource;
     fn extern_mod_stmt_cnum(&self, emod_id: ast::NodeId) -> Option<CrateNum>;
@@ -413,8 +434,6 @@ fn used_libraries(&self) -> Vec<NativeLibrary> { vec![] }
     fn used_link_args(&self) -> Vec<String> { vec![] }
 
     // utility functions
-    fn metadata_filename(&self) -> &str { bug!("metadata_filename") }
-    fn metadata_section_name(&self, target: &Target) -> &str { bug!("metadata_section_name") }
     fn used_crates(&self, prefer: LinkagePreference) -> Vec<(CrateNum, LibSource)>
         { vec![] }
     fn used_crate_source(&self, cnum: CrateNum) -> CrateSource { bug!("used_crate_source") }
@@ -427,6 +446,9 @@ fn encode_metadata<'a, 'tcx>(&self,
         bug!("encode_metadata")
     }
     fn metadata_encoding_version(&self) -> &[u8] { bug!("metadata_encoding_version") }
+
+    // access to the metadata loader
+    fn metadata_loader(&self) -> &MetadataLoader { bug!("metadata_loader") }
 }
 
 pub trait CrateLoader {
index 024fc546a158efe9d175f4ba7357be522cf1a739..2dab680ad45aa581599368b2da5d8505b9f92120 100644 (file)
@@ -204,7 +204,7 @@ macro_rules! do_or_return {($expr: expr, $sess: expr) => {
     };
 
     let dep_graph = DepGraph::new(sopts.build_dep_graph());
-    let cstore = Rc::new(CStore::new(&dep_graph));
+    let cstore = Rc::new(CStore::new(&dep_graph, box rustc_trans::LlvmMetadataLoader));
 
     let loader = file_loader.unwrap_or(box RealFileLoader);
     let codemap = Rc::new(CodeMap::with_file_loader(loader, sopts.file_path_mapping()));
@@ -409,7 +409,7 @@ fn no_input(&mut self,
                     return None;
                 }
                 let dep_graph = DepGraph::new(sopts.build_dep_graph());
-                let cstore = Rc::new(CStore::new(&dep_graph));
+                let cstore = Rc::new(CStore::new(&dep_graph, box rustc_trans::LlvmMetadataLoader));
                 let mut sess = build_session(sopts.clone(),
                     &dep_graph,
                     None,
@@ -558,7 +558,11 @@ pub fn list_metadata(sess: &Session, matches: &getopts::Matches, input: &Input)
                 &Input::File(ref ifile) => {
                     let path = &(*ifile);
                     let mut v = Vec::new();
-                    locator::list_file_metadata(&sess.target.target, path, &mut v).unwrap();
+                    locator::list_file_metadata(&sess.target.target,
+                                                path,
+                                                sess.cstore.metadata_loader(),
+                                                &mut v)
+                            .unwrap();
                     println!("{}", String::from_utf8(v).unwrap());
                 }
                 &Input::Str { .. } => {
index e2cbc480715fb66d590be7a5311b9a52e9bf3277..be4f64b7109c5cddce87905362bd293027e04688 100644 (file)
@@ -14,6 +14,7 @@
 use rustc::dep_graph::DepGraph;
 use rustc_lint;
 use rustc_resolve::MakeGlobMap;
+use rustc_trans;
 use rustc::middle::lang_items;
 use rustc::middle::free_region::FreeRegionMap;
 use rustc::middle::region::{CodeExtent, RegionMaps};
@@ -104,7 +105,7 @@ fn test_env<F>(source_string: &str,
 
     let dep_graph = DepGraph::new(false);
     let _ignore = dep_graph.in_ignore();
-    let cstore = Rc::new(CStore::new(&dep_graph));
+    let cstore = Rc::new(CStore::new(&dep_graph, box rustc_trans::LlvmMetadataLoader));
     let sess = session::build_session_(options,
                                        &dep_graph,
                                        None,
index e8b906092730e5cbee6f873daa302fd57eaf46a6..f47788ee036dc5e312d4a05754a3f4b0cd8c7143 100644 (file)
@@ -11,13 +11,13 @@ crate-type = ["dylib"]
 [dependencies]
 flate = { path = "../libflate" }
 log = "0.3"
+owning_ref = "0.3.3"
 proc_macro = { path = "../libproc_macro" }
 rustc = { path = "../librustc" }
 rustc_back = { path = "../librustc_back" }
 rustc_const_math = { path = "../librustc_const_math" }
 rustc_data_structures = { path = "../librustc_data_structures" }
 rustc_errors = { path = "../librustc_errors" }
-rustc_llvm = { path = "../librustc_llvm" }
 serialize = { path = "../libserialize" }
 syntax = { path = "../libsyntax" }
 syntax_ext = { path = "../libsyntax_ext" }
index d2874f16289015afb8095c96111d203aac3745fa..dc7be42e452cb357352c9d9bbb8b9e41ebdc8bcb 100644 (file)
@@ -393,6 +393,7 @@ fn resolve_crate(&mut self,
                 rejected_via_filename: vec![],
                 should_match_name: true,
                 is_proc_macro: Some(false),
+                metadata_loader: &*self.cstore.metadata_loader,
             };
 
             self.load(&mut locate_ctxt).or_else(|| {
@@ -554,6 +555,7 @@ fn read_extension_crate(&mut self, span: Span, info: &ExternCrateInfo) -> Extens
             rejected_via_filename: vec![],
             should_match_name: true,
             is_proc_macro: None,
+            metadata_loader: &*self.cstore.metadata_loader,
         };
         let library = self.load(&mut locate_ctxt).or_else(|| {
             if !is_cross {
index c12b4209675dee9847304591dc66ea6c503834b3..d2ad6d0ab344999a00dbf6375cda9e8b45bb51b2 100644 (file)
 // The crate store - a central repo for information collected about external
 // crates and libraries
 
-use locator;
 use schema::{self, Tracked};
 
 use rustc::dep_graph::{DepGraph, DepNode, GlobalMetaDataKind};
 use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, CrateNum, DefIndex, DefId};
 use rustc::hir::map::definitions::DefPathTable;
 use rustc::hir::svh::Svh;
-use rustc::middle::cstore::{DepKind, ExternCrate};
+use rustc::middle::cstore::{DepKind, ExternCrate, MetadataLoader};
 use rustc_back::PanicStrategy;
 use rustc_data_structures::indexed_vec::IndexVec;
 use rustc::util::nodemap::{FxHashMap, FxHashSet, NodeMap, DefIdMap};
 
 use std::cell::{RefCell, Cell};
 use std::rc::Rc;
-use flate::Bytes;
+use owning_ref::ErasedBoxRef;
 use syntax::{ast, attr};
 use syntax::ext::base::SyntaxExtension;
 use syntax::symbol::Symbol;
 // own crate numbers.
 pub type CrateNumMap = IndexVec<CrateNum, CrateNum>;
 
-pub enum MetadataBlob {
-    Inflated(Bytes),
-    Archive(locator::ArchiveMetadata),
-    Raw(Vec<u8>),
-}
+pub struct MetadataBlob(pub ErasedBoxRef<[u8]>);
 
 /// Holds information about a syntax_pos::FileMap imported from another crate.
 /// See `imported_filemaps()` for more information.
@@ -103,10 +98,11 @@ pub struct CStore {
     statically_included_foreign_items: RefCell<FxHashSet<DefIndex>>,
     pub dllimport_foreign_items: RefCell<FxHashSet<DefIndex>>,
     pub visible_parent_map: RefCell<DefIdMap<DefId>>,
+    pub metadata_loader: Box<MetadataLoader>,
 }
 
 impl CStore {
-    pub fn new(dep_graph: &DepGraph) -> CStore {
+    pub fn new(dep_graph: &DepGraph, metadata_loader: Box<MetadataLoader>) -> CStore {
         CStore {
             dep_graph: dep_graph.clone(),
             metas: RefCell::new(FxHashMap()),
@@ -116,6 +112,7 @@ pub fn new(dep_graph: &DepGraph) -> CStore {
             statically_included_foreign_items: RefCell::new(FxHashSet()),
             dllimport_foreign_items: RefCell::new(FxHashSet()),
             visible_parent_map: RefCell::new(FxHashMap()),
+            metadata_loader: metadata_loader,
         }
     }
 
index dbf3e94832fc4fd724a010fe841d440243c406b0..1a2298d3fb1bacc2fb534674e3bf33dff9d5ba34 100644 (file)
 
 use cstore;
 use encoder;
-use locator;
 use schema;
 
 use rustc::dep_graph::DepTrackingMapConfig;
 use rustc::middle::cstore::{CrateStore, CrateSource, LibSource, DepKind,
-                            ExternCrate, NativeLibrary, LinkMeta,
+                            ExternCrate, NativeLibrary, MetadataLoader, LinkMeta,
                             LinkagePreference, LoadedMacro, EncodedMetadata};
 use rustc::hir::def;
 use rustc::middle::lang_items;
@@ -38,7 +37,6 @@
 use syntax::symbol::Symbol;
 use syntax_pos::{Span, NO_EXPANSION};
 use rustc::hir::svh::Svh;
-use rustc_back::target::Target;
 use rustc::hir;
 
 macro_rules! provide {
@@ -135,6 +133,10 @@ fn crate_data_as_rc_any(&self, krate: CrateNum) -> Rc<Any> {
         self.get_crate_data(krate)
     }
 
+    fn metadata_loader(&self) -> &MetadataLoader {
+        &*self.metadata_loader
+    }
+
     fn visibility(&self, def: DefId) -> ty::Visibility {
         self.dep_graph.read(DepNode::MetaData(def));
         self.get_crate_data(def.krate).get_visibility(def.index)
@@ -420,17 +422,6 @@ fn used_link_args(&self) -> Vec<String>
     {
         self.get_used_link_args().borrow().clone()
     }
-
-    fn metadata_filename(&self) -> &str
-    {
-        locator::METADATA_FILENAME
-    }
-
-    fn metadata_section_name(&self, target: &Target) -> &str
-    {
-        locator::meta_section_name(target)
-    }
-
     fn used_crates(&self, prefer: LinkagePreference) -> Vec<(CrateNum, LibSource)>
     {
         self.do_get_used_crates(prefer)
@@ -522,4 +513,4 @@ fn visible_parent_map<'a>(&'a self) -> ::std::cell::Ref<'a, DefIdMap<DefId>> {
         drop(visible_parent_map);
         self.visible_parent_map.borrow()
     }
-}
+}
\ No newline at end of file
index 819095e262832b207b9f689014c2e805cbc455b4..c734b9f411c2fb05ef112595893544fefacd1f5f 100644 (file)
@@ -77,11 +77,7 @@ fn decoder(self, pos: usize) -> DecodeContext<'a, 'tcx> {
 
 impl<'a, 'tcx> Metadata<'a, 'tcx> for &'a MetadataBlob {
     fn raw_bytes(self) -> &'a [u8] {
-        match *self {
-            MetadataBlob::Inflated(ref vec) => vec,
-            MetadataBlob::Archive(ref ar) => ar.as_slice(),
-            MetadataBlob::Raw(ref vec) => vec,
-        }
+        &self.0
     }
 }
 
index 27555f49e57fc1afc0991cc53c81ae1cb1eca9a0..e3d9e5ac74a062a6a53e5fa9909651117d726858 100644 (file)
@@ -37,6 +37,7 @@
 extern crate syntax_pos;
 extern crate flate;
 extern crate serialize as rustc_serialize; // used by deriving
+extern crate owning_ref;
 extern crate rustc_errors as errors;
 extern crate syntax_ext;
 extern crate proc_macro;
@@ -46,7 +47,6 @@
 extern crate rustc_back;
 extern crate rustc_const_math;
 extern crate rustc_data_structures;
-extern crate rustc_llvm;
 
 mod diagnostics;
 
index 84bb82de370e4f55f5e4635060d8ccde38fa4dc9..34b07af9f01f439cf84e551c5ff5cd629b6bcf98 100644 (file)
 use schema::{METADATA_HEADER, rustc_version};
 
 use rustc::hir::svh::Svh;
+use rustc::middle::cstore::MetadataLoader;
 use rustc::session::{config, Session};
 use rustc::session::filesearch::{FileSearch, FileMatches, FileDoesntMatch};
 use rustc::session::search_paths::PathKind;
-use rustc::util::common;
 use rustc::util::nodemap::FxHashMap;
 
-use rustc_llvm as llvm;
-use rustc_llvm::{False, ObjectFile, mk_section_iter};
-use rustc_llvm::archive_ro::ArchiveRO;
 use errors::DiagnosticBuilder;
 use syntax::symbol::Symbol;
 use syntax_pos::Span;
 use std::fs::{self, File};
 use std::io::{self, Read};
 use std::path::{Path, PathBuf};
-use std::ptr;
-use std::slice;
 use std::time::Instant;
 
 use flate;
+use owning_ref::{ErasedBoxRef, OwningRef};
 
 pub struct CrateMismatch {
     path: PathBuf,
@@ -272,12 +268,7 @@ pub struct Context<'a> {
     pub rejected_via_filename: Vec<CrateMismatch>,
     pub should_match_name: bool,
     pub is_proc_macro: Option<bool>,
-}
-
-pub struct ArchiveMetadata {
-    _archive: ArchiveRO,
-    // points into self._archive
-    data: *const [u8],
+    pub metadata_loader: &'a MetadataLoader,
 }
 
 pub struct CratePaths {
@@ -287,8 +278,6 @@ pub struct CratePaths {
     pub rmeta: Option<PathBuf>,
 }
 
-pub const METADATA_FILENAME: &'static str = "rust.metadata.bin";
-
 #[derive(Copy, Clone, PartialEq)]
 enum CrateFlavor {
     Rlib,
@@ -596,20 +585,21 @@ fn extract_one(&mut self,
         let mut err: Option<DiagnosticBuilder> = None;
         for (lib, kind) in m {
             info!("{} reading metadata from: {}", flavor, lib.display());
-            let (hash, metadata) = match get_metadata_section(self.target, flavor, &lib) {
-                Ok(blob) => {
-                    if let Some(h) = self.crate_matches(&blob, &lib) {
-                        (h, blob)
-                    } else {
-                        info!("metadata mismatch");
+            let (hash, metadata) =
+                match get_metadata_section(self.target, flavor, &lib, self.metadata_loader) {
+                    Ok(blob) => {
+                        if let Some(h) = self.crate_matches(&blob, &lib) {
+                            (h, blob)
+                        } else {
+                            info!("metadata mismatch");
+                            continue;
+                        }
+                    }
+                    Err(err) => {
+                        info!("no metadata found: {}", err);
                         continue;
                     }
-                }
-                Err(err) => {
-                    info!("no metadata found: {}", err);
-                    continue;
-                }
-            };
+                };
             // If we see multiple hashes, emit an error about duplicate candidates.
             if slot.as_ref().map_or(false, |s| s.0 != hash) {
                 let mut e = struct_span_err!(self.sess,
@@ -833,50 +823,14 @@ pub fn note_crate_name(err: &mut DiagnosticBuilder, name: &str) {
     err.note(&format!("crate name: {}", name));
 }
 
-impl ArchiveMetadata {
-    fn new(ar: ArchiveRO) -> Option<ArchiveMetadata> {
-        let data = {
-            let section = ar.iter()
-                .filter_map(|s| s.ok())
-                .find(|sect| sect.name() == Some(METADATA_FILENAME));
-            match section {
-                Some(s) => s.data() as *const [u8],
-                None => {
-                    debug!("didn't find '{}' in the archive", METADATA_FILENAME);
-                    return None;
-                }
-            }
-        };
-
-        Some(ArchiveMetadata {
-            _archive: ar,
-            data: data,
-        })
-    }
-
-    pub fn as_slice<'a>(&'a self) -> &'a [u8] {
-        unsafe { &*self.data }
-    }
-}
-
-fn verify_decompressed_encoding_version(blob: &MetadataBlob,
-                                        filename: &Path)
-                                        -> Result<(), String> {
-    if !blob.is_compatible() {
-        Err((format!("incompatible metadata version found: '{}'",
-                     filename.display())))
-    } else {
-        Ok(())
-    }
-}
-
 // Just a small wrapper to time how long reading metadata takes.
 fn get_metadata_section(target: &Target,
                         flavor: CrateFlavor,
-                        filename: &Path)
+                        filename: &Path,
+                        loader: &MetadataLoader)
                         -> Result<MetadataBlob, String> {
     let start = Instant::now();
-    let ret = get_metadata_section_imp(target, flavor, filename);
+    let ret = get_metadata_section_imp(target, flavor, filename, loader);
     info!("reading {:?} => {:?}",
           filename.file_name().unwrap(),
           start.elapsed());
@@ -885,118 +839,61 @@ fn get_metadata_section(target: &Target,
 
 fn get_metadata_section_imp(target: &Target,
                             flavor: CrateFlavor,
-                            filename: &Path)
+                            filename: &Path,
+                            loader: &MetadataLoader)
                             -> Result<MetadataBlob, String> {
     if !filename.exists() {
         return Err(format!("no such file: '{}'", filename.display()));
     }
-    if flavor == CrateFlavor::Rlib {
-        // Use ArchiveRO for speed here, it's backed by LLVM and uses mmap
-        // internally to read the file. We also avoid even using a memcpy by
-        // just keeping the archive along while the metadata is in use.
-        let archive = match ArchiveRO::open(filename) {
-            Some(ar) => ar,
-            None => {
-                debug!("llvm didn't like `{}`", filename.display());
-                return Err(format!("failed to read rlib metadata: '{}'", filename.display()));
+    let raw_bytes: ErasedBoxRef<[u8]> = match flavor {
+        CrateFlavor::Rlib => loader.get_rlib_metadata(target, filename)?,
+        CrateFlavor::Dylib => {
+            let buf = loader.get_dylib_metadata(target, filename)?;
+            // The header is uncompressed
+            let header_len = METADATA_HEADER.len();
+            debug!("checking {} bytes of metadata-version stamp", header_len);
+            let header = &buf[..cmp::min(header_len, buf.len())];
+            if header != METADATA_HEADER {
+                return Err(format!("incompatible metadata version found: '{}'",
+                                   filename.display()));
             }
-        };
-        return match ArchiveMetadata::new(archive).map(|ar| MetadataBlob::Archive(ar)) {
-            None => Err(format!("failed to read rlib metadata: '{}'", filename.display())),
-            Some(blob) => {
-                verify_decompressed_encoding_version(&blob, filename)?;
-                Ok(blob)
-            }
-        };
-    } else if flavor == CrateFlavor::Rmeta {
-        let mut file = File::open(filename).map_err(|_|
-            format!("could not open file: '{}'", filename.display()))?;
-        let mut buf = vec![];
-        file.read_to_end(&mut buf).map_err(|_|
-            format!("failed to read rlib metadata: '{}'", filename.display()))?;
-        let blob = MetadataBlob::Raw(buf);
-        verify_decompressed_encoding_version(&blob, filename)?;
-        return Ok(blob);
-    }
-    unsafe {
-        let buf = common::path2cstr(filename);
-        let mb = llvm::LLVMRustCreateMemoryBufferWithContentsOfFile(buf.as_ptr());
-        if mb as isize == 0 {
-            return Err(format!("error reading library: '{}'", filename.display()));
-        }
-        let of = match ObjectFile::new(mb) {
-            Some(of) => of,
-            _ => {
-                return Err((format!("provided path not an object file: '{}'", filename.display())))
-            }
-        };
-        let si = mk_section_iter(of.llof);
-        while llvm::LLVMIsSectionIteratorAtEnd(of.llof, si.llsi) == False {
-            let mut name_buf = ptr::null();
-            let name_len = llvm::LLVMRustGetSectionName(si.llsi, &mut name_buf);
-            let name = slice::from_raw_parts(name_buf as *const u8, name_len as usize).to_vec();
-            let name = String::from_utf8(name).unwrap();
-            debug!("get_metadata_section: name {}", name);
-            if read_meta_section_name(target) == name {
-                let cbuf = llvm::LLVMGetSectionContents(si.llsi);
-                let csz = llvm::LLVMGetSectionSize(si.llsi) as usize;
-                let cvbuf: *const u8 = cbuf as *const u8;
-                let vlen = METADATA_HEADER.len();
-                debug!("checking {} bytes of metadata-version stamp", vlen);
-                let minsz = cmp::min(vlen, csz);
-                let buf0 = slice::from_raw_parts(cvbuf, minsz);
-                let version_ok = buf0 == METADATA_HEADER;
-                if !version_ok {
-                    return Err((format!("incompatible metadata version found: '{}'",
-                                        filename.display())));
-                }
 
-                let cvbuf1 = cvbuf.offset(vlen as isize);
-                debug!("inflating {} bytes of compressed metadata", csz - vlen);
-                let bytes = slice::from_raw_parts(cvbuf1, csz - vlen);
-                match flate::inflate_bytes(bytes) {
-                    Ok(inflated) => {
-                        let blob = MetadataBlob::Inflated(inflated);
-                        verify_decompressed_encoding_version(&blob, filename)?;
-                        return Ok(blob);
-                    }
-                    Err(_) => {}
+            // Header is okay -> inflate the actual metadata
+            let compressed_bytes = &buf[header_len..];
+            debug!("inflating {} bytes of compressed metadata", compressed_bytes.len());
+            match flate::inflate_bytes(compressed_bytes) {
+                Ok(inflated) => {
+                    let buf = unsafe { OwningRef::new_assert_stable_address(inflated) };
+                    buf.map_owner_box().erase_owner()
+                }
+                Err(_) => {
+                    return Err(format!("failed to decompress metadata: {}", filename.display()));
                 }
             }
-            llvm::LLVMMoveToNextSection(si.llsi);
         }
-        Err(format!("metadata not found: '{}'", filename.display()))
-    }
-}
-
-pub fn meta_section_name(target: &Target) -> &'static str {
-    // Historical note:
-    //
-    // When using link.exe it was seen that the section name `.note.rustc`
-    // was getting shortened to `.note.ru`, and according to the PE and COFF
-    // specification:
-    //
-    // > Executable images do not use a string table and do not support
-    // > section names longer than 8 characters
-    //
-    // https://msdn.microsoft.com/en-us/library/windows/hardware/gg463119.aspx
-    //
-    // As a result, we choose a slightly shorter name! As to why
-    // `.note.rustc` works on MinGW, that's another good question...
-
-    if target.options.is_like_osx {
-        "__DATA,.rustc"
+        CrateFlavor::Rmeta => {
+            let mut file = File::open(filename).map_err(|_|
+                format!("could not open file: '{}'", filename.display()))?;
+            let mut buf = vec![];
+            file.read_to_end(&mut buf).map_err(|_|
+                format!("failed to read rmeta metadata: '{}'", filename.display()))?;
+            OwningRef::new(buf).map_owner_box().erase_owner()
+        }
+    };
+    let blob = MetadataBlob(raw_bytes);
+    if blob.is_compatible() {
+        Ok(blob)
     } else {
-        ".rustc"
+        Err(format!("incompatible metadata version found: '{}'", filename.display()))
     }
 }
 
-pub fn read_meta_section_name(_target: &Target) -> &'static str {
-    ".rustc"
-}
-
 // A diagnostic function for dumping crate metadata to an output stream
-pub fn list_file_metadata(target: &Target, path: &Path, out: &mut io::Write) -> io::Result<()> {
+pub fn list_file_metadata(target: &Target,
+                          path: &Path,
+                          loader: &MetadataLoader,
+                          out: &mut io::Write)
+                          -> io::Result<()> {
     let filename = path.file_name().unwrap().to_str().unwrap();
     let flavor = if filename.ends_with(".rlib") {
         CrateFlavor::Rlib
@@ -1005,7 +902,7 @@ pub fn list_file_metadata(target: &Target, path: &Path, out: &mut io::Write) ->
     } else {
         CrateFlavor::Dylib
     };
-    match get_metadata_section(target, flavor, path) {
+    match get_metadata_section(target, flavor, path, loader) {
         Ok(metadata) => metadata.list_crate_metadata(out),
         Err(msg) => write!(out, "{}\n", msg),
     }
index af477f5a15217bf7ca4c132a5dba9f77a9cb17d1..4ccc85257f3c990ba313df23fa87a9de43476721 100644 (file)
@@ -12,6 +12,7 @@ test = false
 [dependencies]
 flate = { path = "../libflate" }
 log = "0.3"
+owning_ref = "0.3.3"
 rustc = { path = "../librustc" }
 rustc_back = { path = "../librustc_back" }
 rustc_bitflags = { path = "../librustc_bitflags" }
index 0f908b7d0698bc48e7bd1fd529d46212c5433a0f..902065c8688d0d808fb6c2c29d25c82d8bbd219a 100644 (file)
@@ -20,6 +20,7 @@
 use libc;
 use llvm::archive_ro::{ArchiveRO, Child};
 use llvm::{self, ArchiveKind};
+use metadata::METADATA_FILENAME;
 use rustc::session::Session;
 
 pub struct ArchiveConfig<'a> {
@@ -158,11 +159,9 @@ pub fn add_rlib(&mut self,
         // Ignoring all bytecode files, no matter of
         // name
         let bc_ext = ".bytecode.deflate";
-        let metadata_filename =
-            self.config.sess.cstore.metadata_filename().to_owned();
 
         self.add_archive(rlib, move |fname: &str| {
-            if fname.ends_with(bc_ext) || fname == metadata_filename {
+            if fname.ends_with(bc_ext) || fname == METADATA_FILENAME {
                 return true
             }
 
index e42e69d2a76e27979718317626a86ee2a51df1de..b8aabef65a984adf76c8364ba0337797460ee009 100644 (file)
@@ -13,6 +13,7 @@
 use super::rpath::RPathConfig;
 use super::rpath;
 use super::msvc;
+use metadata::METADATA_FILENAME;
 use session::config;
 use session::config::NoDebugInfo;
 use session::config::{OutputFilenames, Input, OutputType};
@@ -521,7 +522,7 @@ fn link_rlib<'a>(sess: &'a Session,
             // contain the metadata in a separate file. We use a temp directory
             // here so concurrent builds in the same directory don't try to use
             // the same filename for metadata (stomping over one another)
-            let metadata = tmpdir.join(sess.cstore.metadata_filename());
+            let metadata = tmpdir.join(METADATA_FILENAME);
             emit_metadata(sess, trans, &metadata);
             ab.add_file(&metadata);
 
@@ -1141,8 +1142,7 @@ fn link_sanitizer_runtime(cmd: &mut Linker,
         archive.update_symbols();
 
         for f in archive.src_files() {
-            if f.ends_with("bytecode.deflate") ||
-                f == sess.cstore.metadata_filename() {
+            if f.ends_with("bytecode.deflate") || f == METADATA_FILENAME {
                     archive.remove_file(&f);
                     continue
                 }
@@ -1217,8 +1217,7 @@ fn add_static_crate(cmd: &mut Linker,
 
             let mut any_objects = false;
             for f in archive.src_files() {
-                if f.ends_with("bytecode.deflate") ||
-                   f == sess.cstore.metadata_filename() {
+                if f.ends_with("bytecode.deflate") || f == METADATA_FILENAME {
                     archive.remove_file(&f);
                     continue
                 }
index 8689e176f7a7b92d8d5d70f1443ea10361acf804..437ced85b2e4ad48ec97d7186ea54f5d50820764 100644 (file)
@@ -34,6 +34,7 @@
 use back::symbol_export::{self, ExportedSymbols};
 use llvm::{ContextRef, Linkage, ModuleRef, ValueRef, Vector, get_param};
 use llvm;
+use metadata;
 use rustc::hir::def_id::LOCAL_CRATE;
 use middle::lang_items::StartFnLangItem;
 use middle::cstore::EncodedMetadata;
@@ -778,8 +779,7 @@ enum MetadataKind {
     };
     unsafe {
         llvm::LLVMSetInitializer(llglobal, llconst);
-        let section_name =
-            tcx.sess.cstore.metadata_section_name(&tcx.sess.target.target);
+        let section_name = metadata::metadata_section_name(&tcx.sess.target.target);
         let name = CString::new(section_name).unwrap();
         llvm::LLVMSetSection(llglobal, name.as_ptr());
 
index 8e633ee59b67d7696323d460c5d553802927f23c..15a1b32a5fd58c5b413a76e52719bb6d8b71fc76 100644 (file)
@@ -45,6 +45,7 @@
 
 extern crate flate;
 extern crate libc;
+extern crate owning_ref;
 #[macro_use] extern crate rustc;
 extern crate rustc_back;
 extern crate rustc_data_structures;
@@ -70,6 +71,8 @@
 pub use base::trans_crate;
 pub use back::symbol_names::provide;
 
+pub use metadata::LlvmMetadataLoader;
+
 pub mod back {
     pub use rustc::hir::svh;
 
@@ -120,6 +123,7 @@ pub mod back {
 mod glue;
 mod intrinsic;
 mod machine;
+mod metadata;
 mod meth;
 mod mir;
 mod monomorphize;
diff --git a/src/librustc_trans/metadata.rs b/src/librustc_trans/metadata.rs
new file mode 100644 (file)
index 0000000..2c0148d
--- /dev/null
@@ -0,0 +1,122 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use rustc::util::common;
+use rustc::middle::cstore::MetadataLoader;
+use rustc_back::target::Target;
+use llvm;
+use llvm::{False, ObjectFile, mk_section_iter};
+use llvm::archive_ro::ArchiveRO;
+
+use owning_ref::{ErasedBoxRef, OwningRef};
+use std::path::Path;
+use std::ptr;
+use std::slice;
+
+pub const METADATA_FILENAME: &str = "rust.metadata.bin";
+
+pub struct LlvmMetadataLoader;
+
+impl MetadataLoader for LlvmMetadataLoader {
+    fn get_rlib_metadata(&self, _: &Target, filename: &Path) -> Result<ErasedBoxRef<[u8]>, String> {
+        // Use ArchiveRO for speed here, it's backed by LLVM and uses mmap
+        // internally to read the file. We also avoid even using a memcpy by
+        // just keeping the archive along while the metadata is in use.
+        let archive = ArchiveRO::open(filename)
+            .map(|ar| OwningRef::new(box ar))
+            .ok_or_else(|| {
+                            debug!("llvm didn't like `{}`", filename.display());
+                            format!("failed to read rlib metadata: '{}'", filename.display())
+                        })?;
+        let buf: OwningRef<_, [u8]> = archive
+            .try_map(|ar| {
+                ar.iter()
+                    .filter_map(|s| s.ok())
+                    .find(|sect| sect.name() == Some(METADATA_FILENAME))
+                    .map(|s| s.data())
+                    .ok_or_else(|| {
+                                    debug!("didn't find '{}' in the archive", METADATA_FILENAME);
+                                    format!("failed to read rlib metadata: '{}'",
+                                            filename.display())
+                                })
+            })?;
+        Ok(buf.erase_owner())
+    }
+
+    fn get_dylib_metadata(&self,
+                          target: &Target,
+                          filename: &Path)
+                          -> Result<ErasedBoxRef<[u8]>, String> {
+        unsafe {
+            let buf = common::path2cstr(filename);
+            let mb = llvm::LLVMRustCreateMemoryBufferWithContentsOfFile(buf.as_ptr());
+            if mb as isize == 0 {
+                return Err(format!("error reading library: '{}'", filename.display()));
+            }
+            let of = ObjectFile::new(mb)
+                .map(|of| OwningRef::new(box of))
+                .ok_or_else(|| format!("provided path not an object file: '{}'",
+                                        filename.display()))?;
+            let buf = of.try_map(|of| search_meta_section(of, target, filename))?;
+            Ok(buf.erase_owner())
+        }
+    }
+}
+
+fn search_meta_section<'a>(of: &'a ObjectFile,
+                           target: &Target,
+                           filename: &Path)
+                           -> Result<&'a [u8], String> {
+    unsafe {
+        let si = mk_section_iter(of.llof);
+        while llvm::LLVMIsSectionIteratorAtEnd(of.llof, si.llsi) == False {
+            let mut name_buf = ptr::null();
+            let name_len = llvm::LLVMRustGetSectionName(si.llsi, &mut name_buf);
+            let name = slice::from_raw_parts(name_buf as *const u8, name_len as usize).to_vec();
+            let name = String::from_utf8(name).unwrap();
+            debug!("get_metadata_section: name {}", name);
+            if read_metadata_section_name(target) == name {
+                let cbuf = llvm::LLVMGetSectionContents(si.llsi);
+                let csz = llvm::LLVMGetSectionSize(si.llsi) as usize;
+                // The buffer is valid while the object file is around
+                let buf: &'a [u8] = slice::from_raw_parts(cbuf as *const u8, csz);
+                return Ok(buf);
+            }
+            llvm::LLVMMoveToNextSection(si.llsi);
+        }
+    }
+    Err(format!("metadata not found: '{}'", filename.display()))
+}
+
+pub fn metadata_section_name(target: &Target) -> &'static str {
+    // Historical note:
+    //
+    // When using link.exe it was seen that the section name `.note.rustc`
+    // was getting shortened to `.note.ru`, and according to the PE and COFF
+    // specification:
+    //
+    // > Executable images do not use a string table and do not support
+    // > section names longer than 8 characters
+    //
+    // https://msdn.microsoft.com/en-us/library/windows/hardware/gg463119.aspx
+    //
+    // As a result, we choose a slightly shorter name! As to why
+    // `.note.rustc` works on MinGW, that's another good question...
+
+    if target.options.is_like_osx {
+        "__DATA,.rustc"
+    } else {
+        ".rustc"
+    }
+}
+
+fn read_metadata_section_name(_target: &Target) -> &'static str {
+    ".rustc"
+}
index 9e2d85163335c6f066a493070c8b53aa968e2ef0..d41e9931409697b07bed00517353f7b27579b3c1 100644 (file)
@@ -19,6 +19,7 @@
 use rustc::hir::map as hir_map;
 use rustc::lint;
 use rustc::util::nodemap::FxHashMap;
+use rustc_trans;
 use rustc_trans::back::link;
 use rustc_resolve as resolve;
 use rustc_metadata::cstore::CStore;
@@ -138,7 +139,7 @@ pub fn run_core(search_paths: SearchPaths,
 
     let dep_graph = DepGraph::new(false);
     let _ignore = dep_graph.in_ignore();
-    let cstore = Rc::new(CStore::new(&dep_graph));
+    let cstore = Rc::new(CStore::new(&dep_graph, box rustc_trans::LlvmMetadataLoader));
     let mut sess = session::build_session_(
         sessopts, &dep_graph, cpath, diagnostic_handler, codemap, cstore.clone()
     );
index d5237d629cfc1e7f8f40f2a9c3c9b53c6bdb0825..0600ae5b66e7e5b1530025454e245d767e84c484 100644 (file)
@@ -34,6 +34,7 @@
 use rustc_driver::driver::phase_2_configure_and_expand;
 use rustc_metadata::cstore::CStore;
 use rustc_resolve::MakeGlobMap;
+use rustc_trans;
 use rustc_trans::back::link;
 use syntax::ast;
 use syntax::codemap::CodeMap;
@@ -81,7 +82,7 @@ pub fn run(input: &str,
 
     let dep_graph = DepGraph::new(false);
     let _ignore = dep_graph.in_ignore();
-    let cstore = Rc::new(CStore::new(&dep_graph));
+    let cstore = Rc::new(CStore::new(&dep_graph, box rustc_trans::LlvmMetadataLoader));
     let mut sess = session::build_session_(
         sessopts, &dep_graph, Some(input_path.clone()), handler, codemap.clone(), cstore.clone(),
     );
@@ -229,7 +230,7 @@ fn drop(&mut self) {
     let diagnostic_handler = errors::Handler::with_emitter(true, false, box emitter);
 
     let dep_graph = DepGraph::new(false);
-    let cstore = Rc::new(CStore::new(&dep_graph));
+    let cstore = Rc::new(CStore::new(&dep_graph, box rustc_trans::LlvmMetadataLoader));
     let mut sess = session::build_session_(
         sessopts, &dep_graph, None, diagnostic_handler, codemap, cstore.clone(),
     );
index 0336fe277c51f8eb6f064d6e248d1f0d00e26653..74ecdab33725bb2dc9234f150118031c365bc972 100644 (file)
@@ -15,6 +15,7 @@
 extern crate rustc_lint;
 extern crate rustc_metadata;
 extern crate rustc_errors;
+extern crate rustc_trans;
 extern crate syntax;
 
 use rustc::dep_graph::DepGraph;
@@ -58,7 +59,7 @@ fn basic_sess(sysroot: PathBuf) -> (Session, Rc<CStore>) {
 
     let descriptions = Registry::new(&rustc::DIAGNOSTICS);
     let dep_graph = DepGraph::new(opts.build_dep_graph());
-    let cstore = Rc::new(CStore::new(&dep_graph));
+    let cstore = Rc::new(CStore::new(&dep_graph, Box::new(rustc_trans::LlvmMetadataLoader)));
     let sess = build_session(opts, &dep_graph, None, descriptions, cstore.clone());
     rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
     (sess, cstore)