]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc_codegen_llvm/base.rs
Beginning of moving all backend-agnostic code to rustc_codegen_ssa
[rust.git] / src / librustc_codegen_llvm / base.rs
index 806025937cb110c75028094c56caee1e6fda7f1e..4e69bf8e8b3974da5579726dd685e43f3bb9a436 100644 (file)
 //!     int) and rec(x=int, y=int, z=int) will have the same llvm::Type.
 
 use super::ModuleLlvm;
-use super::ModuleCodegen;
-use super::ModuleKind;
-use super::CachedModuleCodegen;
+use rustc_codegen_ssa::{ModuleCodegen, ModuleKind, CachedModuleCodegen};
+use super::LlvmCodegenBackend;
 
 use abi;
-use back::write::{self, OngoingCodegen};
-use llvm::{self, TypeKind, get_param};
+use back::write;
+use llvm;
 use metadata;
 use rustc::dep_graph::cgu_reuse_tracker::CguReuse;
 use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
@@ -39,7 +38,7 @@
 use rustc::mir::mono::{Linkage, Visibility, Stats, CodegenUnitNameBuilder};
 use rustc::middle::cstore::{EncodedMetadata};
 use rustc::ty::{self, Ty, TyCtxt};
-use rustc::ty::layout::{self, Align, TyLayout, LayoutOf};
+use rustc::ty::layout::{self, Align, TyLayout, LayoutOf, VariantIdx, HasTyCtxt};
 use rustc::ty::query::Providers;
 use rustc::middle::cstore::{self, LinkagePreference};
 use rustc::middle::exported_symbols;
 use rustc::session::config::{self, DebugInfo, EntryFnType, Lto};
 use rustc::session::Session;
 use rustc_incremental;
-use allocator;
 use mir::place::PlaceRef;
-use attributes;
 use builder::{Builder, MemFlags};
 use callee;
-use common::{C_bool, C_bytes_in_context, C_usize};
 use rustc_mir::monomorphize::item::DefPathBasedNames;
-use common::{C_struct_in_context, C_array, val_ty};
-use consts;
-use context::CodegenCx;
-use debuginfo;
-use declare;
+use common;
+use rustc_codegen_ssa::common::{RealPredicate, TypeKind, IntPredicate};
 use meth;
 use mir;
+use context::CodegenCx;
 use monomorphize::Instance;
 use monomorphize::partitioning::{CodegenUnit, CodegenUnitExt};
 use rustc_codegen_utils::symbol_names_test;
 use time_graph;
 use mono_item::{MonoItem, MonoItemExt};
-use type_::Type;
-use type_of::LayoutLlvmExt;
+
 use rustc::util::nodemap::FxHashMap;
 use CrateInfo;
 use rustc_data_structures::small_c_str::SmallCStr;
 use rustc_data_structures::sync::Lrc;
+use rustc_data_structures::indexed_vec::Idx;
+
+use interfaces::*;
 
 use std::any::Any;
 use std::cmp;
 use std::ffi::CString;
+use std::marker;
 use std::ops::{Deref, DerefMut};
 use std::sync::mpsc;
 use std::time::{Instant, Duration};
 
 use rustc_codegen_utils::check_for_rustc_errors_attr;
 
-pub struct StatRecorder<'a, 'll: 'a, 'tcx: 'll> {
-    cx: &'a CodegenCx<'ll, 'tcx>,
+pub struct StatRecorder<'a, 'tcx, Cx: 'a + CodegenMethods<'tcx>> {
+    cx: &'a Cx,
     name: Option<String>,
     istart: usize,
+    _marker: marker::PhantomData<&'tcx ()>,
 }
 
-impl StatRecorder<'a, 'll, 'tcx> {
-    pub fn new(cx: &'a CodegenCx<'ll, 'tcx>, name: String) -> Self {
-        let istart = cx.stats.borrow().n_llvm_insns;
+impl<'a, 'tcx, Cx: CodegenMethods<'tcx>> StatRecorder<'a, 'tcx, Cx> {
+    pub fn new(cx: &'a Cx, name: String) -> Self {
+        let istart = cx.stats().borrow().n_llvm_insns;
         StatRecorder {
             cx,
             name: Some(name),
             istart,
+            _marker: marker::PhantomData,
         }
     }
 }
 
-impl Drop for StatRecorder<'a, 'll, 'tcx> {
+impl<'a, 'tcx, Cx: CodegenMethods<'tcx>> Drop for StatRecorder<'a, 'tcx, Cx> {
     fn drop(&mut self) {
         if self.cx.sess().codegen_stats() {
-            let mut stats = self.cx.stats.borrow_mut();
+            let mut stats = self.cx.stats().borrow_mut();
             let iend = stats.n_llvm_insns;
             stats.fn_stats.push((self.name.take().unwrap(), iend - self.istart));
             stats.n_fns += 1;
@@ -123,14 +122,14 @@ fn drop(&mut self) {
 
 pub fn bin_op_to_icmp_predicate(op: hir::BinOpKind,
                                 signed: bool)
-                                -> llvm::IntPredicate {
+                                -> IntPredicate {
     match op {
-        hir::BinOpKind::Eq => llvm::IntEQ,
-        hir::BinOpKind::Ne => llvm::IntNE,
-        hir::BinOpKind::Lt => if signed { llvm::IntSLT } else { llvm::IntULT },
-        hir::BinOpKind::Le => if signed { llvm::IntSLE } else { llvm::IntULE },
-        hir::BinOpKind::Gt => if signed { llvm::IntSGT } else { llvm::IntUGT },
-        hir::BinOpKind::Ge => if signed { llvm::IntSGE } else { llvm::IntUGE },
+        hir::BinOpKind::Eq => IntPredicate::IntEQ,
+        hir::BinOpKind::Ne => IntPredicate::IntNE,
+        hir::BinOpKind::Lt => if signed { IntPredicate::IntSLT } else { IntPredicate::IntULT },
+        hir::BinOpKind::Le => if signed { IntPredicate::IntSLE } else { IntPredicate::IntULE },
+        hir::BinOpKind::Gt => if signed { IntPredicate::IntSGT } else { IntPredicate::IntUGT },
+        hir::BinOpKind::Ge => if signed { IntPredicate::IntSGE } else { IntPredicate::IntUGE },
         op => {
             bug!("comparison_op_to_icmp_predicate: expected comparison operator, \
                   found {:?}",
@@ -139,14 +138,14 @@ pub fn bin_op_to_icmp_predicate(op: hir::BinOpKind,
     }
 }
 
-pub fn bin_op_to_fcmp_predicate(op: hir::BinOpKind) -> llvm::RealPredicate {
+pub fn bin_op_to_fcmp_predicate(op: hir::BinOpKind) -> RealPredicate {
     match op {
-        hir::BinOpKind::Eq => llvm::RealOEQ,
-        hir::BinOpKind::Ne => llvm::RealUNE,
-        hir::BinOpKind::Lt => llvm::RealOLT,
-        hir::BinOpKind::Le => llvm::RealOLE,
-        hir::BinOpKind::Gt => llvm::RealOGT,
-        hir::BinOpKind::Ge => llvm::RealOGE,
+        hir::BinOpKind::Eq => RealPredicate::RealOEQ,
+        hir::BinOpKind::Ne => RealPredicate::RealUNE,
+        hir::BinOpKind::Lt => RealPredicate::RealOLT,
+        hir::BinOpKind::Le => RealPredicate::RealOLE,
+        hir::BinOpKind::Gt => RealPredicate::RealOGT,
+        hir::BinOpKind::Ge => RealPredicate::RealOGE,
         op => {
             bug!("comparison_op_to_fcmp_predicate: expected comparison operator, \
                   found {:?}",
@@ -155,14 +154,14 @@ pub fn bin_op_to_fcmp_predicate(op: hir::BinOpKind) -> llvm::RealPredicate {
     }
 }
 
-pub fn compare_simd_types(
-    bx: &Builder<'a, 'll, 'tcx>,
-    lhs: &'ll Value,
-    rhs: &'ll Value,
+pub fn compare_simd_types<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
+    bx: &Bx,
+    lhs: Bx::Value,
+    rhs: Bx::Value,
     t: Ty<'tcx>,
-    ret_ty: &'ll Type,
+    ret_ty: Bx::Type,
     op: hir::BinOpKind
-) -> &'ll Value {
+) -> Bx::Value {
     let signed = match t.sty {
         ty::Float(_) => {
             let cmp = bin_op_to_fcmp_predicate(op);
@@ -187,16 +186,16 @@ pub fn compare_simd_types(
 /// The `old_info` argument is a bit funny. It is intended for use
 /// in an upcast, where the new vtable for an object will be derived
 /// from the old one.
-pub fn unsized_info(
-    cx: &CodegenCx<'ll, 'tcx>,
+pub fn unsized_info<'tcx, Cx: CodegenMethods<'tcx>>(
+    cx: &Cx,
     source: Ty<'tcx>,
     target: Ty<'tcx>,
-    old_info: Option<&'ll Value>,
-) -> &'ll Value {
-    let (source, target) = cx.tcx.struct_lockstep_tails(source, target);
+    old_info: Option<Cx::Value>,
+) -> Cx::Value {
+    let (source, target) = cx.tcx().struct_lockstep_tails(source, target);
     match (&source.sty, &target.sty) {
         (&ty::Array(_, len), &ty::Slice(_)) => {
-            C_usize(cx, len.unwrap_usize(cx.tcx))
+            cx.const_usize(len.unwrap_usize(cx.tcx()))
         }
         (&ty::Dynamic(..), &ty::Dynamic(..)) => {
             // For now, upcasts are limited to changes in marker
@@ -205,10 +204,10 @@ pub fn unsized_info(
             old_info.expect("unsized_info: missing old info for trait upcast")
         }
         (_, &ty::Dynamic(ref data, ..)) => {
-            let vtable_ptr = cx.layout_of(cx.tcx.mk_mut_ptr(target))
+            let vtable_ptr = cx.layout_of(cx.tcx().mk_mut_ptr(target))
                 .field(cx, abi::FAT_PTR_EXTRA);
-            consts::ptrcast(meth::get_vtable(cx, source, data.principal()),
-                            vtable_ptr.llvm_type(cx))
+            cx.static_ptrcast(meth::get_vtable(cx, source, data.principal()),
+                            cx.backend_type(vtable_ptr))
         }
         _ => bug!("unsized_info: invalid unsizing {:?} -> {:?}",
                   source,
@@ -217,12 +216,12 @@ pub fn unsized_info(
 }
 
 /// Coerce `src` to `dst_ty`. `src_ty` must be a thin pointer.
-pub fn unsize_thin_ptr(
-    bx: &Builder<'a, 'll, 'tcx>,
-    src: &'ll Value,
+pub fn unsize_thin_ptr<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
+    bx: &Bx,
+    src: Bx::Value,
     src_ty: Ty<'tcx>,
     dst_ty: Ty<'tcx>
-) -> (&'ll Value, &'ll Value) {
+) -> (Bx::Value, Bx::Value) {
     debug!("unsize_thin_ptr: {:?} => {:?}", src_ty, dst_ty);
     match (&src_ty.sty, &dst_ty.sty) {
         (&ty::Ref(_, a, _),
@@ -231,24 +230,24 @@ pub fn unsize_thin_ptr(
          &ty::RawPtr(ty::TypeAndMut { ty: b, .. })) |
         (&ty::RawPtr(ty::TypeAndMut { ty: a, .. }),
          &ty::RawPtr(ty::TypeAndMut { ty: b, .. })) => {
-            assert!(bx.cx.type_is_sized(a));
-            let ptr_ty = bx.cx.layout_of(b).llvm_type(bx.cx).ptr_to();
-            (bx.pointercast(src, ptr_ty), unsized_info(bx.cx, a, b, None))
+            assert!(bx.cx().type_is_sized(a));
+            let ptr_ty = bx.cx().type_ptr_to(bx.cx().backend_type(bx.cx().layout_of(b)));
+            (bx.pointercast(src, ptr_ty), unsized_info(bx.cx(), a, b, None))
         }
         (&ty::Adt(def_a, _), &ty::Adt(def_b, _)) if def_a.is_box() && def_b.is_box() => {
             let (a, b) = (src_ty.boxed_ty(), dst_ty.boxed_ty());
-            assert!(bx.cx.type_is_sized(a));
-            let ptr_ty = bx.cx.layout_of(b).llvm_type(bx.cx).ptr_to();
-            (bx.pointercast(src, ptr_ty), unsized_info(bx.cx, a, b, None))
+            assert!(bx.cx().type_is_sized(a));
+            let ptr_ty = bx.cx().type_ptr_to(bx.cx().backend_type(bx.cx().layout_of(b)));
+            (bx.pointercast(src, ptr_ty), unsized_info(bx.cx(), a, b, None))
         }
         (&ty::Adt(def_a, _), &ty::Adt(def_b, _)) => {
             assert_eq!(def_a, def_b);
 
-            let src_layout = bx.cx.layout_of(src_ty);
-            let dst_layout = bx.cx.layout_of(dst_ty);
+            let src_layout = bx.cx().layout_of(src_ty);
+            let dst_layout = bx.cx().layout_of(dst_ty);
             let mut result = None;
             for i in 0..src_layout.fields.count() {
-                let src_f = src_layout.field(bx.cx, i);
+                let src_f = src_layout.field(bx.cx(), i);
                 assert_eq!(src_layout.fields.offset(i).bytes(), 0);
                 assert_eq!(dst_layout.fields.offset(i).bytes(), 0);
                 if src_f.is_zst() {
@@ -256,15 +255,15 @@ pub fn unsize_thin_ptr(
                 }
                 assert_eq!(src_layout.size, src_f.size);
 
-                let dst_f = dst_layout.field(bx.cx, i);
+                let dst_f = dst_layout.field(bx.cx(), i);
                 assert_ne!(src_f.ty, dst_f.ty);
                 assert_eq!(result, None);
                 result = Some(unsize_thin_ptr(bx, src, src_f.ty, dst_f.ty));
             }
             let (lldata, llextra) = result.unwrap();
             // HACK(eddyb) have to bitcast pointers until LLVM removes pointee types.
-            (bx.bitcast(lldata, dst_layout.scalar_pair_element_llvm_type(bx.cx, 0, true)),
-             bx.bitcast(llextra, dst_layout.scalar_pair_element_llvm_type(bx.cx, 1, true)))
+            (bx.bitcast(lldata, bx.cx().scalar_pair_element_backend_type(dst_layout, 0, true)),
+             bx.bitcast(llextra, bx.cx().scalar_pair_element_backend_type(dst_layout, 1, true)))
         }
         _ => bug!("unsize_thin_ptr: called on bad types"),
     }
@@ -272,22 +271,22 @@ pub fn unsize_thin_ptr(
 
 /// Coerce `src`, which is a reference to a value of type `src_ty`,
 /// to a value of type `dst_ty` and store the result in `dst`
-pub fn coerce_unsized_into(
-    bx: &Builder<'a, 'll, 'tcx>,
-    src: PlaceRef<'ll, 'tcx>,
-    dst: PlaceRef<'ll, 'tcx>
-) {
+pub fn coerce_unsized_into<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
+    bx: &Bx,
+    src: PlaceRef<'tcx, Bx::Value>,
+    dst: PlaceRef<'tcx, Bx::Value>
+)  {
     let src_ty = src.layout.ty;
     let dst_ty = dst.layout.ty;
     let coerce_ptr = || {
-        let (base, info) = match src.load(bx).val {
+        let (base, info) = match bx.load_operand(src).val {
             OperandValue::Pair(base, info) => {
                 // fat-ptr to fat-ptr unsize preserves the vtable
                 // i.e. &'a fmt::Debug+Send => &'a fmt::Debug
                 // So we need to pointercast the base to ensure
                 // the types match up.
-                let thin_ptr = dst.layout.field(bx.cx, abi::FAT_PTR_ADDR);
-                (bx.pointercast(base, thin_ptr.llvm_type(bx.cx)), info)
+                let thin_ptr = dst.layout.field(bx.cx(), abi::FAT_PTR_ADDR);
+                (bx.pointercast(base, bx.cx().backend_type(thin_ptr)), info)
             }
             OperandValue::Immediate(base) => {
                 unsize_thin_ptr(bx, base, src_ty, dst_ty)
@@ -309,7 +308,7 @@ pub fn coerce_unsized_into(
         (&ty::Adt(def_a, _), &ty::Adt(def_b, _)) => {
             assert_eq!(def_a, def_b);
 
-            for i in 0..def_a.variants[0].fields.len() {
+            for i in 0..def_a.variants[VariantIdx::new(0)].fields.len() {
                 let src_f = src.project_field(bx, i);
                 let dst_f = dst.project_field(bx, i);
 
@@ -331,33 +330,44 @@ pub fn coerce_unsized_into(
     }
 }
 
-pub fn cast_shift_expr_rhs(
-    cx: &Builder<'_, 'll, '_>, op: hir::BinOpKind, lhs: &'ll Value, rhs: &'ll Value
-) -> &'ll Value {
-    cast_shift_rhs(op, lhs, rhs, |a, b| cx.trunc(a, b), |a, b| cx.zext(a, b))
+pub fn cast_shift_expr_rhs<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
+    bx: &Bx,
+    op: hir::BinOpKind,
+    lhs: Bx::Value,
+    rhs: Bx::Value
+) -> Bx::Value {
+    cast_shift_rhs(bx, op, lhs, rhs, |a, b| bx.trunc(a, b), |a, b| bx.zext(a, b))
 }
 
-fn cast_shift_rhs<'ll, F, G>(op: hir::BinOpKind,
-                             lhs: &'ll Value,
-                             rhs: &'ll Value,
-                             trunc: F,
-                             zext: G)
-                             -> &'ll Value
-    where F: FnOnce(&'ll Value, &'ll Type) -> &'ll Value,
-          G: FnOnce(&'ll Value, &'ll Type) -> &'ll Value
+fn cast_shift_rhs<'a, 'tcx: 'a, F, G, Bx: BuilderMethods<'a, 'tcx>>(
+    bx: &Bx,
+    op: hir::BinOpKind,
+    lhs: Bx::Value,
+    rhs: Bx::Value,
+    trunc: F,
+    zext: G
+) -> Bx::Value
+    where F: FnOnce(
+        Bx::Value,
+        Bx::Type
+    ) -> Bx::Value,
+    G: FnOnce(
+        Bx::Value,
+        Bx::Type
+    ) -> Bx::Value
 {
     // Shifts may have any size int on the rhs
     if op.is_shift() {
-        let mut rhs_llty = val_ty(rhs);
-        let mut lhs_llty = val_ty(lhs);
-        if rhs_llty.kind() == TypeKind::Vector {
-            rhs_llty = rhs_llty.element_type()
+        let mut rhs_llty = bx.cx().val_ty(rhs);
+        let mut lhs_llty = bx.cx().val_ty(lhs);
+        if bx.cx().type_kind(rhs_llty) == TypeKind::Vector {
+            rhs_llty = bx.cx().element_type(rhs_llty)
         }
-        if lhs_llty.kind() == TypeKind::Vector {
-            lhs_llty = lhs_llty.element_type()
+        if bx.cx().type_kind(lhs_llty) == TypeKind::Vector {
+            lhs_llty = bx.cx().element_type(lhs_llty)
         }
-        let rhs_sz = rhs_llty.int_width();
-        let lhs_sz = lhs_llty.int_width();
+        let rhs_sz = bx.cx().int_width(rhs_llty);
+        let lhs_sz = bx.cx().int_width(lhs_llty);
         if lhs_sz < rhs_sz {
             trunc(rhs, lhs_llty)
         } else if lhs_sz > rhs_sz {
@@ -381,70 +391,52 @@ pub fn wants_msvc_seh(sess: &Session) -> bool {
     sess.target.target.options.is_like_msvc
 }
 
-pub fn call_assume(bx: &Builder<'_, 'll, '_>, val: &'ll Value) {
-    let assume_intrinsic = bx.cx.get_intrinsic("llvm.assume");
+pub fn call_assume<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
+    bx: &Bx,
+    val: Bx::Value
+) {
+    let assume_intrinsic = bx.cx().get_intrinsic("llvm.assume");
     bx.call(assume_intrinsic, &[val], None);
 }
 
-pub fn from_immediate(bx: &Builder<'_, 'll, '_>, val: &'ll Value) -> &'ll Value {
-    if val_ty(val) == Type::i1(bx.cx) {
-        bx.zext(val, Type::i8(bx.cx))
+pub fn from_immediate<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
+    bx: &Bx,
+    val: Bx::Value
+) -> Bx::Value {
+    if bx.cx().val_ty(val) == bx.cx().type_i1() {
+        bx.zext(val, bx.cx().type_i8())
     } else {
         val
     }
 }
 
-pub fn to_immediate(
-    bx: &Builder<'_, 'll, '_>,
-    val: &'ll Value,
+pub fn to_immediate<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
+    bx: &Bx,
+    val: Bx::Value,
     layout: layout::TyLayout,
-) -> &'ll Value {
+) -> Bx::Value {
     if let layout::Abi::Scalar(ref scalar) = layout.abi {
         return to_immediate_scalar(bx, val, scalar);
     }
     val
 }
 
-pub fn to_immediate_scalar(
-    bx: &Builder<'_, 'll, '_>,
-    val: &'ll Value,
+pub fn to_immediate_scalar<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
+    bx: &Bx,
+    val: Bx::Value,
     scalar: &layout::Scalar,
-) -> &'ll Value {
+) -> Bx::Value {
     if scalar.is_bool() {
-        return bx.trunc(val, Type::i1(bx.cx));
+        return bx.trunc(val, bx.cx().type_i1());
     }
     val
 }
 
-pub fn call_memcpy(
-    bx: &Builder<'_, 'll, '_>,
-    dst: &'ll Value,
-    dst_align: Align,
-    src: &'ll Value,
-    src_align: Align,
-    n_bytes: &'ll Value,
-    flags: MemFlags,
-) {
-    if flags.contains(MemFlags::NONTEMPORAL) {
-        // HACK(nox): This is inefficient but there is no nontemporal memcpy.
-        let val = bx.load(src, src_align);
-        let ptr = bx.pointercast(dst, val_ty(val).ptr_to());
-        bx.store_with_flags(val, ptr, dst_align, flags);
-        return;
-    }
-    let cx = bx.cx;
-    let src_ptr = bx.pointercast(src, Type::i8p(cx));
-    let dst_ptr = bx.pointercast(dst, Type::i8p(cx));
-    let size = bx.intcast(n_bytes, cx.isize_ty, false);
-    let volatile = flags.contains(MemFlags::VOLATILE);
-    bx.memcpy(dst_ptr, dst_align.abi(), src_ptr, src_align.abi(), size, volatile);
-}
-
-pub fn memcpy_ty(
-    bx: &Builder<'_, 'll, 'tcx>,
-    dst: &'ll Value,
+pub fn memcpy_ty<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
+    bx: &Bx,
+    dst: Bx::Value,
     dst_align: Align,
-    src: &'ll Value,
+    src: Bx::Value,
     src_align: Align,
     layout: TyLayout<'tcx>,
     flags: MemFlags,
@@ -454,28 +446,16 @@ pub fn memcpy_ty(
         return;
     }
 
-    call_memcpy(bx, dst, dst_align, src, src_align, C_usize(bx.cx, size), flags);
+    bx.memcpy(dst, dst_align, src, src_align, bx.cx().const_usize(size), flags);
 }
 
-pub fn call_memset(
-    bx: &Builder<'_, 'll, '_>,
-    ptr: &'ll Value,
-    fill_byte: &'ll Value,
-    size: &'ll Value,
-    align: &'ll Value,
-    volatile: bool,
-) -> &'ll Value {
-    let ptr_width = &bx.cx.sess().target.target.target_pointer_width;
-    let intrinsic_key = format!("llvm.memset.p0i8.i{}", ptr_width);
-    let llintrinsicfn = bx.cx.get_intrinsic(&intrinsic_key);
-    let volatile = C_bool(bx.cx, volatile);
-    bx.call(llintrinsicfn, &[ptr, fill_byte, size, align, volatile], None)
-}
-
-pub fn codegen_instance<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, instance: Instance<'tcx>) {
+pub fn codegen_instance<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
+    cx: &'a Bx::CodegenCx,
+    instance: Instance<'tcx>,
+) {
     let _s = if cx.sess().codegen_stats() {
         let mut instance_name = String::new();
-        DefPathBasedNames::new(cx.tcx, true, true)
+        DefPathBasedNames::new(cx.tcx(), true, true)
             .push_def_path(instance.def_id(), &mut instance_name);
         Some(StatRecorder::new(cx, instance_name))
     } else {
@@ -487,16 +467,16 @@ pub fn codegen_instance<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, instance: Instance<'
     // release builds.
     info!("codegen_instance({})", instance);
 
-    let sig = instance.fn_sig(cx.tcx);
-    let sig = cx.tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig);
+    let sig = instance.fn_sig(cx.tcx());
+    let sig = cx.tcx().normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig);
 
-    let lldecl = cx.instances.borrow().get(&instance).cloned().unwrap_or_else(||
+    let lldecl = cx.instances().borrow().get(&instance).cloned().unwrap_or_else(||
         bug!("Instance `{:?}` not already declared", instance));
 
-    cx.stats.borrow_mut().n_closures += 1;
+    cx.stats().borrow_mut().n_closures += 1;
 
-    let mir = cx.tcx.instance_mir(instance.def);
-    mir::codegen_mir(cx, lldecl, &mir, instance, sig);
+    let mir = cx.tcx().instance_mir(instance.def);
+    mir::codegen_mir::<Bx>(cx, lldecl, &mir, instance, sig);
 }
 
 pub fn set_link_section(llval: &Value, attrs: &CodegenFnAttrs) {
@@ -512,51 +492,54 @@ pub fn set_link_section(llval: &Value, attrs: &CodegenFnAttrs) {
 
 /// Create the `main` function which will initialize the rust runtime and call
 /// users main function.
-fn maybe_create_entry_wrapper(cx: &CodegenCx) {
+fn maybe_create_entry_wrapper<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
+    cx: &'a Bx::CodegenCx
+) {
     let (main_def_id, span) = match *cx.sess().entry_fn.borrow() {
         Some((id, span, _)) => {
-            (cx.tcx.hir.local_def_id(id), span)
+            (cx.tcx().hir.local_def_id(id), span)
         }
         None => return,
     };
 
-    let instance = Instance::mono(cx.tcx, main_def_id);
+    let instance = Instance::mono(cx.tcx(), main_def_id);
 
-    if !cx.codegen_unit.contains_item(&MonoItem::Fn(instance)) {
+    if !cx.codegen_unit().contains_item(&MonoItem::Fn(instance)) {
         // We want to create the wrapper in the same codegen unit as Rust's main
         // function.
         return;
     }
 
-    let main_llfn = callee::get_fn(cx, instance);
+    let main_llfn = cx.get_fn(instance);
 
     let et = cx.sess().entry_fn.get().map(|e| e.2);
     match et {
-        Some(EntryFnType::Main) => create_entry_fn(cx, span, main_llfn, main_def_id, true),
-        Some(EntryFnType::Start) => create_entry_fn(cx, span, main_llfn, main_def_id, false),
+        Some(EntryFnType::Main) => create_entry_fn::<Bx>(cx, span, main_llfn, main_def_id, true),
+        Some(EntryFnType::Start) => create_entry_fn::<Bx>(cx, span, main_llfn, main_def_id, false),
         None => {}    // Do nothing.
     }
 
-    fn create_entry_fn(
-        cx: &CodegenCx<'ll, '_>,
+    fn create_entry_fn<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
+        cx: &'a Bx::CodegenCx,
         sp: Span,
-        rust_main: &'ll Value,
+        rust_main: Bx::Value,
         rust_main_def_id: DefId,
         use_start_lang_item: bool,
     ) {
-        let llfty = Type::func(&[Type::c_int(cx), Type::i8p(cx).ptr_to()], Type::c_int(cx));
+        let llfty =
+            cx.type_func(&[cx.type_int(), cx.type_ptr_to(cx.type_i8p())], cx.type_int());
 
-        let main_ret_ty = cx.tcx.fn_sig(rust_main_def_id).output();
+        let main_ret_ty = cx.tcx().fn_sig(rust_main_def_id).output();
         // Given that `main()` has no arguments,
         // then its return type cannot have
         // late-bound regions, since late-bound
         // regions must appear in the argument
         // listing.
-        let main_ret_ty = cx.tcx.erase_regions(
+        let main_ret_ty = cx.tcx().erase_regions(
             &main_ret_ty.no_bound_vars().unwrap(),
         );
 
-        if declare::get_defined_value(cx, "main").is_some() {
+        if cx.get_defined_value("main").is_some() {
             // FIXME: We should be smart and show a better diagnostic here.
             cx.sess().struct_span_err(sp, "entry symbol `main` defined multiple times")
                      .help("did you use #[no_mangle] on `fn main`? Use #[start] instead")
@@ -564,30 +547,30 @@ fn create_entry_fn(
             cx.sess().abort_if_errors();
             bug!();
         }
-        let llfn = declare::declare_cfn(cx, "main", llfty);
+        let llfn = cx.declare_cfn("main", llfty);
 
         // `main` should respect same config for frame pointer elimination as rest of code
-        attributes::set_frame_pointer_elimination(cx, llfn);
-        attributes::apply_target_cpu_attr(cx, llfn);
+        cx.set_frame_pointer_elimination(llfn);
+        cx.apply_target_cpu_attr(llfn);
 
-        let bx = Builder::new_block(cx, llfn, "top");
+        let bx = Bx::new_block(&cx, llfn, "top");
 
-        debuginfo::gdb::insert_reference_to_gdb_debug_scripts_section_global(&bx);
+        bx.insert_reference_to_gdb_debug_scripts_section_global();
 
         // Params from native main() used as args for rust start function
-        let param_argc = get_param(llfn, 0);
-        let param_argv = get_param(llfn, 1);
-        let arg_argc = bx.intcast(param_argc, cx.isize_ty, true);
+        let param_argc = cx.get_param(llfn, 0);
+        let param_argv = cx.get_param(llfn, 1);
+        let arg_argc = bx.intcast(param_argc, cx.type_isize(), true);
         let arg_argv = param_argv;
 
         let (start_fn, args) = if use_start_lang_item {
-            let start_def_id = cx.tcx.require_lang_item(StartFnLangItem);
+            let start_def_id = cx.tcx().require_lang_item(StartFnLangItem);
             let start_fn = callee::resolve_and_get_fn(
                 cx,
                 start_def_id,
-                cx.tcx.intern_substs(&[main_ret_ty.into()]),
+                cx.tcx().intern_substs(&[main_ret_ty.into()]),
             );
-            (start_fn, vec![bx.pointercast(rust_main, Type::i8p(cx).ptr_to()),
+            (start_fn, vec![bx.pointercast(rust_main, cx.type_ptr_to(cx.type_i8p())),
                             arg_argc, arg_argv])
         } else {
             debug!("using user-defined start fn");
@@ -595,13 +578,14 @@ fn create_entry_fn(
         };
 
         let result = bx.call(start_fn, &args, None);
-        bx.ret(bx.intcast(result, Type::c_int(cx), true));
+        bx.ret(bx.intcast(result, cx.type_int(), true));
     }
 }
 
-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;
@@ -642,12 +626,12 @@ enum MetadataKind {
     DeflateEncoder::new(&mut compressed, Compression::fast())
         .write_all(&metadata.raw_data).unwrap();
 
-    let llmeta = C_bytes_in_context(metadata_llcx, &compressed);
-    let llconst = C_struct_in_context(metadata_llcx, &[llmeta], false);
+    let llmeta = common::bytes_in_context(metadata_llcx, &compressed);
+    let llconst = common::struct_in_context(metadata_llcx, &[llmeta], false);
     let name = exported_symbols::metadata_symbol_name(tcx);
     let buf = CString::new(name).unwrap();
     let llglobal = unsafe {
-        llvm::LLVMAddGlobal(metadata_llmod, val_ty(llconst), buf.as_ptr())
+        llvm::LLVMAddGlobal(metadata_llmod, common::val_ty(llconst), buf.as_ptr())
     };
     unsafe {
         llvm::LLVMSetInitializer(llglobal, llconst);
@@ -728,10 +712,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<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);
@@ -743,9 +729,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));
 
@@ -764,19 +750,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;
     }
@@ -797,13 +783,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.
     //
@@ -826,11 +812,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 {
@@ -843,10 +827,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.
@@ -860,8 +844,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);
@@ -874,7 +858,7 @@ pub fn codegen_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                      &format!("codegen {}", cgu.name()))
                 });
                 let start_time = Instant::now();
-                let stats = compile_codegen_unit(tcx, *cgu.name());
+                let stats = backend.compile_codegen_unit(tcx, *cgu.name());
                 all_stats.extend(stats);
                 total_codegen_time += start_time.elapsed();
                 false
@@ -896,7 +880,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.
@@ -930,7 +914,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()
@@ -941,7 +925,7 @@ pub fn codegen_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 ///
 /// In the process of working on rust-lang/rust#55238 a mysterious segfault was
 /// stumbled upon. The segfault was never reproduced locally, but it was
-/// suspected to be releated to the fact that codegen worker threads were
+/// suspected to be related to the fact that codegen worker threads were
 /// sticking around by the time the main thread was exiting, causing issues.
 ///
 /// This structure is an attempt to fix that issue where the `codegen_aborted`
@@ -953,37 +937,37 @@ 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);
         }
     }
 }
 
-fn assert_and_save_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
+fn assert_and_save_dep_graph<'ll, 'tcx>(tcx: TyCtxt<'ll, 'tcx, 'tcx>) {
     time(tcx.sess,
          "assert dep graph",
          || rustc_incremental::assert_dep_graph(tcx));
@@ -1082,7 +1066,7 @@ fn load_wasm_imports(&mut self, tcx: TyCtxt, cnum: CrateNum) {
     }
 }
 
-fn compile_codegen_unit<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+pub fn compile_codegen_unit<'ll, 'tcx>(tcx: TyCtxt<'ll, 'tcx, 'tcx>,
                                   cgu_name: InternedString)
                                   -> Stats {
     let start_time = Instant::now();
@@ -1104,64 +1088,49 @@ fn compile_codegen_unit<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                            cost);
     return stats;
 
-    fn module_codegen<'a, 'tcx>(
-        tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    fn module_codegen<'ll, 'tcx>(
+        tcx: TyCtxt<'ll, 'tcx, 'tcx>,
         cgu_name: InternedString)
-        -> (Stats, ModuleCodegen)
+        -> (Stats, ModuleCodegen<ModuleLlvm>)
     {
+        let backend = LlvmCodegenBackend(());
         let cgu = tcx.codegen_unit(cgu_name);
-
         // Instantiate monomorphizations without filling out definitions yet...
-        let llvm_module = ModuleLlvm::new(tcx.sess, &cgu_name.as_str());
+        let llvm_module = backend.new_metadata(tcx.sess, &cgu_name.as_str());
         let stats = {
             let cx = CodegenCx::new(tcx, cgu, &llvm_module);
             let mono_items = cx.codegen_unit
                                .items_in_deterministic_order(cx.tcx);
             for &(mono_item, (linkage, visibility)) in &mono_items {
-                mono_item.predefine(&cx, linkage, visibility);
+                mono_item.predefine::<Builder<&Value>>(&cx, linkage, visibility);
             }
 
             // ... and now that we have everything pre-defined, fill out those definitions.
             for &(mono_item, _) in &mono_items {
-                mono_item.define(&cx);
+                mono_item.define::<Builder<&Value>>(&cx);
             }
 
             // If this codegen unit contains the main function, also create the
             // wrapper here
-            maybe_create_entry_wrapper(&cx);
+            maybe_create_entry_wrapper::<Builder<&Value>>(&cx);
 
             // Run replace-all-uses-with for statics that need it
-            for &(old_g, new_g) in cx.statics_to_rauw.borrow().iter() {
-                unsafe {
-                    let bitcast = llvm::LLVMConstPointerCast(new_g, val_ty(old_g));
-                    llvm::LLVMReplaceAllUsesWith(old_g, bitcast);
-                    llvm::LLVMDeleteGlobal(old_g);
-                }
+            for &(old_g, new_g) in cx.statics_to_rauw().borrow().iter() {
+                cx.static_replace_all_uses(old_g, new_g)
             }
 
             // Create the llvm.used variable
             // This variable has type [N x i8*] and is stored in the llvm.metadata section
-            if !cx.used_statics.borrow().is_empty() {
-                let name = const_cstr!("llvm.used");
-                let section = const_cstr!("llvm.metadata");
-                let array = C_array(Type::i8(&cx).ptr_to(), &*cx.used_statics.borrow());
-
-                unsafe {
-                    let g = llvm::LLVMAddGlobal(cx.llmod,
-                                                val_ty(array),
-                                                name.as_ptr());
-                    llvm::LLVMSetInitializer(g, array);
-                    llvm::LLVMRustSetLinkage(g, llvm::Linkage::AppendingLinkage);
-                    llvm::LLVMSetSection(g, section.as_ptr());
-                }
+            if !cx.used_statics().borrow().is_empty() {
+                cx.create_used_variable()
             }
 
             // Finalize debuginfo
             if cx.sess().opts.debuginfo != DebugInfo::None {
-                debuginfo::finalize(&cx);
+                cx.debuginfo_finalize();
             }
 
-            cx.stats.into_inner()
+            cx.consume_stats().into_inner()
         };
 
         (stats, ModuleCodegen {
@@ -1226,25 +1195,3 @@ pub fn visibility_to_llvm(linkage: Visibility) -> llvm::Visibility {
         Visibility::Protected => llvm::Visibility::Protected,
     }
 }
-
-// FIXME(mw): Anything that is produced via DepGraph::with_task() must implement
-//            the HashStable trait. Normally DepGraph::with_task() calls are
-//            hidden behind queries, but CGU creation is a special case in two
-//            ways: (1) it's not a query and (2) CGU are output nodes, so their
-//            Fingerprints are not actually needed. It remains to be clarified
-//            how exactly this case will be handled in the red/green system but
-//            for now we content ourselves with providing a no-op HashStable
-//            implementation for CGUs.
-mod temp_stable_hash_impls {
-    use rustc_data_structures::stable_hasher::{StableHasherResult, StableHasher,
-                                               HashStable};
-    use ModuleCodegen;
-
-    impl<HCX> HashStable<HCX> for ModuleCodegen {
-        fn hash_stable<W: StableHasherResult>(&self,
-                                              _: &mut HCX,
-                                              _: &mut StableHasher<W>) {
-            // do nothing
-        }
-    }
-}