about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/Cargo.lock3
-rw-r--r--src/librustc_codegen_llvm/abi.rs77
-rw-r--r--src/librustc_codegen_llvm/allocator.rs7
-rw-r--r--src/librustc_codegen_llvm/asm.rs13
-rw-r--r--src/librustc_codegen_llvm/attributes.rs20
-rw-r--r--src/librustc_codegen_llvm/back/archive.rs26
-rw-r--r--src/librustc_codegen_llvm/back/lto.rs363
-rw-r--r--src/librustc_codegen_llvm/back/write.rs456
-rw-r--r--src/librustc_codegen_llvm/base.rs244
-rw-r--r--src/librustc_codegen_llvm/builder.rs699
-rw-r--r--src/librustc_codegen_llvm/callee.rs21
-rw-r--r--src/librustc_codegen_llvm/common.rs132
-rw-r--r--src/librustc_codegen_llvm/consts.rs54
-rw-r--r--src/librustc_codegen_llvm/context.rs191
-rw-r--r--src/librustc_codegen_llvm/debuginfo/create_scope_map.rs34
-rw-r--r--src/librustc_codegen_llvm/debuginfo/gdb.rs16
-rw-r--r--src/librustc_codegen_llvm/debuginfo/metadata.rs432
-rw-r--r--src/librustc_codegen_llvm/debuginfo/mod.rs133
-rw-r--r--src/librustc_codegen_llvm/debuginfo/namespace.rs5
-rw-r--r--src/librustc_codegen_llvm/debuginfo/source_loc.rs26
-rw-r--r--src/librustc_codegen_llvm/debuginfo/utils.rs14
-rw-r--r--src/librustc_codegen_llvm/declare.rs67
-rw-r--r--src/librustc_codegen_llvm/glue.rs15
-rw-r--r--src/librustc_codegen_llvm/intrinsic.rs180
-rw-r--r--src/librustc_codegen_llvm/lib.rs43
-rw-r--r--src/librustc_codegen_llvm/llvm/archive_ro.rs (renamed from src/librustc_llvm/archive_ro.rs)55
-rw-r--r--src/librustc_codegen_llvm/llvm/diagnostic.rs (renamed from src/librustc_llvm/diagnostic.rs)76
-rw-r--r--src/librustc_codegen_llvm/llvm/ffi.rs1633
-rw-r--r--src/librustc_codegen_llvm/llvm/mod.rs281
-rw-r--r--src/librustc_codegen_llvm/llvm_util.rs2
-rw-r--r--src/librustc_codegen_llvm/metadata.rs6
-rw-r--r--src/librustc_codegen_llvm/meth.rs24
-rw-r--r--src/librustc_codegen_llvm/mir/analyze.rs14
-rw-r--r--src/librustc_codegen_llvm/mir/block.rs78
-rw-r--r--src/librustc_codegen_llvm/mir/constant.rs37
-rw-r--r--src/librustc_codegen_llvm/mir/mod.rs86
-rw-r--r--src/librustc_codegen_llvm/mir/operand.rs93
-rw-r--r--src/librustc_codegen_llvm/mir/place.rs99
-rw-r--r--src/librustc_codegen_llvm/mir/rvalue.rs92
-rw-r--r--src/librustc_codegen_llvm/mir/statement.rs6
-rw-r--r--src/librustc_codegen_llvm/type_.rs234
-rw-r--r--src/librustc_codegen_llvm/type_of.rs30
-rw-r--r--src/librustc_codegen_llvm/value.rs21
-rw-r--r--src/librustc_llvm/Cargo.toml5
-rw-r--r--src/librustc_llvm/build.rs1
-rw-r--r--src/librustc_llvm/ffi.rs1800
-rw-r--r--src/librustc_llvm/lib.rs318
-rw-r--r--src/librustc_target/lib.rs6
-rw-r--r--src/rustllvm/ArchiveWrapper.cpp2
-rw-r--r--src/rustllvm/PassWrapper.cpp24
-rw-r--r--src/rustllvm/RustWrapper.cpp9
51 files changed, 3982 insertions, 4321 deletions
diff --git a/src/Cargo.lock b/src/Cargo.lock
index 89daa8e09c7..be32872dad8 100644
--- a/src/Cargo.lock
+++ b/src/Cargo.lock
@@ -2222,11 +2222,8 @@ dependencies = [
 name = "rustc_llvm"
 version = "0.0.0"
 dependencies = [
- "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "build_helper 0.1.0",
  "cc 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc_cratesio_shim 0.0.0",
 ]
 
 [[package]]
diff --git a/src/librustc_codegen_llvm/abi.rs b/src/librustc_codegen_llvm/abi.rs
index f1a6e9913d6..44982eee86b 100644
--- a/src/librustc_codegen_llvm/abi.rs
+++ b/src/librustc_codegen_llvm/abi.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use llvm::{self, ValueRef, AttributePlace};
+use llvm::{self, AttributePlace};
 use base;
 use builder::{Builder, MemFlags};
 use common::{ty_fn_sig, C_usize};
@@ -17,6 +17,7 @@ use mir::place::PlaceRef;
 use mir::operand::OperandValue;
 use type_::Type;
 use type_of::{LayoutLlvmExt, PointerKind};
+use value::Value;
 
 use rustc_target::abi::{LayoutOf, Size, TyLayout};
 use rustc::ty::{self, Ty};
@@ -46,12 +47,12 @@ impl ArgAttributeExt for ArgAttribute {
 }
 
 pub trait ArgAttributesExt {
-    fn apply_llfn(&self, idx: AttributePlace, llfn: ValueRef);
-    fn apply_callsite(&self, idx: AttributePlace, callsite: ValueRef);
+    fn apply_llfn(&self, idx: AttributePlace, llfn: &Value);
+    fn apply_callsite(&self, idx: AttributePlace, callsite: &Value);
 }
 
 impl ArgAttributesExt for ArgAttributes {
-    fn apply_llfn(&self, idx: AttributePlace, llfn: ValueRef) {
+    fn apply_llfn(&self, idx: AttributePlace, llfn: &Value) {
         let mut regular = self.regular;
         unsafe {
             let deref = self.pointee_size.bytes();
@@ -76,7 +77,7 @@ impl ArgAttributesExt for ArgAttributes {
         }
     }
 
-    fn apply_callsite(&self, idx: AttributePlace, callsite: ValueRef) {
+    fn apply_callsite(&self, idx: AttributePlace, callsite: &Value) {
         let mut regular = self.regular;
         unsafe {
             let deref = self.pointee_size.bytes();
@@ -103,11 +104,11 @@ impl ArgAttributesExt for ArgAttributes {
 }
 
 pub trait LlvmType {
-    fn llvm_type(&self, cx: &CodegenCx) -> Type;
+    fn llvm_type(&self, cx: &CodegenCx<'ll, '_>) -> &'ll Type;
 }
 
 impl LlvmType for Reg {
-    fn llvm_type(&self, cx: &CodegenCx) -> Type {
+    fn llvm_type(&self, cx: &CodegenCx<'ll, '_>) -> &'ll Type {
         match self.kind {
             RegKind::Integer => Type::ix(cx, self.size.bits()),
             RegKind::Float => {
@@ -118,14 +119,14 @@ impl LlvmType for Reg {
                 }
             }
             RegKind::Vector => {
-                Type::vector(&Type::i8(cx), self.size.bytes())
+                Type::vector(Type::i8(cx), self.size.bytes())
             }
         }
     }
 }
 
 impl LlvmType for CastTarget {
-    fn llvm_type(&self, cx: &CodegenCx) -> Type {
+    fn llvm_type(&self, cx: &CodegenCx<'ll, '_>) -> &'ll Type {
         let rest_ll_unit = self.rest.unit.llvm_type(cx);
         let (rest_count, rem_bytes) = if self.rest.unit.size.bytes() == 0 {
             (0, 0)
@@ -142,7 +143,7 @@ impl LlvmType for CastTarget {
 
             // Simplify to array when all chunks are the same size and type
             if rem_bytes == 0 {
-                return Type::array(&rest_ll_unit, rest_count);
+                return Type::array(rest_ll_unit, rest_count);
             }
         }
 
@@ -164,16 +165,16 @@ impl LlvmType for CastTarget {
     }
 }
 
-pub trait ArgTypeExt<'a, 'tcx> {
-    fn memory_ty(&self, cx: &CodegenCx<'a, 'tcx>) -> Type;
-    fn store(&self, bx: &Builder<'a, 'tcx>, val: ValueRef, dst: PlaceRef<'tcx>);
-    fn store_fn_arg(&self, bx: &Builder<'a, 'tcx>, idx: &mut usize, dst: PlaceRef<'tcx>);
+pub trait ArgTypeExt<'ll, 'tcx> {
+    fn memory_ty(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type;
+    fn store(&self, bx: &Builder<'_, 'll, 'tcx>, val: &'ll Value, dst: PlaceRef<'ll, 'tcx>);
+    fn store_fn_arg(&self, bx: &Builder<'_, 'll, 'tcx>, idx: &mut usize, dst: PlaceRef<'ll, 'tcx>);
 }
 
-impl<'a, 'tcx> ArgTypeExt<'a, 'tcx> for ArgType<'tcx, Ty<'tcx>> {
+impl ArgTypeExt<'ll, 'tcx> for ArgType<'tcx, Ty<'tcx>> {
     /// Get the LLVM type for a place of the original Rust type of
     /// this argument/return, i.e. the result of `type_of::type_of`.
-    fn memory_ty(&self, cx: &CodegenCx<'a, 'tcx>) -> Type {
+    fn memory_ty(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type {
         self.layout.llvm_type(cx)
     }
 
@@ -181,7 +182,7 @@ impl<'a, 'tcx> ArgTypeExt<'a, 'tcx> for ArgType<'tcx, Ty<'tcx>> {
     /// place for the original Rust type of this argument/return.
     /// Can be used for both storing formal arguments into Rust variables
     /// or results of call/invoke instructions into their destinations.
-    fn store(&self, bx: &Builder<'a, 'tcx>, val: ValueRef, dst: PlaceRef<'tcx>) {
+    fn store(&self, bx: &Builder<'_, 'll, 'tcx>, val: &'ll Value, dst: PlaceRef<'ll, 'tcx>) {
         if self.is_ignore() {
             return;
         }
@@ -234,7 +235,7 @@ impl<'a, 'tcx> ArgTypeExt<'a, 'tcx> for ArgType<'tcx, Ty<'tcx>> {
         }
     }
 
-    fn store_fn_arg(&self, bx: &Builder<'a, 'tcx>, idx: &mut usize, dst: PlaceRef<'tcx>) {
+    fn store_fn_arg(&self, bx: &Builder<'a, 'll, 'tcx>, idx: &mut usize, dst: PlaceRef<'ll, 'tcx>) {
         let mut next = || {
             let val = llvm::get_param(bx.llfn(), *idx as c_uint);
             *idx += 1;
@@ -252,32 +253,32 @@ impl<'a, 'tcx> ArgTypeExt<'a, 'tcx> for ArgType<'tcx, Ty<'tcx>> {
     }
 }
 
-pub trait FnTypeExt<'a, 'tcx> {
-    fn of_instance(cx: &CodegenCx<'a, 'tcx>, instance: &ty::Instance<'tcx>)
+pub trait FnTypeExt<'tcx> {
+    fn of_instance(cx: &CodegenCx<'ll, 'tcx>, instance: &ty::Instance<'tcx>)
                    -> Self;
-    fn new(cx: &CodegenCx<'a, 'tcx>,
+    fn new(cx: &CodegenCx<'ll, 'tcx>,
            sig: ty::FnSig<'tcx>,
            extra_args: &[Ty<'tcx>]) -> Self;
-    fn new_vtable(cx: &CodegenCx<'a, 'tcx>,
+    fn new_vtable(cx: &CodegenCx<'ll, 'tcx>,
                   sig: ty::FnSig<'tcx>,
                   extra_args: &[Ty<'tcx>]) -> Self;
     fn new_internal(
-        cx: &CodegenCx<'a, 'tcx>,
+        cx: &CodegenCx<'ll, 'tcx>,
         sig: ty::FnSig<'tcx>,
         extra_args: &[Ty<'tcx>],
         mk_arg_type: impl Fn(Ty<'tcx>, Option<usize>) -> ArgType<'tcx, Ty<'tcx>>,
     ) -> Self;
     fn adjust_for_abi(&mut self,
-                      cx: &CodegenCx<'a, 'tcx>,
+                      cx: &CodegenCx<'ll, 'tcx>,
                       abi: Abi);
-    fn llvm_type(&self, cx: &CodegenCx<'a, 'tcx>) -> Type;
+    fn llvm_type(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type;
     fn llvm_cconv(&self) -> llvm::CallConv;
-    fn apply_attrs_llfn(&self, llfn: ValueRef);
-    fn apply_attrs_callsite(&self, bx: &Builder<'a, 'tcx>, callsite: ValueRef);
+    fn apply_attrs_llfn(&self, llfn: &'ll Value);
+    fn apply_attrs_callsite(&self, bx: &Builder<'a, 'll, 'tcx>, callsite: &'ll Value);
 }
 
-impl<'a, 'tcx> FnTypeExt<'a, 'tcx> for FnType<'tcx, Ty<'tcx>> {
-    fn of_instance(cx: &CodegenCx<'a, 'tcx>, instance: &ty::Instance<'tcx>)
+impl<'tcx> FnTypeExt<'tcx> for FnType<'tcx, Ty<'tcx>> {
+    fn of_instance(cx: &CodegenCx<'ll, 'tcx>, instance: &ty::Instance<'tcx>)
                        -> Self {
         let fn_ty = instance.ty(cx.tcx);
         let sig = ty_fn_sig(cx, fn_ty);
@@ -285,7 +286,7 @@ impl<'a, 'tcx> FnTypeExt<'a, 'tcx> for FnType<'tcx, Ty<'tcx>> {
         FnType::new(cx, sig, &[])
     }
 
-    fn new(cx: &CodegenCx<'a, 'tcx>,
+    fn new(cx: &CodegenCx<'ll, 'tcx>,
                sig: ty::FnSig<'tcx>,
                extra_args: &[Ty<'tcx>]) -> Self {
         FnType::new_internal(cx, sig, extra_args, |ty, _| {
@@ -293,7 +294,7 @@ impl<'a, 'tcx> FnTypeExt<'a, 'tcx> for FnType<'tcx, Ty<'tcx>> {
         })
     }
 
-    fn new_vtable(cx: &CodegenCx<'a, 'tcx>,
+    fn new_vtable(cx: &CodegenCx<'ll, 'tcx>,
                       sig: ty::FnSig<'tcx>,
                       extra_args: &[Ty<'tcx>]) -> Self {
         FnType::new_internal(cx, sig, extra_args, |ty, arg_idx| {
@@ -316,7 +317,7 @@ impl<'a, 'tcx> FnTypeExt<'a, 'tcx> for FnType<'tcx, Ty<'tcx>> {
     }
 
     fn new_internal(
-        cx: &CodegenCx<'a, 'tcx>,
+        cx: &CodegenCx<'ll, 'tcx>,
         sig: ty::FnSig<'tcx>,
         extra_args: &[Ty<'tcx>],
         mk_arg_type: impl Fn(Ty<'tcx>, Option<usize>) -> ArgType<'tcx, Ty<'tcx>>,
@@ -497,7 +498,7 @@ impl<'a, 'tcx> FnTypeExt<'a, 'tcx> for FnType<'tcx, Ty<'tcx>> {
     }
 
     fn adjust_for_abi(&mut self,
-                      cx: &CodegenCx<'a, 'tcx>,
+                      cx: &CodegenCx<'ll, 'tcx>,
                       abi: Abi) {
         if abi == Abi::Unadjusted { return }
 
@@ -564,7 +565,7 @@ impl<'a, 'tcx> FnTypeExt<'a, 'tcx> for FnType<'tcx, Ty<'tcx>> {
         }
     }
 
-    fn llvm_type(&self, cx: &CodegenCx<'a, 'tcx>) -> Type {
+    fn llvm_type(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type {
         let args_capacity: usize = self.args.iter().map(|arg|
             if arg.pad.is_some() { 1 } else { 0 } +
             if let PassMode::Pair(_, _) = arg.mode { 2 } else { 1 }
@@ -606,9 +607,9 @@ impl<'a, 'tcx> FnTypeExt<'a, 'tcx> for FnType<'tcx, Ty<'tcx>> {
         }
 
         if self.variadic {
-            Type::variadic_func(&llargument_tys, &llreturn_ty)
+            Type::variadic_func(&llargument_tys, llreturn_ty)
         } else {
-            Type::func(&llargument_tys, &llreturn_ty)
+            Type::func(&llargument_tys, llreturn_ty)
         }
     }
 
@@ -629,7 +630,7 @@ impl<'a, 'tcx> FnTypeExt<'a, 'tcx> for FnType<'tcx, Ty<'tcx>> {
         }
     }
 
-    fn apply_attrs_llfn(&self, llfn: ValueRef) {
+    fn apply_attrs_llfn(&self, llfn: &'ll Value) {
         let mut i = 0;
         let mut apply = |attrs: &ArgAttributes| {
             attrs.apply_llfn(llvm::AttributePlace::Argument(i), llfn);
@@ -659,7 +660,7 @@ impl<'a, 'tcx> FnTypeExt<'a, 'tcx> for FnType<'tcx, Ty<'tcx>> {
         }
     }
 
-    fn apply_attrs_callsite(&self, bx: &Builder<'a, 'tcx>, callsite: ValueRef) {
+    fn apply_attrs_callsite(&self, bx: &Builder<'a, 'll, 'tcx>, callsite: &'ll Value) {
         let mut i = 0;
         let mut apply = |attrs: &ArgAttributes| {
             attrs.apply_callsite(llvm::AttributePlace::Argument(i), callsite);
diff --git a/src/librustc_codegen_llvm/allocator.rs b/src/librustc_codegen_llvm/allocator.rs
index eeb02e948f1..2d401da958b 100644
--- a/src/librustc_codegen_llvm/allocator.rs
+++ b/src/librustc_codegen_llvm/allocator.rs
@@ -9,7 +9,6 @@
 // except according to those terms.
 
 use std::ffi::CString;
-use std::ptr;
 
 use attributes;
 use libc::c_uint;
@@ -21,8 +20,8 @@ use ModuleLlvm;
 use llvm::{self, False, True};
 
 pub(crate) unsafe fn codegen(tcx: TyCtxt, mods: &ModuleLlvm, kind: AllocatorKind) {
-    let llcx = mods.llcx;
-    let llmod = mods.llmod;
+    let llcx = &*mods.llcx;
+    let llmod = mods.llmod();
     let usize = match &tcx.sess.target.target.target_pointer_width[..] {
         "16" => llvm::LLVMInt16TypeInContext(llcx),
         "32" => llvm::LLVMInt32TypeInContext(llcx),
@@ -90,7 +89,7 @@ pub(crate) unsafe fn codegen(tcx: TyCtxt, mods: &ModuleLlvm, kind: AllocatorKind
                                           callee,
                                           args.as_ptr(),
                                           args.len() as c_uint,
-                                          ptr::null_mut(),
+                                          None,
                                           "\0".as_ptr() as *const _);
         llvm::LLVMSetTailCall(ret, True);
         if output.is_some() {
diff --git a/src/librustc_codegen_llvm/asm.rs b/src/librustc_codegen_llvm/asm.rs
index 82f068106ff..5d27f8eab3e 100644
--- a/src/librustc_codegen_llvm/asm.rs
+++ b/src/librustc_codegen_llvm/asm.rs
@@ -8,11 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use llvm::{self, ValueRef};
+use llvm;
 use common::*;
 use type_::Type;
 use type_of::LayoutLlvmExt;
 use builder::Builder;
+use value::Value;
 
 use rustc::hir;
 
@@ -24,11 +25,11 @@ use syntax::ast::AsmDialect;
 use libc::{c_uint, c_char};
 
 // Take an inline assembly expression and splat it out via LLVM
-pub fn codegen_inline_asm<'a, 'tcx>(
-    bx: &Builder<'a, 'tcx>,
+pub fn codegen_inline_asm(
+    bx: &Builder<'a, 'll, 'tcx>,
     ia: &hir::InlineAsm,
-    outputs: Vec<PlaceRef<'tcx>>,
-    mut inputs: Vec<ValueRef>
+    outputs: Vec<PlaceRef<'ll, 'tcx>>,
+    mut inputs: Vec<&'ll Value>
 ) {
     let mut ext_constraints = vec![];
     let mut output_types = vec![];
@@ -111,7 +112,7 @@ pub fn codegen_inline_asm<'a, 'tcx>(
         let kind = llvm::LLVMGetMDKindIDInContext(bx.cx.llcx,
             key.as_ptr() as *const c_char, key.len() as c_uint);
 
-        let val: llvm::ValueRef = C_i32(bx.cx, ia.ctxt.outer().as_u32() as i32);
+        let val: &'ll Value = C_i32(bx.cx, ia.ctxt.outer().as_u32() as i32);
 
         llvm::LLVMSetMetadata(r, kind,
             llvm::LLVMMDNodeInContext(bx.cx.llcx, &val, 1));
diff --git a/src/librustc_codegen_llvm/attributes.rs b/src/librustc_codegen_llvm/attributes.rs
index 3b5f927d52f..c52f8944108 100644
--- a/src/librustc_codegen_llvm/attributes.rs
+++ b/src/librustc_codegen_llvm/attributes.rs
@@ -22,15 +22,17 @@ use rustc_data_structures::fx::FxHashMap;
 use rustc_target::spec::PanicStrategy;
 
 use attributes;
-use llvm::{self, Attribute, ValueRef};
+use llvm::{self, Attribute};
 use llvm::AttributePlace::Function;
 use llvm_util;
 pub use syntax::attr::{self, InlineAttr};
+
 use context::CodegenCx;
+use value::Value;
 
 /// Mark LLVM function to use provided inline heuristic.
 #[inline]
-pub fn inline(val: ValueRef, inline: InlineAttr) {
+pub fn inline(val: &'ll Value, inline: InlineAttr) {
     use self::InlineAttr::*;
     match inline {
         Hint   => Attribute::InlineHint.apply_llfn(Function, val),
@@ -46,30 +48,30 @@ pub fn inline(val: ValueRef, inline: InlineAttr) {
 
 /// Tell LLVM to emit or not emit the information necessary to unwind the stack for the function.
 #[inline]
-pub fn emit_uwtable(val: ValueRef, emit: bool) {
+pub fn emit_uwtable(val: &'ll Value, emit: bool) {
     Attribute::UWTable.toggle_llfn(Function, val, emit);
 }
 
 /// Tell LLVM whether the function can or cannot unwind.
 #[inline]
-pub fn unwind(val: ValueRef, can_unwind: bool) {
+pub fn unwind(val: &'ll Value, can_unwind: bool) {
     Attribute::NoUnwind.toggle_llfn(Function, val, !can_unwind);
 }
 
 /// Tell LLVM whether it should optimize function for size.
 #[inline]
 #[allow(dead_code)] // possibly useful function
-pub fn set_optimize_for_size(val: ValueRef, optimize: bool) {
+pub fn set_optimize_for_size(val: &'ll Value, optimize: bool) {
     Attribute::OptimizeForSize.toggle_llfn(Function, val, optimize);
 }
 
 /// Tell LLVM if this function should be 'naked', i.e. skip the epilogue and prologue.
 #[inline]
-pub fn naked(val: ValueRef, is_naked: bool) {
+pub fn naked(val: &'ll Value, is_naked: bool) {
     Attribute::Naked.toggle_llfn(Function, val, is_naked);
 }
 
-pub fn set_frame_pointer_elimination(cx: &CodegenCx, llfn: ValueRef) {
+pub fn set_frame_pointer_elimination(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) {
     if cx.sess().must_not_eliminate_frame_pointers() {
         llvm::AddFunctionAttrStringValue(
             llfn, llvm::AttributePlace::Function,
@@ -77,7 +79,7 @@ pub fn set_frame_pointer_elimination(cx: &CodegenCx, llfn: ValueRef) {
     }
 }
 
-pub fn set_probestack(cx: &CodegenCx, llfn: ValueRef) {
+pub fn set_probestack(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) {
     // Only use stack probes if the target specification indicates that we
     // should be using stack probes
     if !cx.sess().target.target.options.stack_probes {
@@ -123,7 +125,7 @@ pub fn llvm_target_features(sess: &Session) -> impl Iterator<Item = &str> {
 
 /// Composite function which sets LLVM attributes for function depending on its AST (#[attribute])
 /// attributes.
-pub fn from_fn_attrs(cx: &CodegenCx, llfn: ValueRef, id: DefId) {
+pub fn from_fn_attrs(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value, id: DefId) {
     let codegen_fn_attrs = cx.tcx.codegen_fn_attrs(id);
 
     inline(llfn, codegen_fn_attrs.inline);
diff --git a/src/librustc_codegen_llvm/back/archive.rs b/src/librustc_codegen_llvm/back/archive.rs
index b99835cb5c6..af9efc6d7c4 100644
--- a/src/librustc_codegen_llvm/back/archive.rs
+++ b/src/librustc_codegen_llvm/back/archive.rs
@@ -226,10 +226,13 @@ impl<'a> ArchiveBuilder<'a> {
     }
 
     fn build_with_llvm(&mut self, kind: ArchiveKind) -> io::Result<()> {
-        let mut archives = Vec::new();
+        let removals = mem::replace(&mut self.removals, Vec::new());
+        let mut additions = mem::replace(&mut self.additions, Vec::new());
         let mut strings = Vec::new();
         let mut members = Vec::new();
-        let removals = mem::replace(&mut self.removals, Vec::new());
+
+        let dst = CString::new(self.config.dst.to_str().unwrap())?;
+        let should_update_symbols = self.should_update_symbols;
 
         unsafe {
             if let Some(archive) = self.src_archive() {
@@ -246,22 +249,22 @@ impl<'a> ArchiveBuilder<'a> {
                     let name = CString::new(child_name)?;
                     members.push(llvm::LLVMRustArchiveMemberNew(ptr::null(),
                                                                 name.as_ptr(),
-                                                                child.raw()));
+                                                                Some(child.raw)));
                     strings.push(name);
                 }
             }
-            for addition in mem::replace(&mut self.additions, Vec::new()) {
+            for addition in &mut additions {
                 match addition {
                     Addition::File { path, name_in_archive } => {
                         let path = CString::new(path.to_str().unwrap())?;
-                        let name = CString::new(name_in_archive)?;
+                        let name = CString::new(name_in_archive.clone())?;
                         members.push(llvm::LLVMRustArchiveMemberNew(path.as_ptr(),
                                                                     name.as_ptr(),
-                                                                    ptr::null_mut()));
+                                                                    None));
                         strings.push(path);
                         strings.push(name);
                     }
-                    Addition::Archive { archive, mut skip } => {
+                    Addition::Archive { archive, skip } => {
                         for child in archive.iter() {
                             let child = child.map_err(string_to_io_error)?;
                             if !is_relevant_child(&child) {
@@ -284,21 +287,18 @@ impl<'a> ArchiveBuilder<'a> {
                             let name = CString::new(child_name)?;
                             let m = llvm::LLVMRustArchiveMemberNew(ptr::null(),
                                                                    name.as_ptr(),
-                                                                   child.raw());
+                                                                   Some(child.raw));
                             members.push(m);
                             strings.push(name);
                         }
-                        archives.push(archive);
                     }
                 }
             }
 
-            let dst = self.config.dst.to_str().unwrap().as_bytes();
-            let dst = CString::new(dst)?;
             let r = llvm::LLVMRustWriteArchive(dst.as_ptr(),
                                                members.len() as libc::size_t,
-                                               members.as_ptr(),
-                                               self.should_update_symbols,
+                                               members.as_ptr() as *const &_,
+                                               should_update_symbols,
                                                kind);
             let ret = if r.into_result().is_err() {
                 let err = llvm::LLVMRustGetLastError();
diff --git a/src/librustc_codegen_llvm/back/lto.rs b/src/librustc_codegen_llvm/back/lto.rs
index 93cb9eb9767..daa2fb05280 100644
--- a/src/librustc_codegen_llvm/back/lto.rs
+++ b/src/librustc_codegen_llvm/back/lto.rs
@@ -14,7 +14,7 @@ use back::write::{ModuleConfig, with_llvm_pmb, CodegenContext};
 use back::write;
 use errors::{FatalError, Handler};
 use llvm::archive_ro::ArchiveRO;
-use llvm::{ModuleRef, TargetMachineRef, True, False};
+use llvm::{True, False};
 use llvm;
 use rustc::hir::def_id::LOCAL_CRATE;
 use rustc::middle::exported_symbols::SymbolExportLevel;
@@ -73,11 +73,13 @@ impl LtoModuleCodegen {
         match *self {
             LtoModuleCodegen::Fat { ref mut module, .. } => {
                 let module = module.take().unwrap();
-                let config = cgcx.config(module.kind);
-                let llmod = module.llvm().unwrap().llmod;
-                let tm = module.llvm().unwrap().tm;
-                run_pass_manager(cgcx, tm, llmod, config, false);
-                timeline.record("fat-done");
+                {
+                    let config = cgcx.config(module.kind);
+                    let llmod = module.llvm().unwrap().llmod();
+                    let tm = &*module.llvm().unwrap().tm;
+                    run_pass_manager(cgcx, tm, llmod, config, false);
+                    timeline.record("fat-done");
+                }
                 Ok(module)
             }
             LtoModuleCodegen::Thin(ref mut thin) => thin.optimize(cgcx, timeline),
@@ -223,66 +225,68 @@ fn fat_lto(cgcx: &CodegenContext,
         .filter(|&(_, module)| module.kind == ModuleKind::Regular)
         .map(|(i, module)| {
             let cost = unsafe {
-                llvm::LLVMRustModuleCost(module.llvm().unwrap().llmod)
+                llvm::LLVMRustModuleCost(module.llvm().unwrap().llmod())
             };
             (cost, i)
         })
         .max()
         .expect("must be codegen'ing at least one module");
     let module = modules.remove(costliest_module);
-    let llmod = module.llvm().expect("can't lto pre-codegened modules").llmod;
-    info!("using {:?} as a base module", module.llmod_id);
-
-    // For all other modules we codegened we'll need to link them into our own
-    // bitcode. All modules were codegened in their own LLVM context, however,
-    // and we want to move everything to the same LLVM context. Currently the
-    // way we know of to do that is to serialize them to a string and them parse
-    // them later. Not great but hey, that's why it's "fat" LTO, right?
-    for module in modules {
-        let llvm = module.llvm().expect("can't lto pre-codegened modules");
-        let buffer = ModuleBuffer::new(llvm.llmod);
-        let llmod_id = CString::new(&module.llmod_id[..]).unwrap();
-        serialized_modules.push((SerializedModule::Local(buffer), llmod_id));
-    }
-
-    // For all serialized bitcode files we parse them and link them in as we did
-    // above, this is all mostly handled in C++. Like above, though, we don't
-    // know much about the memory management here so we err on the side of being
-    // save and persist everything with the original module.
     let mut serialized_bitcode = Vec::new();
-    let mut linker = Linker::new(llmod);
-    for (bc_decoded, name) in serialized_modules {
-        info!("linking {:?}", name);
-        time_ext(cgcx.time_passes, None, &format!("ll link {:?}", name), || {
-            let data = bc_decoded.data();
-            linker.add(&data).map_err(|()| {
-                let msg = format!("failed to load bc of {:?}", name);
-                write::llvm_err(&diag_handler, msg)
-            })
-        })?;
-        timeline.record(&format!("link {:?}", name));
-        serialized_bitcode.push(bc_decoded);
-    }
-    drop(linker);
-    cgcx.save_temp_bitcode(&module, "lto.input");
+    {
+        let llmod = module.llvm().expect("can't lto pre-codegened modules").llmod();
+        info!("using {:?} as a base module", module.llmod_id);
+
+        // For all other modules we codegened we'll need to link them into our own
+        // bitcode. All modules were codegened in their own LLVM context, however,
+        // and we want to move everything to the same LLVM context. Currently the
+        // way we know of to do that is to serialize them to a string and them parse
+        // them later. Not great but hey, that's why it's "fat" LTO, right?
+        for module in modules {
+            let llvm = module.llvm().expect("can't lto pre-codegened modules");
+            let buffer = ModuleBuffer::new(llvm.llmod());
+            let llmod_id = CString::new(&module.llmod_id[..]).unwrap();
+            serialized_modules.push((SerializedModule::Local(buffer), llmod_id));
+        }
 
-    // Internalize everything that *isn't* in our whitelist to help strip out
-    // more modules and such
-    unsafe {
-        let ptr = symbol_white_list.as_ptr();
-        llvm::LLVMRustRunRestrictionPass(llmod,
-                                         ptr as *const *const libc::c_char,
-                                         symbol_white_list.len() as libc::size_t);
-        cgcx.save_temp_bitcode(&module, "lto.after-restriction");
-    }
+        // For all serialized bitcode files we parse them and link them in as we did
+        // above, this is all mostly handled in C++. Like above, though, we don't
+        // know much about the memory management here so we err on the side of being
+        // save and persist everything with the original module.
+        let mut linker = Linker::new(llmod);
+        for (bc_decoded, name) in serialized_modules {
+            info!("linking {:?}", name);
+            time_ext(cgcx.time_passes, None, &format!("ll link {:?}", name), || {
+                let data = bc_decoded.data();
+                linker.add(&data).map_err(|()| {
+                    let msg = format!("failed to load bc of {:?}", name);
+                    write::llvm_err(&diag_handler, msg)
+                })
+            })?;
+            timeline.record(&format!("link {:?}", name));
+            serialized_bitcode.push(bc_decoded);
+        }
+        drop(linker);
+        cgcx.save_temp_bitcode(&module, "lto.input");
 
-    if cgcx.no_landing_pads {
+        // Internalize everything that *isn't* in our whitelist to help strip out
+        // more modules and such
         unsafe {
-            llvm::LLVMRustMarkAllFunctionsNounwind(llmod);
+            let ptr = symbol_white_list.as_ptr();
+            llvm::LLVMRustRunRestrictionPass(llmod,
+                                            ptr as *const *const libc::c_char,
+                                            symbol_white_list.len() as libc::size_t);
+            cgcx.save_temp_bitcode(&module, "lto.after-restriction");
+        }
+
+        if cgcx.no_landing_pads {
+            unsafe {
+                llvm::LLVMRustMarkAllFunctionsNounwind(llmod);
+            }
+            cgcx.save_temp_bitcode(&module, "lto.after-nounwind");
         }
-        cgcx.save_temp_bitcode(&module, "lto.after-nounwind");
+        timeline.record("passes");
     }
-    timeline.record("passes");
 
     Ok(vec![LtoModuleCodegen::Fat {
         module: Some(module),
@@ -290,10 +294,10 @@ fn fat_lto(cgcx: &CodegenContext,
     }])
 }
 
-struct Linker(llvm::LinkerRef);
+struct Linker<'a>(&'a mut llvm::Linker<'a>);
 
-impl Linker {
-    fn new(llmod: ModuleRef) -> Linker {
+impl Linker<'a> {
+    fn new(llmod: &'a llvm::Module) -> Self {
         unsafe { Linker(llvm::LLVMRustLinkerNew(llmod)) }
     }
 
@@ -310,9 +314,9 @@ impl Linker {
     }
 }
 
-impl Drop for Linker {
+impl Drop for Linker<'a> {
     fn drop(&mut self) {
-        unsafe { llvm::LLVMRustLinkerFree(self.0); }
+        unsafe { llvm::LLVMRustLinkerFree(&mut *(self.0 as *mut _)); }
     }
 }
 
@@ -371,7 +375,7 @@ fn thin_lto(diag_handler: &Handler,
             info!("local module: {} - {}", i, module.llmod_id);
             let llvm = module.llvm().expect("can't lto precodegened module");
             let name = CString::new(module.llmod_id.clone()).unwrap();
-            let buffer = ThinBuffer::new(llvm.llmod);
+            let buffer = ThinBuffer::new(llvm.llmod());
             thin_modules.push(llvm::ThinLTOModule {
                 identifier: name.as_ptr(),
                 data: buffer.data().as_ptr(),
@@ -419,11 +423,10 @@ fn thin_lto(diag_handler: &Handler,
             thin_modules.len() as u32,
             symbol_white_list.as_ptr(),
             symbol_white_list.len() as u32,
-        );
-        if data.is_null() {
-            let msg = "failed to prepare thin LTO context".to_string();
-            return Err(write::llvm_err(&diag_handler, msg))
-        }
+        ).ok_or_else(|| {
+            write::llvm_err(&diag_handler, "failed to prepare thin LTO context".to_string())
+        })?;
+
         let data = ThinData(data);
         info!("thin LTO data created");
         timeline.record("data");
@@ -448,8 +451,8 @@ fn thin_lto(diag_handler: &Handler,
 }
 
 fn run_pass_manager(cgcx: &CodegenContext,
-                    tm: TargetMachineRef,
-                    llmod: ModuleRef,
+                    tm: &llvm::TargetMachine,
+                    llmod: &llvm::Module,
                     config: &ModuleConfig,
                     thin: bool) {
     // Now we have one massive module inside of llmod. Time to run the
@@ -464,8 +467,7 @@ fn run_pass_manager(cgcx: &CodegenContext,
 
         if config.verify_llvm_ir {
             let pass = llvm::LLVMRustFindAndCreatePass("verify\0".as_ptr() as *const _);
-            assert!(!pass.is_null());
-            llvm::LLVMRustAddPass(pm, pass);
+            llvm::LLVMRustAddPass(pm, pass.unwrap());
         }
 
         // When optimizing for LTO we don't actually pass in `-O0`, but we force
@@ -499,8 +501,7 @@ fn run_pass_manager(cgcx: &CodegenContext,
 
         if config.verify_llvm_ir {
             let pass = llvm::LLVMRustFindAndCreatePass("verify\0".as_ptr() as *const _);
-            assert!(!pass.is_null());
-            llvm::LLVMRustAddPass(pm, pass);
+            llvm::LLVMRustAddPass(pm, pass.unwrap());
         }
 
         time_ext(cgcx.time_passes, None, "LTO passes", ||
@@ -525,13 +526,13 @@ impl SerializedModule {
     }
 }
 
-pub struct ModuleBuffer(*mut llvm::ModuleBuffer);
+pub struct ModuleBuffer(&'static mut llvm::ModuleBuffer);
 
 unsafe impl Send for ModuleBuffer {}
 unsafe impl Sync for ModuleBuffer {}
 
 impl ModuleBuffer {
-    pub fn new(m: ModuleRef) -> ModuleBuffer {
+    pub fn new(m: &llvm::Module) -> ModuleBuffer {
         ModuleBuffer(unsafe {
             llvm::LLVMRustModuleBufferCreate(m)
         })
@@ -548,7 +549,7 @@ impl ModuleBuffer {
 
 impl Drop for ModuleBuffer {
     fn drop(&mut self) {
-        unsafe { llvm::LLVMRustModuleBufferFree(self.0); }
+        unsafe { llvm::LLVMRustModuleBufferFree(&mut *(self.0 as *mut _)); }
     }
 }
 
@@ -564,7 +565,7 @@ struct ThinShared {
     module_names: Vec<CString>,
 }
 
-struct ThinData(*mut llvm::ThinLTOData);
+struct ThinData(&'static mut llvm::ThinLTOData);
 
 unsafe impl Send for ThinData {}
 unsafe impl Sync for ThinData {}
@@ -572,18 +573,18 @@ unsafe impl Sync for ThinData {}
 impl Drop for ThinData {
     fn drop(&mut self) {
         unsafe {
-            llvm::LLVMRustFreeThinLTOData(self.0);
+            llvm::LLVMRustFreeThinLTOData(&mut *(self.0 as *mut _));
         }
     }
 }
 
-pub struct ThinBuffer(*mut llvm::ThinLTOBuffer);
+pub struct ThinBuffer(&'static mut llvm::ThinLTOBuffer);
 
 unsafe impl Send for ThinBuffer {}
 unsafe impl Sync for ThinBuffer {}
 
 impl ThinBuffer {
-    pub fn new(m: ModuleRef) -> ThinBuffer {
+    pub fn new(m: &llvm::Module) -> ThinBuffer {
         unsafe {
             let buffer = llvm::LLVMRustThinLTOBufferCreate(m);
             ThinBuffer(buffer)
@@ -602,7 +603,7 @@ impl ThinBuffer {
 impl Drop for ThinBuffer {
     fn drop(&mut self) {
         unsafe {
-            llvm::LLVMRustThinLTOBufferFree(self.0);
+            llvm::LLVMRustThinLTOBufferFree(&mut *(self.0 as *mut _));
         }
     }
 }
@@ -640,19 +641,18 @@ impl ThinModule {
         // crates but for locally codegened modules we may be able to reuse
         // that LLVM Context and Module.
         let llcx = llvm::LLVMRustContextCreate(cgcx.fewer_names);
-        let llmod = llvm::LLVMRustParseBitcodeForThinLTO(
+        let llmod_raw = llvm::LLVMRustParseBitcodeForThinLTO(
             llcx,
             self.data().as_ptr(),
             self.data().len(),
             self.shared.module_names[self.idx].as_ptr(),
-        );
-        if llmod.is_null() {
+        ).ok_or_else(|| {
             let msg = "failed to parse bitcode for thin LTO module".to_string();
-            return Err(write::llvm_err(&diag_handler, msg));
-        }
+            write::llvm_err(&diag_handler, msg)
+        })? as *const _;
         let module = ModuleCodegen {
             source: ModuleSource::Codegened(ModuleLlvm {
-                llmod,
+                llmod_raw,
                 llcx,
                 tm,
             }),
@@ -660,104 +660,107 @@ impl ThinModule {
             name: self.name().to_string(),
             kind: ModuleKind::Regular,
         };
-        cgcx.save_temp_bitcode(&module, "thin-lto-input");
-
-        // Before we do much else find the "main" `DICompileUnit` that we'll be
-        // using below. If we find more than one though then rustc has changed
-        // in a way we're not ready for, so generate an ICE by returning
-        // an error.
-        let mut cu1 = ptr::null_mut();
-        let mut cu2 = ptr::null_mut();
-        llvm::LLVMRustThinLTOGetDICompileUnit(llmod, &mut cu1, &mut cu2);
-        if !cu2.is_null() {
-            let msg = "multiple source DICompileUnits found".to_string();
-            return Err(write::llvm_err(&diag_handler, msg))
-        }
+        {
+            let llmod = module.llvm().unwrap().llmod();
+            cgcx.save_temp_bitcode(&module, "thin-lto-input");
+
+            // Before we do much else find the "main" `DICompileUnit` that we'll be
+            // using below. If we find more than one though then rustc has changed
+            // in a way we're not ready for, so generate an ICE by returning
+            // an error.
+            let mut cu1 = ptr::null_mut();
+            let mut cu2 = ptr::null_mut();
+            llvm::LLVMRustThinLTOGetDICompileUnit(llmod, &mut cu1, &mut cu2);
+            if !cu2.is_null() {
+                let msg = "multiple source DICompileUnits found".to_string();
+                return Err(write::llvm_err(&diag_handler, msg))
+            }
 
-        // Like with "fat" LTO, get some better optimizations if landing pads
-        // are disabled by removing all landing pads.
-        if cgcx.no_landing_pads {
-            llvm::LLVMRustMarkAllFunctionsNounwind(llmod);
-            cgcx.save_temp_bitcode(&module, "thin-lto-after-nounwind");
-            timeline.record("nounwind");
-        }
+            // Like with "fat" LTO, get some better optimizations if landing pads
+            // are disabled by removing all landing pads.
+            if cgcx.no_landing_pads {
+                llvm::LLVMRustMarkAllFunctionsNounwind(llmod);
+                cgcx.save_temp_bitcode(&module, "thin-lto-after-nounwind");
+                timeline.record("nounwind");
+            }
 
-        // Up next comes the per-module local analyses that we do for Thin LTO.
-        // Each of these functions is basically copied from the LLVM
-        // implementation and then tailored to suit this implementation. Ideally
-        // each of these would be supported by upstream LLVM but that's perhaps
-        // a patch for another day!
-        //
-        // You can find some more comments about these functions in the LLVM
-        // bindings we've got (currently `PassWrapper.cpp`)
-        if !llvm::LLVMRustPrepareThinLTORename(self.shared.data.0, llmod) {
-            let msg = "failed to prepare thin LTO module".to_string();
-            return Err(write::llvm_err(&diag_handler, msg))
-        }
-        cgcx.save_temp_bitcode(&module, "thin-lto-after-rename");
-        timeline.record("rename");
-        if !llvm::LLVMRustPrepareThinLTOResolveWeak(self.shared.data.0, llmod) {
-            let msg = "failed to prepare thin LTO module".to_string();
-            return Err(write::llvm_err(&diag_handler, msg))
-        }
-        cgcx.save_temp_bitcode(&module, "thin-lto-after-resolve");
-        timeline.record("resolve");
-        if !llvm::LLVMRustPrepareThinLTOInternalize(self.shared.data.0, llmod) {
-            let msg = "failed to prepare thin LTO module".to_string();
-            return Err(write::llvm_err(&diag_handler, msg))
-        }
-        cgcx.save_temp_bitcode(&module, "thin-lto-after-internalize");
-        timeline.record("internalize");
-        if !llvm::LLVMRustPrepareThinLTOImport(self.shared.data.0, llmod) {
-            let msg = "failed to prepare thin LTO module".to_string();
-            return Err(write::llvm_err(&diag_handler, msg))
+            // Up next comes the per-module local analyses that we do for Thin LTO.
+            // Each of these functions is basically copied from the LLVM
+            // implementation and then tailored to suit this implementation. Ideally
+            // each of these would be supported by upstream LLVM but that's perhaps
+            // a patch for another day!
+            //
+            // You can find some more comments about these functions in the LLVM
+            // bindings we've got (currently `PassWrapper.cpp`)
+            if !llvm::LLVMRustPrepareThinLTORename(self.shared.data.0, llmod) {
+                let msg = "failed to prepare thin LTO module".to_string();
+                return Err(write::llvm_err(&diag_handler, msg))
+            }
+            cgcx.save_temp_bitcode(&module, "thin-lto-after-rename");
+            timeline.record("rename");
+            if !llvm::LLVMRustPrepareThinLTOResolveWeak(self.shared.data.0, llmod) {
+                let msg = "failed to prepare thin LTO module".to_string();
+                return Err(write::llvm_err(&diag_handler, msg))
+            }
+            cgcx.save_temp_bitcode(&module, "thin-lto-after-resolve");
+            timeline.record("resolve");
+            if !llvm::LLVMRustPrepareThinLTOInternalize(self.shared.data.0, llmod) {
+                let msg = "failed to prepare thin LTO module".to_string();
+                return Err(write::llvm_err(&diag_handler, msg))
+            }
+            cgcx.save_temp_bitcode(&module, "thin-lto-after-internalize");
+            timeline.record("internalize");
+            if !llvm::LLVMRustPrepareThinLTOImport(self.shared.data.0, llmod) {
+                let msg = "failed to prepare thin LTO module".to_string();
+                return Err(write::llvm_err(&diag_handler, msg))
+            }
+            cgcx.save_temp_bitcode(&module, "thin-lto-after-import");
+            timeline.record("import");
+
+            // Ok now this is a bit unfortunate. This is also something you won't
+            // find upstream in LLVM's ThinLTO passes! This is a hack for now to
+            // work around bugs in LLVM.
+            //
+            // First discovered in #45511 it was found that as part of ThinLTO
+            // importing passes LLVM will import `DICompileUnit` metadata
+            // information across modules. This means that we'll be working with one
+            // LLVM module that has multiple `DICompileUnit` instances in it (a
+            // bunch of `llvm.dbg.cu` members). Unfortunately there's a number of
+            // bugs in LLVM's backend which generates invalid DWARF in a situation
+            // like this:
+            //
+            //  https://bugs.llvm.org/show_bug.cgi?id=35212
+            //  https://bugs.llvm.org/show_bug.cgi?id=35562
+            //
+            // While the first bug there is fixed the second ended up causing #46346
+            // which was basically a resurgence of #45511 after LLVM's bug 35212 was
+            // fixed.
+            //
+            // This function below is a huge hack around this problem. The function
+            // below is defined in `PassWrapper.cpp` and will basically "merge"
+            // all `DICompileUnit` instances in a module. Basically it'll take all
+            // the objects, rewrite all pointers of `DISubprogram` to point to the
+            // first `DICompileUnit`, and then delete all the other units.
+            //
+            // This is probably mangling to the debug info slightly (but hopefully
+            // not too much) but for now at least gets LLVM to emit valid DWARF (or
+            // so it appears). Hopefully we can remove this once upstream bugs are
+            // fixed in LLVM.
+            llvm::LLVMRustThinLTOPatchDICompileUnit(llmod, cu1);
+            cgcx.save_temp_bitcode(&module, "thin-lto-after-patch");
+            timeline.record("patch");
+
+            // Alright now that we've done everything related to the ThinLTO
+            // analysis it's time to run some optimizations! Here we use the same
+            // `run_pass_manager` as the "fat" LTO above except that we tell it to
+            // populate a thin-specific pass manager, which presumably LLVM treats a
+            // little differently.
+            info!("running thin lto passes over {}", module.name);
+            let config = cgcx.config(module.kind);
+            run_pass_manager(cgcx, module.llvm().unwrap().tm, llmod, config, true);
+            cgcx.save_temp_bitcode(&module, "thin-lto-after-pm");
+            timeline.record("thin-done");
         }
-        cgcx.save_temp_bitcode(&module, "thin-lto-after-import");
-        timeline.record("import");
-
-        // Ok now this is a bit unfortunate. This is also something you won't
-        // find upstream in LLVM's ThinLTO passes! This is a hack for now to
-        // work around bugs in LLVM.
-        //
-        // First discovered in #45511 it was found that as part of ThinLTO
-        // importing passes LLVM will import `DICompileUnit` metadata
-        // information across modules. This means that we'll be working with one
-        // LLVM module that has multiple `DICompileUnit` instances in it (a
-        // bunch of `llvm.dbg.cu` members). Unfortunately there's a number of
-        // bugs in LLVM's backend which generates invalid DWARF in a situation
-        // like this:
-        //
-        //  https://bugs.llvm.org/show_bug.cgi?id=35212
-        //  https://bugs.llvm.org/show_bug.cgi?id=35562
-        //
-        // While the first bug there is fixed the second ended up causing #46346
-        // which was basically a resurgence of #45511 after LLVM's bug 35212 was
-        // fixed.
-        //
-        // This function below is a huge hack around this problem. The function
-        // below is defined in `PassWrapper.cpp` and will basically "merge"
-        // all `DICompileUnit` instances in a module. Basically it'll take all
-        // the objects, rewrite all pointers of `DISubprogram` to point to the
-        // first `DICompileUnit`, and then delete all the other units.
-        //
-        // This is probably mangling to the debug info slightly (but hopefully
-        // not too much) but for now at least gets LLVM to emit valid DWARF (or
-        // so it appears). Hopefully we can remove this once upstream bugs are
-        // fixed in LLVM.
-        llvm::LLVMRustThinLTOPatchDICompileUnit(llmod, cu1);
-        cgcx.save_temp_bitcode(&module, "thin-lto-after-patch");
-        timeline.record("patch");
-
-        // Alright now that we've done everything related to the ThinLTO
-        // analysis it's time to run some optimizations! Here we use the same
-        // `run_pass_manager` as the "fat" LTO above except that we tell it to
-        // populate a thin-specific pass manager, which presumably LLVM treats a
-        // little differently.
-        info!("running thin lto passes over {}", module.name);
-        let config = cgcx.config(module.kind);
-        run_pass_manager(cgcx, tm, llmod, config, true);
-        cgcx.save_temp_bitcode(&module, "thin-lto-after-pm");
-        timeline.record("thin-done");
 
         Ok(module)
     }
diff --git a/src/librustc_codegen_llvm/back/write.rs b/src/librustc_codegen_llvm/back/write.rs
index d36142af56c..db044878fe7 100644
--- a/src/librustc_codegen_llvm/back/write.rs
+++ b/src/librustc_codegen_llvm/back/write.rs
@@ -25,9 +25,7 @@ use rustc::session::config::{self, OutputFilenames, OutputType, Passes, SomePass
 use rustc::session::Session;
 use rustc::util::nodemap::FxHashMap;
 use time_graph::{self, TimeGraph, Timeline};
-use llvm;
-use llvm::{ModuleRef, TargetMachineRef, PassManagerRef, DiagnosticInfoRef};
-use llvm::{SMDiagnosticRef, ContextRef};
+use llvm::{self, DiagnosticInfo, PassManager, SMDiagnostic};
 use {CodegenResults, ModuleSource, ModuleCodegen, CompiledModule, ModuleKind};
 use CrateInfo;
 use rustc::hir::def_id::{CrateNum, LOCAL_CRATE};
@@ -94,9 +92,9 @@ pub fn llvm_err(handler: &errors::Handler, msg: String) -> FatalError {
 
 pub fn write_output_file(
         handler: &errors::Handler,
-        target: llvm::TargetMachineRef,
-        pm: llvm::PassManagerRef,
-        m: ModuleRef,
+        target: &'ll llvm::TargetMachine,
+        pm: &llvm::PassManager<'ll>,
+        m: &'ll llvm::Module,
         output: &Path,
         file_type: llvm::FileType) -> Result<(), FatalError> {
     unsafe {
@@ -130,7 +128,10 @@ fn get_llvm_opt_size(optimize: config::OptLevel) -> llvm::CodeGenOptSize {
     }
 }
 
-pub fn create_target_machine(sess: &Session, find_features: bool) -> TargetMachineRef {
+pub fn create_target_machine(
+    sess: &Session,
+    find_features: bool,
+) -> &'static mut llvm::TargetMachine {
     target_machine_factory(sess, find_features)().unwrap_or_else(|err| {
         llvm_err(sess.diagnostic(), err).raise()
     })
@@ -140,7 +141,7 @@ pub fn create_target_machine(sess: &Session, find_features: bool) -> TargetMachi
 // that `is_pie_binary` is false. When we discover LLVM target features
 // `sess.crate_types` is uninitialized so we cannot access it.
 pub fn target_machine_factory(sess: &Session, find_features: bool)
-    -> Arc<dyn Fn() -> Result<TargetMachineRef, String> + Send + Sync>
+    -> Arc<dyn Fn() -> Result<&'static mut llvm::TargetMachine, String> + Send + Sync>
 {
     let reloc_model = get_reloc_model(sess);
 
@@ -199,12 +200,10 @@ pub fn target_machine_factory(sess: &Session, find_features: bool)
             )
         };
 
-        if tm.is_null() {
-            Err(format!("Could not create LLVM TargetMachine for triple: {}",
-                        triple.to_str().unwrap()))
-        } else {
-            Ok(tm)
-        }
+        tm.ok_or_else(|| {
+            format!("Could not create LLVM TargetMachine for triple: {}",
+                    triple.to_str().unwrap())
+        })
     })
 }
 
@@ -343,7 +342,7 @@ pub struct CodegenContext {
     regular_module_config: Arc<ModuleConfig>,
     metadata_module_config: Arc<ModuleConfig>,
     allocator_module_config: Arc<ModuleConfig>,
-    pub tm_factory: Arc<dyn Fn() -> Result<TargetMachineRef, String> + Send + Sync>,
+    pub tm_factory: Arc<dyn Fn() -> Result<&'static mut llvm::TargetMachine, String> + Send + Sync>,
     pub msvc_imps_needed: bool,
     pub target_pointer_width: String,
     debuginfo: config::DebugInfoLevel,
@@ -392,7 +391,7 @@ impl CodegenContext {
             let cgu = Some(&module.name[..]);
             let path = self.output_filenames.temp_path_ext(&ext, cgu);
             let cstr = path2cstr(&path);
-            let llmod = module.llvm().unwrap().llmod;
+            let llmod = module.llvm().unwrap().llmod();
             llvm::LLVMWriteBitcodeToFile(llmod, cstr.as_ptr());
         }
     }
@@ -400,13 +399,13 @@ impl CodegenContext {
 
 struct DiagnosticHandlers<'a> {
     data: *mut (&'a CodegenContext, &'a Handler),
-    llcx: ContextRef,
+    llcx: &'a llvm::Context,
 }
 
 impl<'a> DiagnosticHandlers<'a> {
     fn new(cgcx: &'a CodegenContext,
            handler: &'a Handler,
-           llcx: ContextRef) -> DiagnosticHandlers<'a> {
+           llcx: &'a llvm::Context) -> Self {
         let data = Box::into_raw(Box::new((cgcx, handler)));
         unsafe {
             llvm::LLVMRustSetInlineAsmDiagnosticHandler(llcx, inline_asm_handler, data as *mut _);
@@ -433,7 +432,7 @@ unsafe extern "C" fn report_inline_asm<'a, 'b>(cgcx: &'a CodegenContext,
     cgcx.diag_emitter.inline_asm_error(cookie as u32, msg.to_string());
 }
 
-unsafe extern "C" fn inline_asm_handler(diag: SMDiagnosticRef,
+unsafe extern "C" fn inline_asm_handler(diag: &SMDiagnostic,
                                         user: *const c_void,
                                         cookie: c_uint) {
     if user.is_null() {
@@ -447,7 +446,7 @@ unsafe extern "C" fn inline_asm_handler(diag: SMDiagnosticRef,
     report_inline_asm(cgcx, &msg, cookie);
 }
 
-unsafe extern "C" fn diagnostic_handler(info: DiagnosticInfoRef, user: *mut c_void) {
+unsafe extern "C" fn diagnostic_handler(info: &DiagnosticInfo, user: *mut c_void) {
     if user.is_null() {
         return
     }
@@ -495,7 +494,7 @@ unsafe fn optimize(cgcx: &CodegenContext,
     -> Result<(), FatalError>
 {
     let (llmod, llcx, tm) = match module.source {
-        ModuleSource::Codegened(ref llvm) => (llvm.llmod, llvm.llcx, llvm.tm),
+        ModuleSource::Codegened(ref llvm) => (llvm.llmod(), &*llvm.llcx, &*llvm.tm),
         ModuleSource::Preexisting(_) => {
             bug!("optimize_and_codegen: called with ModuleSource::Preexisting")
         }
@@ -520,50 +519,52 @@ unsafe fn optimize(cgcx: &CodegenContext,
         let fpm = llvm::LLVMCreateFunctionPassManagerForModule(llmod);
         let mpm = llvm::LLVMCreatePassManager();
 
-        // If we're verifying or linting, add them to the function pass
-        // manager.
-        let addpass = |pass_name: &str| {
-            let pass_name = CString::new(pass_name).unwrap();
-            let pass = llvm::LLVMRustFindAndCreatePass(pass_name.as_ptr());
-            if pass.is_null() {
-                return false;
-            }
-            let pass_manager = match llvm::LLVMRustPassKind(pass) {
-                llvm::PassKind::Function => fpm,
-                llvm::PassKind::Module => mpm,
-                llvm::PassKind::Other => {
-                    diag_handler.err("Encountered LLVM pass kind we can't handle");
-                    return true
-                },
+        {
+            // If we're verifying or linting, add them to the function pass
+            // manager.
+            let addpass = |pass_name: &str| {
+                let pass_name = CString::new(pass_name).unwrap();
+                let pass = match llvm::LLVMRustFindAndCreatePass(pass_name.as_ptr()) {
+                    Some(pass) => pass,
+                    None => return false,
+                };
+                let pass_manager = match llvm::LLVMRustPassKind(pass) {
+                    llvm::PassKind::Function => &*fpm,
+                    llvm::PassKind::Module => &*mpm,
+                    llvm::PassKind::Other => {
+                        diag_handler.err("Encountered LLVM pass kind we can't handle");
+                        return true
+                    },
+                };
+                llvm::LLVMRustAddPass(pass_manager, pass);
+                true
             };
-            llvm::LLVMRustAddPass(pass_manager, pass);
-            true
-        };
 
-        if config.verify_llvm_ir { assert!(addpass("verify")); }
-        if !config.no_prepopulate_passes {
-            llvm::LLVMRustAddAnalysisPasses(tm, fpm, llmod);
-            llvm::LLVMRustAddAnalysisPasses(tm, mpm, llmod);
-            let opt_level = config.opt_level.unwrap_or(llvm::CodeGenOptLevel::None);
-            let prepare_for_thin_lto = cgcx.lto == Lto::Thin || cgcx.lto == Lto::ThinLocal;
-            with_llvm_pmb(llmod, &config, opt_level, prepare_for_thin_lto, &mut |b| {
-                llvm::LLVMPassManagerBuilderPopulateFunctionPassManager(b, fpm);
-                llvm::LLVMPassManagerBuilderPopulateModulePassManager(b, mpm);
-            })
-        }
+            if config.verify_llvm_ir { assert!(addpass("verify")); }
+            if !config.no_prepopulate_passes {
+                llvm::LLVMRustAddAnalysisPasses(tm, fpm, llmod);
+                llvm::LLVMRustAddAnalysisPasses(tm, mpm, llmod);
+                let opt_level = config.opt_level.unwrap_or(llvm::CodeGenOptLevel::None);
+                let prepare_for_thin_lto = cgcx.lto == Lto::Thin || cgcx.lto == Lto::ThinLocal;
+                with_llvm_pmb(llmod, &config, opt_level, prepare_for_thin_lto, &mut |b| {
+                    llvm::LLVMPassManagerBuilderPopulateFunctionPassManager(b, fpm);
+                    llvm::LLVMPassManagerBuilderPopulateModulePassManager(b, mpm);
+                })
+            }
 
-        for pass in &config.passes {
-            if !addpass(pass) {
-                diag_handler.warn(&format!("unknown pass `{}`, ignoring",
-                                           pass));
+            for pass in &config.passes {
+                if !addpass(pass) {
+                    diag_handler.warn(&format!("unknown pass `{}`, ignoring",
+                                            pass));
+                }
             }
-        }
 
-        for pass in &cgcx.plugin_passes {
-            if !addpass(pass) {
-                diag_handler.err(&format!("a plugin asked for LLVM pass \
-                                           `{}` but LLVM does not \
-                                           recognize it", pass));
+            for pass in &cgcx.plugin_passes {
+                if !addpass(pass) {
+                    diag_handler.err(&format!("a plugin asked for LLVM pass \
+                                            `{}` but LLVM does not \
+                                            recognize it", pass));
+                }
             }
         }
 
@@ -617,192 +618,191 @@ unsafe fn codegen(cgcx: &CodegenContext,
     -> Result<CompiledModule, FatalError>
 {
     timeline.record("codegen");
-    let (llmod, llcx, tm) = match module.source {
-        ModuleSource::Codegened(ref llvm) => (llvm.llmod, llvm.llcx, llvm.tm),
-        ModuleSource::Preexisting(_) => {
-            bug!("codegen: called with ModuleSource::Preexisting")
-        }
-    };
-    let module_name = module.name.clone();
-    let module_name = Some(&module_name[..]);
-    let handlers = DiagnosticHandlers::new(cgcx, diag_handler, llcx);
-
-    if cgcx.msvc_imps_needed {
-        create_msvc_imps(cgcx, llcx, llmod);
-    }
-
-    // A codegen-specific pass manager is used to generate object
-    // files for an LLVM module.
-    //
-    // Apparently each of these pass managers is a one-shot kind of
-    // thing, so we create a new one for each type of output. The
-    // pass manager passed to the closure should be ensured to not
-    // escape the closure itself, and the manager should only be
-    // used once.
-    unsafe fn with_codegen<F, R>(tm: TargetMachineRef,
-                                 llmod: ModuleRef,
-                                 no_builtins: bool,
-                                 f: F) -> R
-        where F: FnOnce(PassManagerRef) -> R,
     {
-        let cpm = llvm::LLVMCreatePassManager();
-        llvm::LLVMRustAddAnalysisPasses(tm, cpm, llmod);
-        llvm::LLVMRustAddLibraryInfo(cpm, llmod, no_builtins);
-        f(cpm)
-    }
-
-    // If we don't have the integrated assembler, then we need to emit asm
-    // from LLVM and use `gcc` to create the object file.
-    let asm_to_obj = config.emit_obj && config.no_integrated_as;
-
-    // Change what we write and cleanup based on whether obj files are
-    // just llvm bitcode. In that case write bitcode, and possibly
-    // delete the bitcode if it wasn't requested. Don't generate the
-    // machine code, instead copy the .o file from the .bc
-    let write_bc = config.emit_bc || config.obj_is_bitcode;
-    let rm_bc = !config.emit_bc && config.obj_is_bitcode;
-    let write_obj = config.emit_obj && !config.obj_is_bitcode && !asm_to_obj;
-    let copy_bc_to_obj = config.emit_obj && config.obj_is_bitcode;
-
-    let bc_out = cgcx.output_filenames.temp_path(OutputType::Bitcode, module_name);
-    let obj_out = cgcx.output_filenames.temp_path(OutputType::Object, module_name);
-
-
-    if write_bc || config.emit_bc_compressed || config.embed_bitcode {
-        let thin;
-        let old;
-        let data = if llvm::LLVMRustThinLTOAvailable() {
-            thin = ThinBuffer::new(llmod);
-            thin.data()
-        } else {
-            old = ModuleBuffer::new(llmod);
-            old.data()
+        let (llmod, llcx, tm) = match module.source {
+            ModuleSource::Codegened(ref llvm) => (llvm.llmod(), &*llvm.llcx, &*llvm.tm),
+            ModuleSource::Preexisting(_) => {
+                bug!("codegen: called with ModuleSource::Preexisting")
+            }
         };
-        timeline.record("make-bc");
+        let module_name = module.name.clone();
+        let module_name = Some(&module_name[..]);
+        let handlers = DiagnosticHandlers::new(cgcx, diag_handler, llcx);
 
-        if write_bc {
-            if let Err(e) = fs::write(&bc_out, data) {
-                diag_handler.err(&format!("failed to write bytecode: {}", e));
-            }
-            timeline.record("write-bc");
+        if cgcx.msvc_imps_needed {
+            create_msvc_imps(cgcx, llcx, llmod);
         }
 
-        if config.embed_bitcode {
-            embed_bitcode(cgcx, llcx, llmod, Some(data));
-            timeline.record("embed-bc");
-        }
+        // A codegen-specific pass manager is used to generate object
+        // files for an LLVM module.
+        //
+        // Apparently each of these pass managers is a one-shot kind of
+        // thing, so we create a new one for each type of output. The
+        // pass manager passed to the closure should be ensured to not
+        // escape the closure itself, and the manager should only be
+        // used once.
+        unsafe fn with_codegen<'ll, F, R>(tm: &'ll llvm::TargetMachine,
+                                    llmod: &'ll llvm::Module,
+                                    no_builtins: bool,
+                                    f: F) -> R
+            where F: FnOnce(&'ll mut PassManager<'ll>) -> R,
+        {
+            let cpm = llvm::LLVMCreatePassManager();
+            llvm::LLVMRustAddAnalysisPasses(tm, cpm, llmod);
+            llvm::LLVMRustAddLibraryInfo(cpm, llmod, no_builtins);
+            f(cpm)
+        }
+
+        // If we don't have the integrated assembler, then we need to emit asm
+        // from LLVM and use `gcc` to create the object file.
+        let asm_to_obj = config.emit_obj && config.no_integrated_as;
+
+        // Change what we write and cleanup based on whether obj files are
+        // just llvm bitcode. In that case write bitcode, and possibly
+        // delete the bitcode if it wasn't requested. Don't generate the
+        // machine code, instead copy the .o file from the .bc
+        let write_bc = config.emit_bc || config.obj_is_bitcode;
+        let rm_bc = !config.emit_bc && config.obj_is_bitcode;
+        let write_obj = config.emit_obj && !config.obj_is_bitcode && !asm_to_obj;
+        let copy_bc_to_obj = config.emit_obj && config.obj_is_bitcode;
+
+        let bc_out = cgcx.output_filenames.temp_path(OutputType::Bitcode, module_name);
+        let obj_out = cgcx.output_filenames.temp_path(OutputType::Object, module_name);
+
+
+        if write_bc || config.emit_bc_compressed || config.embed_bitcode {
+            let thin;
+            let old;
+            let data = if llvm::LLVMRustThinLTOAvailable() {
+                thin = ThinBuffer::new(llmod);
+                thin.data()
+            } else {
+                old = ModuleBuffer::new(llmod);
+                old.data()
+            };
+            timeline.record("make-bc");
 
-        if config.emit_bc_compressed {
-            let dst = bc_out.with_extension(RLIB_BYTECODE_EXTENSION);
-            let data = bytecode::encode(&module.llmod_id, data);
-            if let Err(e) = fs::write(&dst, data) {
-                diag_handler.err(&format!("failed to write bytecode: {}", e));
+            if write_bc {
+                if let Err(e) = fs::write(&bc_out, data) {
+                    diag_handler.err(&format!("failed to write bytecode: {}", e));
+                }
+                timeline.record("write-bc");
             }
-            timeline.record("compress-bc");
-        }
-    } else if config.embed_bitcode_marker {
-        embed_bitcode(cgcx, llcx, llmod, None);
-    }
 
-    time_ext(config.time_passes, None, &format!("codegen passes [{}]", module_name.unwrap()),
-         || -> Result<(), FatalError> {
-        if config.emit_ir {
-            let out = cgcx.output_filenames.temp_path(OutputType::LlvmAssembly, module_name);
-            let out = path2cstr(&out);
-
-            extern "C" fn demangle_callback(input_ptr: *const c_char,
-                                            input_len: size_t,
-                                            output_ptr: *mut c_char,
-                                            output_len: size_t) -> size_t {
-                let input = unsafe {
-                    slice::from_raw_parts(input_ptr as *const u8, input_len as usize)
-                };
+            if config.embed_bitcode {
+                embed_bitcode(cgcx, llcx, llmod, Some(data));
+                timeline.record("embed-bc");
+            }
 
-                let input = match str::from_utf8(input) {
-                    Ok(s) => s,
-                    Err(_) => return 0,
-                };
+            if config.emit_bc_compressed {
+                let dst = bc_out.with_extension(RLIB_BYTECODE_EXTENSION);
+                let data = bytecode::encode(&module.llmod_id, data);
+                if let Err(e) = fs::write(&dst, data) {
+                    diag_handler.err(&format!("failed to write bytecode: {}", e));
+                }
+                timeline.record("compress-bc");
+            }
+        } else if config.embed_bitcode_marker {
+            embed_bitcode(cgcx, llcx, llmod, None);
+        }
+
+        time_ext(config.time_passes, None, &format!("codegen passes [{}]", module_name.unwrap()),
+            || -> Result<(), FatalError> {
+            if config.emit_ir {
+                let out = cgcx.output_filenames.temp_path(OutputType::LlvmAssembly, module_name);
+                let out = path2cstr(&out);
+
+                extern "C" fn demangle_callback(input_ptr: *const c_char,
+                                                input_len: size_t,
+                                                output_ptr: *mut c_char,
+                                                output_len: size_t) -> size_t {
+                    let input = unsafe {
+                        slice::from_raw_parts(input_ptr as *const u8, input_len as usize)
+                    };
 
-                let output = unsafe {
-                    slice::from_raw_parts_mut(output_ptr as *mut u8, output_len as usize)
-                };
-                let mut cursor = io::Cursor::new(output);
+                    let input = match str::from_utf8(input) {
+                        Ok(s) => s,
+                        Err(_) => return 0,
+                    };
 
-                let demangled = match rustc_demangle::try_demangle(input) {
-                    Ok(d) => d,
-                    Err(_) => return 0,
-                };
+                    let output = unsafe {
+                        slice::from_raw_parts_mut(output_ptr as *mut u8, output_len as usize)
+                    };
+                    let mut cursor = io::Cursor::new(output);
+
+                    let demangled = match rustc_demangle::try_demangle(input) {
+                        Ok(d) => d,
+                        Err(_) => return 0,
+                    };
+
+                    if let Err(_) = write!(cursor, "{:#}", demangled) {
+                        // Possible only if provided buffer is not big enough
+                        return 0;
+                    }
 
-                if let Err(_) = write!(cursor, "{:#}", demangled) {
-                    // Possible only if provided buffer is not big enough
-                    return 0;
+                    cursor.position() as size_t
                 }
 
-                cursor.position() as size_t
+                with_codegen(tm, llmod, config.no_builtins, |cpm| {
+                    llvm::LLVMRustPrintModule(cpm, llmod, out.as_ptr(), demangle_callback);
+                    llvm::LLVMDisposePassManager(cpm);
+                });
+                timeline.record("ir");
             }
 
-            with_codegen(tm, llmod, config.no_builtins, |cpm| {
-                llvm::LLVMRustPrintModule(cpm, llmod, out.as_ptr(), demangle_callback);
-                llvm::LLVMDisposePassManager(cpm);
-            });
-            timeline.record("ir");
-        }
-
-        if config.emit_asm || asm_to_obj {
-            let path = cgcx.output_filenames.temp_path(OutputType::Assembly, module_name);
+            if config.emit_asm || asm_to_obj {
+                let path = cgcx.output_filenames.temp_path(OutputType::Assembly, module_name);
 
-            // We can't use the same module for asm and binary output, because that triggers
-            // various errors like invalid IR or broken binaries, so we might have to clone the
-            // module to produce the asm output
-            let llmod = if config.emit_obj {
-                llvm::LLVMCloneModule(llmod)
-            } else {
-                llmod
-            };
-            with_codegen(tm, llmod, config.no_builtins, |cpm| {
-                write_output_file(diag_handler, tm, cpm, llmod, &path,
-                                  llvm::FileType::AssemblyFile)
-            })?;
-            if config.emit_obj {
-                llvm::LLVMDisposeModule(llmod);
+                // We can't use the same module for asm and binary output, because that triggers
+                // various errors like invalid IR or broken binaries, so we might have to clone the
+                // module to produce the asm output
+                let llmod = if config.emit_obj {
+                    llvm::LLVMCloneModule(llmod)
+                } else {
+                    llmod
+                };
+                with_codegen(tm, llmod, config.no_builtins, |cpm| {
+                    write_output_file(diag_handler, tm, cpm, llmod, &path,
+                                    llvm::FileType::AssemblyFile)
+                })?;
+                timeline.record("asm");
             }
-            timeline.record("asm");
-        }
 
-        if write_obj {
-            with_codegen(tm, llmod, config.no_builtins, |cpm| {
-                write_output_file(diag_handler, tm, cpm, llmod, &obj_out,
-                                  llvm::FileType::ObjectFile)
-            })?;
-            timeline.record("obj");
-        } else if asm_to_obj {
-            let assembly = cgcx.output_filenames.temp_path(OutputType::Assembly, module_name);
-            run_assembler(cgcx, diag_handler, &assembly, &obj_out);
-            timeline.record("asm_to_obj");
-
-            if !config.emit_asm && !cgcx.save_temps {
-                drop(fs::remove_file(&assembly));
+            if write_obj {
+                with_codegen(tm, llmod, config.no_builtins, |cpm| {
+                    write_output_file(diag_handler, tm, cpm, llmod, &obj_out,
+                                    llvm::FileType::ObjectFile)
+                })?;
+                timeline.record("obj");
+            } else if asm_to_obj {
+                let assembly = cgcx.output_filenames.temp_path(OutputType::Assembly, module_name);
+                run_assembler(cgcx, diag_handler, &assembly, &obj_out);
+                timeline.record("asm_to_obj");
+
+                if !config.emit_asm && !cgcx.save_temps {
+                    drop(fs::remove_file(&assembly));
+                }
             }
-        }
 
-        Ok(())
-    })?;
+            Ok(())
+        })?;
 
-    if copy_bc_to_obj {
-        debug!("copying bitcode {:?} to obj {:?}", bc_out, obj_out);
-        if let Err(e) = link_or_copy(&bc_out, &obj_out) {
-            diag_handler.err(&format!("failed to copy bitcode to object file: {}", e));
+        if copy_bc_to_obj {
+            debug!("copying bitcode {:?} to obj {:?}", bc_out, obj_out);
+            if let Err(e) = link_or_copy(&bc_out, &obj_out) {
+                diag_handler.err(&format!("failed to copy bitcode to object file: {}", e));
+            }
         }
-    }
 
-    if rm_bc {
-        debug!("removing_bitcode {:?}", bc_out);
-        if let Err(e) = fs::remove_file(&bc_out) {
-            diag_handler.err(&format!("failed to remove bitcode: {}", e));
+        if rm_bc {
+            debug!("removing_bitcode {:?}", bc_out);
+            if let Err(e) = fs::remove_file(&bc_out) {
+                diag_handler.err(&format!("failed to remove bitcode: {}", e));
+            }
         }
-    }
 
-    drop(handlers);
+        drop(handlers);
+    }
     Ok(module.into_compiled_module(config.emit_obj,
                                    config.emit_bc,
                                    config.emit_bc_compressed,
@@ -828,13 +828,13 @@ unsafe fn codegen(cgcx: &CodegenContext,
 /// Basically all of this is us attempting to follow in the footsteps of clang
 /// on iOS. See #35968 for lots more info.
 unsafe fn embed_bitcode(cgcx: &CodegenContext,
-                        llcx: ContextRef,
-                        llmod: ModuleRef,
+                        llcx: &llvm::Context,
+                        llmod: &llvm::Module,
                         bitcode: Option<&[u8]>) {
     let llconst = C_bytes_in_context(llcx, bitcode.unwrap_or(&[]));
     let llglobal = llvm::LLVMAddGlobal(
         llmod,
-        val_ty(llconst).to_ref(),
+        val_ty(llconst),
         "rustc.embedded.module\0".as_ptr() as *const _,
     );
     llvm::LLVMSetInitializer(llglobal, llconst);
@@ -854,7 +854,7 @@ unsafe fn embed_bitcode(cgcx: &CodegenContext,
     let llconst = C_bytes_in_context(llcx, &[]);
     let llglobal = llvm::LLVMAddGlobal(
         llmod,
-        val_ty(llconst).to_ref(),
+        val_ty(llconst),
         "rustc.embedded.cmdline\0".as_ptr() as *const _,
     );
     llvm::LLVMSetInitializer(llglobal, llconst);
@@ -2050,11 +2050,11 @@ pub fn run_assembler(cgcx: &CodegenContext, handler: &Handler, assembly: &Path,
     }
 }
 
-pub unsafe fn with_llvm_pmb(llmod: ModuleRef,
+pub unsafe fn with_llvm_pmb(llmod: &llvm::Module,
                             config: &ModuleConfig,
                             opt_level: llvm::CodeGenOptLevel,
                             prepare_for_thin_lto: bool,
-                            f: &mut dyn FnMut(llvm::PassManagerBuilderRef)) {
+                            f: &mut dyn FnMut(&llvm::PassManagerBuilder)) {
     use std::ptr;
 
     // Create the PassManagerBuilder for LLVM. We configure it with
@@ -2353,7 +2353,7 @@ fn msvc_imps_needed(tcx: TyCtxt) -> bool {
 // when using MSVC linker.  We do this only for data, as linker can fix up
 // code references on its own.
 // See #26591, #27438
-fn create_msvc_imps(cgcx: &CodegenContext, llcx: ContextRef, llmod: ModuleRef) {
+fn create_msvc_imps(cgcx: &CodegenContext, llcx: &llvm::Context, llmod: &llvm::Module) {
     if !cgcx.msvc_imps_needed {
         return
     }
@@ -2383,7 +2383,7 @@ fn create_msvc_imps(cgcx: &CodegenContext, llcx: ContextRef, llmod: ModuleRef) {
             .collect::<Vec<_>>();
         for (imp_name, val) in globals {
             let imp = llvm::LLVMAddGlobal(llmod,
-                                          i8p_ty.to_ref(),
+                                          i8p_ty,
                                           imp_name.as_ptr() as *const _);
             llvm::LLVMSetInitializer(imp, consts::ptrcast(val, i8p_ty));
             llvm::LLVMRustSetLinkage(imp, llvm::Linkage::ExternalLinkage);
diff --git a/src/librustc_codegen_llvm/base.rs b/src/librustc_codegen_llvm/base.rs
index 223c04f420f..8278b443a4c 100644
--- a/src/librustc_codegen_llvm/base.rs
+++ b/src/librustc_codegen_llvm/base.rs
@@ -17,11 +17,11 @@
 //!
 //! Hopefully useful general knowledge about codegen:
 //!
-//!   * There's no way to find out the Ty type of a ValueRef.  Doing so
+//!   * There's no way to find out the Ty type of a Value.  Doing so
 //!     would be "trying to get the eggs out of an omelette" (credit:
-//!     pcwalton).  You can, instead, find out its TypeRef by calling val_ty,
-//!     but one TypeRef corresponds to many `Ty`s; for instance, tup(int, int,
-//!     int) and rec(x=int, y=int, z=int) will have the same TypeRef.
+//!     pcwalton).  You can, instead, find out its llvm::Type by calling val_ty,
+//!     but one llvm::Type corresponds to many `Ty`s; for instance, tup(int, int,
+//!     int) and rec(x=int, y=int, z=int) will have the same llvm::Type.
 
 use super::ModuleLlvm;
 use super::ModuleSource;
@@ -30,9 +30,8 @@ use super::ModuleKind;
 
 use abi;
 use back::link;
-use back::write::{self, OngoingCodegen, create_target_machine};
-use llvm::{ContextRef, ModuleRef, ValueRef, Vector, get_param};
-use llvm;
+use back::write::{self, OngoingCodegen};
+use llvm::{self, TypeKind, get_param};
 use metadata;
 use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
 use rustc::middle::lang_items::StartFnLangItem;
@@ -59,7 +58,7 @@ use rustc_mir::monomorphize::collector::{self, MonoItemCollectionMode};
 use rustc_mir::monomorphize::item::DefPathBasedNames;
 use common::{self, C_struct_in_context, C_array, val_ty};
 use consts;
-use context::{self, CodegenCx};
+use context::CodegenCx;
 use debuginfo;
 use declare;
 use meth;
@@ -77,7 +76,6 @@ use rustc_data_structures::sync::Lrc;
 
 use std::any::Any;
 use std::ffi::CString;
-use std::str;
 use std::sync::Arc;
 use std::time::{Instant, Duration};
 use std::i32;
@@ -88,18 +86,20 @@ use syntax_pos::symbol::InternedString;
 use syntax::attr;
 use rustc::hir::{self, CodegenFnAttrs};
 
+use value::Value;
+
 use mir::operand::OperandValue;
 
 use rustc_codegen_utils::check_for_rustc_errors_attr;
 
-pub struct StatRecorder<'a, 'tcx: 'a> {
-    cx: &'a CodegenCx<'a, 'tcx>,
+pub struct StatRecorder<'a, 'll: 'a, 'tcx: 'll> {
+    cx: &'a CodegenCx<'ll, 'tcx>,
     name: Option<String>,
     istart: usize,
 }
 
-impl<'a, 'tcx> StatRecorder<'a, 'tcx> {
-    pub fn new(cx: &'a CodegenCx<'a, 'tcx>, name: String) -> StatRecorder<'a, '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;
         StatRecorder {
             cx,
@@ -109,7 +109,7 @@ impl<'a, 'tcx> StatRecorder<'a, 'tcx> {
     }
 }
 
-impl<'a, 'tcx> Drop for StatRecorder<'a, 'tcx> {
+impl Drop for StatRecorder<'a, 'll, 'tcx> {
     fn drop(&mut self) {
         if self.cx.sess().codegen_stats() {
             let mut stats = self.cx.stats.borrow_mut();
@@ -156,14 +156,14 @@ pub fn bin_op_to_fcmp_predicate(op: hir::BinOpKind) -> llvm::RealPredicate {
     }
 }
 
-pub fn compare_simd_types<'a, 'tcx>(
-    bx: &Builder<'a, 'tcx>,
-    lhs: ValueRef,
-    rhs: ValueRef,
+pub fn compare_simd_types(
+    bx: &Builder<'a, 'll, 'tcx>,
+    lhs: &'ll Value,
+    rhs: &'ll Value,
     t: Ty<'tcx>,
-    ret_ty: Type,
+    ret_ty: &'ll Type,
     op: hir::BinOpKind
-) -> ValueRef {
+) -> &'ll Value {
     let signed = match t.sty {
         ty::TyFloat(_) => {
             let cmp = bin_op_to_fcmp_predicate(op);
@@ -188,11 +188,12 @@ pub fn compare_simd_types<'a, 'tcx>(
 /// 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, 'tcx>(cx: &CodegenCx<'cx, 'tcx>,
-                                source: Ty<'tcx>,
-                                target: Ty<'tcx>,
-                                old_info: Option<ValueRef>)
-                                -> ValueRef {
+pub fn unsized_info(
+    cx: &CodegenCx<'ll, 'tcx>,
+    source: Ty<'tcx>,
+    target: Ty<'tcx>,
+    old_info: Option<&'ll Value>,
+) -> &'ll Value {
     let (source, target) = cx.tcx.struct_lockstep_tails(source, target);
     match (&source.sty, &target.sty) {
         (&ty::TyArray(_, len), &ty::TySlice(_)) => {
@@ -217,12 +218,12 @@ pub fn unsized_info<'cx, 'tcx>(cx: &CodegenCx<'cx, 'tcx>,
 }
 
 /// Coerce `src` to `dst_ty`. `src_ty` must be a thin pointer.
-pub fn unsize_thin_ptr<'a, 'tcx>(
-    bx: &Builder<'a, 'tcx>,
-    src: ValueRef,
+pub fn unsize_thin_ptr(
+    bx: &Builder<'a, 'll, 'tcx>,
+    src: &'ll Value,
     src_ty: Ty<'tcx>,
     dst_ty: Ty<'tcx>
-) -> (ValueRef, ValueRef) {
+) -> (&'ll Value, &'ll Value) {
     debug!("unsize_thin_ptr: {:?} => {:?}", src_ty, dst_ty);
     match (&src_ty.sty, &dst_ty.sty) {
         (&ty::TyRef(_, a, _),
@@ -272,9 +273,11 @@ pub fn unsize_thin_ptr<'a, 'tcx>(
 
 /// 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<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
-                                     src: PlaceRef<'tcx>,
-                                     dst: PlaceRef<'tcx>) {
+pub fn coerce_unsized_into(
+    bx: &Builder<'a, 'll, 'tcx>,
+    src: PlaceRef<'ll, 'tcx>,
+    dst: PlaceRef<'ll, 'tcx>
+) {
     let src_ty = src.layout.ty;
     let dst_ty = dst.layout.ty;
     let coerce_ptr = || {
@@ -330,28 +333,28 @@ pub fn coerce_unsized_into<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
 }
 
 pub fn cast_shift_expr_rhs(
-    cx: &Builder, op: hir::BinOpKind, lhs: ValueRef, rhs: ValueRef
-) -> ValueRef {
+    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))
 }
 
-fn cast_shift_rhs<F, G>(op: hir::BinOpKind,
-                        lhs: ValueRef,
-                        rhs: ValueRef,
+fn cast_shift_rhs<'ll, F, G>(op: hir::BinOpKind,
+                        lhs: &'ll Value,
+                        rhs: &'ll Value,
                         trunc: F,
                         zext: G)
-                        -> ValueRef
-    where F: FnOnce(ValueRef, Type) -> ValueRef,
-          G: FnOnce(ValueRef, Type) -> ValueRef
+                        -> &'ll Value
+    where F: FnOnce(&'ll Value, &'ll Type) -> &'ll Value,
+          G: FnOnce(&'ll Value, &'ll Type) -> &'ll 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() == Vector {
+        if rhs_llty.kind() == TypeKind::Vector {
             rhs_llty = rhs_llty.element_type()
         }
-        if lhs_llty.kind() == Vector {
+        if lhs_llty.kind() == TypeKind::Vector {
             lhs_llty = lhs_llty.element_type()
         }
         let rhs_sz = rhs_llty.int_width();
@@ -379,12 +382,12 @@ pub fn wants_msvc_seh(sess: &Session) -> bool {
     sess.target.target.options.is_like_msvc
 }
 
-pub fn call_assume<'a, 'tcx>(bx: &Builder<'a, 'tcx>, val: ValueRef) {
+pub fn call_assume(bx: &Builder<'_, 'll, '_>, val: &'ll Value) {
     let assume_intrinsic = bx.cx.get_intrinsic("llvm.assume");
     bx.call(assume_intrinsic, &[val], None);
 }
 
-pub fn from_immediate(bx: &Builder, val: ValueRef) -> ValueRef {
+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))
     } else {
@@ -392,26 +395,36 @@ pub fn from_immediate(bx: &Builder, val: ValueRef) -> ValueRef {
     }
 }
 
-pub fn to_immediate(bx: &Builder, val: ValueRef, layout: layout::TyLayout) -> ValueRef {
+pub fn to_immediate(
+    bx: &Builder<'_, 'll, '_>,
+    val: &'ll Value,
+    layout: layout::TyLayout,
+) -> &'ll 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, val: ValueRef, scalar: &layout::Scalar) -> ValueRef {
+pub fn to_immediate_scalar(
+    bx: &Builder<'_, 'll, '_>,
+    val: &'ll Value,
+    scalar: &layout::Scalar,
+) -> &'ll Value {
     if scalar.is_bool() {
         return bx.trunc(val, Type::i1(bx.cx));
     }
     val
 }
 
-pub fn call_memcpy(bx: &Builder,
-                   dst: ValueRef,
-                   src: ValueRef,
-                   n_bytes: ValueRef,
-                   align: Align,
-                   flags: MemFlags) {
+pub fn call_memcpy(
+    bx: &Builder<'_, 'll, '_>,
+    dst: &'ll Value,
+    src: &'ll Value,
+    n_bytes: &'ll Value,
+    align: Align,
+    flags: MemFlags,
+) {
     if flags.contains(MemFlags::NONTEMPORAL) {
         // HACK(nox): This is inefficient but there is no nontemporal memcpy.
         let val = bx.load(src, align);
@@ -431,10 +444,10 @@ pub fn call_memcpy(bx: &Builder,
     bx.call(memcpy, &[dst_ptr, src_ptr, size, align, volatile], None);
 }
 
-pub fn memcpy_ty<'a, 'tcx>(
-    bx: &Builder<'a, 'tcx>,
-    dst: ValueRef,
-    src: ValueRef,
+pub fn memcpy_ty(
+    bx: &Builder<'_, 'll, 'tcx>,
+    dst: &'ll Value,
+    src: &'ll Value,
     layout: TyLayout<'tcx>,
     align: Align,
     flags: MemFlags,
@@ -447,12 +460,14 @@ pub fn memcpy_ty<'a, 'tcx>(
     call_memcpy(bx, dst, src, C_usize(bx.cx, size), align, flags);
 }
 
-pub fn call_memset<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
-                             ptr: ValueRef,
-                             fill_byte: ValueRef,
-                             size: ValueRef,
-                             align: ValueRef,
-                             volatile: bool) -> ValueRef {
+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);
@@ -511,7 +526,7 @@ pub fn codegen_instance<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, instance: Instance<'
     mir::codegen_mir(cx, lldecl, &mir, instance, sig);
 }
 
-pub fn set_link_section(llval: ValueRef, attrs: &CodegenFnAttrs) {
+pub fn set_link_section(llval: &Value, attrs: &CodegenFnAttrs) {
     let sect = match attrs.link_section {
         Some(name) => name,
         None => return,
@@ -549,12 +564,14 @@ fn maybe_create_entry_wrapper(cx: &CodegenCx) {
         None => {}    // Do nothing.
     }
 
-    fn create_entry_fn<'cx>(cx: &'cx CodegenCx,
-                       sp: Span,
-                       rust_main: ValueRef,
-                       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));
+    fn create_entry_fn(
+        cx: &CodegenCx<'ll, '_>,
+        sp: Span,
+        rust_main: &'ll 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 main_ret_ty = cx.tcx.fn_sig(rust_main_def_id).output();
         // Given that `main()` has no arguments,
@@ -609,16 +626,14 @@ fn maybe_create_entry_wrapper(cx: &CodegenCx) {
 }
 
 fn write_metadata<'a, 'gcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>,
-                            llmod_id: &str,
+                            llvm_module: &ModuleLlvm,
                             link_meta: &LinkMeta)
-                            -> (ContextRef, ModuleRef, EncodedMetadata) {
+                            -> EncodedMetadata {
     use std::io::Write;
     use flate2::Compression;
     use flate2::write::DeflateEncoder;
 
-    let (metadata_llcx, metadata_llmod) = unsafe {
-        context::create_context_and_module(tcx.sess, llmod_id)
-    };
+    let (metadata_llcx, metadata_llmod) = (&*llvm_module.llcx, llvm_module.llmod());
 
     #[derive(PartialEq, Eq, PartialOrd, Ord)]
     enum MetadataKind {
@@ -641,14 +656,12 @@ fn write_metadata<'a, 'gcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>,
     }).max().unwrap_or(MetadataKind::None);
 
     if kind == MetadataKind::None {
-        return (metadata_llcx,
-                metadata_llmod,
-                EncodedMetadata::new());
+        return EncodedMetadata::new();
     }
 
     let metadata = tcx.encode_metadata(link_meta);
     if kind == MetadataKind::Uncompressed {
-        return (metadata_llcx, metadata_llmod, metadata);
+        return metadata;
     }
 
     assert!(kind == MetadataKind::Compressed);
@@ -661,7 +674,7 @@ fn write_metadata<'a, 'gcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>,
     let name = exported_symbols::metadata_symbol_name(tcx);
     let buf = CString::new(name).unwrap();
     let llglobal = unsafe {
-        llvm::LLVMAddGlobal(metadata_llmod, val_ty(llconst).to_ref(), buf.as_ptr())
+        llvm::LLVMAddGlobal(metadata_llmod, val_ty(llconst), buf.as_ptr())
     };
     unsafe {
         llvm::LLVMSetInitializer(llglobal, llconst);
@@ -676,29 +689,27 @@ fn write_metadata<'a, 'gcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>,
         let directive = CString::new(directive).unwrap();
         llvm::LLVMSetModuleInlineAsm(metadata_llmod, directive.as_ptr())
     }
-    return (metadata_llcx, metadata_llmod, metadata);
+    return metadata;
 }
 
-pub struct ValueIter {
-    cur: ValueRef,
-    step: unsafe extern "C" fn(ValueRef) -> ValueRef,
+pub struct ValueIter<'ll> {
+    cur: Option<&'ll Value>,
+    step: unsafe extern "C" fn(&'ll Value) -> Option<&'ll Value>,
 }
 
-impl Iterator for ValueIter {
-    type Item = ValueRef;
+impl Iterator for ValueIter<'ll> {
+    type Item = &'ll Value;
 
-    fn next(&mut self) -> Option<ValueRef> {
+    fn next(&mut self) -> Option<&'ll Value> {
         let old = self.cur;
-        if !old.is_null() {
+        if let Some(old) = old {
             self.cur = unsafe { (self.step)(old) };
-            Some(old)
-        } else {
-            None
         }
+        old
     }
 }
 
-pub fn iter_globals(llmod: llvm::ModuleRef) -> ValueIter {
+pub fn iter_globals(llmod: &'ll llvm::Module) -> ValueIter<'ll> {
     unsafe {
         ValueIter {
             cur: llvm::LLVMGetFirstGlobal(llmod),
@@ -731,19 +742,15 @@ pub fn codegen_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
     // Codegen the metadata.
     let llmod_id = "metadata";
-    let (metadata_llcx, metadata_llmod, metadata) =
-        time(tcx.sess, "write metadata", || {
-            write_metadata(tcx, llmod_id, &link_meta)
-        });
+    let metadata_llvm_module = ModuleLlvm::new(tcx.sess, llmod_id);
+    let metadata = time(tcx.sess, "write metadata", || {
+        write_metadata(tcx, &metadata_llvm_module, &link_meta)
+    });
 
     let metadata_module = ModuleCodegen {
         name: link::METADATA_MODULE_NAME.to_string(),
         llmod_id: llmod_id.to_string(),
-        source: ModuleSource::Codegened(ModuleLlvm {
-            llcx: metadata_llcx,
-            llmod: metadata_llmod,
-            tm: create_target_machine(tcx.sess, false),
-        }),
+        source: ModuleSource::Codegened(metadata_llvm_module),
         kind: ModuleKind::Metadata,
     };
 
@@ -803,13 +810,7 @@ pub fn codegen_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     let allocator_module = if let Some(kind) = *tcx.sess.allocator_kind.get() {
         unsafe {
             let llmod_id = "allocator";
-            let (llcx, llmod) =
-                context::create_context_and_module(tcx.sess, llmod_id);
-            let modules = ModuleLlvm {
-                llmod,
-                llcx,
-                tm: create_target_machine(tcx.sess, false),
-            };
+            let modules = ModuleLlvm::new(tcx.sess, llmod_id);
             time(tcx.sess, "write allocator module", || {
                 allocator::codegen(tcx, &modules, kind)
             });
@@ -1200,8 +1201,9 @@ fn compile_codegen_unit<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                    .to_fingerprint().to_hex());
 
         // Instantiate monomorphizations without filling out definitions yet...
-        let cx = CodegenCx::new(tcx, cgu, &llmod_id);
-        let module = {
+        let llvm_module = ModuleLlvm::new(tcx.sess, &llmod_id);
+        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 {
@@ -1220,7 +1222,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, llvm::LLVMTypeOf(old_g));
+                    let bitcast = llvm::LLVMConstPointerCast(new_g, val_ty(old_g));
                     llvm::LLVMReplaceAllUsesWith(old_g, bitcast);
                     llvm::LLVMDeleteGlobal(old_g);
                 }
@@ -1235,7 +1237,7 @@ fn compile_codegen_unit<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
                 unsafe {
                     let g = llvm::LLVMAddGlobal(cx.llmod,
-                                                val_ty(array).to_ref(),
+                                                val_ty(array),
                                                 name.as_ptr());
                     llvm::LLVMSetInitializer(g, array);
                     llvm::LLVMRustSetLinkage(g, llvm::Linkage::AppendingLinkage);
@@ -1248,21 +1250,15 @@ fn compile_codegen_unit<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                 debuginfo::finalize(&cx);
             }
 
-            let llvm_module = ModuleLlvm {
-                llcx: cx.llcx,
-                llmod: cx.llmod,
-                tm: create_target_machine(cx.sess(), false),
-            };
-
-            ModuleCodegen {
-                name: cgu_name,
-                source: ModuleSource::Codegened(llvm_module),
-                kind: ModuleKind::Regular,
-                llmod_id,
-            }
+            cx.stats.into_inner()
         };
 
-        (cx.into_stats(), module)
+        (stats, ModuleCodegen {
+            name: cgu_name,
+            source: ModuleSource::Codegened(llvm_module),
+            kind: ModuleKind::Regular,
+            llmod_id,
+        })
     }
 }
 
diff --git a/src/librustc_codegen_llvm/builder.rs b/src/librustc_codegen_llvm/builder.rs
index b34d0f1cd90..b174cd8c7ac 100644
--- a/src/librustc_codegen_llvm/builder.rs
+++ b/src/librustc_codegen_llvm/builder.rs
@@ -8,12 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![allow(dead_code)] // FFI wrappers
-
-use llvm;
 use llvm::{AtomicRmwBinOp, AtomicOrdering, SynchronizationScope, AsmDialect};
-use llvm::{Opcode, IntPredicate, RealPredicate, False, OperandBundleDef};
-use llvm::{ValueRef, BasicBlockRef, BuilderRef};
+use llvm::{IntPredicate, RealPredicate, False, OperandBundleDef};
+use llvm::{self, BasicBlock};
 use common::*;
 use type_::Type;
 use value::Value;
@@ -26,19 +23,18 @@ use std::borrow::Cow;
 use std::ffi::CString;
 use std::ops::Range;
 use std::ptr;
-use syntax_pos::Span;
 
 // All Builders must have an llfn associated with them
 #[must_use]
-pub struct Builder<'a, 'tcx: 'a> {
-    pub llbuilder: BuilderRef,
-    pub cx: &'a CodegenCx<'a, 'tcx>,
+pub struct Builder<'a, 'll: 'a, 'tcx: 'll> {
+    pub llbuilder: &'ll mut llvm::Builder<'ll>,
+    pub cx: &'a CodegenCx<'ll, 'tcx>,
 }
 
-impl<'a, 'tcx> Drop for Builder<'a, 'tcx> {
+impl Drop for Builder<'a, 'll, 'tcx> {
     fn drop(&mut self) {
         unsafe {
-            llvm::LLVMDisposeBuilder(self.llbuilder);
+            llvm::LLVMDisposeBuilder(&mut *(self.llbuilder as *mut _));
         }
     }
 }
@@ -58,8 +54,8 @@ bitflags! {
     }
 }
 
-impl<'a, 'tcx> Builder<'a, 'tcx> {
-    pub fn new_block<'b>(cx: &'a CodegenCx<'a, 'tcx>, llfn: ValueRef, name: &'b str) -> Self {
+impl Builder<'a, 'll, 'tcx> {
+    pub fn new_block<'b>(cx: &'a CodegenCx<'ll, 'tcx>, llfn: &'ll Value, name: &'b str) -> Self {
         let bx = Builder::with_cx(cx);
         let llbb = unsafe {
             let name = CString::new(name).unwrap();
@@ -73,7 +69,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         bx
     }
 
-    pub fn with_cx(cx: &'a CodegenCx<'a, 'tcx>) -> Self {
+    pub fn with_cx(cx: &'a CodegenCx<'ll, 'tcx>) -> Self {
         // Create a fresh builder from the crate context.
         let llbuilder = unsafe {
             llvm::LLVMCreateBuilderInContext(cx.llcx)
@@ -84,7 +80,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         }
     }
 
-    pub fn build_sibling_block<'b>(&self, name: &'b str) -> Builder<'a, 'tcx> {
+    pub fn build_sibling_block<'b>(&self, name: &'b str) -> Builder<'a, 'll, 'tcx> {
         Builder::new_block(self.cx, self.llfn(), name)
     }
 
@@ -96,13 +92,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         self.cx.tcx
     }
 
-    pub fn llfn(&self) -> ValueRef {
+    pub fn llfn(&self) -> &'ll Value {
         unsafe {
             llvm::LLVMGetBasicBlockParent(self.llbb())
         }
     }
 
-    pub fn llbb(&self) -> BasicBlockRef {
+    pub fn llbb(&self) -> &'ll BasicBlock {
         unsafe {
             llvm::LLVMGetInsertBlock(self.llbuilder)
         }
@@ -121,26 +117,20 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         }
     }
 
-    pub fn set_value_name(&self, value: ValueRef, name: &str) {
+    pub fn set_value_name(&self, value: &'ll Value, name: &str) {
         let cname = CString::new(name.as_bytes()).unwrap();
         unsafe {
             llvm::LLVMSetValueName(value, cname.as_ptr());
         }
     }
 
-    pub fn position_before(&self, insn: ValueRef) {
-        unsafe {
-            llvm::LLVMPositionBuilderBefore(self.llbuilder, insn);
-        }
-    }
-
-    pub fn position_at_end(&self, llbb: BasicBlockRef) {
+    pub fn position_at_end(&self, llbb: &'ll BasicBlock) {
         unsafe {
             llvm::LLVMPositionBuilderAtEnd(self.llbuilder, llbb);
         }
     }
 
-    pub fn position_at_start(&self, llbb: BasicBlockRef) {
+    pub fn position_at_start(&self, llbb: &'ll BasicBlock) {
         unsafe {
             llvm::LLVMRustPositionBuilderAtStart(self.llbuilder, llbb);
         }
@@ -153,65 +143,57 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         }
     }
 
-    pub fn ret(&self, v: ValueRef) {
+    pub fn ret(&self, v: &'ll Value) {
         self.count_insn("ret");
         unsafe {
             llvm::LLVMBuildRet(self.llbuilder, v);
         }
     }
 
-    pub fn aggregate_ret(&self, ret_vals: &[ValueRef]) {
-        unsafe {
-            llvm::LLVMBuildAggregateRet(self.llbuilder,
-                                        ret_vals.as_ptr(),
-                                        ret_vals.len() as c_uint);
-        }
-    }
-
-    pub fn br(&self, dest: BasicBlockRef) {
+    pub fn br(&self, dest: &'ll BasicBlock) {
         self.count_insn("br");
         unsafe {
             llvm::LLVMBuildBr(self.llbuilder, dest);
         }
     }
 
-    pub fn cond_br(&self, cond: ValueRef, then_llbb: BasicBlockRef, else_llbb: BasicBlockRef) {
+    pub fn cond_br(
+        &self,
+        cond: &'ll Value,
+        then_llbb: &'ll BasicBlock,
+        else_llbb: &'ll BasicBlock,
+    ) {
         self.count_insn("condbr");
         unsafe {
             llvm::LLVMBuildCondBr(self.llbuilder, cond, then_llbb, else_llbb);
         }
     }
 
-    pub fn switch(&self, v: ValueRef, else_llbb: BasicBlockRef, num_cases: usize) -> ValueRef {
+    pub fn switch(
+        &self,
+        v: &'ll Value,
+        else_llbb: &'ll BasicBlock,
+        num_cases: usize,
+    ) -> &'ll Value {
         unsafe {
             llvm::LLVMBuildSwitch(self.llbuilder, v, else_llbb, num_cases as c_uint)
         }
     }
 
-    pub fn indirect_br(&self, addr: ValueRef, num_dests: usize) {
-        self.count_insn("indirectbr");
-        unsafe {
-            llvm::LLVMBuildIndirectBr(self.llbuilder, addr, num_dests as c_uint);
-        }
-    }
-
     pub fn invoke(&self,
-                  llfn: ValueRef,
-                  args: &[ValueRef],
-                  then: BasicBlockRef,
-                  catch: BasicBlockRef,
-                  bundle: Option<&OperandBundleDef>) -> ValueRef {
+                  llfn: &'ll Value,
+                  args: &[&'ll Value],
+                  then: &'ll BasicBlock,
+                  catch: &'ll BasicBlock,
+                  bundle: Option<&OperandBundleDef<'ll>>) -> &'ll Value {
         self.count_insn("invoke");
 
-        debug!("Invoke {:?} with args ({})",
-               Value(llfn),
-               args.iter()
-                   .map(|&v| format!("{:?}", Value(v)))
-                   .collect::<Vec<String>>()
-                   .join(", "));
+        debug!("Invoke {:?} with args ({:?})",
+               llfn,
+               args);
 
         let args = self.check_call("invoke", llfn, args);
-        let bundle = bundle.as_ref().map(|b| b.raw()).unwrap_or(ptr::null_mut());
+        let bundle = bundle.map(|b| &*b.raw);
 
         unsafe {
             llvm::LLVMRustBuildInvoke(self.llbuilder,
@@ -233,35 +215,21 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     }
 
     /* Arithmetic */
-    pub fn add(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
+    pub fn add(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
         self.count_insn("add");
         unsafe {
             llvm::LLVMBuildAdd(self.llbuilder, lhs, rhs, noname())
         }
     }
 
-    pub fn nswadd(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
-        self.count_insn("nswadd");
-        unsafe {
-            llvm::LLVMBuildNSWAdd(self.llbuilder, lhs, rhs, noname())
-        }
-    }
-
-    pub fn nuwadd(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
-        self.count_insn("nuwadd");
-        unsafe {
-            llvm::LLVMBuildNUWAdd(self.llbuilder, lhs, rhs, noname())
-        }
-    }
-
-    pub fn fadd(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
+    pub fn fadd(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
         self.count_insn("fadd");
         unsafe {
             llvm::LLVMBuildFAdd(self.llbuilder, lhs, rhs, noname())
         }
     }
 
-    pub fn fadd_fast(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
+    pub fn fadd_fast(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
         self.count_insn("fadd");
         unsafe {
             let instr = llvm::LLVMBuildFAdd(self.llbuilder, lhs, rhs, noname());
@@ -270,35 +238,21 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         }
     }
 
-    pub fn sub(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
+    pub fn sub(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
         self.count_insn("sub");
         unsafe {
             llvm::LLVMBuildSub(self.llbuilder, lhs, rhs, noname())
         }
     }
 
-    pub fn nswsub(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
-        self.count_insn("nswsub");
-        unsafe {
-            llvm::LLVMBuildNSWSub(self.llbuilder, lhs, rhs, noname())
-        }
-    }
-
-    pub fn nuwsub(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
-        self.count_insn("nuwsub");
-        unsafe {
-            llvm::LLVMBuildNUWSub(self.llbuilder, lhs, rhs, noname())
-        }
-    }
-
-    pub fn fsub(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
+    pub fn fsub(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
         self.count_insn("fsub");
         unsafe {
             llvm::LLVMBuildFSub(self.llbuilder, lhs, rhs, noname())
         }
     }
 
-    pub fn fsub_fast(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
+    pub fn fsub_fast(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
         self.count_insn("fsub");
         unsafe {
             let instr = llvm::LLVMBuildFSub(self.llbuilder, lhs, rhs, noname());
@@ -307,35 +261,21 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         }
     }
 
-    pub fn mul(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
+    pub fn mul(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
         self.count_insn("mul");
         unsafe {
             llvm::LLVMBuildMul(self.llbuilder, lhs, rhs, noname())
         }
     }
 
-    pub fn nswmul(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
-        self.count_insn("nswmul");
-        unsafe {
-            llvm::LLVMBuildNSWMul(self.llbuilder, lhs, rhs, noname())
-        }
-    }
-
-    pub fn nuwmul(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
-        self.count_insn("nuwmul");
-        unsafe {
-            llvm::LLVMBuildNUWMul(self.llbuilder, lhs, rhs, noname())
-        }
-    }
-
-    pub fn fmul(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
+    pub fn fmul(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
         self.count_insn("fmul");
         unsafe {
             llvm::LLVMBuildFMul(self.llbuilder, lhs, rhs, noname())
         }
     }
 
-    pub fn fmul_fast(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
+    pub fn fmul_fast(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
         self.count_insn("fmul");
         unsafe {
             let instr = llvm::LLVMBuildFMul(self.llbuilder, lhs, rhs, noname());
@@ -345,42 +285,42 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     }
 
 
-    pub fn udiv(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
+    pub fn udiv(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
         self.count_insn("udiv");
         unsafe {
             llvm::LLVMBuildUDiv(self.llbuilder, lhs, rhs, noname())
         }
     }
 
-    pub fn exactudiv(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
+    pub fn exactudiv(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
         self.count_insn("exactudiv");
         unsafe {
             llvm::LLVMBuildExactUDiv(self.llbuilder, lhs, rhs, noname())
         }
     }
 
-    pub fn sdiv(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
+    pub fn sdiv(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
         self.count_insn("sdiv");
         unsafe {
             llvm::LLVMBuildSDiv(self.llbuilder, lhs, rhs, noname())
         }
     }
 
-    pub fn exactsdiv(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
+    pub fn exactsdiv(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
         self.count_insn("exactsdiv");
         unsafe {
             llvm::LLVMBuildExactSDiv(self.llbuilder, lhs, rhs, noname())
         }
     }
 
-    pub fn fdiv(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
+    pub fn fdiv(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
         self.count_insn("fdiv");
         unsafe {
             llvm::LLVMBuildFDiv(self.llbuilder, lhs, rhs, noname())
         }
     }
 
-    pub fn fdiv_fast(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
+    pub fn fdiv_fast(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
         self.count_insn("fdiv");
         unsafe {
             let instr = llvm::LLVMBuildFDiv(self.llbuilder, lhs, rhs, noname());
@@ -389,28 +329,28 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         }
     }
 
-    pub fn urem(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
+    pub fn urem(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
         self.count_insn("urem");
         unsafe {
             llvm::LLVMBuildURem(self.llbuilder, lhs, rhs, noname())
         }
     }
 
-    pub fn srem(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
+    pub fn srem(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
         self.count_insn("srem");
         unsafe {
             llvm::LLVMBuildSRem(self.llbuilder, lhs, rhs, noname())
         }
     }
 
-    pub fn frem(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
+    pub fn frem(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
         self.count_insn("frem");
         unsafe {
             llvm::LLVMBuildFRem(self.llbuilder, lhs, rhs, noname())
         }
     }
 
-    pub fn frem_fast(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
+    pub fn frem_fast(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
         self.count_insn("frem");
         unsafe {
             let instr = llvm::LLVMBuildFRem(self.llbuilder, lhs, rhs, noname());
@@ -419,91 +359,70 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         }
     }
 
-    pub fn shl(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
+    pub fn shl(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
         self.count_insn("shl");
         unsafe {
             llvm::LLVMBuildShl(self.llbuilder, lhs, rhs, noname())
         }
     }
 
-    pub fn lshr(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
+    pub fn lshr(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
         self.count_insn("lshr");
         unsafe {
             llvm::LLVMBuildLShr(self.llbuilder, lhs, rhs, noname())
         }
     }
 
-    pub fn ashr(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
+    pub fn ashr(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
         self.count_insn("ashr");
         unsafe {
             llvm::LLVMBuildAShr(self.llbuilder, lhs, rhs, noname())
         }
     }
 
-    pub fn and(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
+    pub fn and(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
         self.count_insn("and");
         unsafe {
             llvm::LLVMBuildAnd(self.llbuilder, lhs, rhs, noname())
         }
     }
 
-    pub fn or(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
+    pub fn or(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
         self.count_insn("or");
         unsafe {
             llvm::LLVMBuildOr(self.llbuilder, lhs, rhs, noname())
         }
     }
 
-    pub fn xor(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
+    pub fn xor(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
         self.count_insn("xor");
         unsafe {
             llvm::LLVMBuildXor(self.llbuilder, lhs, rhs, noname())
         }
     }
 
-    pub fn binop(&self, op: Opcode, lhs: ValueRef, rhs: ValueRef)
-              -> ValueRef {
-        self.count_insn("binop");
-        unsafe {
-            llvm::LLVMBuildBinOp(self.llbuilder, op, lhs, rhs, noname())
-        }
-    }
-
-    pub fn neg(&self, v: ValueRef) -> ValueRef {
+    pub fn neg(&self, v: &'ll Value) -> &'ll Value {
         self.count_insn("neg");
         unsafe {
             llvm::LLVMBuildNeg(self.llbuilder, v, noname())
         }
     }
 
-    pub fn nswneg(&self, v: ValueRef) -> ValueRef {
-        self.count_insn("nswneg");
-        unsafe {
-            llvm::LLVMBuildNSWNeg(self.llbuilder, v, noname())
-        }
-    }
-
-    pub fn nuwneg(&self, v: ValueRef) -> ValueRef {
-        self.count_insn("nuwneg");
-        unsafe {
-            llvm::LLVMBuildNUWNeg(self.llbuilder, v, noname())
-        }
-    }
-    pub fn fneg(&self, v: ValueRef) -> ValueRef {
+    pub fn fneg(&self, v: &'ll Value) -> &'ll Value {
         self.count_insn("fneg");
         unsafe {
             llvm::LLVMBuildFNeg(self.llbuilder, v, noname())
         }
     }
 
-    pub fn not(&self, v: ValueRef) -> ValueRef {
+    pub fn not(&self, v: &'ll Value) -> &'ll Value {
         self.count_insn("not");
         unsafe {
             llvm::LLVMBuildNot(self.llbuilder, v, noname())
         }
     }
 
-    pub fn alloca(&self, ty: Type, name: &str, align: Align) -> ValueRef {
+    pub fn alloca(&self, ty: &'ll Type, name: &str, align: Align) -> &'ll Value {
         let bx = Builder::with_cx(self.cx);
         bx.position_at_start(unsafe {
             llvm::LLVMGetFirstBasicBlock(self.llfn())
@@ -511,14 +430,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         bx.dynamic_alloca(ty, name, align)
     }
 
-    pub fn dynamic_alloca(&self, ty: Type, name: &str, align: Align) -> ValueRef {
+    pub fn dynamic_alloca(&self, ty: &'ll Type, name: &str, align: Align) -> &'ll Value {
         self.count_insn("alloca");
         unsafe {
             let alloca = if name.is_empty() {
-                llvm::LLVMBuildAlloca(self.llbuilder, ty.to_ref(), noname())
+                llvm::LLVMBuildAlloca(self.llbuilder, ty, noname())
             } else {
                 let name = CString::new(name).unwrap();
-                llvm::LLVMBuildAlloca(self.llbuilder, ty.to_ref(),
+                llvm::LLVMBuildAlloca(self.llbuilder, ty,
                                       name.as_ptr())
             };
             llvm::LLVMSetAlignment(alloca, align.abi() as c_uint);
@@ -526,14 +445,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         }
     }
 
-    pub fn free(&self, ptr: ValueRef) {
-        self.count_insn("free");
-        unsafe {
-            llvm::LLVMBuildFree(self.llbuilder, ptr);
-        }
-    }
-
-    pub fn load(&self, ptr: ValueRef, align: Align) -> ValueRef {
+    pub fn load(&self, ptr: &'ll Value, align: Align) -> &'ll Value {
         self.count_insn("load");
         unsafe {
             let load = llvm::LLVMBuildLoad(self.llbuilder, ptr, noname());
@@ -542,7 +454,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         }
     }
 
-    pub fn volatile_load(&self, ptr: ValueRef) -> ValueRef {
+    pub fn volatile_load(&self, ptr: &'ll Value) -> &'ll Value {
         self.count_insn("load.volatile");
         unsafe {
             let insn = llvm::LLVMBuildLoad(self.llbuilder, ptr, noname());
@@ -551,7 +463,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         }
     }
 
-    pub fn atomic_load(&self, ptr: ValueRef, order: AtomicOrdering, align: Align) -> ValueRef {
+    pub fn atomic_load(&self, ptr: &'ll Value, order: AtomicOrdering, align: Align) -> &'ll Value {
         self.count_insn("load.atomic");
         unsafe {
             let load = llvm::LLVMRustBuildAtomicLoad(self.llbuilder, ptr, noname(), order);
@@ -564,7 +476,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     }
 
 
-    pub fn range_metadata(&self, load: ValueRef, range: Range<u128>) {
+    pub fn range_metadata(&self, load: &'ll Value, range: Range<u128>) {
         unsafe {
             let llty = val_ty(load);
             let v = [
@@ -579,26 +491,25 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         }
     }
 
-    pub fn nonnull_metadata(&self, load: ValueRef) {
+    pub fn nonnull_metadata(&self, load: &'ll Value) {
         unsafe {
             llvm::LLVMSetMetadata(load, llvm::MD_nonnull as c_uint,
                                   llvm::LLVMMDNodeInContext(self.cx.llcx, ptr::null(), 0));
         }
     }
 
-    pub fn store(&self, val: ValueRef, ptr: ValueRef, align: Align) -> ValueRef {
+    pub fn store(&self, val: &'ll Value, ptr: &'ll Value, align: Align) -> &'ll Value {
         self.store_with_flags(val, ptr, align, MemFlags::empty())
     }
 
     pub fn store_with_flags(
         &self,
-        val: ValueRef,
-        ptr: ValueRef,
+        val: &'ll Value,
+        ptr: &'ll Value,
         align: Align,
         flags: MemFlags,
-    ) -> ValueRef {
-        debug!("Store {:?} -> {:?} ({:?})", Value(val), Value(ptr), flags);
-        assert!(!self.llbuilder.is_null());
+    ) -> &'ll Value {
+        debug!("Store {:?} -> {:?} ({:?})", val, ptr, flags);
         self.count_insn("store");
         let ptr = self.check_store(val, ptr);
         unsafe {
@@ -625,9 +536,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         }
     }
 
-    pub fn atomic_store(&self, val: ValueRef, ptr: ValueRef,
+    pub fn atomic_store(&self, val: &'ll Value, ptr: &'ll Value,
                         order: AtomicOrdering, align: Align) {
-        debug!("Store {:?} -> {:?}", Value(val), Value(ptr));
+        debug!("Store {:?} -> {:?}", val, ptr);
         self.count_insn("store.atomic");
         let ptr = self.check_store(val, ptr);
         unsafe {
@@ -638,7 +549,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         }
     }
 
-    pub fn gep(&self, ptr: ValueRef, indices: &[ValueRef]) -> ValueRef {
+    pub fn gep(&self, ptr: &'ll Value, indices: &[&'ll Value]) -> &'ll Value {
         self.count_insn("gep");
         unsafe {
             llvm::LLVMBuildGEP(self.llbuilder, ptr, indices.as_ptr(),
@@ -646,7 +557,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         }
     }
 
-    pub fn inbounds_gep(&self, ptr: ValueRef, indices: &[ValueRef]) -> ValueRef {
+    pub fn inbounds_gep(&self, ptr: &'ll Value, indices: &[&'ll Value]) -> &'ll Value {
         self.count_insn("inboundsgep");
         unsafe {
             llvm::LLVMBuildInBoundsGEP(
@@ -654,7 +565,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         }
     }
 
-    pub fn struct_gep(&self, ptr: ValueRef, idx: u64) -> ValueRef {
+    pub fn struct_gep(&self, ptr: &'ll Value, idx: u64) -> &'ll Value {
         self.count_insn("structgep");
         assert_eq!(idx as c_uint as u64, idx);
         unsafe {
@@ -662,164 +573,114 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         }
     }
 
-    pub fn global_string(&self, _str: *const c_char) -> ValueRef {
-        self.count_insn("globalstring");
-        unsafe {
-            llvm::LLVMBuildGlobalString(self.llbuilder, _str, noname())
-        }
-    }
-
-    pub fn global_string_ptr(&self, _str: *const c_char) -> ValueRef {
-        self.count_insn("globalstringptr");
-        unsafe {
-            llvm::LLVMBuildGlobalStringPtr(self.llbuilder, _str, noname())
-        }
-    }
-
     /* Casts */
-    pub fn trunc(&self, val: ValueRef, dest_ty: Type) -> ValueRef {
+    pub fn trunc(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
         self.count_insn("trunc");
         unsafe {
-            llvm::LLVMBuildTrunc(self.llbuilder, val, dest_ty.to_ref(), noname())
+            llvm::LLVMBuildTrunc(self.llbuilder, val, dest_ty, noname())
         }
     }
 
-    pub fn zext(&self, val: ValueRef, dest_ty: Type) -> ValueRef {
+    pub fn zext(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
         self.count_insn("zext");
         unsafe {
-            llvm::LLVMBuildZExt(self.llbuilder, val, dest_ty.to_ref(), noname())
+            llvm::LLVMBuildZExt(self.llbuilder, val, dest_ty, noname())
         }
     }
 
-    pub fn sext(&self, val: ValueRef, dest_ty: Type) -> ValueRef {
+    pub fn sext(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
         self.count_insn("sext");
         unsafe {
-            llvm::LLVMBuildSExt(self.llbuilder, val, dest_ty.to_ref(), noname())
+            llvm::LLVMBuildSExt(self.llbuilder, val, dest_ty, noname())
         }
     }
 
-    pub fn fptoui(&self, val: ValueRef, dest_ty: Type) -> ValueRef {
+    pub fn fptoui(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
         self.count_insn("fptoui");
         unsafe {
-            llvm::LLVMBuildFPToUI(self.llbuilder, val, dest_ty.to_ref(), noname())
+            llvm::LLVMBuildFPToUI(self.llbuilder, val, dest_ty, noname())
         }
     }
 
-    pub fn fptosi(&self, val: ValueRef, dest_ty: Type) -> ValueRef {
+    pub fn fptosi(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
         self.count_insn("fptosi");
         unsafe {
-            llvm::LLVMBuildFPToSI(self.llbuilder, val, dest_ty.to_ref(),noname())
+            llvm::LLVMBuildFPToSI(self.llbuilder, val, dest_ty,noname())
         }
     }
 
-    pub fn uitofp(&self, val: ValueRef, dest_ty: Type) -> ValueRef {
+    pub fn uitofp(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
         self.count_insn("uitofp");
         unsafe {
-            llvm::LLVMBuildUIToFP(self.llbuilder, val, dest_ty.to_ref(), noname())
+            llvm::LLVMBuildUIToFP(self.llbuilder, val, dest_ty, noname())
         }
     }
 
-    pub fn sitofp(&self, val: ValueRef, dest_ty: Type) -> ValueRef {
+    pub fn sitofp(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
         self.count_insn("sitofp");
         unsafe {
-            llvm::LLVMBuildSIToFP(self.llbuilder, val, dest_ty.to_ref(), noname())
+            llvm::LLVMBuildSIToFP(self.llbuilder, val, dest_ty, noname())
         }
     }
 
-    pub fn fptrunc(&self, val: ValueRef, dest_ty: Type) -> ValueRef {
+    pub fn fptrunc(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
         self.count_insn("fptrunc");
         unsafe {
-            llvm::LLVMBuildFPTrunc(self.llbuilder, val, dest_ty.to_ref(), noname())
+            llvm::LLVMBuildFPTrunc(self.llbuilder, val, dest_ty, noname())
         }
     }
 
-    pub fn fpext(&self, val: ValueRef, dest_ty: Type) -> ValueRef {
+    pub fn fpext(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
         self.count_insn("fpext");
         unsafe {
-            llvm::LLVMBuildFPExt(self.llbuilder, val, dest_ty.to_ref(), noname())
+            llvm::LLVMBuildFPExt(self.llbuilder, val, dest_ty, noname())
         }
     }
 
-    pub fn ptrtoint(&self, val: ValueRef, dest_ty: Type) -> ValueRef {
+    pub fn ptrtoint(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
         self.count_insn("ptrtoint");
         unsafe {
-            llvm::LLVMBuildPtrToInt(self.llbuilder, val, dest_ty.to_ref(), noname())
+            llvm::LLVMBuildPtrToInt(self.llbuilder, val, dest_ty, noname())
         }
     }
 
-    pub fn inttoptr(&self, val: ValueRef, dest_ty: Type) -> ValueRef {
+    pub fn inttoptr(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
         self.count_insn("inttoptr");
         unsafe {
-            llvm::LLVMBuildIntToPtr(self.llbuilder, val, dest_ty.to_ref(), noname())
+            llvm::LLVMBuildIntToPtr(self.llbuilder, val, dest_ty, noname())
         }
     }
 
-    pub fn bitcast(&self, val: ValueRef, dest_ty: Type) -> ValueRef {
+    pub fn bitcast(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
         self.count_insn("bitcast");
         unsafe {
-            llvm::LLVMBuildBitCast(self.llbuilder, val, dest_ty.to_ref(), noname())
-        }
-    }
-
-    pub fn zext_or_bitcast(&self, val: ValueRef, dest_ty: Type) -> ValueRef {
-        self.count_insn("zextorbitcast");
-        unsafe {
-            llvm::LLVMBuildZExtOrBitCast(self.llbuilder, val, dest_ty.to_ref(), noname())
+            llvm::LLVMBuildBitCast(self.llbuilder, val, dest_ty, noname())
         }
     }
 
-    pub fn sext_or_bitcast(&self, val: ValueRef, dest_ty: Type) -> ValueRef {
-        self.count_insn("sextorbitcast");
-        unsafe {
-            llvm::LLVMBuildSExtOrBitCast(self.llbuilder, val, dest_ty.to_ref(), noname())
-        }
-    }
-
-    pub fn trunc_or_bitcast(&self, val: ValueRef, dest_ty: Type) -> ValueRef {
-        self.count_insn("truncorbitcast");
-        unsafe {
-            llvm::LLVMBuildTruncOrBitCast(self.llbuilder, val, dest_ty.to_ref(), noname())
-        }
-    }
-
-    pub fn cast(&self, op: Opcode, val: ValueRef, dest_ty: Type) -> ValueRef {
-        self.count_insn("cast");
-        unsafe {
-            llvm::LLVMBuildCast(self.llbuilder, op, val, dest_ty.to_ref(), noname())
-        }
-    }
-
-    pub fn pointercast(&self, val: ValueRef, dest_ty: Type) -> ValueRef {
+    pub fn pointercast(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
         self.count_insn("pointercast");
         unsafe {
-            llvm::LLVMBuildPointerCast(self.llbuilder, val, dest_ty.to_ref(), noname())
+            llvm::LLVMBuildPointerCast(self.llbuilder, val, dest_ty, noname())
         }
     }
 
-    pub fn intcast(&self, val: ValueRef, dest_ty: Type, is_signed: bool) -> ValueRef {
+    pub fn intcast(&self, val: &'ll Value, dest_ty: &'ll Type, is_signed: bool) -> &'ll Value {
         self.count_insn("intcast");
         unsafe {
-            llvm::LLVMRustBuildIntCast(self.llbuilder, val, dest_ty.to_ref(), is_signed)
-        }
-    }
-
-    pub fn fpcast(&self, val: ValueRef, dest_ty: Type) -> ValueRef {
-        self.count_insn("fpcast");
-        unsafe {
-            llvm::LLVMBuildFPCast(self.llbuilder, val, dest_ty.to_ref(), noname())
+            llvm::LLVMRustBuildIntCast(self.llbuilder, val, dest_ty, is_signed)
         }
     }
 
-
     /* Comparisons */
-    pub fn icmp(&self, op: IntPredicate, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
+    pub fn icmp(&self, op: IntPredicate, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
         self.count_insn("icmp");
         unsafe {
             llvm::LLVMBuildICmp(self.llbuilder, op as c_uint, lhs, rhs, noname())
         }
     }
 
-    pub fn fcmp(&self, op: RealPredicate, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
+    pub fn fcmp(&self, op: RealPredicate, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
         self.count_insn("fcmp");
         unsafe {
             llvm::LLVMBuildFCmp(self.llbuilder, op as c_uint, lhs, rhs, noname())
@@ -827,14 +688,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     }
 
     /* Miscellaneous instructions */
-    pub fn empty_phi(&self, ty: Type) -> ValueRef {
+    pub fn empty_phi(&self, ty: &'ll Type) -> &'ll Value {
         self.count_insn("emptyphi");
         unsafe {
-            llvm::LLVMBuildPhi(self.llbuilder, ty.to_ref(), noname())
+            llvm::LLVMBuildPhi(self.llbuilder, ty, noname())
         }
     }
 
-    pub fn phi(&self, ty: Type, vals: &[ValueRef], bbs: &[BasicBlockRef]) -> ValueRef {
+    pub fn phi(&self, ty: &'ll Type, vals: &[&'ll Value], bbs: &[&'ll BasicBlock]) -> &'ll Value {
         assert_eq!(vals.len(), bbs.len());
         let phi = self.empty_phi(ty);
         self.count_insn("addincoming");
@@ -846,36 +707,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         }
     }
 
-    pub fn add_span_comment(&self, sp: Span, text: &str) {
-        if self.cx.sess().asm_comments() {
-            let s = format!("{} ({})",
-                            text,
-                            self.cx.sess().codemap().span_to_string(sp));
-            debug!("{}", s);
-            self.add_comment(&s);
-        }
-    }
-
-    pub fn add_comment(&self, text: &str) {
-        if self.cx.sess().asm_comments() {
-            let sanitized = text.replace("$", "");
-            let comment_text = format!("{} {}", "#",
-                                       sanitized.replace("\n", "\n\t# "));
-            self.count_insn("inlineasm");
-            let comment_text = CString::new(comment_text).unwrap();
-            let asm = unsafe {
-                llvm::LLVMConstInlineAsm(Type::func(&[], &Type::void(self.cx)).to_ref(),
-                                         comment_text.as_ptr(), noname(), False,
-                                         False)
-            };
-            self.call(asm, &[], None);
-        }
-    }
-
     pub fn inline_asm_call(&self, asm: *const c_char, cons: *const c_char,
-                         inputs: &[ValueRef], output: Type,
+                         inputs: &[&'ll Value], output: &'ll Type,
                          volatile: bool, alignstack: bool,
-                         dia: AsmDialect) -> ValueRef {
+                         dia: AsmDialect) -> &'ll Value {
         self.count_insn("inlineasm");
 
         let volatile = if volatile { llvm::True }
@@ -884,32 +719,29 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                          else          { llvm::False };
 
         let argtys = inputs.iter().map(|v| {
-            debug!("Asm Input Type: {:?}", Value(*v));
+            debug!("Asm Input Type: {:?}", *v);
             val_ty(*v)
         }).collect::<Vec<_>>();
 
         debug!("Asm Output Type: {:?}", output);
-        let fty = Type::func(&argtys[..], &output);
+        let fty = Type::func(&argtys[..], output);
         unsafe {
             let v = llvm::LLVMRustInlineAsm(
-                fty.to_ref(), asm, cons, volatile, alignstack, dia);
+                fty, asm, cons, volatile, alignstack, dia);
             self.call(v, inputs, None)
         }
     }
 
-    pub fn call(&self, llfn: ValueRef, args: &[ValueRef],
-                bundle: Option<&OperandBundleDef>) -> ValueRef {
+    pub fn call(&self, llfn: &'ll Value, args: &[&'ll Value],
+                bundle: Option<&OperandBundleDef<'ll>>) -> &'ll Value {
         self.count_insn("call");
 
-        debug!("Call {:?} with args ({})",
-               Value(llfn),
-               args.iter()
-                   .map(|&v| format!("{:?}", Value(v)))
-                   .collect::<Vec<String>>()
-                   .join(", "));
+        debug!("Call {:?} with args ({:?})",
+               llfn,
+               args);
 
         let args = self.check_call("call", llfn, args);
-        let bundle = bundle.as_ref().map(|b| b.raw()).unwrap_or(ptr::null_mut());
+        let bundle = bundle.map(|b| &*b.raw);
 
         unsafe {
             llvm::LLVMRustBuildCall(self.llbuilder, llfn, args.as_ptr(),
@@ -917,214 +749,182 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         }
     }
 
-    pub fn minnum(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
+    pub fn minnum(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
         self.count_insn("minnum");
         unsafe {
             let instr = llvm::LLVMRustBuildMinNum(self.llbuilder, lhs, rhs);
-            if instr.is_null() {
-                bug!("LLVMRustBuildMinNum is not available in LLVM version < 6.0");
-            }
-            instr
+            instr.expect("LLVMRustBuildMinNum is not available in LLVM version < 6.0")
         }
     }
-    pub fn maxnum(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
+    pub fn maxnum(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
         self.count_insn("maxnum");
         unsafe {
             let instr = llvm::LLVMRustBuildMaxNum(self.llbuilder, lhs, rhs);
-            if instr.is_null() {
-                bug!("LLVMRustBuildMaxNum is not available in LLVM version < 6.0");
-            }
-            instr
+            instr.expect("LLVMRustBuildMaxNum is not available in LLVM version < 6.0")
         }
     }
 
-    pub fn select(&self, cond: ValueRef, then_val: ValueRef, else_val: ValueRef) -> ValueRef {
+    pub fn select(
+        &self, cond: &'ll Value,
+        then_val: &'ll Value,
+        else_val: &'ll Value,
+    ) -> &'ll Value {
         self.count_insn("select");
         unsafe {
             llvm::LLVMBuildSelect(self.llbuilder, cond, then_val, else_val, noname())
         }
     }
 
-    pub fn va_arg(&self, list: ValueRef, ty: Type) -> ValueRef {
+    #[allow(dead_code)]
+    pub fn va_arg(&self, list: &'ll Value, ty: &'ll Type) -> &'ll Value {
         self.count_insn("vaarg");
         unsafe {
-            llvm::LLVMBuildVAArg(self.llbuilder, list, ty.to_ref(), noname())
+            llvm::LLVMBuildVAArg(self.llbuilder, list, ty, noname())
         }
     }
 
-    pub fn extract_element(&self, vec: ValueRef, idx: ValueRef) -> ValueRef {
+    pub fn extract_element(&self, vec: &'ll Value, idx: &'ll Value) -> &'ll Value {
         self.count_insn("extractelement");
         unsafe {
             llvm::LLVMBuildExtractElement(self.llbuilder, vec, idx, noname())
         }
     }
 
-    pub fn insert_element(&self, vec: ValueRef, elt: ValueRef, idx: ValueRef) -> ValueRef {
+    pub fn insert_element(
+        &self, vec: &'ll Value,
+        elt: &'ll Value,
+        idx: &'ll Value,
+    ) -> &'ll Value {
         self.count_insn("insertelement");
         unsafe {
             llvm::LLVMBuildInsertElement(self.llbuilder, vec, elt, idx, noname())
         }
     }
 
-    pub fn shuffle_vector(&self, v1: ValueRef, v2: ValueRef, mask: ValueRef) -> ValueRef {
+    pub fn shuffle_vector(&self, v1: &'ll Value, v2: &'ll Value, mask: &'ll Value) -> &'ll Value {
         self.count_insn("shufflevector");
         unsafe {
             llvm::LLVMBuildShuffleVector(self.llbuilder, v1, v2, mask, noname())
         }
     }
 
-    pub fn vector_splat(&self, num_elts: usize, elt: ValueRef) -> ValueRef {
+    pub fn vector_splat(&self, num_elts: usize, elt: &'ll Value) -> &'ll Value {
         unsafe {
             let elt_ty = val_ty(elt);
-            let undef = llvm::LLVMGetUndef(Type::vector(&elt_ty, num_elts as u64).to_ref());
+            let undef = llvm::LLVMGetUndef(Type::vector(elt_ty, num_elts as u64));
             let vec = self.insert_element(undef, elt, C_i32(self.cx, 0));
-            let vec_i32_ty = Type::vector(&Type::i32(self.cx), num_elts as u64);
+            let vec_i32_ty = Type::vector(Type::i32(self.cx), num_elts as u64);
             self.shuffle_vector(vec, undef, C_null(vec_i32_ty))
         }
     }
 
-    pub fn vector_reduce_fadd_fast(&self, acc: ValueRef, src: ValueRef) -> ValueRef {
+    pub fn vector_reduce_fadd_fast(&self, acc: &'ll Value, src: &'ll Value) -> &'ll Value {
         self.count_insn("vector.reduce.fadd_fast");
         unsafe {
             // FIXME: add a non-fast math version once
             // https://bugs.llvm.org/show_bug.cgi?id=36732
             // is fixed.
-            let instr = llvm::LLVMRustBuildVectorReduceFAdd(self.llbuilder, acc, src);
-            if instr.is_null() {
-                bug!("LLVMRustBuildVectorReduceFAdd is not available in LLVM version < 5.0");
-            }
+            let instr = llvm::LLVMRustBuildVectorReduceFAdd(self.llbuilder, acc, src)
+                .expect("LLVMRustBuildVectorReduceFAdd is not available in LLVM version < 5.0");
             llvm::LLVMRustSetHasUnsafeAlgebra(instr);
             instr
         }
     }
-    pub fn vector_reduce_fmul_fast(&self, acc: ValueRef, src: ValueRef) -> ValueRef {
+    pub fn vector_reduce_fmul_fast(&self, acc: &'ll Value, src: &'ll Value) -> &'ll Value {
         self.count_insn("vector.reduce.fmul_fast");
         unsafe {
             // FIXME: add a non-fast math version once
             // https://bugs.llvm.org/show_bug.cgi?id=36732
             // is fixed.
-            let instr = llvm::LLVMRustBuildVectorReduceFMul(self.llbuilder, acc, src);
-            if instr.is_null() {
-                bug!("LLVMRustBuildVectorReduceFMul is not available in LLVM version < 5.0");
-            }
+            let instr = llvm::LLVMRustBuildVectorReduceFMul(self.llbuilder, acc, src)
+                .expect("LLVMRustBuildVectorReduceFMul is not available in LLVM version < 5.0");
             llvm::LLVMRustSetHasUnsafeAlgebra(instr);
             instr
         }
     }
-    pub fn vector_reduce_add(&self, src: ValueRef) -> ValueRef {
+    pub fn vector_reduce_add(&self, src: &'ll Value) -> &'ll Value {
         self.count_insn("vector.reduce.add");
         unsafe {
             let instr = llvm::LLVMRustBuildVectorReduceAdd(self.llbuilder, src);
-            if instr.is_null() {
-                bug!("LLVMRustBuildVectorReduceAdd is not available in LLVM version < 5.0");
-            }
-            instr
+            instr.expect("LLVMRustBuildVectorReduceAdd is not available in LLVM version < 5.0")
         }
     }
-    pub fn vector_reduce_mul(&self, src: ValueRef) -> ValueRef {
+    pub fn vector_reduce_mul(&self, src: &'ll Value) -> &'ll Value {
         self.count_insn("vector.reduce.mul");
         unsafe {
             let instr = llvm::LLVMRustBuildVectorReduceMul(self.llbuilder, src);
-            if instr.is_null() {
-                bug!("LLVMRustBuildVectorReduceMul is not available in LLVM version < 5.0");
-            }
-            instr
+            instr.expect("LLVMRustBuildVectorReduceMul is not available in LLVM version < 5.0")
         }
     }
-    pub fn vector_reduce_and(&self, src: ValueRef) -> ValueRef {
+    pub fn vector_reduce_and(&self, src: &'ll Value) -> &'ll Value {
         self.count_insn("vector.reduce.and");
         unsafe {
             let instr = llvm::LLVMRustBuildVectorReduceAnd(self.llbuilder, src);
-            if instr.is_null() {
-                bug!("LLVMRustBuildVectorReduceAnd is not available in LLVM version < 5.0");
-            }
-            instr
+            instr.expect("LLVMRustBuildVectorReduceAnd is not available in LLVM version < 5.0")
         }
     }
-    pub fn vector_reduce_or(&self, src: ValueRef) -> ValueRef {
+    pub fn vector_reduce_or(&self, src: &'ll Value) -> &'ll Value {
         self.count_insn("vector.reduce.or");
         unsafe {
             let instr = llvm::LLVMRustBuildVectorReduceOr(self.llbuilder, src);
-            if instr.is_null() {
-                bug!("LLVMRustBuildVectorReduceOr is not available in LLVM version < 5.0");
-            }
-            instr
+            instr.expect("LLVMRustBuildVectorReduceOr is not available in LLVM version < 5.0")
         }
     }
-    pub fn vector_reduce_xor(&self, src: ValueRef) -> ValueRef {
+    pub fn vector_reduce_xor(&self, src: &'ll Value) -> &'ll Value {
         self.count_insn("vector.reduce.xor");
         unsafe {
             let instr = llvm::LLVMRustBuildVectorReduceXor(self.llbuilder, src);
-            if instr.is_null() {
-                bug!("LLVMRustBuildVectorReduceXor is not available in LLVM version < 5.0");
-            }
-            instr
+            instr.expect("LLVMRustBuildVectorReduceXor is not available in LLVM version < 5.0")
         }
     }
-    pub fn vector_reduce_fmin(&self, src: ValueRef) -> ValueRef {
+    pub fn vector_reduce_fmin(&self, src: &'ll Value) -> &'ll Value {
         self.count_insn("vector.reduce.fmin");
         unsafe {
             let instr = llvm::LLVMRustBuildVectorReduceFMin(self.llbuilder, src, /*NoNaNs:*/ false);
-            if instr.is_null() {
-                bug!("LLVMRustBuildVectorReduceFMin is not available in LLVM version < 5.0");
-            }
-            instr
+            instr.expect("LLVMRustBuildVectorReduceFMin is not available in LLVM version < 5.0")
         }
     }
-    pub fn vector_reduce_fmax(&self, src: ValueRef) -> ValueRef {
+    pub fn vector_reduce_fmax(&self, src: &'ll Value) -> &'ll Value {
         self.count_insn("vector.reduce.fmax");
         unsafe {
             let instr = llvm::LLVMRustBuildVectorReduceFMax(self.llbuilder, src, /*NoNaNs:*/ false);
-            if instr.is_null() {
-                bug!("LLVMRustBuildVectorReduceFMax is not available in LLVM version < 5.0");
-            }
-            instr
+            instr.expect("LLVMRustBuildVectorReduceFMax is not available in LLVM version < 5.0")
         }
     }
-    pub fn vector_reduce_fmin_fast(&self, src: ValueRef) -> ValueRef {
+    pub fn vector_reduce_fmin_fast(&self, src: &'ll Value) -> &'ll Value {
         self.count_insn("vector.reduce.fmin_fast");
         unsafe {
-            let instr = llvm::LLVMRustBuildVectorReduceFMin(self.llbuilder, src, /*NoNaNs:*/ true);
-            if instr.is_null() {
-                bug!("LLVMRustBuildVectorReduceFMin is not available in LLVM version < 5.0");
-            }
+            let instr = llvm::LLVMRustBuildVectorReduceFMin(self.llbuilder, src, /*NoNaNs:*/ true)
+                .expect("LLVMRustBuildVectorReduceFMin is not available in LLVM version < 5.0");
             llvm::LLVMRustSetHasUnsafeAlgebra(instr);
             instr
         }
     }
-    pub fn vector_reduce_fmax_fast(&self, src: ValueRef) -> ValueRef {
+    pub fn vector_reduce_fmax_fast(&self, src: &'ll Value) -> &'ll Value {
         self.count_insn("vector.reduce.fmax_fast");
         unsafe {
-            let instr = llvm::LLVMRustBuildVectorReduceFMax(self.llbuilder, src, /*NoNaNs:*/ true);
-            if instr.is_null() {
-                bug!("LLVMRustBuildVectorReduceFMax is not available in LLVM version < 5.0");
-            }
+            let instr = llvm::LLVMRustBuildVectorReduceFMax(self.llbuilder, src, /*NoNaNs:*/ true)
+                .expect("LLVMRustBuildVectorReduceFMax is not available in LLVM version < 5.0");
             llvm::LLVMRustSetHasUnsafeAlgebra(instr);
             instr
         }
     }
-    pub fn vector_reduce_min(&self, src: ValueRef, is_signed: bool) -> ValueRef {
+    pub fn vector_reduce_min(&self, src: &'ll Value, is_signed: bool) -> &'ll Value {
         self.count_insn("vector.reduce.min");
         unsafe {
             let instr = llvm::LLVMRustBuildVectorReduceMin(self.llbuilder, src, is_signed);
-            if instr.is_null() {
-                bug!("LLVMRustBuildVectorReduceMin is not available in LLVM version < 5.0");
-            }
-            instr
+            instr.expect("LLVMRustBuildVectorReduceMin is not available in LLVM version < 5.0")
         }
     }
-    pub fn vector_reduce_max(&self, src: ValueRef, is_signed: bool) -> ValueRef {
+    pub fn vector_reduce_max(&self, src: &'ll Value, is_signed: bool) -> &'ll Value {
         self.count_insn("vector.reduce.max");
         unsafe {
             let instr = llvm::LLVMRustBuildVectorReduceMax(self.llbuilder, src, is_signed);
-            if instr.is_null() {
-                bug!("LLVMRustBuildVectorReduceMax is not available in LLVM version < 5.0");
-            }
-            instr
+            instr.expect("LLVMRustBuildVectorReduceMax is not available in LLVM version < 5.0")
         }
     }
 
-    pub fn extract_value(&self, agg_val: ValueRef, idx: u64) -> ValueRef {
+    pub fn extract_value(&self, agg_val: &'ll Value, idx: u64) -> &'ll Value {
         self.count_insn("extractvalue");
         assert_eq!(idx as c_uint as u64, idx);
         unsafe {
@@ -1132,8 +932,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         }
     }
 
-    pub fn insert_value(&self, agg_val: ValueRef, elt: ValueRef,
-                       idx: u64) -> ValueRef {
+    pub fn insert_value(&self, agg_val: &'ll Value, elt: &'ll Value,
+                       idx: u64) -> &'ll Value {
         self.count_insn("insertvalue");
         assert_eq!(idx as c_uint as u64, idx);
         unsafe {
@@ -1142,50 +942,29 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         }
     }
 
-    pub fn is_null(&self, val: ValueRef) -> ValueRef {
-        self.count_insn("isnull");
-        unsafe {
-            llvm::LLVMBuildIsNull(self.llbuilder, val, noname())
-        }
-    }
-
-    pub fn is_not_null(&self, val: ValueRef) -> ValueRef {
-        self.count_insn("isnotnull");
-        unsafe {
-            llvm::LLVMBuildIsNotNull(self.llbuilder, val, noname())
-        }
-    }
-
-    pub fn ptrdiff(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
-        self.count_insn("ptrdiff");
-        unsafe {
-            llvm::LLVMBuildPtrDiff(self.llbuilder, lhs, rhs, noname())
-        }
-    }
-
-    pub fn landing_pad(&self, ty: Type, pers_fn: ValueRef,
-                       num_clauses: usize) -> ValueRef {
+    pub fn landing_pad(&self, ty: &'ll Type, pers_fn: &'ll Value,
+                       num_clauses: usize) -> &'ll Value {
         self.count_insn("landingpad");
         unsafe {
-            llvm::LLVMBuildLandingPad(self.llbuilder, ty.to_ref(), pers_fn,
+            llvm::LLVMBuildLandingPad(self.llbuilder, ty, pers_fn,
                                       num_clauses as c_uint, noname())
         }
     }
 
-    pub fn add_clause(&self, landing_pad: ValueRef, clause: ValueRef) {
+    pub fn add_clause(&self, landing_pad: &'ll Value, clause: &'ll Value) {
         unsafe {
             llvm::LLVMAddClause(landing_pad, clause);
         }
     }
 
-    pub fn set_cleanup(&self, landing_pad: ValueRef) {
+    pub fn set_cleanup(&self, landing_pad: &'ll Value) {
         self.count_insn("setcleanup");
         unsafe {
             llvm::LLVMSetCleanup(landing_pad, llvm::True);
         }
     }
 
-    pub fn resume(&self, exn: ValueRef) -> ValueRef {
+    pub fn resume(&self, exn: &'ll Value) -> &'ll Value {
         self.count_insn("resume");
         unsafe {
             llvm::LLVMBuildResume(self.llbuilder, exn)
@@ -1193,10 +972,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     }
 
     pub fn cleanup_pad(&self,
-                       parent: Option<ValueRef>,
-                       args: &[ValueRef]) -> ValueRef {
+                       parent: Option<&'ll Value>,
+                       args: &[&'ll Value]) -> &'ll Value {
         self.count_insn("cleanuppad");
-        let parent = parent.unwrap_or(ptr::null_mut());
         let name = CString::new("cleanuppad").unwrap();
         let ret = unsafe {
             llvm::LLVMRustBuildCleanupPad(self.llbuilder,
@@ -1205,24 +983,23 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                                           args.as_ptr(),
                                           name.as_ptr())
         };
-        assert!(!ret.is_null(), "LLVM does not have support for cleanuppad");
-        return ret
+        ret.expect("LLVM does not have support for cleanuppad")
     }
 
-    pub fn cleanup_ret(&self, cleanup: ValueRef,
-                       unwind: Option<BasicBlockRef>) -> ValueRef {
+    pub fn cleanup_ret(
+        &self, cleanup: &'ll Value,
+        unwind: Option<&'ll BasicBlock>,
+    ) -> &'ll Value {
         self.count_insn("cleanupret");
-        let unwind = unwind.unwrap_or(ptr::null_mut());
         let ret = unsafe {
             llvm::LLVMRustBuildCleanupRet(self.llbuilder, cleanup, unwind)
         };
-        assert!(!ret.is_null(), "LLVM does not have support for cleanupret");
-        return ret
+        ret.expect("LLVM does not have support for cleanupret")
     }
 
     pub fn catch_pad(&self,
-                     parent: ValueRef,
-                     args: &[ValueRef]) -> ValueRef {
+                     parent: &'ll Value,
+                     args: &[&'ll Value]) -> &'ll Value {
         self.count_insn("catchpad");
         let name = CString::new("catchpad").unwrap();
         let ret = unsafe {
@@ -1230,62 +1007,67 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                                         args.len() as c_uint, args.as_ptr(),
                                         name.as_ptr())
         };
-        assert!(!ret.is_null(), "LLVM does not have support for catchpad");
-        return ret
+        ret.expect("LLVM does not have support for catchpad")
     }
 
-    pub fn catch_ret(&self, pad: ValueRef, unwind: BasicBlockRef) -> ValueRef {
+    pub fn catch_ret(&self, pad: &'ll Value, unwind: &'ll BasicBlock) -> &'ll Value {
         self.count_insn("catchret");
         let ret = unsafe {
             llvm::LLVMRustBuildCatchRet(self.llbuilder, pad, unwind)
         };
-        assert!(!ret.is_null(), "LLVM does not have support for catchret");
-        return ret
+        ret.expect("LLVM does not have support for catchret")
     }
 
-    pub fn catch_switch(&self,
-                        parent: Option<ValueRef>,
-                        unwind: Option<BasicBlockRef>,
-                        num_handlers: usize) -> ValueRef {
+    pub fn catch_switch(
+        &self,
+        parent: Option<&'ll Value>,
+        unwind: Option<&'ll BasicBlock>,
+        num_handlers: usize,
+    ) -> &'ll Value {
         self.count_insn("catchswitch");
-        let parent = parent.unwrap_or(ptr::null_mut());
-        let unwind = unwind.unwrap_or(ptr::null_mut());
         let name = CString::new("catchswitch").unwrap();
         let ret = unsafe {
             llvm::LLVMRustBuildCatchSwitch(self.llbuilder, parent, unwind,
                                            num_handlers as c_uint,
                                            name.as_ptr())
         };
-        assert!(!ret.is_null(), "LLVM does not have support for catchswitch");
-        return ret
+        ret.expect("LLVM does not have support for catchswitch")
     }
 
-    pub fn add_handler(&self, catch_switch: ValueRef, handler: BasicBlockRef) {
+    pub fn add_handler(&self, catch_switch: &'ll Value, handler: &'ll BasicBlock) {
         unsafe {
             llvm::LLVMRustAddHandler(catch_switch, handler);
         }
     }
 
-    pub fn set_personality_fn(&self, personality: ValueRef) {
+    pub fn set_personality_fn(&self, personality: &'ll Value) {
         unsafe {
             llvm::LLVMSetPersonalityFn(self.llfn(), personality);
         }
     }
 
     // Atomic Operations
-    pub fn atomic_cmpxchg(&self, dst: ValueRef,
-                         cmp: ValueRef, src: ValueRef,
-                         order: AtomicOrdering,
-                         failure_order: AtomicOrdering,
-                         weak: llvm::Bool) -> ValueRef {
+    pub fn atomic_cmpxchg(
+        &self,
+        dst: &'ll Value,
+        cmp: &'ll Value,
+        src: &'ll Value,
+        order: AtomicOrdering,
+        failure_order: AtomicOrdering,
+        weak: llvm::Bool,
+    ) -> &'ll Value {
         unsafe {
             llvm::LLVMRustBuildAtomicCmpXchg(self.llbuilder, dst, cmp, src,
                                          order, failure_order, weak)
         }
     }
-    pub fn atomic_rmw(&self, op: AtomicRmwBinOp,
-                     dst: ValueRef, src: ValueRef,
-                     order: AtomicOrdering) -> ValueRef {
+    pub fn atomic_rmw(
+        &self,
+        op: AtomicRmwBinOp,
+        dst: &'ll Value,
+        src: &'ll Value,
+        order: AtomicOrdering,
+    ) -> &'ll Value {
         unsafe {
             llvm::LLVMBuildAtomicRMW(self.llbuilder, op, dst, src, order, False)
         }
@@ -1297,20 +1079,20 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         }
     }
 
-    pub fn add_case(&self, s: ValueRef, on_val: ValueRef, dest: BasicBlockRef) {
+    pub fn add_case(&self, s: &'ll Value, on_val: &'ll Value, dest: &'ll BasicBlock) {
         unsafe {
             llvm::LLVMAddCase(s, on_val, dest)
         }
     }
 
-    pub fn add_incoming_to_phi(&self, phi: ValueRef, val: ValueRef, bb: BasicBlockRef) {
+    pub fn add_incoming_to_phi(&self, phi: &'ll Value, val: &'ll Value, bb: &'ll BasicBlock) {
         self.count_insn("addincoming");
         unsafe {
             llvm::LLVMAddIncoming(phi, &val, &bb, 1 as c_uint);
         }
     }
 
-    pub fn set_invariant_load(&self, load: ValueRef) {
+    pub fn set_invariant_load(&self, load: &'ll Value) {
         unsafe {
             llvm::LLVMSetMetadata(load, llvm::MD_invariant_load as c_uint,
                                   llvm::LLVMMDNodeInContext(self.cx.llcx, ptr::null(), 0));
@@ -1319,8 +1101,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
 
     /// Returns the ptr value that should be used for storing `val`.
     fn check_store<'b>(&self,
-                       val: ValueRef,
-                       ptr: ValueRef) -> ValueRef {
+                       val: &'ll Value,
+                       ptr: &'ll Value) -> &'ll Value {
         let dest_ptr_ty = val_ty(ptr);
         let stored_ty = val_ty(val);
         let stored_ptr_ty = stored_ty.ptr_to();
@@ -1340,8 +1122,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     /// Returns the args that should be used for a call to `llfn`.
     fn check_call<'b>(&self,
                       typ: &str,
-                      llfn: ValueRef,
-                      args: &'b [ValueRef]) -> Cow<'b, [ValueRef]> {
+                      llfn: &'ll Value,
+                      args: &'b [&'ll Value]) -> Cow<'b, [&'ll Value]> {
         let mut fn_ty = val_ty(llfn);
         // Strip off pointers
         while fn_ty.kind() == llvm::TypeKind::Pointer {
@@ -1369,8 +1151,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 if expected_ty != actual_ty {
                     debug!("Type mismatch in function call of {:?}. \
                             Expected {:?} for param {}, got {:?}; injecting bitcast",
-                           Value(llfn),
-                           expected_ty, i, actual_ty);
+                           llfn, expected_ty, i, actual_ty);
                     self.bitcast(actual_val, expected_ty)
                 } else {
                     actual_val
@@ -1381,11 +1162,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         return Cow::Owned(casted_args);
     }
 
-    pub fn lifetime_start(&self, ptr: ValueRef, size: Size) {
+    pub fn lifetime_start(&self, ptr: &'ll Value, size: Size) {
         self.call_lifetime_intrinsic("llvm.lifetime.start", ptr, size);
     }
 
-    pub fn lifetime_end(&self, ptr: ValueRef, size: Size) {
+    pub fn lifetime_end(&self, ptr: &'ll Value, size: Size) {
         self.call_lifetime_intrinsic("llvm.lifetime.end", ptr, size);
     }
 
@@ -1397,7 +1178,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     ///
     /// If LLVM lifetime intrinsic support is disabled (i.e.  optimizations
     /// off) or `ptr` is zero-sized, then no-op (does not call `emit`).
-    fn call_lifetime_intrinsic(&self, intrinsic: &str, ptr: ValueRef, size: Size) {
+    fn call_lifetime_intrinsic(&self, intrinsic: &str, ptr: &'ll Value, size: Size) {
         if self.cx.sess().opts.optimize == config::OptLevel::No {
             return;
         }
diff --git a/src/librustc_codegen_llvm/callee.rs b/src/librustc_codegen_llvm/callee.rs
index 2c01bd42cc7..e64dedac55a 100644
--- a/src/librustc_codegen_llvm/callee.rs
+++ b/src/librustc_codegen_llvm/callee.rs
@@ -18,9 +18,10 @@ use attributes;
 use common::{self, CodegenCx};
 use consts;
 use declare;
-use llvm::{self, ValueRef};
+use llvm;
 use monomorphize::Instance;
 use type_of::LayoutLlvmExt;
+use value::Value;
 
 use rustc::hir::def_id::DefId;
 use rustc::ty::{self, TypeFoldable};
@@ -34,10 +35,10 @@ use rustc::ty::subst::Substs;
 ///
 /// - `cx`: the crate context
 /// - `instance`: the instance to be instantiated
-pub fn get_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
-                        instance: Instance<'tcx>)
-                        -> ValueRef
-{
+pub fn get_fn(
+    cx: &CodegenCx<'ll, 'tcx>,
+    instance: Instance<'tcx>,
+) -> &'ll Value {
     let tcx = cx.tcx;
 
     debug!("get_fn(instance={:?})", instance);
@@ -204,11 +205,11 @@ pub fn get_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
     llfn
 }
 
-pub fn resolve_and_get_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
-                                    def_id: DefId,
-                                    substs: &'tcx Substs<'tcx>)
-                                    -> ValueRef
-{
+pub fn resolve_and_get_fn(
+    cx: &CodegenCx<'ll, 'tcx>,
+    def_id: DefId,
+    substs: &'tcx Substs<'tcx>,
+) -> &'ll Value {
     get_fn(
         cx,
         ty::Instance::resolve(
diff --git a/src/librustc_codegen_llvm/common.rs b/src/librustc_codegen_llvm/common.rs
index 60bba635a78..51fc610408b 100644
--- a/src/librustc_codegen_llvm/common.rs
+++ b/src/librustc_codegen_llvm/common.rs
@@ -12,8 +12,7 @@
 
 //! Code that is useful in various codegen modules.
 
-use llvm;
-use llvm::{ValueRef, ContextRef, TypeKind};
+use llvm::{self, TypeKind};
 use llvm::{True, False, Bool, OperandBundleDef};
 use rustc::hir::def_id::DefId;
 use rustc::middle::lang_items::LangItem;
@@ -25,6 +24,7 @@ use declare;
 use type_::Type;
 use type_of::LayoutLlvmExt;
 use value::Value;
+
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc::ty::layout::{HasDataLayout, LayoutOf};
 use rustc::hir;
@@ -90,83 +90,83 @@ pub fn type_is_freeze<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty: Ty<'tcx>) -> bo
 /// When inside of a landing pad, each function call in LLVM IR needs to be
 /// annotated with which landing pad it's a part of. This is accomplished via
 /// the `OperandBundleDef` value created for MSVC landing pads.
-pub struct Funclet {
-    cleanuppad: ValueRef,
-    operand: OperandBundleDef,
+pub struct Funclet<'ll> {
+    cleanuppad: &'ll Value,
+    operand: OperandBundleDef<'ll>,
 }
 
-impl Funclet {
-    pub fn new(cleanuppad: ValueRef) -> Funclet {
+impl Funclet<'ll> {
+    pub fn new(cleanuppad: &'ll Value) -> Self {
         Funclet {
             cleanuppad,
             operand: OperandBundleDef::new("funclet", &[cleanuppad]),
         }
     }
 
-    pub fn cleanuppad(&self) -> ValueRef {
+    pub fn cleanuppad(&self) -> &'ll Value {
         self.cleanuppad
     }
 
-    pub fn bundle(&self) -> &OperandBundleDef {
+    pub fn bundle(&self) -> &OperandBundleDef<'ll> {
         &self.operand
     }
 }
 
-pub fn val_ty(v: ValueRef) -> Type {
+pub fn val_ty(v: &'ll Value) -> &'ll Type {
     unsafe {
-        Type::from_ref(llvm::LLVMTypeOf(v))
+        llvm::LLVMTypeOf(v)
     }
 }
 
 // LLVM constant constructors.
-pub fn C_null(t: Type) -> ValueRef {
+pub fn C_null(t: &'ll Type) -> &'ll Value {
     unsafe {
-        llvm::LLVMConstNull(t.to_ref())
+        llvm::LLVMConstNull(t)
     }
 }
 
-pub fn C_undef(t: Type) -> ValueRef {
+pub fn C_undef(t: &'ll Type) -> &'ll Value {
     unsafe {
-        llvm::LLVMGetUndef(t.to_ref())
+        llvm::LLVMGetUndef(t)
     }
 }
 
-pub fn C_int(t: Type, i: i64) -> ValueRef {
+pub fn C_int(t: &'ll Type, i: i64) -> &'ll Value {
     unsafe {
-        llvm::LLVMConstInt(t.to_ref(), i as u64, True)
+        llvm::LLVMConstInt(t, i as u64, True)
     }
 }
 
-pub fn C_uint(t: Type, i: u64) -> ValueRef {
+pub fn C_uint(t: &'ll Type, i: u64) -> &'ll Value {
     unsafe {
-        llvm::LLVMConstInt(t.to_ref(), i, False)
+        llvm::LLVMConstInt(t, i, False)
     }
 }
 
-pub fn C_uint_big(t: Type, u: u128) -> ValueRef {
+pub fn C_uint_big(t: &'ll Type, u: u128) -> &'ll Value {
     unsafe {
         let words = [u as u64, (u >> 64) as u64];
-        llvm::LLVMConstIntOfArbitraryPrecision(t.to_ref(), 2, words.as_ptr())
+        llvm::LLVMConstIntOfArbitraryPrecision(t, 2, words.as_ptr())
     }
 }
 
-pub fn C_bool(cx: &CodegenCx, val: bool) -> ValueRef {
+pub fn C_bool(cx: &CodegenCx<'ll, '_>, val: bool) -> &'ll Value {
     C_uint(Type::i1(cx), val as u64)
 }
 
-pub fn C_i32(cx: &CodegenCx, i: i32) -> ValueRef {
+pub fn C_i32(cx: &CodegenCx<'ll, '_>, i: i32) -> &'ll Value {
     C_int(Type::i32(cx), i as i64)
 }
 
-pub fn C_u32(cx: &CodegenCx, i: u32) -> ValueRef {
+pub fn C_u32(cx: &CodegenCx<'ll, '_>, i: u32) -> &'ll Value {
     C_uint(Type::i32(cx), i as u64)
 }
 
-pub fn C_u64(cx: &CodegenCx, i: u64) -> ValueRef {
+pub fn C_u64(cx: &CodegenCx<'ll, '_>, i: u64) -> &'ll Value {
     C_uint(Type::i64(cx), i)
 }
 
-pub fn C_usize(cx: &CodegenCx, i: u64) -> ValueRef {
+pub fn C_usize(cx: &CodegenCx<'ll, '_>, i: u64) -> &'ll Value {
     let bit_size = cx.data_layout().pointer_size.bits();
     if bit_size < 64 {
         // make sure it doesn't overflow
@@ -176,14 +176,18 @@ pub fn C_usize(cx: &CodegenCx, i: u64) -> ValueRef {
     C_uint(cx.isize_ty, i)
 }
 
-pub fn C_u8(cx: &CodegenCx, i: u8) -> ValueRef {
+pub fn C_u8(cx: &CodegenCx<'ll, '_>, i: u8) -> &'ll Value {
     C_uint(Type::i8(cx), i as u64)
 }
 
 
 // This is a 'c-like' raw string, which differs from
 // our boxed-and-length-annotated strings.
-pub fn C_cstr(cx: &CodegenCx, s: LocalInternedString, null_terminated: bool) -> ValueRef {
+pub fn C_cstr(
+    cx: &CodegenCx<'ll, '_>,
+    s: LocalInternedString,
+    null_terminated: bool,
+) -> &'ll Value {
     unsafe {
         if let Some(&llval) = cx.const_cstr_cache.borrow().get(&s) {
             return llval;
@@ -208,24 +212,28 @@ pub fn C_cstr(cx: &CodegenCx, s: LocalInternedString, null_terminated: bool) ->
 
 // NB: Do not use `do_spill_noroot` to make this into a constant string, or
 // you will be kicked off fast isel. See issue #4352 for an example of this.
-pub fn C_str_slice(cx: &CodegenCx, s: LocalInternedString) -> ValueRef {
+pub fn C_str_slice(cx: &CodegenCx<'ll, '_>, s: LocalInternedString) -> &'ll Value {
     let len = s.len();
     let cs = consts::ptrcast(C_cstr(cx, s, false),
         cx.layout_of(cx.tcx.mk_str()).llvm_type(cx).ptr_to());
     C_fat_ptr(cx, cs, C_usize(cx, len as u64))
 }
 
-pub fn C_fat_ptr(cx: &CodegenCx, ptr: ValueRef, meta: ValueRef) -> ValueRef {
+pub fn C_fat_ptr(cx: &CodegenCx<'ll, '_>, ptr: &'ll Value, meta: &'ll Value) -> &'ll Value {
     assert_eq!(abi::FAT_PTR_ADDR, 0);
     assert_eq!(abi::FAT_PTR_EXTRA, 1);
     C_struct(cx, &[ptr, meta], false)
 }
 
-pub fn C_struct(cx: &CodegenCx, elts: &[ValueRef], packed: bool) -> ValueRef {
+pub fn C_struct(cx: &CodegenCx<'ll, '_>, elts: &[&'ll Value], packed: bool) -> &'ll Value {
     C_struct_in_context(cx.llcx, elts, packed)
 }
 
-pub fn C_struct_in_context(llcx: ContextRef, elts: &[ValueRef], packed: bool) -> ValueRef {
+pub fn C_struct_in_context(
+    llcx: &'ll llvm::Context,
+    elts: &[&'ll Value],
+    packed: bool,
+) -> &'ll Value {
     unsafe {
         llvm::LLVMConstStructInContext(llcx,
                                        elts.as_ptr(), elts.len() as c_uint,
@@ -233,47 +241,47 @@ pub fn C_struct_in_context(llcx: ContextRef, elts: &[ValueRef], packed: bool) ->
     }
 }
 
-pub fn C_array(ty: Type, elts: &[ValueRef]) -> ValueRef {
+pub fn C_array(ty: &'ll Type, elts: &[&'ll Value]) -> &'ll Value {
     unsafe {
-        return llvm::LLVMConstArray(ty.to_ref(), elts.as_ptr(), elts.len() as c_uint);
+        return llvm::LLVMConstArray(ty, elts.as_ptr(), elts.len() as c_uint);
     }
 }
 
-pub fn C_vector(elts: &[ValueRef]) -> ValueRef {
+pub fn C_vector(elts: &[&'ll Value]) -> &'ll Value {
     unsafe {
         return llvm::LLVMConstVector(elts.as_ptr(), elts.len() as c_uint);
     }
 }
 
-pub fn C_bytes(cx: &CodegenCx, bytes: &[u8]) -> ValueRef {
+pub fn C_bytes(cx: &CodegenCx<'ll, '_>, bytes: &[u8]) -> &'ll Value {
     C_bytes_in_context(cx.llcx, bytes)
 }
 
-pub fn C_bytes_in_context(llcx: ContextRef, bytes: &[u8]) -> ValueRef {
+pub 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);
     }
 }
 
-pub fn const_get_elt(v: ValueRef, idx: u64) -> ValueRef {
+pub fn const_get_elt(v: &'ll Value, idx: u64) -> &'ll Value {
     unsafe {
         assert_eq!(idx as c_uint as u64, idx);
         let us = &[idx as c_uint];
         let r = llvm::LLVMConstExtractValue(v, us.as_ptr(), us.len() as c_uint);
 
         debug!("const_get_elt(v={:?}, idx={}, r={:?})",
-               Value(v), idx, Value(r));
+               v, idx, r);
 
         r
     }
 }
 
-pub fn const_get_real(v: ValueRef) -> Option<(f64, bool)> {
+pub fn const_get_real(v: &'ll Value) -> Option<(f64, bool)> {
     unsafe {
         if is_const_real(v) {
             let mut loses_info: llvm::Bool = ::std::mem::uninitialized();
-            let r = llvm::LLVMConstRealGetDouble(v, &mut loses_info as *mut llvm::Bool);
+            let r = llvm::LLVMConstRealGetDouble(v, &mut loses_info);
             let loses_info = if loses_info == 1 { true } else { false };
             Some((r, loses_info))
         } else {
@@ -282,21 +290,21 @@ pub fn const_get_real(v: ValueRef) -> Option<(f64, bool)> {
     }
 }
 
-pub fn const_to_uint(v: ValueRef) -> u64 {
+pub fn const_to_uint(v: &'ll Value) -> u64 {
     unsafe {
         llvm::LLVMConstIntGetZExtValue(v)
     }
 }
 
-pub fn is_const_integral(v: ValueRef) -> bool {
+pub fn is_const_integral(v: &'ll Value) -> bool {
     unsafe {
-        !llvm::LLVMIsAConstantInt(v).is_null()
+        llvm::LLVMIsAConstantInt(v).is_some()
     }
 }
 
-pub fn is_const_real(v: ValueRef) -> bool {
+pub fn is_const_real(v: &'ll Value) -> bool {
     unsafe {
-        !llvm::LLVMIsAConstantFP(v).is_null()
+        llvm::LLVMIsAConstantFP(v).is_some()
     }
 }
 
@@ -306,12 +314,12 @@ fn hi_lo_to_u128(lo: u64, hi: u64) -> u128 {
     ((hi as u128) << 64) | (lo as u128)
 }
 
-pub fn const_to_opt_u128(v: ValueRef, sign_ext: bool) -> Option<u128> {
+pub fn const_to_opt_u128(v: &'ll Value, sign_ext: bool) -> Option<u128> {
     unsafe {
         if is_const_integral(v) {
             let (mut lo, mut hi) = (0u64, 0u64);
             let success = llvm::LLVMRustConstInt128Get(v, sign_ext,
-                                                       &mut hi as *mut u64, &mut lo as *mut u64);
+                                                       &mut hi, &mut lo);
             if success {
                 Some(hi_lo_to_u128(lo, hi))
             } else {
@@ -345,20 +353,20 @@ pub fn langcall(tcx: TyCtxt,
 // all shifts). For 32- and 64-bit types, this matches the semantics
 // of Java. (See related discussion on #1877 and #10183.)
 
-pub fn build_unchecked_lshift<'a, 'tcx>(
-    bx: &Builder<'a, 'tcx>,
-    lhs: ValueRef,
-    rhs: ValueRef
-) -> ValueRef {
+pub fn build_unchecked_lshift(
+    bx: &Builder<'a, 'll, 'tcx>,
+    lhs: &'ll Value,
+    rhs: &'ll Value
+) -> &'ll Value {
     let rhs = base::cast_shift_expr_rhs(bx, hir::BinOpKind::Shl, lhs, rhs);
     // #1877, #10183: Ensure that input is always valid
     let rhs = shift_mask_rhs(bx, rhs);
     bx.shl(lhs, rhs)
 }
 
-pub fn build_unchecked_rshift<'a, 'tcx>(
-    bx: &Builder<'a, 'tcx>, lhs_t: Ty<'tcx>, lhs: ValueRef, rhs: ValueRef
-) -> ValueRef {
+pub fn build_unchecked_rshift(
+    bx: &Builder<'a, 'll, 'tcx>, lhs_t: Ty<'tcx>, lhs: &'ll Value, rhs: &'ll Value
+) -> &'ll Value {
     let rhs = base::cast_shift_expr_rhs(bx, hir::BinOpKind::Shr, lhs, rhs);
     // #1877, #10183: Ensure that input is always valid
     let rhs = shift_mask_rhs(bx, rhs);
@@ -370,17 +378,17 @@ pub fn build_unchecked_rshift<'a, 'tcx>(
     }
 }
 
-fn shift_mask_rhs<'a, 'tcx>(bx: &Builder<'a, 'tcx>, rhs: ValueRef) -> ValueRef {
+fn shift_mask_rhs(bx: &Builder<'a, 'll, 'tcx>, rhs: &'ll Value) -> &'ll Value {
     let rhs_llty = val_ty(rhs);
     bx.and(rhs, shift_mask_val(bx, rhs_llty, rhs_llty, false))
 }
 
-pub fn shift_mask_val<'a, 'tcx>(
-    bx: &Builder<'a, 'tcx>,
-    llty: Type,
-    mask_llty: Type,
+pub fn shift_mask_val(
+    bx: &Builder<'a, 'll, 'tcx>,
+    llty: &'ll Type,
+    mask_llty: &'ll Type,
     invert: bool
-) -> ValueRef {
+) -> &'ll Value {
     let kind = llty.kind();
     match kind {
         TypeKind::Integer => {
diff --git a/src/librustc_codegen_llvm/consts.rs b/src/librustc_codegen_llvm/consts.rs
index f0b5f4b8879..72ff65361ca 100644
--- a/src/librustc_codegen_llvm/consts.rs
+++ b/src/librustc_codegen_llvm/consts.rs
@@ -9,9 +9,7 @@
 // except according to those terms.
 
 use libc::c_uint;
-use llvm;
-use llvm::{SetUnnamedAddr};
-use llvm::{ValueRef, True};
+use llvm::{self, SetUnnamedAddr, True};
 use rustc::hir::def_id::DefId;
 use rustc::hir::map as hir_map;
 use debuginfo;
@@ -24,27 +22,29 @@ use syntax_pos::Span;
 use syntax_pos::symbol::LocalInternedString;
 use type_::Type;
 use type_of::LayoutLlvmExt;
+use value::Value;
 use rustc::ty::{self, Ty};
+
 use rustc::ty::layout::{Align, LayoutOf};
 
 use rustc::hir::{self, CodegenFnAttrs, CodegenFnAttrFlags};
 
 use std::ffi::{CStr, CString};
 
-pub fn ptrcast(val: ValueRef, ty: Type) -> ValueRef {
+pub fn ptrcast(val: &'ll Value, ty: &'ll Type) -> &'ll Value {
     unsafe {
-        llvm::LLVMConstPointerCast(val, ty.to_ref())
+        llvm::LLVMConstPointerCast(val, ty)
     }
 }
 
-pub fn bitcast(val: ValueRef, ty: Type) -> ValueRef {
+pub fn bitcast(val: &'ll Value, ty: &'ll Type) -> &'ll Value {
     unsafe {
-        llvm::LLVMConstBitCast(val, ty.to_ref())
+        llvm::LLVMConstBitCast(val, ty)
     }
 }
 
-fn set_global_alignment(cx: &CodegenCx,
-                        gv: ValueRef,
+fn set_global_alignment(cx: &CodegenCx<'ll, '_>,
+                        gv: &'ll Value,
                         mut align: Align) {
     // The target may require greater alignment for globals than the type does.
     // Note: GCC and Clang also allow `__attribute__((aligned))` on variables,
@@ -62,11 +62,12 @@ fn set_global_alignment(cx: &CodegenCx,
     }
 }
 
-pub fn addr_of_mut(cx: &CodegenCx,
-                   cv: ValueRef,
-                   align: Align,
-                   kind: &str)
-                    -> ValueRef {
+pub fn addr_of_mut(
+    cx: &CodegenCx<'ll, '_>,
+    cv: &'ll Value,
+    align: Align,
+    kind: &str,
+) -> &'ll Value {
     unsafe {
         let name = cx.generate_local_symbol_name(kind);
         let gv = declare::define_global(cx, &name[..], val_ty(cv)).unwrap_or_else(||{
@@ -80,11 +81,12 @@ pub fn addr_of_mut(cx: &CodegenCx,
     }
 }
 
-pub fn addr_of(cx: &CodegenCx,
-               cv: ValueRef,
-               align: Align,
-               kind: &str)
-               -> ValueRef {
+pub fn addr_of(
+    cx: &CodegenCx<'ll, '_>,
+    cv: &'ll Value,
+    align: Align,
+    kind: &str,
+) -> &'ll Value {
     if let Some(&gv) = cx.const_globals.borrow().get(&cv) {
         unsafe {
             // Upgrade the alignment in cases where the same constant is used with different
@@ -104,7 +106,7 @@ pub fn addr_of(cx: &CodegenCx,
     gv
 }
 
-pub fn get_static(cx: &CodegenCx, def_id: DefId) -> ValueRef {
+pub fn get_static(cx: &CodegenCx<'ll, '_>, def_id: DefId) -> &'ll Value {
     let instance = Instance::mono(cx.tcx, def_id);
     if let Some(&g) = cx.instances.borrow().get(&instance) {
         return g;
@@ -213,13 +215,13 @@ pub fn get_static(cx: &CodegenCx, def_id: DefId) -> ValueRef {
     g
 }
 
-fn check_and_apply_linkage<'tcx>(
-    cx: &CodegenCx<'_, 'tcx>,
+fn check_and_apply_linkage(
+    cx: &CodegenCx<'ll, 'tcx>,
     attrs: &CodegenFnAttrs,
     ty: Ty<'tcx>,
     sym: LocalInternedString,
     span: Option<Span>
-) -> ValueRef {
+) -> &'ll Value {
     let llty = cx.layout_of(ty).llvm_type(cx);
     if let Some(linkage) = attrs.linkage {
         debug!("get_static: sym={} linkage={:?}", sym, linkage);
@@ -294,7 +296,7 @@ pub fn codegen_static<'a, 'tcx>(
         let mut val_llty = val_ty(v);
         let v = if val_llty == Type::i1(cx) {
             val_llty = Type::i8(cx);
-            llvm::LLVMConstZExt(v, val_llty.to_ref())
+            llvm::LLVMConstZExt(v, val_llty)
         } else {
             v
         };
@@ -316,7 +318,7 @@ pub fn codegen_static<'a, 'tcx>(
             let visibility = llvm::LLVMRustGetVisibility(g);
 
             let new_g = llvm::LLVMRustGetOrInsertGlobal(
-                cx.llmod, name_string.as_ptr(), val_llty.to_ref());
+                cx.llmod, name_string.as_ptr(), val_llty);
 
             llvm::LLVMRustSetLinkage(new_g, linkage);
             llvm::LLVMRustSetVisibility(new_g, visibility);
@@ -411,7 +413,7 @@ pub fn codegen_static<'a, 'tcx>(
 
         if attrs.flags.contains(CodegenFnAttrFlags::USED) {
             // This static will be stored in the llvm.used variable which is an array of i8*
-            let cast = llvm::LLVMConstPointerCast(g, Type::i8p(cx).to_ref());
+            let cast = llvm::LLVMConstPointerCast(g, Type::i8p(cx));
             cx.used_statics.borrow_mut().push(cast);
         }
     }
diff --git a/src/librustc_codegen_llvm/context.rs b/src/librustc_codegen_llvm/context.rs
index b774d7c5def..11f8e75831e 100644
--- a/src/librustc_codegen_llvm/context.rs
+++ b/src/librustc_codegen_llvm/context.rs
@@ -10,7 +10,6 @@
 
 use common;
 use llvm;
-use llvm::{ContextRef, ModuleRef, ValueRef};
 use rustc::dep_graph::DepGraphSafe;
 use rustc::hir;
 use rustc::hir::def_id::DefId;
@@ -19,6 +18,7 @@ use callee;
 use base;
 use declare;
 use monomorphize::Instance;
+use value::Value;
 
 use monomorphize::partitioning::CodegenUnit;
 use type_::Type;
@@ -35,7 +35,6 @@ use rustc_target::spec::{HasTargetSpec, Target};
 
 use std::ffi::{CStr, CString};
 use std::cell::{Cell, RefCell};
-use std::ptr;
 use std::iter;
 use std::str;
 use std::sync::Arc;
@@ -43,65 +42,65 @@ use syntax::symbol::LocalInternedString;
 use abi::Abi;
 
 /// There is one `CodegenCx` per compilation unit. Each one has its own LLVM
-/// `ContextRef` so that several compilation units may be optimized in parallel.
-/// All other LLVM data structures in the `CodegenCx` are tied to that `ContextRef`.
+/// `llvm::Context` so that several compilation units may be optimized in parallel.
+/// All other LLVM data structures in the `CodegenCx` are tied to that `llvm::Context`.
 pub struct CodegenCx<'a, 'tcx: 'a> {
     pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
     pub check_overflow: bool,
     pub use_dll_storage_attrs: bool,
     pub tls_model: llvm::ThreadLocalMode,
 
-    pub llmod: ModuleRef,
-    pub llcx: ContextRef,
+    pub llmod: &'a llvm::Module,
+    pub llcx: &'a llvm::Context,
     pub stats: RefCell<Stats>,
     pub codegen_unit: Arc<CodegenUnit<'tcx>>,
 
     /// Cache instances of monomorphic and polymorphic items
-    pub instances: RefCell<FxHashMap<Instance<'tcx>, ValueRef>>,
+    pub instances: RefCell<FxHashMap<Instance<'tcx>, &'a Value>>,
     /// Cache generated vtables
     pub vtables: RefCell<FxHashMap<(Ty<'tcx>,
-                                Option<ty::PolyExistentialTraitRef<'tcx>>), ValueRef>>,
+                                Option<ty::PolyExistentialTraitRef<'tcx>>), &'a Value>>,
     /// Cache of constant strings,
-    pub const_cstr_cache: RefCell<FxHashMap<LocalInternedString, ValueRef>>,
+    pub const_cstr_cache: RefCell<FxHashMap<LocalInternedString, &'a Value>>,
 
     /// Reverse-direction for const ptrs cast from globals.
-    /// Key is a ValueRef holding a *T,
-    /// Val is a ValueRef holding a *[T].
+    /// Key is a Value holding a *T,
+    /// Val is a Value holding a *[T].
     ///
     /// Needed because LLVM loses pointer->pointee association
     /// when we ptrcast, and we have to ptrcast during codegen
     /// of a [T] const because we form a slice, a (*T,usize) pair, not
     /// a pointer to an LLVM array type. Similar for trait objects.
-    pub const_unsized: RefCell<FxHashMap<ValueRef, ValueRef>>,
+    pub const_unsized: RefCell<FxHashMap<&'a Value, &'a Value>>,
 
     /// Cache of emitted const globals (value -> global)
-    pub const_globals: RefCell<FxHashMap<ValueRef, ValueRef>>,
+    pub const_globals: RefCell<FxHashMap<&'a Value, &'a Value>>,
 
     /// Mapping from static definitions to their DefId's.
-    pub statics: RefCell<FxHashMap<ValueRef, DefId>>,
+    pub statics: RefCell<FxHashMap<&'a Value, DefId>>,
 
     /// List of globals for static variables which need to be passed to the
     /// LLVM function ReplaceAllUsesWith (RAUW) when codegen is complete.
-    /// (We have to make sure we don't invalidate any ValueRefs referring
+    /// (We have to make sure we don't invalidate any Values referring
     /// to constants.)
-    pub statics_to_rauw: RefCell<Vec<(ValueRef, ValueRef)>>,
+    pub statics_to_rauw: RefCell<Vec<(&'a Value, &'a Value)>>,
 
     /// Statics that will be placed in the llvm.used variable
     /// See http://llvm.org/docs/LangRef.html#the-llvm-used-global-variable for details
-    pub used_statics: RefCell<Vec<ValueRef>>,
+    pub used_statics: RefCell<Vec<&'a Value>>,
 
-    pub lltypes: RefCell<FxHashMap<(Ty<'tcx>, Option<usize>), Type>>,
-    pub scalar_lltypes: RefCell<FxHashMap<Ty<'tcx>, Type>>,
+    pub lltypes: RefCell<FxHashMap<(Ty<'tcx>, Option<usize>), &'a Type>>,
+    pub scalar_lltypes: RefCell<FxHashMap<Ty<'tcx>, &'a Type>>,
     pub pointee_infos: RefCell<FxHashMap<(Ty<'tcx>, Size), Option<PointeeInfo>>>,
-    pub isize_ty: Type,
+    pub isize_ty: &'a Type,
 
-    pub dbg_cx: Option<debuginfo::CrateDebugContext<'tcx>>,
+    pub dbg_cx: Option<debuginfo::CrateDebugContext<'a, 'tcx>>,
 
-    eh_personality: Cell<Option<ValueRef>>,
-    eh_unwind_resume: Cell<Option<ValueRef>>,
-    pub rust_try_fn: Cell<Option<ValueRef>>,
+    eh_personality: Cell<Option<&'a Value>>,
+    eh_unwind_resume: Cell<Option<&'a Value>>,
+    pub rust_try_fn: Cell<Option<&'a Value>>,
 
-    intrinsics: RefCell<FxHashMap<&'static str, ValueRef>>,
+    intrinsics: RefCell<FxHashMap<&'static str, &'a Value>>,
 
     /// A counter that is used for generating local symbol names
     local_gen_sym_counter: Cell<usize>,
@@ -156,8 +155,11 @@ pub fn is_pie_binary(sess: &Session) -> bool {
     !is_any_library(sess) && get_reloc_model(sess) == llvm::RelocMode::PIC
 }
 
-pub unsafe fn create_context_and_module(sess: &Session, mod_name: &str) -> (ContextRef, ModuleRef) {
-    let llcx = llvm::LLVMRustContextCreate(sess.fewer_names());
+pub unsafe fn create_module(
+    sess: &Session,
+    llcx: &'ll llvm::Context,
+    mod_name: &str,
+) -> &'ll llvm::Module {
     let mod_name = CString::new(mod_name).unwrap();
     let llmod = llvm::LLVMModuleCreateWithNameInContext(mod_name.as_ptr(), llcx);
 
@@ -209,13 +211,13 @@ pub unsafe fn create_context_and_module(sess: &Session, mod_name: &str) -> (Cont
         llvm::LLVMRustSetModulePIELevel(llmod);
     }
 
-    (llcx, llmod)
+    llmod
 }
 
 impl<'a, 'tcx> CodegenCx<'a, 'tcx> {
-    pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    crate fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                codegen_unit: Arc<CodegenUnit<'tcx>>,
-               llmod_id: &str)
+               llvm_module: &'a ::ModuleLlvm)
                -> CodegenCx<'a, 'tcx> {
         // An interesting part of Windows which MSVC forces our hand on (and
         // apparently MinGW didn't) is the usage of `dllimport` and `dllexport`
@@ -266,55 +268,48 @@ impl<'a, 'tcx> CodegenCx<'a, 'tcx> {
 
         let tls_model = get_tls_model(&tcx.sess);
 
-        unsafe {
-            let (llcx, llmod) = create_context_and_module(&tcx.sess,
-                                                          &llmod_id[..]);
-
-            let dbg_cx = if tcx.sess.opts.debuginfo != NoDebugInfo {
-                let dctx = debuginfo::CrateDebugContext::new(llmod);
-                debuginfo::metadata::compile_unit_metadata(tcx,
-                                                           &codegen_unit.name().as_str(),
-                                                           &dctx);
-                Some(dctx)
-            } else {
-                None
-            };
-
-            let mut cx = CodegenCx {
-                tcx,
-                check_overflow,
-                use_dll_storage_attrs,
-                tls_model,
-                llmod,
-                llcx,
-                stats: RefCell::new(Stats::default()),
-                codegen_unit,
-                instances: RefCell::new(FxHashMap()),
-                vtables: RefCell::new(FxHashMap()),
-                const_cstr_cache: RefCell::new(FxHashMap()),
-                const_unsized: RefCell::new(FxHashMap()),
-                const_globals: RefCell::new(FxHashMap()),
-                statics: RefCell::new(FxHashMap()),
-                statics_to_rauw: RefCell::new(Vec::new()),
-                used_statics: RefCell::new(Vec::new()),
-                lltypes: RefCell::new(FxHashMap()),
-                scalar_lltypes: RefCell::new(FxHashMap()),
-                pointee_infos: RefCell::new(FxHashMap()),
-                isize_ty: Type::from_ref(ptr::null_mut()),
-                dbg_cx,
-                eh_personality: Cell::new(None),
-                eh_unwind_resume: Cell::new(None),
-                rust_try_fn: Cell::new(None),
-                intrinsics: RefCell::new(FxHashMap()),
-                local_gen_sym_counter: Cell::new(0),
-            };
-            cx.isize_ty = Type::isize(&cx);
-            cx
-        }
-    }
+        let (llcx, llmod) = (&*llvm_module.llcx, llvm_module.llmod());
 
-    pub fn into_stats(self) -> Stats {
-        self.stats.into_inner()
+        let dbg_cx = if tcx.sess.opts.debuginfo != NoDebugInfo {
+            let dctx = debuginfo::CrateDebugContext::new(llmod);
+            debuginfo::metadata::compile_unit_metadata(tcx,
+                                                        &codegen_unit.name().as_str(),
+                                                        &dctx);
+            Some(dctx)
+        } else {
+            None
+        };
+
+        let isize_ty = Type::ix_llcx(llcx, tcx.data_layout.pointer_size.bits());
+
+        CodegenCx {
+            tcx,
+            check_overflow,
+            use_dll_storage_attrs,
+            tls_model,
+            llmod,
+            llcx,
+            stats: RefCell::new(Stats::default()),
+            codegen_unit,
+            instances: RefCell::new(FxHashMap()),
+            vtables: RefCell::new(FxHashMap()),
+            const_cstr_cache: RefCell::new(FxHashMap()),
+            const_unsized: RefCell::new(FxHashMap()),
+            const_globals: RefCell::new(FxHashMap()),
+            statics: RefCell::new(FxHashMap()),
+            statics_to_rauw: RefCell::new(Vec::new()),
+            used_statics: RefCell::new(Vec::new()),
+            lltypes: RefCell::new(FxHashMap()),
+            scalar_lltypes: RefCell::new(FxHashMap()),
+            pointee_infos: RefCell::new(FxHashMap()),
+            isize_ty,
+            dbg_cx,
+            eh_personality: Cell::new(None),
+            eh_unwind_resume: Cell::new(None),
+            rust_try_fn: Cell::new(None),
+            intrinsics: RefCell::new(FxHashMap()),
+            local_gen_sym_counter: Cell::new(0),
+        }
     }
 }
 
@@ -323,7 +318,7 @@ impl<'b, 'tcx> CodegenCx<'b, 'tcx> {
         &self.tcx.sess
     }
 
-    pub fn get_intrinsic(&self, key: &str) -> ValueRef {
+    pub fn get_intrinsic(&self, key: &str) -> &'b Value {
         if let Some(v) = self.intrinsics.borrow().get(key).cloned() {
             return v;
         }
@@ -347,7 +342,7 @@ impl<'b, 'tcx> CodegenCx<'b, 'tcx> {
         name
     }
 
-    pub fn eh_personality(&self) -> ValueRef {
+    pub fn eh_personality(&self) -> &'b Value {
         // The exception handling personality function.
         //
         // If our compilation unit has the `eh_personality` lang item somewhere
@@ -382,7 +377,7 @@ impl<'b, 'tcx> CodegenCx<'b, 'tcx> {
                 } else {
                     "rust_eh_personality"
                 };
-                let fty = Type::variadic_func(&[], &Type::i32(self));
+                let fty = Type::variadic_func(&[], Type::i32(self));
                 declare::declare_cfn(self, name, fty)
             }
         };
@@ -390,9 +385,9 @@ impl<'b, 'tcx> CodegenCx<'b, 'tcx> {
         llfn
     }
 
-    // Returns a ValueRef of the "eh_unwind_resume" lang item if one is defined,
+    // Returns a Value of the "eh_unwind_resume" lang item if one is defined,
     // otherwise declares it as an external function.
-    pub fn eh_unwind_resume(&self) -> ValueRef {
+    pub fn eh_unwind_resume(&self) -> &'b Value {
         use attributes;
         let unwresume = &self.eh_unwind_resume;
         if let Some(llfn) = unwresume.get() {
@@ -448,25 +443,25 @@ impl<'b, 'tcx> CodegenCx<'b, 'tcx> {
     }
 }
 
-impl<'a, 'tcx> ty::layout::HasDataLayout for &'a CodegenCx<'a, 'tcx> {
+impl ty::layout::HasDataLayout for &'a CodegenCx<'ll, 'tcx> {
     fn data_layout(&self) -> &ty::layout::TargetDataLayout {
         &self.tcx.data_layout
     }
 }
 
-impl<'a, 'tcx> HasTargetSpec for &'a CodegenCx<'a, 'tcx> {
+impl HasTargetSpec for &'a CodegenCx<'ll, 'tcx> {
     fn target_spec(&self) -> &Target {
         &self.tcx.sess.target.target
     }
 }
 
-impl<'a, 'tcx> ty::layout::HasTyCtxt<'tcx> for &'a CodegenCx<'a, 'tcx> {
+impl ty::layout::HasTyCtxt<'tcx> for &'a CodegenCx<'ll, 'tcx> {
     fn tcx<'b>(&'b self) -> TyCtxt<'b, 'tcx, 'tcx> {
         self.tcx
     }
 }
 
-impl<'a, 'tcx> LayoutOf for &'a CodegenCx<'a, 'tcx> {
+impl LayoutOf for &'a CodegenCx<'ll, 'tcx> {
     type Ty = Ty<'tcx>;
     type TyLayout = TyLayout<'tcx>;
 
@@ -480,11 +475,11 @@ impl<'a, 'tcx> LayoutOf for &'a CodegenCx<'a, 'tcx> {
 }
 
 /// Declare any llvm intrinsics that you might need
-fn declare_intrinsic(cx: &CodegenCx, key: &str) -> Option<ValueRef> {
+fn declare_intrinsic(cx: &CodegenCx<'ll, '_>, key: &str) -> Option<&'ll Value> {
     macro_rules! ifn {
         ($name:expr, fn() -> $ret:expr) => (
             if key == $name {
-                let f = declare::declare_cfn(cx, $name, Type::func(&[], &$ret));
+                let f = declare::declare_cfn(cx, $name, Type::func(&[], $ret));
                 llvm::SetUnnamedAddr(f, false);
                 cx.intrinsics.borrow_mut().insert($name, f.clone());
                 return Some(f);
@@ -492,7 +487,7 @@ fn declare_intrinsic(cx: &CodegenCx, key: &str) -> Option<ValueRef> {
         );
         ($name:expr, fn(...) -> $ret:expr) => (
             if key == $name {
-                let f = declare::declare_cfn(cx, $name, Type::variadic_func(&[], &$ret));
+                let f = declare::declare_cfn(cx, $name, Type::variadic_func(&[], $ret));
                 llvm::SetUnnamedAddr(f, false);
                 cx.intrinsics.borrow_mut().insert($name, f.clone());
                 return Some(f);
@@ -500,7 +495,7 @@ fn declare_intrinsic(cx: &CodegenCx, key: &str) -> Option<ValueRef> {
         );
         ($name:expr, fn($($arg:expr),*) -> $ret:expr) => (
             if key == $name {
-                let f = declare::declare_cfn(cx, $name, Type::func(&[$($arg),*], &$ret));
+                let f = declare::declare_cfn(cx, $name, Type::func(&[$($arg),*], $ret));
                 llvm::SetUnnamedAddr(f, false);
                 cx.intrinsics.borrow_mut().insert($name, f.clone());
                 return Some(f);
@@ -522,14 +517,14 @@ fn declare_intrinsic(cx: &CodegenCx, key: &str) -> Option<ValueRef> {
     let t_f32 = Type::f32(cx);
     let t_f64 = Type::f64(cx);
 
-    let t_v2f32 = Type::vector(&t_f32, 2);
-    let t_v4f32 = Type::vector(&t_f32, 4);
-    let t_v8f32 = Type::vector(&t_f32, 8);
-    let t_v16f32 = Type::vector(&t_f32, 16);
+    let t_v2f32 = Type::vector(t_f32, 2);
+    let t_v4f32 = Type::vector(t_f32, 4);
+    let t_v8f32 = Type::vector(t_f32, 8);
+    let t_v16f32 = Type::vector(t_f32, 16);
 
-    let t_v2f64 = Type::vector(&t_f64, 2);
-    let t_v4f64 = Type::vector(&t_f64, 4);
-    let t_v8f64 = Type::vector(&t_f64, 8);
+    let t_v2f64 = Type::vector(t_f64, 2);
+    let t_v4f64 = Type::vector(t_f64, 4);
+    let t_v8f64 = Type::vector(t_f64, 8);
 
     ifn!("llvm.memcpy.p0i8.p0i8.i16", fn(i8p, i8p, t_i16, t_i32, i1) -> void);
     ifn!("llvm.memcpy.p0i8.p0i8.i32", fn(i8p, i8p, t_i32, t_i32, i1) -> void);
diff --git a/src/librustc_codegen_llvm/debuginfo/create_scope_map.rs b/src/librustc_codegen_llvm/debuginfo/create_scope_map.rs
index fcde7f9bbc3..5273032f2d7 100644
--- a/src/librustc_codegen_llvm/debuginfo/create_scope_map.rs
+++ b/src/librustc_codegen_llvm/debuginfo/create_scope_map.rs
@@ -18,7 +18,6 @@ use common::CodegenCx;
 use rustc::mir::{Mir, SourceScope};
 
 use libc::c_uint;
-use std::ptr;
 
 use syntax_pos::Pos;
 
@@ -28,26 +27,29 @@ use rustc_data_structures::indexed_vec::{Idx, IndexVec};
 use syntax_pos::BytePos;
 
 #[derive(Clone, Copy, Debug)]
-pub struct MirDebugScope {
-    pub scope_metadata: DIScope,
+pub struct MirDebugScope<'ll> {
+    pub scope_metadata: Option<&'ll DIScope>,
     // Start and end offsets of the file to which this DIScope belongs.
     // These are used to quickly determine whether some span refers to the same file.
     pub file_start_pos: BytePos,
     pub file_end_pos: BytePos,
 }
 
-impl MirDebugScope {
+impl MirDebugScope<'ll> {
     pub fn is_valid(&self) -> bool {
-        !self.scope_metadata.is_null()
+        !self.scope_metadata.is_none()
     }
 }
 
 /// Produce DIScope DIEs for each MIR Scope which has variables defined in it.
 /// If debuginfo is disabled, the returned vector is empty.
-pub fn create_mir_scopes(cx: &CodegenCx, mir: &Mir, debug_context: &FunctionDebugContext)
-    -> IndexVec<SourceScope, MirDebugScope> {
+pub fn create_mir_scopes(
+    cx: &CodegenCx<'ll, '_>,
+    mir: &Mir,
+    debug_context: &FunctionDebugContext<'ll>,
+) -> IndexVec<SourceScope, MirDebugScope<'ll>> {
     let null_scope = MirDebugScope {
-        scope_metadata: ptr::null_mut(),
+        scope_metadata: None,
         file_start_pos: BytePos(0),
         file_end_pos: BytePos(0)
     };
@@ -77,12 +79,12 @@ pub fn create_mir_scopes(cx: &CodegenCx, mir: &Mir, debug_context: &FunctionDebu
     scopes
 }
 
-fn make_mir_scope(cx: &CodegenCx,
+fn make_mir_scope(cx: &CodegenCx<'ll, '_>,
                   mir: &Mir,
                   has_variables: &BitVector<SourceScope>,
-                  debug_context: &FunctionDebugContextData,
+                  debug_context: &FunctionDebugContextData<'ll>,
                   scope: SourceScope,
-                  scopes: &mut IndexVec<SourceScope, MirDebugScope>) {
+                  scopes: &mut IndexVec<SourceScope, MirDebugScope<'ll>>) {
     if scopes[scope].is_valid() {
         return;
     }
@@ -95,7 +97,7 @@ fn make_mir_scope(cx: &CodegenCx,
         // The root is the function itself.
         let loc = span_start(cx, mir.span);
         scopes[scope] = MirDebugScope {
-            scope_metadata: debug_context.fn_metadata,
+            scope_metadata: Some(debug_context.fn_metadata),
             file_start_pos: loc.file.start_pos,
             file_end_pos: loc.file.end_pos,
         };
@@ -109,7 +111,7 @@ fn make_mir_scope(cx: &CodegenCx,
         // However, we don't skip creating a nested scope if
         // our parent is the root, because we might want to
         // put arguments in the root and not have shadowing.
-        if parent_scope.scope_metadata != debug_context.fn_metadata {
+        if parent_scope.scope_metadata.unwrap() != debug_context.fn_metadata {
             scopes[scope] = parent_scope;
             return;
         }
@@ -121,12 +123,12 @@ fn make_mir_scope(cx: &CodegenCx,
                                       debug_context.defining_crate);
 
     let scope_metadata = unsafe {
-        llvm::LLVMRustDIBuilderCreateLexicalBlock(
+        Some(llvm::LLVMRustDIBuilderCreateLexicalBlock(
             DIB(cx),
-            parent_scope.scope_metadata,
+            parent_scope.scope_metadata.unwrap(),
             file_metadata,
             loc.line as c_uint,
-            loc.col.to_usize() as c_uint)
+            loc.col.to_usize() as c_uint))
     };
     scopes[scope] = MirDebugScope {
         scope_metadata,
diff --git a/src/librustc_codegen_llvm/debuginfo/gdb.rs b/src/librustc_codegen_llvm/debuginfo/gdb.rs
index 0b4858c7ab0..08128a729b5 100644
--- a/src/librustc_codegen_llvm/debuginfo/gdb.rs
+++ b/src/librustc_codegen_llvm/debuginfo/gdb.rs
@@ -15,10 +15,10 @@ use llvm;
 use common::{C_bytes, CodegenCx, C_i32};
 use builder::Builder;
 use declare;
-use type_::Type;
 use rustc::session::config::NoDebugInfo;
+use type_::Type;
+use value::Value;
 
-use std::ptr;
 use syntax::attr;
 
 
@@ -40,8 +40,8 @@ pub fn insert_reference_to_gdb_debug_scripts_section_global(bx: &Builder) {
 
 /// Allocates the global variable responsible for the .debug_gdb_scripts binary
 /// section.
-pub fn get_or_insert_gdb_debug_scripts_section_global(cx: &CodegenCx)
-                                                  -> llvm::ValueRef {
+pub fn get_or_insert_gdb_debug_scripts_section_global(cx: &CodegenCx<'ll, '_>)
+                                                  -> &'ll Value {
     let c_section_var_name = "__rustc_debug_gdb_scripts_section__\0";
     let section_var_name = &c_section_var_name[..c_section_var_name.len()-1];
 
@@ -50,12 +50,12 @@ pub fn get_or_insert_gdb_debug_scripts_section_global(cx: &CodegenCx)
                                  c_section_var_name.as_ptr() as *const _)
     };
 
-    if section_var == ptr::null_mut() {
+    section_var.unwrap_or_else(|| {
         let section_name = b".debug_gdb_scripts\0";
         let section_contents = b"\x01gdb_load_rust_pretty_printers.py\0";
 
         unsafe {
-            let llvm_type = Type::array(&Type::i8(cx),
+            let llvm_type = Type::array(Type::i8(cx),
                                         section_contents.len() as u64);
 
             let section_var = declare::define_global(cx, section_var_name,
@@ -72,9 +72,7 @@ pub fn get_or_insert_gdb_debug_scripts_section_global(cx: &CodegenCx)
             llvm::LLVMSetAlignment(section_var, 1);
             section_var
         }
-    } else {
-        section_var
-    }
+    })
 }
 
 pub fn needs_gdb_debug_scripts_section(cx: &CodegenCx) -> bool {
diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs
index 2f4dd5a7ce5..69ef92ed98e 100644
--- a/src/librustc_codegen_llvm/debuginfo/metadata.rs
+++ b/src/librustc_codegen_llvm/debuginfo/metadata.rs
@@ -18,8 +18,9 @@ use super::namespace::mangled_name_of_instance;
 use super::type_names::compute_debuginfo_type_name;
 use super::{CrateDebugContext};
 use abi;
+use value::Value;
 
-use llvm::{self, ValueRef};
+use llvm;
 use llvm::debuginfo::{DIType, DIFile, DIScope, DIDescriptor,
                       DICompositeType, DILexicalBlock, DIFlags};
 
@@ -38,7 +39,8 @@ use rustc::util::common::path2cstr;
 
 use libc::{c_uint, c_longlong};
 use std::ffi::CString;
-use std::fmt::Write;
+use std::fmt::{self, Write};
+use std::hash::{Hash, Hasher};
 use std::iter;
 use std::ptr;
 use std::path::{Path, PathBuf};
@@ -46,6 +48,25 @@ use syntax::ast;
 use syntax::symbol::{Interner, InternedString, Symbol};
 use syntax_pos::{self, Span, FileName};
 
+impl PartialEq for llvm::Metadata {
+    fn eq(&self, other: &Self) -> bool {
+        self as *const _ == other as *const _
+    }
+}
+
+impl Eq for llvm::Metadata {}
+
+impl Hash for llvm::Metadata {
+    fn hash<H: Hasher>(&self, hasher: &mut H) {
+        (self as *const Self).hash(hasher);
+    }
+}
+
+impl fmt::Debug for llvm::Metadata {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        (self as *const Self).fmt(f)
+    }
+}
 
 // From DWARF 5.
 // See http://www.dwarfstd.org/ShowIssue.php?issue=140129.1
@@ -64,8 +85,7 @@ const DW_ATE_unsigned_char: c_uint = 0x08;
 pub const UNKNOWN_LINE_NUMBER: c_uint = 0;
 pub const UNKNOWN_COLUMN_NUMBER: c_uint = 0;
 
-// ptr::null() doesn't work :(
-pub const NO_SCOPE_METADATA: DIScope = (0 as DIScope);
+pub const NO_SCOPE_METADATA: Option<&DIScope> = None;
 
 #[derive(Copy, Debug, Hash, Eq, PartialEq, Clone)]
 pub struct UniqueTypeId(ast::Name);
@@ -74,19 +94,19 @@ pub struct UniqueTypeId(ast::Name);
 // created so far. The metadata nodes are indexed by UniqueTypeId, and, for
 // faster lookup, also by Ty. The TypeMap is responsible for creating
 // UniqueTypeIds.
-pub struct TypeMap<'tcx> {
+pub struct TypeMap<'ll, 'tcx> {
     // The UniqueTypeIds created so far
     unique_id_interner: Interner,
     // A map from UniqueTypeId to debuginfo metadata for that type. This is a 1:1 mapping.
-    unique_id_to_metadata: FxHashMap<UniqueTypeId, DIType>,
+    unique_id_to_metadata: FxHashMap<UniqueTypeId, &'ll DIType>,
     // A map from types to debuginfo metadata. This is a N:1 mapping.
-    type_to_metadata: FxHashMap<Ty<'tcx>, DIType>,
+    type_to_metadata: FxHashMap<Ty<'tcx>, &'ll DIType>,
     // A map from types to UniqueTypeId. This is a N:1 mapping.
     type_to_unique_id: FxHashMap<Ty<'tcx>, UniqueTypeId>
 }
 
-impl<'tcx> TypeMap<'tcx> {
-    pub fn new() -> TypeMap<'tcx> {
+impl TypeMap<'ll, 'tcx> {
+    pub fn new() -> Self {
         TypeMap {
             unique_id_interner: Interner::new(),
             type_to_metadata: FxHashMap(),
@@ -97,9 +117,11 @@ impl<'tcx> TypeMap<'tcx> {
 
     // Adds a Ty to metadata mapping to the TypeMap. The method will fail if
     // the mapping already exists.
-    fn register_type_with_metadata<'a>(&mut self,
-                                       type_: Ty<'tcx>,
-                                       metadata: DIType) {
+    fn register_type_with_metadata(
+        &mut self,
+        type_: Ty<'tcx>,
+        metadata: &'ll DIType,
+    ) {
         if self.type_to_metadata.insert(type_, metadata).is_some() {
             bug!("Type metadata for Ty '{}' is already in the TypeMap!", type_);
         }
@@ -107,20 +129,22 @@ impl<'tcx> TypeMap<'tcx> {
 
     // Adds a UniqueTypeId to metadata mapping to the TypeMap. The method will
     // fail if the mapping already exists.
-    fn register_unique_id_with_metadata(&mut self,
-                                        unique_type_id: UniqueTypeId,
-                                        metadata: DIType) {
+    fn register_unique_id_with_metadata(
+        &mut self,
+        unique_type_id: UniqueTypeId,
+        metadata: &'ll DIType,
+    ) {
         if self.unique_id_to_metadata.insert(unique_type_id, metadata).is_some() {
             bug!("Type metadata for unique id '{}' is already in the TypeMap!",
                  self.get_unique_type_id_as_string(unique_type_id));
         }
     }
 
-    fn find_metadata_for_type(&self, type_: Ty<'tcx>) -> Option<DIType> {
+    fn find_metadata_for_type(&self, type_: Ty<'tcx>) -> Option<&'ll DIType> {
         self.type_to_metadata.get(&type_).cloned()
     }
 
-    fn find_metadata_for_unique_id(&self, unique_type_id: UniqueTypeId) -> Option<DIType> {
+    fn find_metadata_for_unique_id(&self, unique_type_id: UniqueTypeId) -> Option<&'ll DIType> {
         self.unique_id_to_metadata.get(&unique_type_id).cloned()
     }
 
@@ -182,23 +206,23 @@ impl<'tcx> TypeMap<'tcx> {
 // needed to generate the missing parts of the description. See the
 // documentation section on Recursive Types at the top of this file for more
 // information.
-enum RecursiveTypeDescription<'tcx> {
+enum RecursiveTypeDescription<'ll, 'tcx> {
     UnfinishedMetadata {
         unfinished_type: Ty<'tcx>,
         unique_type_id: UniqueTypeId,
-        metadata_stub: DICompositeType,
-        member_description_factory: MemberDescriptionFactory<'tcx>,
+        metadata_stub: &'ll DICompositeType,
+        member_description_factory: MemberDescriptionFactory<'ll, 'tcx>,
     },
-    FinalMetadata(DICompositeType)
+    FinalMetadata(&'ll DICompositeType)
 }
 
-fn create_and_register_recursive_type_forward_declaration<'a, 'tcx>(
-    cx: &CodegenCx<'a, 'tcx>,
+fn create_and_register_recursive_type_forward_declaration(
+    cx: &CodegenCx<'ll, 'tcx>,
     unfinished_type: Ty<'tcx>,
     unique_type_id: UniqueTypeId,
-    metadata_stub: DICompositeType,
-    member_description_factory: MemberDescriptionFactory<'tcx>)
- -> RecursiveTypeDescription<'tcx> {
+    metadata_stub: &'ll DICompositeType,
+    member_description_factory: MemberDescriptionFactory<'ll, 'tcx>,
+) -> RecursiveTypeDescription<'ll, 'tcx> {
 
     // Insert the stub into the TypeMap in order to allow for recursive references
     let mut type_map = debug_context(cx).type_map.borrow_mut();
@@ -213,11 +237,11 @@ fn create_and_register_recursive_type_forward_declaration<'a, 'tcx>(
     }
 }
 
-impl<'tcx> RecursiveTypeDescription<'tcx> {
+impl RecursiveTypeDescription<'ll, 'tcx> {
     // Finishes up the description of the type in question (mostly by providing
     // descriptions of the fields of the given type) and returns the final type
     // metadata.
-    fn finalize<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> MetadataCreationResult {
+    fn finalize(&self, cx: &CodegenCx<'ll, 'tcx>) -> MetadataCreationResult<'ll> {
         match *self {
             FinalMetadata(metadata) => MetadataCreationResult::new(metadata, false),
             UnfinishedMetadata {
@@ -269,12 +293,13 @@ macro_rules! return_if_metadata_created_in_meantime {
     )
 }
 
-fn fixed_vec_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
-                                unique_type_id: UniqueTypeId,
-                                array_or_slice_type: Ty<'tcx>,
-                                element_type: Ty<'tcx>,
-                                span: Span)
-                                -> MetadataCreationResult {
+fn fixed_vec_metadata(
+    cx: &CodegenCx<'ll, 'tcx>,
+    unique_type_id: UniqueTypeId,
+    array_or_slice_type: Ty<'tcx>,
+    element_type: Ty<'tcx>,
+    span: Span,
+) -> MetadataCreationResult<'ll> {
     let element_type_metadata = type_metadata(cx, element_type, span);
 
     return_if_metadata_created_in_meantime!(cx, unique_type_id);
@@ -289,7 +314,7 @@ fn fixed_vec_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
     };
 
     let subrange = unsafe {
-        llvm::LLVMRustDIBuilderGetOrCreateSubrange(DIB(cx), 0, upper_bound)
+        Some(llvm::LLVMRustDIBuilderGetOrCreateSubrange(DIB(cx), 0, upper_bound))
     };
 
     let subscripts = create_DIArray(DIB(cx), &[subrange]);
@@ -305,12 +330,13 @@ fn fixed_vec_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
     return MetadataCreationResult::new(metadata, false);
 }
 
-fn vec_slice_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
-                                slice_ptr_type: Ty<'tcx>,
-                                element_type: Ty<'tcx>,
-                                unique_type_id: UniqueTypeId,
-                                span: Span)
-                                -> MetadataCreationResult {
+fn vec_slice_metadata(
+    cx: &CodegenCx<'ll, 'tcx>,
+    slice_ptr_type: Ty<'tcx>,
+    element_type: Ty<'tcx>,
+    unique_type_id: UniqueTypeId,
+    span: Span,
+) -> MetadataCreationResult<'ll> {
     let data_ptr_type = cx.tcx.mk_imm_ptr(element_type);
 
     let data_ptr_metadata = type_metadata(cx, data_ptr_type, span);
@@ -354,26 +380,28 @@ fn vec_slice_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
     MetadataCreationResult::new(metadata, false)
 }
 
-fn subroutine_type_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
-                                      unique_type_id: UniqueTypeId,
-                                      signature: ty::PolyFnSig<'tcx>,
-                                      span: Span)
-                                      -> MetadataCreationResult
-{
+fn subroutine_type_metadata(
+    cx: &CodegenCx<'ll, 'tcx>,
+    unique_type_id: UniqueTypeId,
+    signature: ty::PolyFnSig<'tcx>,
+    span: Span,
+) -> MetadataCreationResult<'ll> {
     let signature = cx.tcx.normalize_erasing_late_bound_regions(
         ty::ParamEnv::reveal_all(),
         &signature,
     );
 
-    let signature_metadata: Vec<DIType> = iter::once(
+    let signature_metadata: Vec<_> = iter::once(
         // return type
         match signature.output().sty {
-            ty::TyTuple(ref tys) if tys.is_empty() => ptr::null_mut(),
-            _ => type_metadata(cx, signature.output(), span)
+            ty::TyTuple(ref tys) if tys.is_empty() => None,
+            _ => Some(type_metadata(cx, signature.output(), span))
         }
     ).chain(
         // regular arguments
-        signature.inputs().iter().map(|argument_type| type_metadata(cx, argument_type, span))
+        signature.inputs().iter().map(|argument_type| {
+            Some(type_metadata(cx, argument_type, span))
+        })
     ).collect();
 
     return_if_metadata_created_in_meantime!(cx, unique_type_id);
@@ -394,11 +422,12 @@ fn subroutine_type_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
 // trait_type should be the actual trait (e.g., Trait). Where the trait is part
 // of a DST struct, there is no trait_object_type and the results of this
 // function will be a little bit weird.
-fn trait_pointer_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
-                                    trait_type: Ty<'tcx>,
-                                    trait_object_type: Option<Ty<'tcx>>,
-                                    unique_type_id: UniqueTypeId)
-                                    -> DIType {
+fn trait_pointer_metadata(
+    cx: &CodegenCx<'ll, 'tcx>,
+    trait_type: Ty<'tcx>,
+    trait_object_type: Option<Ty<'tcx>>,
+    unique_type_id: UniqueTypeId,
+) -> &'ll DIType {
     // The implementation provided here is a stub. It makes sure that the trait
     // type is assigned the correct name, size, namespace, and source location.
     // But it does not describe the trait's methods.
@@ -406,7 +435,7 @@ fn trait_pointer_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
     let containing_scope = match trait_type.sty {
         ty::TyDynamic(ref data, ..) => if let Some(principal) = data.principal() {
             let def_id = principal.def_id();
-            get_namespace_for_item(cx, def_id)
+            Some(get_namespace_for_item(cx, def_id))
         } else {
             NO_SCOPE_METADATA
         },
@@ -461,10 +490,11 @@ fn trait_pointer_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                             syntax_pos::DUMMY_SP)
 }
 
-pub fn type_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
-                               t: Ty<'tcx>,
-                               usage_site_span: Span)
-                               -> DIType {
+pub fn type_metadata(
+    cx: &CodegenCx<'ll, 'tcx>,
+    t: Ty<'tcx>,
+    usage_site_span: Span,
+) -> &'ll DIType {
     // Get the unique type id of this type.
     let unique_type_id = {
         let mut type_map = debug_context(cx).type_map.borrow_mut();
@@ -681,9 +711,9 @@ pub fn type_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
     metadata
 }
 
-pub fn file_metadata(cx: &CodegenCx,
+pub fn file_metadata(cx: &CodegenCx<'ll, '_>,
                      file_name: &FileName,
-                     defining_crate: CrateNum) -> DIFile {
+                     defining_crate: CrateNum) -> &'ll DIFile {
     debug!("file_metadata: file_name: {}, defining_crate: {}",
            file_name,
            defining_crate);
@@ -699,14 +729,14 @@ pub fn file_metadata(cx: &CodegenCx,
     file_metadata_raw(cx, &file_name.to_string(), &directory.to_string_lossy())
 }
 
-pub fn unknown_file_metadata(cx: &CodegenCx) -> DIFile {
+pub fn unknown_file_metadata(cx: &CodegenCx<'ll, '_>) -> &'ll DIFile {
     file_metadata_raw(cx, "<unknown>", "")
 }
 
-fn file_metadata_raw(cx: &CodegenCx,
+fn file_metadata_raw(cx: &CodegenCx<'ll, '_>,
                      file_name: &str,
                      directory: &str)
-                     -> DIFile {
+                     -> &'ll DIFile {
     let key = (Symbol::intern(file_name), Symbol::intern(directory));
 
     if let Some(file_metadata) = debug_context(cx).created_files.borrow().get(&key) {
@@ -729,9 +759,7 @@ fn file_metadata_raw(cx: &CodegenCx,
     file_metadata
 }
 
-fn basic_type_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
-                                 t: Ty<'tcx>) -> DIType {
-
+fn basic_type_metadata(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll DIType {
     debug!("basic_type_metadata: {:?}", t);
 
     let (name, encoding) = match t.sty {
@@ -766,19 +794,22 @@ fn basic_type_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
     return ty_metadata;
 }
 
-fn foreign_type_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
-                                   t: Ty<'tcx>,
-                                   unique_type_id: UniqueTypeId) -> DIType {
+fn foreign_type_metadata(
+    cx: &CodegenCx<'ll, 'tcx>,
+    t: Ty<'tcx>,
+    unique_type_id: UniqueTypeId,
+) -> &'ll DIType {
     debug!("foreign_type_metadata: {:?}", t);
 
     let name = compute_debuginfo_type_name(cx, t, false);
     create_struct_stub(cx, t, &name, unique_type_id, NO_SCOPE_METADATA)
 }
 
-fn pointer_type_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
-                                   pointer_type: Ty<'tcx>,
-                                   pointee_type_metadata: DIType)
-                                   -> DIType {
+fn pointer_type_metadata(
+    cx: &CodegenCx<'ll, 'tcx>,
+    pointer_type: Ty<'tcx>,
+    pointee_type_metadata: &'ll DIType,
+) -> &'ll DIType {
     let (pointer_size, pointer_align) = cx.size_and_align_of(pointer_type);
     let name = compute_debuginfo_type_name(cx, pointer_type, false);
     let name = CString::new(name).unwrap();
@@ -794,8 +825,8 @@ fn pointer_type_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
 
 pub fn compile_unit_metadata(tcx: TyCtxt,
                              codegen_unit_name: &str,
-                             debug_context: &CrateDebugContext)
-                             -> DIDescriptor {
+                             debug_context: &CrateDebugContext<'ll, '_>)
+                             -> &'ll DIDescriptor {
     let mut name_in_debuginfo = match tcx.sess.local_crate_source_file {
         Some(ref path) => path.clone(),
         None => PathBuf::from(&*tcx.crate_name(LOCAL_CRATE).as_str()),
@@ -860,7 +891,7 @@ pub fn compile_unit_metadata(tcx: TyCtxt,
         return unit_metadata;
     };
 
-    fn path_to_mdstring(llcx: llvm::ContextRef, path: &Path) -> llvm::ValueRef {
+    fn path_to_mdstring(llcx: &'ll llvm::Context, path: &Path) -> &'ll Value {
         let path_str = path2cstr(path);
         unsafe {
             llvm::LLVMMDStringInContext(llcx,
@@ -870,13 +901,13 @@ pub fn compile_unit_metadata(tcx: TyCtxt,
     }
 }
 
-struct MetadataCreationResult {
-    metadata: DIType,
+struct MetadataCreationResult<'ll> {
+    metadata: &'ll DIType,
     already_stored_in_typemap: bool
 }
 
-impl MetadataCreationResult {
-    fn new(metadata: DIType, already_stored_in_typemap: bool) -> MetadataCreationResult {
+impl MetadataCreationResult<'ll> {
+    fn new(metadata: &'ll DIType, already_stored_in_typemap: bool) -> Self {
         MetadataCreationResult {
             metadata,
             already_stored_in_typemap,
@@ -887,9 +918,9 @@ impl MetadataCreationResult {
 // Description of a type member, which can either be a regular field (as in
 // structs or tuples) or an enum variant.
 #[derive(Debug)]
-struct MemberDescription {
+struct MemberDescription<'ll> {
     name: String,
-    type_metadata: DIType,
+    type_metadata: &'ll DIType,
     offset: Size,
     size: Size,
     align: Align,
@@ -900,17 +931,17 @@ struct MemberDescription {
 // for some record-like type. MemberDescriptionFactories are used to defer the
 // creation of type member descriptions in order to break cycles arising from
 // recursive type definitions.
-enum MemberDescriptionFactory<'tcx> {
+enum MemberDescriptionFactory<'ll, 'tcx> {
     StructMDF(StructMemberDescriptionFactory<'tcx>),
     TupleMDF(TupleMemberDescriptionFactory<'tcx>),
-    EnumMDF(EnumMemberDescriptionFactory<'tcx>),
+    EnumMDF(EnumMemberDescriptionFactory<'ll, 'tcx>),
     UnionMDF(UnionMemberDescriptionFactory<'tcx>),
-    VariantMDF(VariantMemberDescriptionFactory<'tcx>)
+    VariantMDF(VariantMemberDescriptionFactory<'ll, 'tcx>)
 }
 
-impl<'tcx> MemberDescriptionFactory<'tcx> {
-    fn create_member_descriptions<'a>(&self, cx: &CodegenCx<'a, 'tcx>)
-                                      -> Vec<MemberDescription> {
+impl MemberDescriptionFactory<'ll, 'tcx> {
+    fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>)
+                                      -> Vec<MemberDescription<'ll>> {
         match *self {
             StructMDF(ref this) => {
                 this.create_member_descriptions(cx)
@@ -943,8 +974,8 @@ struct StructMemberDescriptionFactory<'tcx> {
 }
 
 impl<'tcx> StructMemberDescriptionFactory<'tcx> {
-    fn create_member_descriptions<'a>(&self, cx: &CodegenCx<'a, 'tcx>)
-                                      -> Vec<MemberDescription> {
+    fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>)
+                                      -> Vec<MemberDescription<'ll>> {
         let layout = cx.layout_of(self.ty);
         self.variant.fields.iter().enumerate().map(|(i, f)| {
             let name = if self.variant.ctor_kind == CtorKind::Fn {
@@ -967,11 +998,12 @@ impl<'tcx> StructMemberDescriptionFactory<'tcx> {
 }
 
 
-fn prepare_struct_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
-                                     struct_type: Ty<'tcx>,
-                                     unique_type_id: UniqueTypeId,
-                                     span: Span)
-                                     -> RecursiveTypeDescription<'tcx> {
+fn prepare_struct_metadata(
+    cx: &CodegenCx<'ll, 'tcx>,
+    struct_type: Ty<'tcx>,
+    unique_type_id: UniqueTypeId,
+    span: Span,
+) -> RecursiveTypeDescription<'ll, 'tcx> {
     let struct_name = compute_debuginfo_type_name(cx, struct_type, false);
 
     let (struct_def_id, variant) = match struct_type.sty {
@@ -985,7 +1017,7 @@ fn prepare_struct_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                                                   struct_type,
                                                   &struct_name,
                                                   unique_type_id,
-                                                  containing_scope);
+                                                  Some(containing_scope));
 
     create_and_register_recursive_type_forward_declaration(
         cx,
@@ -1012,8 +1044,8 @@ struct TupleMemberDescriptionFactory<'tcx> {
 }
 
 impl<'tcx> TupleMemberDescriptionFactory<'tcx> {
-    fn create_member_descriptions<'a>(&self, cx: &CodegenCx<'a, 'tcx>)
-                                      -> Vec<MemberDescription> {
+    fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>)
+                                      -> Vec<MemberDescription<'ll>> {
         let layout = cx.layout_of(self.ty);
         self.component_types.iter().enumerate().map(|(i, &component_type)| {
             let (size, align) = cx.size_and_align_of(component_type);
@@ -1029,12 +1061,13 @@ impl<'tcx> TupleMemberDescriptionFactory<'tcx> {
     }
 }
 
-fn prepare_tuple_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
-                                    tuple_type: Ty<'tcx>,
-                                    component_types: &[Ty<'tcx>],
-                                    unique_type_id: UniqueTypeId,
-                                    span: Span)
-                                    -> RecursiveTypeDescription<'tcx> {
+fn prepare_tuple_metadata(
+    cx: &CodegenCx<'ll, 'tcx>,
+    tuple_type: Ty<'tcx>,
+    component_types: &[Ty<'tcx>],
+    unique_type_id: UniqueTypeId,
+    span: Span,
+) -> RecursiveTypeDescription<'ll, 'tcx> {
     let tuple_name = compute_debuginfo_type_name(cx, tuple_type, false);
 
     create_and_register_recursive_type_forward_declaration(
@@ -1065,8 +1098,8 @@ struct UnionMemberDescriptionFactory<'tcx> {
 }
 
 impl<'tcx> UnionMemberDescriptionFactory<'tcx> {
-    fn create_member_descriptions<'a>(&self, cx: &CodegenCx<'a, 'tcx>)
-                                      -> Vec<MemberDescription> {
+    fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>)
+                                      -> Vec<MemberDescription<'ll>> {
         self.variant.fields.iter().enumerate().map(|(i, f)| {
             let field = self.layout.field(cx, i);
             let (size, align) = field.size_and_align();
@@ -1082,11 +1115,12 @@ impl<'tcx> UnionMemberDescriptionFactory<'tcx> {
     }
 }
 
-fn prepare_union_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
-                                    union_type: Ty<'tcx>,
-                                    unique_type_id: UniqueTypeId,
-                                    span: Span)
-                                    -> RecursiveTypeDescription<'tcx> {
+fn prepare_union_metadata(
+    cx: &CodegenCx<'ll, 'tcx>,
+    union_type: Ty<'tcx>,
+    unique_type_id: UniqueTypeId,
+    span: Span,
+) -> RecursiveTypeDescription<'ll, 'tcx> {
     let union_name = compute_debuginfo_type_name(cx, union_type, false);
 
     let (union_def_id, variant) = match union_type.sty {
@@ -1124,17 +1158,17 @@ fn prepare_union_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
 // the members of this union; so for every variant of the given enum, this
 // factory will produce one MemberDescription (all with no name and a fixed
 // offset of zero bytes).
-struct EnumMemberDescriptionFactory<'tcx> {
+struct EnumMemberDescriptionFactory<'ll, 'tcx> {
     enum_type: Ty<'tcx>,
     layout: TyLayout<'tcx>,
-    discriminant_type_metadata: Option<DIType>,
-    containing_scope: DIScope,
+    discriminant_type_metadata: Option<&'ll DIType>,
+    containing_scope: &'ll DIScope,
     span: Span,
 }
 
-impl<'tcx> EnumMemberDescriptionFactory<'tcx> {
-    fn create_member_descriptions<'a>(&self, cx: &CodegenCx<'a, 'tcx>)
-                                      -> Vec<MemberDescription> {
+impl EnumMemberDescriptionFactory<'ll, 'tcx> {
+    fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>)
+                                      -> Vec<MemberDescription<'ll>> {
         let adt = &self.enum_type.ty_adt_def().unwrap();
         match self.layout.variants {
             layout::Variants::Single { .. } if adt.variants.is_empty() => vec![],
@@ -1259,17 +1293,17 @@ impl<'tcx> EnumMemberDescriptionFactory<'tcx> {
 }
 
 // Creates MemberDescriptions for the fields of a single enum variant.
-struct VariantMemberDescriptionFactory<'tcx> {
+struct VariantMemberDescriptionFactory<'ll, 'tcx> {
     // Cloned from the layout::Struct describing the variant.
     offsets: Vec<layout::Size>,
     args: Vec<(String, Ty<'tcx>)>,
-    discriminant_type_metadata: Option<DIType>,
+    discriminant_type_metadata: Option<&'ll DIType>,
     span: Span,
 }
 
-impl<'tcx> VariantMemberDescriptionFactory<'tcx> {
-    fn create_member_descriptions<'a>(&self, cx: &CodegenCx<'a, 'tcx>)
-                                      -> Vec<MemberDescription> {
+impl VariantMemberDescriptionFactory<'ll, 'tcx> {
+    fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>)
+                                      -> Vec<MemberDescription<'ll>> {
         self.args.iter().enumerate().map(|(i, &(ref name, ty))| {
             let (size, align) = cx.size_and_align_of(ty);
             MemberDescription {
@@ -1288,8 +1322,8 @@ impl<'tcx> VariantMemberDescriptionFactory<'tcx> {
 }
 
 #[derive(Copy, Clone)]
-enum EnumDiscriminantInfo {
-    RegularDiscriminant(DIType),
+enum EnumDiscriminantInfo<'ll> {
+    RegularDiscriminant(&'ll DIType),
     OptimizedDiscriminant,
     NoDiscriminant
 }
@@ -1298,13 +1332,14 @@ enum EnumDiscriminantInfo {
 // of the variant, and (3) a MemberDescriptionFactory for producing the
 // descriptions of the fields of the variant. This is a rudimentary version of a
 // full RecursiveTypeDescription.
-fn describe_enum_variant<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
-                                   layout: layout::TyLayout<'tcx>,
-                                   variant: &'tcx ty::VariantDef,
-                                   discriminant_info: EnumDiscriminantInfo,
-                                   containing_scope: DIScope,
-                                   span: Span)
-                                   -> (DICompositeType, MemberDescriptionFactory<'tcx>) {
+fn describe_enum_variant(
+    cx: &CodegenCx<'ll, 'tcx>,
+    layout: layout::TyLayout<'tcx>,
+    variant: &'tcx ty::VariantDef,
+    discriminant_info: EnumDiscriminantInfo<'ll>,
+    containing_scope: &'ll DIScope,
+    span: Span,
+) -> (&'ll DICompositeType, MemberDescriptionFactory<'ll, 'tcx>) {
     let variant_name = variant.name.as_str();
     let unique_type_id = debug_context(cx).type_map
                                           .borrow_mut()
@@ -1317,7 +1352,7 @@ fn describe_enum_variant<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                                            layout.ty,
                                            &variant_name,
                                            unique_type_id,
-                                           containing_scope);
+                                           Some(containing_scope));
 
     // If this is not a univariant enum, there is also the discriminant field.
     let (discr_offset, discr_arg) = match discriminant_info {
@@ -1358,12 +1393,13 @@ fn describe_enum_variant<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
     (metadata_stub, member_description_factory)
 }
 
-fn prepare_enum_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
-                                   enum_type: Ty<'tcx>,
-                                   enum_def_id: DefId,
-                                   unique_type_id: UniqueTypeId,
-                                   span: Span)
-                                   -> RecursiveTypeDescription<'tcx> {
+fn prepare_enum_metadata(
+    cx: &CodegenCx<'ll, 'tcx>,
+    enum_type: Ty<'tcx>,
+    enum_def_id: DefId,
+    unique_type_id: UniqueTypeId,
+    span: Span,
+) -> RecursiveTypeDescription<'ll, 'tcx> {
     let enum_name = compute_debuginfo_type_name(cx, enum_type, false);
 
     let containing_scope = get_namespace_for_item(cx, enum_def_id);
@@ -1376,17 +1412,17 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
     let file_metadata = unknown_file_metadata(cx);
 
     let def = enum_type.ty_adt_def().unwrap();
-    let enumerators_metadata: Vec<DIDescriptor> = def.discriminants(cx.tcx)
+    let enumerators_metadata: Vec<_> = def.discriminants(cx.tcx)
         .zip(&def.variants)
         .map(|(discr, v)| {
             let token = v.name.as_str();
             let name = CString::new(token.as_bytes()).unwrap();
             unsafe {
-                llvm::LLVMRustDIBuilderCreateEnumerator(
+                Some(llvm::LLVMRustDIBuilderCreateEnumerator(
                     DIB(cx),
                     name.as_ptr(),
                     // FIXME: what if enumeration has i128 discriminant?
-                    discr.val as u64)
+                    discr.val as u64))
             }
         })
         .collect();
@@ -1459,7 +1495,7 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
         enum_type_size.bits(),
         enum_type_align.abi_bits() as u32,
         DIFlags::FlagZero,
-        ptr::null_mut(),
+        None,
         0, // RuntimeLang
         unique_type_id_str.as_ptr())
     };
@@ -1489,18 +1525,19 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
 /// results in a LLVM struct.
 ///
 /// Examples of Rust types to use this are: structs, tuples, boxes, vecs, and enums.
-fn composite_type_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
-                                     composite_type: Ty<'tcx>,
-                                     composite_type_name: &str,
-                                     composite_type_unique_id: UniqueTypeId,
-                                     member_descriptions: &[MemberDescription],
-                                     containing_scope: DIScope,
-
-                                     // Ignore source location information as long as it
-                                     // can't be reconstructed for non-local crates.
-                                     _file_metadata: DIFile,
-                                     _definition_span: Span)
-                                     -> DICompositeType {
+fn composite_type_metadata(
+    cx: &CodegenCx<'ll, 'tcx>,
+    composite_type: Ty<'tcx>,
+    composite_type_name: &str,
+    composite_type_unique_id: UniqueTypeId,
+    member_descriptions: &[MemberDescription<'ll>],
+    containing_scope: Option<&'ll DIScope>,
+
+    // Ignore source location information as long as it
+    // can't be reconstructed for non-local crates.
+    _file_metadata: &'ll DIFile,
+    _definition_span: Span,
+) -> &'ll DICompositeType {
     // Create the (empty) struct metadata node ...
     let composite_type_metadata = create_struct_stub(cx,
                                                      composite_type,
@@ -1515,9 +1552,9 @@ fn composite_type_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
     return composite_type_metadata;
 }
 
-fn set_members_of_composite_type(cx: &CodegenCx,
-                                 composite_type_metadata: DICompositeType,
-                                 member_descriptions: &[MemberDescription]) {
+fn set_members_of_composite_type(cx: &CodegenCx<'ll, '_>,
+                                 composite_type_metadata: &'ll DICompositeType,
+                                 member_descriptions: &[MemberDescription<'ll>]) {
     // In some rare cases LLVM metadata uniquing would lead to an existing type
     // description being used instead of a new one created in
     // create_struct_stub. This would cause a hard to trace assertion in
@@ -1535,13 +1572,13 @@ fn set_members_of_composite_type(cx: &CodegenCx,
         }
     }
 
-    let member_metadata: Vec<DIDescriptor> = member_descriptions
+    let member_metadata: Vec<_> = member_descriptions
         .iter()
         .map(|member_description| {
             let member_name = member_description.name.as_bytes();
             let member_name = CString::new(member_name).unwrap();
             unsafe {
-                llvm::LLVMRustDIBuilderCreateMemberType(
+                Some(llvm::LLVMRustDIBuilderCreateMemberType(
                     DIB(cx),
                     composite_type_metadata,
                     member_name.as_ptr(),
@@ -1551,7 +1588,7 @@ fn set_members_of_composite_type(cx: &CodegenCx,
                     member_description.align.abi_bits() as u32,
                     member_description.offset.bits(),
                     member_description.flags,
-                    member_description.type_metadata)
+                    member_description.type_metadata))
             }
         })
         .collect();
@@ -1566,12 +1603,13 @@ fn set_members_of_composite_type(cx: &CodegenCx,
 // A convenience wrapper around LLVMRustDIBuilderCreateStructType(). Does not do
 // any caching, does not add any fields to the struct. This can be done later
 // with set_members_of_composite_type().
-fn create_struct_stub<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
-                                struct_type: Ty<'tcx>,
-                                struct_type_name: &str,
-                                unique_type_id: UniqueTypeId,
-                                containing_scope: DIScope)
-                                -> DICompositeType {
+fn create_struct_stub(
+    cx: &CodegenCx<'ll, 'tcx>,
+    struct_type: Ty<'tcx>,
+    struct_type_name: &str,
+    unique_type_id: UniqueTypeId,
+    containing_scope: Option<&'ll DIScope>,
+) -> &'ll DICompositeType {
     let (struct_size, struct_align) = cx.size_and_align_of(struct_type);
 
     let name = CString::new(struct_type_name).unwrap();
@@ -1593,22 +1631,23 @@ fn create_struct_stub<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
             struct_size.bits(),
             struct_align.abi_bits() as u32,
             DIFlags::FlagZero,
-            ptr::null_mut(),
+            None,
             empty_array,
             0,
-            ptr::null_mut(),
+            None,
             unique_type_id.as_ptr())
     };
 
     return metadata_stub;
 }
 
-fn create_union_stub<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
-                               union_type: Ty<'tcx>,
-                               union_type_name: &str,
-                               unique_type_id: UniqueTypeId,
-                               containing_scope: DIScope)
-                               -> DICompositeType {
+fn create_union_stub(
+    cx: &CodegenCx<'ll, 'tcx>,
+    union_type: Ty<'tcx>,
+    union_type_name: &str,
+    unique_type_id: UniqueTypeId,
+    containing_scope: &'ll DIScope,
+) -> &'ll DICompositeType {
     let (union_size, union_align) = cx.size_and_align_of(union_type);
 
     let name = CString::new(union_type_name).unwrap();
@@ -1630,7 +1669,7 @@ fn create_union_stub<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
             union_size.bits(),
             union_align.abi_bits() as u32,
             DIFlags::FlagZero,
-            empty_array,
+            Some(empty_array),
             0, // RuntimeLang
             unique_type_id.as_ptr())
     };
@@ -1641,9 +1680,11 @@ fn create_union_stub<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
 /// Creates debug information for the given global variable.
 ///
 /// Adds the created metadata nodes directly to the crate's IR.
-pub fn create_global_var_metadata(cx: &CodegenCx,
-                                  def_id: DefId,
-                                  global: ValueRef) {
+pub fn create_global_var_metadata(
+    cx: &CodegenCx<'ll, '_>,
+    def_id: DefId,
+    global: &'ll Value,
+) {
     if cx.dbg_cx.is_none() {
         return;
     }
@@ -1684,7 +1725,7 @@ pub fn create_global_var_metadata(cx: &CodegenCx,
 
     unsafe {
         llvm::LLVMRustDIBuilderCreateStaticVariable(DIB(cx),
-                                                    var_scope,
+                                                    Some(var_scope),
                                                     var_name.as_ptr(),
                                                     // If null, linkage_name field is omitted,
                                                     // which is what we want for no_mangle statics
@@ -1695,18 +1736,19 @@ pub fn create_global_var_metadata(cx: &CodegenCx,
                                                     type_metadata,
                                                     is_local_to_unit,
                                                     global,
-                                                    ptr::null_mut(),
+                                                    None,
                                                     global_align.abi() as u32,
         );
     }
 }
 
 // Creates an "extension" of an existing DIScope into another file.
-pub fn extend_scope_to_file(cx: &CodegenCx,
-                            scope_metadata: DIScope,
-                            file: &syntax_pos::FileMap,
-                            defining_crate: CrateNum)
-                            -> DILexicalBlock {
+pub fn extend_scope_to_file(
+    cx: &CodegenCx<'ll, '_>,
+    scope_metadata: &'ll DIScope,
+    file: &syntax_pos::FileMap,
+    defining_crate: CrateNum,
+) -> &'ll DILexicalBlock {
     let file_metadata = file_metadata(cx, &file.name, defining_crate);
     unsafe {
         llvm::LLVMRustDIBuilderCreateLexicalBlockFile(
@@ -1720,9 +1762,11 @@ pub fn extend_scope_to_file(cx: &CodegenCx,
 /// given type.
 ///
 /// Adds the created metadata nodes directly to the crate's IR.
-pub fn create_vtable_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
-                                        ty: ty::Ty<'tcx>,
-                                        vtable: ValueRef) {
+pub fn create_vtable_metadata(
+    cx: &CodegenCx<'ll, 'tcx>,
+    ty: ty::Ty<'tcx>,
+    vtable: &'ll Value,
+) {
     if cx.dbg_cx.is_none() {
         return;
     }
@@ -1749,10 +1793,10 @@ pub fn create_vtable_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
             Size::ZERO.bits(),
             cx.tcx.data_layout.pointer_align.abi_bits() as u32,
             DIFlags::FlagArtificial,
-            ptr::null_mut(),
+            None,
             empty_array,
             0,
-            type_metadata,
+            Some(type_metadata),
             name.as_ptr()
         );
 
@@ -1771,7 +1815,7 @@ pub fn create_vtable_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                                                     vtable_type,
                                                     true,
                                                     vtable,
-                                                    ptr::null_mut(),
+                                                    None,
                                                     0);
     }
 }
diff --git a/src/librustc_codegen_llvm/debuginfo/mod.rs b/src/librustc_codegen_llvm/debuginfo/mod.rs
index 9671db75baf..143b122a5a1 100644
--- a/src/librustc_codegen_llvm/debuginfo/mod.rs
+++ b/src/librustc_codegen_llvm/debuginfo/mod.rs
@@ -21,8 +21,7 @@ use self::metadata::{type_metadata, file_metadata, TypeMap};
 use self::source_loc::InternalDebugLocation::{self, UnknownLocation};
 
 use llvm;
-use llvm::{ModuleRef, ContextRef, ValueRef};
-use llvm::debuginfo::{DIFile, DIType, DIScope, DIBuilderRef, DISubprogram, DIArray, DIFlags};
+use llvm::debuginfo::{DIFile, DIType, DIScope, DIBuilder, DISubprogram, DIArray, DIFlags};
 use rustc::hir::CodegenFnAttrFlags;
 use rustc::hir::def_id::{DefId, CrateNum};
 use rustc::ty::subst::{Substs, UnpackedKind};
@@ -35,11 +34,11 @@ use rustc::ty::{self, ParamEnv, Ty, InstanceDef};
 use rustc::mir;
 use rustc::session::config::{self, FullDebugInfo, LimitedDebugInfo, NoDebugInfo};
 use rustc::util::nodemap::{DefIdMap, FxHashMap, FxHashSet};
+use value::Value;
 
 use libc::c_uint;
 use std::cell::{Cell, RefCell};
 use std::ffi::CString;
-use std::ptr;
 
 use syntax_pos::{self, Span, Pos};
 use syntax::ast;
@@ -67,23 +66,31 @@ const DW_TAG_auto_variable: c_uint = 0x100;
 const DW_TAG_arg_variable: c_uint = 0x101;
 
 /// A context object for maintaining all state needed by the debuginfo module.
-pub struct CrateDebugContext<'tcx> {
-    llcontext: ContextRef,
-    llmod: ModuleRef,
-    builder: DIBuilderRef,
-    created_files: RefCell<FxHashMap<(Symbol, Symbol), DIFile>>,
-    created_enum_disr_types: RefCell<FxHashMap<(DefId, layout::Primitive), DIType>>,
+pub struct CrateDebugContext<'a, 'tcx> {
+    llcontext: &'a llvm::Context,
+    llmod: &'a llvm::Module,
+    builder: &'a mut DIBuilder<'a>,
+    created_files: RefCell<FxHashMap<(Symbol, Symbol), &'a DIFile>>,
+    created_enum_disr_types: RefCell<FxHashMap<(DefId, layout::Primitive), &'a DIType>>,
 
-    type_map: RefCell<TypeMap<'tcx>>,
-    namespace_map: RefCell<DefIdMap<DIScope>>,
+    type_map: RefCell<TypeMap<'a, 'tcx>>,
+    namespace_map: RefCell<DefIdMap<&'a DIScope>>,
 
     // This collection is used to assert that composite types (structs, enums,
     // ...) have their members only set once:
-    composite_types_completed: RefCell<FxHashSet<DIType>>,
+    composite_types_completed: RefCell<FxHashSet<&'a DIType>>,
 }
 
-impl<'tcx> CrateDebugContext<'tcx> {
-    pub fn new(llmod: ModuleRef) -> CrateDebugContext<'tcx> {
+impl Drop for CrateDebugContext<'a, 'tcx> {
+    fn drop(&mut self) {
+        unsafe {
+            llvm::LLVMRustDIBuilderDispose(&mut *(self.builder as *mut _));
+        }
+    }
+}
+
+impl<'a, 'tcx> CrateDebugContext<'a, 'tcx> {
+    pub fn new(llmod: &'a llvm::Module) -> Self {
         debug!("CrateDebugContext::new");
         let builder = unsafe { llvm::LLVMRustDIBuilderCreate(llmod) };
         // DIBuilder inherits context from the module, so we'd better use the same one
@@ -101,14 +108,14 @@ impl<'tcx> CrateDebugContext<'tcx> {
     }
 }
 
-pub enum FunctionDebugContext {
-    RegularContext(FunctionDebugContextData),
+pub enum FunctionDebugContext<'ll> {
+    RegularContext(FunctionDebugContextData<'ll>),
     DebugInfoDisabled,
     FunctionWithoutDebugInfo,
 }
 
-impl FunctionDebugContext {
-    pub fn get_ref<'a>(&'a self, span: Span) -> &'a FunctionDebugContextData {
+impl FunctionDebugContext<'ll> {
+    pub fn get_ref<'a>(&'a self, span: Span) -> &'a FunctionDebugContextData<'ll> {
         match *self {
             FunctionDebugContext::RegularContext(ref data) => data,
             FunctionDebugContext::DebugInfoDisabled => {
@@ -130,18 +137,18 @@ impl FunctionDebugContext {
     }
 }
 
-pub struct FunctionDebugContextData {
-    fn_metadata: DISubprogram,
+pub struct FunctionDebugContextData<'ll> {
+    fn_metadata: &'ll DISubprogram,
     source_locations_enabled: Cell<bool>,
     pub defining_crate: CrateNum,
 }
 
-pub enum VariableAccess<'a> {
+pub enum VariableAccess<'a, 'll> {
     // The llptr given is an alloca containing the variable's value
-    DirectVariable { alloca: ValueRef },
+    DirectVariable { alloca: &'ll Value },
     // The llptr given is an alloca containing the start of some pointer chain
     // leading to the variable's content.
-    IndirectVariable { alloca: ValueRef, address_operations: &'a [i64] }
+    IndirectVariable { alloca: &'ll Value, address_operations: &'a [i64] }
 }
 
 pub enum VariableKind {
@@ -167,7 +174,6 @@ pub fn finalize(cx: &CodegenCx) {
 
     unsafe {
         llvm::LLVMRustDIBuilderFinalize(DIB(cx));
-        llvm::LLVMRustDIBuilderDispose(DIB(cx));
         // Debuginfo generation in LLVM by default uses a higher
         // version of dwarf than macOS currently understands. We can
         // instruct LLVM to emit an older version of dwarf, however,
@@ -201,11 +207,13 @@ pub fn finalize(cx: &CodegenCx) {
 /// for debug info creation. The function may also return another variant of the
 /// FunctionDebugContext enum which indicates why no debuginfo should be created
 /// for the function.
-pub fn create_function_debug_context<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
-                                               instance: Instance<'tcx>,
-                                               sig: ty::FnSig<'tcx>,
-                                               llfn: ValueRef,
-                                               mir: &mir::Mir) -> FunctionDebugContext {
+pub fn create_function_debug_context(
+    cx: &CodegenCx<'ll, 'tcx>,
+    instance: Instance<'tcx>,
+    sig: ty::FnSig<'tcx>,
+    llfn: &'ll Value,
+    mir: &mir::Mir,
+) -> FunctionDebugContext<'ll> {
     if cx.sess().opts.debuginfo == NoDebugInfo {
         return FunctionDebugContext::DebugInfoDisabled;
     }
@@ -290,7 +298,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
             cx.sess().opts.optimize != config::OptLevel::No,
             llfn,
             template_parameters,
-            ptr::null_mut())
+            None)
     };
 
     // Initialize fn debug context (including scope map and namespace map)
@@ -302,8 +310,10 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
 
     return FunctionDebugContext::RegularContext(fn_debug_context);
 
-    fn get_function_signature<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
-                                        sig: ty::FnSig<'tcx>) -> DIArray {
+    fn get_function_signature(
+        cx: &CodegenCx<'ll, 'tcx>,
+        sig: ty::FnSig<'tcx>,
+    ) -> &'ll DIArray {
         if cx.sess().opts.debuginfo == LimitedDebugInfo {
             return create_DIArray(DIB(cx), &[]);
         }
@@ -312,8 +322,8 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
 
         // Return type -- llvm::DIBuilder wants this at index 0
         signature.push(match sig.output().sty {
-            ty::TyTuple(ref tys) if tys.is_empty() => ptr::null_mut(),
-            _ => type_metadata(cx, sig.output(), syntax_pos::DUMMY_SP)
+            ty::TyTuple(ref tys) if tys.is_empty() => None,
+            _ => Some(type_metadata(cx, sig.output(), syntax_pos::DUMMY_SP))
         });
 
         let inputs = if sig.abi == Abi::RustCall {
@@ -342,19 +352,20 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                     }
                     _ => t
                 };
-                type_metadata(cx, t, syntax_pos::DUMMY_SP)
+                Some(type_metadata(cx, t, syntax_pos::DUMMY_SP))
             }));
         } else {
             signature.extend(inputs.iter().map(|t| {
-                type_metadata(cx, t, syntax_pos::DUMMY_SP)
+                Some(type_metadata(cx, t, syntax_pos::DUMMY_SP))
             }));
         }
 
         if sig.abi == Abi::RustCall && !sig.inputs().is_empty() {
             if let ty::TyTuple(args) = sig.inputs()[sig.inputs().len() - 1].sty {
                 signature.extend(
-                    args.iter().map(|argument_type|
-                        type_metadata(cx, argument_type, syntax_pos::DUMMY_SP))
+                    args.iter().map(|argument_type| {
+                        Some(type_metadata(cx, argument_type, syntax_pos::DUMMY_SP))
+                    })
                 );
             }
         }
@@ -362,13 +373,13 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
         return create_DIArray(DIB(cx), &signature[..]);
     }
 
-    fn get_template_parameters<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
-                                         generics: &ty::Generics,
-                                         substs: &Substs<'tcx>,
-                                         file_metadata: DIFile,
-                                         name_to_append_suffix_to: &mut String)
-                                         -> DIArray
-    {
+    fn get_template_parameters(
+        cx: &CodegenCx<'ll, 'tcx>,
+        generics: &ty::Generics,
+        substs: &Substs<'tcx>,
+        file_metadata: &'ll DIFile,
+        name_to_append_suffix_to: &mut String,
+    ) -> &'ll DIArray {
         if substs.types().next().is_none() {
             return create_DIArray(DIB(cx), &[]);
         }
@@ -398,14 +409,15 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                         type_metadata(cx, actual_type, syntax_pos::DUMMY_SP);
                     let name = CString::new(name.as_str().as_bytes()).unwrap();
                     Some(unsafe {
-                        llvm::LLVMRustDIBuilderCreateTemplateTypeParameter(
+                        Some(llvm::LLVMRustDIBuilderCreateTemplateTypeParameter(
                             DIB(cx),
-                            ptr::null_mut(),
+                            None,
                             name.as_ptr(),
                             actual_type_metadata,
                             file_metadata,
                             0,
-                            0)
+                            0,
+                        ))
                     })
                 } else {
                     None
@@ -428,9 +440,10 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
         names
     }
 
-    fn get_containing_scope<'cx, 'tcx>(cx: &CodegenCx<'cx, 'tcx>,
-                                        instance: Instance<'tcx>)
-                                        -> DIScope {
+    fn get_containing_scope(
+        cx: &CodegenCx<'ll, 'tcx>,
+        instance: Instance<'tcx>,
+    ) -> &'ll DIScope {
         // First, let's see if this is a method within an inherent impl. Because
         // if yes, we want to make the result subroutine DIE a child of the
         // subroutine's self-type.
@@ -470,14 +483,16 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
     }
 }
 
-pub fn declare_local<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
-                               dbg_context: &FunctionDebugContext,
-                               variable_name: ast::Name,
-                               variable_type: Ty<'tcx>,
-                               scope_metadata: DIScope,
-                               variable_access: VariableAccess,
-                               variable_kind: VariableKind,
-                               span: Span) {
+pub fn declare_local(
+    bx: &Builder<'a, 'll, 'tcx>,
+    dbg_context: &FunctionDebugContext<'ll>,
+    variable_name: ast::Name,
+    variable_type: Ty<'tcx>,
+    scope_metadata: &'ll DIScope,
+    variable_access: VariableAccess<'_, 'll>,
+    variable_kind: VariableKind,
+    span: Span,
+) {
     assert!(!dbg_context.get_ref(span).source_locations_enabled.get());
     let cx = bx.cx;
 
diff --git a/src/librustc_codegen_llvm/debuginfo/namespace.rs b/src/librustc_codegen_llvm/debuginfo/namespace.rs
index 51c45de9dc2..9f1141a7e7d 100644
--- a/src/librustc_codegen_llvm/debuginfo/namespace.rs
+++ b/src/librustc_codegen_llvm/debuginfo/namespace.rs
@@ -22,7 +22,6 @@ use rustc::hir::map::DefPathData;
 use common::CodegenCx;
 
 use std::ffi::CString;
-use std::ptr;
 
 pub fn mangled_name_of_instance<'a, 'tcx>(
     cx: &CodegenCx<'a, 'tcx>,
@@ -32,13 +31,13 @@ pub fn mangled_name_of_instance<'a, 'tcx>(
      tcx.symbol_name(instance)
 }
 
-pub fn item_namespace(cx: &CodegenCx, def_id: DefId) -> DIScope {
+pub fn item_namespace(cx: &CodegenCx<'ll, '_>, def_id: DefId) -> &'ll DIScope {
     if let Some(&scope) = debug_context(cx).namespace_map.borrow().get(&def_id) {
         return scope;
     }
 
     let def_key = cx.tcx.def_key(def_id);
-    let parent_scope = def_key.parent.map_or(ptr::null_mut(), |parent| {
+    let parent_scope = def_key.parent.map(|parent| {
         item_namespace(cx, DefId {
             krate: def_id.krate,
             index: parent
diff --git a/src/librustc_codegen_llvm/debuginfo/source_loc.rs b/src/librustc_codegen_llvm/debuginfo/source_loc.rs
index 958d09413ed..55cf1393943 100644
--- a/src/librustc_codegen_llvm/debuginfo/source_loc.rs
+++ b/src/librustc_codegen_llvm/debuginfo/source_loc.rs
@@ -19,14 +19,16 @@ use llvm::debuginfo::DIScope;
 use builder::Builder;
 
 use libc::c_uint;
-use std::ptr;
 use syntax_pos::{Span, Pos};
 
 /// Sets the current debug location at the beginning of the span.
 ///
 /// Maps to a call to llvm::LLVMSetCurrentDebugLocation(...).
 pub fn set_source_location(
-    debug_context: &FunctionDebugContext, bx: &Builder, scope: DIScope, span: Span
+    debug_context: &FunctionDebugContext<'ll>,
+    bx: &Builder<'_, 'll, '_>,
+    scope: Option<&'ll DIScope>,
+    span: Span,
 ) {
     let function_debug_context = match *debug_context {
         FunctionDebugContext::DebugInfoDisabled => return,
@@ -40,7 +42,7 @@ pub fn set_source_location(
     let dbg_loc = if function_debug_context.source_locations_enabled.get() {
         debug!("set_source_location: {}", bx.sess().codemap().span_to_string(span));
         let loc = span_start(bx.cx, span);
-        InternalDebugLocation::new(scope, loc.line, loc.col.to_usize())
+        InternalDebugLocation::new(scope.unwrap(), loc.line, loc.col.to_usize())
     } else {
         UnknownLocation
     };
@@ -53,7 +55,7 @@ pub fn set_source_location(
 /// they are disabled when beginning to codegen a new function. This functions
 /// switches source location emitting on and must therefore be called before the
 /// first real statement/expression of the function is codegened.
-pub fn start_emitting_source_locations(dbg_context: &FunctionDebugContext) {
+pub fn start_emitting_source_locations(dbg_context: &FunctionDebugContext<'ll>) {
     match *dbg_context {
         FunctionDebugContext::RegularContext(ref data) => {
             data.source_locations_enabled.set(true)
@@ -64,13 +66,13 @@ pub fn start_emitting_source_locations(dbg_context: &FunctionDebugContext) {
 
 
 #[derive(Copy, Clone, PartialEq)]
-pub enum InternalDebugLocation {
-    KnownLocation { scope: DIScope, line: usize, col: usize },
+pub enum InternalDebugLocation<'ll> {
+    KnownLocation { scope: &'ll DIScope, line: usize, col: usize },
     UnknownLocation
 }
 
-impl InternalDebugLocation {
-    pub fn new(scope: DIScope, line: usize, col: usize) -> InternalDebugLocation {
+impl InternalDebugLocation<'ll> {
+    pub fn new(scope: &'ll DIScope, line: usize, col: usize) -> Self {
         KnownLocation {
             scope,
             line,
@@ -79,7 +81,7 @@ impl InternalDebugLocation {
     }
 }
 
-pub fn set_debug_location(bx: &Builder, debug_location: InternalDebugLocation) {
+pub fn set_debug_location(bx: &Builder<'_, 'll, '_>, debug_location: InternalDebugLocation<'ll>) {
     let metadata_node = match debug_location {
         KnownLocation { scope, line, col } => {
             // For MSVC, set the column number to zero.
@@ -93,17 +95,17 @@ pub fn set_debug_location(bx: &Builder, debug_location: InternalDebugLocation) {
             debug!("setting debug location to {} {}", line, col);
 
             unsafe {
-                llvm::LLVMRustDIBuilderCreateDebugLocation(
+                Some(llvm::LLVMRustDIBuilderCreateDebugLocation(
                     debug_context(bx.cx).llcontext,
                     line as c_uint,
                     col_used,
                     scope,
-                    ptr::null_mut())
+                    None))
             }
         }
         UnknownLocation => {
             debug!("clearing debug location ");
-            ptr::null_mut()
+            None
         }
     };
 
diff --git a/src/librustc_codegen_llvm/debuginfo/utils.rs b/src/librustc_codegen_llvm/debuginfo/utils.rs
index 9d37f99cb2a..9f4a555082a 100644
--- a/src/librustc_codegen_llvm/debuginfo/utils.rs
+++ b/src/librustc_codegen_llvm/debuginfo/utils.rs
@@ -17,7 +17,7 @@ use rustc::hir::def_id::DefId;
 use rustc::ty::DefIdTree;
 
 use llvm;
-use llvm::debuginfo::{DIScope, DIBuilderRef, DIDescriptor, DIArray};
+use llvm::debuginfo::{DIScope, DIBuilder, DIDescriptor, DIArray};
 use common::{CodegenCx};
 
 use syntax_pos::{self, Span};
@@ -36,7 +36,10 @@ pub fn is_node_local_to_unit(cx: &CodegenCx, def_id: DefId) -> bool
 }
 
 #[allow(non_snake_case)]
-pub fn create_DIArray(builder: DIBuilderRef, arr: &[DIDescriptor]) -> DIArray {
+pub fn create_DIArray(
+    builder: &DIBuilder<'ll>,
+    arr: &[Option<&'ll DIDescriptor>],
+) -> &'ll DIArray {
     return unsafe {
         llvm::LLVMRustDIBuilderGetOrCreateArray(builder, arr.as_ptr(), arr.len() as u32)
     };
@@ -48,18 +51,17 @@ pub fn span_start(cx: &CodegenCx, span: Span) -> syntax_pos::Loc {
 }
 
 #[inline]
-pub fn debug_context<'a, 'tcx>(cx: &'a CodegenCx<'a, 'tcx>)
-                           -> &'a CrateDebugContext<'tcx> {
+pub fn debug_context(cx: &'a CodegenCx<'ll, 'tcx>) -> &'a CrateDebugContext<'ll, 'tcx> {
     cx.dbg_cx.as_ref().unwrap()
 }
 
 #[inline]
 #[allow(non_snake_case)]
-pub fn DIB(cx: &CodegenCx) -> DIBuilderRef {
+pub fn DIB(cx: &'a CodegenCx<'ll, '_>) -> &'a DIBuilder<'ll> {
     cx.dbg_cx.as_ref().unwrap().builder
 }
 
-pub fn get_namespace_for_item(cx: &CodegenCx, def_id: DefId) -> DIScope {
+pub fn get_namespace_for_item(cx: &CodegenCx<'ll, '_>, def_id: DefId) -> &'ll DIScope {
     item_namespace(cx, cx.tcx.parent(def_id)
         .expect("get_namespace_for_item: missing parent?"))
 }
diff --git a/src/librustc_codegen_llvm/declare.rs b/src/librustc_codegen_llvm/declare.rs
index fdc84f914f5..9812d7f9a41 100644
--- a/src/librustc_codegen_llvm/declare.rs
+++ b/src/librustc_codegen_llvm/declare.rs
@@ -16,11 +16,11 @@
 //! Some useful guidelines:
 //!
 //! * Use declare_* family of methods if you are declaring, but are not
-//!   interested in defining the ValueRef they return.
-//! * Use define_* family of methods when you might be defining the ValueRef.
+//!   interested in defining the Value they return.
+//! * Use define_* family of methods when you might be defining the Value.
 //! * When in doubt, define.
 
-use llvm::{self, ValueRef};
+use llvm;
 use llvm::AttributePlace::Function;
 use rustc::ty::{self, Ty};
 use rustc::ty::layout::{self, LayoutOf};
@@ -39,14 +39,14 @@ use std::ffi::CString;
 /// Declare a global value.
 ///
 /// If there’s a value with the same name already declared, the function will
-/// return its ValueRef instead.
-pub fn declare_global(cx: &CodegenCx, name: &str, ty: Type) -> llvm::ValueRef {
+/// return its Value instead.
+pub fn declare_global(cx: &CodegenCx<'ll, '_>, name: &str, ty: &'ll Type) -> &'ll Value {
     debug!("declare_global(name={:?})", name);
     let namebuf = CString::new(name).unwrap_or_else(|_|{
         bug!("name {:?} contains an interior null byte", name)
     });
     unsafe {
-        llvm::LLVMRustGetOrInsertGlobal(cx.llmod, namebuf.as_ptr(), ty.to_ref())
+        llvm::LLVMRustGetOrInsertGlobal(cx.llmod, namebuf.as_ptr(), ty)
     }
 }
 
@@ -54,14 +54,19 @@ pub fn declare_global(cx: &CodegenCx, name: &str, ty: Type) -> llvm::ValueRef {
 /// Declare a function.
 ///
 /// If there’s a value with the same name already declared, the function will
-/// update the declaration and return existing ValueRef instead.
-fn declare_raw_fn(cx: &CodegenCx, name: &str, callconv: llvm::CallConv, ty: Type) -> ValueRef {
+/// update the declaration and return existing Value instead.
+fn declare_raw_fn(
+    cx: &CodegenCx<'ll, '_>,
+    name: &str,
+    callconv: llvm::CallConv,
+    ty: &'ll Type,
+) -> &'ll Value {
     debug!("declare_raw_fn(name={:?}, ty={:?})", name, ty);
     let namebuf = CString::new(name).unwrap_or_else(|_|{
         bug!("name {:?} contains an interior null byte", name)
     });
     let llfn = unsafe {
-        llvm::LLVMRustGetOrInsertFunction(cx.llmod, namebuf.as_ptr(), ty.to_ref())
+        llvm::LLVMRustGetOrInsertFunction(cx.llmod, namebuf.as_ptr(), ty)
     };
 
     llvm::SetFunctionCallConv(llfn, callconv);
@@ -114,8 +119,8 @@ fn declare_raw_fn(cx: &CodegenCx, name: &str, callconv: llvm::CallConv, ty: Type
 /// `declare_fn` instead.
 ///
 /// If there’s a value with the same name already declared, the function will
-/// update the declaration and return existing ValueRef instead.
-pub fn declare_cfn(cx: &CodegenCx, name: &str, fn_type: Type) -> ValueRef {
+/// update the declaration and return existing Value instead.
+pub fn declare_cfn(cx: &CodegenCx<'ll, '_>, name: &str, fn_type: &'ll Type) -> &'ll Value {
     declare_raw_fn(cx, name, llvm::CCallConv, fn_type)
 }
 
@@ -123,9 +128,12 @@ pub fn declare_cfn(cx: &CodegenCx, name: &str, fn_type: Type) -> ValueRef {
 /// Declare a Rust function.
 ///
 /// If there’s a value with the same name already declared, the function will
-/// update the declaration and return existing ValueRef instead.
-pub fn declare_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, name: &str,
-                            fn_type: Ty<'tcx>) -> ValueRef {
+/// update the declaration and return existing Value instead.
+pub fn declare_fn(
+    cx: &CodegenCx<'ll, 'tcx>,
+    name: &str,
+    fn_type: Ty<'tcx>,
+) -> &'ll Value {
     debug!("declare_rust_fn(name={:?}, fn_type={:?})", name, fn_type);
     let sig = common::ty_fn_sig(cx, fn_type);
     let sig = cx.tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig);
@@ -154,7 +162,7 @@ pub fn declare_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, name: &str,
 /// return None if the name already has a definition associated with it. In that
 /// case an error should be reported to the user, because it usually happens due
 /// to user’s fault (e.g. misuse of #[no_mangle] or #[export_name] attributes).
-pub fn define_global(cx: &CodegenCx, name: &str, ty: Type) -> Option<ValueRef> {
+pub fn define_global(cx: &CodegenCx<'ll, '_>, name: &str, ty: &'ll Type) -> Option<&'ll Value> {
     if get_defined_value(cx, name).is_some() {
         None
     } else {
@@ -167,9 +175,11 @@ pub fn define_global(cx: &CodegenCx, name: &str, ty: Type) -> Option<ValueRef> {
 /// Use this function when you intend to define a function. This function will
 /// return panic if the name already has a definition associated with it. This
 /// can happen with #[no_mangle] or #[export_name], for example.
-pub fn define_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
-                           name: &str,
-                           fn_type: Ty<'tcx>) -> ValueRef {
+pub fn define_fn(
+    cx: &CodegenCx<'ll, 'tcx>,
+    name: &str,
+    fn_type: Ty<'tcx>,
+) -> &'ll Value {
     if get_defined_value(cx, name).is_some() {
         cx.sess().fatal(&format!("symbol `{}` already defined", name))
     } else {
@@ -182,9 +192,11 @@ pub fn define_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
 /// Use this function when you intend to define a function. This function will
 /// return panic if the name already has a definition associated with it. This
 /// can happen with #[no_mangle] or #[export_name], for example.
-pub fn define_internal_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
-                                    name: &str,
-                                    fn_type: Ty<'tcx>) -> ValueRef {
+pub fn define_internal_fn(
+    cx: &CodegenCx<'ll, 'tcx>,
+    name: &str,
+    fn_type: Ty<'tcx>,
+) -> &'ll Value {
     let llfn = define_fn(cx, name, fn_type);
     unsafe { llvm::LLVMRustSetLinkage(llfn, llvm::Linkage::InternalLinkage) };
     llfn
@@ -192,24 +204,17 @@ pub fn define_internal_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
 
 
 /// Get declared value by name.
-pub fn get_declared_value(cx: &CodegenCx, name: &str) -> Option<ValueRef> {
+pub fn get_declared_value(cx: &CodegenCx<'ll, '_>, name: &str) -> Option<&'ll Value> {
     debug!("get_declared_value(name={:?})", name);
     let namebuf = CString::new(name).unwrap_or_else(|_|{
         bug!("name {:?} contains an interior null byte", name)
     });
-    let val = unsafe { llvm::LLVMRustGetNamedValue(cx.llmod, namebuf.as_ptr()) };
-    if val.is_null() {
-        debug!("get_declared_value: {:?} value is null", name);
-        None
-    } else {
-        debug!("get_declared_value: {:?} => {:?}", name, Value(val));
-        Some(val)
-    }
+    unsafe { llvm::LLVMRustGetNamedValue(cx.llmod, namebuf.as_ptr()) }
 }
 
 /// Get defined or externally defined (AvailableExternally linkage) value by
 /// name.
-pub fn get_defined_value(cx: &CodegenCx, name: &str) -> Option<ValueRef> {
+pub fn get_defined_value(cx: &CodegenCx<'ll, '_>, name: &str) -> Option<&'ll Value> {
     get_declared_value(cx, name).and_then(|val|{
         let declaration = unsafe {
             llvm::LLVMIsDeclaration(val) != 0
diff --git a/src/librustc_codegen_llvm/glue.rs b/src/librustc_codegen_llvm/glue.rs
index c7275d09401..37ce51da778 100644
--- a/src/librustc_codegen_llvm/glue.rs
+++ b/src/librustc_codegen_llvm/glue.rs
@@ -16,37 +16,36 @@ use std;
 
 use builder::Builder;
 use common::*;
-use llvm::{ValueRef};
 use llvm;
 use meth;
 use rustc::ty::layout::LayoutOf;
 use rustc::ty::{self, Ty};
 use value::Value;
 
-pub fn size_and_align_of_dst<'a, 'tcx>(bx: &Builder<'a, 'tcx>, t: Ty<'tcx>, info: ValueRef)
-                                       -> (ValueRef, ValueRef) {
+pub fn size_and_align_of_dst(bx: &Builder<'_, 'll, 'tcx>, t: Ty<'tcx>, info: Option<&'ll Value>)
+                                       -> (&'ll Value, &'ll Value) {
     debug!("calculate size of DST: {}; with lost info: {:?}",
-           t, Value(info));
+           t, info);
     if bx.cx.type_is_sized(t) {
         let (size, align) = bx.cx.size_and_align_of(t);
         debug!("size_and_align_of_dst t={} info={:?} size: {:?} align: {:?}",
-               t, Value(info), size, align);
+               t, info, size, align);
         let size = C_usize(bx.cx, size.bytes());
         let align = C_usize(bx.cx, align.abi());
         return (size, align);
     }
-    assert!(!info.is_null());
     match t.sty {
         ty::TyDynamic(..) => {
             // load size/align from vtable
-            (meth::SIZE.get_usize(bx, info), meth::ALIGN.get_usize(bx, info))
+            let vtable = info.unwrap();
+            (meth::SIZE.get_usize(bx, vtable), meth::ALIGN.get_usize(bx, vtable))
         }
         ty::TySlice(_) | ty::TyStr => {
             let unit = t.sequence_element_type(bx.tcx());
             // The info in this case is the length of the str, so the size is that
             // times the unit size.
             let (size, align) = bx.cx.size_and_align_of(unit);
-            (bx.mul(info, C_usize(bx.cx, size.bytes())),
+            (bx.mul(info.unwrap(), C_usize(bx.cx, size.bytes())),
              C_usize(bx.cx, align.abi()))
         }
         _ => {
diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs
index 9c5c0f730c1..06a5c34a4ca 100644
--- a/src/librustc_codegen_llvm/intrinsic.rs
+++ b/src/librustc_codegen_llvm/intrinsic.rs
@@ -11,8 +11,7 @@
 #![allow(non_upper_case_globals)]
 
 use intrinsics::{self, Intrinsic};
-use llvm;
-use llvm::{ValueRef};
+use llvm::{self, TypeKind};
 use abi::{Abi, FnType, LlvmType, PassMode};
 use mir::place::PlaceRef;
 use mir::operand::{OperandRef, OperandValue};
@@ -28,6 +27,7 @@ use rustc::hir;
 use syntax::ast;
 use syntax::symbol::Symbol;
 use builder::Builder;
+use value::Value;
 
 use rustc::session::Session;
 use syntax_pos::Span;
@@ -35,7 +35,7 @@ use syntax_pos::Span;
 use std::cmp::Ordering;
 use std::iter;
 
-fn get_simple_intrinsic(cx: &CodegenCx, name: &str) -> Option<ValueRef> {
+fn get_simple_intrinsic(cx: &CodegenCx<'ll, '_>, name: &str) -> Option<&'ll Value> {
     let llvm_name = match name {
         "sqrtf32" => "llvm.sqrt.f32",
         "sqrtf64" => "llvm.sqrt.f64",
@@ -85,12 +85,14 @@ fn get_simple_intrinsic(cx: &CodegenCx, name: &str) -> Option<ValueRef> {
 /// Remember to add all intrinsics here, in librustc_typeck/check/mod.rs,
 /// and in libcore/intrinsics.rs; if you need access to any llvm intrinsics,
 /// add them to librustc_codegen_llvm/context.rs
-pub fn codegen_intrinsic_call<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
-                                      callee_ty: Ty<'tcx>,
-                                      fn_ty: &FnType<'tcx, Ty<'tcx>>,
-                                      args: &[OperandRef<'tcx>],
-                                      llresult: ValueRef,
-                                      span: Span) {
+pub fn codegen_intrinsic_call(
+    bx: &Builder<'a, 'll, 'tcx>,
+    callee_ty: Ty<'tcx>,
+    fn_ty: &FnType<'tcx, Ty<'tcx>>,
+    args: &[OperandRef<'ll, 'tcx>],
+    llresult: &'ll Value,
+    span: Span,
+) {
     let cx = bx.cx;
     let tcx = cx.tcx;
 
@@ -146,7 +148,7 @@ pub fn codegen_intrinsic_call<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
             let tp_ty = substs.type_at(0);
             if let OperandValue::Pair(_, meta) = args[0].val {
                 let (llsize, _) =
-                    glue::size_and_align_of_dst(bx, tp_ty, meta);
+                    glue::size_and_align_of_dst(bx, tp_ty, Some(meta));
                 llsize
             } else {
                 C_usize(cx, cx.size_of(tp_ty).bytes())
@@ -160,7 +162,7 @@ pub fn codegen_intrinsic_call<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
             let tp_ty = substs.type_at(0);
             if let OperandValue::Pair(_, meta) = args[0].val {
                 let (_, llalign) =
-                    glue::size_and_align_of_dst(bx, tp_ty, meta);
+                    glue::size_and_align_of_dst(bx, tp_ty, Some(meta));
                 llalign
             } else {
                 C_usize(cx, cx.align_of(tp_ty).abi())
@@ -545,7 +547,7 @@ pub fn codegen_intrinsic_call<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
                 assert_eq!(x.len(), 1);
                 x.into_iter().next().unwrap()
             }
-            fn ty_to_type(cx: &CodegenCx, t: &intrinsics::Type) -> Vec<Type> {
+            fn ty_to_type(cx: &CodegenCx<'ll, '_>, t: &intrinsics::Type) -> Vec<&'ll Type> {
                 use intrinsics::Type::*;
                 match *t {
                     Void => vec![Type::void(cx)],
@@ -567,7 +569,7 @@ pub fn codegen_intrinsic_call<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
                     Vector(ref t, ref llvm_elem, length) => {
                         let t = llvm_elem.as_ref().unwrap_or(t);
                         let elem = one(ty_to_type(cx, t));
-                        vec![Type::vector(&elem, length as u64)]
+                        vec![Type::vector(elem, length as u64)]
                     }
                     Aggregate(false, ref contents) => {
                         let elems = contents.iter()
@@ -587,11 +589,11 @@ pub fn codegen_intrinsic_call<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
             // qux` to be converted into `foo, bar, baz, qux`, integer
             // arguments to be truncated as needed and pointers to be
             // cast.
-            fn modify_as_needed<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
-                                          t: &intrinsics::Type,
-                                          arg: &OperandRef<'tcx>)
-                                          -> Vec<ValueRef>
-            {
+            fn modify_as_needed(
+                bx: &Builder<'a, 'll, 'tcx>,
+                t: &intrinsics::Type,
+                arg: &OperandRef<'ll, 'tcx>,
+            ) -> Vec<&'ll Value> {
                 match *t {
                     intrinsics::Type::Aggregate(true, ref contents) => {
                         // We found a tuple that needs squishing! So
@@ -616,7 +618,7 @@ pub fn codegen_intrinsic_call<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
                     }
                     intrinsics::Type::Vector(_, Some(ref llvm_elem), length) => {
                         let llvm_elem = one(ty_to_type(bx.cx, llvm_elem));
-                        vec![bx.bitcast(arg.immediate(), Type::vector(&llvm_elem, length as u64))]
+                        vec![bx.bitcast(arg.immediate(), Type::vector(llvm_elem, length as u64))]
                     }
                     intrinsics::Type::Integer(_, width, llvm_width) if width != llvm_width => {
                         // the LLVM intrinsic uses a smaller integer
@@ -644,7 +646,7 @@ pub fn codegen_intrinsic_call<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
                 intrinsics::IntrinsicDef::Named(name) => {
                     let f = declare::declare_cfn(cx,
                                                  name,
-                                                 Type::func(&inputs, &outputs));
+                                                 Type::func(&inputs, outputs));
                     bx.call(f, &llargs, None)
                 }
             };
@@ -677,14 +679,15 @@ pub fn codegen_intrinsic_call<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
     }
 }
 
-fn copy_intrinsic<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
-                            allow_overlap: bool,
-                            volatile: bool,
-                            ty: Ty<'tcx>,
-                            dst: ValueRef,
-                            src: ValueRef,
-                            count: ValueRef)
-                            -> ValueRef {
+fn copy_intrinsic(
+    bx: &Builder<'a, 'll, 'tcx>,
+    allow_overlap: bool,
+    volatile: bool,
+    ty: Ty<'tcx>,
+    dst: &'ll Value,
+    src: &'ll Value,
+    count: &'ll Value,
+) -> &'ll Value {
     let cx = bx.cx;
     let (size, align) = cx.size_and_align_of(ty);
     let size = C_usize(cx, size.bytes());
@@ -712,14 +715,14 @@ fn copy_intrinsic<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
         None)
 }
 
-fn memset_intrinsic<'a, 'tcx>(
-    bx: &Builder<'a, 'tcx>,
+fn memset_intrinsic(
+    bx: &Builder<'a, 'll, 'tcx>,
     volatile: bool,
     ty: Ty<'tcx>,
-    dst: ValueRef,
-    val: ValueRef,
-    count: ValueRef
-) -> ValueRef {
+    dst: &'ll Value,
+    val: &'ll Value,
+    count: &'ll Value
+) -> &'ll Value {
     let cx = bx.cx;
     let (size, align) = cx.size_and_align_of(ty);
     let size = C_usize(cx, size.bytes());
@@ -728,13 +731,13 @@ fn memset_intrinsic<'a, 'tcx>(
     call_memset(bx, dst, val, bx.mul(size, count), align, volatile)
 }
 
-fn try_intrinsic<'a, 'tcx>(
-    bx: &Builder<'a, 'tcx>,
-    cx: &CodegenCx,
-    func: ValueRef,
-    data: ValueRef,
-    local_ptr: ValueRef,
-    dest: ValueRef,
+fn try_intrinsic(
+    bx: &Builder<'a, 'll, 'tcx>,
+    cx: &CodegenCx<'ll, 'tcx>,
+    func: &'ll Value,
+    data: &'ll Value,
+    local_ptr: &'ll Value,
+    dest: &'ll Value,
 ) {
     if bx.sess().no_landing_pads() {
         bx.call(func, &[data], None);
@@ -754,12 +757,14 @@ fn try_intrinsic<'a, 'tcx>(
 // instructions are meant to work for all targets, as of the time of this
 // writing, however, LLVM does not recommend the usage of these new instructions
 // as the old ones are still more optimized.
-fn codegen_msvc_try<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
-                            cx: &CodegenCx,
-                            func: ValueRef,
-                            data: ValueRef,
-                            local_ptr: ValueRef,
-                            dest: ValueRef) {
+fn codegen_msvc_try(
+    bx: &Builder<'a, 'll, 'tcx>,
+    cx: &CodegenCx<'ll, 'tcx>,
+    func: &'ll Value,
+    data: &'ll Value,
+    local_ptr: &'ll Value,
+    dest: &'ll Value,
+) {
     let llfn = get_rust_try_fn(cx, &mut |bx| {
         let cx = bx.cx;
 
@@ -862,12 +867,14 @@ fn codegen_msvc_try<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
 // function calling it, and that function may already have other personality
 // functions in play. By calling a shim we're guaranteed that our shim will have
 // the right personality function.
-fn codegen_gnu_try<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
-                           cx: &CodegenCx,
-                           func: ValueRef,
-                           data: ValueRef,
-                           local_ptr: ValueRef,
-                           dest: ValueRef) {
+fn codegen_gnu_try(
+    bx: &Builder<'a, 'll, 'tcx>,
+    cx: &CodegenCx<'ll, 'tcx>,
+    func: &'ll Value,
+    data: &'ll Value,
+    local_ptr: &'ll Value,
+    dest: &'ll Value,
+) {
     let llfn = get_rust_try_fn(cx, &mut |bx| {
         let cx = bx.cx;
 
@@ -922,12 +929,13 @@ fn codegen_gnu_try<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
 
 // Helper function to give a Block to a closure to codegen a shim function.
 // This is currently primarily used for the `try` intrinsic functions above.
-fn gen_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
-                    name: &str,
-                    inputs: Vec<Ty<'tcx>>,
-                    output: Ty<'tcx>,
-                    codegen: &mut dyn for<'b> FnMut(Builder<'b, 'tcx>))
-                    -> ValueRef {
+fn gen_fn<'ll, 'tcx>(
+    cx: &CodegenCx<'ll, 'tcx>,
+    name: &str,
+    inputs: Vec<Ty<'tcx>>,
+    output: Ty<'tcx>,
+    codegen: &mut dyn FnMut(Builder<'_, 'll, 'tcx>),
+) -> &'ll Value {
     let rust_fn_ty = cx.tcx.mk_fn_ptr(ty::Binder::bind(cx.tcx.mk_fn_sig(
         inputs.into_iter(),
         output,
@@ -945,9 +953,10 @@ fn gen_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
 // catch exceptions.
 //
 // This function is only generated once and is then cached.
-fn get_rust_try_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
-                             codegen: &mut dyn for<'b> FnMut(Builder<'b, 'tcx>))
-                             -> ValueRef {
+fn get_rust_try_fn<'ll, 'tcx>(
+    cx: &CodegenCx<'ll, 'tcx>,
+    codegen: &mut dyn FnMut(Builder<'_, 'll, 'tcx>),
+) -> &'ll Value {
     if let Some(llfn) = cx.rust_try_fn.get() {
         return llfn;
     }
@@ -972,15 +981,15 @@ fn span_invalid_monomorphization_error(a: &Session, b: Span, c: &str) {
     span_err!(a, b, E0511, "{}", c);
 }
 
-fn generic_simd_intrinsic<'a, 'tcx>(
-    bx: &Builder<'a, 'tcx>,
+fn generic_simd_intrinsic(
+    bx: &Builder<'a, 'll, 'tcx>,
     name: &str,
     callee_ty: Ty<'tcx>,
-    args: &[OperandRef<'tcx>],
+    args: &[OperandRef<'ll, 'tcx>],
     ret_ty: Ty<'tcx>,
-    llret_ty: Type,
+    llret_ty: &'ll Type,
     span: Span
-) -> Result<ValueRef, ()> {
+) -> Result<&'ll Value, ()> {
     // macros for error handling:
     macro_rules! emit_error {
         ($msg: tt) => {
@@ -1050,7 +1059,7 @@ fn generic_simd_intrinsic<'a, 'tcx>(
                   found `{}` with length {}",
                  in_len, in_ty,
                  ret_ty, out_len);
-        require!(llret_ty.element_type().kind() == llvm::Integer,
+        require!(llret_ty.element_type().kind() == TypeKind::Integer,
                  "expected return type with integer elements, found `{}` with non-integer `{}`",
                  ret_ty,
                  ret_ty.simd_type(tcx));
@@ -1145,19 +1154,20 @@ fn generic_simd_intrinsic<'a, 'tcx>(
         }
         // truncate the mask to a vector of i1s
         let i1 = Type::i1(bx.cx);
-        let i1xn = Type::vector(&i1, m_len as u64);
+        let i1xn = Type::vector(i1, m_len as u64);
         let m_i1s = bx.trunc(args[0].immediate(), i1xn);
         return Ok(bx.select(m_i1s, args[1].immediate(), args[2].immediate()));
     }
 
-    fn simd_simple_float_intrinsic<'a, 'tcx>(name: &str,
-                                             in_elem: &::rustc::ty::TyS,
-                                             in_ty: &::rustc::ty::TyS,
-                                             in_len: usize,
-                                             bx: &Builder<'a, 'tcx>,
-                                             span: Span,
-                                             args: &[OperandRef<'tcx>])
-                                             -> Result<ValueRef, ()> {
+    fn simd_simple_float_intrinsic(
+        name: &str,
+        in_elem: &::rustc::ty::TyS,
+        in_ty: &::rustc::ty::TyS,
+        in_len: usize,
+        bx: &Builder<'a, 'll, 'tcx>,
+        span: Span,
+        args: &[OperandRef<'ll, 'tcx>],
+    ) -> Result<&'ll Value, ()> {
         macro_rules! emit_error {
             ($msg: tt) => {
                 emit_error!($msg, )
@@ -1283,8 +1293,8 @@ fn generic_simd_intrinsic<'a, 'tcx>(
         }
     }
 
-    fn llvm_vector_ty(cx: &CodegenCx, elem_ty: ty::Ty, vec_len: usize,
-                      mut no_pointers: usize) -> Type {
+    fn llvm_vector_ty(cx: &CodegenCx<'ll, '_>, elem_ty: ty::Ty, vec_len: usize,
+                      mut no_pointers: usize) -> &'ll Type {
         // FIXME: use cx.layout_of(ty).llvm_type() ?
         let mut elem_ty = match elem_ty.sty {
             ty::TyInt(v) => Type::int_from_ty(cx, v),
@@ -1296,7 +1306,7 @@ fn generic_simd_intrinsic<'a, 'tcx>(
             elem_ty = elem_ty.ptr_to();
             no_pointers -= 1;
         }
-        Type::vector(&elem_ty, vec_len as u64)
+        Type::vector(elem_ty, vec_len as u64)
     }
 
 
@@ -1379,7 +1389,7 @@ fn generic_simd_intrinsic<'a, 'tcx>(
         // Truncate the mask vector to a vector of i1s:
         let (mask, mask_ty) = {
             let i1 = Type::i1(bx.cx);
-            let i1xn = Type::vector(&i1, in_len as u64);
+            let i1xn = Type::vector(i1, in_len as u64);
             (bx.trunc(args[2].immediate(), i1xn), i1xn)
         };
 
@@ -1395,7 +1405,7 @@ fn generic_simd_intrinsic<'a, 'tcx>(
                                      llvm_elem_vec_str, llvm_pointer_vec_str);
         let f = declare::declare_cfn(bx.cx, &llvm_intrinsic,
                                      Type::func(&[llvm_pointer_vec_ty, alignment_ty, mask_ty,
-                                                  llvm_elem_vec_ty], &llvm_elem_vec_ty));
+                                                  llvm_elem_vec_ty], llvm_elem_vec_ty));
         llvm::SetUnnamedAddr(f, false);
         let v = bx.call(f, &[args[1].immediate(), alignment, mask, args[0].immediate()],
                         None);
@@ -1476,7 +1486,7 @@ fn generic_simd_intrinsic<'a, 'tcx>(
         // Truncate the mask vector to a vector of i1s:
         let (mask, mask_ty) = {
             let i1 = Type::i1(bx.cx);
-            let i1xn = Type::vector(&i1, in_len as u64);
+            let i1xn = Type::vector(i1, in_len as u64);
             (bx.trunc(args[2].immediate(), i1xn), i1xn)
         };
 
@@ -1496,7 +1506,7 @@ fn generic_simd_intrinsic<'a, 'tcx>(
                                      Type::func(&[llvm_elem_vec_ty,
                                                   llvm_pointer_vec_ty,
                                                   alignment_ty,
-                                                  mask_ty], &ret_t));
+                                                  mask_ty], ret_t));
         llvm::SetUnnamedAddr(f, false);
         let v = bx.call(f, &[args[0].immediate(), args[1].immediate(), alignment, mask],
                         None);
@@ -1629,7 +1639,7 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#,
 
                     // boolean reductions operate on vectors of i1s:
                     let i1 = Type::i1(bx.cx);
-                    let i1xn = Type::vector(&i1, in_len as u64);
+                    let i1xn = Type::vector(i1, in_len as u64);
                     bx.trunc(args[0].immediate(), i1xn)
                 };
                 return match in_elem.sty {
diff --git a/src/librustc_codegen_llvm/lib.rs b/src/librustc_codegen_llvm/lib.rs
index 90f96c9687b..724a2e3e65f 100644
--- a/src/librustc_codegen_llvm/lib.rs
+++ b/src/librustc_codegen_llvm/lib.rs
@@ -20,8 +20,11 @@
 
 #![feature(box_patterns)]
 #![feature(box_syntax)]
+#![feature(crate_visibility_modifier)]
 #![feature(custom_attribute)]
+#![feature(extern_types)]
 #![feature(fs_read_write)]
+#![feature(in_band_lifetimes)]
 #![allow(unused_attributes)]
 #![feature(libc)]
 #![feature(quote)]
@@ -29,7 +32,11 @@
 #![feature(rustc_diagnostic_macros)]
 #![feature(slice_sort_by_cached_key)]
 #![feature(optin_builtin_traits)]
+#![feature(concat_idents)]
+#![feature(link_args)]
+#![feature(static_nobundle)]
 
+use back::write::create_target_machine;
 use rustc::dep_graph::WorkProduct;
 use syntax_pos::symbol::Symbol;
 
@@ -46,7 +53,7 @@ extern crate rustc_target;
 #[macro_use] extern crate rustc_data_structures;
 extern crate rustc_demangle;
 extern crate rustc_incremental;
-extern crate rustc_llvm as llvm;
+extern crate rustc_llvm;
 extern crate rustc_platform_intrinsics as intrinsics;
 extern crate rustc_codegen_utils;
 
@@ -110,6 +117,7 @@ mod debuginfo;
 mod declare;
 mod glue;
 mod intrinsic;
+pub mod llvm;
 mod llvm_util;
 mod metadata;
 mod meth;
@@ -335,22 +343,41 @@ enum ModuleSource {
     Codegened(ModuleLlvm),
 }
 
-#[derive(Debug)]
 struct ModuleLlvm {
-    llcx: llvm::ContextRef,
-    llmod: llvm::ModuleRef,
-    tm: llvm::TargetMachineRef,
+    llcx: &'static mut llvm::Context,
+    llmod_raw: *const llvm::Module,
+    tm: &'static mut llvm::TargetMachine,
 }
 
 unsafe impl Send for ModuleLlvm { }
 unsafe impl Sync for ModuleLlvm { }
 
+impl ModuleLlvm {
+    fn new(sess: &Session, mod_name: &str) -> Self {
+        unsafe {
+            let llcx = llvm::LLVMRustContextCreate(sess.fewer_names());
+            let llmod_raw = context::create_module(sess, llcx, mod_name) as *const _;
+
+            ModuleLlvm {
+                llmod_raw,
+                llcx,
+                tm: create_target_machine(sess, false),
+            }
+        }
+    }
+
+    fn llmod(&self) -> &llvm::Module {
+        unsafe {
+            &*self.llmod_raw
+        }
+    }
+}
+
 impl Drop for ModuleLlvm {
     fn drop(&mut self) {
         unsafe {
-            llvm::LLVMDisposeModule(self.llmod);
-            llvm::LLVMContextDispose(self.llcx);
-            llvm::LLVMRustDisposeTargetMachine(self.tm);
+            llvm::LLVMContextDispose(&mut *(self.llcx as *mut _));
+            llvm::LLVMRustDisposeTargetMachine(&mut *(self.tm as *mut _));
         }
     }
 }
diff --git a/src/librustc_llvm/archive_ro.rs b/src/librustc_codegen_llvm/llvm/archive_ro.rs
index 9d869007270..4cbf0d92d7b 100644
--- a/src/librustc_llvm/archive_ro.rs
+++ b/src/librustc_codegen_llvm/llvm/archive_ro.rs
@@ -10,28 +10,23 @@
 
 //! A wrapper around LLVM's archive (.a) code
 
-use ArchiveRef;
-
 use std::ffi::CString;
-use std::marker;
 use std::path::Path;
 use std::slice;
 use std::str;
 
 pub struct ArchiveRO {
-    ptr: ArchiveRef,
+    pub raw: &'static mut super::Archive,
 }
 
 unsafe impl Send for ArchiveRO {}
 
 pub struct Iter<'a> {
-    archive: &'a ArchiveRO,
-    ptr: ::ArchiveIteratorRef,
+    raw: &'a mut super::ArchiveIterator<'a>,
 }
 
 pub struct Child<'a> {
-    ptr: ::ArchiveChildRef,
-    _data: marker::PhantomData<&'a ArchiveRO>,
+    pub raw: &'a mut super::ArchiveChild<'a>,
 }
 
 impl ArchiveRO {
@@ -44,12 +39,10 @@ impl ArchiveRO {
     pub fn open(dst: &Path) -> Result<ArchiveRO, String> {
         return unsafe {
             let s = path2cstr(dst);
-            let ar = ::LLVMRustOpenArchive(s.as_ptr());
-            if ar.is_null() {
-                Err(::last_error().unwrap_or("failed to open archive".to_string()))
-            } else {
-                Ok(ArchiveRO { ptr: ar })
-            }
+            let ar = super::LLVMRustOpenArchive(s.as_ptr()).ok_or_else(|| {
+                super::last_error().unwrap_or("failed to open archive".to_string())
+            })?;
+            Ok(ArchiveRO { raw: ar })
         };
 
         #[cfg(unix)]
@@ -65,15 +58,10 @@ impl ArchiveRO {
         }
     }
 
-    pub fn raw(&self) -> ArchiveRef {
-        self.ptr
-    }
-
     pub fn iter(&self) -> Iter {
         unsafe {
             Iter {
-                ptr: ::LLVMRustArchiveIteratorNew(self.ptr),
-                archive: self,
+                raw: super::LLVMRustArchiveIteratorNew(self.raw),
             }
         }
     }
@@ -82,7 +70,7 @@ impl ArchiveRO {
 impl Drop for ArchiveRO {
     fn drop(&mut self) {
         unsafe {
-            ::LLVMRustDestroyArchive(self.ptr);
+            super::LLVMRustDestroyArchive(&mut *(self.raw as *mut _));
         }
     }
 }
@@ -91,14 +79,11 @@ impl<'a> Iterator for Iter<'a> {
     type Item = Result<Child<'a>, String>;
 
     fn next(&mut self) -> Option<Result<Child<'a>, String>> {
-        let ptr = unsafe { ::LLVMRustArchiveIteratorNext(self.ptr) };
-        if ptr.is_null() {
-            ::last_error().map(Err)
-        } else {
-            Some(Ok(Child {
-                ptr,
-                _data: marker::PhantomData,
-            }))
+        unsafe {
+            match super::LLVMRustArchiveIteratorNext(self.raw) {
+                Some(raw) => Some(Ok(Child { raw })),
+                None => super::last_error().map(Err),
+            }
         }
     }
 }
@@ -106,7 +91,7 @@ impl<'a> Iterator for Iter<'a> {
 impl<'a> Drop for Iter<'a> {
     fn drop(&mut self) {
         unsafe {
-            ::LLVMRustArchiveIteratorFree(self.ptr);
+            super::LLVMRustArchiveIteratorFree(&mut *(self.raw as *mut _));
         }
     }
 }
@@ -115,7 +100,7 @@ impl<'a> Child<'a> {
     pub fn name(&self) -> Option<&'a str> {
         unsafe {
             let mut name_len = 0;
-            let name_ptr = ::LLVMRustArchiveChildName(self.ptr, &mut name_len);
+            let name_ptr = super::LLVMRustArchiveChildName(self.raw, &mut name_len);
             if name_ptr.is_null() {
                 None
             } else {
@@ -128,23 +113,19 @@ impl<'a> Child<'a> {
     pub fn data(&self) -> &'a [u8] {
         unsafe {
             let mut data_len = 0;
-            let data_ptr = ::LLVMRustArchiveChildData(self.ptr, &mut data_len);
+            let data_ptr = super::LLVMRustArchiveChildData(self.raw, &mut data_len);
             if data_ptr.is_null() {
                 panic!("failed to read data from archive child");
             }
             slice::from_raw_parts(data_ptr as *const u8, data_len as usize)
         }
     }
-
-    pub fn raw(&self) -> ::ArchiveChildRef {
-        self.ptr
-    }
 }
 
 impl<'a> Drop for Child<'a> {
     fn drop(&mut self) {
         unsafe {
-            ::LLVMRustArchiveChildFree(self.ptr);
+            super::LLVMRustArchiveChildFree(&mut *(self.raw as *mut _));
         }
     }
 }
diff --git a/src/librustc_llvm/diagnostic.rs b/src/librustc_codegen_llvm/llvm/diagnostic.rs
index e73c570ed82..7f2a9d6984a 100644
--- a/src/librustc_llvm/diagnostic.rs
+++ b/src/librustc_codegen_llvm/llvm/diagnostic.rs
@@ -14,9 +14,9 @@ pub use self::OptimizationDiagnosticKind::*;
 pub use self::Diagnostic::*;
 
 use libc::c_uint;
-use std::ptr;
+use value::Value;
 
-use {DiagnosticInfoRef, TwineRef, ValueRef};
+use super::{DiagnosticInfo, Twine};
 
 #[derive(Copy, Clone)]
 pub enum OptimizationDiagnosticKind {
@@ -42,21 +42,22 @@ impl OptimizationDiagnosticKind {
     }
 }
 
-pub struct OptimizationDiagnostic {
+pub struct OptimizationDiagnostic<'ll> {
     pub kind: OptimizationDiagnosticKind,
     pub pass_name: String,
-    pub function: ValueRef,
+    pub function: &'ll Value,
     pub line: c_uint,
     pub column: c_uint,
     pub filename: String,
     pub message: String,
 }
 
-impl OptimizationDiagnostic {
-    unsafe fn unpack(kind: OptimizationDiagnosticKind,
-                     di: DiagnosticInfoRef)
-                     -> OptimizationDiagnostic {
-        let mut function = ptr::null_mut();
+impl OptimizationDiagnostic<'ll> {
+    unsafe fn unpack(
+        kind: OptimizationDiagnosticKind,
+        di: &'ll DiagnosticInfo,
+    ) -> Self {
+        let mut function = None;
         let mut line = 0;
         let mut column = 0;
 
@@ -72,9 +73,9 @@ impl OptimizationDiagnostic {
                                                                 &mut column,
                                                                 filename,
                                                                 message)
-                )
-            )
-        );
+                ).ok()
+            ).ok()
+        ).ok();
 
         let mut filename = filename.unwrap_or(String::new());
         if filename.is_empty() {
@@ -84,7 +85,7 @@ impl OptimizationDiagnostic {
         OptimizationDiagnostic {
             kind,
             pass_name: pass_name.expect("got a non-UTF8 pass name from LLVM"),
-            function,
+            function: function.unwrap(),
             line,
             column,
             filename,
@@ -94,41 +95,44 @@ impl OptimizationDiagnostic {
 }
 
 #[derive(Copy, Clone)]
-pub struct InlineAsmDiagnostic {
+pub struct InlineAsmDiagnostic<'ll> {
     pub cookie: c_uint,
-    pub message: TwineRef,
-    pub instruction: ValueRef,
+    pub message: &'ll Twine,
+    pub instruction: &'ll Value,
 }
 
-impl InlineAsmDiagnostic {
-    unsafe fn unpack(di: DiagnosticInfoRef) -> InlineAsmDiagnostic {
-
-        let mut opt = InlineAsmDiagnostic {
-            cookie: 0,
-            message: ptr::null_mut(),
-            instruction: ptr::null_mut(),
-        };
+impl InlineAsmDiagnostic<'ll> {
+    unsafe fn unpack(di: &'ll DiagnosticInfo) -> Self {
+        let mut cookie = 0;
+        let mut message = None;
+        let mut instruction = None;
 
-        super::LLVMRustUnpackInlineAsmDiagnostic(di,
-                                                 &mut opt.cookie,
-                                                 &mut opt.message,
-                                                 &mut opt.instruction);
+        super::LLVMRustUnpackInlineAsmDiagnostic(
+            di,
+            &mut cookie,
+            &mut message,
+            &mut instruction,
+        );
 
-        opt
+        InlineAsmDiagnostic {
+            cookie,
+            message: message.unwrap(),
+            instruction: instruction.unwrap(),
+        }
     }
 }
 
-pub enum Diagnostic {
-    Optimization(OptimizationDiagnostic),
-    InlineAsm(InlineAsmDiagnostic),
-    PGO(DiagnosticInfoRef),
+pub enum Diagnostic<'ll> {
+    Optimization(OptimizationDiagnostic<'ll>),
+    InlineAsm(InlineAsmDiagnostic<'ll>),
+    PGO(&'ll DiagnosticInfo),
 
     /// LLVM has other types that we do not wrap here.
-    UnknownDiagnostic(DiagnosticInfoRef),
+    UnknownDiagnostic(&'ll DiagnosticInfo),
 }
 
-impl Diagnostic {
-    pub unsafe fn unpack(di: DiagnosticInfoRef) -> Diagnostic {
+impl Diagnostic<'ll> {
+    pub unsafe fn unpack(di: &'ll DiagnosticInfo) -> Self {
         use super::DiagnosticKind as Dk;
         let kind = super::LLVMRustGetDiagInfoKind(di);
 
diff --git a/src/librustc_codegen_llvm/llvm/ffi.rs b/src/librustc_codegen_llvm/llvm/ffi.rs
new file mode 100644
index 00000000000..898d3d67353
--- /dev/null
+++ b/src/librustc_codegen_llvm/llvm/ffi.rs
@@ -0,0 +1,1633 @@
+// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// FIXME: Rename 'DIGlobalVariable' to 'DIGlobalVariableExpression'
+// once support for LLVM 3.9 is dropped.
+//
+// This method was changed in this LLVM patch:
+// https://reviews.llvm.org/D26769
+
+use super::debuginfo::{
+    DIBuilder, DIDescriptor, DIFile, DILexicalBlock, DISubprogram, DIType,
+    DIBasicType, DIDerivedType, DICompositeType, DIScope, DIVariable,
+    DIGlobalVariable, DIArray, DISubrange, DITemplateTypeParameter, DIEnumerator,
+    DINameSpace, DIFlags,
+};
+
+use libc::{c_uint, c_int, size_t, c_char};
+use libc::{c_ulonglong, c_void};
+
+use std::marker::PhantomData;
+
+use super::RustString;
+
+pub type Bool = c_uint;
+
+pub const True: Bool = 1 as Bool;
+pub const False: Bool = 0 as Bool;
+
+#[derive(Copy, Clone, PartialEq)]
+#[repr(C)]
+#[allow(dead_code)] // Variants constructed by C++.
+pub enum LLVMRustResult {
+    Success,
+    Failure,
+}
+// Consts for the LLVM CallConv type, pre-cast to usize.
+
+/// LLVM CallingConv::ID. Should we wrap this?
+#[derive(Copy, Clone, PartialEq, Debug)]
+#[repr(C)]
+pub enum CallConv {
+    CCallConv = 0,
+    FastCallConv = 8,
+    ColdCallConv = 9,
+    X86StdcallCallConv = 64,
+    X86FastcallCallConv = 65,
+    ArmAapcsCallConv = 67,
+    Msp430Intr = 69,
+    X86_ThisCall = 70,
+    PtxKernel = 71,
+    X86_64_SysV = 78,
+    X86_64_Win64 = 79,
+    X86_VectorCall = 80,
+    X86_Intr = 83,
+    AmdGpuKernel = 91,
+}
+
+/// LLVMRustLinkage
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
+#[repr(C)]
+pub enum Linkage {
+    ExternalLinkage = 0,
+    AvailableExternallyLinkage = 1,
+    LinkOnceAnyLinkage = 2,
+    LinkOnceODRLinkage = 3,
+    WeakAnyLinkage = 4,
+    WeakODRLinkage = 5,
+    AppendingLinkage = 6,
+    InternalLinkage = 7,
+    PrivateLinkage = 8,
+    ExternalWeakLinkage = 9,
+    CommonLinkage = 10,
+}
+
+// LLVMRustVisibility
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
+#[repr(C)]
+pub enum Visibility {
+    Default = 0,
+    Hidden = 1,
+    Protected = 2,
+}
+
+/// LLVMDLLStorageClass
+#[derive(Copy, Clone)]
+#[repr(C)]
+pub enum DLLStorageClass {
+    #[allow(dead_code)]
+    Default = 0,
+    DllImport = 1, // Function to be imported from DLL.
+    #[allow(dead_code)]
+    DllExport = 2, // Function to be accessible from DLL.
+}
+
+/// Matches LLVMRustAttribute in rustllvm.h
+/// Semantically a subset of the C++ enum llvm::Attribute::AttrKind,
+/// though it is not ABI compatible (since it's a C++ enum)
+#[repr(C)]
+#[derive(Copy, Clone, Debug)]
+pub enum Attribute {
+    AlwaysInline    = 0,
+    ByVal           = 1,
+    Cold            = 2,
+    InlineHint      = 3,
+    MinSize         = 4,
+    Naked           = 5,
+    NoAlias         = 6,
+    NoCapture       = 7,
+    NoInline        = 8,
+    NonNull         = 9,
+    NoRedZone       = 10,
+    NoReturn        = 11,
+    NoUnwind        = 12,
+    OptimizeForSize = 13,
+    ReadOnly        = 14,
+    SExt            = 15,
+    StructRet       = 16,
+    UWTable         = 17,
+    ZExt            = 18,
+    InReg           = 19,
+    SanitizeThread  = 20,
+    SanitizeAddress = 21,
+    SanitizeMemory  = 22,
+}
+
+/// LLVMIntPredicate
+#[derive(Copy, Clone)]
+#[repr(C)]
+pub enum IntPredicate {
+    IntEQ = 32,
+    IntNE = 33,
+    IntUGT = 34,
+    IntUGE = 35,
+    IntULT = 36,
+    IntULE = 37,
+    IntSGT = 38,
+    IntSGE = 39,
+    IntSLT = 40,
+    IntSLE = 41,
+}
+
+/// LLVMRealPredicate
+#[derive(Copy, Clone)]
+#[repr(C)]
+pub enum RealPredicate {
+    RealPredicateFalse = 0,
+    RealOEQ = 1,
+    RealOGT = 2,
+    RealOGE = 3,
+    RealOLT = 4,
+    RealOLE = 5,
+    RealONE = 6,
+    RealORD = 7,
+    RealUNO = 8,
+    RealUEQ = 9,
+    RealUGT = 10,
+    RealUGE = 11,
+    RealULT = 12,
+    RealULE = 13,
+    RealUNE = 14,
+    RealPredicateTrue = 15,
+}
+
+/// LLVMTypeKind
+#[derive(Copy, Clone, PartialEq, Debug)]
+#[repr(C)]
+pub enum TypeKind {
+    Void = 0,
+    Half = 1,
+    Float = 2,
+    Double = 3,
+    X86_FP80 = 4,
+    FP128 = 5,
+    PPC_FP128 = 6,
+    Label = 7,
+    Integer = 8,
+    Function = 9,
+    Struct = 10,
+    Array = 11,
+    Pointer = 12,
+    Vector = 13,
+    Metadata = 14,
+    X86_MMX = 15,
+    Token = 16,
+}
+
+/// LLVMAtomicRmwBinOp
+#[derive(Copy, Clone)]
+#[repr(C)]
+pub enum AtomicRmwBinOp {
+    AtomicXchg = 0,
+    AtomicAdd = 1,
+    AtomicSub = 2,
+    AtomicAnd = 3,
+    AtomicNand = 4,
+    AtomicOr = 5,
+    AtomicXor = 6,
+    AtomicMax = 7,
+    AtomicMin = 8,
+    AtomicUMax = 9,
+    AtomicUMin = 10,
+}
+
+/// LLVMAtomicOrdering
+#[derive(Copy, Clone)]
+#[repr(C)]
+pub enum AtomicOrdering {
+    #[allow(dead_code)]
+    NotAtomic = 0,
+    Unordered = 1,
+    Monotonic = 2,
+    // Consume = 3,  // Not specified yet.
+    Acquire = 4,
+    Release = 5,
+    AcquireRelease = 6,
+    SequentiallyConsistent = 7,
+}
+
+/// LLVMRustSynchronizationScope
+#[derive(Copy, Clone)]
+#[repr(C)]
+pub enum SynchronizationScope {
+    // FIXME: figure out if this variant is needed at all.
+    #[allow(dead_code)]
+    Other,
+    SingleThread,
+    CrossThread,
+}
+
+/// LLVMRustFileType
+#[derive(Copy, Clone)]
+#[repr(C)]
+pub enum FileType {
+    // FIXME: figure out if this variant is needed at all.
+    #[allow(dead_code)]
+    Other,
+    AssemblyFile,
+    ObjectFile,
+}
+
+/// LLVMMetadataType
+#[derive(Copy, Clone)]
+#[repr(C)]
+pub enum MetadataType {
+    MD_dbg = 0,
+    MD_tbaa = 1,
+    MD_prof = 2,
+    MD_fpmath = 3,
+    MD_range = 4,
+    MD_tbaa_struct = 5,
+    MD_invariant_load = 6,
+    MD_alias_scope = 7,
+    MD_noalias = 8,
+    MD_nontemporal = 9,
+    MD_mem_parallel_loop_access = 10,
+    MD_nonnull = 11,
+}
+
+/// LLVMRustAsmDialect
+#[derive(Copy, Clone)]
+#[repr(C)]
+pub enum AsmDialect {
+    // FIXME: figure out if this variant is needed at all.
+    #[allow(dead_code)]
+    Other,
+    Att,
+    Intel,
+}
+
+/// LLVMRustCodeGenOptLevel
+#[derive(Copy, Clone, PartialEq)]
+#[repr(C)]
+pub enum CodeGenOptLevel {
+    // FIXME: figure out if this variant is needed at all.
+    #[allow(dead_code)]
+    Other,
+    None,
+    Less,
+    Default,
+    Aggressive,
+}
+
+/// LLVMRelocMode
+#[derive(Copy, Clone, PartialEq)]
+#[repr(C)]
+pub enum RelocMode {
+    Default,
+    Static,
+    PIC,
+    DynamicNoPic,
+    ROPI,
+    RWPI,
+    ROPI_RWPI,
+}
+
+/// LLVMRustCodeModel
+#[derive(Copy, Clone)]
+#[repr(C)]
+pub enum CodeModel {
+    // FIXME: figure out if this variant is needed at all.
+    #[allow(dead_code)]
+    Other,
+    Small,
+    Kernel,
+    Medium,
+    Large,
+    None,
+}
+
+/// LLVMRustDiagnosticKind
+#[derive(Copy, Clone)]
+#[repr(C)]
+#[allow(dead_code)] // Variants constructed by C++.
+pub enum DiagnosticKind {
+    Other,
+    InlineAsm,
+    StackSize,
+    DebugMetadataVersion,
+    SampleProfile,
+    OptimizationRemark,
+    OptimizationRemarkMissed,
+    OptimizationRemarkAnalysis,
+    OptimizationRemarkAnalysisFPCommute,
+    OptimizationRemarkAnalysisAliasing,
+    OptimizationRemarkOther,
+    OptimizationFailure,
+    PGOProfile,
+}
+
+/// LLVMRustArchiveKind
+#[derive(Copy, Clone)]
+#[repr(C)]
+pub enum ArchiveKind {
+    // FIXME: figure out if this variant is needed at all.
+    #[allow(dead_code)]
+    Other,
+    K_GNU,
+    K_BSD,
+    K_COFF,
+}
+
+/// LLVMRustPassKind
+#[derive(Copy, Clone, PartialEq, Debug)]
+#[repr(C)]
+#[allow(dead_code)] // Variants constructed by C++.
+pub enum PassKind {
+    Other,
+    Function,
+    Module,
+}
+
+/// LLVMRustThinLTOData
+extern { pub type ThinLTOData; }
+
+/// LLVMRustThinLTOBuffer
+extern { pub type ThinLTOBuffer; }
+
+/// LLVMRustThinLTOModule
+#[repr(C)]
+pub struct ThinLTOModule {
+    pub identifier: *const c_char,
+    pub data: *const u8,
+    pub len: usize,
+}
+
+/// LLVMThreadLocalMode
+#[derive(Copy, Clone)]
+#[repr(C)]
+pub enum ThreadLocalMode {
+  NotThreadLocal,
+  GeneralDynamic,
+  LocalDynamic,
+  InitialExec,
+  LocalExec
+}
+
+extern { type Opaque; }
+#[repr(C)]
+struct InvariantOpaque<'a> {
+    _marker: PhantomData<&'a mut &'a ()>,
+    _opaque: Opaque,
+}
+
+// Opaque pointer types
+extern { pub type Module; }
+extern { pub type Context; }
+extern { pub type Type; }
+extern { pub type Value; }
+extern { pub type Metadata; }
+extern { pub type BasicBlock; }
+#[repr(C)]
+pub struct Builder<'a>(InvariantOpaque<'a>);
+extern { pub type MemoryBuffer; }
+#[repr(C)]
+pub struct PassManager<'a>(InvariantOpaque<'a>);
+extern { pub type PassManagerBuilder; }
+extern { pub type ObjectFile; }
+#[repr(C)]
+pub struct SectionIterator<'a>(InvariantOpaque<'a>);
+extern { pub type Pass; }
+extern { pub type TargetMachine; }
+extern { pub type Archive; }
+#[repr(C)]
+pub struct ArchiveIterator<'a>(InvariantOpaque<'a>);
+#[repr(C)]
+pub struct ArchiveChild<'a>(InvariantOpaque<'a>);
+extern { pub type Twine; }
+extern { pub type DiagnosticInfo; }
+extern { pub type SMDiagnostic; }
+#[repr(C)]
+pub struct RustArchiveMember<'a>(InvariantOpaque<'a>);
+#[repr(C)]
+pub struct OperandBundleDef<'a>(InvariantOpaque<'a>);
+#[repr(C)]
+pub struct Linker<'a>(InvariantOpaque<'a>);
+
+pub type DiagnosticHandler = unsafe extern "C" fn(&DiagnosticInfo, *mut c_void);
+pub type InlineAsmDiagHandler = unsafe extern "C" fn(&SMDiagnostic, *const c_void, c_uint);
+
+
+pub mod debuginfo {
+    use super::{InvariantOpaque, Metadata};
+
+    #[repr(C)]
+    pub struct DIBuilder<'a>(InvariantOpaque<'a>);
+
+    pub type DIDescriptor = Metadata;
+    pub type DIScope = DIDescriptor;
+    pub type DIFile = DIScope;
+    pub type DILexicalBlock = DIScope;
+    pub type DISubprogram = DIScope;
+    pub type DINameSpace = DIScope;
+    pub type DIType = DIDescriptor;
+    pub type DIBasicType = DIType;
+    pub type DIDerivedType = DIType;
+    pub type DICompositeType = DIDerivedType;
+    pub type DIVariable = DIDescriptor;
+    pub type DIGlobalVariable = DIDescriptor;
+    pub type DIArray = DIDescriptor;
+    pub type DISubrange = DIDescriptor;
+    pub type DIEnumerator = DIDescriptor;
+    pub type DITemplateTypeParameter = DIDescriptor;
+
+    // These values **must** match with LLVMRustDIFlags!!
+    bitflags! {
+        #[repr(C)]
+        #[derive(Default)]
+        pub struct DIFlags: ::libc::uint32_t {
+            const FlagZero                = 0;
+            const FlagPrivate             = 1;
+            const FlagProtected           = 2;
+            const FlagPublic              = 3;
+            const FlagFwdDecl             = (1 << 2);
+            const FlagAppleBlock          = (1 << 3);
+            const FlagBlockByrefStruct    = (1 << 4);
+            const FlagVirtual             = (1 << 5);
+            const FlagArtificial          = (1 << 6);
+            const FlagExplicit            = (1 << 7);
+            const FlagPrototyped          = (1 << 8);
+            const FlagObjcClassComplete   = (1 << 9);
+            const FlagObjectPointer       = (1 << 10);
+            const FlagVector              = (1 << 11);
+            const FlagStaticMember        = (1 << 12);
+            const FlagLValueReference     = (1 << 13);
+            const FlagRValueReference     = (1 << 14);
+            const FlagExternalTypeRef     = (1 << 15);
+            const FlagIntroducedVirtual   = (1 << 18);
+            const FlagBitField            = (1 << 19);
+            const FlagNoReturn            = (1 << 20);
+            const FlagMainSubprogram      = (1 << 21);
+        }
+    }
+}
+
+extern { pub type ModuleBuffer; }
+
+extern "C" {
+    // Create and destroy contexts.
+    pub fn LLVMRustContextCreate(shouldDiscardNames: bool) -> &'static mut Context;
+    pub fn LLVMContextDispose(C: &'static mut Context);
+    pub fn LLVMGetMDKindIDInContext(C: &Context, Name: *const c_char, SLen: c_uint) -> c_uint;
+
+    // Create modules.
+    pub fn LLVMModuleCreateWithNameInContext(ModuleID: *const c_char, C: &Context) -> &Module;
+    pub fn LLVMGetModuleContext(M: &Module) -> &Context;
+    pub fn LLVMCloneModule(M: &Module) -> &Module;
+
+    /// Data layout. See Module::getDataLayout.
+    pub fn LLVMGetDataLayout(M: &Module) -> *const c_char;
+    pub fn LLVMSetDataLayout(M: &Module, Triple: *const c_char);
+
+    /// See Module::setModuleInlineAsm.
+    pub fn LLVMSetModuleInlineAsm(M: &Module, Asm: *const c_char);
+    pub fn LLVMRustAppendModuleInlineAsm(M: &Module, Asm: *const c_char);
+
+    /// See llvm::LLVMTypeKind::getTypeID.
+    pub fn LLVMRustGetTypeKind(Ty: &Type) -> TypeKind;
+
+    // Operations on integer types
+    pub fn LLVMInt1TypeInContext(C: &Context) -> &Type;
+    pub fn LLVMInt8TypeInContext(C: &Context) -> &Type;
+    pub fn LLVMInt16TypeInContext(C: &Context) -> &Type;
+    pub fn LLVMInt32TypeInContext(C: &Context) -> &Type;
+    pub fn LLVMInt64TypeInContext(C: &Context) -> &Type;
+    pub fn LLVMIntTypeInContext(C: &Context, NumBits: c_uint) -> &Type;
+
+    pub fn LLVMGetIntTypeWidth(IntegerTy: &Type) -> c_uint;
+
+    // Operations on real types
+    pub fn LLVMFloatTypeInContext(C: &Context) -> &Type;
+    pub fn LLVMDoubleTypeInContext(C: &Context) -> &Type;
+
+    // Operations on function types
+    pub fn LLVMFunctionType(ReturnType: &'a Type,
+                            ParamTypes: *const &'a Type,
+                            ParamCount: c_uint,
+                            IsVarArg: Bool)
+                            -> &'a Type;
+    pub fn LLVMCountParamTypes(FunctionTy: &Type) -> c_uint;
+    pub fn LLVMGetParamTypes(FunctionTy: &'a Type, Dest: *mut &'a Type);
+
+    // Operations on struct types
+    pub fn LLVMStructTypeInContext(C: &'a Context,
+                                   ElementTypes: *const &'a Type,
+                                   ElementCount: c_uint,
+                                   Packed: Bool)
+                                   -> &'a Type;
+
+    // Operations on array, pointer, and vector types (sequence types)
+    pub fn LLVMRustArrayType(ElementType: &Type, ElementCount: u64) -> &Type;
+    pub fn LLVMPointerType(ElementType: &Type, AddressSpace: c_uint) -> &Type;
+    pub fn LLVMVectorType(ElementType: &Type, ElementCount: c_uint) -> &Type;
+
+    pub fn LLVMGetElementType(Ty: &Type) -> &Type;
+    pub fn LLVMGetVectorSize(VectorTy: &Type) -> c_uint;
+
+    // Operations on other types
+    pub fn LLVMVoidTypeInContext(C: &Context) -> &Type;
+    pub fn LLVMX86MMXTypeInContext(C: &Context) -> &Type;
+    pub fn LLVMRustMetadataTypeInContext(C: &Context) -> &Type;
+
+    // Operations on all values
+    pub fn LLVMTypeOf(Val: &Value) -> &Type;
+    pub fn LLVMGetValueName(Val: &Value) -> *const c_char;
+    pub fn LLVMSetValueName(Val: &Value, Name: *const c_char);
+    pub fn LLVMReplaceAllUsesWith(OldVal: &'a Value, NewVal: &'a Value);
+    pub fn LLVMSetMetadata(Val: &'a Value, KindID: c_uint, Node: &'a Value);
+
+    // Operations on constants of any type
+    pub fn LLVMConstNull(Ty: &Type) -> &Value;
+    pub fn LLVMGetUndef(Ty: &Type) -> &Value;
+
+    // Operations on metadata
+    pub fn LLVMMDStringInContext(C: &Context, Str: *const c_char, SLen: c_uint) -> &Value;
+    pub fn LLVMMDNodeInContext(C: &'a Context, Vals: *const &'a Value, Count: c_uint) -> &'a Value;
+    pub fn LLVMAddNamedMetadataOperand(M: &'a Module, Name: *const c_char, Val: &'a Value);
+
+    // Operations on scalar constants
+    pub fn LLVMConstInt(IntTy: &Type, N: c_ulonglong, SignExtend: Bool) -> &Value;
+    pub fn LLVMConstIntOfArbitraryPrecision(IntTy: &Type, Wn: c_uint, Ws: *const u64) -> &Value;
+    pub fn LLVMConstIntGetZExtValue(ConstantVal: &Value) -> c_ulonglong;
+    pub fn LLVMRustConstInt128Get(ConstantVal: &Value, SExt: bool,
+                                  high: &mut u64, low: &mut u64) -> bool;
+    pub fn LLVMConstRealGetDouble (ConstantVal: &Value, losesInfo: &mut Bool) -> f64;
+
+
+    // Operations on composite constants
+    pub fn LLVMConstStringInContext(C: &Context,
+                                    Str: *const c_char,
+                                    Length: c_uint,
+                                    DontNullTerminate: Bool)
+                                    -> &Value;
+    pub fn LLVMConstStructInContext(C: &'a Context,
+                                    ConstantVals: *const &'a Value,
+                                    Count: c_uint,
+                                    Packed: Bool)
+                                    -> &'a Value;
+
+    pub fn LLVMConstArray(ElementTy: &'a Type,
+                          ConstantVals: *const &'a Value,
+                          Length: c_uint)
+                          -> &'a Value;
+    pub fn LLVMConstVector(ScalarConstantVals: *const &Value, Size: c_uint) -> &Value;
+
+    // Constant expressions
+    pub fn LLVMConstInBoundsGEP(
+        ConstantVal: &'a Value,
+        ConstantIndices: *const &'a Value,
+        NumIndices: c_uint,
+    ) -> &'a Value;
+    pub fn LLVMConstZExt(ConstantVal: &'a Value, ToType: &'a Type) -> &'a Value;
+    pub fn LLVMConstPtrToInt(ConstantVal: &'a Value, ToType: &'a Type) -> &'a Value;
+    pub fn LLVMConstIntToPtr(ConstantVal: &'a Value, ToType: &'a Type) -> &'a Value;
+    pub fn LLVMConstBitCast(ConstantVal: &'a Value, ToType: &'a Type) -> &'a Value;
+    pub fn LLVMConstPointerCast(ConstantVal: &'a Value, ToType: &'a Type) -> &'a Value;
+    pub fn LLVMConstExtractValue(AggConstant: &Value,
+                                 IdxList: *const c_uint,
+                                 NumIdx: c_uint)
+                                 -> &Value;
+
+    // Operations on global variables, functions, and aliases (globals)
+    pub fn LLVMIsDeclaration(Global: &Value) -> Bool;
+    pub fn LLVMRustGetLinkage(Global: &Value) -> Linkage;
+    pub fn LLVMRustSetLinkage(Global: &Value, RustLinkage: Linkage);
+    pub fn LLVMSetSection(Global: &Value, Section: *const c_char);
+    pub fn LLVMRustGetVisibility(Global: &Value) -> Visibility;
+    pub fn LLVMRustSetVisibility(Global: &Value, Viz: Visibility);
+    pub fn LLVMGetAlignment(Global: &Value) -> c_uint;
+    pub fn LLVMSetAlignment(Global: &Value, Bytes: c_uint);
+    pub fn LLVMSetDLLStorageClass(V: &Value, C: DLLStorageClass);
+
+
+    // Operations on global variables
+    pub fn LLVMIsAGlobalVariable(GlobalVar: &Value) -> Option<&Value>;
+    pub fn LLVMAddGlobal(M: &'a Module, Ty: &'a Type, Name: *const c_char) -> &'a Value;
+    pub fn LLVMGetNamedGlobal(M: &Module, Name: *const c_char) -> Option<&Value>;
+    pub fn LLVMRustGetOrInsertGlobal(M: &'a Module, Name: *const c_char, T: &'a Type) -> &'a Value;
+    pub fn LLVMGetFirstGlobal(M: &Module) -> Option<&Value>;
+    pub fn LLVMGetNextGlobal(GlobalVar: &Value) -> Option<&Value>;
+    pub fn LLVMDeleteGlobal(GlobalVar: &Value);
+    pub fn LLVMGetInitializer(GlobalVar: &Value) -> Option<&Value>;
+    pub fn LLVMSetInitializer(GlobalVar: &'a Value, ConstantVal: &'a Value);
+    pub fn LLVMSetThreadLocal(GlobalVar: &Value, IsThreadLocal: Bool);
+    pub fn LLVMSetThreadLocalMode(GlobalVar: &Value, Mode: ThreadLocalMode);
+    pub fn LLVMIsGlobalConstant(GlobalVar: &Value) -> Bool;
+    pub fn LLVMSetGlobalConstant(GlobalVar: &Value, IsConstant: Bool);
+    pub fn LLVMRustGetNamedValue(M: &Module, Name: *const c_char) -> Option<&Value>;
+    pub fn LLVMSetTailCall(CallInst: &Value, IsTailCall: Bool);
+
+    // Operations on functions
+    pub fn LLVMRustGetOrInsertFunction(M: &'a Module,
+                                       Name: *const c_char,
+                                       FunctionTy: &'a Type)
+                                       -> &'a Value;
+    pub fn LLVMSetFunctionCallConv(Fn: &Value, CC: c_uint);
+    pub fn LLVMRustAddAlignmentAttr(Fn: &Value, index: c_uint, bytes: u32);
+    pub fn LLVMRustAddDereferenceableAttr(Fn: &Value, index: c_uint, bytes: u64);
+    pub fn LLVMRustAddDereferenceableOrNullAttr(Fn: &Value, index: c_uint, bytes: u64);
+    pub fn LLVMRustAddFunctionAttribute(Fn: &Value, index: c_uint, attr: Attribute);
+    pub fn LLVMRustAddFunctionAttrStringValue(Fn: &Value,
+                                              index: c_uint,
+                                              Name: *const c_char,
+                                              Value: *const c_char);
+    pub fn LLVMRustRemoveFunctionAttributes(Fn: &Value, index: c_uint, attr: Attribute);
+
+    // Operations on parameters
+    pub fn LLVMCountParams(Fn: &Value) -> c_uint;
+    pub fn LLVMGetParam(Fn: &Value, Index: c_uint) -> &Value;
+
+    // Operations on basic blocks
+    pub fn LLVMGetBasicBlockParent(BB: &BasicBlock) -> &Value;
+    pub fn LLVMAppendBasicBlockInContext(C: &'a Context,
+                                         Fn: &'a Value,
+                                         Name: *const c_char)
+                                         -> &'a BasicBlock;
+    pub fn LLVMDeleteBasicBlock(BB: &BasicBlock);
+
+    // Operations on instructions
+    pub fn LLVMGetFirstBasicBlock(Fn: &Value) -> &BasicBlock;
+
+    // Operations on call sites
+    pub fn LLVMSetInstructionCallConv(Instr: &Value, CC: c_uint);
+    pub fn LLVMRustAddCallSiteAttribute(Instr: &Value, index: c_uint, attr: Attribute);
+    pub fn LLVMRustAddAlignmentCallSiteAttr(Instr: &Value, index: c_uint, bytes: u32);
+    pub fn LLVMRustAddDereferenceableCallSiteAttr(Instr: &Value, index: c_uint, bytes: u64);
+    pub fn LLVMRustAddDereferenceableOrNullCallSiteAttr(Instr: &Value,
+                                                        index: c_uint,
+                                                        bytes: u64);
+
+    // Operations on load/store instructions (only)
+    pub fn LLVMSetVolatile(MemoryAccessInst: &Value, volatile: Bool);
+
+    // Operations on phi nodes
+    pub fn LLVMAddIncoming(PhiNode: &'a Value,
+                           IncomingValues: *const &'a Value,
+                           IncomingBlocks: *const &'a BasicBlock,
+                           Count: c_uint);
+
+    // Instruction builders
+    pub fn LLVMCreateBuilderInContext(C: &'a Context) -> &'a mut Builder<'a>;
+    pub fn LLVMPositionBuilderAtEnd(Builder: &Builder<'a>, Block: &'a BasicBlock);
+    pub fn LLVMGetInsertBlock(Builder: &Builder<'a>) -> &'a BasicBlock;
+    pub fn LLVMDisposeBuilder(Builder: &'a mut Builder<'a>);
+
+    // Metadata
+    pub fn LLVMSetCurrentDebugLocation(Builder: &Builder<'a>, L: Option<&'a Value>);
+    pub fn LLVMGetCurrentDebugLocation(Builder: &Builder<'a>) -> &'a Value;
+    pub fn LLVMSetInstDebugLocation(Builder: &Builder<'a>, Inst: &'a Value);
+
+    // Terminators
+    pub fn LLVMBuildRetVoid(B: &Builder<'a>) -> &'a Value;
+    pub fn LLVMBuildRet(B: &Builder<'a>, V: &'a Value) -> &'a Value;
+    pub fn LLVMBuildBr(B: &Builder<'a>, Dest: &'a BasicBlock) -> &'a Value;
+    pub fn LLVMBuildCondBr(B: &Builder<'a>,
+                           If: &'a Value,
+                           Then: &'a BasicBlock,
+                           Else: &'a BasicBlock)
+                           -> &'a Value;
+    pub fn LLVMBuildSwitch(B: &Builder<'a>,
+                           V: &'a Value,
+                           Else: &'a BasicBlock,
+                           NumCases: c_uint)
+                           -> &'a Value;
+    pub fn LLVMRustBuildInvoke(B: &Builder<'a>,
+                               Fn: &'a Value,
+                               Args: *const &'a Value,
+                               NumArgs: c_uint,
+                               Then: &'a BasicBlock,
+                               Catch: &'a BasicBlock,
+                               Bundle: Option<&OperandBundleDef<'a>>,
+                               Name: *const c_char)
+                               -> &'a Value;
+    pub fn LLVMBuildLandingPad(B: &Builder<'a>,
+                               Ty: &'a Type,
+                               PersFn: &'a Value,
+                               NumClauses: c_uint,
+                               Name: *const c_char)
+                               -> &'a Value;
+    pub fn LLVMBuildResume(B: &Builder<'a>, Exn: &'a Value) -> &'a Value;
+    pub fn LLVMBuildUnreachable(B: &Builder<'a>) -> &'a Value;
+
+    pub fn LLVMRustBuildCleanupPad(B: &Builder<'a>,
+                                   ParentPad: Option<&'a Value>,
+                                   ArgCnt: c_uint,
+                                   Args: *const &'a Value,
+                                   Name: *const c_char)
+                                   -> Option<&'a Value>;
+    pub fn LLVMRustBuildCleanupRet(B: &Builder<'a>,
+                                   CleanupPad: &'a Value,
+                                   UnwindBB: Option<&'a BasicBlock>)
+                                   -> Option<&'a Value>;
+    pub fn LLVMRustBuildCatchPad(B: &Builder<'a>,
+                                 ParentPad: &'a Value,
+                                 ArgCnt: c_uint,
+                                 Args: *const &'a Value,
+                                 Name: *const c_char)
+                                 -> Option<&'a Value>;
+    pub fn LLVMRustBuildCatchRet(
+        B: &Builder<'a>,
+        Pad: &'a Value,
+        BB: &'a BasicBlock,
+    ) -> Option<&'a Value>;
+    pub fn LLVMRustBuildCatchSwitch(Builder: &Builder<'a>,
+                                    ParentPad: Option<&'a Value>,
+                                    BB: Option<&'a BasicBlock>,
+                                    NumHandlers: c_uint,
+                                    Name: *const c_char)
+                                    -> Option<&'a Value>;
+    pub fn LLVMRustAddHandler(CatchSwitch: &'a Value, Handler: &'a BasicBlock);
+    pub fn LLVMSetPersonalityFn(Func: &'a Value, Pers: &'a Value);
+
+    // Add a case to the switch instruction
+    pub fn LLVMAddCase(Switch: &'a Value, OnVal: &'a Value, Dest: &'a BasicBlock);
+
+    // Add a clause to the landing pad instruction
+    pub fn LLVMAddClause(LandingPad: &'a Value, ClauseVal: &'a Value);
+
+    // Set the cleanup on a landing pad instruction
+    pub fn LLVMSetCleanup(LandingPad: &Value, Val: Bool);
+
+    // Arithmetic
+    pub fn LLVMBuildAdd(B: &Builder<'a>,
+                        LHS: &'a Value,
+                        RHS: &'a Value,
+                        Name: *const c_char)
+                        -> &'a Value;
+    pub fn LLVMBuildFAdd(B: &Builder<'a>,
+                         LHS: &'a Value,
+                         RHS: &'a Value,
+                         Name: *const c_char)
+                         -> &'a Value;
+    pub fn LLVMBuildSub(B: &Builder<'a>,
+                        LHS: &'a Value,
+                        RHS: &'a Value,
+                        Name: *const c_char)
+                        -> &'a Value;
+    pub fn LLVMBuildFSub(B: &Builder<'a>,
+                         LHS: &'a Value,
+                         RHS: &'a Value,
+                         Name: *const c_char)
+                         -> &'a Value;
+    pub fn LLVMBuildMul(B: &Builder<'a>,
+                        LHS: &'a Value,
+                        RHS: &'a Value,
+                        Name: *const c_char)
+                        -> &'a Value;
+    pub fn LLVMBuildFMul(B: &Builder<'a>,
+                         LHS: &'a Value,
+                         RHS: &'a Value,
+                         Name: *const c_char)
+                         -> &'a Value;
+    pub fn LLVMBuildUDiv(B: &Builder<'a>,
+                         LHS: &'a Value,
+                         RHS: &'a Value,
+                         Name: *const c_char)
+                         -> &'a Value;
+    pub fn LLVMBuildExactUDiv(B: &Builder<'a>,
+                              LHS: &'a Value,
+                              RHS: &'a Value,
+                              Name: *const c_char)
+                              -> &'a Value;
+    pub fn LLVMBuildSDiv(B: &Builder<'a>,
+                         LHS: &'a Value,
+                         RHS: &'a Value,
+                         Name: *const c_char)
+                         -> &'a Value;
+    pub fn LLVMBuildExactSDiv(B: &Builder<'a>,
+                              LHS: &'a Value,
+                              RHS: &'a Value,
+                              Name: *const c_char)
+                              -> &'a Value;
+    pub fn LLVMBuildFDiv(B: &Builder<'a>,
+                         LHS: &'a Value,
+                         RHS: &'a Value,
+                         Name: *const c_char)
+                         -> &'a Value;
+    pub fn LLVMBuildURem(B: &Builder<'a>,
+                         LHS: &'a Value,
+                         RHS: &'a Value,
+                         Name: *const c_char)
+                         -> &'a Value;
+    pub fn LLVMBuildSRem(B: &Builder<'a>,
+                         LHS: &'a Value,
+                         RHS: &'a Value,
+                         Name: *const c_char)
+                         -> &'a Value;
+    pub fn LLVMBuildFRem(B: &Builder<'a>,
+                         LHS: &'a Value,
+                         RHS: &'a Value,
+                         Name: *const c_char)
+                         -> &'a Value;
+    pub fn LLVMBuildShl(B: &Builder<'a>,
+                        LHS: &'a Value,
+                        RHS: &'a Value,
+                        Name: *const c_char)
+                        -> &'a Value;
+    pub fn LLVMBuildLShr(B: &Builder<'a>,
+                         LHS: &'a Value,
+                         RHS: &'a Value,
+                         Name: *const c_char)
+                         -> &'a Value;
+    pub fn LLVMBuildAShr(B: &Builder<'a>,
+                         LHS: &'a Value,
+                         RHS: &'a Value,
+                         Name: *const c_char)
+                         -> &'a Value;
+    pub fn LLVMBuildAnd(B: &Builder<'a>,
+                        LHS: &'a Value,
+                        RHS: &'a Value,
+                        Name: *const c_char)
+                        -> &'a Value;
+    pub fn LLVMBuildOr(B: &Builder<'a>,
+                       LHS: &'a Value,
+                       RHS: &'a Value,
+                       Name: *const c_char)
+                       -> &'a Value;
+    pub fn LLVMBuildXor(B: &Builder<'a>,
+                        LHS: &'a Value,
+                        RHS: &'a Value,
+                        Name: *const c_char)
+                        -> &'a Value;
+    pub fn LLVMBuildNeg(B: &Builder<'a>, V: &'a Value, Name: *const c_char) -> &'a Value;
+    pub fn LLVMBuildFNeg(B: &Builder<'a>, V: &'a Value, Name: *const c_char) -> &'a Value;
+    pub fn LLVMBuildNot(B: &Builder<'a>, V: &'a Value, Name: *const c_char) -> &'a Value;
+    pub fn LLVMRustSetHasUnsafeAlgebra(Instr: &Value);
+
+    // Memory
+    pub fn LLVMBuildAlloca(B: &Builder<'a>, Ty: &'a Type, Name: *const c_char) -> &'a Value;
+    pub fn LLVMBuildLoad(B: &Builder<'a>, PointerVal: &'a Value, Name: *const c_char) -> &'a Value;
+
+    pub fn LLVMBuildStore(B: &Builder<'a>, Val: &'a Value, Ptr: &'a Value) -> &'a Value;
+
+    pub fn LLVMBuildGEP(B: &Builder<'a>,
+                        Pointer: &'a Value,
+                        Indices: *const &'a Value,
+                        NumIndices: c_uint,
+                        Name: *const c_char)
+                        -> &'a Value;
+    pub fn LLVMBuildInBoundsGEP(B: &Builder<'a>,
+                                Pointer: &'a Value,
+                                Indices: *const &'a Value,
+                                NumIndices: c_uint,
+                                Name: *const c_char)
+                                -> &'a Value;
+    pub fn LLVMBuildStructGEP(B: &Builder<'a>,
+                              Pointer: &'a Value,
+                              Idx: c_uint,
+                              Name: *const c_char)
+                              -> &'a Value;
+
+    // Casts
+    pub fn LLVMBuildTrunc(B: &Builder<'a>,
+                          Val: &'a Value,
+                          DestTy: &'a Type,
+                          Name: *const c_char)
+                          -> &'a Value;
+    pub fn LLVMBuildZExt(B: &Builder<'a>,
+                         Val: &'a Value,
+                         DestTy: &'a Type,
+                         Name: *const c_char)
+                         -> &'a Value;
+    pub fn LLVMBuildSExt(B: &Builder<'a>,
+                         Val: &'a Value,
+                         DestTy: &'a Type,
+                         Name: *const c_char)
+                         -> &'a Value;
+    pub fn LLVMBuildFPToUI(B: &Builder<'a>,
+                           Val: &'a Value,
+                           DestTy: &'a Type,
+                           Name: *const c_char)
+                           -> &'a Value;
+    pub fn LLVMBuildFPToSI(B: &Builder<'a>,
+                           Val: &'a Value,
+                           DestTy: &'a Type,
+                           Name: *const c_char)
+                           -> &'a Value;
+    pub fn LLVMBuildUIToFP(B: &Builder<'a>,
+                           Val: &'a Value,
+                           DestTy: &'a Type,
+                           Name: *const c_char)
+                           -> &'a Value;
+    pub fn LLVMBuildSIToFP(B: &Builder<'a>,
+                           Val: &'a Value,
+                           DestTy: &'a Type,
+                           Name: *const c_char)
+                           -> &'a Value;
+    pub fn LLVMBuildFPTrunc(B: &Builder<'a>,
+                            Val: &'a Value,
+                            DestTy: &'a Type,
+                            Name: *const c_char)
+                            -> &'a Value;
+    pub fn LLVMBuildFPExt(B: &Builder<'a>,
+                          Val: &'a Value,
+                          DestTy: &'a Type,
+                          Name: *const c_char)
+                          -> &'a Value;
+    pub fn LLVMBuildPtrToInt(B: &Builder<'a>,
+                             Val: &'a Value,
+                             DestTy: &'a Type,
+                             Name: *const c_char)
+                             -> &'a Value;
+    pub fn LLVMBuildIntToPtr(B: &Builder<'a>,
+                             Val: &'a Value,
+                             DestTy: &'a Type,
+                             Name: *const c_char)
+                             -> &'a Value;
+    pub fn LLVMBuildBitCast(B: &Builder<'a>,
+                            Val: &'a Value,
+                            DestTy: &'a Type,
+                            Name: *const c_char)
+                            -> &'a Value;
+    pub fn LLVMBuildPointerCast(B: &Builder<'a>,
+                                Val: &'a Value,
+                                DestTy: &'a Type,
+                                Name: *const c_char)
+                                -> &'a Value;
+    pub fn LLVMRustBuildIntCast(B: &Builder<'a>,
+                                Val: &'a Value,
+                                DestTy: &'a Type,
+                                IsSized: bool)
+                                -> &'a Value;
+
+    // Comparisons
+    pub fn LLVMBuildICmp(B: &Builder<'a>,
+                         Op: c_uint,
+                         LHS: &'a Value,
+                         RHS: &'a Value,
+                         Name: *const c_char)
+                         -> &'a Value;
+    pub fn LLVMBuildFCmp(B: &Builder<'a>,
+                         Op: c_uint,
+                         LHS: &'a Value,
+                         RHS: &'a Value,
+                         Name: *const c_char)
+                         -> &'a Value;
+
+    // Miscellaneous instructions
+    pub fn LLVMBuildPhi(B: &Builder<'a>, Ty: &'a Type, Name: *const c_char) -> &'a Value;
+    pub fn LLVMRustBuildCall(B: &Builder<'a>,
+                             Fn: &'a Value,
+                             Args: *const &'a Value,
+                             NumArgs: c_uint,
+                             Bundle: Option<&OperandBundleDef<'a>>,
+                             Name: *const c_char)
+                             -> &'a Value;
+    pub fn LLVMBuildSelect(B: &Builder<'a>,
+                           If: &'a Value,
+                           Then: &'a Value,
+                           Else: &'a Value,
+                           Name: *const c_char)
+                           -> &'a Value;
+    pub fn LLVMBuildVAArg(B: &Builder<'a>,
+                          list: &'a Value,
+                          Ty: &'a Type,
+                          Name: *const c_char)
+                          -> &'a Value;
+    pub fn LLVMBuildExtractElement(B: &Builder<'a>,
+                                   VecVal: &'a Value,
+                                   Index: &'a Value,
+                                   Name: *const c_char)
+                                   -> &'a Value;
+    pub fn LLVMBuildInsertElement(B: &Builder<'a>,
+                                  VecVal: &'a Value,
+                                  EltVal: &'a Value,
+                                  Index: &'a Value,
+                                  Name: *const c_char)
+                                  -> &'a Value;
+    pub fn LLVMBuildShuffleVector(B: &Builder<'a>,
+                                  V1: &'a Value,
+                                  V2: &'a Value,
+                                  Mask: &'a Value,
+                                  Name: *const c_char)
+                                  -> &'a Value;
+    pub fn LLVMBuildExtractValue(B: &Builder<'a>,
+                                 AggVal: &'a Value,
+                                 Index: c_uint,
+                                 Name: *const c_char)
+                                 -> &'a Value;
+    pub fn LLVMBuildInsertValue(B: &Builder<'a>,
+                                AggVal: &'a Value,
+                                EltVal: &'a Value,
+                                Index: c_uint,
+                                Name: *const c_char)
+                                -> &'a Value;
+
+    pub fn LLVMRustBuildVectorReduceFAdd(B: &Builder<'a>,
+                                         Acc: &'a Value,
+                                         Src: &'a Value)
+                                         -> Option<&'a Value>;
+    pub fn LLVMRustBuildVectorReduceFMul(B: &Builder<'a>,
+                                         Acc: &'a Value,
+                                         Src: &'a Value)
+                                         -> Option<&'a Value>;
+    pub fn LLVMRustBuildVectorReduceAdd(B: &Builder<'a>,
+                                        Src: &'a Value)
+                                        -> Option<&'a Value>;
+    pub fn LLVMRustBuildVectorReduceMul(B: &Builder<'a>,
+                                        Src: &'a Value)
+                                        -> Option<&'a Value>;
+    pub fn LLVMRustBuildVectorReduceAnd(B: &Builder<'a>,
+                                        Src: &'a Value)
+                                        -> Option<&'a Value>;
+    pub fn LLVMRustBuildVectorReduceOr(B: &Builder<'a>,
+                                       Src: &'a Value)
+                                       -> Option<&'a Value>;
+    pub fn LLVMRustBuildVectorReduceXor(B: &Builder<'a>,
+                                        Src: &'a Value)
+                                        -> Option<&'a Value>;
+    pub fn LLVMRustBuildVectorReduceMin(B: &Builder<'a>,
+                                        Src: &'a Value,
+                                        IsSigned: bool)
+                                        -> Option<&'a Value>;
+    pub fn LLVMRustBuildVectorReduceMax(B: &Builder<'a>,
+                                        Src: &'a Value,
+                                        IsSigned: bool)
+                                        -> Option<&'a Value>;
+    pub fn LLVMRustBuildVectorReduceFMin(B: &Builder<'a>,
+                                         Src: &'a Value,
+                                         IsNaN: bool)
+                                         -> Option<&'a Value>;
+    pub fn LLVMRustBuildVectorReduceFMax(B: &Builder<'a>,
+                                         Src: &'a Value,
+                                         IsNaN: bool)
+                                         -> Option<&'a Value>;
+
+    pub fn LLVMRustBuildMinNum(
+        B: &Builder<'a>,
+        LHS: &'a Value,
+        LHS: &'a Value,
+    ) -> Option<&'a Value>;
+    pub fn LLVMRustBuildMaxNum(
+        B: &Builder<'a>,
+        LHS: &'a Value,
+        LHS: &'a Value,
+    ) -> Option<&'a Value>;
+
+    // Atomic Operations
+    pub fn LLVMRustBuildAtomicLoad(B: &Builder<'a>,
+                                   PointerVal: &'a Value,
+                                   Name: *const c_char,
+                                   Order: AtomicOrdering)
+                                   -> &'a Value;
+
+    pub fn LLVMRustBuildAtomicStore(B: &Builder<'a>,
+                                    Val: &'a Value,
+                                    Ptr: &'a Value,
+                                    Order: AtomicOrdering)
+                                    -> &'a Value;
+
+    pub fn LLVMRustBuildAtomicCmpXchg(B: &Builder<'a>,
+                                      LHS: &'a Value,
+                                      CMP: &'a Value,
+                                      RHS: &'a Value,
+                                      Order: AtomicOrdering,
+                                      FailureOrder: AtomicOrdering,
+                                      Weak: Bool)
+                                      -> &'a Value;
+
+    pub fn LLVMBuildAtomicRMW(B: &Builder<'a>,
+                              Op: AtomicRmwBinOp,
+                              LHS: &'a Value,
+                              RHS: &'a Value,
+                              Order: AtomicOrdering,
+                              SingleThreaded: Bool)
+                              -> &'a Value;
+
+    pub fn LLVMRustBuildAtomicFence(B: &Builder,
+                                    Order: AtomicOrdering,
+                                    Scope: SynchronizationScope);
+
+    /// Writes a module to the specified path. Returns 0 on success.
+    pub fn LLVMWriteBitcodeToFile(M: &Module, Path: *const c_char) -> c_int;
+
+    /// Creates a pass manager.
+    pub fn LLVMCreatePassManager() -> &'a mut PassManager<'a>;
+
+    /// Creates a function-by-function pass manager
+    pub fn LLVMCreateFunctionPassManagerForModule(M: &'a Module) -> &'a mut PassManager<'a>;
+
+    /// Disposes a pass manager.
+    pub fn LLVMDisposePassManager(PM: &'a mut PassManager<'a>);
+
+    /// Runs a pass manager on a module.
+    pub fn LLVMRunPassManager(PM: &PassManager<'a>, M: &'a Module) -> Bool;
+
+    pub fn LLVMInitializePasses();
+
+    pub fn LLVMPassManagerBuilderCreate() -> &'static mut PassManagerBuilder;
+    pub fn LLVMPassManagerBuilderDispose(PMB: &'static mut PassManagerBuilder);
+    pub fn LLVMPassManagerBuilderSetSizeLevel(PMB: &PassManagerBuilder, Value: Bool);
+    pub fn LLVMPassManagerBuilderSetDisableUnrollLoops(PMB: &PassManagerBuilder, Value: Bool);
+    pub fn LLVMPassManagerBuilderUseInlinerWithThreshold(PMB: &PassManagerBuilder,
+                                                         threshold: c_uint);
+    pub fn LLVMPassManagerBuilderPopulateModulePassManager(PMB: &PassManagerBuilder,
+                                                           PM: &PassManager);
+
+    pub fn LLVMPassManagerBuilderPopulateFunctionPassManager(PMB: &PassManagerBuilder,
+                                                             PM: &PassManager);
+    pub fn LLVMPassManagerBuilderPopulateLTOPassManager(PMB: &PassManagerBuilder,
+                                                        PM: &PassManager,
+                                                        Internalize: Bool,
+                                                        RunInliner: Bool);
+    pub fn LLVMRustPassManagerBuilderPopulateThinLTOPassManager(
+        PMB: &PassManagerBuilder,
+        PM: &PassManager) -> bool;
+
+    // Stuff that's in rustllvm/ because it's not upstream yet.
+
+    /// Opens an object file.
+    pub fn LLVMCreateObjectFile(
+        MemBuf: &'static mut MemoryBuffer,
+    ) -> Option<&'static mut ObjectFile>;
+    /// Closes an object file.
+    pub fn LLVMDisposeObjectFile(ObjFile: &'static mut ObjectFile);
+
+    /// Enumerates the sections in an object file.
+    pub fn LLVMGetSections(ObjFile: &'a ObjectFile) -> &'a mut SectionIterator<'a>;
+    /// Destroys a section iterator.
+    pub fn LLVMDisposeSectionIterator(SI: &'a mut SectionIterator<'a>);
+    /// Returns true if the section iterator is at the end of the section
+    /// list:
+    pub fn LLVMIsSectionIteratorAtEnd(ObjFile: &'a ObjectFile, SI: &SectionIterator<'a>) -> Bool;
+    /// Moves the section iterator to point to the next section.
+    pub fn LLVMMoveToNextSection(SI: &SectionIterator);
+    /// Returns the current section size.
+    pub fn LLVMGetSectionSize(SI: &SectionIterator) -> c_ulonglong;
+    /// Returns the current section contents as a string buffer.
+    pub fn LLVMGetSectionContents(SI: &SectionIterator) -> *const c_char;
+
+    /// Reads the given file and returns it as a memory buffer. Use
+    /// LLVMDisposeMemoryBuffer() to get rid of it.
+    pub fn LLVMRustCreateMemoryBufferWithContentsOfFile(
+        Path: *const c_char,
+    ) -> Option<&'static mut MemoryBuffer>;
+
+    pub fn LLVMStartMultithreaded() -> Bool;
+
+    /// Returns a string describing the last error caused by an LLVMRust* call.
+    pub fn LLVMRustGetLastError() -> *const c_char;
+
+    /// Print the pass timings since static dtors aren't picking them up.
+    pub fn LLVMRustPrintPassTimings();
+
+    pub fn LLVMStructCreateNamed(C: &Context, Name: *const c_char) -> &Type;
+
+    pub fn LLVMStructSetBody(StructTy: &'a Type,
+                             ElementTypes: *const &'a Type,
+                             ElementCount: c_uint,
+                             Packed: Bool);
+
+    /// Prepares inline assembly.
+    pub fn LLVMRustInlineAsm(Ty: &Type,
+                             AsmString: *const c_char,
+                             Constraints: *const c_char,
+                             SideEffects: Bool,
+                             AlignStack: Bool,
+                             Dialect: AsmDialect)
+                             -> &Value;
+
+    pub fn LLVMRustDebugMetadataVersion() -> u32;
+    pub fn LLVMRustVersionMajor() -> u32;
+    pub fn LLVMRustVersionMinor() -> u32;
+
+    pub fn LLVMRustAddModuleFlag(M: &Module, name: *const c_char, value: u32);
+
+    pub fn LLVMRustMetadataAsValue(C: &'a Context, MD: &'a Metadata) -> &'a Value;
+
+    pub fn LLVMRustDIBuilderCreate(M: &'a Module) -> &'a mut DIBuilder<'a>;
+
+    pub fn LLVMRustDIBuilderDispose(Builder: &'a mut DIBuilder<'a>);
+
+    pub fn LLVMRustDIBuilderFinalize(Builder: &DIBuilder);
+
+    pub fn LLVMRustDIBuilderCreateCompileUnit(Builder: &DIBuilder<'a>,
+                                              Lang: c_uint,
+                                              File: &'a DIFile,
+                                              Producer: *const c_char,
+                                              isOptimized: bool,
+                                              Flags: *const c_char,
+                                              RuntimeVer: c_uint,
+                                              SplitName: *const c_char)
+                                              -> &'a DIDescriptor;
+
+    pub fn LLVMRustDIBuilderCreateFile(Builder: &DIBuilder<'a>,
+                                       Filename: *const c_char,
+                                       Directory: *const c_char)
+                                       -> &'a DIFile;
+
+    pub fn LLVMRustDIBuilderCreateSubroutineType(Builder: &DIBuilder<'a>,
+                                                 File: &'a DIFile,
+                                                 ParameterTypes: &'a DIArray)
+                                                 -> &'a DICompositeType;
+
+    pub fn LLVMRustDIBuilderCreateFunction(Builder: &DIBuilder<'a>,
+                                           Scope: &'a DIDescriptor,
+                                           Name: *const c_char,
+                                           LinkageName: *const c_char,
+                                           File: &'a DIFile,
+                                           LineNo: c_uint,
+                                           Ty: &'a DIType,
+                                           isLocalToUnit: bool,
+                                           isDefinition: bool,
+                                           ScopeLine: c_uint,
+                                           Flags: DIFlags,
+                                           isOptimized: bool,
+                                           Fn: &'a Value,
+                                           TParam: &'a DIArray,
+                                           Decl: Option<&'a DIDescriptor>)
+                                           -> &'a DISubprogram;
+
+    pub fn LLVMRustDIBuilderCreateBasicType(Builder: &DIBuilder<'a>,
+                                            Name: *const c_char,
+                                            SizeInBits: u64,
+                                            AlignInBits: u32,
+                                            Encoding: c_uint)
+                                            -> &'a DIBasicType;
+
+    pub fn LLVMRustDIBuilderCreatePointerType(Builder: &DIBuilder<'a>,
+                                              PointeeTy: &'a DIType,
+                                              SizeInBits: u64,
+                                              AlignInBits: u32,
+                                              Name: *const c_char)
+                                              -> &'a DIDerivedType;
+
+    pub fn LLVMRustDIBuilderCreateStructType(Builder: &DIBuilder<'a>,
+                                             Scope: Option<&'a DIDescriptor>,
+                                             Name: *const c_char,
+                                             File: &'a DIFile,
+                                             LineNumber: c_uint,
+                                             SizeInBits: u64,
+                                             AlignInBits: u32,
+                                             Flags: DIFlags,
+                                             DerivedFrom: Option<&'a DIType>,
+                                             Elements: &'a DIArray,
+                                             RunTimeLang: c_uint,
+                                             VTableHolder: Option<&'a DIType>,
+                                             UniqueId: *const c_char)
+                                             -> &'a DICompositeType;
+
+    pub fn LLVMRustDIBuilderCreateMemberType(Builder: &DIBuilder<'a>,
+                                             Scope: &'a DIDescriptor,
+                                             Name: *const c_char,
+                                             File: &'a DIFile,
+                                             LineNo: c_uint,
+                                             SizeInBits: u64,
+                                             AlignInBits: u32,
+                                             OffsetInBits: u64,
+                                             Flags: DIFlags,
+                                             Ty: &'a DIType)
+                                             -> &'a DIDerivedType;
+
+    pub fn LLVMRustDIBuilderCreateLexicalBlock(Builder: &DIBuilder<'a>,
+                                               Scope: &'a DIScope,
+                                               File: &'a DIFile,
+                                               Line: c_uint,
+                                               Col: c_uint)
+                                               -> &'a DILexicalBlock;
+
+    pub fn LLVMRustDIBuilderCreateLexicalBlockFile(Builder: &DIBuilder<'a>,
+                                                   Scope: &'a DIScope,
+                                                   File: &'a DIFile)
+                                                   -> &'a DILexicalBlock;
+
+    pub fn LLVMRustDIBuilderCreateStaticVariable(Builder: &DIBuilder<'a>,
+                                                 Context: Option<&'a DIScope>,
+                                                 Name: *const c_char,
+                                                 LinkageName: *const c_char,
+                                                 File: &'a DIFile,
+                                                 LineNo: c_uint,
+                                                 Ty: &'a DIType,
+                                                 isLocalToUnit: bool,
+                                                 Val: &'a Value,
+                                                 Decl: Option<&'a DIDescriptor>,
+                                                 AlignInBits: u32)
+                                                 -> &'a DIGlobalVariable;
+
+    pub fn LLVMRustDIBuilderCreateVariable(Builder: &DIBuilder<'a>,
+                                           Tag: c_uint,
+                                           Scope: &'a DIDescriptor,
+                                           Name: *const c_char,
+                                           File: &'a DIFile,
+                                           LineNo: c_uint,
+                                           Ty: &'a DIType,
+                                           AlwaysPreserve: bool,
+                                           Flags: DIFlags,
+                                           ArgNo: c_uint,
+                                           AlignInBits: u32)
+                                           -> &'a DIVariable;
+
+    pub fn LLVMRustDIBuilderCreateArrayType(Builder: &DIBuilder<'a>,
+                                            Size: u64,
+                                            AlignInBits: u32,
+                                            Ty: &'a DIType,
+                                            Subscripts: &'a DIArray)
+                                            -> &'a DIType;
+
+    pub fn LLVMRustDIBuilderGetOrCreateSubrange(Builder: &DIBuilder<'a>,
+                                                Lo: i64,
+                                                Count: i64)
+                                                -> &'a DISubrange;
+
+    pub fn LLVMRustDIBuilderGetOrCreateArray(Builder: &DIBuilder<'a>,
+                                             Ptr: *const Option<&'a DIDescriptor>,
+                                             Count: c_uint)
+                                             -> &'a DIArray;
+
+    pub fn LLVMRustDIBuilderInsertDeclareAtEnd(Builder: &DIBuilder<'a>,
+                                               Val: &'a Value,
+                                               VarInfo: &'a DIVariable,
+                                               AddrOps: *const i64,
+                                               AddrOpsCount: c_uint,
+                                               DL: &'a Value,
+                                               InsertAtEnd: &'a BasicBlock)
+                                               -> &'a Value;
+
+    pub fn LLVMRustDIBuilderCreateEnumerator(Builder: &DIBuilder<'a>,
+                                             Name: *const c_char,
+                                             Val: u64)
+                                             -> &'a DIEnumerator;
+
+    pub fn LLVMRustDIBuilderCreateEnumerationType(Builder: &DIBuilder<'a>,
+                                                  Scope: &'a DIScope,
+                                                  Name: *const c_char,
+                                                  File: &'a DIFile,
+                                                  LineNumber: c_uint,
+                                                  SizeInBits: u64,
+                                                  AlignInBits: u32,
+                                                  Elements: &'a DIArray,
+                                                  ClassType: &'a DIType)
+                                                  -> &'a DIType;
+
+    pub fn LLVMRustDIBuilderCreateUnionType(Builder: &DIBuilder<'a>,
+                                            Scope: &'a DIScope,
+                                            Name: *const c_char,
+                                            File: &'a DIFile,
+                                            LineNumber: c_uint,
+                                            SizeInBits: u64,
+                                            AlignInBits: u32,
+                                            Flags: DIFlags,
+                                            Elements: Option<&'a DIArray>,
+                                            RunTimeLang: c_uint,
+                                            UniqueId: *const c_char)
+                                            -> &'a DIType;
+
+    pub fn LLVMSetUnnamedAddr(GlobalVar: &Value, UnnamedAddr: Bool);
+
+    pub fn LLVMRustDIBuilderCreateTemplateTypeParameter(Builder: &DIBuilder<'a>,
+                                                        Scope: Option<&'a DIScope>,
+                                                        Name: *const c_char,
+                                                        Ty: &'a DIType,
+                                                        File: &'a DIFile,
+                                                        LineNo: c_uint,
+                                                        ColumnNo: c_uint)
+                                                        -> &'a DITemplateTypeParameter;
+
+
+    pub fn LLVMRustDIBuilderCreateNameSpace(Builder: &DIBuilder<'a>,
+                                            Scope: Option<&'a DIScope>,
+                                            Name: *const c_char,
+                                            File: &'a DIFile,
+                                            LineNo: c_uint)
+                                            -> &'a DINameSpace;
+
+    pub fn LLVMRustDICompositeTypeSetTypeArray(Builder: &DIBuilder<'a>,
+                                               CompositeType: &'a DIType,
+                                               TypeArray: &'a DIArray);
+
+
+    pub fn LLVMRustDIBuilderCreateDebugLocation(Context: &'a Context,
+                                                Line: c_uint,
+                                                Column: c_uint,
+                                                Scope: &'a DIScope,
+                                                InlinedAt: Option<&'a Metadata>)
+                                                -> &'a Value;
+    pub fn LLVMRustDIBuilderCreateOpDeref() -> i64;
+    pub fn LLVMRustDIBuilderCreateOpPlusUconst() -> i64;
+}
+
+#[allow(improper_ctypes)] // FIXME(#52456) needed for RustString.
+extern "C" {
+    pub fn LLVMRustWriteTypeToString(Type: &Type, s: &RustString);
+    pub fn LLVMRustWriteValueToString(value_ref: &Value, s: &RustString);
+}
+
+extern "C" {
+    pub fn LLVMIsAConstantInt(value_ref: &Value) -> Option<&Value>;
+    pub fn LLVMIsAConstantFP(value_ref: &Value) -> Option<&Value>;
+
+    pub fn LLVMRustPassKind(Pass: &Pass) -> PassKind;
+    pub fn LLVMRustFindAndCreatePass(Pass: *const c_char) -> Option<&'static mut Pass>;
+    pub fn LLVMRustAddPass(PM: &PassManager, Pass: &'static mut Pass);
+
+    pub fn LLVMRustHasFeature(T: &TargetMachine, s: *const c_char) -> bool;
+
+    pub fn LLVMRustPrintTargetCPUs(T: &TargetMachine);
+    pub fn LLVMRustPrintTargetFeatures(T: &TargetMachine);
+
+    pub fn LLVMRustCreateTargetMachine(Triple: *const c_char,
+                                       CPU: *const c_char,
+                                       Features: *const c_char,
+                                       Model: CodeModel,
+                                       Reloc: RelocMode,
+                                       Level: CodeGenOptLevel,
+                                       UseSoftFP: bool,
+                                       PositionIndependentExecutable: bool,
+                                       FunctionSections: bool,
+                                       DataSections: bool,
+                                       TrapUnreachable: bool,
+                                       Singlethread: bool)
+                                       -> Option<&'static mut TargetMachine>;
+    pub fn LLVMRustDisposeTargetMachine(T: &'static mut TargetMachine);
+    pub fn LLVMRustAddAnalysisPasses(T: &'a TargetMachine, PM: &PassManager<'a>, M: &'a Module);
+    pub fn LLVMRustAddBuilderLibraryInfo(PMB: &'a PassManagerBuilder,
+                                         M: &'a Module,
+                                         DisableSimplifyLibCalls: bool);
+    pub fn LLVMRustConfigurePassManagerBuilder(PMB: &PassManagerBuilder,
+                                               OptLevel: CodeGenOptLevel,
+                                               MergeFunctions: bool,
+                                               SLPVectorize: bool,
+                                               LoopVectorize: bool,
+                                               PrepareForThinLTO: bool,
+                                               PGOGenPath: *const c_char,
+                                               PGOUsePath: *const c_char);
+    pub fn LLVMRustAddLibraryInfo(PM: &PassManager<'a>,
+                                  M: &'a Module,
+                                  DisableSimplifyLibCalls: bool);
+    pub fn LLVMRustRunFunctionPassManager(PM: &PassManager<'a>, M: &'a Module);
+    pub fn LLVMRustWriteOutputFile(T: &'a TargetMachine,
+                                   PM: &PassManager<'a>,
+                                   M: &'a Module,
+                                   Output: *const c_char,
+                                   FileType: FileType)
+                                   -> LLVMRustResult;
+    pub fn LLVMRustPrintModule(PM: &PassManager<'a>,
+                               M: &'a Module,
+                               Output: *const c_char,
+                               Demangle: extern fn(*const c_char,
+                                                   size_t,
+                                                   *mut c_char,
+                                                   size_t) -> size_t);
+    pub fn LLVMRustSetLLVMOptions(Argc: c_int, Argv: *const *const c_char);
+    pub fn LLVMRustPrintPasses();
+    pub fn LLVMRustSetNormalizedTarget(M: &Module, triple: *const c_char);
+    pub fn LLVMRustAddAlwaysInlinePass(P: &PassManagerBuilder, AddLifetimes: bool);
+    pub fn LLVMRustRunRestrictionPass(M: &Module, syms: *const *const c_char, len: size_t);
+    pub fn LLVMRustMarkAllFunctionsNounwind(M: &Module);
+
+    pub fn LLVMRustOpenArchive(path: *const c_char) -> Option<&'static mut Archive>;
+    pub fn LLVMRustArchiveIteratorNew(AR: &'a Archive) -> &'a mut ArchiveIterator<'a>;
+    pub fn LLVMRustArchiveIteratorNext(
+        AIR: &ArchiveIterator<'a>,
+    ) -> Option<&'a mut ArchiveChild<'a>>;
+    pub fn LLVMRustArchiveChildName(ACR: &ArchiveChild, size: &mut size_t) -> *const c_char;
+    pub fn LLVMRustArchiveChildData(ACR: &ArchiveChild, size: &mut size_t) -> *const c_char;
+    pub fn LLVMRustArchiveChildFree(ACR: &'a mut ArchiveChild<'a>);
+    pub fn LLVMRustArchiveIteratorFree(AIR: &'a mut ArchiveIterator<'a>);
+    pub fn LLVMRustDestroyArchive(AR: &'static mut Archive);
+
+    pub fn LLVMRustGetSectionName(SI: &SectionIterator, data: &mut *const c_char) -> size_t;
+}
+
+#[allow(improper_ctypes)] // FIXME(#52456) needed for RustString.
+extern "C" {
+    pub fn LLVMRustWriteTwineToString(T: &Twine, s: &RustString);
+}
+
+extern "C" {
+    pub fn LLVMContextSetDiagnosticHandler(C: &Context,
+                                           Handler: DiagnosticHandler,
+                                           DiagnosticContext: *mut c_void);
+}
+
+#[allow(improper_ctypes)] // FIXME(#52456) needed for RustString.
+extern "C" {
+    pub fn LLVMRustUnpackOptimizationDiagnostic(DI: &'a DiagnosticInfo,
+                                                pass_name_out: &RustString,
+                                                function_out: &mut Option<&'a Value>,
+                                                loc_line_out: &mut c_uint,
+                                                loc_column_out: &mut c_uint,
+                                                loc_filename_out: &RustString,
+                                                message_out: &RustString);
+}
+
+extern "C" {
+    pub fn LLVMRustUnpackInlineAsmDiagnostic(DI: &'a DiagnosticInfo,
+                                             cookie_out: &mut c_uint,
+                                             message_out: &mut Option<&'a Twine>,
+                                             instruction_out: &mut Option<&'a Value>);
+}
+
+#[allow(improper_ctypes)] // FIXME(#52456) needed for RustString.
+extern "C" {
+    pub fn LLVMRustWriteDiagnosticInfoToString(DI: &DiagnosticInfo, s: &RustString);
+}
+
+extern "C" {
+    pub fn LLVMRustGetDiagInfoKind(DI: &DiagnosticInfo) -> DiagnosticKind;
+
+    pub fn LLVMRustSetInlineAsmDiagnosticHandler(C: &Context,
+                                                 H: InlineAsmDiagHandler,
+                                                 CX: *mut c_void);
+}
+
+#[allow(improper_ctypes)] // FIXME(#52456) needed for RustString.
+extern "C" {
+    pub fn LLVMRustWriteSMDiagnosticToString(d: &SMDiagnostic, s: &RustString);
+}
+
+extern "C" {
+    pub fn LLVMRustWriteArchive(Dst: *const c_char,
+                                NumMembers: size_t,
+                                Members: *const &RustArchiveMember,
+                                WriteSymbtab: bool,
+                                Kind: ArchiveKind)
+                                -> LLVMRustResult;
+    pub fn LLVMRustArchiveMemberNew(Filename: *const c_char,
+                                    Name: *const c_char,
+                                    Child: Option<&'a ArchiveChild>)
+                                    -> &'a mut RustArchiveMember<'a>;
+    pub fn LLVMRustArchiveMemberFree(Member: &'a mut RustArchiveMember<'a>);
+
+    pub fn LLVMRustSetDataLayoutFromTargetMachine(M: &'a Module, TM: &'a TargetMachine);
+
+    pub fn LLVMRustBuildOperandBundleDef(Name: *const c_char,
+                                         Inputs: *const &'a Value,
+                                         NumInputs: c_uint)
+                                         -> &'a mut OperandBundleDef<'a>;
+    pub fn LLVMRustFreeOperandBundleDef(Bundle: &'a mut OperandBundleDef<'a>);
+
+    pub fn LLVMRustPositionBuilderAtStart(B: &Builder<'a>, BB: &'a BasicBlock);
+
+    pub fn LLVMRustSetComdat(M: &'a Module, V: &'a Value, Name: *const c_char);
+    pub fn LLVMRustUnsetComdat(V: &Value);
+    pub fn LLVMRustSetModulePIELevel(M: &Module);
+    pub fn LLVMRustModuleBufferCreate(M: &Module) -> &'static mut ModuleBuffer;
+    pub fn LLVMRustModuleBufferPtr(p: &ModuleBuffer) -> *const u8;
+    pub fn LLVMRustModuleBufferLen(p: &ModuleBuffer) -> usize;
+    pub fn LLVMRustModuleBufferFree(p: &'static mut ModuleBuffer);
+    pub fn LLVMRustModuleCost(M: &Module) -> u64;
+
+    pub fn LLVMRustThinLTOAvailable() -> bool;
+    pub fn LLVMRustPGOAvailable() -> bool;
+    pub fn LLVMRustThinLTOBufferCreate(M: &Module) -> &'static mut ThinLTOBuffer;
+    pub fn LLVMRustThinLTOBufferFree(M: &'static mut ThinLTOBuffer);
+    pub fn LLVMRustThinLTOBufferPtr(M: &ThinLTOBuffer) -> *const c_char;
+    pub fn LLVMRustThinLTOBufferLen(M: &ThinLTOBuffer) -> size_t;
+    pub fn LLVMRustCreateThinLTOData(
+        Modules: *const ThinLTOModule,
+        NumModules: c_uint,
+        PreservedSymbols: *const *const c_char,
+        PreservedSymbolsLen: c_uint,
+    ) -> Option<&'static mut ThinLTOData>;
+    pub fn LLVMRustPrepareThinLTORename(
+        Data: &ThinLTOData,
+        Module: &Module,
+    ) -> bool;
+    pub fn LLVMRustPrepareThinLTOResolveWeak(
+        Data: &ThinLTOData,
+        Module: &Module,
+    ) -> bool;
+    pub fn LLVMRustPrepareThinLTOInternalize(
+        Data: &ThinLTOData,
+        Module: &Module,
+    ) -> bool;
+    pub fn LLVMRustPrepareThinLTOImport(
+        Data: &ThinLTOData,
+        Module: &Module,
+    ) -> bool;
+    pub fn LLVMRustFreeThinLTOData(Data: &'static mut ThinLTOData);
+    pub fn LLVMRustParseBitcodeForThinLTO(
+        Context: &Context,
+        Data: *const u8,
+        len: usize,
+        Identifier: *const c_char,
+    ) -> Option<&Module>;
+    pub fn LLVMRustThinLTOGetDICompileUnit(M: &Module,
+                                           CU1: &mut *mut c_void,
+                                           CU2: &mut *mut c_void);
+    pub fn LLVMRustThinLTOPatchDICompileUnit(M: &Module, CU: *mut c_void);
+
+    pub fn LLVMRustLinkerNew(M: &'a Module) -> &'a mut Linker<'a>;
+    pub fn LLVMRustLinkerAdd(linker: &Linker,
+                             bytecode: *const c_char,
+                             bytecode_len: usize) -> bool;
+    pub fn LLVMRustLinkerFree(linker: &'a mut Linker<'a>);
+}
diff --git a/src/librustc_codegen_llvm/llvm/mod.rs b/src/librustc_codegen_llvm/llvm/mod.rs
new file mode 100644
index 00000000000..558d2a2bc87
--- /dev/null
+++ b/src/librustc_codegen_llvm/llvm/mod.rs
@@ -0,0 +1,281 @@
+// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![allow(non_upper_case_globals)]
+#![allow(non_camel_case_types)]
+#![allow(non_snake_case)]
+#![deny(bare_trait_objects)]
+
+pub use self::IntPredicate::*;
+pub use self::RealPredicate::*;
+pub use self::AtomicRmwBinOp::*;
+pub use self::MetadataType::*;
+pub use self::CodeGenOptSize::*;
+pub use self::CallConv::*;
+pub use self::Linkage::*;
+
+use std::str::FromStr;
+use std::string::FromUtf8Error;
+use std::slice;
+use std::ffi::{CString, CStr};
+use std::cell::RefCell;
+use libc::{self, c_uint, c_char, size_t};
+
+pub mod archive_ro;
+pub mod diagnostic;
+mod ffi;
+
+pub use self::ffi::*;
+
+impl LLVMRustResult {
+    pub fn into_result(self) -> Result<(), ()> {
+        match self {
+            LLVMRustResult::Success => Ok(()),
+            LLVMRustResult::Failure => Err(()),
+        }
+    }
+}
+
+pub fn AddFunctionAttrStringValue(llfn: &'a Value,
+                                  idx: AttributePlace,
+                                  attr: &CStr,
+                                  value: &CStr) {
+    unsafe {
+        LLVMRustAddFunctionAttrStringValue(llfn,
+                                           idx.as_uint(),
+                                           attr.as_ptr(),
+                                           value.as_ptr())
+    }
+}
+
+#[derive(Copy, Clone)]
+pub enum AttributePlace {
+    ReturnValue,
+    Argument(u32),
+    Function,
+}
+
+impl AttributePlace {
+    pub fn as_uint(self) -> c_uint {
+        match self {
+            AttributePlace::ReturnValue => 0,
+            AttributePlace::Argument(i) => 1 + i,
+            AttributePlace::Function => !0,
+        }
+    }
+}
+
+#[derive(Copy, Clone, PartialEq)]
+#[repr(C)]
+pub enum CodeGenOptSize {
+    CodeGenOptSizeNone = 0,
+    CodeGenOptSizeDefault = 1,
+    CodeGenOptSizeAggressive = 2,
+}
+
+impl FromStr for ArchiveKind {
+    type Err = ();
+
+    fn from_str(s: &str) -> Result<Self, Self::Err> {
+        match s {
+            "gnu" => Ok(ArchiveKind::K_GNU),
+            "bsd" => Ok(ArchiveKind::K_BSD),
+            "coff" => Ok(ArchiveKind::K_COFF),
+            _ => Err(()),
+        }
+    }
+}
+
+#[repr(C)]
+pub struct RustString {
+    bytes: RefCell<Vec<u8>>,
+}
+
+/// Appending to a Rust string -- used by RawRustStringOstream.
+#[no_mangle]
+pub unsafe extern "C" fn LLVMRustStringWriteImpl(sr: &RustString,
+                                                 ptr: *const c_char,
+                                                 size: size_t) {
+    let slice = slice::from_raw_parts(ptr as *const u8, size as usize);
+
+    sr.bytes.borrow_mut().extend_from_slice(slice);
+}
+
+pub fn SetInstructionCallConv(instr: &'a Value, cc: CallConv) {
+    unsafe {
+        LLVMSetInstructionCallConv(instr, cc as c_uint);
+    }
+}
+pub fn SetFunctionCallConv(fn_: &'a Value, cc: CallConv) {
+    unsafe {
+        LLVMSetFunctionCallConv(fn_, cc as c_uint);
+    }
+}
+
+// Externally visible symbols that might appear in multiple codegen units need to appear in
+// their own comdat section so that the duplicates can be discarded at link time. This can for
+// example happen for generics when using multiple codegen units. This function simply uses the
+// value's name as the comdat value to make sure that it is in a 1-to-1 relationship to the
+// function.
+// For more details on COMDAT sections see e.g. http://www.airs.com/blog/archives/52
+pub fn SetUniqueComdat(llmod: &Module, val: &'a Value) {
+    unsafe {
+        LLVMRustSetComdat(llmod, val, LLVMGetValueName(val));
+    }
+}
+
+pub fn UnsetComdat(val: &'a Value) {
+    unsafe {
+        LLVMRustUnsetComdat(val);
+    }
+}
+
+pub fn SetUnnamedAddr(global: &'a Value, unnamed: bool) {
+    unsafe {
+        LLVMSetUnnamedAddr(global, unnamed as Bool);
+    }
+}
+
+pub fn set_thread_local(global: &'a Value, is_thread_local: bool) {
+    unsafe {
+        LLVMSetThreadLocal(global, is_thread_local as Bool);
+    }
+}
+pub fn set_thread_local_mode(global: &'a Value, mode: ThreadLocalMode) {
+    unsafe {
+        LLVMSetThreadLocalMode(global, mode);
+    }
+}
+
+impl Attribute {
+    pub fn apply_llfn(&self, idx: AttributePlace, llfn: &Value) {
+        unsafe { LLVMRustAddFunctionAttribute(llfn, idx.as_uint(), *self) }
+    }
+
+    pub fn apply_callsite(&self, idx: AttributePlace, callsite: &Value) {
+        unsafe { LLVMRustAddCallSiteAttribute(callsite, idx.as_uint(), *self) }
+    }
+
+    pub fn unapply_llfn(&self, idx: AttributePlace, llfn: &Value) {
+        unsafe { LLVMRustRemoveFunctionAttributes(llfn, idx.as_uint(), *self) }
+    }
+
+    pub fn toggle_llfn(&self, idx: AttributePlace, llfn: &Value, set: bool) {
+        if set {
+            self.apply_llfn(idx, llfn);
+        } else {
+            self.unapply_llfn(idx, llfn);
+        }
+    }
+}
+
+// Memory-managed interface to object files.
+
+pub struct ObjectFile {
+    pub llof: &'static mut ffi::ObjectFile,
+}
+
+unsafe impl Send for ObjectFile {}
+
+impl ObjectFile {
+    // This will take ownership of llmb
+    pub fn new(llmb: &'static mut MemoryBuffer) -> Option<ObjectFile> {
+        unsafe {
+            let llof = LLVMCreateObjectFile(llmb)?;
+            Some(ObjectFile { llof: llof })
+        }
+    }
+}
+
+impl Drop for ObjectFile {
+    fn drop(&mut self) {
+        unsafe {
+            LLVMDisposeObjectFile(&mut *(self.llof as *mut _));
+        }
+    }
+}
+
+// Memory-managed interface to section iterators.
+
+pub struct SectionIter<'a> {
+    pub llsi: &'a mut SectionIterator<'a>,
+}
+
+impl Drop for SectionIter<'a> {
+    fn drop(&mut self) {
+        unsafe {
+            LLVMDisposeSectionIterator(&mut *(self.llsi as *mut _));
+        }
+    }
+}
+
+pub fn mk_section_iter(llof: &'a ffi::ObjectFile) -> SectionIter<'a> {
+    unsafe { SectionIter { llsi: LLVMGetSections(llof) } }
+}
+
+/// Safe wrapper around `LLVMGetParam`, because segfaults are no fun.
+pub fn get_param(llfn: &'a Value, index: c_uint) -> &'a Value {
+    unsafe {
+        assert!(index < LLVMCountParams(llfn),
+            "out of bounds argument access: {} out of {} arguments", index, LLVMCountParams(llfn));
+        LLVMGetParam(llfn, index)
+    }
+}
+
+pub fn build_string(f: impl FnOnce(&RustString)) -> Result<String, FromUtf8Error> {
+    let sr = RustString {
+        bytes: RefCell::new(Vec::new()),
+    };
+    f(&sr);
+    String::from_utf8(sr.bytes.into_inner())
+}
+
+pub fn twine_to_string(tr: &Twine) -> String {
+    unsafe {
+        build_string(|s| LLVMRustWriteTwineToString(tr, s))
+            .expect("got a non-UTF8 Twine from LLVM")
+    }
+}
+
+pub fn last_error() -> Option<String> {
+    unsafe {
+        let cstr = LLVMRustGetLastError();
+        if cstr.is_null() {
+            None
+        } else {
+            let err = CStr::from_ptr(cstr).to_bytes();
+            let err = String::from_utf8_lossy(err).to_string();
+            libc::free(cstr as *mut _);
+            Some(err)
+        }
+    }
+}
+
+pub struct OperandBundleDef<'a> {
+    pub raw: &'a mut ffi::OperandBundleDef<'a>,
+}
+
+impl OperandBundleDef<'a> {
+    pub fn new(name: &str, vals: &[&'a Value]) -> Self {
+        let name = CString::new(name).unwrap();
+        let def = unsafe {
+            LLVMRustBuildOperandBundleDef(name.as_ptr(), vals.as_ptr(), vals.len() as c_uint)
+        };
+        OperandBundleDef { raw: def }
+    }
+}
+
+impl Drop for OperandBundleDef<'a> {
+    fn drop(&mut self) {
+        unsafe {
+            LLVMRustFreeOperandBundleDef(&mut *(self.raw as *mut _));
+        }
+    }
+}
diff --git a/src/librustc_codegen_llvm/llvm_util.rs b/src/librustc_codegen_llvm/llvm_util.rs
index e941998098d..441fff5f08c 100644
--- a/src/librustc_codegen_llvm/llvm_util.rs
+++ b/src/librustc_codegen_llvm/llvm_util.rs
@@ -73,7 +73,7 @@ unsafe fn configure_llvm(sess: &Session) {
 
     llvm::LLVMInitializePasses();
 
-    llvm::initialize_available_targets();
+    ::rustc_llvm::initialize_available_targets();
 
     llvm::LLVMRustSetLLVMOptions(llvm_args.len() as c_int,
                                  llvm_args.as_ptr());
diff --git a/src/librustc_codegen_llvm/metadata.rs b/src/librustc_codegen_llvm/metadata.rs
index 144baa65c1b..fcb704413ef 100644
--- a/src/librustc_codegen_llvm/metadata.rs
+++ b/src/librustc_codegen_llvm/metadata.rs
@@ -58,10 +58,8 @@ impl MetadataLoader for LlvmMetadataLoader {
                           -> Result<MetadataRef, String> {
         unsafe {
             let buf = common::path2cstr(filename);
-            let mb = llvm::LLVMRustCreateMemoryBufferWithContentsOfFile(buf.as_ptr());
-            if mb as isize == 0 {
-                return Err(format!("error reading library: '{}'", filename.display()));
-            }
+            let mb = llvm::LLVMRustCreateMemoryBufferWithContentsOfFile(buf.as_ptr())
+                .ok_or_else(|| format!("error reading library: '{}'", filename.display()))?;
             let of = ObjectFile::new(mb)
                 .map(|of| OwningRef::new(box of))
                 .ok_or_else(|| format!("provided path not an object file: '{}'",
diff --git a/src/librustc_codegen_llvm/meth.rs b/src/librustc_codegen_llvm/meth.rs
index 21bbdf31dcb..9c0dd0dc3d8 100644
--- a/src/librustc_codegen_llvm/meth.rs
+++ b/src/librustc_codegen_llvm/meth.rs
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use llvm::ValueRef;
 use abi::{FnType, FnTypeExt};
 use callee;
 use common::*;
@@ -17,6 +16,7 @@ use consts;
 use monomorphize;
 use type_::Type;
 use value::Value;
+
 use rustc::ty::{self, Ty};
 use rustc::ty::layout::HasDataLayout;
 use debuginfo;
@@ -33,11 +33,11 @@ impl<'a, 'tcx> VirtualIndex {
         VirtualIndex(index as u64 + 3)
     }
 
-    pub fn get_fn(self, bx: &Builder<'a, 'tcx>,
-                  llvtable: ValueRef,
-                  fn_ty: &FnType<'tcx, Ty<'tcx>>) -> ValueRef {
+    pub fn get_fn(self, bx: &Builder<'a, 'll, 'tcx>,
+                  llvtable: &'ll Value,
+                  fn_ty: &FnType<'tcx, Ty<'tcx>>) -> &'ll Value {
         // Load the data pointer from the object.
-        debug!("get_fn({:?}, {:?})", Value(llvtable), self);
+        debug!("get_fn({:?}, {:?})", llvtable, self);
 
         let llvtable = bx.pointercast(llvtable, fn_ty.llvm_type(bx.cx).ptr_to().ptr_to());
         let ptr_align = bx.tcx().data_layout.pointer_align;
@@ -48,9 +48,9 @@ impl<'a, 'tcx> VirtualIndex {
         ptr
     }
 
-    pub fn get_usize(self, bx: &Builder<'a, 'tcx>, llvtable: ValueRef) -> ValueRef {
+    pub fn get_usize(self, bx: &Builder<'a, 'll, 'tcx>, llvtable: &'ll Value) -> &'ll Value {
         // Load the data pointer from the object.
-        debug!("get_int({:?}, {:?})", Value(llvtable), self);
+        debug!("get_int({:?}, {:?})", llvtable, self);
 
         let llvtable = bx.pointercast(llvtable, Type::isize(bx.cx).ptr_to());
         let usize_align = bx.tcx().data_layout.pointer_align;
@@ -69,11 +69,11 @@ impl<'a, 'tcx> VirtualIndex {
 /// The `trait_ref` encodes the erased self type. Hence if we are
 /// making an object `Foo<Trait>` from a value of type `Foo<T>`, then
 /// `trait_ref` would map `T:Trait`.
-pub fn get_vtable<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
-                            ty: Ty<'tcx>,
-                            trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>)
-                            -> ValueRef
-{
+pub fn get_vtable(
+    cx: &CodegenCx<'ll, 'tcx>,
+    ty: Ty<'tcx>,
+    trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>,
+) -> &'ll Value {
     let tcx = cx.tcx;
 
     debug!("get_vtable(ty={:?}, trait_ref={:?})", ty, trait_ref);
diff --git a/src/librustc_codegen_llvm/mir/analyze.rs b/src/librustc_codegen_llvm/mir/analyze.rs
index e105baba8aa..2c205803524 100644
--- a/src/librustc_codegen_llvm/mir/analyze.rs
+++ b/src/librustc_codegen_llvm/mir/analyze.rs
@@ -22,7 +22,7 @@ use rustc::ty::layout::LayoutOf;
 use type_of::LayoutLlvmExt;
 use super::FunctionCx;
 
-pub fn non_ssa_locals<'a, 'tcx>(fx: &FunctionCx<'a, 'tcx>) -> BitVector<mir::Local> {
+pub fn non_ssa_locals(fx: &FunctionCx<'a, 'll, 'tcx>) -> BitVector<mir::Local> {
     let mir = fx.mir;
     let mut analyzer = LocalAnalyzer::new(fx);
 
@@ -34,7 +34,7 @@ pub fn non_ssa_locals<'a, 'tcx>(fx: &FunctionCx<'a, 'tcx>) -> BitVector<mir::Loc
         let layout = fx.cx.layout_of(ty);
         if layout.is_llvm_immediate() {
             // These sorts of types are immediates that we can store
-            // in an ValueRef without an alloca.
+            // in an Value without an alloca.
         } else if layout.is_llvm_scalar_pair() {
             // We allow pairs and uses of any of their 2 fields.
         } else {
@@ -51,8 +51,8 @@ pub fn non_ssa_locals<'a, 'tcx>(fx: &FunctionCx<'a, 'tcx>) -> BitVector<mir::Loc
     analyzer.non_ssa_locals
 }
 
-struct LocalAnalyzer<'mir, 'a: 'mir, 'tcx: 'a> {
-    fx: &'mir FunctionCx<'a, 'tcx>,
+struct LocalAnalyzer<'mir, 'a: 'mir, 'll: 'a, 'tcx: 'll> {
+    fx: &'mir FunctionCx<'a, 'll, 'tcx>,
     dominators: Dominators<mir::BasicBlock>,
     non_ssa_locals: BitVector<mir::Local>,
     // The location of the first visited direct assignment to each
@@ -60,8 +60,8 @@ struct LocalAnalyzer<'mir, 'a: 'mir, 'tcx: 'a> {
     first_assignment: IndexVec<mir::Local, Location>
 }
 
-impl<'mir, 'a, 'tcx> LocalAnalyzer<'mir, 'a, 'tcx> {
-    fn new(fx: &'mir FunctionCx<'a, 'tcx>) -> LocalAnalyzer<'mir, 'a, 'tcx> {
+impl LocalAnalyzer<'mir, 'a, 'll, 'tcx> {
+    fn new(fx: &'mir FunctionCx<'a, 'll, 'tcx>) -> Self {
         let invalid_location =
             mir::BasicBlock::new(fx.mir.basic_blocks().len()).start_location();
         let mut analyzer = LocalAnalyzer {
@@ -102,7 +102,7 @@ impl<'mir, 'a, 'tcx> LocalAnalyzer<'mir, 'a, 'tcx> {
     }
 }
 
-impl<'mir, 'a, 'tcx> Visitor<'tcx> for LocalAnalyzer<'mir, 'a, 'tcx> {
+impl Visitor<'tcx> for LocalAnalyzer<'mir, 'a, 'll, 'tcx> {
     fn visit_assign(&mut self,
                     block: mir::BasicBlock,
                     place: &mir::Place<'tcx>,
diff --git a/src/librustc_codegen_llvm/mir/block.rs b/src/librustc_codegen_llvm/mir/block.rs
index dc4b9e0ae99..684ecfaeec8 100644
--- a/src/librustc_codegen_llvm/mir/block.rs
+++ b/src/librustc_codegen_llvm/mir/block.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use llvm::{self, ValueRef, BasicBlockRef};
+use llvm::{self, BasicBlock};
 use rustc::middle::lang_items;
 use rustc::ty::{self, Ty, TypeFoldable};
 use rustc::ty::layout::{self, LayoutOf};
@@ -24,6 +24,7 @@ use meth;
 use monomorphize;
 use type_of::LayoutLlvmExt;
 use type_::Type;
+use value::Value;
 
 use syntax::symbol::Symbol;
 use syntax_pos::Pos;
@@ -33,7 +34,7 @@ use super::place::PlaceRef;
 use super::operand::OperandRef;
 use super::operand::OperandValue::{Pair, Ref, Immediate};
 
-impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
+impl FunctionCx<'a, 'll, 'tcx> {
     pub fn codegen_block(&mut self, bb: mir::BasicBlock) {
         let mut bx = self.build_block(bb);
         let data = &self.mir[bb];
@@ -48,7 +49,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
     }
 
     fn codegen_terminator(&mut self,
-                        mut bx: Builder<'a, 'tcx>,
+                        mut bx: Builder<'a, 'll, 'tcx>,
                         bb: mir::BasicBlock,
                         terminator: &mir::Terminator<'tcx>)
     {
@@ -97,7 +98,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
             }
         };
 
-        let funclet_br = |this: &mut Self, bx: Builder, target: mir::BasicBlock| {
+        let funclet_br = |this: &mut Self, bx: Builder<'_, 'll, '_>, target: mir::BasicBlock| {
             let (lltarget, is_cleanupret) = lltarget(this, target);
             if is_cleanupret {
                 // micro-optimization: generate a `ret` rather than a jump
@@ -110,11 +111,11 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
 
         let do_call = |
             this: &mut Self,
-            bx: Builder<'a, 'tcx>,
+            bx: Builder<'a, 'll, 'tcx>,
             fn_ty: FnType<'tcx, Ty<'tcx>>,
-            fn_ptr: ValueRef,
-            llargs: &[ValueRef],
-            destination: Option<(ReturnDest<'tcx>, mir::BasicBlock)>,
+            fn_ptr: &'ll Value,
+            llargs: &[&'ll Value],
+            destination: Option<(ReturnDest<'ll, 'tcx>, mir::BasicBlock)>,
             cleanup: Option<mir::BasicBlock>
         | {
             if let Some(cleanup) = cleanup {
@@ -285,8 +286,14 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
                 }
 
                 let place = self.codegen_place(&bx, location);
-                let mut args: &[_] = &[place.llval, place.llextra];
-                args = &args[..1 + place.has_extra() as usize];
+                let (args1, args2);
+                let mut args = if let Some(llextra) = place.llextra {
+                    args2 = [place.llval, llextra];
+                    &args2[..]
+                } else {
+                    args1 = [place.llval];
+                    &args1[..]
+                };
                 let (drop_fn, fn_ty) = match ty.sty {
                     ty::TyDynamic(..) => {
                         let fn_ty = drop_fn.ty(bx.cx.tcx);
@@ -296,8 +303,9 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
                             &sig,
                         );
                         let fn_ty = FnType::new_vtable(bx.cx, sig, &[]);
+                        let vtable = args[1];
                         args = &args[..1];
-                        (meth::DESTRUCTOR.get_fn(&bx, place.llextra, &fn_ty), fn_ty)
+                        (meth::DESTRUCTOR.get_fn(&bx, vtable, &fn_ty), fn_ty)
                     }
                     _ => {
                         (callee::get_fn(bx.cx, drop_fn),
@@ -627,9 +635,9 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
     }
 
     fn codegen_argument(&mut self,
-                      bx: &Builder<'a, 'tcx>,
-                      op: OperandRef<'tcx>,
-                      llargs: &mut Vec<ValueRef>,
+                      bx: &Builder<'a, 'll, 'tcx>,
+                      op: OperandRef<'ll, 'tcx>,
+                      llargs: &mut Vec<&'ll Value>,
                       arg: &ArgType<'tcx, Ty<'tcx>>) {
         // Fill padding with undef value, where applicable.
         if let Some(ty) = arg.pad {
@@ -706,9 +714,9 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
     }
 
     fn codegen_arguments_untupled(&mut self,
-                                bx: &Builder<'a, 'tcx>,
+                                bx: &Builder<'a, 'll, 'tcx>,
                                 operand: &mir::Operand<'tcx>,
-                                llargs: &mut Vec<ValueRef>,
+                                llargs: &mut Vec<&'ll Value>,
                                 args: &[ArgType<'tcx, Ty<'tcx>>]) {
         let tuple = self.codegen_operand(bx, operand);
 
@@ -728,7 +736,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
         }
     }
 
-    fn get_personality_slot(&mut self, bx: &Builder<'a, 'tcx>) -> PlaceRef<'tcx> {
+    fn get_personality_slot(&mut self, bx: &Builder<'a, 'll, 'tcx>) -> PlaceRef<'ll, 'tcx> {
         let cx = bx.cx;
         if let Some(slot) = self.personality_slot {
             slot
@@ -746,7 +754,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
     /// Return the landingpad wrapper around the given basic block
     ///
     /// No-op in MSVC SEH scheme.
-    fn landing_pad_to(&mut self, target_bb: mir::BasicBlock) -> BasicBlockRef {
+    fn landing_pad_to(&mut self, target_bb: mir::BasicBlock) -> &'ll BasicBlock {
         if let Some(block) = self.landing_pads[target_bb] {
             return block;
         }
@@ -757,7 +765,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
         landing_pad
     }
 
-    fn landing_pad_uncached(&mut self, target_bb: BasicBlockRef) -> BasicBlockRef {
+    fn landing_pad_uncached(&mut self, target_bb: &'ll BasicBlock) -> &'ll BasicBlock {
         if base::wants_msvc_seh(self.cx.sess()) {
             span_bug!(self.mir.span, "landing pad was not inserted?")
         }
@@ -777,12 +785,12 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
         bx.llbb()
     }
 
-    fn landing_pad_type(&self) -> Type {
+    fn landing_pad_type(&self) -> &'ll Type {
         let cx = self.cx;
         Type::struct_(cx, &[Type::i8p(cx), Type::i32(cx)], false)
     }
 
-    fn unreachable_block(&mut self) -> BasicBlockRef {
+    fn unreachable_block(&mut self) -> &'ll BasicBlock {
         self.unreachable_block.unwrap_or_else(|| {
             let bl = self.new_block("unreachable");
             bl.unreachable();
@@ -791,20 +799,20 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
         })
     }
 
-    pub fn new_block(&self, name: &str) -> Builder<'a, 'tcx> {
+    pub fn new_block(&self, name: &str) -> Builder<'a, 'll, 'tcx> {
         Builder::new_block(self.cx, self.llfn, name)
     }
 
-    pub fn build_block(&self, bb: mir::BasicBlock) -> Builder<'a, 'tcx> {
+    pub fn build_block(&self, bb: mir::BasicBlock) -> Builder<'a, 'll, 'tcx> {
         let bx = Builder::with_cx(self.cx);
         bx.position_at_end(self.blocks[bb]);
         bx
     }
 
-    fn make_return_dest(&mut self, bx: &Builder<'a, 'tcx>,
+    fn make_return_dest(&mut self, bx: &Builder<'a, 'll, 'tcx>,
                         dest: &mir::Place<'tcx>, fn_ret: &ArgType<'tcx, Ty<'tcx>>,
-                        llargs: &mut Vec<ValueRef>, is_intrinsic: bool)
-                        -> ReturnDest<'tcx> {
+                        llargs: &mut Vec<&'ll Value>, is_intrinsic: bool)
+                        -> ReturnDest<'ll, 'tcx> {
         // If the return is ignored, we can just return a do-nothing ReturnDest
         if fn_ret.is_ignore() {
             return ReturnDest::Nothing;
@@ -857,7 +865,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
         }
     }
 
-    fn codegen_transmute(&mut self, bx: &Builder<'a, 'tcx>,
+    fn codegen_transmute(&mut self, bx: &Builder<'a, 'll, 'tcx>,
                        src: &mir::Operand<'tcx>,
                        dst: &mir::Place<'tcx>) {
         if let mir::Place::Local(index) = *dst {
@@ -884,9 +892,9 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
         }
     }
 
-    fn codegen_transmute_into(&mut self, bx: &Builder<'a, 'tcx>,
+    fn codegen_transmute_into(&mut self, bx: &Builder<'a, 'll, 'tcx>,
                             src: &mir::Operand<'tcx>,
-                            dst: PlaceRef<'tcx>) {
+                            dst: PlaceRef<'ll, 'tcx>) {
         let src = self.codegen_operand(bx, src);
         let llty = src.layout.llvm_type(bx.cx);
         let cast_ptr = bx.pointercast(dst.llval, llty.ptr_to());
@@ -897,10 +905,10 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
 
     // Stores the return value of a function call into it's final location.
     fn store_return(&mut self,
-                    bx: &Builder<'a, 'tcx>,
-                    dest: ReturnDest<'tcx>,
+                    bx: &Builder<'a, 'll, 'tcx>,
+                    dest: ReturnDest<'ll, 'tcx>,
                     ret_ty: &ArgType<'tcx, Ty<'tcx>>,
-                    llval: ValueRef) {
+                    llval: &'ll Value) {
         use self::ReturnDest::*;
 
         match dest {
@@ -929,13 +937,13 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
     }
 }
 
-enum ReturnDest<'tcx> {
+enum ReturnDest<'ll, 'tcx> {
     // Do nothing, the return value is indirect or ignored
     Nothing,
     // Store the return value to the pointer
-    Store(PlaceRef<'tcx>),
+    Store(PlaceRef<'ll, 'tcx>),
     // Stores an indirect return value to an operand local place
-    IndirectOperand(PlaceRef<'tcx>, mir::Local),
+    IndirectOperand(PlaceRef<'ll, 'tcx>, mir::Local),
     // Stores a direct return value to an operand local place
     DirectOperand(mir::Local)
 }
diff --git a/src/librustc_codegen_llvm/mir/constant.rs b/src/librustc_codegen_llvm/mir/constant.rs
index 0d682d5d6f6..341ed9df64b 100644
--- a/src/librustc_codegen_llvm/mir/constant.rs
+++ b/src/librustc_codegen_llvm/mir/constant.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use llvm::{self, ValueRef};
+use llvm;
 use rustc::mir::interpret::ConstEvalErr;
 use rustc_mir::interpret::{read_target_uint, const_val_field};
 use rustc::hir::def_id::DefId;
@@ -26,14 +26,17 @@ use type_of::LayoutLlvmExt;
 use type_::Type;
 use syntax::ast::Mutability;
 use syntax::codemap::Span;
+use value::Value;
 
 use super::super::callee;
 use super::FunctionCx;
 
-pub fn scalar_to_llvm(cx: &CodegenCx,
-                       cv: Scalar,
-                       layout: &layout::Scalar,
-                       llty: Type) -> ValueRef {
+pub fn scalar_to_llvm(
+    cx: &CodegenCx<'ll, '_>,
+    cv: Scalar,
+    layout: &layout::Scalar,
+    llty: &'ll Type,
+) -> &'ll Value {
     let bitsize = if layout.is_bool() { 1 } else { layout.value.size(cx).bits() };
     match cv {
         Scalar::Bits { defined, .. } if (defined as u64) < bitsize || defined == 0 => {
@@ -42,7 +45,7 @@ pub fn scalar_to_llvm(cx: &CodegenCx,
         Scalar::Bits { bits, .. } => {
             let llval = C_uint_big(Type::ix(cx, bitsize), bits);
             if layout.value == layout::Pointer {
-                unsafe { llvm::LLVMConstIntToPtr(llval, llty.to_ref()) }
+                unsafe { llvm::LLVMConstIntToPtr(llval, llty) }
             } else {
                 consts::bitcast(llval, llty)
             }
@@ -73,7 +76,7 @@ pub fn scalar_to_llvm(cx: &CodegenCx,
                 1,
             ) };
             if layout.value != layout::Pointer {
-                unsafe { llvm::LLVMConstPtrToInt(llval, llty.to_ref()) }
+                unsafe { llvm::LLVMConstPtrToInt(llval, llty) }
             } else {
                 consts::bitcast(llval, llty)
             }
@@ -81,7 +84,7 @@ pub fn scalar_to_llvm(cx: &CodegenCx,
     }
 }
 
-pub fn const_alloc_to_llvm(cx: &CodegenCx, alloc: &Allocation) -> ValueRef {
+pub fn const_alloc_to_llvm(cx: &CodegenCx<'ll, '_>, alloc: &Allocation) -> &'ll Value {
     let mut llvals = Vec::with_capacity(alloc.relocations.len() + 1);
     let layout = cx.data_layout();
     let pointer_size = layout.pointer_size.bytes() as usize;
@@ -116,10 +119,10 @@ pub fn const_alloc_to_llvm(cx: &CodegenCx, alloc: &Allocation) -> ValueRef {
     C_struct(cx, &llvals, true)
 }
 
-pub fn codegen_static_initializer<'a, 'tcx>(
-    cx: &CodegenCx<'a, 'tcx>,
+pub fn codegen_static_initializer(
+    cx: &CodegenCx<'ll, 'tcx>,
     def_id: DefId,
-) -> Result<(ValueRef, &'tcx Allocation), Lrc<ConstEvalErr<'tcx>>> {
+) -> Result<(&'ll Value, &'tcx Allocation), Lrc<ConstEvalErr<'tcx>>> {
     let instance = ty::Instance::mono(cx.tcx, def_id);
     let cid = GlobalId {
         instance,
@@ -135,10 +138,10 @@ pub fn codegen_static_initializer<'a, 'tcx>(
     Ok((const_alloc_to_llvm(cx, alloc), alloc))
 }
 
-impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
+impl FunctionCx<'a, 'll, 'tcx> {
     fn fully_evaluate(
         &mut self,
-        bx: &Builder<'a, 'tcx>,
+        bx: &Builder<'a, 'll, 'tcx>,
         constant: &'tcx ty::Const<'tcx>,
     ) -> Result<&'tcx ty::Const<'tcx>, Lrc<ConstEvalErr<'tcx>>> {
         match constant.val {
@@ -158,7 +161,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
 
     pub fn eval_mir_constant(
         &mut self,
-        bx: &Builder<'a, 'tcx>,
+        bx: &Builder<'a, 'll, 'tcx>,
         constant: &mir::Constant<'tcx>,
     ) -> Result<&'tcx ty::Const<'tcx>, Lrc<ConstEvalErr<'tcx>>> {
         let c = self.monomorphize(&constant.literal);
@@ -168,11 +171,11 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
     /// process constant containing SIMD shuffle indices
     pub fn simd_shuffle_indices(
         &mut self,
-        bx: &Builder<'a, 'tcx>,
+        bx: &Builder<'a, 'll, 'tcx>,
         span: Span,
         ty: Ty<'tcx>,
         constant: Result<&'tcx ty::Const<'tcx>, Lrc<ConstEvalErr<'tcx>>>,
-    ) -> (ValueRef, Ty<'tcx>) {
+    ) -> (&'ll Value, Ty<'tcx>) {
         constant
             .and_then(|c| {
                 let field_ty = c.ty.builtin_index().unwrap();
@@ -180,7 +183,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
                     ty::TyArray(_, n) => n.unwrap_usize(bx.tcx()),
                     ref other => bug!("invalid simd shuffle type: {}", other),
                 };
-                let values: Result<Vec<ValueRef>, Lrc<_>> = (0..fields).map(|field| {
+                let values: Result<Vec<_>, Lrc<_>> = (0..fields).map(|field| {
                     let field = const_val_field(
                         bx.tcx(),
                         ty::ParamEnv::reveal_all(),
diff --git a/src/librustc_codegen_llvm/mir/mod.rs b/src/librustc_codegen_llvm/mir/mod.rs
index 312939408c6..8cdd0398eff 100644
--- a/src/librustc_codegen_llvm/mir/mod.rs
+++ b/src/librustc_codegen_llvm/mir/mod.rs
@@ -10,7 +10,7 @@
 
 use common::{C_i32, C_null};
 use libc::c_uint;
-use llvm::{self, ValueRef, BasicBlockRef};
+use llvm::{self, BasicBlock};
 use llvm::debuginfo::DIScope;
 use rustc::ty::{self, Ty, TypeFoldable, UpvarSubsts};
 use rustc::ty::layout::{LayoutOf, TyLayout};
@@ -24,6 +24,7 @@ use debuginfo::{self, declare_local, VariableAccess, VariableKind, FunctionDebug
 use monomorphize::Instance;
 use abi::{ArgTypeExt, FnType, FnTypeExt, PassMode};
 use type_::Type;
+use value::Value;
 
 use syntax_pos::{DUMMY_SP, NO_EXPANSION, BytePos, Span};
 use syntax::symbol::keywords;
@@ -42,16 +43,16 @@ use rustc::mir::traversal;
 use self::operand::{OperandRef, OperandValue};
 
 /// Master context for codegenning from MIR.
-pub struct FunctionCx<'a, 'tcx:'a> {
+pub struct FunctionCx<'a, 'll: 'a, 'tcx: 'll> {
     instance: Instance<'tcx>,
 
     mir: &'a mir::Mir<'tcx>,
 
-    debug_context: debuginfo::FunctionDebugContext,
+    debug_context: FunctionDebugContext<'ll>,
 
-    llfn: ValueRef,
+    llfn: &'ll Value,
 
-    cx: &'a CodegenCx<'a, 'tcx>,
+    cx: &'a CodegenCx<'ll, 'tcx>,
 
     fn_ty: FnType<'tcx, Ty<'tcx>>,
 
@@ -62,24 +63,24 @@ pub struct FunctionCx<'a, 'tcx:'a> {
     /// don't really care about it very much. Anyway, this value
     /// contains an alloca into which the personality is stored and
     /// then later loaded when generating the DIVERGE_BLOCK.
-    personality_slot: Option<PlaceRef<'tcx>>,
+    personality_slot: Option<PlaceRef<'ll, 'tcx>>,
 
     /// A `Block` for each MIR `BasicBlock`
-    blocks: IndexVec<mir::BasicBlock, BasicBlockRef>,
+    blocks: IndexVec<mir::BasicBlock, &'ll BasicBlock>,
 
     /// The funclet status of each basic block
     cleanup_kinds: IndexVec<mir::BasicBlock, analyze::CleanupKind>,
 
     /// When targeting MSVC, this stores the cleanup info for each funclet
     /// BB. This is initialized as we compute the funclets' head block in RPO.
-    funclets: &'a IndexVec<mir::BasicBlock, Option<Funclet>>,
+    funclets: &'a IndexVec<mir::BasicBlock, Option<Funclet<'ll>>>,
 
     /// This stores the landing-pad block for a given BB, computed lazily on GNU
     /// and eagerly on MSVC.
-    landing_pads: IndexVec<mir::BasicBlock, Option<BasicBlockRef>>,
+    landing_pads: IndexVec<mir::BasicBlock, Option<&'ll BasicBlock>>,
 
     /// Cached unreachable block
-    unreachable_block: Option<BasicBlockRef>,
+    unreachable_block: Option<&'ll BasicBlock>,
 
     /// The location where each MIR arg/var/tmp/ret is stored. This is
     /// usually an `PlaceRef` representing an alloca, but not always:
@@ -96,16 +97,16 @@ pub struct FunctionCx<'a, 'tcx:'a> {
     ///
     /// Avoiding allocs can also be important for certain intrinsics,
     /// notably `expect`.
-    locals: IndexVec<mir::Local, LocalRef<'tcx>>,
+    locals: IndexVec<mir::Local, LocalRef<'ll, 'tcx>>,
 
     /// Debug information for MIR scopes.
-    scopes: IndexVec<mir::SourceScope, debuginfo::MirDebugScope>,
+    scopes: IndexVec<mir::SourceScope, debuginfo::MirDebugScope<'ll>>,
 
     /// If this function is being monomorphized, this contains the type substitutions used.
     param_substs: &'tcx Substs<'tcx>,
 }
 
-impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
+impl FunctionCx<'a, 'll, 'tcx> {
     pub fn monomorphize<T>(&self, value: &T) -> T
         where T: TypeFoldable<'tcx>
     {
@@ -116,12 +117,12 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
         )
     }
 
-    pub fn set_debug_loc(&mut self, bx: &Builder, source_info: mir::SourceInfo) {
+    pub fn set_debug_loc(&mut self, bx: &Builder<'_, 'll, '_>, source_info: mir::SourceInfo) {
         let (scope, span) = self.debug_loc(source_info);
         debuginfo::set_source_location(&self.debug_context, bx, scope, span);
     }
 
-    pub fn debug_loc(&mut self, source_info: mir::SourceInfo) -> (DIScope, Span) {
+    pub fn debug_loc(&mut self, source_info: mir::SourceInfo) -> (Option<&'ll DIScope>, Span) {
         // Bail out if debug info emission is not enabled.
         match self.debug_context {
             FunctionDebugContext::DebugInfoDisabled |
@@ -161,29 +162,29 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
     // corresponding to span's containing source scope.  If so, we need to create a DIScope
     // "extension" into that file.
     fn scope_metadata_for_loc(&self, scope_id: mir::SourceScope, pos: BytePos)
-                               -> llvm::debuginfo::DIScope {
+                               -> Option<&'ll DIScope> {
         let scope_metadata = self.scopes[scope_id].scope_metadata;
         if pos < self.scopes[scope_id].file_start_pos ||
            pos >= self.scopes[scope_id].file_end_pos {
             let cm = self.cx.sess().codemap();
             let defining_crate = self.debug_context.get_ref(DUMMY_SP).defining_crate;
-            debuginfo::extend_scope_to_file(self.cx,
-                                            scope_metadata,
+            Some(debuginfo::extend_scope_to_file(self.cx,
+                                            scope_metadata.unwrap(),
                                             &cm.lookup_char_pos(pos).file,
-                                            defining_crate)
+                                            defining_crate))
         } else {
             scope_metadata
         }
     }
 }
 
-enum LocalRef<'tcx> {
-    Place(PlaceRef<'tcx>),
-    Operand(Option<OperandRef<'tcx>>),
+enum LocalRef<'ll, 'tcx> {
+    Place(PlaceRef<'ll, 'tcx>),
+    Operand(Option<OperandRef<'ll, 'tcx>>),
 }
 
-impl<'a, 'tcx> LocalRef<'tcx> {
-    fn new_operand(cx: &CodegenCx<'a, 'tcx>, layout: TyLayout<'tcx>) -> LocalRef<'tcx> {
+impl LocalRef<'ll, 'tcx> {
+    fn new_operand(cx: &CodegenCx<'ll, 'tcx>, layout: TyLayout<'tcx>) -> LocalRef<'ll, 'tcx> {
         if layout.is_zst() {
             // Zero-size temporaries aren't always initialized, which
             // doesn't matter because they don't contain data, but
@@ -197,9 +198,9 @@ impl<'a, 'tcx> LocalRef<'tcx> {
 
 ///////////////////////////////////////////////////////////////////////////
 
-pub fn codegen_mir<'a, 'tcx: 'a>(
-    cx: &'a CodegenCx<'a, 'tcx>,
-    llfn: ValueRef,
+pub fn codegen_mir(
+    cx: &'a CodegenCx<'ll, 'tcx>,
+    llfn: &'ll Value,
     mir: &'a Mir<'tcx>,
     instance: Instance<'tcx>,
     sig: ty::FnSig<'tcx>,
@@ -218,7 +219,7 @@ pub fn codegen_mir<'a, 'tcx: 'a>(
     // Allocate a `Block` for every basic block, except
     // the start block, if nothing loops back to it.
     let reentrant_start_block = !mir.predecessors_for(mir::START_BLOCK).is_empty();
-    let block_bxs: IndexVec<mir::BasicBlock, BasicBlockRef> =
+    let block_bxs: IndexVec<mir::BasicBlock, &'ll BasicBlock> =
         mir.basic_blocks().indices().map(|bb| {
             if bb == mir::START_BLOCK && !reentrant_start_block {
                 bx.llbb()
@@ -280,7 +281,7 @@ pub fn codegen_mir<'a, 'tcx: 'a>(
                         span: decl.source_info.span,
                         scope: decl.visibility_scope,
                     });
-                    declare_local(&bx, &fx.debug_context, name, layout.ty, scope,
+                    declare_local(&bx, &fx.debug_context, name, layout.ty, scope.unwrap(),
                         VariableAccess::DirectVariable { alloca: place.llval },
                         VariableKind::LocalVariable, span);
                 }
@@ -343,13 +344,13 @@ pub fn codegen_mir<'a, 'tcx: 'a>(
     }
 }
 
-fn create_funclets<'a, 'tcx>(
+fn create_funclets(
     mir: &'a Mir<'tcx>,
-    bx: &Builder<'a, 'tcx>,
+    bx: &Builder<'a, 'll, 'tcx>,
     cleanup_kinds: &IndexVec<mir::BasicBlock, CleanupKind>,
-    block_bxs: &IndexVec<mir::BasicBlock, BasicBlockRef>)
-    -> (IndexVec<mir::BasicBlock, Option<BasicBlockRef>>,
-        IndexVec<mir::BasicBlock, Option<Funclet>>)
+    block_bxs: &IndexVec<mir::BasicBlock, &'ll BasicBlock>)
+    -> (IndexVec<mir::BasicBlock, Option<&'ll BasicBlock>>,
+        IndexVec<mir::BasicBlock, Option<Funclet<'ll>>>)
 {
     block_bxs.iter_enumerated().zip(cleanup_kinds).map(|((bb, &llbb), cleanup_kind)| {
         match *cleanup_kind {
@@ -409,14 +410,15 @@ fn create_funclets<'a, 'tcx>(
     }).unzip()
 }
 
-/// Produce, for each argument, a `ValueRef` pointing at the
+/// Produce, for each argument, a `Value` pointing at the
 /// argument's value. As arguments are places, these are always
 /// indirect.
-fn arg_local_refs<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
-                            fx: &FunctionCx<'a, 'tcx>,
-                            scopes: &IndexVec<mir::SourceScope, debuginfo::MirDebugScope>,
-                            memory_locals: &BitVector<mir::Local>)
-                            -> Vec<LocalRef<'tcx>> {
+fn arg_local_refs(
+    bx: &Builder<'a, 'll, 'tcx>,
+    fx: &FunctionCx<'a, 'll, 'tcx>,
+    scopes: &IndexVec<mir::SourceScope, debuginfo::MirDebugScope<'ll>>,
+    memory_locals: &BitVector<mir::Local>,
+) -> Vec<LocalRef<'ll, 'tcx>> {
     let mir = fx.mir;
     let tcx = bx.tcx();
     let mut idx = 0;
@@ -424,8 +426,8 @@ fn arg_local_refs<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
 
     // Get the argument scope, if it exists and if we need it.
     let arg_scope = scopes[mir::OUTERMOST_SOURCE_SCOPE];
-    let arg_scope = if arg_scope.is_valid() && bx.sess().opts.debuginfo == FullDebugInfo {
-        Some(arg_scope.scope_metadata)
+    let arg_scope = if bx.sess().opts.debuginfo == FullDebugInfo {
+        arg_scope.scope_metadata
     } else {
         None
     };
diff --git a/src/librustc_codegen_llvm/mir/operand.rs b/src/librustc_codegen_llvm/mir/operand.rs
index c433df51110..1296f5e4b14 100644
--- a/src/librustc_codegen_llvm/mir/operand.rs
+++ b/src/librustc_codegen_llvm/mir/operand.rs
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use llvm::ValueRef;
 use rustc::mir::interpret::ConstEvalErr;
 use rustc::mir;
 use rustc::mir::interpret::ConstValue;
@@ -24,7 +23,6 @@ use value::Value;
 use type_of::LayoutLlvmExt;
 
 use std::fmt;
-use std::ptr;
 
 use super::{FunctionCx, LocalRef};
 use super::constant::scalar_to_llvm;
@@ -33,31 +31,15 @@ use super::place::PlaceRef;
 /// The representation of a Rust value. The enum variant is in fact
 /// uniquely determined by the value's type, but is kept as a
 /// safety check.
-#[derive(Copy, Clone)]
-pub enum OperandValue {
+#[derive(Copy, Clone, Debug)]
+pub enum OperandValue<'ll> {
     /// A reference to the actual operand. The data is guaranteed
     /// to be valid for the operand's lifetime.
-    Ref(ValueRef, Align),
+    Ref(&'ll Value, Align),
     /// A single LLVM value.
-    Immediate(ValueRef),
+    Immediate(&'ll Value),
     /// A pair of immediate LLVM values. Used by fat pointers too.
-    Pair(ValueRef, ValueRef)
-}
-
-impl fmt::Debug for OperandValue {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        match *self {
-            OperandValue::Ref(r, align) => {
-                write!(f, "Ref({:?}, {:?})", Value(r), align)
-            }
-            OperandValue::Immediate(i) => {
-                write!(f, "Immediate({:?})", Value(i))
-            }
-            OperandValue::Pair(a, b) => {
-                write!(f, "Pair({:?}, {:?})", Value(a), Value(b))
-            }
-        }
-    }
+    Pair(&'ll Value, &'ll Value)
 }
 
 /// An `OperandRef` is an "SSA" reference to a Rust value, along with
@@ -69,23 +51,23 @@ impl fmt::Debug for OperandValue {
 /// directly is sure to cause problems -- use `OperandRef::store`
 /// instead.
 #[derive(Copy, Clone)]
-pub struct OperandRef<'tcx> {
+pub struct OperandRef<'ll, 'tcx> {
     // The value.
-    pub val: OperandValue,
+    pub val: OperandValue<'ll>,
 
     // The layout of value, based on its Rust type.
     pub layout: TyLayout<'tcx>,
 }
 
-impl<'tcx> fmt::Debug for OperandRef<'tcx> {
+impl fmt::Debug for OperandRef<'ll, 'tcx> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         write!(f, "OperandRef({:?} @ {:?})", self.val, self.layout)
     }
 }
 
-impl<'a, 'tcx> OperandRef<'tcx> {
-    pub fn new_zst(cx: &CodegenCx<'a, 'tcx>,
-                   layout: TyLayout<'tcx>) -> OperandRef<'tcx> {
+impl OperandRef<'ll, 'tcx> {
+    pub fn new_zst(cx: &CodegenCx<'ll, 'tcx>,
+                   layout: TyLayout<'tcx>) -> OperandRef<'ll, 'tcx> {
         assert!(layout.is_zst());
         OperandRef {
             val: OperandValue::Immediate(C_undef(layout.immediate_llvm_type(cx))),
@@ -93,9 +75,9 @@ impl<'a, 'tcx> OperandRef<'tcx> {
         }
     }
 
-    pub fn from_const(bx: &Builder<'a, 'tcx>,
+    pub fn from_const(bx: &Builder<'a, 'll, 'tcx>,
                       val: &'tcx ty::Const<'tcx>)
-                      -> Result<OperandRef<'tcx>, Lrc<ConstEvalErr<'tcx>>> {
+                      -> Result<OperandRef<'ll, 'tcx>, Lrc<ConstEvalErr<'tcx>>> {
         let layout = bx.cx.layout_of(val.ty);
 
         if layout.is_zst() {
@@ -149,19 +131,19 @@ impl<'a, 'tcx> OperandRef<'tcx> {
 
     /// Asserts that this operand refers to a scalar and returns
     /// a reference to its value.
-    pub fn immediate(self) -> ValueRef {
+    pub fn immediate(self) -> &'ll Value {
         match self.val {
             OperandValue::Immediate(s) => s,
             _ => bug!("not immediate: {:?}", self)
         }
     }
 
-    pub fn deref(self, cx: &CodegenCx<'a, 'tcx>) -> PlaceRef<'tcx> {
+    pub fn deref(self, cx: &CodegenCx<'ll, 'tcx>) -> PlaceRef<'ll, 'tcx> {
         let projected_ty = self.layout.ty.builtin_deref(true)
             .unwrap_or_else(|| bug!("deref of non-pointer {:?}", self)).ty;
         let (llptr, llextra) = match self.val {
-            OperandValue::Immediate(llptr) => (llptr, ptr::null_mut()),
-            OperandValue::Pair(llptr, llextra) => (llptr, llextra),
+            OperandValue::Immediate(llptr) => (llptr, None),
+            OperandValue::Pair(llptr, llextra) => (llptr, Some(llextra)),
             OperandValue::Ref(..) => bug!("Deref of by-Ref operand {:?}", self)
         };
         let layout = cx.layout_of(projected_ty);
@@ -175,7 +157,7 @@ impl<'a, 'tcx> OperandRef<'tcx> {
 
     /// If this operand is a `Pair`, we return an aggregate with the two values.
     /// For other cases, see `immediate`.
-    pub fn immediate_or_packed_pair(self, bx: &Builder<'a, 'tcx>) -> ValueRef {
+    pub fn immediate_or_packed_pair(self, bx: &Builder<'a, 'll, 'tcx>) -> &'ll Value {
         if let OperandValue::Pair(a, b) = self.val {
             let llty = self.layout.llvm_type(bx.cx);
             debug!("Operand::immediate_or_packed_pair: packing {:?} into {:?}",
@@ -191,10 +173,10 @@ impl<'a, 'tcx> OperandRef<'tcx> {
     }
 
     /// If the type is a pair, we return a `Pair`, otherwise, an `Immediate`.
-    pub fn from_immediate_or_packed_pair(bx: &Builder<'a, 'tcx>,
-                                         llval: ValueRef,
+    pub fn from_immediate_or_packed_pair(bx: &Builder<'a, 'll, 'tcx>,
+                                         llval: &'ll Value,
                                          layout: TyLayout<'tcx>)
-                                         -> OperandRef<'tcx> {
+                                         -> OperandRef<'ll, 'tcx> {
         let val = if let layout::Abi::ScalarPair(ref a, ref b) = layout.abi {
             debug!("Operand::from_immediate_or_packed_pair: unpacking {:?} @ {:?}",
                     llval, layout);
@@ -209,7 +191,7 @@ impl<'a, 'tcx> OperandRef<'tcx> {
         OperandRef { val, layout }
     }
 
-    pub fn extract_field(&self, bx: &Builder<'a, 'tcx>, i: usize) -> OperandRef<'tcx> {
+    pub fn extract_field(&self, bx: &Builder<'a, 'll, 'tcx>, i: usize) -> OperandRef<'ll, 'tcx> {
         let field = self.layout.field(bx.cx, i);
         let offset = self.layout.fields.offset(i);
 
@@ -267,24 +249,29 @@ impl<'a, 'tcx> OperandRef<'tcx> {
     }
 }
 
-impl<'a, 'tcx> OperandValue {
-    pub fn store(self, bx: &Builder<'a, 'tcx>, dest: PlaceRef<'tcx>) {
+impl OperandValue<'ll> {
+    pub fn store(self, bx: &Builder<'a, 'll, 'tcx>, dest: PlaceRef<'ll, 'tcx>) {
         self.store_with_flags(bx, dest, MemFlags::empty());
     }
 
-    pub fn volatile_store(self, bx: &Builder<'a, 'tcx>, dest: PlaceRef<'tcx>) {
+    pub fn volatile_store(self, bx: &Builder<'a, 'll, 'tcx>, dest: PlaceRef<'ll, 'tcx>) {
         self.store_with_flags(bx, dest, MemFlags::VOLATILE);
     }
 
-    pub fn unaligned_volatile_store(self, bx: &Builder<'a, 'tcx>, dest: PlaceRef<'tcx>) {
+    pub fn unaligned_volatile_store(self, bx: &Builder<'a, 'll, 'tcx>, dest: PlaceRef<'ll, 'tcx>) {
         self.store_with_flags(bx, dest, MemFlags::VOLATILE | MemFlags::UNALIGNED);
     }
 
-    pub fn nontemporal_store(self, bx: &Builder<'a, 'tcx>, dest: PlaceRef<'tcx>) {
+    pub fn nontemporal_store(self, bx: &Builder<'a, 'll, 'tcx>, dest: PlaceRef<'ll, 'tcx>) {
         self.store_with_flags(bx, dest, MemFlags::NONTEMPORAL);
     }
 
-    fn store_with_flags(self, bx: &Builder<'a, 'tcx>, dest: PlaceRef<'tcx>, flags: MemFlags) {
+    fn store_with_flags(
+        self,
+        bx: &Builder<'a, 'll, 'tcx>,
+        dest: PlaceRef<'ll, 'tcx>,
+        flags: MemFlags,
+    ) {
         debug!("OperandRef::store: operand={:?}, dest={:?}", self, dest);
         // Avoid generating stores of zero-sized values, because the only way to have a zero-sized
         // value is through `undef`, and store itself is useless.
@@ -311,11 +298,11 @@ impl<'a, 'tcx> OperandValue {
     }
 }
 
-impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
+impl FunctionCx<'a, 'll, 'tcx> {
     fn maybe_codegen_consume_direct(&mut self,
-                                  bx: &Builder<'a, 'tcx>,
+                                  bx: &Builder<'a, 'll, 'tcx>,
                                   place: &mir::Place<'tcx>)
-                                   -> Option<OperandRef<'tcx>>
+                                   -> Option<OperandRef<'ll, 'tcx>>
     {
         debug!("maybe_codegen_consume_direct(place={:?})", place);
 
@@ -361,9 +348,9 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
     }
 
     pub fn codegen_consume(&mut self,
-                         bx: &Builder<'a, 'tcx>,
+                         bx: &Builder<'a, 'll, 'tcx>,
                          place: &mir::Place<'tcx>)
-                         -> OperandRef<'tcx>
+                         -> OperandRef<'ll, 'tcx>
     {
         debug!("codegen_consume(place={:?})", place);
 
@@ -385,9 +372,9 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
     }
 
     pub fn codegen_operand(&mut self,
-                         bx: &Builder<'a, 'tcx>,
+                         bx: &Builder<'a, 'll, 'tcx>,
                          operand: &mir::Operand<'tcx>)
-                         -> OperandRef<'tcx>
+                         -> OperandRef<'ll, 'tcx>
     {
         debug!("codegen_operand(operand={:?})", operand);
 
diff --git a/src/librustc_codegen_llvm/mir/place.rs b/src/librustc_codegen_llvm/mir/place.rs
index 9abf9077a95..abc3dbdab2f 100644
--- a/src/librustc_codegen_llvm/mir/place.rs
+++ b/src/librustc_codegen_llvm/mir/place.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use llvm::{self, ValueRef, LLVMConstInBoundsGEP};
+use llvm::{self, LLVMConstInBoundsGEP};
 use rustc::ty::{self, Ty};
 use rustc::ty::layout::{self, Align, TyLayout, LayoutOf, Size};
 use rustc::mir;
@@ -24,18 +24,16 @@ use value::Value;
 use glue;
 use mir::constant::const_alloc_to_llvm;
 
-use std::ptr;
-
 use super::{FunctionCx, LocalRef};
 use super::operand::{OperandRef, OperandValue};
 
 #[derive(Copy, Clone, Debug)]
-pub struct PlaceRef<'tcx> {
+pub struct PlaceRef<'ll, 'tcx> {
     /// Pointer to the contents of the place
-    pub llval: ValueRef,
+    pub llval: &'ll Value,
 
     /// This place's extra data if it is unsized, or null
-    pub llextra: ValueRef,
+    pub llextra: Option<&'ll Value>,
 
     /// Monomorphized type of this place, including variant information
     pub layout: TyLayout<'tcx>,
@@ -44,25 +42,26 @@ pub struct PlaceRef<'tcx> {
     pub align: Align,
 }
 
-impl<'a, 'tcx> PlaceRef<'tcx> {
-    pub fn new_sized(llval: ValueRef,
-                     layout: TyLayout<'tcx>,
-                     align: Align)
-                     -> PlaceRef<'tcx> {
+impl PlaceRef<'ll, 'tcx> {
+    pub fn new_sized(
+        llval: &'ll Value,
+        layout: TyLayout<'tcx>,
+        align: Align,
+    ) -> PlaceRef<'ll, 'tcx> {
         PlaceRef {
             llval,
-            llextra: ptr::null_mut(),
+            llextra: None,
             layout,
             align
         }
     }
 
     pub fn from_const_alloc(
-        bx: &Builder<'a, 'tcx>,
+        bx: &Builder<'a, 'll, 'tcx>,
         layout: TyLayout<'tcx>,
         alloc: &mir::interpret::Allocation,
         offset: Size,
-    ) -> PlaceRef<'tcx> {
+    ) -> PlaceRef<'ll, 'tcx> {
         let init = const_alloc_to_llvm(bx.cx, alloc);
         let base_addr = consts::addr_of(bx.cx, init, layout.align, "byte_str");
 
@@ -75,19 +74,18 @@ impl<'a, 'tcx> PlaceRef<'tcx> {
         PlaceRef::new_sized(llval, layout, alloc.align)
     }
 
-    pub fn alloca(bx: &Builder<'a, 'tcx>, layout: TyLayout<'tcx>, name: &str)
-                  -> PlaceRef<'tcx> {
+    pub fn alloca(bx: &Builder<'a, 'll, 'tcx>, layout: TyLayout<'tcx>, name: &str)
+                  -> PlaceRef<'ll, 'tcx> {
         debug!("alloca({:?}: {:?})", name, layout);
         let tmp = bx.alloca(layout.llvm_type(bx.cx), name, layout.align);
         Self::new_sized(tmp, layout, layout.align)
     }
 
-    pub fn len(&self, cx: &CodegenCx<'a, 'tcx>) -> ValueRef {
+    pub fn len(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Value {
         if let layout::FieldPlacement::Array { count, .. } = self.layout.fields {
             if self.layout.is_unsized() {
-                assert!(self.has_extra());
                 assert_eq!(count, 0);
-                self.llextra
+                self.llextra.unwrap()
             } else {
                 C_usize(cx, count)
             }
@@ -96,14 +94,10 @@ impl<'a, 'tcx> PlaceRef<'tcx> {
         }
     }
 
-    pub fn has_extra(&self) -> bool {
-        !self.llextra.is_null()
-    }
-
-    pub fn load(&self, bx: &Builder<'a, 'tcx>) -> OperandRef<'tcx> {
+    pub fn load(&self, bx: &Builder<'a, 'll, 'tcx>) -> OperandRef<'ll, 'tcx> {
         debug!("PlaceRef::load: {:?}", self);
 
-        assert!(!self.has_extra());
+        assert_eq!(self.llextra, None);
 
         if self.layout.is_zst() {
             return OperandRef::new_zst(bx.cx, self.layout);
@@ -126,23 +120,21 @@ impl<'a, 'tcx> PlaceRef<'tcx> {
         };
 
         let val = if self.layout.is_llvm_immediate() {
-            let mut const_llval = ptr::null_mut();
+            let mut const_llval = None;
             unsafe {
-                let global = llvm::LLVMIsAGlobalVariable(self.llval);
-                if !global.is_null() && llvm::LLVMIsGlobalConstant(global) == llvm::True {
-                    const_llval = llvm::LLVMGetInitializer(global);
+                if let Some(global) = llvm::LLVMIsAGlobalVariable(self.llval) {
+                    if llvm::LLVMIsGlobalConstant(global) == llvm::True {
+                        const_llval = llvm::LLVMGetInitializer(global);
+                    }
                 }
             }
-
-            let llval = if !const_llval.is_null() {
-                const_llval
-            } else {
+            let llval = const_llval.unwrap_or_else(|| {
                 let load = bx.load(self.llval, self.align);
                 if let layout::Abi::Scalar(ref scalar) = self.layout.abi {
                     scalar_load_metadata(load, scalar);
                 }
                 load
-            };
+            });
             OperandValue::Immediate(base::to_immediate(bx, llval, self.layout))
         } else if let layout::Abi::ScalarPair(ref a, ref b) = self.layout.abi {
             let load = |i, scalar: &layout::Scalar| {
@@ -164,7 +156,7 @@ impl<'a, 'tcx> PlaceRef<'tcx> {
     }
 
     /// Access a field, at a point when the value's case is known.
-    pub fn project_field(self, bx: &Builder<'a, 'tcx>, ix: usize) -> PlaceRef<'tcx> {
+    pub fn project_field(self, bx: &Builder<'a, 'll, 'tcx>, ix: usize) -> PlaceRef<'ll, 'tcx> {
         let cx = bx.cx;
         let field = self.layout.field(cx, ix);
         let offset = self.layout.fields.offset(ix);
@@ -187,7 +179,7 @@ impl<'a, 'tcx> PlaceRef<'tcx> {
                 llextra: if cx.type_has_metadata(field.ty) {
                     self.llextra
                 } else {
-                    ptr::null_mut()
+                    None
                 },
                 layout: field,
                 align,
@@ -199,9 +191,9 @@ impl<'a, 'tcx> PlaceRef<'tcx> {
         //   * known alignment - sized types, [T], str or a foreign type
         //   * packed struct - there is no alignment padding
         match field.ty.sty {
-            _ if !self.has_extra() => {
+            _ if self.llextra.is_none() => {
                 debug!("Unsized field `{}`, of `{:?}` has no metadata for adjustment",
-                    ix, Value(self.llval));
+                    ix, self.llval);
                 return simple();
             }
             _ if !field.is_unsized() => return simple(),
@@ -249,7 +241,7 @@ impl<'a, 'tcx> PlaceRef<'tcx> {
         let offset = bx.and(bx.add(unaligned_offset, align_sub_1),
         bx.neg(unsized_align));
 
-        debug!("struct_field_ptr: DST field offset: {:?}", Value(offset));
+        debug!("struct_field_ptr: DST field offset: {:?}", offset);
 
         // Cast and adjust pointer
         let byte_ptr = bx.pointercast(self.llval, Type::i8p(cx));
@@ -268,7 +260,7 @@ impl<'a, 'tcx> PlaceRef<'tcx> {
     }
 
     /// Obtain the actual discriminant of a value.
-    pub fn codegen_get_discr(self, bx: &Builder<'a, 'tcx>, cast_to: Ty<'tcx>) -> ValueRef {
+    pub fn codegen_get_discr(self, bx: &Builder<'a, 'll, 'tcx>, cast_to: Ty<'tcx>) -> &'ll Value {
         let cast_to = bx.cx.layout_of(cast_to).immediate_llvm_type(bx.cx);
         if self.layout.abi == layout::Abi::Uninhabited {
             return C_undef(cast_to);
@@ -332,7 +324,7 @@ impl<'a, 'tcx> PlaceRef<'tcx> {
 
     /// Set the discriminant for a new value of the given case of the given
     /// representation.
-    pub fn codegen_set_discr(&self, bx: &Builder<'a, 'tcx>, variant_index: usize) {
+    pub fn codegen_set_discr(&self, bx: &Builder<'a, 'll, 'tcx>, variant_index: usize) {
         if self.layout.for_variant(bx.cx, variant_index).abi == layout::Abi::Uninhabited {
             return;
         }
@@ -386,18 +378,18 @@ impl<'a, 'tcx> PlaceRef<'tcx> {
         }
     }
 
-    pub fn project_index(&self, bx: &Builder<'a, 'tcx>, llindex: ValueRef)
-                         -> PlaceRef<'tcx> {
+    pub fn project_index(&self, bx: &Builder<'a, 'll, 'tcx>, llindex: &'ll Value)
+                         -> PlaceRef<'ll, 'tcx> {
         PlaceRef {
             llval: bx.inbounds_gep(self.llval, &[C_usize(bx.cx, 0), llindex]),
-            llextra: ptr::null_mut(),
+            llextra: None,
             layout: self.layout.field(bx.cx, 0),
             align: self.align
         }
     }
 
-    pub fn project_downcast(&self, bx: &Builder<'a, 'tcx>, variant_index: usize)
-                            -> PlaceRef<'tcx> {
+    pub fn project_downcast(&self, bx: &Builder<'a, 'll, 'tcx>, variant_index: usize)
+                            -> PlaceRef<'ll, 'tcx> {
         let mut downcast = *self;
         downcast.layout = self.layout.for_variant(bx.cx, variant_index);
 
@@ -408,20 +400,20 @@ impl<'a, 'tcx> PlaceRef<'tcx> {
         downcast
     }
 
-    pub fn storage_live(&self, bx: &Builder<'a, 'tcx>) {
+    pub fn storage_live(&self, bx: &Builder<'a, 'll, 'tcx>) {
         bx.lifetime_start(self.llval, self.layout.size);
     }
 
-    pub fn storage_dead(&self, bx: &Builder<'a, 'tcx>) {
+    pub fn storage_dead(&self, bx: &Builder<'a, 'll, 'tcx>) {
         bx.lifetime_end(self.llval, self.layout.size);
     }
 }
 
-impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
+impl FunctionCx<'a, 'll, 'tcx> {
     pub fn codegen_place(&mut self,
-                        bx: &Builder<'a, 'tcx>,
+                        bx: &Builder<'a, 'll, 'tcx>,
                         place: &mir::Place<'tcx>)
-                        -> PlaceRef<'tcx> {
+                        -> PlaceRef<'ll, 'tcx> {
         debug!("codegen_place(place={:?})", place);
 
         let cx = bx.cx;
@@ -513,9 +505,8 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
                         subslice.layout = bx.cx.layout_of(self.monomorphize(&projected_ty));
 
                         if subslice.layout.is_unsized() {
-                            assert!(cg_base.has_extra());
-                            subslice.llextra = bx.sub(cg_base.llextra,
-                                C_usize(bx.cx, (from as u64) + (to as u64)));
+                            subslice.llextra = Some(bx.sub(cg_base.llextra.unwrap(),
+                                C_usize(bx.cx, (from as u64) + (to as u64))));
                         }
 
                         // Cast the place pointer type to the new
diff --git a/src/librustc_codegen_llvm/mir/rvalue.rs b/src/librustc_codegen_llvm/mir/rvalue.rs
index 2e81fc16a58..02b5c27840e 100644
--- a/src/librustc_codegen_llvm/mir/rvalue.rs
+++ b/src/librustc_codegen_llvm/mir/rvalue.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use llvm::{self, ValueRef};
+use llvm;
 use rustc::ty::{self, Ty};
 use rustc::ty::cast::{CastTy, IntTy};
 use rustc::ty::layout::{self, LayoutOf};
@@ -32,15 +32,15 @@ use super::{FunctionCx, LocalRef};
 use super::operand::{OperandRef, OperandValue};
 use super::place::PlaceRef;
 
-impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
+impl FunctionCx<'a, 'll, 'tcx> {
     pub fn codegen_rvalue(&mut self,
-                        bx: Builder<'a, 'tcx>,
-                        dest: PlaceRef<'tcx>,
+                        bx: Builder<'a, 'll, 'tcx>,
+                        dest: PlaceRef<'ll, 'tcx>,
                         rvalue: &mir::Rvalue<'tcx>)
-                        -> Builder<'a, 'tcx>
+                        -> Builder<'a, 'll, 'tcx>
     {
         debug!("codegen_rvalue(dest.llval={:?}, rvalue={:?})",
-               Value(dest.llval), rvalue);
+               dest.llval, rvalue);
 
         match *rvalue {
            mir::Rvalue::Use(ref operand) => {
@@ -176,9 +176,9 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
     }
 
     pub fn codegen_rvalue_operand(&mut self,
-                                bx: Builder<'a, 'tcx>,
+                                bx: Builder<'a, 'll, 'tcx>,
                                 rvalue: &mir::Rvalue<'tcx>)
-                                -> (Builder<'a, 'tcx>, OperandRef<'tcx>)
+                                -> (Builder<'a, 'll, 'tcx>, OperandRef<'ll, 'tcx>)
     {
         assert!(self.rvalue_creates_operand(rvalue), "cannot codegen {:?} to operand", rvalue);
 
@@ -371,7 +371,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
                 let val = if !bx.cx.type_has_metadata(ty) {
                     OperandValue::Immediate(cg_place.llval)
                 } else {
-                    OperandValue::Pair(cg_place.llval, cg_place.llextra)
+                    OperandValue::Pair(cg_place.llval, cg_place.llextra.unwrap())
                 };
                 (bx, OperandRef {
                     val,
@@ -511,10 +511,11 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
         }
     }
 
-    fn evaluate_array_len(&mut self,
-                          bx: &Builder<'a, 'tcx>,
-                          place: &mir::Place<'tcx>) -> ValueRef
-    {
+    fn evaluate_array_len(
+        &mut self,
+        bx: &Builder<'a, 'll, 'tcx>,
+        place: &mir::Place<'tcx>,
+    ) -> &'ll Value {
         // ZST are passed as operands and require special handling
         // because codegen_place() panics if Local is operand.
         if let mir::Place::Local(index) = *place {
@@ -530,12 +531,14 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
         return cg_value.len(bx.cx);
     }
 
-    pub fn codegen_scalar_binop(&mut self,
-                              bx: &Builder<'a, 'tcx>,
-                              op: mir::BinOp,
-                              lhs: ValueRef,
-                              rhs: ValueRef,
-                              input_ty: Ty<'tcx>) -> ValueRef {
+    pub fn codegen_scalar_binop(
+        &mut self,
+        bx: &Builder<'a, 'll, 'tcx>,
+        op: mir::BinOp,
+        lhs: &'ll Value,
+        rhs: &'ll Value,
+        input_ty: Ty<'tcx>,
+    ) -> &'ll Value {
         let is_float = input_ty.is_fp();
         let is_signed = input_ty.is_signed();
         let is_nil = input_ty.is_nil();
@@ -596,15 +599,16 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
         }
     }
 
-    pub fn codegen_fat_ptr_binop(&mut self,
-                               bx: &Builder<'a, 'tcx>,
-                               op: mir::BinOp,
-                               lhs_addr: ValueRef,
-                               lhs_extra: ValueRef,
-                               rhs_addr: ValueRef,
-                               rhs_extra: ValueRef,
-                               _input_ty: Ty<'tcx>)
-                               -> ValueRef {
+    pub fn codegen_fat_ptr_binop(
+        &mut self,
+        bx: &Builder<'a, 'll, 'tcx>,
+        op: mir::BinOp,
+        lhs_addr: &'ll Value,
+        lhs_extra: &'ll Value,
+        rhs_addr: &'ll Value,
+        rhs_extra: &'ll Value,
+        _input_ty: Ty<'tcx>,
+    ) -> &'ll Value {
         match op {
             mir::BinOp::Eq => {
                 bx.and(
@@ -644,11 +648,11 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
     }
 
     pub fn codegen_scalar_checked_binop(&mut self,
-                                      bx: &Builder<'a, 'tcx>,
+                                      bx: &Builder<'a, 'll, 'tcx>,
                                       op: mir::BinOp,
-                                      lhs: ValueRef,
-                                      rhs: ValueRef,
-                                      input_ty: Ty<'tcx>) -> OperandValue {
+                                      lhs: &'ll Value,
+                                      rhs: &'ll Value,
+                                      input_ty: Ty<'tcx>) -> OperandValue<'ll> {
         // This case can currently arise only from functions marked
         // with #[rustc_inherit_overflow_checks] and inlined from
         // another crate (mostly core::num generic/#[inline] fns),
@@ -721,7 +725,7 @@ enum OverflowOp {
     Add, Sub, Mul
 }
 
-fn get_overflow_intrinsic(oop: OverflowOp, bx: &Builder, ty: Ty) -> ValueRef {
+fn get_overflow_intrinsic(oop: OverflowOp, bx: &Builder<'_, 'll, '_>, ty: Ty) -> &'ll Value {
     use syntax::ast::IntTy::*;
     use syntax::ast::UintTy::*;
     use rustc::ty::{TyInt, TyUint};
@@ -796,11 +800,11 @@ fn get_overflow_intrinsic(oop: OverflowOp, bx: &Builder, ty: Ty) -> ValueRef {
     bx.cx.get_intrinsic(&name)
 }
 
-fn cast_int_to_float(bx: &Builder,
+fn cast_int_to_float(bx: &Builder<'_, 'll, '_>,
                      signed: bool,
-                     x: ValueRef,
-                     int_ty: Type,
-                     float_ty: Type) -> ValueRef {
+                     x: &'ll Value,
+                     int_ty: &'ll Type,
+                     float_ty: &'ll Type) -> &'ll Value {
     // Most integer types, even i128, fit into [-f32::MAX, f32::MAX] after rounding.
     // It's only u128 -> f32 that can cause overflows (i.e., should yield infinity).
     // LLVM's uitofp produces undef in those cases, so we manually check for that case.
@@ -826,11 +830,11 @@ fn cast_int_to_float(bx: &Builder,
     }
 }
 
-fn cast_float_to_int(bx: &Builder,
+fn cast_float_to_int(bx: &Builder<'_, 'll, '_>,
                      signed: bool,
-                     x: ValueRef,
-                     float_ty: Type,
-                     int_ty: Type) -> ValueRef {
+                     x: &'ll Value,
+                     float_ty: &'ll Type,
+                     int_ty: &'ll Type) -> &'ll Value {
     let fptosui_result = if signed {
         bx.fptosi(x, int_ty)
     } else {
@@ -859,14 +863,14 @@ fn cast_float_to_int(bx: &Builder,
     // On the other hand, f_max works even if int_ty::MAX is greater than float_ty::MAX. Because
     // we're rounding towards zero, we just get float_ty::MAX (which is always an integer).
     // This already happens today with u128::MAX = 2^128 - 1 > f32::MAX.
-    fn compute_clamp_bounds<F: Float>(signed: bool, int_ty: Type) -> (u128, u128) {
+    fn compute_clamp_bounds<F: Float>(signed: bool, int_ty: &Type) -> (u128, u128) {
         let rounded_min = F::from_i128_r(int_min(signed, int_ty), Round::TowardZero);
         assert_eq!(rounded_min.status, Status::OK);
         let rounded_max = F::from_u128_r(int_max(signed, int_ty), Round::TowardZero);
         assert!(rounded_max.value.is_finite());
         (rounded_min.value.to_bits(), rounded_max.value.to_bits())
     }
-    fn int_max(signed: bool, int_ty: Type) -> u128 {
+    fn int_max(signed: bool, int_ty: &Type) -> u128 {
         let shift_amount = 128 - int_ty.int_width();
         if signed {
             i128::MAX as u128 >> shift_amount
@@ -874,7 +878,7 @@ fn cast_float_to_int(bx: &Builder,
             u128::MAX >> shift_amount
         }
     }
-    fn int_min(signed: bool, int_ty: Type) -> i128 {
+    fn int_min(signed: bool, int_ty: &Type) -> i128 {
         if signed {
             i128::MIN >> (128 - int_ty.int_width())
         } else {
diff --git a/src/librustc_codegen_llvm/mir/statement.rs b/src/librustc_codegen_llvm/mir/statement.rs
index c0cce297ef6..06340a3e5d8 100644
--- a/src/librustc_codegen_llvm/mir/statement.rs
+++ b/src/librustc_codegen_llvm/mir/statement.rs
@@ -16,11 +16,11 @@ use builder::Builder;
 use super::FunctionCx;
 use super::LocalRef;
 
-impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
+impl FunctionCx<'a, 'll, 'tcx> {
     pub fn codegen_statement(&mut self,
-                           bx: Builder<'a, 'tcx>,
+                           bx: Builder<'a, 'll, 'tcx>,
                            statement: &mir::Statement<'tcx>)
-                           -> Builder<'a, 'tcx> {
+                           -> Builder<'a, 'll, 'tcx> {
         debug!("codegen_statement(statement={:?})", statement);
 
         self.set_debug_loc(&bx, statement.source_info);
diff --git a/src/librustc_codegen_llvm/type_.rs b/src/librustc_codegen_llvm/type_.rs
index a77acc4f175..9fa7cc46aee 100644
--- a/src/librustc_codegen_llvm/type_.rs
+++ b/src/librustc_codegen_llvm/type_.rs
@@ -10,9 +10,10 @@
 
 #![allow(non_upper_case_globals)]
 
+pub use llvm::Type;
+
 use llvm;
-use llvm::{ContextRef, TypeRef, Bool, False, True, TypeKind};
-use llvm::{Float, Double, X86_FP80, PPC_FP128, FP128};
+use llvm::{Bool, False, True, TypeKind};
 
 use context::CodegenCx;
 
@@ -21,122 +22,125 @@ use rustc::ty::layout::{self, Align, Size};
 
 use std::ffi::CString;
 use std::fmt;
-use std::mem;
-use std::ptr;
 
 use libc::c_uint;
 
-#[derive(Clone, Copy, PartialEq)]
-#[repr(C)]
-pub struct Type {
-    rf: TypeRef
+impl PartialEq for Type {
+    fn eq(&self, other: &Self) -> bool {
+        self as *const _ == other as *const _
+    }
 }
 
 impl fmt::Debug for Type {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.write_str(&llvm::build_string(|s| unsafe {
-            llvm::LLVMRustWriteTypeToString(self.to_ref(), s);
+            llvm::LLVMRustWriteTypeToString(self, s);
         }).expect("non-UTF8 type description from LLVM"))
     }
 }
 
-macro_rules! ty {
-    ($e:expr) => ( Type::from_ref(unsafe { $e }))
-}
-
-/// Wrapper for LLVM TypeRef
 impl Type {
-    #[inline(always)]
-    pub fn from_ref(r: TypeRef) -> Type {
-        Type {
-            rf: r
+    pub fn void(cx: &CodegenCx<'ll, '_>) -> &'ll Type {
+        unsafe {
+            llvm::LLVMVoidTypeInContext(cx.llcx)
         }
     }
 
-    #[inline(always)] // So it doesn't kill --opt-level=0 builds of the compiler
-    pub fn to_ref(&self) -> TypeRef {
-        self.rf
-    }
-
-    pub fn to_ref_slice(slice: &[Type]) -> &[TypeRef] {
-        unsafe { mem::transmute(slice) }
-    }
-
-    pub fn void(cx: &CodegenCx) -> Type {
-        ty!(llvm::LLVMVoidTypeInContext(cx.llcx))
+    pub fn metadata(cx: &CodegenCx<'ll, '_>) -> &'ll Type {
+        unsafe {
+            llvm::LLVMRustMetadataTypeInContext(cx.llcx)
+        }
     }
 
-    pub fn metadata(cx: &CodegenCx) -> Type {
-        ty!(llvm::LLVMRustMetadataTypeInContext(cx.llcx))
+    pub fn i1(cx: &CodegenCx<'ll, '_>) -> &'ll Type {
+        unsafe {
+            llvm::LLVMInt1TypeInContext(cx.llcx)
+        }
     }
 
-    pub fn i1(cx: &CodegenCx) -> Type {
-        ty!(llvm::LLVMInt1TypeInContext(cx.llcx))
+    pub fn i8(cx: &CodegenCx<'ll, '_>) -> &'ll Type {
+        unsafe {
+            llvm::LLVMInt8TypeInContext(cx.llcx)
+        }
     }
 
-    pub fn i8(cx: &CodegenCx) -> Type {
-        ty!(llvm::LLVMInt8TypeInContext(cx.llcx))
+    pub fn i8_llcx(llcx: &llvm::Context) -> &Type {
+        unsafe {
+            llvm::LLVMInt8TypeInContext(llcx)
+        }
     }
 
-    pub fn i8_llcx(llcx: ContextRef) -> Type {
-        ty!(llvm::LLVMInt8TypeInContext(llcx))
+    pub fn i16(cx: &CodegenCx<'ll, '_>) -> &'ll Type {
+        unsafe {
+            llvm::LLVMInt16TypeInContext(cx.llcx)
+        }
     }
 
-    pub fn i16(cx: &CodegenCx) -> Type {
-        ty!(llvm::LLVMInt16TypeInContext(cx.llcx))
+    pub fn i32(cx: &CodegenCx<'ll, '_>) -> &'ll Type {
+        unsafe {
+            llvm::LLVMInt32TypeInContext(cx.llcx)
+        }
     }
 
-    pub fn i32(cx: &CodegenCx) -> Type {
-        ty!(llvm::LLVMInt32TypeInContext(cx.llcx))
+    pub fn i64(cx: &CodegenCx<'ll, '_>) -> &'ll Type {
+        unsafe {
+            llvm::LLVMInt64TypeInContext(cx.llcx)
+        }
     }
 
-    pub fn i64(cx: &CodegenCx) -> Type {
-        ty!(llvm::LLVMInt64TypeInContext(cx.llcx))
+    pub fn i128(cx: &CodegenCx<'ll, '_>) -> &'ll Type {
+        unsafe {
+            llvm::LLVMIntTypeInContext(cx.llcx, 128)
+        }
     }
 
-    pub fn i128(cx: &CodegenCx) -> Type {
-        ty!(llvm::LLVMIntTypeInContext(cx.llcx, 128))
+    // Creates an integer type with the given number of bits, e.g. i24
+    pub fn ix(cx: &CodegenCx<'ll, '_>, num_bits: u64) -> &'ll Type {
+        unsafe {
+            llvm::LLVMIntTypeInContext(cx.llcx, num_bits as c_uint)
+        }
     }
 
     // Creates an integer type with the given number of bits, e.g. i24
-    pub fn ix(cx: &CodegenCx, num_bits: u64) -> Type {
-        ty!(llvm::LLVMIntTypeInContext(cx.llcx, num_bits as c_uint))
+    pub fn ix_llcx(llcx: &llvm::Context, num_bits: u64) -> &Type {
+        unsafe {
+            llvm::LLVMIntTypeInContext(llcx, num_bits as c_uint)
+        }
     }
 
-    pub fn f32(cx: &CodegenCx) -> Type {
-        ty!(llvm::LLVMFloatTypeInContext(cx.llcx))
+    pub fn f32(cx: &CodegenCx<'ll, '_>) -> &'ll Type {
+        unsafe {
+            llvm::LLVMFloatTypeInContext(cx.llcx)
+        }
     }
 
-    pub fn f64(cx: &CodegenCx) -> Type {
-        ty!(llvm::LLVMDoubleTypeInContext(cx.llcx))
+    pub fn f64(cx: &CodegenCx<'ll, '_>) -> &'ll Type {
+        unsafe {
+            llvm::LLVMDoubleTypeInContext(cx.llcx)
+        }
     }
 
-    pub fn bool(cx: &CodegenCx) -> Type {
+    pub fn bool(cx: &CodegenCx<'ll, '_>) -> &'ll Type {
         Type::i8(cx)
     }
 
-    pub fn char(cx: &CodegenCx) -> Type {
+    pub fn char(cx: &CodegenCx<'ll, '_>) -> &'ll Type {
         Type::i32(cx)
     }
 
-    pub fn i8p(cx: &CodegenCx) -> Type {
+    pub fn i8p(cx: &CodegenCx<'ll, '_>) -> &'ll Type {
         Type::i8(cx).ptr_to()
     }
 
-    pub fn i8p_llcx(llcx: ContextRef) -> Type {
+    pub fn i8p_llcx(llcx: &llvm::Context) -> &Type {
         Type::i8_llcx(llcx).ptr_to()
     }
 
-    pub fn isize(cx: &CodegenCx) -> Type {
-        match &cx.tcx.sess.target.target.target_pointer_width[..] {
-            "16" => Type::i16(cx),
-            "32" => Type::i32(cx),
-            "64" => Type::i64(cx),
-            tws => bug!("Unsupported target word size for int: {}", tws),
-        }
+    pub fn isize(cx: &CodegenCx<'ll, '_>) -> &'ll Type {
+        cx.isize_ty
     }
 
-    pub fn c_int(cx: &CodegenCx) -> Type {
+    pub fn c_int(cx: &CodegenCx<'ll, '_>) -> &'ll Type {
         match &cx.tcx.sess.target.target.target_c_int_width[..] {
             "16" => Type::i16(cx),
             "32" => Type::i32(cx),
@@ -145,7 +149,7 @@ impl Type {
         }
     }
 
-    pub fn int_from_ty(cx: &CodegenCx, t: ast::IntTy) -> Type {
+    pub fn int_from_ty(cx: &CodegenCx<'ll, '_>, t: ast::IntTy) -> &'ll Type {
         match t {
             ast::IntTy::Isize => cx.isize_ty,
             ast::IntTy::I8 => Type::i8(cx),
@@ -156,7 +160,7 @@ impl Type {
         }
     }
 
-    pub fn uint_from_ty(cx: &CodegenCx, t: ast::UintTy) -> Type {
+    pub fn uint_from_ty(cx: &CodegenCx<'ll, '_>, t: ast::UintTy) -> &'ll Type {
         match t {
             ast::UintTy::Usize => cx.isize_ty,
             ast::UintTy::U8 => Type::i8(cx),
@@ -167,93 +171,103 @@ impl Type {
         }
     }
 
-    pub fn float_from_ty(cx: &CodegenCx, t: ast::FloatTy) -> Type {
+    pub fn float_from_ty(cx: &CodegenCx<'ll, '_>, t: ast::FloatTy) -> &'ll Type {
         match t {
             ast::FloatTy::F32 => Type::f32(cx),
             ast::FloatTy::F64 => Type::f64(cx),
         }
     }
 
-    pub fn func(args: &[Type], ret: &Type) -> Type {
-        let slice: &[TypeRef] = Type::to_ref_slice(args);
-        ty!(llvm::LLVMFunctionType(ret.to_ref(), slice.as_ptr(),
-                                   args.len() as c_uint, False))
+    pub fn func(args: &[&'ll Type], ret: &'ll Type) -> &'ll Type {
+        unsafe {
+            llvm::LLVMFunctionType(ret, args.as_ptr(),
+                                   args.len() as c_uint, False)
+        }
     }
 
-    pub fn variadic_func(args: &[Type], ret: &Type) -> Type {
-        let slice: &[TypeRef] = Type::to_ref_slice(args);
-        ty!(llvm::LLVMFunctionType(ret.to_ref(), slice.as_ptr(),
-                                   args.len() as c_uint, True))
+    pub fn variadic_func(args: &[&'ll Type], ret: &'ll Type) -> &'ll Type {
+        unsafe {
+            llvm::LLVMFunctionType(ret, args.as_ptr(),
+                                   args.len() as c_uint, True)
+        }
     }
 
-    pub fn struct_(cx: &CodegenCx, els: &[Type], packed: bool) -> Type {
-        let els: &[TypeRef] = Type::to_ref_slice(els);
-        ty!(llvm::LLVMStructTypeInContext(cx.llcx, els.as_ptr(),
+    pub fn struct_(cx: &CodegenCx<'ll, '_>, els: &[&'ll Type], packed: bool) -> &'ll Type {
+        unsafe {
+            llvm::LLVMStructTypeInContext(cx.llcx, els.as_ptr(),
                                           els.len() as c_uint,
-                                          packed as Bool))
+                                          packed as Bool)
+        }
     }
 
-    pub fn named_struct(cx: &CodegenCx, name: &str) -> Type {
+    pub fn named_struct(cx: &CodegenCx<'ll, '_>, name: &str) -> &'ll Type {
         let name = CString::new(name).unwrap();
-        ty!(llvm::LLVMStructCreateNamed(cx.llcx, name.as_ptr()))
+        unsafe {
+            llvm::LLVMStructCreateNamed(cx.llcx, name.as_ptr())
+        }
     }
 
 
-    pub fn array(ty: &Type, len: u64) -> Type {
-        ty!(llvm::LLVMRustArrayType(ty.to_ref(), len))
+    pub fn array(ty: &Type, len: u64) -> &Type {
+        unsafe {
+            llvm::LLVMRustArrayType(ty, len)
+        }
     }
 
-    pub fn vector(ty: &Type, len: u64) -> Type {
-        ty!(llvm::LLVMVectorType(ty.to_ref(), len as c_uint))
+    pub fn vector(ty: &Type, len: u64) -> &Type {
+        unsafe {
+            llvm::LLVMVectorType(ty, len as c_uint)
+        }
     }
 
     pub fn kind(&self) -> TypeKind {
         unsafe {
-            llvm::LLVMRustGetTypeKind(self.to_ref())
+            llvm::LLVMRustGetTypeKind(self)
         }
     }
 
-    pub fn set_struct_body(&mut self, els: &[Type], packed: bool) {
-        let slice: &[TypeRef] = Type::to_ref_slice(els);
+    pub fn set_struct_body(&'ll self, els: &[&'ll Type], packed: bool) {
         unsafe {
-            llvm::LLVMStructSetBody(self.to_ref(), slice.as_ptr(),
+            llvm::LLVMStructSetBody(self, els.as_ptr(),
                                     els.len() as c_uint, packed as Bool)
         }
     }
 
-    pub fn ptr_to(&self) -> Type {
-        ty!(llvm::LLVMPointerType(self.to_ref(), 0))
+    pub fn ptr_to(&self) -> &Type {
+        unsafe {
+            llvm::LLVMPointerType(self, 0)
+        }
     }
 
-    pub fn element_type(&self) -> Type {
+    pub fn element_type(&self) -> &Type {
         unsafe {
-            Type::from_ref(llvm::LLVMGetElementType(self.to_ref()))
+            llvm::LLVMGetElementType(self)
         }
     }
 
     /// Return the number of elements in `self` if it is a LLVM vector type.
     pub fn vector_length(&self) -> usize {
         unsafe {
-            llvm::LLVMGetVectorSize(self.to_ref()) as usize
+            llvm::LLVMGetVectorSize(self) as usize
         }
     }
 
-    pub fn func_params(&self) -> Vec<Type> {
+    pub fn func_params(&self) -> Vec<&Type> {
         unsafe {
-            let n_args = llvm::LLVMCountParamTypes(self.to_ref()) as usize;
-            let mut args = vec![Type { rf: ptr::null_mut() }; n_args];
-            llvm::LLVMGetParamTypes(self.to_ref(),
-                                    args.as_mut_ptr() as *mut TypeRef);
+            let n_args = llvm::LLVMCountParamTypes(self) as usize;
+            let mut args = Vec::with_capacity(n_args);
+            llvm::LLVMGetParamTypes(self, args.as_mut_ptr());
+            args.set_len(n_args);
             args
         }
     }
 
     pub fn float_width(&self) -> usize {
         match self.kind() {
-            Float => 32,
-            Double => 64,
-            X86_FP80 => 80,
-            FP128 | PPC_FP128 => 128,
+            TypeKind::Float => 32,
+            TypeKind::Double => 64,
+            TypeKind::X86_FP80 => 80,
+            TypeKind::FP128 | TypeKind::PPC_FP128 => 128,
             _ => bug!("llvm_float_width called on a non-float type")
         }
     }
@@ -261,11 +275,11 @@ impl Type {
     /// Retrieve the bit width of the integer type `self`.
     pub fn int_width(&self) -> u64 {
         unsafe {
-            llvm::LLVMGetIntTypeWidth(self.to_ref()) as u64
+            llvm::LLVMGetIntTypeWidth(self) as u64
         }
     }
 
-    pub fn from_integer(cx: &CodegenCx, i: layout::Integer) -> Type {
+    pub fn from_integer(cx: &CodegenCx<'ll, '_>, i: layout::Integer) -> &'ll Type {
         use rustc::ty::layout::Integer::*;
         match i {
             I8 => Type::i8(cx),
@@ -278,7 +292,7 @@ impl Type {
 
     /// Return a LLVM type that has at most the required alignment,
     /// as a conservative approximation for unknown pointee types.
-    pub fn pointee_for_abi_align(cx: &CodegenCx, align: Align) -> Type {
+    pub fn pointee_for_abi_align(cx: &CodegenCx<'ll, '_>, align: Align) -> &'ll Type {
         // FIXME(eddyb) We could find a better approximation if ity.align < align.
         let ity = layout::Integer::approximate_abi_align(cx, align);
         Type::from_integer(cx, ity)
@@ -286,15 +300,17 @@ impl Type {
 
     /// Return a LLVM type that has at most the required alignment,
     /// and exactly the required size, as a best-effort padding array.
-    pub fn padding_filler(cx: &CodegenCx, size: Size, align: Align) -> Type {
+    pub fn padding_filler(cx: &CodegenCx<'ll, '_>, size: Size, align: Align) -> &'ll Type {
         let unit = layout::Integer::approximate_abi_align(cx, align);
         let size = size.bytes();
         let unit_size = unit.size().bytes();
         assert_eq!(size % unit_size, 0);
-        Type::array(&Type::from_integer(cx, unit), size / unit_size)
+        Type::array(Type::from_integer(cx, unit), size / unit_size)
     }
 
-    pub fn x86_mmx(cx: &CodegenCx) -> Type {
-        ty!(llvm::LLVMX86MMXTypeInContext(cx.llcx))
+    pub fn x86_mmx(cx: &CodegenCx<'ll, '_>) -> &'ll Type {
+        unsafe {
+            llvm::LLVMX86MMXTypeInContext(cx.llcx)
+        }
     }
 }
diff --git a/src/librustc_codegen_llvm/type_of.rs b/src/librustc_codegen_llvm/type_of.rs
index 4728d7717a1..5fd4f15acd1 100644
--- a/src/librustc_codegen_llvm/type_of.rs
+++ b/src/librustc_codegen_llvm/type_of.rs
@@ -23,8 +23,8 @@ use std::fmt::Write;
 
 fn uncached_llvm_type<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                                 layout: TyLayout<'tcx>,
-                                defer: &mut Option<(Type, TyLayout<'tcx>)>)
-                                -> Type {
+                                defer: &mut Option<(&'a Type, TyLayout<'tcx>)>)
+                                -> &'a Type {
     match layout.abi {
         layout::Abi::Scalar(_) => bug!("handled elsewhere"),
         layout::Abi::Vector { ref element, count } => {
@@ -42,7 +42,7 @@ fn uncached_llvm_type<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                 return Type::x86_mmx(cx)
             } else {
                 let element = layout.scalar_llvm_type_at(cx, element, Size::ZERO);
-                return Type::vector(&element, count);
+                return Type::vector(element, count);
             }
         }
         layout::Abi::ScalarPair(..) => {
@@ -96,7 +96,7 @@ fn uncached_llvm_type<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
             }
         }
         layout::FieldPlacement::Array { count, .. } => {
-            Type::array(&layout.field(cx, 0).llvm_type(cx), count)
+            Type::array(layout.field(cx, 0).llvm_type(cx), count)
         }
         layout::FieldPlacement::Arbitrary { .. } => {
             match name {
@@ -116,14 +116,14 @@ fn uncached_llvm_type<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
 
 fn struct_llfields<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                              layout: TyLayout<'tcx>)
-                             -> (Vec<Type>, bool) {
+                             -> (Vec<&'a Type>, bool) {
     debug!("struct_llfields: {:#?}", layout);
     let field_count = layout.fields.count();
 
     let mut packed = false;
     let mut offset = Size::ZERO;
     let mut prev_align = layout.align;
-    let mut result: Vec<Type> = Vec::with_capacity(1 + field_count * 2);
+    let mut result: Vec<_> = Vec::with_capacity(1 + field_count * 2);
     for i in layout.fields.index_by_increasing_offset() {
         let field = layout.field(cx, i);
         packed |= layout.align.abi() < field.align.abi();
@@ -201,12 +201,12 @@ pub struct PointeeInfo {
 pub trait LayoutLlvmExt<'tcx> {
     fn is_llvm_immediate(&self) -> bool;
     fn is_llvm_scalar_pair<'a>(&self) -> bool;
-    fn llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> Type;
-    fn immediate_llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> Type;
+    fn llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> &'a Type;
+    fn immediate_llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> &'a Type;
     fn scalar_llvm_type_at<'a>(&self, cx: &CodegenCx<'a, 'tcx>,
-                               scalar: &layout::Scalar, offset: Size) -> Type;
+                               scalar: &layout::Scalar, offset: Size) -> &'a Type;
     fn scalar_pair_element_llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>,
-                                         index: usize, immediate: bool) -> Type;
+                                         index: usize, immediate: bool) -> &'a Type;
     fn llvm_field_index(&self, index: usize) -> u64;
     fn pointee_info_at<'a>(&self, cx: &CodegenCx<'a, 'tcx>, offset: Size)
                            -> Option<PointeeInfo>;
@@ -244,7 +244,7 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyLayout<'tcx> {
     /// with the inner-most trailing unsized field using the "minimal unit"
     /// of that field's type - this is useful for taking the address of
     /// that field and ensuring the struct has the right alignment.
-    fn llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> Type {
+    fn llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> &'a Type {
         if let layout::Abi::Scalar(ref scalar) = self.abi {
             // Use a different cache for scalars because pointers to DSTs
             // can be either fat or thin (data pointers of fat pointers).
@@ -304,7 +304,7 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyLayout<'tcx> {
 
         cx.lltypes.borrow_mut().insert((self.ty, variant_index), llty);
 
-        if let Some((mut llty, layout)) = defer {
+        if let Some((llty, layout)) = defer {
             let (llfields, packed) = struct_llfields(cx, layout);
             llty.set_struct_body(&llfields, packed)
         }
@@ -312,7 +312,7 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyLayout<'tcx> {
         llty
     }
 
-    fn immediate_llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> Type {
+    fn immediate_llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> &'a Type {
         if let layout::Abi::Scalar(ref scalar) = self.abi {
             if scalar.is_bool() {
                 return Type::i1(cx);
@@ -322,7 +322,7 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyLayout<'tcx> {
     }
 
     fn scalar_llvm_type_at<'a>(&self, cx: &CodegenCx<'a, 'tcx>,
-                               scalar: &layout::Scalar, offset: Size) -> Type {
+                               scalar: &layout::Scalar, offset: Size) -> &'a Type {
         match scalar.value {
             layout::Int(i, _) => Type::from_integer(cx, i),
             layout::Float(FloatTy::F32) => Type::f32(cx),
@@ -340,7 +340,7 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyLayout<'tcx> {
     }
 
     fn scalar_pair_element_llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>,
-                                         index: usize, immediate: bool) -> Type {
+                                         index: usize, immediate: bool) -> &'a Type {
         // HACK(eddyb) special-case fat pointers until LLVM removes
         // pointee types, to avoid bitcasting every `OperandRef::deref`.
         match self.ty.sty {
diff --git a/src/librustc_codegen_llvm/value.rs b/src/librustc_codegen_llvm/value.rs
index 287ad87caac..3328948c295 100644
--- a/src/librustc_codegen_llvm/value.rs
+++ b/src/librustc_codegen_llvm/value.rs
@@ -8,17 +8,32 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+pub use llvm::Value;
+
 use llvm;
 
 use std::fmt;
+use std::hash::{Hash, Hasher};
+
+impl PartialEq for Value {
+    fn eq(&self, other: &Self) -> bool {
+        self as *const _ == other as *const _
+    }
+}
+
+impl Eq for Value {}
+
+impl Hash for Value {
+    fn hash<H: Hasher>(&self, hasher: &mut H) {
+        (self as *const Self).hash(hasher);
+    }
+}
 
-#[derive(Copy, Clone, PartialEq)]
-pub struct Value(pub llvm::ValueRef);
 
 impl fmt::Debug for Value {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.write_str(&llvm::build_string(|s| unsafe {
-            llvm::LLVMRustWriteValueToString(self.0, s);
+            llvm::LLVMRustWriteValueToString(self, s);
         }).expect("nun-UTF8 value description from LLVM"))
     }
 }
diff --git a/src/librustc_llvm/Cargo.toml b/src/librustc_llvm/Cargo.toml
index 0978c2ceb14..013badb71cc 100644
--- a/src/librustc_llvm/Cargo.toml
+++ b/src/librustc_llvm/Cargo.toml
@@ -12,11 +12,6 @@ path = "lib.rs"
 static-libstdcpp = []
 emscripten = []
 
-[dependencies]
-bitflags = "1.0"
-libc = "0.2"
-rustc_cratesio_shim = { path = "../librustc_cratesio_shim" }
-
 [build-dependencies]
 build_helper = { path = "../build_helper" }
 cc = "1.0.1"
diff --git a/src/librustc_llvm/build.rs b/src/librustc_llvm/build.rs
index 1619637b827..5910e55def3 100644
--- a/src/librustc_llvm/build.rs
+++ b/src/librustc_llvm/build.rs
@@ -271,5 +271,6 @@ fn main() {
     if target.contains("windows-gnu") {
         println!("cargo:rustc-link-lib=static-nobundle=gcc_s");
         println!("cargo:rustc-link-lib=static-nobundle=pthread");
+        println!("cargo:rustc-link-lib=dylib=uuid");
     }
 }
diff --git a/src/librustc_llvm/ffi.rs b/src/librustc_llvm/ffi.rs
deleted file mode 100644
index 8d04438eea2..00000000000
--- a/src/librustc_llvm/ffi.rs
+++ /dev/null
@@ -1,1800 +0,0 @@
-// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// FIXME: Rename 'DIGlobalVariable' to 'DIGlobalVariableExpression'
-// once support for LLVM 3.9 is dropped.
-//
-// This method was changed in this LLVM patch:
-// https://reviews.llvm.org/D26769
-
-use debuginfo::{DIBuilderRef, DIDescriptor, DIFile, DILexicalBlock, DISubprogram, DIType,
-                DIBasicType, DIDerivedType, DICompositeType, DIScope, DIVariable,
-                DIGlobalVariable, DIArray, DISubrange, DITemplateTypeParameter, DIEnumerator,
-                DINameSpace, DIFlags};
-
-use libc::{c_uint, c_int, size_t, c_char};
-use libc::{c_longlong, c_ulonglong, c_void};
-
-use RustStringRef;
-
-pub type Opcode = u32;
-pub type Bool = c_uint;
-
-pub const True: Bool = 1 as Bool;
-pub const False: Bool = 0 as Bool;
-
-#[derive(Copy, Clone, PartialEq)]
-#[repr(C)]
-pub enum LLVMRustResult {
-    Success,
-    Failure,
-}
-// Consts for the LLVM CallConv type, pre-cast to usize.
-
-/// LLVM CallingConv::ID. Should we wrap this?
-#[derive(Copy, Clone, PartialEq, Debug)]
-#[repr(C)]
-pub enum CallConv {
-    CCallConv = 0,
-    FastCallConv = 8,
-    ColdCallConv = 9,
-    X86StdcallCallConv = 64,
-    X86FastcallCallConv = 65,
-    ArmAapcsCallConv = 67,
-    Msp430Intr = 69,
-    X86_ThisCall = 70,
-    PtxKernel = 71,
-    X86_64_SysV = 78,
-    X86_64_Win64 = 79,
-    X86_VectorCall = 80,
-    X86_Intr = 83,
-    AmdGpuKernel = 91,
-}
-
-/// LLVMRustLinkage
-#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
-#[repr(C)]
-pub enum Linkage {
-    ExternalLinkage = 0,
-    AvailableExternallyLinkage = 1,
-    LinkOnceAnyLinkage = 2,
-    LinkOnceODRLinkage = 3,
-    WeakAnyLinkage = 4,
-    WeakODRLinkage = 5,
-    AppendingLinkage = 6,
-    InternalLinkage = 7,
-    PrivateLinkage = 8,
-    ExternalWeakLinkage = 9,
-    CommonLinkage = 10,
-}
-
-// LLVMRustVisibility
-#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
-#[repr(C)]
-pub enum Visibility {
-    Default = 0,
-    Hidden = 1,
-    Protected = 2,
-}
-
-/// LLVMDiagnosticSeverity
-#[derive(Copy, Clone, Debug)]
-#[repr(C)]
-pub enum DiagnosticSeverity {
-    Error = 0,
-    Warning = 1,
-    Remark = 2,
-    Note = 3,
-}
-
-/// LLVMDLLStorageClass
-#[derive(Copy, Clone)]
-#[repr(C)]
-pub enum DLLStorageClass {
-    Default = 0,
-    DllImport = 1, // Function to be imported from DLL.
-    DllExport = 2, // Function to be accessible from DLL.
-}
-
-/// Matches LLVMRustAttribute in rustllvm.h
-/// Semantically a subset of the C++ enum llvm::Attribute::AttrKind,
-/// though it is not ABI compatible (since it's a C++ enum)
-#[repr(C)]
-#[derive(Copy, Clone, Debug)]
-pub enum Attribute {
-    AlwaysInline    = 0,
-    ByVal           = 1,
-    Cold            = 2,
-    InlineHint      = 3,
-    MinSize         = 4,
-    Naked           = 5,
-    NoAlias         = 6,
-    NoCapture       = 7,
-    NoInline        = 8,
-    NonNull         = 9,
-    NoRedZone       = 10,
-    NoReturn        = 11,
-    NoUnwind        = 12,
-    OptimizeForSize = 13,
-    ReadOnly        = 14,
-    SExt            = 15,
-    StructRet       = 16,
-    UWTable         = 17,
-    ZExt            = 18,
-    InReg           = 19,
-    SanitizeThread  = 20,
-    SanitizeAddress = 21,
-    SanitizeMemory  = 22,
-}
-
-/// LLVMIntPredicate
-#[derive(Copy, Clone)]
-#[repr(C)]
-pub enum IntPredicate {
-    IntEQ = 32,
-    IntNE = 33,
-    IntUGT = 34,
-    IntUGE = 35,
-    IntULT = 36,
-    IntULE = 37,
-    IntSGT = 38,
-    IntSGE = 39,
-    IntSLT = 40,
-    IntSLE = 41,
-}
-
-/// LLVMRealPredicate
-#[derive(Copy, Clone)]
-#[repr(C)]
-pub enum RealPredicate {
-    RealPredicateFalse = 0,
-    RealOEQ = 1,
-    RealOGT = 2,
-    RealOGE = 3,
-    RealOLT = 4,
-    RealOLE = 5,
-    RealONE = 6,
-    RealORD = 7,
-    RealUNO = 8,
-    RealUEQ = 9,
-    RealUGT = 10,
-    RealUGE = 11,
-    RealULT = 12,
-    RealULE = 13,
-    RealUNE = 14,
-    RealPredicateTrue = 15,
-}
-
-/// LLVMTypeKind
-#[derive(Copy, Clone, PartialEq, Debug)]
-#[repr(C)]
-pub enum TypeKind {
-    Void = 0,
-    Half = 1,
-    Float = 2,
-    Double = 3,
-    X86_FP80 = 4,
-    FP128 = 5,
-    PPC_FP128 = 6,
-    Label = 7,
-    Integer = 8,
-    Function = 9,
-    Struct = 10,
-    Array = 11,
-    Pointer = 12,
-    Vector = 13,
-    Metadata = 14,
-    X86_MMX = 15,
-    Token = 16,
-}
-
-/// LLVMAtomicRmwBinOp
-#[derive(Copy, Clone)]
-#[repr(C)]
-pub enum AtomicRmwBinOp {
-    AtomicXchg = 0,
-    AtomicAdd = 1,
-    AtomicSub = 2,
-    AtomicAnd = 3,
-    AtomicNand = 4,
-    AtomicOr = 5,
-    AtomicXor = 6,
-    AtomicMax = 7,
-    AtomicMin = 8,
-    AtomicUMax = 9,
-    AtomicUMin = 10,
-}
-
-/// LLVMAtomicOrdering
-#[derive(Copy, Clone)]
-#[repr(C)]
-pub enum AtomicOrdering {
-    NotAtomic = 0,
-    Unordered = 1,
-    Monotonic = 2,
-    // Consume = 3,  // Not specified yet.
-    Acquire = 4,
-    Release = 5,
-    AcquireRelease = 6,
-    SequentiallyConsistent = 7,
-}
-
-/// LLVMRustSynchronizationScope
-#[derive(Copy, Clone)]
-#[repr(C)]
-pub enum SynchronizationScope {
-    Other,
-    SingleThread,
-    CrossThread,
-}
-
-/// LLVMRustFileType
-#[derive(Copy, Clone)]
-#[repr(C)]
-pub enum FileType {
-    Other,
-    AssemblyFile,
-    ObjectFile,
-}
-
-/// LLVMMetadataType
-#[derive(Copy, Clone)]
-#[repr(C)]
-pub enum MetadataType {
-    MD_dbg = 0,
-    MD_tbaa = 1,
-    MD_prof = 2,
-    MD_fpmath = 3,
-    MD_range = 4,
-    MD_tbaa_struct = 5,
-    MD_invariant_load = 6,
-    MD_alias_scope = 7,
-    MD_noalias = 8,
-    MD_nontemporal = 9,
-    MD_mem_parallel_loop_access = 10,
-    MD_nonnull = 11,
-}
-
-/// LLVMRustAsmDialect
-#[derive(Copy, Clone)]
-#[repr(C)]
-pub enum AsmDialect {
-    Other,
-    Att,
-    Intel,
-}
-
-/// LLVMRustCodeGenOptLevel
-#[derive(Copy, Clone, PartialEq)]
-#[repr(C)]
-pub enum CodeGenOptLevel {
-    Other,
-    None,
-    Less,
-    Default,
-    Aggressive,
-}
-
-/// LLVMRelocMode
-#[derive(Copy, Clone, PartialEq)]
-#[repr(C)]
-pub enum RelocMode {
-    Default,
-    Static,
-    PIC,
-    DynamicNoPic,
-    ROPI,
-    RWPI,
-    ROPI_RWPI,
-}
-
-/// LLVMRustCodeModel
-#[derive(Copy, Clone)]
-#[repr(C)]
-pub enum CodeModel {
-    Other,
-    Small,
-    Kernel,
-    Medium,
-    Large,
-    None,
-}
-
-/// LLVMRustDiagnosticKind
-#[derive(Copy, Clone)]
-#[repr(C)]
-pub enum DiagnosticKind {
-    Other,
-    InlineAsm,
-    StackSize,
-    DebugMetadataVersion,
-    SampleProfile,
-    OptimizationRemark,
-    OptimizationRemarkMissed,
-    OptimizationRemarkAnalysis,
-    OptimizationRemarkAnalysisFPCommute,
-    OptimizationRemarkAnalysisAliasing,
-    OptimizationRemarkOther,
-    OptimizationFailure,
-    PGOProfile,
-}
-
-/// LLVMRustArchiveKind
-#[derive(Copy, Clone)]
-#[repr(C)]
-pub enum ArchiveKind {
-    Other,
-    K_GNU,
-    K_BSD,
-    K_COFF,
-}
-
-/// LLVMRustPassKind
-#[derive(Copy, Clone, PartialEq, Debug)]
-#[repr(C)]
-pub enum PassKind {
-    Other,
-    Function,
-    Module,
-}
-
-/// LLVMRustThinLTOData
-pub enum ThinLTOData {}
-
-/// LLVMRustThinLTOBuffer
-pub enum ThinLTOBuffer {}
-
-/// LLVMRustThinLTOModule
-#[repr(C)]
-pub struct ThinLTOModule {
-    pub identifier: *const c_char,
-    pub data: *const u8,
-    pub len: usize,
-}
-
-/// LLVMThreadLocalMode
-#[derive(Copy, Clone)]
-#[repr(C)]
-pub enum ThreadLocalMode {
-  NotThreadLocal,
-  GeneralDynamic,
-  LocalDynamic,
-  InitialExec,
-  LocalExec
-}
-
-// Opaque pointer types
-#[allow(missing_copy_implementations)]
-pub enum Module_opaque {}
-pub type ModuleRef = *mut Module_opaque;
-#[allow(missing_copy_implementations)]
-pub enum Context_opaque {}
-pub type ContextRef = *mut Context_opaque;
-#[allow(missing_copy_implementations)]
-pub enum Type_opaque {}
-pub type TypeRef = *mut Type_opaque;
-#[allow(missing_copy_implementations)]
-pub enum Value_opaque {}
-pub type ValueRef = *mut Value_opaque;
-#[allow(missing_copy_implementations)]
-pub enum Metadata_opaque {}
-pub type MetadataRef = *mut Metadata_opaque;
-#[allow(missing_copy_implementations)]
-pub enum BasicBlock_opaque {}
-pub type BasicBlockRef = *mut BasicBlock_opaque;
-#[allow(missing_copy_implementations)]
-pub enum Builder_opaque {}
-pub type BuilderRef = *mut Builder_opaque;
-#[allow(missing_copy_implementations)]
-pub enum ExecutionEngine_opaque {}
-pub type ExecutionEngineRef = *mut ExecutionEngine_opaque;
-#[allow(missing_copy_implementations)]
-pub enum MemoryBuffer_opaque {}
-pub type MemoryBufferRef = *mut MemoryBuffer_opaque;
-#[allow(missing_copy_implementations)]
-pub enum PassManager_opaque {}
-pub type PassManagerRef = *mut PassManager_opaque;
-#[allow(missing_copy_implementations)]
-pub enum PassManagerBuilder_opaque {}
-pub type PassManagerBuilderRef = *mut PassManagerBuilder_opaque;
-#[allow(missing_copy_implementations)]
-pub enum Use_opaque {}
-pub type UseRef = *mut Use_opaque;
-#[allow(missing_copy_implementations)]
-pub enum TargetData_opaque {}
-pub type TargetDataRef = *mut TargetData_opaque;
-#[allow(missing_copy_implementations)]
-pub enum ObjectFile_opaque {}
-pub type ObjectFileRef = *mut ObjectFile_opaque;
-#[allow(missing_copy_implementations)]
-pub enum SectionIterator_opaque {}
-pub type SectionIteratorRef = *mut SectionIterator_opaque;
-#[allow(missing_copy_implementations)]
-pub enum Pass_opaque {}
-pub type PassRef = *mut Pass_opaque;
-#[allow(missing_copy_implementations)]
-pub enum TargetMachine_opaque {}
-pub type TargetMachineRef = *mut TargetMachine_opaque;
-pub enum Archive_opaque {}
-pub type ArchiveRef = *mut Archive_opaque;
-pub enum ArchiveIterator_opaque {}
-pub type ArchiveIteratorRef = *mut ArchiveIterator_opaque;
-pub enum ArchiveChild_opaque {}
-pub type ArchiveChildRef = *mut ArchiveChild_opaque;
-#[allow(missing_copy_implementations)]
-pub enum Twine_opaque {}
-pub type TwineRef = *mut Twine_opaque;
-#[allow(missing_copy_implementations)]
-pub enum DiagnosticInfo_opaque {}
-pub type DiagnosticInfoRef = *mut DiagnosticInfo_opaque;
-#[allow(missing_copy_implementations)]
-pub enum DebugLoc_opaque {}
-pub type DebugLocRef = *mut DebugLoc_opaque;
-#[allow(missing_copy_implementations)]
-pub enum SMDiagnostic_opaque {}
-pub type SMDiagnosticRef = *mut SMDiagnostic_opaque;
-#[allow(missing_copy_implementations)]
-pub enum RustArchiveMember_opaque {}
-pub type RustArchiveMemberRef = *mut RustArchiveMember_opaque;
-#[allow(missing_copy_implementations)]
-pub enum OperandBundleDef_opaque {}
-pub type OperandBundleDefRef = *mut OperandBundleDef_opaque;
-#[allow(missing_copy_implementations)]
-pub enum Linker_opaque {}
-pub type LinkerRef = *mut Linker_opaque;
-
-pub type DiagnosticHandler = unsafe extern "C" fn(DiagnosticInfoRef, *mut c_void);
-pub type InlineAsmDiagHandler = unsafe extern "C" fn(SMDiagnosticRef, *const c_void, c_uint);
-
-
-pub mod debuginfo {
-    use super::MetadataRef;
-
-    #[allow(missing_copy_implementations)]
-    pub enum DIBuilder_opaque {}
-    pub type DIBuilderRef = *mut DIBuilder_opaque;
-
-    pub type DIDescriptor = MetadataRef;
-    pub type DIScope = DIDescriptor;
-    pub type DILocation = DIDescriptor;
-    pub type DIFile = DIScope;
-    pub type DILexicalBlock = DIScope;
-    pub type DISubprogram = DIScope;
-    pub type DINameSpace = DIScope;
-    pub type DIType = DIDescriptor;
-    pub type DIBasicType = DIType;
-    pub type DIDerivedType = DIType;
-    pub type DICompositeType = DIDerivedType;
-    pub type DIVariable = DIDescriptor;
-    pub type DIGlobalVariable = DIDescriptor;
-    pub type DIArray = DIDescriptor;
-    pub type DISubrange = DIDescriptor;
-    pub type DIEnumerator = DIDescriptor;
-    pub type DITemplateTypeParameter = DIDescriptor;
-
-    // These values **must** match with LLVMRustDIFlags!!
-    bitflags! {
-        #[repr(C)]
-        #[derive(Default)]
-        pub struct DIFlags: ::libc::uint32_t {
-            const FlagZero                = 0;
-            const FlagPrivate             = 1;
-            const FlagProtected           = 2;
-            const FlagPublic              = 3;
-            const FlagFwdDecl             = (1 << 2);
-            const FlagAppleBlock          = (1 << 3);
-            const FlagBlockByrefStruct    = (1 << 4);
-            const FlagVirtual             = (1 << 5);
-            const FlagArtificial          = (1 << 6);
-            const FlagExplicit            = (1 << 7);
-            const FlagPrototyped          = (1 << 8);
-            const FlagObjcClassComplete   = (1 << 9);
-            const FlagObjectPointer       = (1 << 10);
-            const FlagVector              = (1 << 11);
-            const FlagStaticMember        = (1 << 12);
-            const FlagLValueReference     = (1 << 13);
-            const FlagRValueReference     = (1 << 14);
-            const FlagExternalTypeRef     = (1 << 15);
-            const FlagIntroducedVirtual   = (1 << 18);
-            const FlagBitField            = (1 << 19);
-            const FlagNoReturn            = (1 << 20);
-            const FlagMainSubprogram      = (1 << 21);
-        }
-    }
-}
-
-pub enum ModuleBuffer {}
-
-// This annotation is primarily needed for MSVC where attributes like
-// dllimport/dllexport are applied and need to be correct for everything to
-// link successfully. The #[link] annotation here says "these symbols are
-// included statically" which means that they're all exported with dllexport
-// and from the rustc_llvm dynamic library. Otherwise the rustc_codegen_llvm dynamic
-// library would not be able to access these symbols.
-#[link(name = "rustllvm", kind = "static")]
-extern "C" {
-    // Create and destroy contexts.
-    pub fn LLVMRustContextCreate(shouldDiscardNames: bool) -> ContextRef;
-    pub fn LLVMContextDispose(C: ContextRef);
-    pub fn LLVMGetMDKindIDInContext(C: ContextRef, Name: *const c_char, SLen: c_uint) -> c_uint;
-
-    // Create and destroy modules.
-    pub fn LLVMModuleCreateWithNameInContext(ModuleID: *const c_char, C: ContextRef) -> ModuleRef;
-    pub fn LLVMGetModuleContext(M: ModuleRef) -> ContextRef;
-    pub fn LLVMCloneModule(M: ModuleRef) -> ModuleRef;
-    pub fn LLVMDisposeModule(M: ModuleRef);
-
-    /// Data layout. See Module::getDataLayout.
-    pub fn LLVMGetDataLayout(M: ModuleRef) -> *const c_char;
-    pub fn LLVMSetDataLayout(M: ModuleRef, Triple: *const c_char);
-
-    /// See Module::dump.
-    pub fn LLVMDumpModule(M: ModuleRef);
-
-    /// See Module::setModuleInlineAsm.
-    pub fn LLVMSetModuleInlineAsm(M: ModuleRef, Asm: *const c_char);
-    pub fn LLVMRustAppendModuleInlineAsm(M: ModuleRef, Asm: *const c_char);
-
-    /// See llvm::LLVMTypeKind::getTypeID.
-    pub fn LLVMRustGetTypeKind(Ty: TypeRef) -> TypeKind;
-
-    // Operations on integer types
-    pub fn LLVMInt1TypeInContext(C: ContextRef) -> TypeRef;
-    pub fn LLVMInt8TypeInContext(C: ContextRef) -> TypeRef;
-    pub fn LLVMInt16TypeInContext(C: ContextRef) -> TypeRef;
-    pub fn LLVMInt32TypeInContext(C: ContextRef) -> TypeRef;
-    pub fn LLVMInt64TypeInContext(C: ContextRef) -> TypeRef;
-    pub fn LLVMIntTypeInContext(C: ContextRef, NumBits: c_uint) -> TypeRef;
-
-    pub fn LLVMGetIntTypeWidth(IntegerTy: TypeRef) -> c_uint;
-
-    // Operations on real types
-    pub fn LLVMFloatTypeInContext(C: ContextRef) -> TypeRef;
-    pub fn LLVMDoubleTypeInContext(C: ContextRef) -> TypeRef;
-
-    // Operations on function types
-    pub fn LLVMFunctionType(ReturnType: TypeRef,
-                            ParamTypes: *const TypeRef,
-                            ParamCount: c_uint,
-                            IsVarArg: Bool)
-                            -> TypeRef;
-    pub fn LLVMGetReturnType(FunctionTy: TypeRef) -> TypeRef;
-    pub fn LLVMCountParamTypes(FunctionTy: TypeRef) -> c_uint;
-    pub fn LLVMGetParamTypes(FunctionTy: TypeRef, Dest: *mut TypeRef);
-
-    // Operations on struct types
-    pub fn LLVMStructTypeInContext(C: ContextRef,
-                                   ElementTypes: *const TypeRef,
-                                   ElementCount: c_uint,
-                                   Packed: Bool)
-                                   -> TypeRef;
-    pub fn LLVMIsPackedStruct(StructTy: TypeRef) -> Bool;
-
-    // Operations on array, pointer, and vector types (sequence types)
-    pub fn LLVMRustArrayType(ElementType: TypeRef, ElementCount: u64) -> TypeRef;
-    pub fn LLVMPointerType(ElementType: TypeRef, AddressSpace: c_uint) -> TypeRef;
-    pub fn LLVMVectorType(ElementType: TypeRef, ElementCount: c_uint) -> TypeRef;
-
-    pub fn LLVMGetElementType(Ty: TypeRef) -> TypeRef;
-    pub fn LLVMGetVectorSize(VectorTy: TypeRef) -> c_uint;
-
-    // Operations on other types
-    pub fn LLVMVoidTypeInContext(C: ContextRef) -> TypeRef;
-    pub fn LLVMX86MMXTypeInContext(C: ContextRef) -> TypeRef;
-    pub fn LLVMRustMetadataTypeInContext(C: ContextRef) -> TypeRef;
-
-    // Operations on all values
-    pub fn LLVMTypeOf(Val: ValueRef) -> TypeRef;
-    pub fn LLVMGetValueName(Val: ValueRef) -> *const c_char;
-    pub fn LLVMSetValueName(Val: ValueRef, Name: *const c_char);
-    pub fn LLVMReplaceAllUsesWith(OldVal: ValueRef, NewVal: ValueRef);
-    pub fn LLVMSetMetadata(Val: ValueRef, KindID: c_uint, Node: ValueRef);
-
-    // Operations on Uses
-    pub fn LLVMGetFirstUse(Val: ValueRef) -> UseRef;
-    pub fn LLVMGetNextUse(U: UseRef) -> UseRef;
-    pub fn LLVMGetUser(U: UseRef) -> ValueRef;
-
-    // Operations on Users
-    pub fn LLVMGetOperand(Val: ValueRef, Index: c_uint) -> ValueRef;
-
-    // Operations on constants of any type
-    pub fn LLVMConstNull(Ty: TypeRef) -> ValueRef;
-    pub fn LLVMConstICmp(Pred: IntPredicate, V1: ValueRef, V2: ValueRef) -> ValueRef;
-    pub fn LLVMConstFCmp(Pred: RealPredicate, V1: ValueRef, V2: ValueRef) -> ValueRef;
-    pub fn LLVMGetUndef(Ty: TypeRef) -> ValueRef;
-
-    // Operations on metadata
-    pub fn LLVMMDStringInContext(C: ContextRef, Str: *const c_char, SLen: c_uint) -> ValueRef;
-    pub fn LLVMMDNodeInContext(C: ContextRef, Vals: *const ValueRef, Count: c_uint) -> ValueRef;
-    pub fn LLVMAddNamedMetadataOperand(M: ModuleRef, Name: *const c_char, Val: ValueRef);
-
-    // Operations on scalar constants
-    pub fn LLVMConstInt(IntTy: TypeRef, N: c_ulonglong, SignExtend: Bool) -> ValueRef;
-    pub fn LLVMConstIntOfArbitraryPrecision(IntTy: TypeRef, Wn: c_uint, Ws: *const u64) -> ValueRef;
-    pub fn LLVMConstIntGetZExtValue(ConstantVal: ValueRef) -> c_ulonglong;
-    pub fn LLVMConstIntGetSExtValue(ConstantVal: ValueRef) -> c_longlong;
-    pub fn LLVMRustConstInt128Get(ConstantVal: ValueRef, SExt: bool,
-                                  high: *mut u64, low: *mut u64) -> bool;
-    pub fn LLVMConstRealGetDouble (ConstantVal: ValueRef, losesInfo: *mut Bool) -> f64;
-
-
-    // Operations on composite constants
-    pub fn LLVMConstStringInContext(C: ContextRef,
-                                    Str: *const c_char,
-                                    Length: c_uint,
-                                    DontNullTerminate: Bool)
-                                    -> ValueRef;
-    pub fn LLVMConstStructInContext(C: ContextRef,
-                                    ConstantVals: *const ValueRef,
-                                    Count: c_uint,
-                                    Packed: Bool)
-                                    -> ValueRef;
-
-    pub fn LLVMConstArray(ElementTy: TypeRef,
-                          ConstantVals: *const ValueRef,
-                          Length: c_uint)
-                          -> ValueRef;
-    pub fn LLVMConstVector(ScalarConstantVals: *const ValueRef, Size: c_uint) -> ValueRef;
-
-    // Constant expressions
-    pub fn LLVMSizeOf(Ty: TypeRef) -> ValueRef;
-    pub fn LLVMConstNeg(ConstantVal: ValueRef) -> ValueRef;
-    pub fn LLVMConstFNeg(ConstantVal: ValueRef) -> ValueRef;
-    pub fn LLVMConstNot(ConstantVal: ValueRef) -> ValueRef;
-    pub fn LLVMConstAdd(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef;
-    pub fn LLVMConstFAdd(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef;
-    pub fn LLVMConstSub(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef;
-    pub fn LLVMConstFSub(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef;
-    pub fn LLVMConstMul(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef;
-    pub fn LLVMConstFMul(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef;
-    pub fn LLVMConstUDiv(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef;
-    pub fn LLVMConstSDiv(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef;
-    pub fn LLVMConstFDiv(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef;
-    pub fn LLVMConstURem(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef;
-    pub fn LLVMConstSRem(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef;
-    pub fn LLVMConstFRem(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef;
-    pub fn LLVMConstAnd(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef;
-    pub fn LLVMConstOr(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef;
-    pub fn LLVMConstXor(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef;
-    pub fn LLVMConstShl(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef;
-    pub fn LLVMConstLShr(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef;
-    pub fn LLVMConstAShr(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef;
-    pub fn LLVMConstGEP(
-        ConstantVal: ValueRef,
-        ConstantIndices: *const ValueRef,
-        NumIndices: c_uint,
-    ) -> ValueRef;
-    pub fn LLVMConstInBoundsGEP(
-        ConstantVal: ValueRef,
-        ConstantIndices: *const ValueRef,
-        NumIndices: c_uint,
-    ) -> ValueRef;
-    pub fn LLVMConstTrunc(ConstantVal: ValueRef, ToType: TypeRef) -> ValueRef;
-    pub fn LLVMConstZExt(ConstantVal: ValueRef, ToType: TypeRef) -> ValueRef;
-    pub fn LLVMConstUIToFP(ConstantVal: ValueRef, ToType: TypeRef) -> ValueRef;
-    pub fn LLVMConstSIToFP(ConstantVal: ValueRef, ToType: TypeRef) -> ValueRef;
-    pub fn LLVMConstFPToUI(ConstantVal: ValueRef, ToType: TypeRef) -> ValueRef;
-    pub fn LLVMConstFPToSI(ConstantVal: ValueRef, ToType: TypeRef) -> ValueRef;
-    pub fn LLVMConstPtrToInt(ConstantVal: ValueRef, ToType: TypeRef) -> ValueRef;
-    pub fn LLVMConstIntToPtr(ConstantVal: ValueRef, ToType: TypeRef) -> ValueRef;
-    pub fn LLVMConstBitCast(ConstantVal: ValueRef, ToType: TypeRef) -> ValueRef;
-    pub fn LLVMConstPointerCast(ConstantVal: ValueRef, ToType: TypeRef) -> ValueRef;
-    pub fn LLVMConstIntCast(ConstantVal: ValueRef, ToType: TypeRef, isSigned: Bool) -> ValueRef;
-    pub fn LLVMConstFPCast(ConstantVal: ValueRef, ToType: TypeRef) -> ValueRef;
-    pub fn LLVMConstExtractValue(AggConstant: ValueRef,
-                                 IdxList: *const c_uint,
-                                 NumIdx: c_uint)
-                                 -> ValueRef;
-    pub fn LLVMConstInlineAsm(Ty: TypeRef,
-                              AsmString: *const c_char,
-                              Constraints: *const c_char,
-                              HasSideEffects: Bool,
-                              IsAlignStack: Bool)
-                              -> ValueRef;
-
-
-    // Operations on global variables, functions, and aliases (globals)
-    pub fn LLVMGetGlobalParent(Global: ValueRef) -> ModuleRef;
-    pub fn LLVMIsDeclaration(Global: ValueRef) -> Bool;
-    pub fn LLVMRustGetLinkage(Global: ValueRef) -> Linkage;
-    pub fn LLVMRustSetLinkage(Global: ValueRef, RustLinkage: Linkage);
-    pub fn LLVMGetSection(Global: ValueRef) -> *const c_char;
-    pub fn LLVMSetSection(Global: ValueRef, Section: *const c_char);
-    pub fn LLVMRustGetVisibility(Global: ValueRef) -> Visibility;
-    pub fn LLVMRustSetVisibility(Global: ValueRef, Viz: Visibility);
-    pub fn LLVMGetAlignment(Global: ValueRef) -> c_uint;
-    pub fn LLVMSetAlignment(Global: ValueRef, Bytes: c_uint);
-    pub fn LLVMSetDLLStorageClass(V: ValueRef, C: DLLStorageClass);
-
-
-    // Operations on global variables
-    pub fn LLVMIsAGlobalVariable(GlobalVar: ValueRef) -> ValueRef;
-    pub fn LLVMAddGlobal(M: ModuleRef, Ty: TypeRef, Name: *const c_char) -> ValueRef;
-    pub fn LLVMGetNamedGlobal(M: ModuleRef, Name: *const c_char) -> ValueRef;
-    pub fn LLVMRustGetOrInsertGlobal(M: ModuleRef, Name: *const c_char, T: TypeRef) -> ValueRef;
-    pub fn LLVMGetFirstGlobal(M: ModuleRef) -> ValueRef;
-    pub fn LLVMGetNextGlobal(GlobalVar: ValueRef) -> ValueRef;
-    pub fn LLVMDeleteGlobal(GlobalVar: ValueRef);
-    pub fn LLVMGetInitializer(GlobalVar: ValueRef) -> ValueRef;
-    pub fn LLVMSetInitializer(GlobalVar: ValueRef, ConstantVal: ValueRef);
-    pub fn LLVMSetThreadLocal(GlobalVar: ValueRef, IsThreadLocal: Bool);
-    pub fn LLVMSetThreadLocalMode(GlobalVar: ValueRef, Mode: ThreadLocalMode);
-    pub fn LLVMIsGlobalConstant(GlobalVar: ValueRef) -> Bool;
-    pub fn LLVMSetGlobalConstant(GlobalVar: ValueRef, IsConstant: Bool);
-    pub fn LLVMRustGetNamedValue(M: ModuleRef, Name: *const c_char) -> ValueRef;
-    pub fn LLVMSetTailCall(CallInst: ValueRef, IsTailCall: Bool);
-
-    // Operations on functions
-    pub fn LLVMAddFunction(M: ModuleRef, Name: *const c_char, FunctionTy: TypeRef) -> ValueRef;
-    pub fn LLVMGetNamedFunction(M: ModuleRef, Name: *const c_char) -> ValueRef;
-    pub fn LLVMGetFirstFunction(M: ModuleRef) -> ValueRef;
-    pub fn LLVMGetNextFunction(Fn: ValueRef) -> ValueRef;
-    pub fn LLVMRustGetOrInsertFunction(M: ModuleRef,
-                                       Name: *const c_char,
-                                       FunctionTy: TypeRef)
-                                       -> ValueRef;
-    pub fn LLVMSetFunctionCallConv(Fn: ValueRef, CC: c_uint);
-    pub fn LLVMRustAddAlignmentAttr(Fn: ValueRef, index: c_uint, bytes: u32);
-    pub fn LLVMRustAddDereferenceableAttr(Fn: ValueRef, index: c_uint, bytes: u64);
-    pub fn LLVMRustAddDereferenceableOrNullAttr(Fn: ValueRef, index: c_uint, bytes: u64);
-    pub fn LLVMRustAddFunctionAttribute(Fn: ValueRef, index: c_uint, attr: Attribute);
-    pub fn LLVMRustAddFunctionAttrStringValue(Fn: ValueRef,
-                                              index: c_uint,
-                                              Name: *const c_char,
-                                              Value: *const c_char);
-    pub fn LLVMRustRemoveFunctionAttributes(Fn: ValueRef, index: c_uint, attr: Attribute);
-
-    // Operations on parameters
-    pub fn LLVMCountParams(Fn: ValueRef) -> c_uint;
-    pub fn LLVMGetParam(Fn: ValueRef, Index: c_uint) -> ValueRef;
-
-    // Operations on basic blocks
-    pub fn LLVMBasicBlockAsValue(BB: BasicBlockRef) -> ValueRef;
-    pub fn LLVMGetBasicBlockParent(BB: BasicBlockRef) -> ValueRef;
-    pub fn LLVMAppendBasicBlockInContext(C: ContextRef,
-                                         Fn: ValueRef,
-                                         Name: *const c_char)
-                                         -> BasicBlockRef;
-    pub fn LLVMDeleteBasicBlock(BB: BasicBlockRef);
-
-    // Operations on instructions
-    pub fn LLVMGetInstructionParent(Inst: ValueRef) -> BasicBlockRef;
-    pub fn LLVMGetFirstBasicBlock(Fn: ValueRef) -> BasicBlockRef;
-    pub fn LLVMGetFirstInstruction(BB: BasicBlockRef) -> ValueRef;
-    pub fn LLVMInstructionEraseFromParent(Inst: ValueRef);
-
-    // Operations on call sites
-    pub fn LLVMSetInstructionCallConv(Instr: ValueRef, CC: c_uint);
-    pub fn LLVMRustAddCallSiteAttribute(Instr: ValueRef, index: c_uint, attr: Attribute);
-    pub fn LLVMRustAddAlignmentCallSiteAttr(Instr: ValueRef, index: c_uint, bytes: u32);
-    pub fn LLVMRustAddDereferenceableCallSiteAttr(Instr: ValueRef, index: c_uint, bytes: u64);
-    pub fn LLVMRustAddDereferenceableOrNullCallSiteAttr(Instr: ValueRef,
-                                                        index: c_uint,
-                                                        bytes: u64);
-
-    // Operations on load/store instructions (only)
-    pub fn LLVMSetVolatile(MemoryAccessInst: ValueRef, volatile: Bool);
-
-    // Operations on phi nodes
-    pub fn LLVMAddIncoming(PhiNode: ValueRef,
-                           IncomingValues: *const ValueRef,
-                           IncomingBlocks: *const BasicBlockRef,
-                           Count: c_uint);
-
-    // Instruction builders
-    pub fn LLVMCreateBuilderInContext(C: ContextRef) -> BuilderRef;
-    pub fn LLVMPositionBuilder(Builder: BuilderRef, Block: BasicBlockRef, Instr: ValueRef);
-    pub fn LLVMPositionBuilderBefore(Builder: BuilderRef, Instr: ValueRef);
-    pub fn LLVMPositionBuilderAtEnd(Builder: BuilderRef, Block: BasicBlockRef);
-    pub fn LLVMGetInsertBlock(Builder: BuilderRef) -> BasicBlockRef;
-    pub fn LLVMDisposeBuilder(Builder: BuilderRef);
-
-    // Metadata
-    pub fn LLVMSetCurrentDebugLocation(Builder: BuilderRef, L: ValueRef);
-    pub fn LLVMGetCurrentDebugLocation(Builder: BuilderRef) -> ValueRef;
-    pub fn LLVMSetInstDebugLocation(Builder: BuilderRef, Inst: ValueRef);
-
-    // Terminators
-    pub fn LLVMBuildRetVoid(B: BuilderRef) -> ValueRef;
-    pub fn LLVMBuildRet(B: BuilderRef, V: ValueRef) -> ValueRef;
-    pub fn LLVMBuildAggregateRet(B: BuilderRef, RetVals: *const ValueRef, N: c_uint) -> ValueRef;
-    pub fn LLVMBuildBr(B: BuilderRef, Dest: BasicBlockRef) -> ValueRef;
-    pub fn LLVMBuildCondBr(B: BuilderRef,
-                           If: ValueRef,
-                           Then: BasicBlockRef,
-                           Else: BasicBlockRef)
-                           -> ValueRef;
-    pub fn LLVMBuildSwitch(B: BuilderRef,
-                           V: ValueRef,
-                           Else: BasicBlockRef,
-                           NumCases: c_uint)
-                           -> ValueRef;
-    pub fn LLVMBuildIndirectBr(B: BuilderRef, Addr: ValueRef, NumDests: c_uint) -> ValueRef;
-    pub fn LLVMRustBuildInvoke(B: BuilderRef,
-                               Fn: ValueRef,
-                               Args: *const ValueRef,
-                               NumArgs: c_uint,
-                               Then: BasicBlockRef,
-                               Catch: BasicBlockRef,
-                               Bundle: OperandBundleDefRef,
-                               Name: *const c_char)
-                               -> ValueRef;
-    pub fn LLVMBuildLandingPad(B: BuilderRef,
-                               Ty: TypeRef,
-                               PersFn: ValueRef,
-                               NumClauses: c_uint,
-                               Name: *const c_char)
-                               -> ValueRef;
-    pub fn LLVMBuildResume(B: BuilderRef, Exn: ValueRef) -> ValueRef;
-    pub fn LLVMBuildUnreachable(B: BuilderRef) -> ValueRef;
-
-    pub fn LLVMRustBuildCleanupPad(B: BuilderRef,
-                                   ParentPad: ValueRef,
-                                   ArgCnt: c_uint,
-                                   Args: *const ValueRef,
-                                   Name: *const c_char)
-                                   -> ValueRef;
-    pub fn LLVMRustBuildCleanupRet(B: BuilderRef,
-                                   CleanupPad: ValueRef,
-                                   UnwindBB: BasicBlockRef)
-                                   -> ValueRef;
-    pub fn LLVMRustBuildCatchPad(B: BuilderRef,
-                                 ParentPad: ValueRef,
-                                 ArgCnt: c_uint,
-                                 Args: *const ValueRef,
-                                 Name: *const c_char)
-                                 -> ValueRef;
-    pub fn LLVMRustBuildCatchRet(B: BuilderRef, Pad: ValueRef, BB: BasicBlockRef) -> ValueRef;
-    pub fn LLVMRustBuildCatchSwitch(Builder: BuilderRef,
-                                    ParentPad: ValueRef,
-                                    BB: BasicBlockRef,
-                                    NumHandlers: c_uint,
-                                    Name: *const c_char)
-                                    -> ValueRef;
-    pub fn LLVMRustAddHandler(CatchSwitch: ValueRef, Handler: BasicBlockRef);
-    pub fn LLVMSetPersonalityFn(Func: ValueRef, Pers: ValueRef);
-
-    // Add a case to the switch instruction
-    pub fn LLVMAddCase(Switch: ValueRef, OnVal: ValueRef, Dest: BasicBlockRef);
-
-    // Add a clause to the landing pad instruction
-    pub fn LLVMAddClause(LandingPad: ValueRef, ClauseVal: ValueRef);
-
-    // Set the cleanup on a landing pad instruction
-    pub fn LLVMSetCleanup(LandingPad: ValueRef, Val: Bool);
-
-    // Arithmetic
-    pub fn LLVMBuildAdd(B: BuilderRef,
-                        LHS: ValueRef,
-                        RHS: ValueRef,
-                        Name: *const c_char)
-                        -> ValueRef;
-    pub fn LLVMBuildNSWAdd(B: BuilderRef,
-                           LHS: ValueRef,
-                           RHS: ValueRef,
-                           Name: *const c_char)
-                           -> ValueRef;
-    pub fn LLVMBuildNUWAdd(B: BuilderRef,
-                           LHS: ValueRef,
-                           RHS: ValueRef,
-                           Name: *const c_char)
-                           -> ValueRef;
-    pub fn LLVMBuildFAdd(B: BuilderRef,
-                         LHS: ValueRef,
-                         RHS: ValueRef,
-                         Name: *const c_char)
-                         -> ValueRef;
-    pub fn LLVMBuildSub(B: BuilderRef,
-                        LHS: ValueRef,
-                        RHS: ValueRef,
-                        Name: *const c_char)
-                        -> ValueRef;
-    pub fn LLVMBuildNSWSub(B: BuilderRef,
-                           LHS: ValueRef,
-                           RHS: ValueRef,
-                           Name: *const c_char)
-                           -> ValueRef;
-    pub fn LLVMBuildNUWSub(B: BuilderRef,
-                           LHS: ValueRef,
-                           RHS: ValueRef,
-                           Name: *const c_char)
-                           -> ValueRef;
-    pub fn LLVMBuildFSub(B: BuilderRef,
-                         LHS: ValueRef,
-                         RHS: ValueRef,
-                         Name: *const c_char)
-                         -> ValueRef;
-    pub fn LLVMBuildMul(B: BuilderRef,
-                        LHS: ValueRef,
-                        RHS: ValueRef,
-                        Name: *const c_char)
-                        -> ValueRef;
-    pub fn LLVMBuildNSWMul(B: BuilderRef,
-                           LHS: ValueRef,
-                           RHS: ValueRef,
-                           Name: *const c_char)
-                           -> ValueRef;
-    pub fn LLVMBuildNUWMul(B: BuilderRef,
-                           LHS: ValueRef,
-                           RHS: ValueRef,
-                           Name: *const c_char)
-                           -> ValueRef;
-    pub fn LLVMBuildFMul(B: BuilderRef,
-                         LHS: ValueRef,
-                         RHS: ValueRef,
-                         Name: *const c_char)
-                         -> ValueRef;
-    pub fn LLVMBuildUDiv(B: BuilderRef,
-                         LHS: ValueRef,
-                         RHS: ValueRef,
-                         Name: *const c_char)
-                         -> ValueRef;
-    pub fn LLVMBuildExactUDiv(B: BuilderRef,
-                              LHS: ValueRef,
-                              RHS: ValueRef,
-                              Name: *const c_char)
-                              -> ValueRef;
-    pub fn LLVMBuildSDiv(B: BuilderRef,
-                         LHS: ValueRef,
-                         RHS: ValueRef,
-                         Name: *const c_char)
-                         -> ValueRef;
-    pub fn LLVMBuildExactSDiv(B: BuilderRef,
-                              LHS: ValueRef,
-                              RHS: ValueRef,
-                              Name: *const c_char)
-                              -> ValueRef;
-    pub fn LLVMBuildFDiv(B: BuilderRef,
-                         LHS: ValueRef,
-                         RHS: ValueRef,
-                         Name: *const c_char)
-                         -> ValueRef;
-    pub fn LLVMBuildURem(B: BuilderRef,
-                         LHS: ValueRef,
-                         RHS: ValueRef,
-                         Name: *const c_char)
-                         -> ValueRef;
-    pub fn LLVMBuildSRem(B: BuilderRef,
-                         LHS: ValueRef,
-                         RHS: ValueRef,
-                         Name: *const c_char)
-                         -> ValueRef;
-    pub fn LLVMBuildFRem(B: BuilderRef,
-                         LHS: ValueRef,
-                         RHS: ValueRef,
-                         Name: *const c_char)
-                         -> ValueRef;
-    pub fn LLVMBuildShl(B: BuilderRef,
-                        LHS: ValueRef,
-                        RHS: ValueRef,
-                        Name: *const c_char)
-                        -> ValueRef;
-    pub fn LLVMBuildLShr(B: BuilderRef,
-                         LHS: ValueRef,
-                         RHS: ValueRef,
-                         Name: *const c_char)
-                         -> ValueRef;
-    pub fn LLVMBuildAShr(B: BuilderRef,
-                         LHS: ValueRef,
-                         RHS: ValueRef,
-                         Name: *const c_char)
-                         -> ValueRef;
-    pub fn LLVMBuildAnd(B: BuilderRef,
-                        LHS: ValueRef,
-                        RHS: ValueRef,
-                        Name: *const c_char)
-                        -> ValueRef;
-    pub fn LLVMBuildOr(B: BuilderRef,
-                       LHS: ValueRef,
-                       RHS: ValueRef,
-                       Name: *const c_char)
-                       -> ValueRef;
-    pub fn LLVMBuildXor(B: BuilderRef,
-                        LHS: ValueRef,
-                        RHS: ValueRef,
-                        Name: *const c_char)
-                        -> ValueRef;
-    pub fn LLVMBuildBinOp(B: BuilderRef,
-                          Op: Opcode,
-                          LHS: ValueRef,
-                          RHS: ValueRef,
-                          Name: *const c_char)
-                          -> ValueRef;
-    pub fn LLVMBuildNeg(B: BuilderRef, V: ValueRef, Name: *const c_char) -> ValueRef;
-    pub fn LLVMBuildNSWNeg(B: BuilderRef, V: ValueRef, Name: *const c_char) -> ValueRef;
-    pub fn LLVMBuildNUWNeg(B: BuilderRef, V: ValueRef, Name: *const c_char) -> ValueRef;
-    pub fn LLVMBuildFNeg(B: BuilderRef, V: ValueRef, Name: *const c_char) -> ValueRef;
-    pub fn LLVMBuildNot(B: BuilderRef, V: ValueRef, Name: *const c_char) -> ValueRef;
-    pub fn LLVMRustSetHasUnsafeAlgebra(Instr: ValueRef);
-
-    // Memory
-    pub fn LLVMBuildAlloca(B: BuilderRef, Ty: TypeRef, Name: *const c_char) -> ValueRef;
-    pub fn LLVMBuildFree(B: BuilderRef, PointerVal: ValueRef) -> ValueRef;
-    pub fn LLVMBuildLoad(B: BuilderRef, PointerVal: ValueRef, Name: *const c_char) -> ValueRef;
-
-    pub fn LLVMBuildStore(B: BuilderRef, Val: ValueRef, Ptr: ValueRef) -> ValueRef;
-
-    pub fn LLVMBuildGEP(B: BuilderRef,
-                        Pointer: ValueRef,
-                        Indices: *const ValueRef,
-                        NumIndices: c_uint,
-                        Name: *const c_char)
-                        -> ValueRef;
-    pub fn LLVMBuildInBoundsGEP(B: BuilderRef,
-                                Pointer: ValueRef,
-                                Indices: *const ValueRef,
-                                NumIndices: c_uint,
-                                Name: *const c_char)
-                                -> ValueRef;
-    pub fn LLVMBuildStructGEP(B: BuilderRef,
-                              Pointer: ValueRef,
-                              Idx: c_uint,
-                              Name: *const c_char)
-                              -> ValueRef;
-    pub fn LLVMBuildGlobalString(B: BuilderRef,
-                                 Str: *const c_char,
-                                 Name: *const c_char)
-                                 -> ValueRef;
-    pub fn LLVMBuildGlobalStringPtr(B: BuilderRef,
-                                    Str: *const c_char,
-                                    Name: *const c_char)
-                                    -> ValueRef;
-
-    // Casts
-    pub fn LLVMBuildTrunc(B: BuilderRef,
-                          Val: ValueRef,
-                          DestTy: TypeRef,
-                          Name: *const c_char)
-                          -> ValueRef;
-    pub fn LLVMBuildZExt(B: BuilderRef,
-                         Val: ValueRef,
-                         DestTy: TypeRef,
-                         Name: *const c_char)
-                         -> ValueRef;
-    pub fn LLVMBuildSExt(B: BuilderRef,
-                         Val: ValueRef,
-                         DestTy: TypeRef,
-                         Name: *const c_char)
-                         -> ValueRef;
-    pub fn LLVMBuildFPToUI(B: BuilderRef,
-                           Val: ValueRef,
-                           DestTy: TypeRef,
-                           Name: *const c_char)
-                           -> ValueRef;
-    pub fn LLVMBuildFPToSI(B: BuilderRef,
-                           Val: ValueRef,
-                           DestTy: TypeRef,
-                           Name: *const c_char)
-                           -> ValueRef;
-    pub fn LLVMBuildUIToFP(B: BuilderRef,
-                           Val: ValueRef,
-                           DestTy: TypeRef,
-                           Name: *const c_char)
-                           -> ValueRef;
-    pub fn LLVMBuildSIToFP(B: BuilderRef,
-                           Val: ValueRef,
-                           DestTy: TypeRef,
-                           Name: *const c_char)
-                           -> ValueRef;
-    pub fn LLVMBuildFPTrunc(B: BuilderRef,
-                            Val: ValueRef,
-                            DestTy: TypeRef,
-                            Name: *const c_char)
-                            -> ValueRef;
-    pub fn LLVMBuildFPExt(B: BuilderRef,
-                          Val: ValueRef,
-                          DestTy: TypeRef,
-                          Name: *const c_char)
-                          -> ValueRef;
-    pub fn LLVMBuildPtrToInt(B: BuilderRef,
-                             Val: ValueRef,
-                             DestTy: TypeRef,
-                             Name: *const c_char)
-                             -> ValueRef;
-    pub fn LLVMBuildIntToPtr(B: BuilderRef,
-                             Val: ValueRef,
-                             DestTy: TypeRef,
-                             Name: *const c_char)
-                             -> ValueRef;
-    pub fn LLVMBuildBitCast(B: BuilderRef,
-                            Val: ValueRef,
-                            DestTy: TypeRef,
-                            Name: *const c_char)
-                            -> ValueRef;
-    pub fn LLVMBuildZExtOrBitCast(B: BuilderRef,
-                                  Val: ValueRef,
-                                  DestTy: TypeRef,
-                                  Name: *const c_char)
-                                  -> ValueRef;
-    pub fn LLVMBuildSExtOrBitCast(B: BuilderRef,
-                                  Val: ValueRef,
-                                  DestTy: TypeRef,
-                                  Name: *const c_char)
-                                  -> ValueRef;
-    pub fn LLVMBuildTruncOrBitCast(B: BuilderRef,
-                                   Val: ValueRef,
-                                   DestTy: TypeRef,
-                                   Name: *const c_char)
-                                   -> ValueRef;
-    pub fn LLVMBuildCast(B: BuilderRef,
-                         Op: Opcode,
-                         Val: ValueRef,
-                         DestTy: TypeRef,
-                         Name: *const c_char)
-                         -> ValueRef;
-    pub fn LLVMBuildPointerCast(B: BuilderRef,
-                                Val: ValueRef,
-                                DestTy: TypeRef,
-                                Name: *const c_char)
-                                -> ValueRef;
-    pub fn LLVMRustBuildIntCast(B: BuilderRef,
-                                Val: ValueRef,
-                                DestTy: TypeRef,
-                                IsSized: bool)
-                                -> ValueRef;
-    pub fn LLVMBuildFPCast(B: BuilderRef,
-                           Val: ValueRef,
-                           DestTy: TypeRef,
-                           Name: *const c_char)
-                           -> ValueRef;
-
-    // Comparisons
-    pub fn LLVMBuildICmp(B: BuilderRef,
-                         Op: c_uint,
-                         LHS: ValueRef,
-                         RHS: ValueRef,
-                         Name: *const c_char)
-                         -> ValueRef;
-    pub fn LLVMBuildFCmp(B: BuilderRef,
-                         Op: c_uint,
-                         LHS: ValueRef,
-                         RHS: ValueRef,
-                         Name: *const c_char)
-                         -> ValueRef;
-
-    // Miscellaneous instructions
-    pub fn LLVMBuildPhi(B: BuilderRef, Ty: TypeRef, Name: *const c_char) -> ValueRef;
-    pub fn LLVMRustBuildCall(B: BuilderRef,
-                             Fn: ValueRef,
-                             Args: *const ValueRef,
-                             NumArgs: c_uint,
-                             Bundle: OperandBundleDefRef,
-                             Name: *const c_char)
-                             -> ValueRef;
-    pub fn LLVMBuildSelect(B: BuilderRef,
-                           If: ValueRef,
-                           Then: ValueRef,
-                           Else: ValueRef,
-                           Name: *const c_char)
-                           -> ValueRef;
-    pub fn LLVMBuildVAArg(B: BuilderRef,
-                          list: ValueRef,
-                          Ty: TypeRef,
-                          Name: *const c_char)
-                          -> ValueRef;
-    pub fn LLVMBuildExtractElement(B: BuilderRef,
-                                   VecVal: ValueRef,
-                                   Index: ValueRef,
-                                   Name: *const c_char)
-                                   -> ValueRef;
-    pub fn LLVMBuildInsertElement(B: BuilderRef,
-                                  VecVal: ValueRef,
-                                  EltVal: ValueRef,
-                                  Index: ValueRef,
-                                  Name: *const c_char)
-                                  -> ValueRef;
-    pub fn LLVMBuildShuffleVector(B: BuilderRef,
-                                  V1: ValueRef,
-                                  V2: ValueRef,
-                                  Mask: ValueRef,
-                                  Name: *const c_char)
-                                  -> ValueRef;
-    pub fn LLVMBuildExtractValue(B: BuilderRef,
-                                 AggVal: ValueRef,
-                                 Index: c_uint,
-                                 Name: *const c_char)
-                                 -> ValueRef;
-    pub fn LLVMBuildInsertValue(B: BuilderRef,
-                                AggVal: ValueRef,
-                                EltVal: ValueRef,
-                                Index: c_uint,
-                                Name: *const c_char)
-                                -> ValueRef;
-
-    pub fn LLVMRustBuildVectorReduceFAdd(B: BuilderRef,
-                                         Acc: ValueRef,
-                                         Src: ValueRef)
-                                         -> ValueRef;
-    pub fn LLVMRustBuildVectorReduceFMul(B: BuilderRef,
-                                         Acc: ValueRef,
-                                         Src: ValueRef)
-                                         -> ValueRef;
-    pub fn LLVMRustBuildVectorReduceAdd(B: BuilderRef,
-                                        Src: ValueRef)
-                                        -> ValueRef;
-    pub fn LLVMRustBuildVectorReduceMul(B: BuilderRef,
-                                        Src: ValueRef)
-                                        -> ValueRef;
-    pub fn LLVMRustBuildVectorReduceAnd(B: BuilderRef,
-                                        Src: ValueRef)
-                                        -> ValueRef;
-    pub fn LLVMRustBuildVectorReduceOr(B: BuilderRef,
-                                       Src: ValueRef)
-                                       -> ValueRef;
-    pub fn LLVMRustBuildVectorReduceXor(B: BuilderRef,
-                                        Src: ValueRef)
-                                        -> ValueRef;
-    pub fn LLVMRustBuildVectorReduceMin(B: BuilderRef,
-                                        Src: ValueRef,
-                                        IsSigned: bool)
-                                        -> ValueRef;
-    pub fn LLVMRustBuildVectorReduceMax(B: BuilderRef,
-                                        Src: ValueRef,
-                                        IsSigned: bool)
-                                        -> ValueRef;
-    pub fn LLVMRustBuildVectorReduceFMin(B: BuilderRef,
-                                         Src: ValueRef,
-                                         IsNaN: bool)
-                                         -> ValueRef;
-    pub fn LLVMRustBuildVectorReduceFMax(B: BuilderRef,
-                                         Src: ValueRef,
-                                         IsNaN: bool)
-                                         -> ValueRef;
-
-    pub fn LLVMRustBuildMinNum(B: BuilderRef, LHS: ValueRef, LHS: ValueRef) -> ValueRef;
-    pub fn LLVMRustBuildMaxNum(B: BuilderRef, LHS: ValueRef, LHS: ValueRef) -> ValueRef;
-
-    pub fn LLVMBuildIsNull(B: BuilderRef, Val: ValueRef, Name: *const c_char) -> ValueRef;
-    pub fn LLVMBuildIsNotNull(B: BuilderRef, Val: ValueRef, Name: *const c_char) -> ValueRef;
-    pub fn LLVMBuildPtrDiff(B: BuilderRef,
-                            LHS: ValueRef,
-                            RHS: ValueRef,
-                            Name: *const c_char)
-                            -> ValueRef;
-
-    // Atomic Operations
-    pub fn LLVMRustBuildAtomicLoad(B: BuilderRef,
-                                   PointerVal: ValueRef,
-                                   Name: *const c_char,
-                                   Order: AtomicOrdering)
-                                   -> ValueRef;
-
-    pub fn LLVMRustBuildAtomicStore(B: BuilderRef,
-                                    Val: ValueRef,
-                                    Ptr: ValueRef,
-                                    Order: AtomicOrdering)
-                                    -> ValueRef;
-
-    pub fn LLVMRustBuildAtomicCmpXchg(B: BuilderRef,
-                                      LHS: ValueRef,
-                                      CMP: ValueRef,
-                                      RHS: ValueRef,
-                                      Order: AtomicOrdering,
-                                      FailureOrder: AtomicOrdering,
-                                      Weak: Bool)
-                                      -> ValueRef;
-
-    pub fn LLVMBuildAtomicRMW(B: BuilderRef,
-                              Op: AtomicRmwBinOp,
-                              LHS: ValueRef,
-                              RHS: ValueRef,
-                              Order: AtomicOrdering,
-                              SingleThreaded: Bool)
-                              -> ValueRef;
-
-    pub fn LLVMRustBuildAtomicFence(B: BuilderRef,
-                                    Order: AtomicOrdering,
-                                    Scope: SynchronizationScope);
-
-
-    // Selected entries from the downcasts.
-    pub fn LLVMIsATerminatorInst(Inst: ValueRef) -> ValueRef;
-    pub fn LLVMIsAStoreInst(Inst: ValueRef) -> ValueRef;
-
-    /// Writes a module to the specified path. Returns 0 on success.
-    pub fn LLVMWriteBitcodeToFile(M: ModuleRef, Path: *const c_char) -> c_int;
-
-    /// Creates target data from a target layout string.
-    pub fn LLVMCreateTargetData(StringRep: *const c_char) -> TargetDataRef;
-
-    /// Disposes target data.
-    pub fn LLVMDisposeTargetData(TD: TargetDataRef);
-
-    /// Creates a pass manager.
-    pub fn LLVMCreatePassManager() -> PassManagerRef;
-
-    /// Creates a function-by-function pass manager
-    pub fn LLVMCreateFunctionPassManagerForModule(M: ModuleRef) -> PassManagerRef;
-
-    /// Disposes a pass manager.
-    pub fn LLVMDisposePassManager(PM: PassManagerRef);
-
-    /// Runs a pass manager on a module.
-    pub fn LLVMRunPassManager(PM: PassManagerRef, M: ModuleRef) -> Bool;
-
-    pub fn LLVMInitializePasses();
-
-    pub fn LLVMPassManagerBuilderCreate() -> PassManagerBuilderRef;
-    pub fn LLVMPassManagerBuilderDispose(PMB: PassManagerBuilderRef);
-    pub fn LLVMPassManagerBuilderSetSizeLevel(PMB: PassManagerBuilderRef, Value: Bool);
-    pub fn LLVMPassManagerBuilderSetDisableUnrollLoops(PMB: PassManagerBuilderRef, Value: Bool);
-    pub fn LLVMPassManagerBuilderUseInlinerWithThreshold(PMB: PassManagerBuilderRef,
-                                                         threshold: c_uint);
-    pub fn LLVMPassManagerBuilderPopulateModulePassManager(PMB: PassManagerBuilderRef,
-                                                           PM: PassManagerRef);
-
-    pub fn LLVMPassManagerBuilderPopulateFunctionPassManager(PMB: PassManagerBuilderRef,
-                                                             PM: PassManagerRef);
-    pub fn LLVMPassManagerBuilderPopulateLTOPassManager(PMB: PassManagerBuilderRef,
-                                                        PM: PassManagerRef,
-                                                        Internalize: Bool,
-                                                        RunInliner: Bool);
-    pub fn LLVMRustPassManagerBuilderPopulateThinLTOPassManager(
-        PMB: PassManagerBuilderRef,
-        PM: PassManagerRef) -> bool;
-
-    // Stuff that's in rustllvm/ because it's not upstream yet.
-
-    /// Opens an object file.
-    pub fn LLVMCreateObjectFile(MemBuf: MemoryBufferRef) -> ObjectFileRef;
-    /// Closes an object file.
-    pub fn LLVMDisposeObjectFile(ObjFile: ObjectFileRef);
-
-    /// Enumerates the sections in an object file.
-    pub fn LLVMGetSections(ObjFile: ObjectFileRef) -> SectionIteratorRef;
-    /// Destroys a section iterator.
-    pub fn LLVMDisposeSectionIterator(SI: SectionIteratorRef);
-    /// Returns true if the section iterator is at the end of the section
-    /// list:
-    pub fn LLVMIsSectionIteratorAtEnd(ObjFile: ObjectFileRef, SI: SectionIteratorRef) -> Bool;
-    /// Moves the section iterator to point to the next section.
-    pub fn LLVMMoveToNextSection(SI: SectionIteratorRef);
-    /// Returns the current section size.
-    pub fn LLVMGetSectionSize(SI: SectionIteratorRef) -> c_ulonglong;
-    /// Returns the current section contents as a string buffer.
-    pub fn LLVMGetSectionContents(SI: SectionIteratorRef) -> *const c_char;
-
-    /// Reads the given file and returns it as a memory buffer. Use
-    /// LLVMDisposeMemoryBuffer() to get rid of it.
-    pub fn LLVMRustCreateMemoryBufferWithContentsOfFile(Path: *const c_char) -> MemoryBufferRef;
-
-    pub fn LLVMStartMultithreaded() -> Bool;
-
-    /// Returns a string describing the last error caused by an LLVMRust* call.
-    pub fn LLVMRustGetLastError() -> *const c_char;
-
-    /// Print the pass timings since static dtors aren't picking them up.
-    pub fn LLVMRustPrintPassTimings();
-
-    pub fn LLVMStructCreateNamed(C: ContextRef, Name: *const c_char) -> TypeRef;
-
-    pub fn LLVMStructSetBody(StructTy: TypeRef,
-                             ElementTypes: *const TypeRef,
-                             ElementCount: c_uint,
-                             Packed: Bool);
-
-    /// Prepares inline assembly.
-    pub fn LLVMRustInlineAsm(Ty: TypeRef,
-                             AsmString: *const c_char,
-                             Constraints: *const c_char,
-                             SideEffects: Bool,
-                             AlignStack: Bool,
-                             Dialect: AsmDialect)
-                             -> ValueRef;
-
-    pub fn LLVMRustDebugMetadataVersion() -> u32;
-    pub fn LLVMRustVersionMajor() -> u32;
-    pub fn LLVMRustVersionMinor() -> u32;
-
-    pub fn LLVMRustAddModuleFlag(M: ModuleRef, name: *const c_char, value: u32);
-
-    pub fn LLVMRustMetadataAsValue(C: ContextRef, MD: MetadataRef) -> ValueRef;
-
-    pub fn LLVMRustDIBuilderCreate(M: ModuleRef) -> DIBuilderRef;
-
-    pub fn LLVMRustDIBuilderDispose(Builder: DIBuilderRef);
-
-    pub fn LLVMRustDIBuilderFinalize(Builder: DIBuilderRef);
-
-    pub fn LLVMRustDIBuilderCreateCompileUnit(Builder: DIBuilderRef,
-                                              Lang: c_uint,
-                                              File: DIFile,
-                                              Producer: *const c_char,
-                                              isOptimized: bool,
-                                              Flags: *const c_char,
-                                              RuntimeVer: c_uint,
-                                              SplitName: *const c_char)
-                                              -> DIDescriptor;
-
-    pub fn LLVMRustDIBuilderCreateFile(Builder: DIBuilderRef,
-                                       Filename: *const c_char,
-                                       Directory: *const c_char)
-                                       -> DIFile;
-
-    pub fn LLVMRustDIBuilderCreateSubroutineType(Builder: DIBuilderRef,
-                                                 File: DIFile,
-                                                 ParameterTypes: DIArray)
-                                                 -> DICompositeType;
-
-    pub fn LLVMRustDIBuilderCreateFunction(Builder: DIBuilderRef,
-                                           Scope: DIDescriptor,
-                                           Name: *const c_char,
-                                           LinkageName: *const c_char,
-                                           File: DIFile,
-                                           LineNo: c_uint,
-                                           Ty: DIType,
-                                           isLocalToUnit: bool,
-                                           isDefinition: bool,
-                                           ScopeLine: c_uint,
-                                           Flags: DIFlags,
-                                           isOptimized: bool,
-                                           Fn: ValueRef,
-                                           TParam: DIArray,
-                                           Decl: DIDescriptor)
-                                           -> DISubprogram;
-
-    pub fn LLVMRustDIBuilderCreateBasicType(Builder: DIBuilderRef,
-                                            Name: *const c_char,
-                                            SizeInBits: u64,
-                                            AlignInBits: u32,
-                                            Encoding: c_uint)
-                                            -> DIBasicType;
-
-    pub fn LLVMRustDIBuilderCreatePointerType(Builder: DIBuilderRef,
-                                              PointeeTy: DIType,
-                                              SizeInBits: u64,
-                                              AlignInBits: u32,
-                                              Name: *const c_char)
-                                              -> DIDerivedType;
-
-    pub fn LLVMRustDIBuilderCreateStructType(Builder: DIBuilderRef,
-                                             Scope: DIDescriptor,
-                                             Name: *const c_char,
-                                             File: DIFile,
-                                             LineNumber: c_uint,
-                                             SizeInBits: u64,
-                                             AlignInBits: u32,
-                                             Flags: DIFlags,
-                                             DerivedFrom: DIType,
-                                             Elements: DIArray,
-                                             RunTimeLang: c_uint,
-                                             VTableHolder: DIType,
-                                             UniqueId: *const c_char)
-                                             -> DICompositeType;
-
-    pub fn LLVMRustDIBuilderCreateMemberType(Builder: DIBuilderRef,
-                                             Scope: DIDescriptor,
-                                             Name: *const c_char,
-                                             File: DIFile,
-                                             LineNo: c_uint,
-                                             SizeInBits: u64,
-                                             AlignInBits: u32,
-                                             OffsetInBits: u64,
-                                             Flags: DIFlags,
-                                             Ty: DIType)
-                                             -> DIDerivedType;
-
-    pub fn LLVMRustDIBuilderCreateLexicalBlock(Builder: DIBuilderRef,
-                                               Scope: DIScope,
-                                               File: DIFile,
-                                               Line: c_uint,
-                                               Col: c_uint)
-                                               -> DILexicalBlock;
-
-    pub fn LLVMRustDIBuilderCreateLexicalBlockFile(Builder: DIBuilderRef,
-                                                   Scope: DIScope,
-                                                   File: DIFile)
-                                                   -> DILexicalBlock;
-
-    pub fn LLVMRustDIBuilderCreateStaticVariable(Builder: DIBuilderRef,
-                                                 Context: DIScope,
-                                                 Name: *const c_char,
-                                                 LinkageName: *const c_char,
-                                                 File: DIFile,
-                                                 LineNo: c_uint,
-                                                 Ty: DIType,
-                                                 isLocalToUnit: bool,
-                                                 Val: ValueRef,
-                                                 Decl: DIDescriptor,
-                                                 AlignInBits: u32)
-                                                 -> DIGlobalVariable;
-
-    pub fn LLVMRustDIBuilderCreateVariable(Builder: DIBuilderRef,
-                                           Tag: c_uint,
-                                           Scope: DIDescriptor,
-                                           Name: *const c_char,
-                                           File: DIFile,
-                                           LineNo: c_uint,
-                                           Ty: DIType,
-                                           AlwaysPreserve: bool,
-                                           Flags: DIFlags,
-                                           ArgNo: c_uint,
-                                           AlignInBits: u32)
-                                           -> DIVariable;
-
-    pub fn LLVMRustDIBuilderCreateArrayType(Builder: DIBuilderRef,
-                                            Size: u64,
-                                            AlignInBits: u32,
-                                            Ty: DIType,
-                                            Subscripts: DIArray)
-                                            -> DIType;
-
-    pub fn LLVMRustDIBuilderCreateVectorType(Builder: DIBuilderRef,
-                                             Size: u64,
-                                             AlignInBits: u32,
-                                             Ty: DIType,
-                                             Subscripts: DIArray)
-                                             -> DIType;
-
-    pub fn LLVMRustDIBuilderGetOrCreateSubrange(Builder: DIBuilderRef,
-                                                Lo: i64,
-                                                Count: i64)
-                                                -> DISubrange;
-
-    pub fn LLVMRustDIBuilderGetOrCreateArray(Builder: DIBuilderRef,
-                                             Ptr: *const DIDescriptor,
-                                             Count: c_uint)
-                                             -> DIArray;
-
-    pub fn LLVMRustDIBuilderInsertDeclareAtEnd(Builder: DIBuilderRef,
-                                               Val: ValueRef,
-                                               VarInfo: DIVariable,
-                                               AddrOps: *const i64,
-                                               AddrOpsCount: c_uint,
-                                               DL: ValueRef,
-                                               InsertAtEnd: BasicBlockRef)
-                                               -> ValueRef;
-
-    pub fn LLVMRustDIBuilderCreateEnumerator(Builder: DIBuilderRef,
-                                             Name: *const c_char,
-                                             Val: u64)
-                                             -> DIEnumerator;
-
-    pub fn LLVMRustDIBuilderCreateEnumerationType(Builder: DIBuilderRef,
-                                                  Scope: DIScope,
-                                                  Name: *const c_char,
-                                                  File: DIFile,
-                                                  LineNumber: c_uint,
-                                                  SizeInBits: u64,
-                                                  AlignInBits: u32,
-                                                  Elements: DIArray,
-                                                  ClassType: DIType)
-                                                  -> DIType;
-
-    pub fn LLVMRustDIBuilderCreateUnionType(Builder: DIBuilderRef,
-                                            Scope: DIScope,
-                                            Name: *const c_char,
-                                            File: DIFile,
-                                            LineNumber: c_uint,
-                                            SizeInBits: u64,
-                                            AlignInBits: u32,
-                                            Flags: DIFlags,
-                                            Elements: DIArray,
-                                            RunTimeLang: c_uint,
-                                            UniqueId: *const c_char)
-                                            -> DIType;
-
-    pub fn LLVMSetUnnamedAddr(GlobalVar: ValueRef, UnnamedAddr: Bool);
-
-    pub fn LLVMRustDIBuilderCreateTemplateTypeParameter(Builder: DIBuilderRef,
-                                                        Scope: DIScope,
-                                                        Name: *const c_char,
-                                                        Ty: DIType,
-                                                        File: DIFile,
-                                                        LineNo: c_uint,
-                                                        ColumnNo: c_uint)
-                                                        -> DITemplateTypeParameter;
-
-
-    pub fn LLVMRustDIBuilderCreateNameSpace(Builder: DIBuilderRef,
-                                            Scope: DIScope,
-                                            Name: *const c_char,
-                                            File: DIFile,
-                                            LineNo: c_uint)
-                                            -> DINameSpace;
-    pub fn LLVMRustDICompositeTypeSetTypeArray(Builder: DIBuilderRef,
-                                               CompositeType: DIType,
-                                               TypeArray: DIArray);
-
-
-    pub fn LLVMRustDIBuilderCreateDebugLocation(Context: ContextRef,
-                                                Line: c_uint,
-                                                Column: c_uint,
-                                                Scope: DIScope,
-                                                InlinedAt: MetadataRef)
-                                                -> ValueRef;
-    pub fn LLVMRustDIBuilderCreateOpDeref() -> i64;
-    pub fn LLVMRustDIBuilderCreateOpPlusUconst() -> i64;
-
-    pub fn LLVMRustWriteTypeToString(Type: TypeRef, s: RustStringRef);
-    pub fn LLVMRustWriteValueToString(value_ref: ValueRef, s: RustStringRef);
-
-    pub fn LLVMIsAConstantInt(value_ref: ValueRef) -> ValueRef;
-    pub fn LLVMIsAConstantFP(value_ref: ValueRef) -> ValueRef;
-
-    pub fn LLVMRustPassKind(Pass: PassRef) -> PassKind;
-    pub fn LLVMRustFindAndCreatePass(Pass: *const c_char) -> PassRef;
-    pub fn LLVMRustAddPass(PM: PassManagerRef, Pass: PassRef);
-
-    pub fn LLVMRustHasFeature(T: TargetMachineRef, s: *const c_char) -> bool;
-
-    pub fn LLVMRustPrintTargetCPUs(T: TargetMachineRef);
-    pub fn LLVMRustPrintTargetFeatures(T: TargetMachineRef);
-
-    pub fn LLVMRustCreateTargetMachine(Triple: *const c_char,
-                                       CPU: *const c_char,
-                                       Features: *const c_char,
-                                       Model: CodeModel,
-                                       Reloc: RelocMode,
-                                       Level: CodeGenOptLevel,
-                                       UseSoftFP: bool,
-                                       PositionIndependentExecutable: bool,
-                                       FunctionSections: bool,
-                                       DataSections: bool,
-                                       TrapUnreachable: bool,
-                                       Singlethread: bool)
-                                       -> TargetMachineRef;
-    pub fn LLVMRustDisposeTargetMachine(T: TargetMachineRef);
-    pub fn LLVMRustAddAnalysisPasses(T: TargetMachineRef, PM: PassManagerRef, M: ModuleRef);
-    pub fn LLVMRustAddBuilderLibraryInfo(PMB: PassManagerBuilderRef,
-                                         M: ModuleRef,
-                                         DisableSimplifyLibCalls: bool);
-    pub fn LLVMRustConfigurePassManagerBuilder(PMB: PassManagerBuilderRef,
-                                               OptLevel: CodeGenOptLevel,
-                                               MergeFunctions: bool,
-                                               SLPVectorize: bool,
-                                               LoopVectorize: bool,
-                                               PrepareForThinLTO: bool,
-                                               PGOGenPath: *const c_char,
-                                               PGOUsePath: *const c_char);
-    pub fn LLVMRustAddLibraryInfo(PM: PassManagerRef,
-                                  M: ModuleRef,
-                                  DisableSimplifyLibCalls: bool);
-    pub fn LLVMRustRunFunctionPassManager(PM: PassManagerRef, M: ModuleRef);
-    pub fn LLVMRustWriteOutputFile(T: TargetMachineRef,
-                                   PM: PassManagerRef,
-                                   M: ModuleRef,
-                                   Output: *const c_char,
-                                   FileType: FileType)
-                                   -> LLVMRustResult;
-    pub fn LLVMRustPrintModule(PM: PassManagerRef,
-                               M: ModuleRef,
-                               Output: *const c_char,
-                               Demangle: extern fn(*const c_char,
-                                                   size_t,
-                                                   *mut c_char,
-                                                   size_t) -> size_t);
-    pub fn LLVMRustSetLLVMOptions(Argc: c_int, Argv: *const *const c_char);
-    pub fn LLVMRustPrintPasses();
-    pub fn LLVMRustSetNormalizedTarget(M: ModuleRef, triple: *const c_char);
-    pub fn LLVMRustAddAlwaysInlinePass(P: PassManagerBuilderRef, AddLifetimes: bool);
-    pub fn LLVMRustRunRestrictionPass(M: ModuleRef, syms: *const *const c_char, len: size_t);
-    pub fn LLVMRustMarkAllFunctionsNounwind(M: ModuleRef);
-
-    pub fn LLVMRustOpenArchive(path: *const c_char) -> ArchiveRef;
-    pub fn LLVMRustArchiveIteratorNew(AR: ArchiveRef) -> ArchiveIteratorRef;
-    pub fn LLVMRustArchiveIteratorNext(AIR: ArchiveIteratorRef) -> ArchiveChildRef;
-    pub fn LLVMRustArchiveChildName(ACR: ArchiveChildRef, size: *mut size_t) -> *const c_char;
-    pub fn LLVMRustArchiveChildData(ACR: ArchiveChildRef, size: *mut size_t) -> *const c_char;
-    pub fn LLVMRustArchiveChildFree(ACR: ArchiveChildRef);
-    pub fn LLVMRustArchiveIteratorFree(AIR: ArchiveIteratorRef);
-    pub fn LLVMRustDestroyArchive(AR: ArchiveRef);
-
-    pub fn LLVMRustGetSectionName(SI: SectionIteratorRef, data: *mut *const c_char) -> size_t;
-
-    pub fn LLVMRustWriteTwineToString(T: TwineRef, s: RustStringRef);
-
-    pub fn LLVMContextSetDiagnosticHandler(C: ContextRef,
-                                           Handler: DiagnosticHandler,
-                                           DiagnosticContext: *mut c_void);
-
-    pub fn LLVMRustUnpackOptimizationDiagnostic(DI: DiagnosticInfoRef,
-                                                pass_name_out: RustStringRef,
-                                                function_out: *mut ValueRef,
-                                                loc_line_out: *mut c_uint,
-                                                loc_column_out: *mut c_uint,
-                                                loc_filename_out: RustStringRef,
-                                                message_out: RustStringRef);
-    pub fn LLVMRustUnpackInlineAsmDiagnostic(DI: DiagnosticInfoRef,
-                                             cookie_out: *mut c_uint,
-                                             message_out: *mut TwineRef,
-                                             instruction_out: *mut ValueRef);
-
-    pub fn LLVMRustWriteDiagnosticInfoToString(DI: DiagnosticInfoRef, s: RustStringRef);
-    pub fn LLVMRustGetDiagInfoKind(DI: DiagnosticInfoRef) -> DiagnosticKind;
-
-    pub fn LLVMRustSetInlineAsmDiagnosticHandler(C: ContextRef,
-                                                 H: InlineAsmDiagHandler,
-                                                 CX: *mut c_void);
-
-    pub fn LLVMRustWriteSMDiagnosticToString(d: SMDiagnosticRef, s: RustStringRef);
-
-    pub fn LLVMRustWriteArchive(Dst: *const c_char,
-                                NumMembers: size_t,
-                                Members: *const RustArchiveMemberRef,
-                                WriteSymbtab: bool,
-                                Kind: ArchiveKind)
-                                -> LLVMRustResult;
-    pub fn LLVMRustArchiveMemberNew(Filename: *const c_char,
-                                    Name: *const c_char,
-                                    Child: ArchiveChildRef)
-                                    -> RustArchiveMemberRef;
-    pub fn LLVMRustArchiveMemberFree(Member: RustArchiveMemberRef);
-
-    pub fn LLVMRustSetDataLayoutFromTargetMachine(M: ModuleRef, TM: TargetMachineRef);
-
-    pub fn LLVMRustBuildOperandBundleDef(Name: *const c_char,
-                                         Inputs: *const ValueRef,
-                                         NumInputs: c_uint)
-                                         -> OperandBundleDefRef;
-    pub fn LLVMRustFreeOperandBundleDef(Bundle: OperandBundleDefRef);
-
-    pub fn LLVMRustPositionBuilderAtStart(B: BuilderRef, BB: BasicBlockRef);
-
-    pub fn LLVMRustSetComdat(M: ModuleRef, V: ValueRef, Name: *const c_char);
-    pub fn LLVMRustUnsetComdat(V: ValueRef);
-    pub fn LLVMRustSetModulePIELevel(M: ModuleRef);
-    pub fn LLVMRustModuleBufferCreate(M: ModuleRef) -> *mut ModuleBuffer;
-    pub fn LLVMRustModuleBufferPtr(p: *const ModuleBuffer) -> *const u8;
-    pub fn LLVMRustModuleBufferLen(p: *const ModuleBuffer) -> usize;
-    pub fn LLVMRustModuleBufferFree(p: *mut ModuleBuffer);
-    pub fn LLVMRustModuleCost(M: ModuleRef) -> u64;
-
-    pub fn LLVMRustThinLTOAvailable() -> bool;
-    pub fn LLVMRustPGOAvailable() -> bool;
-    pub fn LLVMRustWriteThinBitcodeToFile(PMR: PassManagerRef,
-                                          M: ModuleRef,
-                                          BC: *const c_char) -> bool;
-    pub fn LLVMRustThinLTOBufferCreate(M: ModuleRef) -> *mut ThinLTOBuffer;
-    pub fn LLVMRustThinLTOBufferFree(M: *mut ThinLTOBuffer);
-    pub fn LLVMRustThinLTOBufferPtr(M: *const ThinLTOBuffer) -> *const c_char;
-    pub fn LLVMRustThinLTOBufferLen(M: *const ThinLTOBuffer) -> size_t;
-    pub fn LLVMRustCreateThinLTOData(
-        Modules: *const ThinLTOModule,
-        NumModules: c_uint,
-        PreservedSymbols: *const *const c_char,
-        PreservedSymbolsLen: c_uint,
-    ) -> *mut ThinLTOData;
-    pub fn LLVMRustPrepareThinLTORename(
-        Data: *const ThinLTOData,
-        Module: ModuleRef,
-    ) -> bool;
-    pub fn LLVMRustPrepareThinLTOResolveWeak(
-        Data: *const ThinLTOData,
-        Module: ModuleRef,
-    ) -> bool;
-    pub fn LLVMRustPrepareThinLTOInternalize(
-        Data: *const ThinLTOData,
-        Module: ModuleRef,
-    ) -> bool;
-    pub fn LLVMRustPrepareThinLTOImport(
-        Data: *const ThinLTOData,
-        Module: ModuleRef,
-    ) -> bool;
-    pub fn LLVMRustFreeThinLTOData(Data: *mut ThinLTOData);
-    pub fn LLVMRustParseBitcodeForThinLTO(
-        Context: ContextRef,
-        Data: *const u8,
-        len: usize,
-        Identifier: *const c_char,
-    ) -> ModuleRef;
-    pub fn LLVMGetModuleIdentifier(M: ModuleRef, size: *mut usize) -> *const c_char;
-    pub fn LLVMRustThinLTOGetDICompileUnit(M: ModuleRef,
-                                           CU1: *mut *mut c_void,
-                                           CU2: *mut *mut c_void);
-    pub fn LLVMRustThinLTOPatchDICompileUnit(M: ModuleRef, CU: *mut c_void);
-
-    pub fn LLVMRustLinkerNew(M: ModuleRef) -> LinkerRef;
-    pub fn LLVMRustLinkerAdd(linker: LinkerRef,
-                             bytecode: *const c_char,
-                             bytecode_len: usize) -> bool;
-    pub fn LLVMRustLinkerFree(linker: LinkerRef);
-}
diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs
index 91f9b4ac03b..05f6b5b5fbd 100644
--- a/src/librustc_llvm/lib.rs
+++ b/src/librustc_llvm/lib.rs
@@ -8,290 +8,20 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![allow(non_upper_case_globals)]
-#![allow(non_camel_case_types)]
-#![allow(non_snake_case)]
-#![allow(dead_code)]
+#![feature(static_nobundle)]
 
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
        html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
        html_root_url = "https://doc.rust-lang.org/nightly/")]
 
-#![feature(box_syntax)]
-#![feature(concat_idents)]
-#![feature(libc)]
-#![feature(link_args)]
-#![feature(static_nobundle)]
-
 // See librustc_cratesio_shim/Cargo.toml for a comment explaining this.
 #[allow(unused_extern_crates)]
 extern crate rustc_cratesio_shim;
 
-#[macro_use]
-extern crate bitflags;
-extern crate libc;
-
-pub use self::IntPredicate::*;
-pub use self::RealPredicate::*;
-pub use self::TypeKind::*;
-pub use self::AtomicRmwBinOp::*;
-pub use self::MetadataType::*;
-pub use self::CodeGenOptSize::*;
-pub use self::CallConv::*;
-pub use self::Linkage::*;
-
-use std::str::FromStr;
-use std::slice;
-use std::ffi::{CString, CStr};
-use std::cell::RefCell;
-use libc::{c_uint, c_char, size_t};
-
-pub mod archive_ro;
-pub mod diagnostic;
-mod ffi;
-
-pub use ffi::*;
-
-impl LLVMRustResult {
-    pub fn into_result(self) -> Result<(), ()> {
-        match self {
-            LLVMRustResult::Success => Ok(()),
-            LLVMRustResult::Failure => Err(()),
-        }
-    }
-}
-
-pub fn AddFunctionAttrStringValue(llfn: ValueRef,
-                                  idx: AttributePlace,
-                                  attr: &CStr,
-                                  value: &CStr) {
-    unsafe {
-        LLVMRustAddFunctionAttrStringValue(llfn,
-                                           idx.as_uint(),
-                                           attr.as_ptr(),
-                                           value.as_ptr())
-    }
-}
-
-#[derive(Copy, Clone)]
-pub enum AttributePlace {
-    ReturnValue,
-    Argument(u32),
-    Function,
-}
-
-impl AttributePlace {
-    pub fn as_uint(self) -> c_uint {
-        match self {
-            AttributePlace::ReturnValue => 0,
-            AttributePlace::Argument(i) => 1 + i,
-            AttributePlace::Function => !0,
-        }
-    }
-}
-
-#[derive(Copy, Clone, PartialEq)]
-#[repr(C)]
-pub enum CodeGenOptSize {
-    CodeGenOptSizeNone = 0,
-    CodeGenOptSizeDefault = 1,
-    CodeGenOptSizeAggressive = 2,
-}
-
-impl FromStr for ArchiveKind {
-    type Err = ();
-
-    fn from_str(s: &str) -> Result<Self, Self::Err> {
-        match s {
-            "gnu" => Ok(ArchiveKind::K_GNU),
-            "bsd" => Ok(ArchiveKind::K_BSD),
-            "coff" => Ok(ArchiveKind::K_COFF),
-            _ => Err(()),
-        }
-    }
-}
-
-#[allow(missing_copy_implementations)]
-pub enum RustString_opaque {}
-type RustStringRef = *mut RustString_opaque;
-type RustStringRepr = *mut RefCell<Vec<u8>>;
-
-/// Appending to a Rust string -- used by RawRustStringOstream.
-#[no_mangle]
-pub unsafe extern "C" fn LLVMRustStringWriteImpl(sr: RustStringRef,
-                                                 ptr: *const c_char,
-                                                 size: size_t) {
-    let slice = slice::from_raw_parts(ptr as *const u8, size as usize);
-
-    let sr = sr as RustStringRepr;
-    (*sr).borrow_mut().extend_from_slice(slice);
-}
-
-pub fn SetInstructionCallConv(instr: ValueRef, cc: CallConv) {
-    unsafe {
-        LLVMSetInstructionCallConv(instr, cc as c_uint);
-    }
-}
-pub fn SetFunctionCallConv(fn_: ValueRef, cc: CallConv) {
-    unsafe {
-        LLVMSetFunctionCallConv(fn_, cc as c_uint);
-    }
-}
-
-// Externally visible symbols that might appear in multiple codegen units need to appear in
-// their own comdat section so that the duplicates can be discarded at link time. This can for
-// example happen for generics when using multiple codegen units. This function simply uses the
-// value's name as the comdat value to make sure that it is in a 1-to-1 relationship to the
-// function.
-// For more details on COMDAT sections see e.g. http://www.airs.com/blog/archives/52
-pub fn SetUniqueComdat(llmod: ModuleRef, val: ValueRef) {
-    unsafe {
-        LLVMRustSetComdat(llmod, val, LLVMGetValueName(val));
-    }
-}
-
-pub fn UnsetComdat(val: ValueRef) {
-    unsafe {
-        LLVMRustUnsetComdat(val);
-    }
-}
-
-pub fn SetUnnamedAddr(global: ValueRef, unnamed: bool) {
-    unsafe {
-        LLVMSetUnnamedAddr(global, unnamed as Bool);
-    }
-}
-
-pub fn set_thread_local(global: ValueRef, is_thread_local: bool) {
-    unsafe {
-        LLVMSetThreadLocal(global, is_thread_local as Bool);
-    }
-}
-pub fn set_thread_local_mode(global: ValueRef, mode: ThreadLocalMode) {
-    unsafe {
-        LLVMSetThreadLocalMode(global, mode);
-    }
-}
-
-impl Attribute {
-    pub fn apply_llfn(&self, idx: AttributePlace, llfn: ValueRef) {
-        unsafe { LLVMRustAddFunctionAttribute(llfn, idx.as_uint(), *self) }
-    }
-
-    pub fn apply_callsite(&self, idx: AttributePlace, callsite: ValueRef) {
-        unsafe { LLVMRustAddCallSiteAttribute(callsite, idx.as_uint(), *self) }
-    }
-
-    pub fn unapply_llfn(&self, idx: AttributePlace, llfn: ValueRef) {
-        unsafe { LLVMRustRemoveFunctionAttributes(llfn, idx.as_uint(), *self) }
-    }
-
-    pub fn toggle_llfn(&self, idx: AttributePlace, llfn: ValueRef, set: bool) {
-        if set {
-            self.apply_llfn(idx, llfn);
-        } else {
-            self.unapply_llfn(idx, llfn);
-        }
-    }
-}
-
-// Memory-managed interface to target data.
-
-struct TargetData {
-    lltd: TargetDataRef,
-}
-
-impl Drop for TargetData {
-    fn drop(&mut self) {
-        unsafe {
-            LLVMDisposeTargetData(self.lltd);
-        }
-    }
-}
-
-fn mk_target_data(string_rep: &str) -> TargetData {
-    let string_rep = CString::new(string_rep).unwrap();
-    TargetData { lltd: unsafe { LLVMCreateTargetData(string_rep.as_ptr()) } }
-}
-
-// Memory-managed interface to object files.
-
-pub struct ObjectFile {
-    pub llof: ObjectFileRef,
-}
-
-unsafe impl Send for ObjectFile {}
-
-impl ObjectFile {
-    // This will take ownership of llmb
-    pub fn new(llmb: MemoryBufferRef) -> Option<ObjectFile> {
-        unsafe {
-            let llof = LLVMCreateObjectFile(llmb);
-            if llof as isize == 0 {
-                // LLVMCreateObjectFile took ownership of llmb
-                return None;
-            }
-
-            Some(ObjectFile { llof: llof })
-        }
-    }
-}
-
-impl Drop for ObjectFile {
-    fn drop(&mut self) {
-        unsafe {
-            LLVMDisposeObjectFile(self.llof);
-        }
-    }
-}
-
-// Memory-managed interface to section iterators.
-
-pub struct SectionIter {
-    pub llsi: SectionIteratorRef,
-}
-
-impl Drop for SectionIter {
-    fn drop(&mut self) {
-        unsafe {
-            LLVMDisposeSectionIterator(self.llsi);
-        }
-    }
-}
-
-pub fn mk_section_iter(llof: ObjectFileRef) -> SectionIter {
-    unsafe { SectionIter { llsi: LLVMGetSections(llof) } }
-}
-
-/// Safe wrapper around `LLVMGetParam`, because segfaults are no fun.
-pub fn get_param(llfn: ValueRef, index: c_uint) -> ValueRef {
-    unsafe {
-        assert!(index < LLVMCountParams(llfn),
-            "out of bounds argument access: {} out of {} arguments", index, LLVMCountParams(llfn));
-        LLVMGetParam(llfn, index)
-    }
-}
-
-fn get_params(llfn: ValueRef) -> Vec<ValueRef> {
-    unsafe {
-        let num_params = LLVMCountParams(llfn);
-
-        (0..num_params).map(|idx| LLVMGetParam(llfn, idx)).collect()
-    }
-}
-
-pub fn build_string<F>(f: F) -> Option<String>
-    where F: FnOnce(RustStringRef)
-{
-    let mut buf = RefCell::new(Vec::new());
-    f(&mut buf as RustStringRepr as RustStringRef);
-    String::from_utf8(buf.into_inner()).ok()
-}
-
-pub unsafe fn twine_to_string(tr: TwineRef) -> String {
-    build_string(|s| LLVMRustWriteTwineToString(tr, s)).expect("got a non-UTF8 Twine from LLVM")
-}
+// NOTE: This crate only exists to allow linking on mingw targets.
 
+/// Initialize targets enabled by the build script via `cfg(llvm_component = "...")`.
+/// NB: this function can't be moved to `rustc_codegen_llvm` because of the `cfg`s.
 pub fn initialize_available_targets() {
     macro_rules! init_target(
         ($cfg:meta, $($method:ident),*) => { {
@@ -383,43 +113,3 @@ pub fn initialize_available_targets() {
                  LLVMInitializeWebAssemblyTargetMC,
                  LLVMInitializeWebAssemblyAsmPrinter);
 }
-
-pub fn last_error() -> Option<String> {
-    unsafe {
-        let cstr = LLVMRustGetLastError();
-        if cstr.is_null() {
-            None
-        } else {
-            let err = CStr::from_ptr(cstr).to_bytes();
-            let err = String::from_utf8_lossy(err).to_string();
-            libc::free(cstr as *mut _);
-            Some(err)
-        }
-    }
-}
-
-pub struct OperandBundleDef {
-    inner: OperandBundleDefRef,
-}
-
-impl OperandBundleDef {
-    pub fn new(name: &str, vals: &[ValueRef]) -> OperandBundleDef {
-        let name = CString::new(name).unwrap();
-        let def = unsafe {
-            LLVMRustBuildOperandBundleDef(name.as_ptr(), vals.as_ptr(), vals.len() as c_uint)
-        };
-        OperandBundleDef { inner: def }
-    }
-
-    pub fn raw(&self) -> OperandBundleDefRef {
-        self.inner
-    }
-}
-
-impl Drop for OperandBundleDef {
-    fn drop(&mut self) {
-        unsafe {
-            LLVMRustFreeOperandBundleDef(self.inner);
-        }
-    }
-}
diff --git a/src/librustc_target/lib.rs b/src/librustc_target/lib.rs
index 8f491157439..a50a5a2d1cb 100644
--- a/src/librustc_target/lib.rs
+++ b/src/librustc_target/lib.rs
@@ -15,11 +15,7 @@
 //! is really just odds-and-ends relating to code gen and linking.
 //! This crate mostly exists to make rustc smaller, so we might put
 //! more 'stuff' here in the future.  It does not have a dependency on
-//! rustc_llvm.
-//!
-//! FIXME: Split this into two crates: one that has deps on syntax, and
-//! one that doesn't; the one that doesn't might get decent parallel
-//! build speedups.
+//! LLVM.
 
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
diff --git a/src/rustllvm/ArchiveWrapper.cpp b/src/rustllvm/ArchiveWrapper.cpp
index 93157cd6819..49a4962858c 100644
--- a/src/rustllvm/ArchiveWrapper.cpp
+++ b/src/rustllvm/ArchiveWrapper.cpp
@@ -148,7 +148,7 @@ LLVMRustArchiveChildName(LLVMRustArchiveChildConstRef Child, size_t *Size) {
 #if LLVM_VERSION_GE(4, 0)
   Expected<StringRef> NameOrErr = Child->getName();
   if (!NameOrErr) {
-    // rustc_llvm currently doesn't use this error string, but it might be
+    // rustc_codegen_llvm currently doesn't use this error string, but it might be
     // useful in the future, and in the mean time this tells LLVM that the
     // error was not ignored and that it shouldn't abort the process.
     LLVMRustSetLastError(toString(NameOrErr.takeError()).c_str());
diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp
index 85fbc4bf378..3f5550bf95f 100644
--- a/src/rustllvm/PassWrapper.cpp
+++ b/src/rustllvm/PassWrapper.cpp
@@ -828,23 +828,6 @@ LLVMRustPGOAvailable() {
 // and various online resources about ThinLTO to make heads or tails of all
 // this.
 
-extern "C" bool
-LLVMRustWriteThinBitcodeToFile(LLVMPassManagerRef PMR,
-                               LLVMModuleRef M,
-                               const char *BcFile) {
-  llvm::legacy::PassManager *PM = unwrap<llvm::legacy::PassManager>(PMR);
-  std::error_code EC;
-  llvm::raw_fd_ostream bc(BcFile, EC, llvm::sys::fs::F_None);
-  if (EC) {
-    LLVMRustSetLastError(EC.message().c_str());
-    return false;
-  }
-  PM->add(createWriteThinLTOBitcodePass(bc));
-  PM->run(*unwrap(M));
-  delete PM;
-  return true;
-}
-
 // This is a shared data structure which *must* be threadsafe to share
 // read-only amongst threads. This also corresponds basically to the arguments
 // of the `ProcessThinLTOModule` function in the LLVM source.
@@ -1259,13 +1242,6 @@ LLVMRustThinLTOPatchDICompileUnit(LLVMModuleRef Mod, DICompileUnit *Unit) {
 
 #else
 
-extern "C" bool
-LLVMRustWriteThinBitcodeToFile(LLVMPassManagerRef PMR,
-                               LLVMModuleRef M,
-                               const char *BcFile) {
-  report_fatal_error("ThinLTO not available");
-}
-
 struct LLVMRustThinLTOData {
 };
 
diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp
index d82410618d0..f2b5297285c 100644
--- a/src/rustllvm/RustWrapper.cpp
+++ b/src/rustllvm/RustWrapper.cpp
@@ -751,15 +751,6 @@ LLVMRustDIBuilderCreateArrayType(LLVMRustDIBuilderRef Builder, uint64_t Size,
 }
 
 extern "C" LLVMMetadataRef
-LLVMRustDIBuilderCreateVectorType(LLVMRustDIBuilderRef Builder, uint64_t Size,
-                                  uint32_t AlignInBits, LLVMMetadataRef Ty,
-                                  LLVMMetadataRef Subscripts) {
-  return wrap(
-      Builder->createVectorType(Size, AlignInBits, unwrapDI<DIType>(Ty),
-                                DINodeArray(unwrapDI<MDTuple>(Subscripts))));
-}
-
-extern "C" LLVMMetadataRef
 LLVMRustDIBuilderGetOrCreateSubrange(LLVMRustDIBuilderRef Builder, int64_t Lo,
                                      int64_t Count) {
   return wrap(Builder->getOrCreateSubrange(Lo, Count));