diff --git a/src/librustc_trans/abi.rs b/src/librustc_trans/abi.rs index 1838dae049ad7..0d6cd1088f2cb 100644 --- a/src/librustc_trans/abi.rs +++ b/src/librustc_trans/abi.rs @@ -558,7 +558,7 @@ impl<'a, 'tcx> FnTypeExt<'a, 'tcx> for FnType<'tcx, Ty<'tcx>> { let llreturn_ty = match self.ret.mode { PassMode::Ignore => Type::void(cx), PassMode::Direct(_) | PassMode::Pair(..) => { - self.ret.layout.immediate_llvm_type(cx) + self.ret.layout.llvm_type(cx) } PassMode::Cast(cast) => cast.llvm_type(cx), PassMode::Indirect(_) => { @@ -575,7 +575,7 @@ impl<'a, 'tcx> FnTypeExt<'a, 'tcx> for FnType<'tcx, Ty<'tcx>> { let llarg_ty = match arg.mode { PassMode::Ignore => continue, - PassMode::Direct(_) => arg.layout.immediate_llvm_type(cx), + PassMode::Direct(_) => arg.layout.llvm_type(cx), PassMode::Pair(..) => { llargument_tys.push(arg.layout.scalar_pair_element_llvm_type(cx, 0)); llargument_tys.push(arg.layout.scalar_pair_element_llvm_type(cx, 1)); diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index b756a6695f941..03f96c4eec8a6 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -40,7 +40,7 @@ use rustc::middle::weak_lang_items; use rustc::mir::mono::{Linkage, Visibility, Stats}; use rustc::middle::cstore::{EncodedMetadata}; use rustc::ty::{self, Ty, TyCtxt}; -use rustc::ty::layout::{self, Align, TyLayout, LayoutOf}; +use rustc::ty::layout::{Align, TyLayout, LayoutOf}; use rustc::ty::maps::Providers; use rustc::dep_graph::{DepNode, DepConstructor}; use rustc::ty::subst::Kind; @@ -387,23 +387,6 @@ pub fn call_assume<'a, 'tcx>(bx: &Builder<'a, 'tcx>, val: ValueRef) { bx.call(assume_intrinsic, &[val], None); } -pub fn from_immediate(bx: &Builder, val: ValueRef) -> ValueRef { - if val_ty(val) == Type::i1(bx.cx) { - bx.zext(val, Type::i8(bx.cx)) - } else { - val - } -} - -pub fn to_immediate(bx: &Builder, val: ValueRef, layout: layout::TyLayout) -> ValueRef { - if let layout::Abi::Scalar(ref scalar) = layout.abi { - if scalar.is_bool() { - return bx.trunc(val, Type::i1(bx.cx)); - } - } - val -} - pub fn call_memcpy(bx: &Builder, dst: ValueRef, src: ValueRef, diff --git a/src/librustc_trans/intrinsic.rs b/src/librustc_trans/intrinsic.rs index 49a207a2d8ab5..4239b373180b4 100644 --- a/src/librustc_trans/intrinsic.rs +++ b/src/librustc_trans/intrinsic.rs @@ -244,7 +244,7 @@ pub fn trans_intrinsic_call<'a, 'tcx>(bx: &Builder<'a, 'tcx>, unsafe { llvm::LLVMSetAlignment(load, cx.align_of(tp_ty).abi() as u32); } - to_immediate(bx, load, cx.layout_of(tp_ty)) + load }, "volatile_store" => { let tp_ty = substs.type_at(0); @@ -259,7 +259,7 @@ pub fn trans_intrinsic_call<'a, 'tcx>(bx: &Builder<'a, 'tcx>, if dst.layout.is_zst() { return; } - from_immediate(bx, args[1].immediate()) + args[1].immediate() }; let ptr = bx.pointercast(dst.llval, val_ty(val).ptr_to()); let store = bx.volatile_store(val, ptr); @@ -556,7 +556,7 @@ pub fn trans_intrinsic_call<'a, 'tcx>(bx: &Builder<'a, 'tcx>, let val = if let OperandValue::Ref(ptr, align) = args[1].val { bx.load(ptr, align) } else { - from_immediate(bx, args[1].immediate()) + args[1].immediate() }; let ptr = bx.pointercast(dst.llval, val_ty(val).ptr_to()); let store = bx.nontemporal_store(val, ptr); diff --git a/src/librustc_trans/mir/block.rs b/src/librustc_trans/mir/block.rs index b666c2b211525..1d2375ab3380b 100644 --- a/src/librustc_trans/mir/block.rs +++ b/src/librustc_trans/mir/block.rs @@ -204,7 +204,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { let (otherwise, targets) = targets.split_last().unwrap(); let switch = bx.switch(discr.immediate(), llblock(self, *otherwise), values.len()); - let switch_llty = bx.cx.layout_of(switch_ty).immediate_llvm_type(bx.cx); + let switch_llty = bx.cx.layout_of(switch_ty).llvm_type(bx.cx); for (&value, target) in values.iter().zip(targets) { let llval = C_uint_big(switch_llty, value); let llbb = llblock(self, *target); @@ -651,8 +651,6 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { bx.range_metadata(llval, 0..2); } } - // We store bools as i8 so we need to truncate to i1. - llval = base::to_immediate(bx, llval, arg.layout); } } diff --git a/src/librustc_trans/mir/constant.rs b/src/librustc_trans/mir/constant.rs index 6e07b8e73ef22..221b870822ee7 100644 --- a/src/librustc_trans/mir/constant.rs +++ b/src/librustc_trans/mir/constant.rs @@ -215,7 +215,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { }; Ok(primval_to_llvm( bx.cx, prim, scalar, - layout.immediate_llvm_type(bx.cx), + layout.llvm_type(bx.cx), )) }, other => bug!("simd shuffle field {:?}, {}", other, constant.ty), diff --git a/src/librustc_trans/mir/operand.rs b/src/librustc_trans/mir/operand.rs index 656ab95a28cf3..6f5084ad4b062 100644 --- a/src/librustc_trans/mir/operand.rs +++ b/src/librustc_trans/mir/operand.rs @@ -88,7 +88,7 @@ impl<'a, 'tcx> OperandRef<'tcx> { layout: TyLayout<'tcx>) -> OperandRef<'tcx> { assert!(layout.is_zst()); OperandRef { - val: OperandValue::Immediate(C_undef(layout.immediate_llvm_type(cx))), + val: OperandValue::Immediate(C_undef(layout.llvm_type(cx))), layout } } @@ -113,7 +113,7 @@ impl<'a, 'tcx> OperandRef<'tcx> { bx.cx, x, scalar, - layout.immediate_llvm_type(bx.cx), + layout.llvm_type(bx.cx), ); OperandValue::Immediate(llval) }, @@ -226,7 +226,7 @@ impl<'a, 'tcx> OperandRef<'tcx> { // If we're uninhabited, or the field is ZST, it has no data. _ if self.layout.abi == layout::Abi::Uninhabited || field.is_zst() => { return OperandRef { - val: OperandValue::Immediate(C_undef(field.immediate_llvm_type(bx.cx))), + val: OperandValue::Immediate(C_undef(field.llvm_type(bx.cx))), layout: field }; } @@ -263,7 +263,7 @@ impl<'a, 'tcx> OperandRef<'tcx> { // HACK(eddyb) have to bitcast pointers until LLVM removes pointee types. match val { OperandValue::Immediate(ref mut llval) => { - *llval = bx.bitcast(*llval, field.immediate_llvm_type(bx.cx)); + *llval = bx.bitcast(*llval, field.llvm_type(bx.cx)); } OperandValue::Pair(ref mut a, ref mut b) => { *a = bx.bitcast(*a, field.scalar_pair_element_llvm_type(bx.cx, 0)); @@ -292,7 +292,7 @@ impl<'a, 'tcx> OperandValue { base::memcpy_ty(bx, dest.llval, r, dest.layout, source_align.min(dest.align)), OperandValue::Immediate(s) => { - bx.store(base::from_immediate(bx, s), dest.llval, dest.align); + bx.store(s, dest.llval, dest.align); } OperandValue::Pair(a, b) => { for (i, &x) in [a, b].iter().enumerate() { @@ -301,7 +301,7 @@ impl<'a, 'tcx> OperandValue { if common::val_ty(x) == Type::i1(bx.cx) { llptr = bx.pointercast(llptr, Type::i8p(bx.cx)); } - bx.store(base::from_immediate(bx, x), llptr, dest.align); + bx.store(x, llptr, dest.align); } } } diff --git a/src/librustc_trans/mir/place.rs b/src/librustc_trans/mir/place.rs index 79859aee64d87..971fdee57caa7 100644 --- a/src/librustc_trans/mir/place.rs +++ b/src/librustc_trans/mir/place.rs @@ -93,7 +93,7 @@ impl<'a, 'tcx> PlaceRef<'tcx> { let scalar_load_metadata = |load, scalar: &layout::Scalar| { let vr = scalar.valid_range.clone(); match scalar.value { - layout::Int(..) => { + layout::Int(..) if !scalar.is_bool() => { let range = scalar.valid_range_exclusive(bx.cx); if range.start != range.end { bx.range_metadata(load, range); @@ -124,21 +124,13 @@ impl<'a, 'tcx> PlaceRef<'tcx> { } load }; - OperandValue::Immediate(base::to_immediate(bx, llval, self.layout)) + OperandValue::Immediate(llval) } else if let layout::Abi::ScalarPair(ref a, ref b) = self.layout.abi { let load = |i, scalar: &layout::Scalar| { - let mut llptr = bx.struct_gep(self.llval, i as u64); - // Make sure to always load i1 as i8. - if scalar.is_bool() { - llptr = bx.pointercast(llptr, Type::i8p(bx.cx)); - } + let llptr = bx.struct_gep(self.llval, i as u64); let load = bx.load(llptr, self.align); scalar_load_metadata(load, scalar); - if scalar.is_bool() { - bx.trunc(load, Type::i1(bx.cx)) - } else { - load - } + load }; OperandValue::Pair(load(0, a), load(1, b)) } else { @@ -254,7 +246,7 @@ impl<'a, 'tcx> PlaceRef<'tcx> { /// Obtain the actual discriminant of a value. pub fn trans_get_discr(self, bx: &Builder<'a, 'tcx>, cast_to: Ty<'tcx>) -> ValueRef { - let cast_to = bx.cx.layout_of(cast_to).immediate_llvm_type(bx.cx); + let cast_to = bx.cx.layout_of(cast_to).llvm_type(bx.cx); if self.layout.abi == layout::Abi::Uninhabited { return C_undef(cast_to); } @@ -286,7 +278,7 @@ impl<'a, 'tcx> PlaceRef<'tcx> { niche_start, .. } => { - let niche_llty = discr.layout.immediate_llvm_type(bx.cx); + let niche_llty = discr.layout.llvm_type(bx.cx); if niche_variants.start() == niche_variants.end() { // FIXME(eddyb) Check the actual primitive type here. let niche_llval = if niche_start == 0 { @@ -351,7 +343,7 @@ impl<'a, 'tcx> PlaceRef<'tcx> { } let niche = self.project_field(bx, 0); - let niche_llty = niche.layout.immediate_llvm_type(bx.cx); + let niche_llty = niche.layout.llvm_type(bx.cx); let niche_value = ((variant_index - *niche_variants.start()) as u128) .wrapping_add(niche_start); // FIXME(eddyb) Check the actual primitive type here. diff --git a/src/librustc_trans/mir/rvalue.rs b/src/librustc_trans/mir/rvalue.rs index 0cd823391b9b6..2c8f858154d57 100644 --- a/src/librustc_trans/mir/rvalue.rs +++ b/src/librustc_trans/mir/rvalue.rs @@ -101,7 +101,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { let start = dest.project_index(&bx, C_usize(bx.cx, 0)).llval; - if let OperandValue::Immediate(v) = tr_elem.val { + if let OperandValue::Immediate(mut v) = tr_elem.val { let align = C_i32(bx.cx, dest.align.abi() as i32); let size = C_usize(bx.cx, dest.layout.size.bytes()); @@ -113,7 +113,9 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { } // Use llvm.memset.p0i8.* to initialize byte arrays - let v = base::from_immediate(&bx, v); + if common::val_ty(v) == Type::i1(bx.cx) { + v = bx.zext(v, Type::i8(bx.cx)) + } if common::val_ty(v) == Type::i8(bx.cx) { base::call_memset(&bx, start, v, size, align, false); return bx; @@ -256,7 +258,7 @@ impl<'a, 'tcx> FunctionCx<'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 = cast.immediate_llvm_type(bx.cx); + let llcast_ty = cast.llvm_type(bx.cx); let llval = bx.pointercast(data_ptr, llcast_ty); OperandValue::Immediate(llval) } @@ -266,7 +268,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { } mir::CastKind::Misc => { assert!(cast.is_llvm_immediate()); - let ll_t_out = cast.immediate_llvm_type(bx.cx); + let ll_t_out = cast.llvm_type(bx.cx); if operand.layout.abi == layout::Abi::Uninhabited { return (bx, OperandRef { val: OperandValue::Immediate(C_undef(ll_t_out)), @@ -276,7 +278,7 @@ impl<'a, 'tcx> FunctionCx<'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 = operand.layout.immediate_llvm_type(bx.cx); + let ll_t_in = operand.layout.llvm_type(bx.cx); match operand.layout.variants { layout::Variants::Single { index } => { if let Some(def) = operand.layout.ty.ty_adt_def() { diff --git a/src/librustc_trans/type_of.rs b/src/librustc_trans/type_of.rs index 5e6b276495764..9c4b679524dca 100644 --- a/src/librustc_trans/type_of.rs +++ b/src/librustc_trans/type_of.rs @@ -200,7 +200,6 @@ 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 scalar_llvm_type_at<'a>(&self, cx: &CodegenCx<'a, 'tcx>, scalar: &layout::Scalar, offset: Size) -> Type; fn scalar_pair_element_llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>, @@ -244,6 +243,9 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyLayout<'tcx> { /// that field and ensuring the struct has the right alignment. fn llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> Type { if let layout::Abi::Scalar(ref scalar) = self.abi { + if scalar.is_bool() { + return Type::i1(cx); + } // Use a different cache for scalars because pointers to DSTs // can be either fat or thin (data pointers of fat pointers). if let Some(&llty) = cx.scalar_lltypes.borrow().get(&self.ty) { @@ -310,15 +312,6 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyLayout<'tcx> { llty } - fn immediate_llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> Type { - if let layout::Abi::Scalar(ref scalar) = self.abi { - if scalar.is_bool() { - return Type::i1(cx); - } - } - self.llvm_type(cx) - } - fn scalar_llvm_type_at<'a>(&self, cx: &CodegenCx<'a, 'tcx>, scalar: &layout::Scalar, offset: Size) -> Type { match scalar.value { @@ -359,13 +352,6 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyLayout<'tcx> { }; let scalar = [a, b][index]; - // Make sure to return the same type `immediate_llvm_type` would, - // to avoid dealing with two types and the associated conversions. - // This means that `(bool, bool)` is represented as `{i1, i1}`, - // both in memory and as an immediate, while `bool` is typically - // `i8` in memory and only `i1` when immediate. While we need to - // load/store `bool` as `i8` to avoid crippling LLVM optimizations, - // `i1` in a LLVM aggregate is valid and mostly equivalent to `i8`. if scalar.is_bool() { return Type::i1(cx); } diff --git a/src/test/codegen/function-arguments.rs b/src/test/codegen/function-arguments.rs index 40a9ea5a18139..ed4c93d53df44 100644 --- a/src/test/codegen/function-arguments.rs +++ b/src/test/codegen/function-arguments.rs @@ -151,7 +151,7 @@ pub fn enum_id_1(x: Option>) -> Option> { x } -// CHECK: i16 @enum_id_2(i16) +// CHECK: { i1, i8 } @enum_id_2(i1 zeroext %x.0, i8 %x.1) #[no_mangle] pub fn enum_id_2(x: Option) -> Option { x