about summary refs log tree commit diff
path: root/compiler/rustc_codegen_cranelift/src
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_codegen_cranelift/src')
-rw-r--r--compiler/rustc_codegen_cranelift/src/archive.rs74
-rw-r--r--compiler/rustc_codegen_cranelift/src/backend.rs152
-rw-r--r--compiler/rustc_codegen_cranelift/src/bin/cg_clif.rs3
-rw-r--r--compiler/rustc_codegen_cranelift/src/bin/cg_clif_build_sysroot.rs4
-rw-r--r--compiler/rustc_codegen_cranelift/src/debuginfo/emit.rs6
-rw-r--r--compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs1
-rw-r--r--compiler/rustc_codegen_cranelift/src/debuginfo/object.rs85
-rw-r--r--compiler/rustc_codegen_cranelift/src/debuginfo/unwind.rs5
-rw-r--r--compiler/rustc_codegen_cranelift/src/driver/aot.rs23
-rw-r--r--compiler/rustc_codegen_cranelift/src/lib.rs4
-rw-r--r--compiler/rustc_codegen_cranelift/src/metadata.rs68
11 files changed, 215 insertions, 210 deletions
diff --git a/compiler/rustc_codegen_cranelift/src/archive.rs b/compiler/rustc_codegen_cranelift/src/archive.rs
index 0fa228fc944..8a1f6543990 100644
--- a/compiler/rustc_codegen_cranelift/src/archive.rs
+++ b/compiler/rustc_codegen_cranelift/src/archive.rs
@@ -1,17 +1,20 @@
 //! Creation of ar archives like for the lib and staticlib crate type
 
 use std::collections::BTreeMap;
+use std::convert::TryFrom;
 use std::fs::File;
+use std::io::{self, Read, Seek};
 use std::path::{Path, PathBuf};
 
 use rustc_codegen_ssa::back::archive::ArchiveBuilder;
 use rustc_session::Session;
 
-use object::{Object, ObjectSymbol, SymbolKind};
+use object::read::archive::ArchiveFile;
+use object::{Object, ObjectSymbol, ReadCache, SymbolKind};
 
 #[derive(Debug)]
 enum ArchiveEntry {
-    FromArchive { archive_index: usize, entry_index: usize },
+    FromArchive { archive_index: usize, file_range: (u64, u64) },
     File(PathBuf),
 }
 
@@ -21,29 +24,28 @@ pub(crate) struct ArArchiveBuilder<'a> {
     use_gnu_style_archive: bool,
     no_builtin_ranlib: bool,
 
-    src_archives: Vec<(PathBuf, ar::Archive<File>)>,
+    src_archives: Vec<File>,
     // Don't use `HashMap` here, as the order is important. `rust.metadata.bin` must always be at
     // the end of an archive for linkers to not get confused.
-    entries: Vec<(String, ArchiveEntry)>,
+    entries: Vec<(Vec<u8>, ArchiveEntry)>,
 }
 
 impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
     fn new(sess: &'a Session, output: &Path, input: Option<&Path>) -> Self {
         let (src_archives, entries) = if let Some(input) = input {
-            let mut archive = ar::Archive::new(File::open(input).unwrap());
+            let read_cache = ReadCache::new(File::open(input).unwrap());
+            let archive = ArchiveFile::parse(&read_cache).unwrap();
             let mut entries = Vec::new();
 
-            let mut i = 0;
-            while let Some(entry) = archive.next_entry() {
+            for entry in archive.members() {
                 let entry = entry.unwrap();
                 entries.push((
-                    String::from_utf8(entry.header().identifier().to_vec()).unwrap(),
-                    ArchiveEntry::FromArchive { archive_index: 0, entry_index: i },
+                    entry.name().to_vec(),
+                    ArchiveEntry::FromArchive { archive_index: 0, file_range: entry.file_range() },
                 ));
-                i += 1;
             }
 
-            (vec![(input.to_owned(), archive)], entries)
+            (vec![read_cache.into_inner()], entries)
         } else {
             (vec![], Vec::new())
         };
@@ -61,21 +63,21 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
     }
 
     fn src_files(&mut self) -> Vec<String> {
-        self.entries.iter().map(|(name, _)| name.clone()).collect()
+        self.entries.iter().map(|(name, _)| String::from_utf8(name.clone()).unwrap()).collect()
     }
 
     fn remove_file(&mut self, name: &str) {
         let index = self
             .entries
             .iter()
-            .position(|(entry_name, _)| entry_name == name)
+            .position(|(entry_name, _)| entry_name == name.as_bytes())
             .expect("Tried to remove file not existing in src archive");
         self.entries.remove(index);
     }
 
     fn add_file(&mut self, file: &Path) {
         self.entries.push((
-            file.file_name().unwrap().to_str().unwrap().to_string(),
+            file.file_name().unwrap().to_str().unwrap().to_string().into_bytes(),
             ArchiveEntry::File(file.to_owned()),
         ));
     }
@@ -84,22 +86,23 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
     where
         F: FnMut(&str) -> bool + 'static,
     {
-        let mut archive = ar::Archive::new(std::fs::File::open(&archive_path)?);
+        let read_cache = ReadCache::new(std::fs::File::open(&archive_path)?);
+        let archive = ArchiveFile::parse(&read_cache).unwrap();
         let archive_index = self.src_archives.len();
 
-        let mut i = 0;
-        while let Some(entry) = archive.next_entry() {
-            let entry = entry?;
-            let file_name = String::from_utf8(entry.header().identifier().to_vec())
-                .map_err(|err| std::io::Error::new(std::io::ErrorKind::InvalidData, err))?;
+        for entry in archive.members() {
+            let entry = entry.map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?;
+            let file_name = String::from_utf8(entry.name().to_vec())
+                .map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?;
             if !skip(&file_name) {
-                self.entries
-                    .push((file_name, ArchiveEntry::FromArchive { archive_index, entry_index: i }));
+                self.entries.push((
+                    file_name.into_bytes(),
+                    ArchiveEntry::FromArchive { archive_index, file_range: entry.file_range() },
+                ));
             }
-            i += 1;
         }
 
-        self.src_archives.push((archive_path.to_owned(), archive));
+        self.src_archives.push(read_cache.into_inner());
         Ok(())
     }
 
@@ -121,14 +124,14 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
             // FIXME only read the symbol table of the object files to avoid having to keep all
             // object files in memory at once, or read them twice.
             let data = match entry {
-                ArchiveEntry::FromArchive { archive_index, entry_index } => {
+                ArchiveEntry::FromArchive { archive_index, file_range } => {
                     // FIXME read symbols from symtab
-                    use std::io::Read;
-                    let (ref _src_archive_path, ref mut src_archive) =
-                        self.src_archives[archive_index];
-                    let mut entry = src_archive.jump_to_entry(entry_index).unwrap();
-                    let mut data = Vec::new();
-                    entry.read_to_end(&mut data).unwrap();
+                    let src_read_cache = &mut self.src_archives[archive_index];
+
+                    src_read_cache.seek(io::SeekFrom::Start(file_range.0)).unwrap();
+                    let mut data = std::vec::from_elem(0, usize::try_from(file_range.1).unwrap());
+                    src_read_cache.read_exact(&mut data).unwrap();
+
                     data
                 }
                 ArchiveEntry::File(file) => std::fs::read(file).unwrap_or_else(|err| {
@@ -143,7 +146,7 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
                 match object::File::parse(&*data) {
                     Ok(object) => {
                         symbol_table.insert(
-                            entry_name.as_bytes().to_vec(),
+                            entry_name.to_vec(),
                             object
                                 .symbols()
                                 .filter_map(|symbol| {
@@ -168,7 +171,8 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
                         } else {
                             sess.fatal(&format!(
                                 "error parsing `{}` during archive creation: {}",
-                                entry_name, err
+                                String::from_utf8_lossy(&entry_name),
+                                err
                             ));
                         }
                     }
@@ -187,7 +191,7 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
                             err
                         ));
                     }),
-                    entries.iter().map(|(name, _)| name.as_bytes().to_vec()).collect(),
+                    entries.iter().map(|(name, _)| name.clone()).collect(),
                     ar::GnuSymbolTableFormat::Size32,
                     symbol_table,
                 )
@@ -210,7 +214,7 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
 
         // Add all files
         for (entry_name, data) in entries.into_iter() {
-            let header = ar::Header::new(entry_name.into_bytes(), data.len() as u64);
+            let header = ar::Header::new(entry_name, data.len() as u64);
             match builder {
                 BuilderKind::Bsd(ref mut builder) => builder.append(&header, &mut &*data).unwrap(),
                 BuilderKind::Gnu(ref mut builder) => builder.append(&header, &mut &*data).unwrap(),
diff --git a/compiler/rustc_codegen_cranelift/src/backend.rs b/compiler/rustc_codegen_cranelift/src/backend.rs
deleted file mode 100644
index 05c06bac27d..00000000000
--- a/compiler/rustc_codegen_cranelift/src/backend.rs
+++ /dev/null
@@ -1,152 +0,0 @@
-//! Abstraction around the object writing crate
-
-use std::convert::{TryFrom, TryInto};
-
-use rustc_data_structures::fx::FxHashMap;
-use rustc_session::Session;
-
-use cranelift_codegen::isa::TargetIsa;
-use cranelift_module::FuncId;
-use cranelift_object::{ObjectBuilder, ObjectModule, ObjectProduct};
-
-use object::write::*;
-use object::{RelocationEncoding, SectionKind, SymbolFlags};
-
-use gimli::SectionId;
-
-use crate::debuginfo::{DebugReloc, DebugRelocName};
-
-pub(crate) trait WriteMetadata {
-    fn add_rustc_section(&mut self, symbol_name: String, data: Vec<u8>);
-}
-
-impl WriteMetadata for object::write::Object {
-    fn add_rustc_section(&mut self, symbol_name: String, data: Vec<u8>) {
-        let segment = self.segment_name(object::write::StandardSegment::Data).to_vec();
-        let section_id = self.add_section(segment, b".rustc".to_vec(), object::SectionKind::Data);
-        let offset = self.append_section_data(section_id, &data, 1);
-        // For MachO and probably PE this is necessary to prevent the linker from throwing away the
-        // .rustc section. For ELF this isn't necessary, but it also doesn't harm.
-        self.add_symbol(object::write::Symbol {
-            name: symbol_name.into_bytes(),
-            value: offset,
-            size: data.len() as u64,
-            kind: object::SymbolKind::Data,
-            scope: object::SymbolScope::Dynamic,
-            weak: false,
-            section: SymbolSection::Section(section_id),
-            flags: SymbolFlags::None,
-        });
-    }
-}
-
-pub(crate) trait WriteDebugInfo {
-    type SectionId: Copy;
-
-    fn add_debug_section(&mut self, name: SectionId, data: Vec<u8>) -> Self::SectionId;
-    fn add_debug_reloc(
-        &mut self,
-        section_map: &FxHashMap<SectionId, Self::SectionId>,
-        from: &Self::SectionId,
-        reloc: &DebugReloc,
-    );
-}
-
-impl WriteDebugInfo for ObjectProduct {
-    type SectionId = (object::write::SectionId, object::write::SymbolId);
-
-    fn add_debug_section(
-        &mut self,
-        id: SectionId,
-        data: Vec<u8>,
-    ) -> (object::write::SectionId, object::write::SymbolId) {
-        let name = if self.object.format() == object::BinaryFormat::MachO {
-            id.name().replace('.', "__") // machO expects __debug_info instead of .debug_info
-        } else {
-            id.name().to_string()
-        }
-        .into_bytes();
-
-        let segment = self.object.segment_name(StandardSegment::Debug).to_vec();
-        // FIXME use SHT_X86_64_UNWIND for .eh_frame
-        let section_id = self.object.add_section(
-            segment,
-            name,
-            if id == SectionId::EhFrame { SectionKind::ReadOnlyData } else { SectionKind::Debug },
-        );
-        self.object
-            .section_mut(section_id)
-            .set_data(data, if id == SectionId::EhFrame { 8 } else { 1 });
-        let symbol_id = self.object.section_symbol(section_id);
-        (section_id, symbol_id)
-    }
-
-    fn add_debug_reloc(
-        &mut self,
-        section_map: &FxHashMap<SectionId, Self::SectionId>,
-        from: &Self::SectionId,
-        reloc: &DebugReloc,
-    ) {
-        let (symbol, symbol_offset) = match reloc.name {
-            DebugRelocName::Section(id) => (section_map.get(&id).unwrap().1, 0),
-            DebugRelocName::Symbol(id) => {
-                let symbol_id = self.function_symbol(FuncId::from_u32(id.try_into().unwrap()));
-                self.object
-                    .symbol_section_and_offset(symbol_id)
-                    .expect("Debug reloc for undef sym???")
-            }
-        };
-        self.object
-            .add_relocation(
-                from.0,
-                Relocation {
-                    offset: u64::from(reloc.offset),
-                    symbol,
-                    kind: reloc.kind,
-                    encoding: RelocationEncoding::Generic,
-                    size: reloc.size * 8,
-                    addend: i64::try_from(symbol_offset).unwrap() + reloc.addend,
-                },
-            )
-            .unwrap();
-    }
-}
-
-pub(crate) fn with_object(sess: &Session, name: &str, f: impl FnOnce(&mut Object)) -> Vec<u8> {
-    let triple = crate::target_triple(sess);
-
-    let binary_format = match triple.binary_format {
-        target_lexicon::BinaryFormat::Elf => object::BinaryFormat::Elf,
-        target_lexicon::BinaryFormat::Coff => object::BinaryFormat::Coff,
-        target_lexicon::BinaryFormat::Macho => object::BinaryFormat::MachO,
-        binary_format => sess.fatal(&format!("binary format {} is unsupported", binary_format)),
-    };
-    let architecture = match triple.architecture {
-        target_lexicon::Architecture::X86_32(_) => object::Architecture::I386,
-        target_lexicon::Architecture::X86_64 => object::Architecture::X86_64,
-        target_lexicon::Architecture::Arm(_) => object::Architecture::Arm,
-        target_lexicon::Architecture::Aarch64(_) => object::Architecture::Aarch64,
-        architecture => {
-            sess.fatal(&format!("target architecture {:?} is unsupported", architecture,))
-        }
-    };
-    let endian = match triple.endianness().unwrap() {
-        target_lexicon::Endianness::Little => object::Endianness::Little,
-        target_lexicon::Endianness::Big => object::Endianness::Big,
-    };
-
-    let mut metadata_object = object::write::Object::new(binary_format, architecture, endian);
-    metadata_object.add_file_symbol(name.as_bytes().to_vec());
-    f(&mut metadata_object);
-    metadata_object.write().unwrap()
-}
-
-pub(crate) fn make_module(sess: &Session, isa: Box<dyn TargetIsa>, name: String) -> ObjectModule {
-    let mut builder =
-        ObjectBuilder::new(isa, name + ".o", cranelift_module::default_libcall_names()).unwrap();
-    // Unlike cg_llvm, cg_clif defaults to disabling -Zfunction-sections. For cg_llvm binary size
-    // is important, while cg_clif cares more about compilation times. Enabling -Zfunction-sections
-    // can easily double the amount of time necessary to perform linking.
-    builder.per_function_section(sess.opts.debugging_opts.function_sections.unwrap_or(false));
-    ObjectModule::new(builder)
-}
diff --git a/compiler/rustc_codegen_cranelift/src/bin/cg_clif.rs b/compiler/rustc_codegen_cranelift/src/bin/cg_clif.rs
index a044b43b864..b924f2085a0 100644
--- a/compiler/rustc_codegen_cranelift/src/bin/cg_clif.rs
+++ b/compiler/rustc_codegen_cranelift/src/bin/cg_clif.rs
@@ -1,4 +1,7 @@
 #![feature(rustc_private, once_cell)]
+#![warn(rust_2018_idioms)]
+#![warn(unused_lifetimes)]
+#![warn(unreachable_pub)]
 
 extern crate rustc_data_structures;
 extern crate rustc_driver;
diff --git a/compiler/rustc_codegen_cranelift/src/bin/cg_clif_build_sysroot.rs b/compiler/rustc_codegen_cranelift/src/bin/cg_clif_build_sysroot.rs
index e7cd5edbbf6..bde4d71b9a3 100644
--- a/compiler/rustc_codegen_cranelift/src/bin/cg_clif_build_sysroot.rs
+++ b/compiler/rustc_codegen_cranelift/src/bin/cg_clif_build_sysroot.rs
@@ -7,8 +7,10 @@
 //! target crates.
 
 #![feature(rustc_private)]
+#![warn(rust_2018_idioms)]
+#![warn(unused_lifetimes)]
+#![warn(unreachable_pub)]
 
-extern crate rustc_data_structures;
 extern crate rustc_driver;
 extern crate rustc_interface;
 extern crate rustc_session;
diff --git a/compiler/rustc_codegen_cranelift/src/debuginfo/emit.rs b/compiler/rustc_codegen_cranelift/src/debuginfo/emit.rs
index fb6ccd7c535..c8c2d50b034 100644
--- a/compiler/rustc_codegen_cranelift/src/debuginfo/emit.rs
+++ b/compiler/rustc_codegen_cranelift/src/debuginfo/emit.rs
@@ -1,16 +1,16 @@
 //! Write the debuginfo into an object file.
 
+use cranelift_object::ObjectProduct;
 use rustc_data_structures::fx::FxHashMap;
 
 use gimli::write::{Address, AttributeValue, EndianVec, Result, Sections, Writer};
 use gimli::{RunTimeEndian, SectionId};
 
-use crate::backend::WriteDebugInfo;
-
+use super::object::WriteDebugInfo;
 use super::DebugContext;
 
 impl DebugContext<'_> {
-    pub(crate) fn emit<P: WriteDebugInfo>(&mut self, product: &mut P) {
+    pub(crate) fn emit(&mut self, product: &mut ObjectProduct) {
         let unit_range_list_id = self.dwarf.unit.ranges.add(self.unit_range_list.clone());
         let root = self.dwarf.unit.root();
         let root = self.dwarf.unit.get_mut(root);
diff --git a/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs b/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs
index cabe3e43b34..6d172817cb1 100644
--- a/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs
+++ b/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs
@@ -2,6 +2,7 @@
 
 mod emit;
 mod line_info;
+mod object;
 mod unwind;
 
 use crate::prelude::*;
diff --git a/compiler/rustc_codegen_cranelift/src/debuginfo/object.rs b/compiler/rustc_codegen_cranelift/src/debuginfo/object.rs
new file mode 100644
index 00000000000..9984dc92c44
--- /dev/null
+++ b/compiler/rustc_codegen_cranelift/src/debuginfo/object.rs
@@ -0,0 +1,85 @@
+use std::convert::{TryFrom, TryInto};
+
+use rustc_data_structures::fx::FxHashMap;
+
+use cranelift_module::FuncId;
+use cranelift_object::ObjectProduct;
+
+use object::write::{Relocation, StandardSegment};
+use object::{RelocationEncoding, SectionKind};
+
+use gimli::SectionId;
+
+use crate::debuginfo::{DebugReloc, DebugRelocName};
+
+pub(super) trait WriteDebugInfo {
+    type SectionId: Copy;
+
+    fn add_debug_section(&mut self, name: SectionId, data: Vec<u8>) -> Self::SectionId;
+    fn add_debug_reloc(
+        &mut self,
+        section_map: &FxHashMap<SectionId, Self::SectionId>,
+        from: &Self::SectionId,
+        reloc: &DebugReloc,
+    );
+}
+
+impl WriteDebugInfo for ObjectProduct {
+    type SectionId = (object::write::SectionId, object::write::SymbolId);
+
+    fn add_debug_section(
+        &mut self,
+        id: SectionId,
+        data: Vec<u8>,
+    ) -> (object::write::SectionId, object::write::SymbolId) {
+        let name = if self.object.format() == object::BinaryFormat::MachO {
+            id.name().replace('.', "__") // machO expects __debug_info instead of .debug_info
+        } else {
+            id.name().to_string()
+        }
+        .into_bytes();
+
+        let segment = self.object.segment_name(StandardSegment::Debug).to_vec();
+        // FIXME use SHT_X86_64_UNWIND for .eh_frame
+        let section_id = self.object.add_section(
+            segment,
+            name,
+            if id == SectionId::EhFrame { SectionKind::ReadOnlyData } else { SectionKind::Debug },
+        );
+        self.object
+            .section_mut(section_id)
+            .set_data(data, if id == SectionId::EhFrame { 8 } else { 1 });
+        let symbol_id = self.object.section_symbol(section_id);
+        (section_id, symbol_id)
+    }
+
+    fn add_debug_reloc(
+        &mut self,
+        section_map: &FxHashMap<SectionId, Self::SectionId>,
+        from: &Self::SectionId,
+        reloc: &DebugReloc,
+    ) {
+        let (symbol, symbol_offset) = match reloc.name {
+            DebugRelocName::Section(id) => (section_map.get(&id).unwrap().1, 0),
+            DebugRelocName::Symbol(id) => {
+                let symbol_id = self.function_symbol(FuncId::from_u32(id.try_into().unwrap()));
+                self.object
+                    .symbol_section_and_offset(symbol_id)
+                    .expect("Debug reloc for undef sym???")
+            }
+        };
+        self.object
+            .add_relocation(
+                from.0,
+                Relocation {
+                    offset: u64::from(reloc.offset),
+                    symbol,
+                    kind: reloc.kind,
+                    encoding: RelocationEncoding::Generic,
+                    size: reloc.size * 8,
+                    addend: i64::try_from(symbol_offset).unwrap() + reloc.addend,
+                },
+            )
+            .unwrap();
+    }
+}
diff --git a/compiler/rustc_codegen_cranelift/src/debuginfo/unwind.rs b/compiler/rustc_codegen_cranelift/src/debuginfo/unwind.rs
index d1251e749f3..f0896ea0e16 100644
--- a/compiler/rustc_codegen_cranelift/src/debuginfo/unwind.rs
+++ b/compiler/rustc_codegen_cranelift/src/debuginfo/unwind.rs
@@ -4,10 +4,11 @@ use crate::prelude::*;
 
 use cranelift_codegen::isa::{unwind::UnwindInfo, TargetIsa};
 
+use cranelift_object::ObjectProduct;
 use gimli::write::{Address, CieId, EhFrame, FrameTable, Section};
 use gimli::RunTimeEndian;
 
-use crate::backend::WriteDebugInfo;
+use super::object::WriteDebugInfo;
 
 pub(crate) struct UnwindContext {
     endian: RunTimeEndian,
@@ -55,7 +56,7 @@ impl UnwindContext {
         }
     }
 
-    pub(crate) fn emit<P: WriteDebugInfo>(self, product: &mut P) {
+    pub(crate) fn emit(self, product: &mut ObjectProduct) {
         let mut eh_frame = EhFrame::from(super::emit::WriterRelocate::new(self.endian));
         self.frame_table.write_eh_frame(&mut eh_frame).unwrap();
 
diff --git a/compiler/rustc_codegen_cranelift/src/driver/aot.rs b/compiler/rustc_codegen_cranelift/src/driver/aot.rs
index 3de706ed6d7..40cbc5e1a7e 100644
--- a/compiler/rustc_codegen_cranelift/src/driver/aot.rs
+++ b/compiler/rustc_codegen_cranelift/src/driver/aot.rs
@@ -11,8 +11,10 @@ use rustc_middle::middle::cstore::EncodedMetadata;
 use rustc_middle::mir::mono::{CodegenUnit, MonoItem};
 use rustc_session::cgu_reuse_tracker::CguReuse;
 use rustc_session::config::{DebugInfo, OutputType};
+use rustc_session::Session;
 
-use cranelift_object::ObjectModule;
+use cranelift_codegen::isa::TargetIsa;
+use cranelift_object::{ObjectBuilder, ObjectModule};
 
 use crate::{prelude::*, BackendConfig};
 
@@ -24,6 +26,16 @@ impl<HCX> HashStable<HCX> for ModuleCodegenResult {
     }
 }
 
+fn make_module(sess: &Session, isa: Box<dyn TargetIsa>, name: String) -> ObjectModule {
+    let mut builder =
+        ObjectBuilder::new(isa, name + ".o", cranelift_module::default_libcall_names()).unwrap();
+    // Unlike cg_llvm, cg_clif defaults to disabling -Zfunction-sections. For cg_llvm binary size
+    // is important, while cg_clif cares more about compilation times. Enabling -Zfunction-sections
+    // can easily double the amount of time necessary to perform linking.
+    builder.per_function_section(sess.opts.debugging_opts.function_sections.unwrap_or(false));
+    ObjectModule::new(builder)
+}
+
 fn emit_module(
     tcx: TyCtxt<'_>,
     backend_config: &BackendConfig,
@@ -104,7 +116,7 @@ fn module_codegen(
     let mono_items = cgu.items_in_deterministic_order(tcx);
 
     let isa = crate::build_isa(tcx.sess, &backend_config);
-    let mut module = crate::backend::make_module(tcx.sess, isa, cgu_name.as_str().to_string());
+    let mut module = make_module(tcx.sess, isa, cgu_name.as_str().to_string());
 
     let mut cx = crate::CodegenCx::new(
         tcx,
@@ -227,8 +239,7 @@ pub(crate) fn run_aot(
     tcx.sess.abort_if_errors();
 
     let isa = crate::build_isa(tcx.sess, &backend_config);
-    let mut allocator_module =
-        crate::backend::make_module(tcx.sess, isa, "allocator_shim".to_string());
+    let mut allocator_module = make_module(tcx.sess, isa, "allocator_shim".to_string());
     assert_eq!(pointer_ty(tcx), allocator_module.target_config().pointer_type());
     let mut allocator_unwind_context = UnwindContext::new(tcx, allocator_module.isa(), true);
     let created_alloc_shim =
@@ -266,9 +277,7 @@ pub(crate) fn run_aot(
             let tmp_file =
                 tcx.output_filenames(()).temp_path(OutputType::Metadata, Some(&metadata_cgu_name));
 
-            let obj = crate::backend::with_object(tcx.sess, &metadata_cgu_name, |object| {
-                crate::metadata::write_metadata(tcx, object);
-            });
+            let obj = crate::metadata::new_metadata_object(tcx, &metadata_cgu_name, &metadata);
 
             if let Err(err) = std::fs::write(&tmp_file, obj) {
                 tcx.sess.fatal(&format!("error writing metadata object file: {}", err));
diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs
index 87193e3ef53..2ceccdd3499 100644
--- a/compiler/rustc_codegen_cranelift/src/lib.rs
+++ b/compiler/rustc_codegen_cranelift/src/lib.rs
@@ -1,4 +1,5 @@
-#![feature(rustc_private, decl_macro, never_type, hash_drain_filter, vec_into_raw_parts, once_cell)]
+#![feature(rustc_private, decl_macro)]
+#![cfg_attr(feature = "jit", feature(never_type, vec_into_raw_parts, once_cell))]
 #![warn(rust_2018_idioms)]
 #![warn(unused_lifetimes)]
 #![warn(unreachable_pub)]
@@ -44,7 +45,6 @@ mod abi;
 mod allocator;
 mod analyze;
 mod archive;
-mod backend;
 mod base;
 mod cast;
 mod codegen_i128;
diff --git a/compiler/rustc_codegen_cranelift/src/metadata.rs b/compiler/rustc_codegen_cranelift/src/metadata.rs
index db24bf65eb5..9afa999a87d 100644
--- a/compiler/rustc_codegen_cranelift/src/metadata.rs
+++ b/compiler/rustc_codegen_cranelift/src/metadata.rs
@@ -1,20 +1,72 @@
 //! Writing of the rustc metadata for dylibs
 
-use rustc_middle::ty::TyCtxt;
+use object::write::{Object, StandardSegment, Symbol, SymbolSection};
+use object::{SectionKind, SymbolFlags, SymbolKind, SymbolScope};
 
-use crate::backend::WriteMetadata;
+use rustc_middle::middle::cstore::EncodedMetadata;
+use rustc_middle::ty::TyCtxt;
 
 // Adapted from https://github.com/rust-lang/rust/blob/da573206f87b5510de4b0ee1a9c044127e409bd3/src/librustc_codegen_llvm/base.rs#L47-L112
-pub(crate) fn write_metadata<O: WriteMetadata>(tcx: TyCtxt<'_>, object: &mut O) {
+pub(crate) fn new_metadata_object(tcx: TyCtxt<'_>, cgu_name: &str, metadata: &EncodedMetadata) -> Vec<u8> {
     use snap::write::FrameEncoder;
     use std::io::Write;
 
-    let metadata = tcx.encode_metadata();
     let mut compressed = rustc_metadata::METADATA_HEADER.to_vec();
     FrameEncoder::new(&mut compressed).write_all(&metadata.raw_data).unwrap();
 
-    object.add_rustc_section(
-        rustc_middle::middle::exported_symbols::metadata_symbol_name(tcx),
-        compressed,
-    );
+    let triple = crate::target_triple(tcx.sess);
+
+    let binary_format = match triple.binary_format {
+        target_lexicon::BinaryFormat::Elf => object::BinaryFormat::Elf,
+        target_lexicon::BinaryFormat::Coff => object::BinaryFormat::Coff,
+        target_lexicon::BinaryFormat::Macho => object::BinaryFormat::MachO,
+        binary_format => tcx.sess.fatal(&format!("binary format {} is unsupported", binary_format)),
+    };
+    let architecture = match triple.architecture {
+        target_lexicon::Architecture::Aarch64(_) => object::Architecture::Aarch64,
+        target_lexicon::Architecture::Arm(_) => object::Architecture::Arm,
+        target_lexicon::Architecture::Avr => object::Architecture::Avr,
+        target_lexicon::Architecture::Hexagon => object::Architecture::Hexagon,
+        target_lexicon::Architecture::Mips32(_) => object::Architecture::Mips,
+        target_lexicon::Architecture::Mips64(_) => object::Architecture::Mips64,
+        target_lexicon::Architecture::Msp430 => object::Architecture::Msp430,
+        target_lexicon::Architecture::Powerpc => object::Architecture::PowerPc,
+        target_lexicon::Architecture::Powerpc64 => object::Architecture::PowerPc64,
+        target_lexicon::Architecture::Powerpc64le => todo!(),
+        target_lexicon::Architecture::Riscv32(_) => object::Architecture::Riscv32,
+        target_lexicon::Architecture::Riscv64(_) => object::Architecture::Riscv64,
+        target_lexicon::Architecture::S390x => object::Architecture::S390x,
+        target_lexicon::Architecture::Sparc64 => object::Architecture::Sparc64,
+        target_lexicon::Architecture::Sparcv9 => object::Architecture::Sparc64,
+        target_lexicon::Architecture::X86_32(_) => object::Architecture::I386,
+        target_lexicon::Architecture::X86_64 => object::Architecture::X86_64,
+        architecture => {
+            tcx.sess.fatal(&format!("target architecture {:?} is unsupported", architecture,))
+        }
+    };
+    let endian = match triple.endianness().unwrap() {
+        target_lexicon::Endianness::Little => object::Endianness::Little,
+        target_lexicon::Endianness::Big => object::Endianness::Big,
+    };
+
+    let mut object = Object::new(binary_format, architecture, endian);
+    object.add_file_symbol(cgu_name.as_bytes().to_vec());
+
+    let segment = object.segment_name(StandardSegment::Data).to_vec();
+    let section_id = object.add_section(segment, b".rustc".to_vec(), SectionKind::Data);
+    let offset = object.append_section_data(section_id, &compressed, 1);
+    // For MachO and probably PE this is necessary to prevent the linker from throwing away the
+    // .rustc section. For ELF this isn't necessary, but it also doesn't harm.
+    object.add_symbol(Symbol {
+        name: rustc_middle::middle::exported_symbols::metadata_symbol_name(tcx).into_bytes(),
+        value: offset,
+        size: compressed.len() as u64,
+        kind: SymbolKind::Data,
+        scope: SymbolScope::Dynamic,
+        weak: false,
+        section: SymbolSection::Section(section_id),
+        flags: SymbolFlags::None,
+    });
+
+    object.write().unwrap()
 }