]> git.lizzy.rs Git - rust.git/blobdiff - src/metadata.rs
Rustup to rustc 1.44.0-nightly (1edd389cc 2020-03-23)
[rust.git] / src / metadata.rs
index 29bb1c8e32571d5fbd219999423dfb98fd856a17..cedbff914bfd5dec11cc05bdb8c031875df91f58 100644 (file)
@@ -1,26 +1,34 @@
-use rustc::middle::cstore::MetadataLoader;
-use rustc_data_structures::owning_ref::{self, OwningRef};
+use std::convert::TryFrom;
 use std::fs::File;
 use std::path::Path;
 
+use rustc::middle::cstore::{EncodedMetadata, MetadataLoader};
+use rustc_session::config;
+use rustc::ty::TyCtxt;
+use rustc_codegen_ssa::METADATA_FILENAME;
+use rustc_data_structures::owning_ref::{self, OwningRef};
+use rustc_data_structures::rustc_erase_owner;
+use rustc_target::spec::Target;
+
+use crate::backend::WriteMetadata;
+
 pub struct CraneliftMetadataLoader;
 
 impl MetadataLoader for CraneliftMetadataLoader {
     fn get_rlib_metadata(
         &self,
-        _target: &::rustc_target::spec::Target,
+        _target: &Target,
         path: &Path,
     ) -> Result<owning_ref::ErasedBoxRef<[u8]>, String> {
         let mut archive = ar::Archive::new(File::open(path).map_err(|e| format!("{:?}", e))?);
         // Iterate over all entries in the archive:
         while let Some(entry_result) = archive.next_entry() {
             let mut entry = entry_result.map_err(|e| format!("{:?}", e))?;
-            if entry
-                .header()
-                .identifier()
-                .starts_with(b".rustc.clif_metadata")
-            {
-                let mut buf = Vec::new();
+            if entry.header().identifier() == METADATA_FILENAME.as_bytes() {
+                let mut buf = Vec::with_capacity(
+                    usize::try_from(entry.header().size())
+                        .expect("Rlib metadata file too big to load into memory.")
+                );
                 ::std::io::copy(&mut entry, &mut buf).map_err(|e| format!("{:?}", e))?;
                 let buf: OwningRef<Vec<u8>, [u8]> = OwningRef::new(buf).into();
                 return Ok(rustc_erase_owner!(buf.map_owner_box()));
@@ -33,29 +41,71 @@ fn get_rlib_metadata(
 
     fn get_dylib_metadata(
         &self,
-        _target: &::rustc_target::spec::Target,
-        _path: &Path,
+        _target: &Target,
+        path: &Path,
     ) -> Result<owning_ref::ErasedBoxRef<[u8]>, String> {
-        //use goblin::Object;
-
-        //let buffer = ::std::fs::read(path).map_err(|e|format!("{:?}", e))?;
-        /*match Object::parse(&buffer).map_err(|e|format!("{:?}", e))? {
-            Object::Elf(elf) => {
-                println!("elf: {:#?}", &elf);
-            },
-            Object::PE(pe) => {
-                println!("pe: {:#?}", &pe);
-            },
-            Object::Mach(mach) => {
-                println!("mach: {:#?}", &mach);
-            },
-            Object::Archive(archive) => {
-                return Err(format!("archive: {:#?}", &archive));
-            },
-            Object::Unknown(magic) => {
-                return Err(format!("unknown magic: {:#x}", magic))
-            }
-        }*/
-        Err("dylib metadata loading is not yet supported".to_string())
+        use object::Object;
+        let file = std::fs::read(path).map_err(|e| format!("read:{:?}", e))?;
+        let file = object::File::parse(&file).map_err(|e| format!("parse: {:?}", e))?;
+        let buf = file
+            .section_data_by_name(".rustc")
+            .ok_or("no .rustc section")?
+            .into_owned();
+        let buf: OwningRef<Vec<u8>, [u8]> = OwningRef::new(buf).into();
+        Ok(rustc_erase_owner!(buf.map_owner_box()))
+    }
+}
+
+// Adapted from https://github.com/rust-lang/rust/blob/da573206f87b5510de4b0ee1a9c044127e409bd3/src/librustc_codegen_llvm/base.rs#L47-L112
+pub fn write_metadata<P: WriteMetadata>(tcx: TyCtxt<'_>, product: &mut P) -> EncodedMetadata {
+    use flate2::write::DeflateEncoder;
+    use flate2::Compression;
+    use std::io::Write;
+
+    #[derive(PartialEq, Eq, PartialOrd, Ord)]
+    enum MetadataKind {
+        None,
+        Uncompressed,
+        Compressed,
     }
+
+    let kind = tcx
+        .sess
+        .crate_types
+        .borrow()
+        .iter()
+        .map(|ty| match *ty {
+            config::CrateType::Executable
+            | config::CrateType::Staticlib
+            | config::CrateType::Cdylib => MetadataKind::None,
+
+            config::CrateType::Rlib => MetadataKind::Uncompressed,
+
+            config::CrateType::Dylib | config::CrateType::ProcMacro => MetadataKind::Compressed,
+        })
+        .max()
+        .unwrap_or(MetadataKind::None);
+
+    if kind == MetadataKind::None {
+        return EncodedMetadata::new();
+    }
+
+    let metadata = tcx.encode_metadata();
+    if kind == MetadataKind::Uncompressed {
+        return metadata;
+    }
+
+    assert!(kind == MetadataKind::Compressed);
+    let mut compressed = tcx.metadata_encoding_version();
+    DeflateEncoder::new(&mut compressed, Compression::fast())
+        .write_all(&metadata.raw_data)
+        .unwrap();
+
+    product.add_rustc_section(
+        rustc::middle::exported_symbols::metadata_symbol_name(tcx),
+        compressed,
+        tcx.sess.target.target.options.is_like_osx,
+    );
+
+    metadata
 }