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-08-29 18:42:25 +0200
committerEduard-Mihai Burtescu <edy.burt@gmail.com>2018-11-16 14:11:59 +0200
commit4cc18d3de50b6540e53ddcfefb88dee9ed991264 (patch)
tree7d7cc48d8ddff1b195f9b3caec2138a104b4dc12 /src/librustc_codegen_llvm
parent3aee77277efbac0b9b14b2097ea8a2c449fb1fc3 (diff)
downloadrust-4cc18d3de50b6540e53ddcfefb88dee9ed991264.tar.gz
rust-4cc18d3de50b6540e53ddcfefb88dee9ed991264.zip
CommonWriteMethods are not static any more
Diffstat (limited to 'src/librustc_codegen_llvm')
-rw-r--r--src/librustc_codegen_llvm/back/lto.rs2
-rw-r--r--src/librustc_codegen_llvm/back/write.rs66
-rw-r--r--src/librustc_codegen_llvm/base.rs25
-rw-r--r--src/librustc_codegen_llvm/builder.rs16
-rw-r--r--src/librustc_codegen_llvm/callee.rs4
-rw-r--r--src/librustc_codegen_llvm/common.rs64
-rw-r--r--src/librustc_codegen_llvm/consts.rs6
-rw-r--r--src/librustc_codegen_llvm/interfaces/common.rs15
-rw-r--r--src/librustc_codegen_llvm/lib.rs58
-rw-r--r--src/librustc_codegen_llvm/mir/rvalue.rs8
10 files changed, 179 insertions, 85 deletions
diff --git a/src/librustc_codegen_llvm/back/lto.rs b/src/librustc_codegen_llvm/back/lto.rs
index 60b06c579cb..95b1b6ff3ce 100644
--- a/src/librustc_codegen_llvm/back/lto.rs
+++ b/src/librustc_codegen_llvm/back/lto.rs
@@ -26,6 +26,7 @@ use rustc_data_structures::fx::FxHashMap;
 use rustc_codegen_utils::symbol_export;
 use time_graph::Timeline;
 use {ModuleCodegen, ModuleLlvm, ModuleKind};
+use std::marker::PhantomData;
 
 use libc;
 
@@ -767,6 +768,7 @@ impl ThinModule {
                 llmod_raw,
                 llcx,
                 tm,
+                phantom: PhantomData
             },
             name: self.name().to_string(),
             kind: ModuleKind::Regular,
diff --git a/src/librustc_codegen_llvm/back/write.rs b/src/librustc_codegen_llvm/back/write.rs
index 5d23ff27c49..3c32da43031 100644
--- a/src/librustc_codegen_llvm/back/write.rs
+++ b/src/librustc_codegen_llvm/back/write.rs
@@ -24,7 +24,7 @@ use rustc::session::config::{self, OutputFilenames, OutputType, Passes, Sanitize
 use rustc::session::Session;
 use rustc::util::nodemap::FxHashMap;
 use time_graph::{self, TimeGraph, Timeline};
-use llvm::{self, DiagnosticInfo, PassManager, SMDiagnostic};
+use llvm::{self, DiagnosticInfo, PassManager, SMDiagnostic, BasicBlock, True};
 use llvm_util;
 use {CodegenResults, ModuleCodegen, CompiledModule, ModuleKind, // ModuleLlvm,
      CachedModuleCodegen};
@@ -45,10 +45,12 @@ use syntax::ext::hygiene::Mark;
 use syntax_pos::MultiSpan;
 use syntax_pos::symbol::Symbol;
 use type_::Type;
-use context::{is_pie_binary, get_reloc_model, CodegenCx};
-use interfaces::CommonWriteMethods;
+use context::{is_pie_binary, get_reloc_model};
+use interfaces::{Backend, CommonWriteMethods};
 use jobserver::{Client, Acquired};
 use rustc_demangle;
+use value::Value;
+use std::marker::PhantomData;
 
 use std::any::Any;
 use std::ffi::{CString, CStr};
@@ -351,7 +353,7 @@ struct AssemblerCommand {
 
 /// Additional resources used by optimize_and_codegen (not module specific)
 #[derive(Clone)]
-pub struct CodegenContext {
+pub struct CodegenContext<'ll> {
     // Resources needed when running LTO
     pub time_passes: bool,
     pub lto: Lto,
@@ -393,9 +395,12 @@ pub struct CodegenContext {
     time_graph: Option<TimeGraph>,
     // The assembler command if no_integrated_as option is enabled, None otherwise
     assembler_cmd: Option<Arc<AssemblerCommand>>,
+    // This field is used to give a lifetime parameter to the struct so that it can implement
+    // the Backend trait.
+    phantom: PhantomData<&'ll ()>
 }
 
-impl CodegenContext {
+impl CodegenContext<'ll> {
     pub fn create_diag_handler(&self) -> Handler {
         Handler::with_emitter(true, false, Box::new(self.diag_emitter.clone()))
     }
@@ -423,13 +428,49 @@ impl CodegenContext {
     }
 }
 
+impl<'ll> Backend for CodegenContext<'ll> {
+    type Value = &'ll Value;
+    type BasicBlock = &'ll BasicBlock;
+    type Type = &'ll Type;
+    type Context = &'ll llvm::Context;
+}
+
+impl CommonWriteMethods for CodegenContext<'ll> {
+    fn val_ty(&self, v: &'ll Value) -> &'ll Type {
+        unsafe {
+            llvm::LLVMTypeOf(v)
+        }
+    }
+
+    fn c_bytes_in_context(&self, llcx: &'ll llvm::Context, bytes: &[u8]) -> &'ll Value {
+        unsafe {
+            let ptr = bytes.as_ptr() as *const c_char;
+            return llvm::LLVMConstStringInContext(llcx, ptr, bytes.len() as c_uint, True);
+        }
+    }
+
+    fn c_struct_in_context(
+        &self,
+        llcx: &'a llvm::Context,
+        elts: &[&'a Value],
+        packed: bool,
+    ) -> &'a Value {
+        unsafe {
+            llvm::LLVMConstStructInContext(llcx,
+                                           elts.as_ptr(), elts.len() as c_uint,
+                                           packed as llvm::Bool)
+        }
+    }
+}
+
+
 pub struct DiagnosticHandlers<'a> {
-    data: *mut (&'a CodegenContext, &'a Handler),
+    data: *mut (&'a CodegenContext<'a>, &'a Handler),
     llcx: &'a llvm::Context,
 }
 
 impl<'a> DiagnosticHandlers<'a> {
-    pub fn new(cgcx: &'a CodegenContext,
+    pub fn new(cgcx: &'a CodegenContext<'a>,
                handler: &'a Handler,
                llcx: &'a llvm::Context) -> Self {
         let data = Box::into_raw(Box::new((cgcx, handler)));
@@ -884,10 +925,10 @@ unsafe fn embed_bitcode(cgcx: &CodegenContext,
                         llcx: &llvm::Context,
                         llmod: &llvm::Module,
                         bitcode: Option<&[u8]>) {
-    let llconst = CodegenCx::c_bytes_in_context(llcx, bitcode.unwrap_or(&[]));
+    let llconst = cgcx.c_bytes_in_context(llcx, bitcode.unwrap_or(&[]));
     let llglobal = llvm::LLVMAddGlobal(
         llmod,
-        CodegenCx::val_ty(llconst),
+        cgcx.val_ty(llconst),
         "rustc.embedded.module\0".as_ptr() as *const _,
     );
     llvm::LLVMSetInitializer(llglobal, llconst);
@@ -904,10 +945,10 @@ unsafe fn embed_bitcode(cgcx: &CodegenContext,
     llvm::LLVMRustSetLinkage(llglobal, llvm::Linkage::PrivateLinkage);
     llvm::LLVMSetGlobalConstant(llglobal, llvm::True);
 
-    let llconst = CodegenCx::c_bytes_in_context(llcx, &[]);
+    let llconst = cgcx.c_bytes_in_context(llcx, &[]);
     let llglobal = llvm::LLVMAddGlobal(
         llmod,
-        CodegenCx::val_ty(llconst),
+        cgcx.val_ty(llconst),
         "rustc.embedded.cmdline\0".as_ptr() as *const _,
     );
     llvm::LLVMSetInitializer(llglobal, llconst);
@@ -1614,6 +1655,7 @@ fn start_executing_work(tcx: TyCtxt,
         target_pointer_width: tcx.sess.target.target.target_pointer_width.clone(),
         debuginfo: tcx.sess.opts.debuginfo,
         assembler_cmd,
+        phantom: PhantomData
     };
 
     // This is the "main loop" of parallel work happening for parallel codegen.
@@ -2108,7 +2150,7 @@ pub const CODEGEN_WORK_PACKAGE_KIND: time_graph::WorkPackageKind =
 const LLVM_WORK_PACKAGE_KIND: time_graph::WorkPackageKind =
     time_graph::WorkPackageKind(&["#7DB67A", "#C6EEC4", "#ACDAAA", "#579354", "#3E6F3C"]);
 
-fn spawn_work(cgcx: CodegenContext, work: WorkItem) {
+fn spawn_work(cgcx: CodegenContext<'static>, work: WorkItem) {
     let depth = time_depth();
 
     thread::spawn(move || {
diff --git a/src/librustc_codegen_llvm/base.rs b/src/librustc_codegen_llvm/base.rs
index 2a4d549adcb..6a2f437b1da 100644
--- a/src/librustc_codegen_llvm/base.rs
+++ b/src/librustc_codegen_llvm/base.rs
@@ -334,12 +334,13 @@ pub fn coerce_unsized_into(
 }
 
 pub fn cast_shift_expr_rhs(
-    cx: &Builder<'_, 'll, '_>, op: hir::BinOpKind, lhs: &'ll Value, rhs: &'ll Value
+    bx: &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))
+    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,
+fn cast_shift_rhs<'ll, F, G>(bx: &Builder<'_, 'll, '_>,
+                             op: hir::BinOpKind,
                              lhs: &'ll Value,
                              rhs: &'ll Value,
                              trunc: F,
@@ -350,8 +351,8 @@ fn cast_shift_rhs<'ll, F, G>(op: hir::BinOpKind,
 {
     // Shifts may have any size int on the rhs
     if op.is_shift() {
-        let mut rhs_llty = CodegenCx::val_ty(rhs);
-        let mut lhs_llty = CodegenCx::val_ty(lhs);
+        let mut rhs_llty = bx.cx().val_ty(rhs);
+        let mut lhs_llty = bx.cx().val_ty(lhs);
         if rhs_llty.kind() == TypeKind::Vector {
             rhs_llty = rhs_llty.element_type()
         }
@@ -392,7 +393,7 @@ pub fn from_immediate<'a, 'll: 'a, 'tcx: 'll>(
     bx: &Builder<'_ ,'ll, '_, &'ll Value>,
     val: &'ll Value
 ) -> &'ll Value {
-    if CodegenCx::val_ty(val) == Type::i1(bx.cx()) {
+    if bx.cx().val_ty(val) == Type::i1(bx.cx()) {
         bx.zext(val, Type::i8(bx.cx()))
     } else {
         val
@@ -433,7 +434,7 @@ pub fn call_memcpy<'a, 'll: 'a, 'tcx: 'll>(
     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, CodegenCx::val_ty(val).ptr_to());
+        let ptr = bx.pointercast(dst, bx.cx().val_ty(val).ptr_to());
         bx.store_with_flags(val, ptr, dst_align, flags);
         return;
     }
@@ -648,12 +649,12 @@ fn write_metadata<'a, 'gcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>,
     DeflateEncoder::new(&mut compressed, Compression::fast())
         .write_all(&metadata.raw_data).unwrap();
 
-    let llmeta = CodegenCx::c_bytes_in_context(metadata_llcx, &compressed);
-    let llconst = CodegenCx::c_struct_in_context(metadata_llcx, &[llmeta], false);
+    let llmeta = llvm_module.c_bytes_in_context(metadata_llcx, &compressed);
+    let llconst = llvm_module.c_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, CodegenCx::val_ty(llconst), buf.as_ptr())
+        llvm::LLVMAddGlobal(metadata_llmod, llvm_module.val_ty(llconst), buf.as_ptr())
     };
     unsafe {
         llvm::LLVMSetInitializer(llglobal, llconst);
@@ -1139,7 +1140,7 @@ fn compile_codegen_unit<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             // 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, CodegenCx::val_ty(old_g));
+                    let bitcast = llvm::LLVMConstPointerCast(new_g, cx.val_ty(old_g));
                     llvm::LLVMReplaceAllUsesWith(old_g, bitcast);
                     llvm::LLVMDeleteGlobal(old_g);
                 }
@@ -1154,7 +1155,7 @@ fn compile_codegen_unit<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
                 unsafe {
                     let g = llvm::LLVMAddGlobal(cx.llmod,
-                                                CodegenCx::val_ty(array),
+                                                cx.val_ty(array),
                                                 name.as_ptr());
                     llvm::LLVMSetInitializer(g, array);
                     llvm::LLVMRustSetLinkage(g, llvm::Linkage::AppendingLinkage);
diff --git a/src/librustc_codegen_llvm/builder.rs b/src/librustc_codegen_llvm/builder.rs
index 8a6cf1335cd..2aaccd3c4f8 100644
--- a/src/librustc_codegen_llvm/builder.rs
+++ b/src/librustc_codegen_llvm/builder.rs
@@ -527,7 +527,7 @@ impl BuilderMethods<'a, 'll, 'tcx> for Builder<'a, 'll, 'tcx> {
         }
 
         unsafe {
-            let llty = CodegenCx::val_ty(load);
+            let llty = self.cx.val_ty(load);
             let v = [
                 self.cx.c_uint_big(llty, range.start),
                 self.cx.c_uint_big(llty, range.end)
@@ -760,7 +760,7 @@ impl BuilderMethods<'a, 'll, 'tcx> for Builder<'a, 'll, 'tcx> {
 
         let argtys = inputs.iter().map(|v| {
             debug!("Asm Input Type: {:?}", *v);
-            CodegenCx::val_ty(*v)
+            self.cx.val_ty(*v)
         }).collect::<Vec<_>>();
 
         debug!("Asm Output Type: {:?}", output);
@@ -859,7 +859,7 @@ impl BuilderMethods<'a, 'll, 'tcx> for Builder<'a, 'll, 'tcx> {
 
     fn vector_splat(&self, num_elts: usize, elt: &'ll Value) -> &'ll Value {
         unsafe {
-            let elt_ty = CodegenCx::val_ty(elt);
+            let elt_ty = self.cx.val_ty(elt);
             let undef = llvm::LLVMGetUndef(type_::Type::vector(elt_ty, num_elts as u64));
             let vec = self.insert_element(undef, elt, CodegenCx::c_i32(self.cx, 0));
             let vec_i32_ty = type_::Type::vector(type_::Type::i32(self.cx), num_elts as u64);
@@ -1139,8 +1139,8 @@ impl BuilderMethods<'a, 'll, 'tcx> for Builder<'a, 'll, 'tcx> {
     fn check_store<'b>(&self,
                        val: &'ll Value,
                        ptr: &'ll Value) -> &'ll Value {
-        let dest_ptr_ty = CodegenCx::val_ty(ptr);
-        let stored_ty = CodegenCx::val_ty(val);
+        let dest_ptr_ty = self.cx.val_ty(ptr);
+        let stored_ty = self.cx.val_ty(val);
         let stored_ptr_ty = stored_ty.ptr_to();
 
         assert_eq!(dest_ptr_ty.kind(), llvm::TypeKind::Pointer);
@@ -1160,7 +1160,7 @@ impl BuilderMethods<'a, 'll, 'tcx> for Builder<'a, 'll, 'tcx> {
                       typ: &str,
                       llfn: &'ll Value,
                       args: &'b [&'ll Value]) -> Cow<'b, [&'ll Value]> {
-        let mut fn_ty = CodegenCx::val_ty(llfn);
+        let mut fn_ty = self.cx.val_ty(llfn);
         // Strip off pointers
         while fn_ty.kind() == llvm::TypeKind::Pointer {
             fn_ty = fn_ty.element_type();
@@ -1172,7 +1172,7 @@ impl BuilderMethods<'a, 'll, 'tcx> for Builder<'a, 'll, 'tcx> {
         let param_tys = fn_ty.func_params();
 
         let all_args_match = param_tys.iter()
-            .zip(args.iter().map(|&v| CodegenCx::val_ty(v)))
+            .zip(args.iter().map(|&v| self.cx().val_ty(v)))
             .all(|(expected_ty, actual_ty)| *expected_ty == actual_ty);
 
         if all_args_match {
@@ -1183,7 +1183,7 @@ impl BuilderMethods<'a, 'll, 'tcx> for Builder<'a, 'll, 'tcx> {
             .zip(args.iter())
             .enumerate()
             .map(|(i, (expected_ty, &actual_val))| {
-                let actual_ty = CodegenCx::val_ty(actual_val);
+                let actual_ty = self.cx().val_ty(actual_val);
                 if expected_ty != actual_ty {
                     debug!("Type mismatch in function call of {:?}. \
                             Expected {:?} for param {}, got {:?}; injecting bitcast",
diff --git a/src/librustc_codegen_llvm/callee.rs b/src/librustc_codegen_llvm/callee.rs
index a593cd64efe..a58692d5f41 100644
--- a/src/librustc_codegen_llvm/callee.rs
+++ b/src/librustc_codegen_llvm/callee.rs
@@ -84,7 +84,7 @@ pub fn get_fn(
         // This can occur on either a crate-local or crate-external
         // reference. It also occurs when testing libcore and in some
         // other weird situations. Annoying.
-        if CodegenCx::val_ty(llfn) != llptrty {
+        if cx.val_ty(llfn) != llptrty {
             debug!("get_fn: casting {:?} to {:?}", llfn, llptrty);
             consts::ptrcast(llfn, llptrty)
         } else {
@@ -93,7 +93,7 @@ pub fn get_fn(
         }
     } else {
         let llfn = declare::declare_fn(cx, &sym, sig);
-        assert_eq!(CodegenCx::val_ty(llfn), llptrty);
+        assert_eq!(cx.val_ty(llfn), llptrty);
         debug!("get_fn: not casting pointer!");
 
         if instance.def.is_inline(tcx) {
diff --git a/src/librustc_codegen_llvm/common.rs b/src/librustc_codegen_llvm/common.rs
index cf88a973162..ba8d92d37ac 100644
--- a/src/librustc_codegen_llvm/common.rs
+++ b/src/librustc_codegen_llvm/common.rs
@@ -282,7 +282,7 @@ impl<'ll, 'tcx : 'll> CommonMethods for CodegenCx<'ll, 'tcx> {
                                                     s.len() as c_uint,
                                                     !null_terminated as Bool);
             let sym = &self.generate_local_symbol_name("str");
-            let g = declare::define_global(&self, &sym[..], Self::val_ty(sc)).unwrap_or_else(||{
+            let g = declare::define_global(&self, &sym[..], &self.val_ty(sc)).unwrap_or_else(||{
                 bug!("symbol `{}` is already defined", sym);
             });
             llvm::LLVMSetInitializer(g, sc);
@@ -318,19 +318,7 @@ impl<'ll, 'tcx : 'll> CommonMethods for CodegenCx<'ll, 'tcx> {
         elts: &[&'ll Value],
         packed: bool
     ) -> &'ll Value {
-        Self::c_struct_in_context(&self.llcx, elts, packed)
-    }
-
-    fn c_struct_in_context(
-        llcx: &'a llvm::Context,
-        elts: &[&'a Value],
-        packed: bool,
-    ) -> &'a Value {
-        unsafe {
-            llvm::LLVMConstStructInContext(llcx,
-                                           elts.as_ptr(), elts.len() as c_uint,
-                                           packed as Bool)
-        }
+        &self.c_struct_in_context(&self.llcx, elts, packed)
     }
 
     fn c_array(ty: &'ll Type, elts: &[&'ll Value]) -> &'ll Value {
@@ -346,7 +334,7 @@ impl<'ll, 'tcx : 'll> CommonMethods for CodegenCx<'ll, 'tcx> {
     }
 
     fn c_bytes(&self, bytes: &[u8]) -> &'ll Value {
-        Self::c_bytes_in_context(&self.llcx, bytes)
+        &self.c_bytes_in_context(&self.llcx, bytes)
     }
 
     fn const_get_elt(v: &'ll Value, idx: u64) -> &'ll Value {
@@ -411,6 +399,35 @@ impl<'ll, 'tcx : 'll> CommonMethods for CodegenCx<'ll, 'tcx> {
     }
 }
 
+impl<'ll, 'tcx : 'll> CommonWriteMethods for CodegenCx<'ll, 'tcx> {
+    fn val_ty(&self, v: &'ll Value) -> &'ll Type {
+        unsafe {
+            llvm::LLVMTypeOf(v)
+        }
+    }
+
+    fn c_bytes_in_context(&self, llcx: &'ll llvm::Context, bytes: &[u8]) -> &'ll Value {
+        unsafe {
+            let ptr = bytes.as_ptr() as *const c_char;
+            return llvm::LLVMConstStringInContext(llcx, ptr, bytes.len() as c_uint, True);
+        }
+    }
+
+    fn c_struct_in_context(
+        &self,
+        llcx: &'a llvm::Context,
+        elts: &[&'a Value],
+        packed: bool,
+    ) -> &'a Value {
+        unsafe {
+            llvm::LLVMConstStructInContext(llcx,
+                                           elts.as_ptr(), elts.len() as c_uint,
+                                           packed as Bool)
+        }
+    }
+}
+
+
 #[inline]
 fn hi_lo_to_u128(lo: u64, hi: u64) -> u128 {
     ((hi as u128) << 64) | (lo as u128)
@@ -461,7 +478,7 @@ pub fn build_unchecked_rshift(
 }
 
 fn shift_mask_rhs(bx: &Builder<'a, 'll, 'tcx>, rhs: &'ll Value) -> &'ll Value {
-    let rhs_llty = CodegenCx::val_ty(rhs);
+    let rhs_llty = bx.cx().val_ty(rhs);
     bx.and(rhs, shift_mask_val(bx, rhs_llty, rhs_llty, false))
 }
 
@@ -489,18 +506,3 @@ pub fn shift_mask_val(
         _ => bug!("shift_mask_val: expected Integer or Vector, found {:?}", kind),
     }
 }
-
-impl<'ll, 'tcx : 'll> CommonWriteMethods for CodegenCx<'ll, 'tcx> {
-    fn val_ty(v: &'ll Value) -> &'ll Type {
-        unsafe {
-            llvm::LLVMTypeOf(v)
-        }
-    }
-
-    fn c_bytes_in_context(llcx: &'ll llvm::Context, bytes: &[u8]) -> &'ll Value {
-        unsafe {
-            let ptr = bytes.as_ptr() as *const c_char;
-            return llvm::LLVMConstStringInContext(llcx, ptr, bytes.len() as c_uint, True);
-        }
-    }
-}
diff --git a/src/librustc_codegen_llvm/consts.rs b/src/librustc_codegen_llvm/consts.rs
index a97614e4e50..f8f759365c0 100644
--- a/src/librustc_codegen_llvm/consts.rs
+++ b/src/librustc_codegen_llvm/consts.rs
@@ -74,13 +74,13 @@ pub fn addr_of_mut(
             Some(kind) if !cx.tcx.sess.fewer_names() => {
                 let name = cx.generate_local_symbol_name(kind);
                 let gv = declare::define_global(cx, &name[..],
-                    CodegenCx::val_ty(cv)).unwrap_or_else(||{
+                    cx.val_ty(cv)).unwrap_or_else(||{
                         bug!("symbol `{}` is already defined", name);
                 });
                 llvm::LLVMRustSetLinkage(gv, llvm::Linkage::PrivateLinkage);
                 gv
             },
-            _ => declare::define_private_global(cx, CodegenCx::val_ty(cv)),
+            _ => declare::define_private_global(cx, cx.val_ty(cv)),
         };
         llvm::LLVMSetInitializer(gv, cv);
         set_global_alignment(cx, gv, align);
@@ -312,7 +312,7 @@ pub fn codegen_static<'a, 'tcx>(
 
         // boolean SSA values are i1, but they have to be stored in i8 slots,
         // otherwise some LLVM optimization passes don't work as expected
-        let mut val_llty = CodegenCx::val_ty(v);
+        let mut val_llty = cx.val_ty(v);
         let v = if val_llty == Type::i1(cx) {
             val_llty = Type::i8(cx);
             llvm::LLVMConstZExt(v, val_llty)
diff --git a/src/librustc_codegen_llvm/interfaces/common.rs b/src/librustc_codegen_llvm/interfaces/common.rs
index f58338f384f..9eaf94cff66 100644
--- a/src/librustc_codegen_llvm/interfaces/common.rs
+++ b/src/librustc_codegen_llvm/interfaces/common.rs
@@ -40,11 +40,6 @@ pub trait CommonMethods : Backend + CommonWriteMethods {
         elts: &[Self::Value],
         packed: bool
     ) -> Self::Value;
-    fn c_struct_in_context(
-        llcx: Self::Context,
-        elts: &[Self::Value],
-        packed: bool,
-    ) -> Self::Value;
     fn c_array(ty: Self::Type, elts: &[Self::Value]) -> Self::Value;
     fn c_vector(elts: &[Self::Value]) -> Self::Value;
     fn c_bytes(&self, bytes: &[u8]) -> Self::Value;
@@ -58,6 +53,12 @@ pub trait CommonMethods : Backend + CommonWriteMethods {
 }
 
 pub trait CommonWriteMethods : Backend {
-        fn val_ty(v: Self::Value) -> Self::Type;
-        fn c_bytes_in_context(llcx: Self::Context, bytes: &[u8]) -> Self::Value;
+        fn val_ty(&self, v: Self::Value) -> Self::Type;
+        fn c_bytes_in_context(&self, llcx: Self::Context, bytes: &[u8]) -> Self::Value;
+        fn c_struct_in_context(
+            &self,
+            llcx: Self::Context,
+            elts: &[Self::Value],
+            packed: bool,
+        ) -> Self::Value;
 }
diff --git a/src/librustc_codegen_llvm/lib.rs b/src/librustc_codegen_llvm/lib.rs
index 43942b0db85..2ef90c03c67 100644
--- a/src/librustc_codegen_llvm/lib.rs
+++ b/src/librustc_codegen_llvm/lib.rs
@@ -68,10 +68,15 @@ extern crate tempfile;
 extern crate memmap;
 
 use back::bytecode::RLIB_BYTECODE_EXTENSION;
+use interfaces::{Backend, CommonWriteMethods};
+use value::Value;
+use type_::Type;
 
 pub use llvm_util::target_features;
 use std::any::Any;
 use std::sync::mpsc;
+use std::marker::PhantomData;
+use libc::{c_uint, c_char};
 use rustc_data_structures::sync::Lrc;
 
 use rustc::dep_graph::DepGraph;
@@ -273,7 +278,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: ModuleLlvm<'static>,
     kind: ModuleKind,
 }
 
@@ -315,16 +320,24 @@ impl ModuleCodegen {
     }
 }
 
-struct ModuleLlvm {
+struct ModuleLlvm<'ll> {
     llcx: &'static mut llvm::Context,
     llmod_raw: *const llvm::Module,
     tm: &'static mut llvm::TargetMachine,
+    phantom: PhantomData<&'ll ()>
 }
 
-unsafe impl Send for ModuleLlvm { }
-unsafe impl Sync for ModuleLlvm { }
+impl<'ll> Backend for ModuleLlvm<'ll> {
+    type Value = &'ll Value;
+    type BasicBlock = &'ll llvm::BasicBlock;
+    type Type = &'ll Type;
+    type Context = &'ll llvm::Context;
+}
+
+unsafe impl Send for ModuleLlvm<'ll> { }
+unsafe impl Sync for ModuleLlvm<'ll> { }
 
-impl ModuleLlvm {
+impl ModuleLlvm<'ll> {
     fn new(sess: &Session, mod_name: &str) -> Self {
         unsafe {
             let llcx = llvm::LLVMRustContextCreate(sess.fewer_names());
@@ -334,6 +347,7 @@ impl ModuleLlvm {
                 llmod_raw,
                 llcx,
                 tm: create_target_machine(sess, false),
+                phantom: PhantomData
             }
         }
     }
@@ -345,7 +359,39 @@ impl ModuleLlvm {
     }
 }
 
-impl Drop for ModuleLlvm {
+impl CommonWriteMethods for ModuleLlvm<'ll> {
+    fn val_ty(&self, v: &'ll Value) -> &'ll Type {
+        unsafe {
+            llvm::LLVMTypeOf(v)
+        }
+    }
+
+    fn c_bytes_in_context(&self, llcx: &'ll llvm::Context, bytes: &[u8]) -> &'ll Value {
+        unsafe {
+            let ptr = bytes.as_ptr() as *const c_char;
+            return llvm::LLVMConstStringInContext(
+                llcx,
+                ptr,
+                bytes.len() as c_uint,
+                llvm::True);
+        }
+    }
+
+    fn c_struct_in_context(
+        &self,
+        llcx: &'a llvm::Context,
+        elts: &[&'a Value],
+        packed: bool,
+    ) -> &'a Value {
+        unsafe {
+            llvm::LLVMConstStructInContext(llcx,
+                                           elts.as_ptr(), elts.len() as c_uint,
+                                           packed as llvm::Bool)
+        }
+    }
+}
+
+impl Drop for ModuleLlvm<'ll> {
     fn drop(&mut self) {
         unsafe {
             llvm::LLVMContextDispose(&mut *(self.llcx as *mut _));
diff --git a/src/librustc_codegen_llvm/mir/rvalue.rs b/src/librustc_codegen_llvm/mir/rvalue.rs
index 889bfeeb8ca..3c469cffaf3 100644
--- a/src/librustc_codegen_llvm/mir/rvalue.rs
+++ b/src/librustc_codegen_llvm/mir/rvalue.rs
@@ -118,7 +118,7 @@ impl FunctionCx<'a, 'll, 'tcx, &'ll Value> {
 
                     // Use llvm.memset.p0i8.* to initialize byte arrays
                     let v = base::from_immediate(&bx, v);
-                    if CodegenCx::val_ty(v) == Type::i8(bx.cx()) {
+                    if bx.cx().val_ty(v) == Type::i8(bx.cx()) {
                         base::call_memset(&bx, start, v, size, align, false);
                         return bx;
                     }
@@ -132,7 +132,7 @@ impl FunctionCx<'a, 'll, 'tcx, &'ll Value> {
                 let next_bx = bx.build_sibling_block("repeat_loop_next");
 
                 bx.br(header_bx.llbb());
-                let current = header_bx.phi(CodegenCx::val_ty(start), &[start], &[bx.llbb()]);
+                let current = header_bx.phi(bx.cx().val_ty(start), &[start], &[bx.llbb()]);
 
                 let keep_going = header_bx.icmp(IntPredicate::IntNE, current, end);
                 header_bx.cond_br(keep_going, body_bx.llbb(), next_bx.llbb());
@@ -705,8 +705,8 @@ impl FunctionCx<'a, 'll, 'tcx, &'ll Value> {
                  bx.extract_value(res, 1))
             }
             mir::BinOp::Shl | mir::BinOp::Shr => {
-                let lhs_llty = CodegenCx::val_ty(lhs);
-                let rhs_llty = CodegenCx::val_ty(rhs);
+                let lhs_llty = bx.cx().val_ty(lhs);
+                let rhs_llty = bx.cx().val_ty(rhs);
                 let invert_mask = common::shift_mask_val(&bx, lhs_llty, rhs_llty, true);
                 let outer_bits = bx.and(rhs, invert_mask);