about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEduard-Mihai Burtescu <edy.burt@gmail.com>2017-09-20 23:07:47 +0300
committerEduard-Mihai Burtescu <edy.burt@gmail.com>2017-11-19 02:14:32 +0200
commit3fd6b00082c16369119c2f67981ceb8b47bc71a2 (patch)
tree3e8f5a9d6084c36aea2880e25b59c5a84488dafb
parent1477119344e750d8cd6a5104ec6ea28cec11e574 (diff)
rustc_trans: query LLVM types from a layout instead of a Ty.
-rw-r--r--src/librustc_trans/abi.rs7
-rw-r--r--src/librustc_trans/asm.rs3
-rw-r--r--src/librustc_trans/base.rs12
-rw-r--r--src/librustc_trans/callee.rs5
-rw-r--r--src/librustc_trans/common.rs3
-rw-r--r--src/librustc_trans/consts.rs11
-rw-r--r--src/librustc_trans/context.rs4
-rw-r--r--src/librustc_trans/intrinsic.rs5
-rw-r--r--src/librustc_trans/mir/block.rs38
-rw-r--r--src/librustc_trans/mir/constant.rs21
-rw-r--r--src/librustc_trans/mir/lvalue.rs19
-rw-r--r--src/librustc_trans/mir/mod.rs4
-rw-r--r--src/librustc_trans/mir/operand.rs8
-rw-r--r--src/librustc_trans/mir/rvalue.rs10
-rw-r--r--src/librustc_trans/trans_item.rs4
-rw-r--r--src/librustc_trans/type_of.rs76
16 files changed, 114 insertions, 116 deletions
diff --git a/src/librustc_trans/abi.rs b/src/librustc_trans/abi.rs
index 0b09bca7b68..bd9a460846b 100644
--- a/src/librustc_trans/abi.rs
+++ b/src/librustc_trans/abi.rs
@@ -32,6 +32,7 @@ use cabi_nvptx64;
 use cabi_hexagon;
 use mir::lvalue::LvalueRef;
 use type_::Type;
+use type_of::LayoutLlvmExt;
 
 use rustc::hir;
 use rustc::ty::{self, Ty};
@@ -506,7 +507,7 @@ impl<'a, 'tcx> ArgType<'tcx> {
     /// Get the LLVM type for an lvalue of the original Rust type of
     /// this argument/return, i.e. the result of `type_of::type_of`.
     pub fn memory_ty(&self, ccx: &CrateContext<'a, 'tcx>) -> Type {
-        ccx.llvm_type_of(self.layout.ty)
+        self.layout.llvm_type(ccx)
     }
 
     /// Store a direct/indirect value described by this ArgType into a
@@ -934,7 +935,7 @@ impl<'a, 'tcx> FnType<'tcx> {
         } else if let Some(cast) = self.ret.cast {
             cast.llvm_type(ccx)
         } else {
-            ccx.immediate_llvm_type_of(self.ret.layout.ty)
+            self.ret.layout.immediate_llvm_type(ccx)
         };
 
         {
@@ -952,7 +953,7 @@ impl<'a, 'tcx> FnType<'tcx> {
                 } else if let Some(cast) = arg.cast {
                     cast.llvm_type(ccx)
                 } else {
-                    ccx.immediate_llvm_type_of(arg.layout.ty)
+                    arg.layout.immediate_llvm_type(ccx)
                 };
 
                 llargument_tys.push(llarg_ty);
diff --git a/src/librustc_trans/asm.rs b/src/librustc_trans/asm.rs
index 44bdc75f846..1959fd13ccb 100644
--- a/src/librustc_trans/asm.rs
+++ b/src/librustc_trans/asm.rs
@@ -13,6 +13,7 @@
 use llvm::{self, ValueRef};
 use common::*;
 use type_::Type;
+use type_of::LayoutLlvmExt;
 use builder::Builder;
 
 use rustc::hir;
@@ -44,7 +45,7 @@ pub fn trans_inline_asm<'a, 'tcx>(
         if out.is_indirect {
             indirect_outputs.push(lvalue.load(bcx).immediate());
         } else {
-            output_types.push(bcx.ccx.llvm_type_of(lvalue.layout.ty));
+            output_types.push(lvalue.layout.llvm_type(bcx.ccx));
         }
     }
     if !indirect_outputs.is_empty() {
diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs
index 036f1dfbcfd..545e986d7d1 100644
--- a/src/librustc_trans/base.rs
+++ b/src/librustc_trans/base.rs
@@ -40,7 +40,7 @@ use rustc::middle::lang_items::StartFnLangItem;
 use rustc::middle::trans::{Linkage, Visibility, Stats};
 use rustc::middle::cstore::{EncodedMetadata, EncodedMetadataHashes};
 use rustc::ty::{self, Ty, TyCtxt};
-use rustc::ty::layout::{Align, FullLayout};
+use rustc::ty::layout::{self, Align, FullLayout, LayoutOf};
 use rustc::ty::maps::Providers;
 use rustc::dep_graph::{DepNode, DepKind, DepConstructor};
 use rustc::middle::cstore::{self, LinkMeta, LinkagePreference};
@@ -68,7 +68,7 @@ use symbol_names_test;
 use time_graph;
 use trans_item::{TransItem, BaseTransItemExt, TransItemExt, DefPathBasedNames};
 use type_::Type;
-use type_of;
+use type_of::{self, LayoutLlvmExt};
 use rustc::util::nodemap::{NodeSet, FxHashMap, FxHashSet, DefIdSet};
 use CrateInfo;
 
@@ -228,13 +228,13 @@ pub fn unsize_thin_ptr<'a, 'tcx>(
         (&ty::TyRawPtr(ty::TypeAndMut { ty: a, .. }),
          &ty::TyRawPtr(ty::TypeAndMut { ty: b, .. })) => {
             assert!(bcx.ccx.shared().type_is_sized(a));
-            let ptr_ty = bcx.ccx.llvm_type_of(b).ptr_to();
+            let ptr_ty = bcx.ccx.layout_of(b).llvm_type(bcx.ccx).ptr_to();
             (bcx.pointercast(src, ptr_ty), unsized_info(bcx.ccx, a, b, None))
         }
         (&ty::TyAdt(def_a, _), &ty::TyAdt(def_b, _)) if def_a.is_box() && def_b.is_box() => {
             let (a, b) = (src_ty.boxed_ty(), dst_ty.boxed_ty());
             assert!(bcx.ccx.shared().type_is_sized(a));
-            let ptr_ty = bcx.ccx.llvm_type_of(b).ptr_to();
+            let ptr_ty = bcx.ccx.layout_of(b).llvm_type(bcx.ccx).ptr_to();
             (bcx.pointercast(src, ptr_ty), unsized_info(bcx.ccx, a, b, None))
         }
         _ => bug!("unsize_thin_ptr: called on bad types"),
@@ -371,8 +371,8 @@ pub fn from_immediate(bcx: &Builder, val: ValueRef) -> ValueRef {
     }
 }
 
-pub fn to_immediate(bcx: &Builder, val: ValueRef, ty: Ty) -> ValueRef {
-    if ty.is_bool() {
+pub fn to_immediate(bcx: &Builder, val: ValueRef, layout: layout::FullLayout) -> ValueRef {
+    if let layout::Abi::Scalar(layout::Int(layout::I1, _)) = layout.abi {
         bcx.trunc(val, Type::i1(bcx.ccx))
     } else {
         val
diff --git a/src/librustc_trans/callee.rs b/src/librustc_trans/callee.rs
index bb271a574a5..4afeac2e8f5 100644
--- a/src/librustc_trans/callee.rs
+++ b/src/librustc_trans/callee.rs
@@ -20,8 +20,11 @@ use consts;
 use declare;
 use llvm::{self, ValueRef};
 use monomorphize::Instance;
+use type_of::LayoutLlvmExt;
+
 use rustc::hir::def_id::DefId;
 use rustc::ty::{self, TypeFoldable};
+use rustc::ty::layout::LayoutOf;
 use rustc::traits;
 use rustc::ty::subst::Substs;
 use rustc_back::PanicStrategy;
@@ -55,7 +58,7 @@ pub fn get_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
 
     // Create a fn pointer with the substituted signature.
     let fn_ptr_ty = tcx.mk_fn_ptr(common::ty_fn_sig(ccx, fn_ty));
-    let llptrty = ccx.llvm_type_of(fn_ptr_ty);
+    let llptrty = ccx.layout_of(fn_ptr_ty).llvm_type(ccx);
 
     let llfn = if let Some(llfn) = declare::get_declared_value(ccx, &sym) {
         // This is subtle and surprising, but sometimes we have to bitcast
diff --git a/src/librustc_trans/common.rs b/src/librustc_trans/common.rs
index 55f02ed5f91..ed8f6583406 100644
--- a/src/librustc_trans/common.rs
+++ b/src/librustc_trans/common.rs
@@ -24,6 +24,7 @@ use builder::Builder;
 use consts;
 use declare;
 use type_::Type;
+use type_of::LayoutLlvmExt;
 use value::Value;
 use rustc::traits;
 use rustc::ty::{self, Ty, TyCtxt};
@@ -254,7 +255,7 @@ pub fn C_cstr(cx: &CrateContext, s: InternedString, null_terminated: bool) -> Va
 pub fn C_str_slice(cx: &CrateContext, s: InternedString) -> ValueRef {
     let len = s.len();
     let cs = consts::ptrcast(C_cstr(cx, s, false),
-        cx.llvm_type_of(cx.tcx().mk_str()).ptr_to());
+        cx.layout_of(cx.tcx().mk_str()).llvm_type(cx).ptr_to());
     let empty = C_array(Type::i8(cx), &[]);
     assert_eq!(abi::FAT_PTR_ADDR, 0);
     assert_eq!(abi::FAT_PTR_EXTRA, 1);
diff --git a/src/librustc_trans/consts.rs b/src/librustc_trans/consts.rs
index 339405ab1ba..cfca3b57cb9 100644
--- a/src/librustc_trans/consts.rs
+++ b/src/librustc_trans/consts.rs
@@ -21,8 +21,9 @@ use common::{self, CrateContext, val_ty};
 use declare;
 use monomorphize::Instance;
 use type_::Type;
+use type_of::LayoutLlvmExt;
 use rustc::ty;
-use rustc::ty::layout::Align;
+use rustc::ty::layout::{Align, LayoutOf};
 
 use rustc::hir;
 
@@ -112,7 +113,7 @@ pub fn get_static(ccx: &CrateContext, def_id: DefId) -> ValueRef {
     let ty = common::instance_ty(ccx.tcx(), &instance);
     let g = if let Some(id) = ccx.tcx().hir.as_local_node_id(def_id) {
 
-        let llty = ccx.llvm_type_of(ty);
+        let llty = ccx.layout_of(ty).llvm_type(ccx);
         let (g, attrs) = match ccx.tcx().hir.get(id) {
             hir_map::NodeItem(&hir::Item {
                 ref attrs, span, node: hir::ItemStatic(..), ..
@@ -157,7 +158,7 @@ pub fn get_static(ccx: &CrateContext, def_id: DefId) -> ValueRef {
                         }
                     };
                     let llty2 = match ty.sty {
-                        ty::TyRawPtr(ref mt) => ccx.llvm_type_of(mt.ty),
+                        ty::TyRawPtr(ref mt) => ccx.layout_of(mt.ty).llvm_type(ccx),
                         _ => {
                             ccx.sess().span_fatal(span, "must have type `*const T` or `*mut T`");
                         }
@@ -206,7 +207,7 @@ pub fn get_static(ccx: &CrateContext, def_id: DefId) -> ValueRef {
 
         // FIXME(nagisa): perhaps the map of externs could be offloaded to llvm somehow?
         // FIXME(nagisa): investigate whether it can be changed into define_global
-        let g = declare::declare_global(ccx, &sym, ccx.llvm_type_of(ty));
+        let g = declare::declare_global(ccx, &sym, ccx.layout_of(ty).llvm_type(ccx));
         // Thread-local statics in some other crate need to *always* be linked
         // against in a thread-local fashion, so we need to be sure to apply the
         // thread-local attribute locally if it was present remotely. If we
@@ -266,7 +267,7 @@ pub fn trans_static<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
 
         let instance = Instance::mono(ccx.tcx(), def_id);
         let ty = common::instance_ty(ccx.tcx(), &instance);
-        let llty = ccx.llvm_type_of(ty);
+        let llty = ccx.layout_of(ty).llvm_type(ccx);
         let g = if val_llty == llty {
             g
         } else {
diff --git a/src/librustc_trans/context.rs b/src/librustc_trans/context.rs
index 647cc54effe..555acaad505 100644
--- a/src/librustc_trans/context.rs
+++ b/src/librustc_trans/context.rs
@@ -24,6 +24,8 @@ use monomorphize::Instance;
 
 use partitioning::CodegenUnit;
 use type_::Type;
+use type_of::LayoutLlvmExt;
+
 use rustc_data_structures::base_n;
 use rustc::middle::trans::Stats;
 use rustc_data_structures::stable_hasher::StableHashingContextProvider;
@@ -397,7 +399,7 @@ impl<'a, 'tcx> LocalCrateContext<'a, 'tcx> {
                     let mut str_slice_ty = Type::named_struct(&dummy_ccx, "str_slice");
                     str_slice_ty.set_struct_body(&[
                         Type::array(&Type::i8(&dummy_ccx), 0),
-                        dummy_ccx.llvm_type_of(shared.tcx.mk_str()).ptr_to(),
+                        dummy_ccx.layout_of(shared.tcx.mk_str()).llvm_type(&dummy_ccx).ptr_to(),
                         Type::array(&Type::i8(&dummy_ccx), 0),
                         Type::isize(&dummy_ccx),
                         Type::array(&Type::i8(&dummy_ccx), 0)
diff --git a/src/librustc_trans/intrinsic.rs b/src/librustc_trans/intrinsic.rs
index 1cdd192bfed..45d2f7c69e9 100644
--- a/src/librustc_trans/intrinsic.rs
+++ b/src/librustc_trans/intrinsic.rs
@@ -21,6 +21,7 @@ use common::*;
 use declare;
 use glue;
 use type_::Type;
+use type_of::LayoutLlvmExt;
 use rustc::ty::{self, Ty};
 use rustc::ty::layout::{HasDataLayout, LayoutOf};
 use rustc::hir;
@@ -104,7 +105,7 @@ pub fn trans_intrinsic_call<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
     let ret_ty = sig.output();
     let name = &*tcx.item_name(def_id);
 
-    let llret_ty = ccx.llvm_type_of(ret_ty);
+    let llret_ty = ccx.layout_of(ret_ty).llvm_type(ccx);
     let result = LvalueRef::new_sized(llresult, fn_ty.ret.layout, Alignment::AbiAligned);
 
     let simple = get_simple_intrinsic(ccx, name);
@@ -243,7 +244,7 @@ pub fn trans_intrinsic_call<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
             unsafe {
                 llvm::LLVMSetAlignment(load, ccx.align_of(tp_ty).abi() as u32);
             }
-            to_immediate(bcx, load, tp_ty)
+            to_immediate(bcx, load, ccx.layout_of(tp_ty))
         },
         "volatile_store" => {
             let tp_ty = substs.type_at(0);
diff --git a/src/librustc_trans/mir/block.rs b/src/librustc_trans/mir/block.rs
index 82d5dabc86c..401d4d52216 100644
--- a/src/librustc_trans/mir/block.rs
+++ b/src/librustc_trans/mir/block.rs
@@ -662,7 +662,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
             if arg.layout.ty == bcx.tcx().types.bool {
                 llval = bcx.load_range_assert(llval, 0, 2, llvm::False, None);
                 // We store bools as i8 so we need to truncate to i1.
-                llval = base::to_immediate(bcx, llval, arg.layout.ty);
+                llval = base::to_immediate(bcx, llval, arg.layout);
             } else if let Some(ty) = arg.cast {
                 llval = bcx.load(bcx.pointercast(llval, ty.llvm_type(bcx.ccx).ptr_to()),
                                  (align | Alignment::Packed(arg.layout.align(bcx.ccx)))
@@ -682,45 +682,37 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
                                 args: &[ArgType<'tcx>]) {
         let tuple = self.trans_operand(bcx, operand);
 
-        let arg_types = match tuple.layout.ty.sty {
-            ty::TyTuple(ref tys, _) => tys,
-            _ => span_bug!(self.mir.span,
-                           "bad final argument to \"rust-call\" fn {:?}", tuple.layout.ty)
-        };
-
         // Handle both by-ref and immediate tuples.
         match tuple.val {
             Ref(llval, align) => {
                 let tuple_ptr = LvalueRef::new_sized(llval, tuple.layout, align);
-                for n in 0..arg_types.len() {
-                    let field_ptr = tuple_ptr.project_field(bcx, n);
-                    self.trans_argument(bcx, field_ptr.load(bcx), llargs, &args[n]);
+                for i in 0..tuple.layout.fields.count() {
+                    let field_ptr = tuple_ptr.project_field(bcx, i);
+                    self.trans_argument(bcx, field_ptr.load(bcx), llargs, &args[i]);
                 }
 
             }
             Immediate(llval) => {
-                for (n, &ty) in arg_types.iter().enumerate() {
-                    let mut elem = bcx.extract_value(llval, tuple.layout.llvm_field_index(n));
-                    // Truncate bools to i1, if needed
-                    elem = base::to_immediate(bcx, elem, ty);
+                for i in 0..tuple.layout.fields.count() {
+                    let field = tuple.layout.field(bcx.ccx, i);
+                    let elem = bcx.extract_value(llval, tuple.layout.llvm_field_index(i));
                     // If the tuple is immediate, the elements are as well
                     let op = OperandRef {
-                        val: Immediate(elem),
-                        layout: bcx.ccx.layout_of(ty),
+                        val: Immediate(base::to_immediate(bcx, elem, field)),
+                        layout: field,
                     };
-                    self.trans_argument(bcx, op, llargs, &args[n]);
+                    self.trans_argument(bcx, op, llargs, &args[i]);
                 }
             }
             Pair(a, b) => {
                 let elems = [a, b];
-                for (n, &ty) in arg_types.iter().enumerate() {
-                    let elem = base::to_immediate(bcx, elems[n], ty);
+                for i in 0..tuple.layout.fields.count() {
                     // Pair is always made up of immediates
                     let op = OperandRef {
-                        val: Immediate(elem),
-                        layout: bcx.ccx.layout_of(ty),
+                        val: Immediate(elems[i]),
+                        layout: tuple.layout.field(bcx.ccx, i),
                     };
-                    self.trans_argument(bcx, op, llargs, &args[n]);
+                    self.trans_argument(bcx, op, llargs, &args[i]);
                 }
             }
         }
@@ -891,7 +883,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
                             src: &mir::Operand<'tcx>,
                             dst: LvalueRef<'tcx>) {
         let src = self.trans_operand(bcx, src);
-        let llty = bcx.ccx.llvm_type_of(src.layout.ty);
+        let llty = src.layout.llvm_type(bcx.ccx);
         let cast_ptr = bcx.pointercast(dst.llval, llty.ptr_to());
         let align = src.layout.align(bcx.ccx).min(dst.layout.align(bcx.ccx));
         src.val.store(bcx,
diff --git a/src/librustc_trans/mir/constant.rs b/src/librustc_trans/mir/constant.rs
index 8b86eca7558..94651185686 100644
--- a/src/librustc_trans/mir/constant.rs
+++ b/src/librustc_trans/mir/constant.rs
@@ -87,7 +87,7 @@ impl<'a, 'tcx> Const<'tcx> {
                          cv: &ConstVal,
                          ty: Ty<'tcx>)
                          -> Const<'tcx> {
-        let llty = ccx.llvm_type_of(ty);
+        let llty = ccx.layout_of(ty).llvm_type(ccx);
         let val = match *cv {
             ConstVal::Float(v) => {
                 let bits = match v.ty {
@@ -139,7 +139,7 @@ impl<'a, 'tcx> Const<'tcx> {
     }
 
     pub fn to_operand(&self, ccx: &CrateContext<'a, 'tcx>) -> OperandRef<'tcx> {
-        let llty = ccx.immediate_llvm_type_of(self.ty);
+        let llty = ccx.layout_of(self.ty).immediate_llvm_type(ccx);
         let llvalty = val_ty(self.llval);
 
         let val = if llty == llvalty && common::type_is_imm_pair(ccx, self.ty) {
@@ -489,7 +489,7 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
                         let llelem = if iv < len as u128 {
                             const_get_elt(base.llval, iv as u64)
                         } else {
-                            C_undef(self.ccx.llvm_type_of(projected_ty))
+                            C_undef(self.ccx.layout_of(projected_ty).llvm_type(self.ccx))
                         };
 
                         (Base::Value(llelem), ptr::null_mut())
@@ -543,7 +543,7 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
         let elem_ty = array_ty.builtin_index().unwrap_or_else(|| {
             bug!("bad array type {:?}", array_ty)
         });
-        let llunitty = self.ccx.llvm_type_of(elem_ty);
+        let llunitty = self.ccx.layout_of(elem_ty).llvm_type(self.ccx);
         // If the array contains enums, an LLVM array won't work.
         let val = if fields.iter().all(|&f| val_ty(f) == llunitty) {
             C_array(llunitty, fields)
@@ -665,7 +665,7 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
 
                         let unsized_ty = cast_ty.builtin_deref(true, ty::NoPreference)
                             .expect("consts: unsizing got non-pointer target type").ty;
-                        let ptr_ty = self.ccx.llvm_type_of(unsized_ty).ptr_to();
+                        let ptr_ty = self.ccx.layout_of(unsized_ty).llvm_type(self.ccx).ptr_to();
                         let base = consts::ptrcast(base, ptr_ty);
                         let info = base::unsized_info(self.ccx, pointee_ty,
                                                       unsized_ty, old_info);
@@ -681,7 +681,7 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
                         debug_assert!(common::type_is_immediate(self.ccx, cast_ty));
                         let r_t_in = CastTy::from_ty(operand.ty).expect("bad input type for cast");
                         let r_t_out = CastTy::from_ty(cast_ty).expect("bad output type for cast");
-                        let ll_t_out = self.ccx.immediate_llvm_type_of(cast_ty);
+                        let ll_t_out = self.ccx.layout_of(cast_ty).immediate_llvm_type(self.ccx);
                         let llval = operand.llval;
                         let signed = match self.ccx.layout_of(operand.ty).abi {
                             layout::Abi::Scalar(layout::Int(_, signed)) => signed,
@@ -734,7 +734,8 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
                             } else { // cast to thin-ptr
                                 // Cast of fat-ptr to thin-ptr is an extraction of data-ptr and
                                 // pointer-cast of that pointer to desired pointer type.
-                                let llcast_ty = self.ccx.immediate_llvm_type_of(cast_ty);
+                                let llcast_ty = self.ccx.layout_of(cast_ty)
+                                    .immediate_llvm_type(self.ccx);
                                 consts::ptrcast(data_ptr, llcast_ty)
                             }
                         } else {
@@ -1041,7 +1042,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
 
         let result = result.unwrap_or_else(|_| {
             // We've errored, so we don't have to produce working code.
-            let llty = bcx.ccx.llvm_type_of(ty);
+            let llty = bcx.ccx.layout_of(ty).llvm_type(bcx.ccx);
             Const::new(C_undef(llty), ty)
         });
 
@@ -1100,7 +1101,7 @@ fn trans_const_adt<'a, 'tcx>(
                 _ => 0,
             };
             let discr_ty = l.field(ccx, 0).ty;
-            let discr = C_int(ccx.llvm_type_of(discr_ty), discr as i64);
+            let discr = C_int(ccx.layout_of(discr_ty).llvm_type(ccx), discr as i64);
             if let layout::Abi::Scalar(_) = l.abi {
                 Const::new(discr, t)
             } else {
@@ -1130,7 +1131,7 @@ fn trans_const_adt<'a, 'tcx>(
             } else {
                 // Always use null even if it's not the `discrfield`th
                 // field; see #8506.
-                Const::new(C_null(ccx.llvm_type_of(t)), t)
+                Const::new(C_null(ccx.layout_of(t).llvm_type(ccx)), t)
             }
         }
         _ => bug!("trans_const_adt: cannot handle type {} repreented as {:#?}", t, l)
diff --git a/src/librustc_trans/mir/lvalue.rs b/src/librustc_trans/mir/lvalue.rs
index 3c0776d4798..0732720bd1a 100644
--- a/src/librustc_trans/mir/lvalue.rs
+++ b/src/librustc_trans/mir/lvalue.rs
@@ -109,7 +109,7 @@ impl<'a, 'tcx> LvalueRef<'tcx> {
                   -> LvalueRef<'tcx> {
         debug!("alloca({:?}: {:?})", name, layout);
         let tmp = bcx.alloca(
-            bcx.ccx.llvm_type_of(layout.ty), name, layout.over_align(bcx.ccx));
+            layout.llvm_type(bcx.ccx), name, layout.over_align(bcx.ccx));
         Self::new_sized(tmp, layout, Alignment::AbiAligned)
     }
 
@@ -189,7 +189,7 @@ impl<'a, 'tcx> LvalueRef<'tcx> {
             } else {
                 bcx.load(self.llval, self.alignment.non_abi())
             };
-            OperandValue::Immediate(base::to_immediate(bcx, llval, self.layout.ty))
+            OperandValue::Immediate(base::to_immediate(bcx, llval, self.layout))
         } else {
             OperandValue::Ref(self.llval, self.alignment)
         };
@@ -223,8 +223,7 @@ impl<'a, 'tcx> LvalueRef<'tcx> {
                     bcx.struct_gep(self.llval, self.layout.llvm_field_index(ix))
                 } else {
                     assert_eq!(offset, 0);
-                    let ty = ccx.llvm_type_of(field.ty);
-                    bcx.pointercast(self.llval, ty.ptr_to())
+                    bcx.pointercast(self.llval, field.llvm_type(ccx).ptr_to())
                 },
                 llextra: if ccx.shared().type_has_metadata(field.ty) {
                     self.llextra
@@ -296,7 +295,7 @@ impl<'a, 'tcx> LvalueRef<'tcx> {
         let byte_ptr = bcx.gep(byte_ptr, &[offset]);
 
         // Finally, cast back to the type expected
-        let ll_fty = ccx.llvm_type_of(field.ty);
+        let ll_fty = field.llvm_type(ccx);
         debug!("struct_field_ptr: Field type is {:?}", ll_fty);
 
         LvalueRef {
@@ -309,7 +308,7 @@ impl<'a, 'tcx> LvalueRef<'tcx> {
 
     /// Obtain the actual discriminant of a value.
     pub fn trans_get_discr(self, bcx: &Builder<'a, 'tcx>, cast_to: Ty<'tcx>) -> ValueRef {
-        let cast_to = bcx.ccx.immediate_llvm_type_of(cast_to);
+        let cast_to = bcx.ccx.layout_of(cast_to).immediate_llvm_type(bcx.ccx);
         match *self.layout.layout {
             layout::Layout::Univariant { .. } |
             layout::Layout::UntaggedUnion { .. } => return C_uint(cast_to, 0),
@@ -357,7 +356,7 @@ impl<'a, 'tcx> LvalueRef<'tcx> {
             }
             layout::Layout::NullablePointer { nndiscr, .. } => {
                 let cmp = if nndiscr == 0 { llvm::IntEQ } else { llvm::IntNE };
-                let zero = C_null(bcx.ccx.llvm_type_of(discr.layout.ty));
+                let zero = C_null(discr.layout.llvm_type(bcx.ccx));
                 bcx.intcast(bcx.icmp(cmp, lldiscr, zero), cast_to, false)
             }
             _ => bug!("{} is not an enum", self.layout.ty)
@@ -373,7 +372,7 @@ impl<'a, 'tcx> LvalueRef<'tcx> {
         match *self.layout.layout {
             layout::Layout::General { .. } => {
                 let ptr = self.project_field(bcx, 0);
-                bcx.store(C_int(bcx.ccx.llvm_type_of(ptr.layout.ty), to as i64),
+                bcx.store(C_int(ptr.layout.llvm_type(bcx.ccx), to as i64),
                     ptr.llval, ptr.alignment.non_abi());
             }
             layout::Layout::NullablePointer { nndiscr, .. } => {
@@ -394,7 +393,7 @@ impl<'a, 'tcx> LvalueRef<'tcx> {
                         base::call_memset(bcx, llptr, fill_byte, size, align, false);
                     } else {
                         let ptr = self.project_field(bcx, 0);
-                        bcx.store(C_null(bcx.ccx.llvm_type_of(ptr.layout.ty)),
+                        bcx.store(C_null(ptr.layout.llvm_type(bcx.ccx)),
                             ptr.llval, ptr.alignment.non_abi());
                     }
                 }
@@ -523,7 +522,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
                         // Cast the lvalue pointer type to the new
                         // array or slice type (*[%_; new_len]).
                         subslice.llval = bcx.pointercast(subslice.llval,
-                            bcx.ccx.llvm_type_of(subslice.layout.ty).ptr_to());
+                            subslice.layout.llvm_type(bcx.ccx).ptr_to());
 
                         subslice
                     }
diff --git a/src/librustc_trans/mir/mod.rs b/src/librustc_trans/mir/mod.rs
index 21d2711df83..2cad0964484 100644
--- a/src/librustc_trans/mir/mod.rs
+++ b/src/librustc_trans/mir/mod.rs
@@ -23,7 +23,7 @@ use common::{self, CrateContext, Funclet};
 use debuginfo::{self, declare_local, VariableAccess, VariableKind, FunctionDebugContext};
 use monomorphize::Instance;
 use abi::{ArgAttribute, FnType};
-use type_of;
+use type_of::{self, LayoutLlvmExt};
 
 use syntax_pos::{DUMMY_SP, NO_EXPANSION, BytePos, Span};
 use syntax::symbol::keywords;
@@ -465,7 +465,7 @@ fn arg_local_refs<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
                     ty::TyAdt(def, _) if def.is_box() => arg.layout.ty.boxed_ty(),
                     _ => bug!()
                 };
-                let data_llty = bcx.ccx.llvm_type_of(pointee);
+                let data_llty = bcx.ccx.layout_of(pointee).llvm_type(bcx.ccx);
                 let meta_llty = type_of::unsized_info_ty(bcx.ccx, pointee);
 
                 a = bcx.pointercast(a, data_llty.ptr_to());
diff --git a/src/librustc_trans/mir/operand.rs b/src/librustc_trans/mir/operand.rs
index 24f6a84f620..d1922f8bf99 100644
--- a/src/librustc_trans/mir/operand.rs
+++ b/src/librustc_trans/mir/operand.rs
@@ -84,7 +84,7 @@ impl<'a, 'tcx> OperandRef<'tcx> {
     pub fn new_zst(ccx: &CrateContext<'a, 'tcx>,
                    layout: FullLayout<'tcx>) -> OperandRef<'tcx> {
         assert!(layout.is_zst());
-        let llty = ccx.llvm_type_of(layout.ty);
+        let llty = layout.llvm_type(ccx);
         // FIXME(eddyb) ZSTs should always be immediate, not pairs.
         // This hack only exists to unpack a constant undef pair.
         Const::new(C_undef(llty), layout.ty).to_operand(ccx)
@@ -119,7 +119,7 @@ impl<'a, 'tcx> OperandRef<'tcx> {
     /// Immediate aggregate with the two values.
     pub fn pack_if_pair(mut self, bcx: &Builder<'a, 'tcx>) -> OperandRef<'tcx> {
         if let OperandValue::Pair(a, b) = self.val {
-            let llty = bcx.ccx.llvm_type_of(self.layout.ty);
+            let llty = self.layout.llvm_type(bcx.ccx);
             debug!("Operand::pack_if_pair: packing {:?} into {:?}", self, llty);
             // Reconstruct the immediate aggregate.
             let mut llpair = C_undef(llty);
@@ -142,10 +142,10 @@ impl<'a, 'tcx> OperandRef<'tcx> {
                 debug!("Operand::unpack_if_pair: unpacking {:?}", self);
 
                 let a = bcx.extract_value(llval, self.layout.llvm_field_index(0));
-                let a = base::to_immediate(bcx, a, self.layout.field(bcx.ccx, 0).ty);
+                let a = base::to_immediate(bcx, a, self.layout.field(bcx.ccx, 0));
 
                 let b = bcx.extract_value(llval, self.layout.llvm_field_index(1));
-                let b = base::to_immediate(bcx, b, self.layout.field(bcx.ccx, 1).ty);
+                let b = base::to_immediate(bcx, b, self.layout.field(bcx.ccx, 1));
 
                 self.val = OperandValue::Pair(a, b);
             }
diff --git a/src/librustc_trans/mir/rvalue.rs b/src/librustc_trans/mir/rvalue.rs
index 5c24e4b5536..c7cb69339f7 100644
--- a/src/librustc_trans/mir/rvalue.rs
+++ b/src/librustc_trans/mir/rvalue.rs
@@ -26,7 +26,7 @@ use common::{C_bool, C_u8, C_i32, C_u32, C_u64, C_null, C_usize, C_uint, C_big_i
 use consts;
 use monomorphize;
 use type_::Type;
-use type_of;
+use type_of::{self, LayoutLlvmExt};
 use value::Value;
 
 use super::{MirContext, LocalRef};
@@ -259,7 +259,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
                             } else { // cast to thin-ptr
                                 // Cast of fat-ptr to thin-ptr is an extraction of data-ptr and
                                 // pointer-cast of that pointer to desired pointer type.
-                                let llcast_ty = bcx.ccx.immediate_llvm_type_of(cast.ty);
+                                let llcast_ty = cast.immediate_llvm_type(bcx.ccx);
                                 let llval = bcx.pointercast(data_ptr, llcast_ty);
                                 OperandValue::Immediate(llval)
                             }
@@ -272,8 +272,8 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
                         let r_t_in = CastTy::from_ty(operand.layout.ty)
                             .expect("bad input type for cast");
                         let r_t_out = CastTy::from_ty(cast.ty).expect("bad output type for cast");
-                        let ll_t_in = bcx.ccx.immediate_llvm_type_of(operand.layout.ty);
-                        let ll_t_out = bcx.ccx.immediate_llvm_type_of(cast.ty);
+                        let ll_t_in = operand.layout.immediate_llvm_type(bcx.ccx);
+                        let ll_t_out = cast.immediate_llvm_type(bcx.ccx);
                         let llval = operand.immediate();
 
                         if let Layout::General { ref discr_range, .. } = *operand.layout.layout {
@@ -453,7 +453,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
                 let llsize = C_usize(bcx.ccx, size.bytes());
                 let llalign = C_usize(bcx.ccx, align.abi());
                 let box_layout = bcx.ccx.layout_of(bcx.tcx().mk_box(content_ty));
-                let llty_ptr = bcx.ccx.llvm_type_of(box_layout.ty);
+                let llty_ptr = box_layout.llvm_type(bcx.ccx);
 
                 // Allocate space:
                 let def_id = match bcx.tcx().lang_items().require(ExchangeMallocFnLangItem) {
diff --git a/src/librustc_trans/trans_item.rs b/src/librustc_trans/trans_item.rs
index a452ed21aef..991f99e0f6c 100644
--- a/src/librustc_trans/trans_item.rs
+++ b/src/librustc_trans/trans_item.rs
@@ -23,9 +23,11 @@ use common;
 use declare;
 use llvm;
 use monomorphize::Instance;
+use type_of::LayoutLlvmExt;
 use rustc::hir;
 use rustc::middle::trans::{Linkage, Visibility};
 use rustc::ty::{self, TyCtxt, TypeFoldable};
+use rustc::ty::layout::LayoutOf;
 use syntax::ast;
 use syntax::attr;
 use syntax_pos::Span;
@@ -172,7 +174,7 @@ fn predefine_static<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
     let def_id = ccx.tcx().hir.local_def_id(node_id);
     let instance = Instance::mono(ccx.tcx(), def_id);
     let ty = common::instance_ty(ccx.tcx(), &instance);
-    let llty = ccx.llvm_type_of(ty);
+    let llty = ccx.layout_of(ty).llvm_type(ccx);
 
     let g = declare::define_global(ccx, symbol_name, llty).unwrap_or_else(|| {
         ccx.sess().span_fatal(ccx.tcx().hir.span(node_id),
diff --git a/src/librustc_trans/type_of.rs b/src/librustc_trans/type_of.rs
index e9547bd746b..60c2b539739 100644
--- a/src/librustc_trans/type_of.rs
+++ b/src/librustc_trans/type_of.rs
@@ -21,10 +21,10 @@ pub fn fat_ptr_base_ty<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) ->
     match ty.sty {
         ty::TyRef(_, ty::TypeAndMut { ty: t, .. }) |
         ty::TyRawPtr(ty::TypeAndMut { ty: t, .. }) if ccx.shared().type_has_metadata(t) => {
-            ccx.llvm_type_of(t).ptr_to()
+            ccx.layout_of(t).llvm_type(ccx).ptr_to()
         }
         ty::TyAdt(def, _) if def.is_box() => {
-            ccx.llvm_type_of(ty.boxed_ty()).ptr_to()
+            ccx.layout_of(ty.boxed_ty()).llvm_type(ccx).ptr_to()
         }
         _ => bug!("expected fat ptr ty but got {:?}", ty)
     }
@@ -53,7 +53,7 @@ fn uncached_llvm_type<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                 // unsized).
                 cx.str_slice_type()
             } else {
-                let ptr_ty = cx.llvm_type_of(ty).ptr_to();
+                let ptr_ty = cx.layout_of(ty).llvm_type(cx).ptr_to();
                 let info_ty = unsized_info_ty(cx, ty);
                 Type::struct_(cx, &[
                     Type::array(&Type::i8(cx), 0),
@@ -64,7 +64,7 @@ fn uncached_llvm_type<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                 ], false)
             }
         } else {
-            cx.llvm_type_of(ty).ptr_to()
+            cx.layout_of(ty).llvm_type(cx).ptr_to()
         }
     };
     match ty.sty {
@@ -89,13 +89,15 @@ fn uncached_llvm_type<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
             layout::Int(i, _) => Type::from_integer(cx, i),
             layout::F32 => Type::f32(cx),
             layout::F64 => Type::f64(cx),
-            layout::Pointer => cx.llvm_type_of(layout::Pointer.to_ty(cx.tcx()))
+            layout::Pointer => {
+                cx.layout_of(layout::Pointer.to_ty(cx.tcx())).llvm_type(cx)
+            }
         };
         return llty;
     }
 
     if let layout::Abi::Vector { .. } = layout.abi {
-        return Type::vector(&cx.llvm_type_of(layout.field(cx, 0).ty),
+        return Type::vector(&layout.field(cx, 0).llvm_type(cx),
                             layout.fields.count() as u64);
     }
 
@@ -125,7 +127,7 @@ fn uncached_llvm_type<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
             }
         }
         layout::FieldPlacement::Array { count, .. } => {
-            Type::array(&cx.llvm_type_of(layout.field(cx, 0).ty), count)
+            Type::array(&layout.field(cx, 0).llvm_type(cx), count)
         }
         layout::FieldPlacement::Arbitrary { .. } => {
             match name {
@@ -161,8 +163,7 @@ pub fn struct_llfields<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
         result.push(Type::array(&Type::i8(cx), padding.bytes()));
         debug!("    padding before: {:?}", padding);
 
-        let llty = cx.llvm_type_of(field.ty);
-        result.push(llty);
+        result.push(field.llvm_type(cx));
 
         if layout.is_packed() {
             assert_eq!(padding.bytes(), 0);
@@ -206,12 +207,16 @@ impl<'a, 'tcx> CrateContext<'a, 'tcx> {
         let layout = self.layout_of(ty);
         (layout.size(self), layout.align(self))
     }
+}
 
-    /// Returns alignment if it is different than the primitive alignment.
-    pub fn over_align_of(&self, ty: Ty<'tcx>) -> Option<Align> {
-        self.layout_of(ty).over_align(self)
-    }
+pub trait LayoutLlvmExt<'tcx> {
+    fn llvm_type<'a>(&self, ccx: &CrateContext<'a, 'tcx>) -> Type;
+    fn immediate_llvm_type<'a>(&self, ccx: &CrateContext<'a, 'tcx>) -> Type;
+    fn over_align(&self, ccx: &CrateContext) -> Option<Align>;
+    fn llvm_field_index(&self, index: usize) -> u64;
+}
 
+impl<'tcx> LayoutLlvmExt<'tcx> for FullLayout<'tcx> {
     /// Get the LLVM type corresponding to a Rust type, i.e. `rustc::ty::Ty`.
     /// The pointee type of the pointer in `LvalueRef` is always this type.
     /// For sized types, it is also the right LLVM type for an `alloca`
@@ -223,56 +228,45 @@ impl<'a, 'tcx> CrateContext<'a, '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.
-    pub fn llvm_type_of(&self, ty: Ty<'tcx>) -> Type {
+    fn llvm_type<'a>(&self, ccx: &CrateContext<'a, 'tcx>) -> Type {
         // Check the cache.
-        if let Some(&llty) = self.lltypes().borrow().get(&ty) {
+        if let Some(&llty) = ccx.lltypes().borrow().get(&self.ty) {
             return llty;
         }
 
-        debug!("type_of {:?}", ty);
+        debug!("llvm_type({:#?})", self);
 
-        assert!(!ty.has_escaping_regions(), "{:?} has escaping regions", ty);
+        assert!(!self.ty.has_escaping_regions(), "{:?} has escaping regions", self.ty);
 
         // Make sure lifetimes are erased, to avoid generating distinct LLVM
         // types for Rust types that only differ in the choice of lifetimes.
-        let normal_ty = self.tcx().erase_regions(&ty);
-
-        if ty != normal_ty {
-            let llty = self.llvm_type_of(normal_ty);
-            debug!("--> normalized {:?} to {:?} llty={:?}", ty, normal_ty, llty);
-            self.lltypes().borrow_mut().insert(ty, llty);
-            return llty;
-        }
+        let normal_ty = ccx.tcx().erase_regions(&self.ty);
 
         let mut defer = None;
-        let llty = uncached_llvm_type(self, ty, &mut defer);
-
-        debug!("--> mapped ty={:?} to llty={:?}", ty, llty);
+        let llty = if self.ty != normal_ty {
+            ccx.layout_of(normal_ty).llvm_type(ccx)
+        } else {
+            uncached_llvm_type(ccx, self.ty, &mut defer)
+        };
+        debug!("--> mapped {:#?} to llty={:?}", self, llty);
 
-        self.lltypes().borrow_mut().insert(ty, llty);
+        ccx.lltypes().borrow_mut().insert(self.ty, llty);
 
         if let Some((mut llty, layout)) = defer {
-            llty.set_struct_body(&struct_llfields(self, layout), layout.is_packed())
+            llty.set_struct_body(&struct_llfields(ccx, layout), layout.is_packed())
         }
 
         llty
     }
 
-    pub fn immediate_llvm_type_of(&self, ty: Ty<'tcx>) -> Type {
-        if ty.is_bool() {
-            Type::i1(self)
+    fn immediate_llvm_type<'a>(&self, ccx: &CrateContext<'a, 'tcx>) -> Type {
+        if let layout::Abi::Scalar(layout::Int(layout::I1, _)) = self.abi {
+            Type::i1(ccx)
         } else {
-            self.llvm_type_of(ty)
+            self.llvm_type(ccx)
         }
     }
-}
-
-pub trait LayoutLlvmExt {
-    fn over_align(&self, ccx: &CrateContext) -> Option<Align>;
-    fn llvm_field_index(&self, index: usize) -> u64;
-}
 
-impl<'tcx> LayoutLlvmExt for FullLayout<'tcx> {
     fn over_align(&self, ccx: &CrateContext) -> Option<Align> {
         let align = self.align(ccx);
         let primitive_align = self.primitive_align(ccx);