about summary refs log tree commit diff
path: root/src/librustc_codegen_llvm
diff options
context:
space:
mode:
authorDenis Merigoux <denis.merigoux@gmail.com>2018-09-25 17:52:03 +0200
committerEduard-Mihai Burtescu <edy.burt@gmail.com>2018-11-16 14:36:43 +0200
commit8d530db2c5e63da2fed3ec1ac3bba2fa0fb4363c (patch)
treef60326e943c6dd42e3bc9deb7778b197936f9473 /src/librustc_codegen_llvm
parent97825a36bec3bdad71669834178a85d7fdff43bc (diff)
downloadrust-8d530db2c5e63da2fed3ec1ac3bba2fa0fb4363c.tar.gz
rust-8d530db2c5e63da2fed3ec1ac3bba2fa0fb4363c.zip
Generalized base:codegen_crate
Diffstat (limited to 'src/librustc_codegen_llvm')
-rw-r--r--src/librustc_codegen_llvm/back/lto.rs15
-rw-r--r--src/librustc_codegen_llvm/back/write.rs22
-rw-r--r--src/librustc_codegen_llvm/base.rs80
-rw-r--r--src/librustc_codegen_llvm/interfaces/backend.rs40
-rw-r--r--src/librustc_codegen_llvm/interfaces/mod.rs2
-rw-r--r--src/librustc_codegen_llvm/lib.rs67
6 files changed, 160 insertions, 66 deletions
diff --git a/src/librustc_codegen_llvm/back/lto.rs b/src/librustc_codegen_llvm/back/lto.rs
index 60b06c579cb..5eb2e28a2a8 100644
--- a/src/librustc_codegen_llvm/back/lto.rs
+++ b/src/librustc_codegen_llvm/back/lto.rs
@@ -13,8 +13,7 @@ use back::write::{ModuleConfig, with_llvm_pmb, CodegenContext};
 use back::write::{self, DiagnosticHandlers, pre_lto_bitcode_filename};
 use errors::{FatalError, Handler};
 use llvm::archive_ro::ArchiveRO;
-use llvm::{True, False};
-use llvm;
+use llvm::{self, True, False};
 use memmap;
 use rustc::dep_graph::WorkProduct;
 use rustc::dep_graph::cgu_reuse_tracker::CguReuse;
@@ -49,7 +48,7 @@ pub fn crate_type_allows_lto(crate_type: config::CrateType) -> bool {
 
 pub(crate) enum LtoModuleCodegen {
     Fat {
-        module: Option<ModuleCodegen>,
+        module: Option<ModuleCodegen<ModuleLlvm>>,
         _serialized_bitcode: Vec<SerializedModule>,
     },
 
@@ -73,7 +72,7 @@ impl LtoModuleCodegen {
     pub(crate) unsafe fn optimize(&mut self,
                                   cgcx: &CodegenContext,
                                   timeline: &mut Timeline)
-        -> Result<ModuleCodegen, FatalError>
+        -> Result<ModuleCodegen<ModuleLlvm>, FatalError>
     {
         match *self {
             LtoModuleCodegen::Fat { ref mut module, .. } => {
@@ -108,7 +107,7 @@ impl LtoModuleCodegen {
 /// the need optimization and another for modules that can simply be copied over
 /// from the incr. comp. cache.
 pub(crate) fn run(cgcx: &CodegenContext,
-                  modules: Vec<ModuleCodegen>,
+                  modules: Vec<ModuleCodegen<ModuleLlvm>>,
                   cached_modules: Vec<(SerializedModule, WorkProduct)>,
                   timeline: &mut Timeline)
     -> Result<(Vec<LtoModuleCodegen>, Vec<WorkProduct>), FatalError>
@@ -232,7 +231,7 @@ pub(crate) fn run(cgcx: &CodegenContext,
 
 fn fat_lto(cgcx: &CodegenContext,
            diag_handler: &Handler,
-           mut modules: Vec<ModuleCodegen>,
+           mut modules: Vec<ModuleCodegen<ModuleLlvm>>,
            mut serialized_modules: Vec<(SerializedModule, CString)>,
            symbol_white_list: &[*const libc::c_char],
            timeline: &mut Timeline)
@@ -388,7 +387,7 @@ impl Drop for Linker<'a> {
 /// they all go out of scope.
 fn thin_lto(cgcx: &CodegenContext,
             diag_handler: &Handler,
-            modules: Vec<ModuleCodegen>,
+            modules: Vec<ModuleCodegen<ModuleLlvm>>,
             serialized_modules: Vec<(SerializedModule, CString)>,
             cached_modules: Vec<(SerializedModule, WorkProduct)>,
             symbol_white_list: &[*const libc::c_char],
@@ -740,7 +739,7 @@ impl ThinModule {
     }
 
     unsafe fn optimize(&mut self, cgcx: &CodegenContext, timeline: &mut Timeline)
-        -> Result<ModuleCodegen, FatalError>
+        -> Result<ModuleCodegen<ModuleLlvm>, FatalError>
     {
         let diag_handler = cgcx.create_diag_handler();
         let tm = (cgcx.tm_factory)().map_err(|e| {
diff --git a/src/librustc_codegen_llvm/back/write.rs b/src/librustc_codegen_llvm/back/write.rs
index bb490c58285..72820f967af 100644
--- a/src/librustc_codegen_llvm/back/write.rs
+++ b/src/librustc_codegen_llvm/back/write.rs
@@ -26,7 +26,7 @@ use rustc::util::nodemap::FxHashMap;
 use time_graph::{self, TimeGraph, Timeline};
 use llvm::{self, DiagnosticInfo, PassManager, SMDiagnostic};
 use llvm_util;
-use {CodegenResults, ModuleCodegen, CompiledModule, ModuleKind, // ModuleLlvm,
+use {CodegenResults, ModuleCodegen, CompiledModule, ModuleKind, ModuleLlvm,
      CachedModuleCodegen};
 use CrateInfo;
 use rustc::hir::def_id::{CrateNum, LOCAL_CRATE};
@@ -408,7 +408,7 @@ impl CodegenContext {
         }
     }
 
-    pub(crate) fn save_temp_bitcode(&self, module: &ModuleCodegen, name: &str) {
+    pub(crate) fn save_temp_bitcode(&self, module: &ModuleCodegen<ModuleLlvm>, name: &str) {
         if !self.save_temps {
             return
         }
@@ -515,7 +515,7 @@ unsafe extern "C" fn diagnostic_handler(info: &DiagnosticInfo, user: *mut c_void
 // Unsafe due to LLVM calls.
 unsafe fn optimize(cgcx: &CodegenContext,
                    diag_handler: &Handler,
-                   module: &ModuleCodegen,
+                   module: &ModuleCodegen<ModuleLlvm>,
                    config: &ModuleConfig,
                    timeline: &mut Timeline)
     -> Result<(), FatalError>
@@ -646,7 +646,7 @@ unsafe fn optimize(cgcx: &CodegenContext,
 }
 
 fn generate_lto_work(cgcx: &CodegenContext,
-                     modules: Vec<ModuleCodegen>,
+                     modules: Vec<ModuleCodegen<ModuleLlvm>>,
                      import_only_modules: Vec<(SerializedModule, WorkProduct)>)
     -> Vec<(WorkItem, u64)>
 {
@@ -675,7 +675,7 @@ fn generate_lto_work(cgcx: &CodegenContext,
 
 unsafe fn codegen(cgcx: &CodegenContext,
                   diag_handler: &Handler,
-                  module: ModuleCodegen,
+                  module: ModuleCodegen<ModuleLlvm>,
                   config: &ModuleConfig,
                   timeline: &mut Timeline)
     -> Result<CompiledModule, FatalError>
@@ -1284,7 +1284,7 @@ pub(crate) fn dump_incremental_data(_codegen_results: &CodegenResults) {
 
 enum WorkItem {
     /// Optimize a newly codegened, totally unoptimized module.
-    Optimize(ModuleCodegen),
+    Optimize(ModuleCodegen<ModuleLlvm>),
     /// Copy the post-LTO artifacts from the incremental cache to the output
     /// directory.
     CopyPostLtoArtifacts(CachedModuleCodegen),
@@ -1312,7 +1312,7 @@ impl WorkItem {
 
 enum WorkItemResult {
     Compiled(CompiledModule),
-    NeedsLTO(ModuleCodegen),
+    NeedsLTO(ModuleCodegen<ModuleLlvm>),
 }
 
 fn execute_work_item(cgcx: &CodegenContext,
@@ -1336,7 +1336,7 @@ fn execute_work_item(cgcx: &CodegenContext,
 }
 
 fn execute_optimize_work_item(cgcx: &CodegenContext,
-                              module: ModuleCodegen,
+                              module: ModuleCodegen<ModuleLlvm>,
                               module_config: &ModuleConfig,
                               timeline: &mut Timeline)
     -> Result<WorkItemResult, FatalError>
@@ -1480,7 +1480,7 @@ fn execute_lto_work_item(cgcx: &CodegenContext,
 enum Message {
     Token(io::Result<Acquired>),
     NeedsLTO {
-        result: ModuleCodegen,
+        result: ModuleCodegen<ModuleLlvm>,
         worker_id: usize,
     },
     Done {
@@ -2445,7 +2445,7 @@ impl OngoingCodegen {
 
     pub(crate) fn submit_pre_codegened_module_to_llvm(&self,
                                                       tcx: TyCtxt,
-                                                      module: ModuleCodegen) {
+                                                      module: ModuleCodegen<ModuleLlvm>) {
         self.wait_for_signal_to_codegen_item();
         self.check_for_errors(tcx.sess);
 
@@ -2497,7 +2497,7 @@ impl OngoingCodegen {
 // }
 
 pub(crate) fn submit_codegened_module_to_llvm(tcx: TyCtxt,
-                                              module: ModuleCodegen,
+                                              module: ModuleCodegen<ModuleLlvm>,
                                               cost: u64) {
     let llvm_work_item = WorkItem::Optimize(module);
     drop(tcx.tx_to_llvm_workers.lock().send(Box::new(Message::CodegenDone {
diff --git a/src/librustc_codegen_llvm/base.rs b/src/librustc_codegen_llvm/base.rs
index 333264cf1c3..5fd413b4c7b 100644
--- a/src/librustc_codegen_llvm/base.rs
+++ b/src/librustc_codegen_llvm/base.rs
@@ -29,7 +29,7 @@ use super::ModuleKind;
 use super::CachedModuleCodegen;
 
 use abi;
-use back::write::{self, OngoingCodegen};
+use back::write;
 use llvm;
 use metadata;
 use rustc::dep_graph::cgu_reuse_tracker::CguReuse;
@@ -48,7 +48,6 @@ use rustc::util::profiling::ProfileCategory;
 use rustc::session::config::{self, DebugInfo, EntryFnType, Lto};
 use rustc::session::Session;
 use rustc_incremental;
-use allocator;
 use mir::place::PlaceRef;
 use builder::{Builder, MemFlags};
 use callee;
@@ -584,9 +583,10 @@ fn maybe_create_entry_wrapper<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
     }
 }
 
-fn write_metadata<'a, 'gcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>,
-                            llvm_module: &ModuleLlvm)
-                            -> EncodedMetadata {
+pub(crate) fn write_metadata<'a, 'gcx>(
+    tcx: TyCtxt<'a, 'gcx, 'gcx>,
+    llvm_module: &ModuleLlvm
+) -> EncodedMetadata {
     use std::io::Write;
     use flate2::Compression;
     use flate2::write::DeflateEncoder;
@@ -713,10 +713,12 @@ fn determine_cgu_reuse<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     }
 }
 
-pub fn codegen_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                               rx: mpsc::Receiver<Box<dyn Any + Send>>)
-                               -> OngoingCodegen
-{
+pub fn codegen_crate<'a, 'tcx, B: BackendMethods>(
+    backend: B,
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    rx: mpsc::Receiver<Box<dyn Any + Send>>
+) -> B::OngoingCodegen {
+
     check_for_rustc_errors_attr(tcx);
 
     let cgu_name_builder = &mut CodegenUnitNameBuilder::new(tcx);
@@ -728,9 +730,9 @@ pub fn codegen_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                                             &["crate"],
                                                             Some("metadata")).as_str()
                                                                              .to_string();
-    let metadata_llvm_module = ModuleLlvm::new(tcx.sess, &metadata_cgu_name);
+    let metadata_llvm_module = backend.new_metadata(tcx.sess, &metadata_cgu_name);
     let metadata = time(tcx.sess, "write metadata", || {
-        write_metadata(tcx, &metadata_llvm_module)
+        backend.write_metadata(tcx, &metadata_llvm_module)
     });
     tcx.sess.profiler(|p| p.end_activity(ProfileCategory::Codegen));
 
@@ -749,19 +751,19 @@ pub fn codegen_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     // Skip crate items and just output metadata in -Z no-codegen mode.
     if tcx.sess.opts.debugging_opts.no_codegen ||
        !tcx.sess.opts.output_types.should_codegen() {
-        let ongoing_codegen = write::start_async_codegen(
+        let ongoing_codegen = backend.start_async_codegen(
             tcx,
             time_graph,
             metadata,
             rx,
             1);
 
-        ongoing_codegen.submit_pre_codegened_module_to_llvm(tcx, metadata_module);
-        ongoing_codegen.codegen_finished(tcx);
+        backend.submit_pre_codegened_module_to_llvm(&ongoing_codegen, tcx, metadata_module);
+        backend.codegen_finished(&ongoing_codegen, tcx);
 
         assert_and_save_dep_graph(tcx);
 
-        ongoing_codegen.check_for_errors(tcx.sess);
+        backend.check_for_errors(&ongoing_codegen, tcx.sess);
 
         return ongoing_codegen;
     }
@@ -782,13 +784,13 @@ pub fn codegen_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         }
     }
 
-    let ongoing_codegen = write::start_async_codegen(
+    let ongoing_codegen = backend.start_async_codegen(
         tcx,
         time_graph.clone(),
         metadata,
         rx,
         codegen_units.len());
-    let ongoing_codegen = AbortCodegenOnDrop(Some(ongoing_codegen));
+    let ongoing_codegen = AbortCodegenOnDrop::<B>(Some(ongoing_codegen));
 
     // Codegen an allocator shim, if necessary.
     //
@@ -811,11 +813,9 @@ pub fn codegen_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                                        &["crate"],
                                                        Some("allocator")).as_str()
                                                                          .to_string();
-        let modules = ModuleLlvm::new(tcx.sess, &llmod_id);
+        let modules = backend.new_metadata(tcx.sess, &llmod_id);
         time(tcx.sess, "write allocator module", || {
-            unsafe {
-                allocator::codegen(tcx, &modules, kind)
-            }
+            backend.codegen_allocator(tcx, &modules, kind)
         });
 
         Some(ModuleCodegen {
@@ -828,10 +828,10 @@ pub fn codegen_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     };
 
     if let Some(allocator_module) = allocator_module {
-        ongoing_codegen.submit_pre_codegened_module_to_llvm(tcx, allocator_module);
+        backend.submit_pre_codegened_module_to_llvm(&ongoing_codegen, tcx, allocator_module);
     }
 
-    ongoing_codegen.submit_pre_codegened_module_to_llvm(tcx, metadata_module);
+    backend.submit_pre_codegened_module_to_llvm(&ongoing_codegen, tcx, metadata_module);
 
     // We sort the codegen units by size. This way we can schedule work for LLVM
     // a bit more efficiently.
@@ -845,8 +845,8 @@ pub fn codegen_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     let mut all_stats = Stats::default();
 
     for cgu in codegen_units.into_iter() {
-        ongoing_codegen.wait_for_signal_to_codegen_item();
-        ongoing_codegen.check_for_errors(tcx.sess);
+        backend.wait_for_signal_to_codegen_item(&ongoing_codegen);
+        backend.check_for_errors(&ongoing_codegen, tcx.sess);
 
         let cgu_reuse = determine_cgu_reuse(tcx, &cgu);
         tcx.sess.cgu_reuse_tracker.set_actual_reuse(&cgu.name().as_str(), cgu_reuse);
@@ -881,7 +881,7 @@ pub fn codegen_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         };
     }
 
-    ongoing_codegen.codegen_finished(tcx);
+    backend.codegen_finished(&ongoing_codegen, tcx);
 
     // Since the main thread is sometimes blocked during codegen, we keep track
     // -Ztime-passes output manually.
@@ -915,7 +915,7 @@ pub fn codegen_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         }
     }
 
-    ongoing_codegen.check_for_errors(tcx.sess);
+    backend.check_for_errors(&ongoing_codegen, tcx.sess);
 
     assert_and_save_dep_graph(tcx);
     ongoing_codegen.into_inner()
@@ -938,32 +938,32 @@ pub fn codegen_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 /// If you see this comment in the code, then it means that this workaround
 /// worked! We may yet one day track down the mysterious cause of that
 /// segfault...
-struct AbortCodegenOnDrop(Option<OngoingCodegen>);
+struct AbortCodegenOnDrop<B: BackendMethods>(Option<B::OngoingCodegen>);
 
-impl AbortCodegenOnDrop {
-    fn into_inner(mut self) -> OngoingCodegen {
+impl<B: BackendMethods> AbortCodegenOnDrop<B> {
+    fn into_inner(mut self) -> B::OngoingCodegen {
         self.0.take().unwrap()
     }
 }
 
-impl Deref for AbortCodegenOnDrop {
-    type Target = OngoingCodegen;
+impl<B: BackendMethods> Deref for AbortCodegenOnDrop<B> {
+    type Target = B::OngoingCodegen;
 
-    fn deref(&self) -> &OngoingCodegen {
+    fn deref(&self) -> &B::OngoingCodegen {
         self.0.as_ref().unwrap()
     }
 }
 
-impl DerefMut for AbortCodegenOnDrop {
-    fn deref_mut(&mut self) -> &mut OngoingCodegen {
+impl<B: BackendMethods> DerefMut for AbortCodegenOnDrop<B> {
+    fn deref_mut(&mut self) -> &mut B::OngoingCodegen {
         self.0.as_mut().unwrap()
     }
 }
 
-impl Drop for AbortCodegenOnDrop {
+impl<B: BackendMethods> Drop for AbortCodegenOnDrop<B> {
     fn drop(&mut self) {
         if let Some(codegen) = self.0.take() {
-            codegen.codegen_aborted();
+            B::codegen_aborted(codegen);
         }
     }
 }
@@ -1092,7 +1092,7 @@ fn compile_codegen_unit<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     fn module_codegen<'a, 'tcx>(
         tcx: TyCtxt<'a, 'tcx, 'tcx>,
         cgu_name: InternedString)
-        -> (Stats, ModuleCodegen)
+        -> (Stats, ModuleCodegen<ModuleLlvm>)
     {
         let cgu = tcx.codegen_unit(cgu_name);
 
@@ -1226,9 +1226,9 @@ pub fn visibility_to_llvm(linkage: Visibility) -> llvm::Visibility {
 mod temp_stable_hash_impls {
     use rustc_data_structures::stable_hasher::{StableHasherResult, StableHasher,
                                                HashStable};
-    use ModuleCodegen;
+    use {ModuleCodegen, ModuleLlvm};
 
-    impl<HCX> HashStable<HCX> for ModuleCodegen {
+    impl<HCX> HashStable<HCX> for ModuleCodegen<ModuleLlvm> {
         fn hash_stable<W: StableHasherResult>(&self,
                                               _: &mut HCX,
                                               _: &mut StableHasher<W>) {
diff --git a/src/librustc_codegen_llvm/interfaces/backend.rs b/src/librustc_codegen_llvm/interfaces/backend.rs
index 7e95cb24804..a5df7e5af6f 100644
--- a/src/librustc_codegen_llvm/interfaces/backend.rs
+++ b/src/librustc_codegen_llvm/interfaces/backend.rs
@@ -12,6 +12,14 @@ use rustc::ty::layout::{HasTyCtxt, LayoutOf, TyLayout};
 use rustc::ty::Ty;
 
 use super::CodegenObject;
+use rustc::middle::allocator::AllocatorKind;
+use rustc::middle::cstore::EncodedMetadata;
+use rustc::session::Session;
+use rustc::ty::TyCtxt;
+use std::any::Any;
+use std::sync::mpsc::Receiver;
+use time_graph::TimeGraph;
+use ModuleCodegen;
 
 pub trait BackendTypes {
     type Value: CodegenObject;
@@ -30,3 +38,35 @@ pub trait Backend<'tcx>:
 impl<'tcx, T> Backend<'tcx> for T where
     Self: BackendTypes + HasTyCtxt<'tcx> + LayoutOf<Ty = Ty<'tcx>, TyLayout = TyLayout<'tcx>>
 {}
+
+pub trait BackendMethods {
+    type Metadata;
+    type OngoingCodegen;
+
+    fn new_metadata(&self, sess: &Session, mod_name: &str) -> Self::Metadata;
+    fn write_metadata<'a, 'gcx>(
+        &self,
+        tcx: TyCtxt<'a, 'gcx, 'gcx>,
+        metadata: &Self::Metadata,
+    ) -> EncodedMetadata;
+    fn codegen_allocator(&self, tcx: TyCtxt, mods: &Self::Metadata, kind: AllocatorKind);
+
+    fn start_async_codegen(
+        &self,
+        tcx: TyCtxt,
+        time_graph: Option<TimeGraph>,
+        metadata: EncodedMetadata,
+        coordinator_receive: Receiver<Box<dyn Any + Send>>,
+        total_cgus: usize,
+    ) -> Self::OngoingCodegen;
+    fn submit_pre_codegened_module_to_llvm(
+        &self,
+        codegen: &Self::OngoingCodegen,
+        tcx: TyCtxt,
+        module: ModuleCodegen<Self::Metadata>,
+    );
+    fn codegen_aborted(codegen: Self::OngoingCodegen);
+    fn codegen_finished(&self, codegen: &Self::OngoingCodegen, tcx: TyCtxt);
+    fn check_for_errors(&self, codegen: &Self::OngoingCodegen, sess: &Session);
+    fn wait_for_signal_to_codegen_item(&self, codegen: &Self::OngoingCodegen);
+}
diff --git a/src/librustc_codegen_llvm/interfaces/mod.rs b/src/librustc_codegen_llvm/interfaces/mod.rs
index 6ff66261416..e0ce05d0a84 100644
--- a/src/librustc_codegen_llvm/interfaces/mod.rs
+++ b/src/librustc_codegen_llvm/interfaces/mod.rs
@@ -22,7 +22,7 @@ mod type_;
 
 pub use self::abi::{AbiBuilderMethods, AbiMethods};
 pub use self::asm::{AsmBuilderMethods, AsmMethods};
-pub use self::backend::{Backend, BackendTypes};
+pub use self::backend::{Backend, BackendMethods, BackendTypes};
 pub use self::builder::BuilderMethods;
 pub use self::consts::ConstMethods;
 pub use self::debuginfo::{DebugInfoBuilderMethods, DebugInfoMethods};
diff --git a/src/librustc_codegen_llvm/lib.rs b/src/librustc_codegen_llvm/lib.rs
index 43942b0db85..d1be81f1224 100644
--- a/src/librustc_codegen_llvm/lib.rs
+++ b/src/librustc_codegen_llvm/lib.rs
@@ -68,6 +68,10 @@ extern crate tempfile;
 extern crate memmap;
 
 use back::bytecode::RLIB_BYTECODE_EXTENSION;
+use interfaces::*;
+use time_graph::TimeGraph;
+use std::sync::mpsc::Receiver;
+use back::write::{self, OngoingCodegen};
 
 pub use llvm_util::target_features;
 use std::any::Any;
@@ -76,7 +80,8 @@ use rustc_data_structures::sync::Lrc;
 
 use rustc::dep_graph::DepGraph;
 use rustc::hir::def_id::CrateNum;
-use rustc::middle::cstore::MetadataLoader;
+use rustc::middle::allocator::AllocatorKind;
+use rustc::middle::cstore::{EncodedMetadata, MetadataLoader};
 use rustc::middle::cstore::{NativeLibrary, CrateSource, LibSource};
 use rustc::middle::lang_items::LangItem;
 use rustc::session::{Session, CompileIncomplete};
@@ -133,6 +138,56 @@ mod value;
 
 pub struct LlvmCodegenBackend(());
 
+impl BackendMethods for LlvmCodegenBackend {
+    type Metadata = ModuleLlvm;
+    type OngoingCodegen = OngoingCodegen;
+
+    fn new_metadata(&self, sess: &Session, mod_name: &str) -> ModuleLlvm {
+        ModuleLlvm::new(sess, mod_name)
+    }
+    fn write_metadata<'a, 'gcx>(
+        &self,
+        tcx: TyCtxt<'a, 'gcx, 'gcx>,
+        metadata: &ModuleLlvm
+    ) -> EncodedMetadata {
+        base::write_metadata(tcx, metadata)
+    }
+    fn start_async_codegen(
+        &self,
+        tcx: TyCtxt,
+        time_graph: Option<TimeGraph>,
+        metadata: EncodedMetadata,
+        coordinator_receive: Receiver<Box<dyn Any + Send>>,
+        total_cgus: usize
+    ) -> OngoingCodegen {
+        write::start_async_codegen(tcx, time_graph, metadata, coordinator_receive, total_cgus)
+    }
+    fn submit_pre_codegened_module_to_llvm(
+        &self,
+        codegen: &OngoingCodegen,
+        tcx: TyCtxt,
+        module: ModuleCodegen<ModuleLlvm>
+    ) {
+        codegen.submit_pre_codegened_module_to_llvm(tcx, module)
+    }
+    fn codegen_aborted(codegen: OngoingCodegen) {
+        codegen.codegen_aborted();
+    }
+    fn codegen_finished(&self, codegen: &OngoingCodegen, tcx: TyCtxt) {
+        codegen.codegen_finished(tcx)
+    }
+    fn check_for_errors(&self, codegen: &OngoingCodegen, sess: &Session) {
+        codegen.check_for_errors(sess)
+    }
+    fn codegen_allocator(&self, tcx: TyCtxt, mods: &ModuleLlvm, kind: AllocatorKind) {
+        unsafe { allocator::codegen(tcx, mods, kind) }
+    }
+    fn wait_for_signal_to_codegen_item(&self, codegen: &OngoingCodegen) {
+        codegen.wait_for_signal_to_codegen_item()
+    }
+}
+
+
 impl !Send for LlvmCodegenBackend {} // Llvm is on a per-thread basis
 impl !Sync for LlvmCodegenBackend {}
 
@@ -212,7 +267,7 @@ impl CodegenBackend for LlvmCodegenBackend {
         tcx: TyCtxt<'a, 'tcx, 'tcx>,
         rx: mpsc::Receiver<Box<dyn Any + Send>>
     ) -> Box<dyn Any> {
-        box base::codegen_crate(tcx, rx)
+        box base::codegen_crate(LlvmCodegenBackend(()), tcx, rx)
     }
 
     fn join_codegen_and_link(
@@ -265,7 +320,7 @@ pub fn __rustc_codegen_backend() -> Box<dyn CodegenBackend> {
     LlvmCodegenBackend::new()
 }
 
-struct ModuleCodegen {
+pub struct ModuleCodegen<M> {
     /// The name of the module. When the crate may be saved between
     /// compilations, incremental compilation requires that name be
     /// unique amongst **all** crates.  Therefore, it should contain
@@ -273,7 +328,7 @@ struct ModuleCodegen {
     /// as the crate name and disambiguator.
     /// We currently generate these names via CodegenUnit::build_cgu_name().
     name: String,
-    module_llvm: ModuleLlvm,
+    module_llvm: M,
     kind: ModuleKind,
 }
 
@@ -282,7 +337,7 @@ struct CachedModuleCodegen {
     source: WorkProduct,
 }
 
-impl ModuleCodegen {
+impl ModuleCodegen<ModuleLlvm> {
     fn into_compiled_module(self,
                             emit_obj: bool,
                             emit_bc: bool,
@@ -315,7 +370,7 @@ impl ModuleCodegen {
     }
 }
 
-struct ModuleLlvm {
+pub struct ModuleLlvm {
     llcx: &'static mut llvm::Context,
     llmod_raw: *const llvm::Module,
     tm: &'static mut llvm::TargetMachine,