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 { - 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; + 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); + 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); - debug!("--> mapped ty={:?} to llty={:?}", ty, 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; - fn llvm_field_index(&self, index: usize) -> u64; -} - -impl<'tcx> LayoutLlvmExt for FullLayout<'tcx> { fn over_align(&self, ccx: &CrateContext) -> Option { let align = self.align(ccx); let primitive_align = self.primitive_align(ccx);