diff --git a/src/librustc/mir/interpret/allocation.rs b/src/librustc/mir/interpret/allocation.rs index 02c0ebcec4fe..eb44c3c8c5f7 100644 --- a/src/librustc/mir/interpret/allocation.rs +++ b/src/librustc/mir/interpret/allocation.rs @@ -12,7 +12,7 @@ use super::{Pointer, EvalResult, AllocId}; -use ty::layout::{Size, Align}; +use ty::layout::{Size, AbiAndPrefAlign}; use syntax::ast::Mutability; use std::iter; use mir; @@ -40,7 +40,7 @@ pub struct Allocation { /// Denotes undefined memory. Reading from undefined memory is forbidden in miri pub undef_mask: UndefMask, /// The alignment of the allocation to detect unaligned reads. - pub align: Align, + pub align: AbiAndPrefAlign, /// Whether the allocation is mutable. /// Also used by codegen to determine if a static should be put into mutable memory, /// which happens for `static mut` and `static` with interior mutability. @@ -90,7 +90,7 @@ impl AllocationExtra<()> for () {} impl Allocation { /// Creates a read-only allocation initialized by the given bytes - pub fn from_bytes(slice: &[u8], align: Align) -> Self { + pub fn from_bytes(slice: &[u8], align: AbiAndPrefAlign) -> Self { let mut undef_mask = UndefMask::new(Size::ZERO); undef_mask.grow(Size::from_bytes(slice.len() as u64), true); Self { @@ -104,10 +104,10 @@ impl Allocation { } pub fn from_byte_aligned_bytes(slice: &[u8]) -> Self { - Allocation::from_bytes(slice, Align::from_bytes(1, 1).unwrap()) + Allocation::from_bytes(slice, AbiAndPrefAlign::from_bytes(1, 1).unwrap()) } - pub fn undef(size: Size, align: Align) -> Self { + pub fn undef(size: Size, align: AbiAndPrefAlign) -> Self { assert_eq!(size.bytes() as usize as u64, size.bytes()); Allocation { bytes: vec![0; size.bytes() as usize], diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs index f1ac4b210583..bae53a9216a4 100644 --- a/src/librustc/mir/interpret/error.rs +++ b/src/librustc/mir/interpret/error.rs @@ -13,7 +13,7 @@ use std::{fmt, env}; use hir::map::definitions::DefPathData; use mir; use ty::{self, Ty, layout}; -use ty::layout::{Size, Align, LayoutError}; +use ty::layout::{Size, AbiAndPrefAlign, LayoutError}; use rustc_target::spec::abi::Abi; use super::{RawConst, Pointer, InboundsCheck, ScalarMaybeUndef}; @@ -301,8 +301,8 @@ pub enum EvalErrorKind<'tcx, O> { TlsOutOfBounds, AbiViolation(String), AlignmentCheckFailed { - required: Align, - has: Align, + required: AbiAndPrefAlign, + has: AbiAndPrefAlign, }, ValidationFailure(String), CalledClosureAsFunction, @@ -315,7 +315,7 @@ pub enum EvalErrorKind<'tcx, O> { DeallocatedWrongMemoryKind(String, String), ReallocateNonBasePtr, DeallocateNonBasePtr, - IncorrectAllocationInformation(Size, Size, Align, Align), + IncorrectAllocationInformation(Size, Size, AbiAndPrefAlign, AbiAndPrefAlign), Layout(layout::LayoutError<'tcx>), HeapAllocZeroBytes, HeapAllocNonPowerOfTwoAlignment(u64), diff --git a/src/librustc/session/code_stats.rs b/src/librustc/session/code_stats.rs index b1dcfdfcda03..34a89ccf7a21 100644 --- a/src/librustc/session/code_stats.rs +++ b/src/librustc/session/code_stats.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use rustc_target::abi::{Align, Size}; +use rustc_target::abi::{AbiAndPrefAlign, Size}; use rustc_data_structures::fx::{FxHashSet}; use std::cmp::{self, Ordering}; @@ -63,7 +63,7 @@ impl CodeStats { pub fn record_type_size(&mut self, kind: DataTypeKind, type_desc: S, - align: Align, + align: AbiAndPrefAlign, overall_size: Size, packed: bool, opt_discr_size: Option, diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index d7fb8da7acd0..76c3c467febb 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -248,7 +248,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { /// A univariant, the last field of which may be coerced to unsized. MaybeUnsized, /// A univariant, but with a prefix of an arbitrary size & alignment (e.g. enum tag). - Prefixed(Size, Align), + Prefixed(Size, AbiAndPrefAlign), } let univariant_uninterned = |fields: &[TyLayout<'_>], repr: &ReprOptions, kind| { @@ -259,7 +259,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { let pack = { let pack = repr.pack as u64; - Align::from_bytes(pack, pack).unwrap() + AbiAndPrefAlign::from_bytes(pack, pack).unwrap() }; let mut align = if packed { @@ -352,7 +352,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { if repr.align > 0 { let repr_align = repr.align as u64; - align = align.max(Align::from_bytes(repr_align, repr_align).unwrap()); + align = align.max(AbiAndPrefAlign::from_bytes(repr_align, repr_align).unwrap()); debug!("univariant repr_align: {:?}", repr_align); } @@ -682,7 +682,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { let pack = { let pack = def.repr.pack as u64; - Align::from_bytes(pack, pack).unwrap() + AbiAndPrefAlign::from_bytes(pack, pack).unwrap() }; let mut align = if packed { @@ -694,7 +694,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { if def.repr.align > 0 { let repr_align = def.repr.align as u64; align = align.max( - Align::from_bytes(repr_align, repr_align).unwrap()); + AbiAndPrefAlign::from_bytes(repr_align, repr_align).unwrap()); } let optimize = !def.repr.inhibit_union_abi_opt(); @@ -964,7 +964,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { let mut size = Size::ZERO; // We're interested in the smallest alignment, so start large. - let mut start_align = Align::from_bytes(256, 256).unwrap(); + let mut start_align = AbiAndPrefAlign::from_bytes(256, 256).unwrap(); assert_eq!(Integer::for_abi_align(dl, start_align), None); // repr(C) on an enum tells us to make a (tag, union) layout, @@ -1994,7 +1994,7 @@ impl_stable_hash_for!(enum ::ty::layout::Primitive { Pointer }); -impl<'gcx> HashStable> for Align { +impl<'gcx> HashStable> for AbiAndPrefAlign { fn hash_stable(&self, hcx: &mut StableHashingContext<'gcx>, hasher: &mut StableHasher) { diff --git a/src/librustc_codegen_llvm/builder.rs b/src/librustc_codegen_llvm/builder.rs index 34e4f4d7e183..38400946a914 100644 --- a/src/librustc_codegen_llvm/builder.rs +++ b/src/librustc_codegen_llvm/builder.rs @@ -19,7 +19,7 @@ use type_of::LayoutLlvmExt; use value::Value; use libc::{c_uint, c_char}; use rustc::ty::{self, Ty, TyCtxt}; -use rustc::ty::layout::{self, Align, Size, TyLayout}; +use rustc::ty::layout::{self, AbiAndPrefAlign, Size, TyLayout}; use rustc::session::config; use rustc_data_structures::small_c_str::SmallCStr; use rustc_codegen_ssa::traits::*; @@ -457,7 +457,7 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { } } - fn alloca(&mut self, ty: &'ll Type, name: &str, align: Align) -> &'ll Value { + fn alloca(&mut self, ty: &'ll Type, name: &str, align: AbiAndPrefAlign) -> &'ll Value { let mut bx = Builder::with_cx(self.cx); bx.position_at_start(unsafe { llvm::LLVMGetFirstBasicBlock(self.llfn()) @@ -465,7 +465,7 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { bx.dynamic_alloca(ty, name, align) } - fn dynamic_alloca(&mut self, ty: &'ll Type, name: &str, align: Align) -> &'ll Value { + fn dynamic_alloca(&mut self, ty: &'ll Type, name: &str, align: AbiAndPrefAlign) -> &'ll Value { self.count_insn("alloca"); unsafe { let alloca = if name.is_empty() { @@ -484,7 +484,7 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { ty: &'ll Type, len: &'ll Value, name: &str, - align: Align) -> &'ll Value { + align: AbiAndPrefAlign) -> &'ll Value { self.count_insn("alloca"); unsafe { let alloca = if name.is_empty() { @@ -499,7 +499,7 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { } } - fn load(&mut self, ptr: &'ll Value, align: Align) -> &'ll Value { + fn load(&mut self, ptr: &'ll Value, align: AbiAndPrefAlign) -> &'ll Value { self.count_insn("load"); unsafe { let load = llvm::LLVMBuildLoad(self.llbuilder, ptr, noname()); @@ -639,7 +639,7 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { } } - fn store(&mut self, val: &'ll Value, ptr: &'ll Value, align: Align) -> &'ll Value { + fn store(&mut self, val: &'ll Value, ptr: &'ll Value, align: AbiAndPrefAlign) -> &'ll Value { self.store_with_flags(val, ptr, align, MemFlags::empty()) } @@ -647,7 +647,7 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { &mut self, val: &'ll Value, ptr: &'ll Value, - align: Align, + align: AbiAndPrefAlign, flags: MemFlags, ) -> &'ll Value { debug!("Store {:?} -> {:?} ({:?})", val, ptr, flags); @@ -878,8 +878,8 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { } } - fn memcpy(&mut self, dst: &'ll Value, dst_align: Align, - src: &'ll Value, src_align: Align, + fn memcpy(&mut self, dst: &'ll Value, dst_align: AbiAndPrefAlign, + src: &'ll Value, src_align: AbiAndPrefAlign, size: &'ll Value, flags: MemFlags) { if flags.contains(MemFlags::NONTEMPORAL) { // HACK(nox): This is inefficient but there is no nontemporal memcpy. @@ -898,8 +898,8 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { } } - fn memmove(&mut self, dst: &'ll Value, dst_align: Align, - src: &'ll Value, src_align: Align, + fn memmove(&mut self, dst: &'ll Value, dst_align: AbiAndPrefAlign, + src: &'ll Value, src_align: AbiAndPrefAlign, size: &'ll Value, flags: MemFlags) { if flags.contains(MemFlags::NONTEMPORAL) { // HACK(nox): This is inefficient but there is no nontemporal memmove. @@ -923,7 +923,7 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { ptr: &'ll Value, fill_byte: &'ll Value, size: &'ll Value, - align: Align, + align: AbiAndPrefAlign, flags: MemFlags, ) { let ptr_width = &self.cx().sess().target.target.target_pointer_width; diff --git a/src/librustc_codegen_llvm/consts.rs b/src/librustc_codegen_llvm/consts.rs index 821ac931aac7..158bc6eb9c10 100644 --- a/src/librustc_codegen_llvm/consts.rs +++ b/src/librustc_codegen_llvm/consts.rs @@ -28,7 +28,7 @@ use value::Value; use rustc::ty::{self, Ty}; use rustc_codegen_ssa::traits::*; -use rustc::ty::layout::{self, Size, Align, LayoutOf}; +use rustc::ty::layout::{self, Size, AbiAndPrefAlign, LayoutOf}; use rustc::hir::{self, CodegenFnAttrs, CodegenFnAttrFlags}; @@ -89,12 +89,12 @@ pub fn codegen_static_initializer( fn set_global_alignment(cx: &CodegenCx<'ll, '_>, gv: &'ll Value, - mut align: Align) { + mut align: AbiAndPrefAlign) { // The target may require greater alignment for globals than the type does. // Note: GCC and Clang also allow `__attribute__((aligned))` on variables, // which can force it to be smaller. Rust doesn't support this yet. if let Some(min) = cx.sess().target.target.options.min_global_align { - match ty::layout::Align::from_bits(min, min) { + match ty::layout::AbiAndPrefAlign::from_bits(min, min) { Ok(min) => align = align.max(min), Err(err) => { cx.sess().err(&format!("invalid minimum global alignment: {}", err)); @@ -186,7 +186,7 @@ impl StaticMethods<'tcx> for CodegenCx<'ll, 'tcx> { fn static_addr_of_mut( &self, cv: &'ll Value, - align: Align, + align: AbiAndPrefAlign, kind: Option<&str>, ) -> &'ll Value { unsafe { @@ -212,7 +212,7 @@ impl StaticMethods<'tcx> for CodegenCx<'ll, 'tcx> { fn static_addr_of( &self, cv: &'ll Value, - align: Align, + align: AbiAndPrefAlign, kind: Option<&str>, ) -> &'ll Value { if let Some(&gv) = self.const_globals.borrow().get(&cv) { diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs index 1c787a969324..42b48b728fd0 100644 --- a/src/librustc_codegen_llvm/debuginfo/metadata.rs +++ b/src/librustc_codegen_llvm/debuginfo/metadata.rs @@ -35,7 +35,7 @@ use rustc_data_structures::fingerprint::Fingerprint; use rustc::ty::Instance; use common::CodegenCx; use rustc::ty::{self, AdtKind, ParamEnv, Ty, TyCtxt}; -use rustc::ty::layout::{self, Align, HasDataLayout, Integer, IntegerExt, LayoutOf, +use rustc::ty::layout::{self, AbiAndPrefAlign, HasDataLayout, Integer, IntegerExt, LayoutOf, PrimitiveExt, Size, TyLayout}; use rustc::session::config; use rustc::util::nodemap::FxHashMap; @@ -923,7 +923,7 @@ struct MemberDescription<'ll> { type_metadata: &'ll DIType, offset: Size, size: Size, - align: Align, + align: AbiAndPrefAlign, flags: DIFlags, discriminant: Option, } @@ -985,13 +985,12 @@ impl<'tcx> StructMemberDescriptionFactory<'tcx> { f.ident.to_string() }; let field = layout.field(cx, i); - let (size, align) = field.size_and_align(); MemberDescription { name, type_metadata: type_metadata(cx, field.ty, self.span), offset: layout.fields.offset(i), - size, - align, + size: field.size, + align: field.align, flags: DIFlags::FlagZero, discriminant: None, } @@ -1109,13 +1108,12 @@ impl<'tcx> UnionMemberDescriptionFactory<'tcx> { -> Vec> { self.variant.fields.iter().enumerate().map(|(i, f)| { let field = self.layout.field(cx, i); - let (size, align) = field.size_and_align(); MemberDescription { name: f.ident.to_string(), type_metadata: type_metadata(cx, field.ty, self.span), offset: Size::ZERO, - size, - align, + size: field.size, + align: field.align, flags: DIFlags::FlagZero, discriminant: None, } @@ -1587,8 +1585,6 @@ fn prepare_enum_metadata( _ => {} } - let (enum_type_size, enum_type_align) = layout.size_and_align(); - let enum_name = SmallCStr::new(&enum_name); let unique_type_id_str = SmallCStr::new( debug_context(cx).type_map.borrow().get_unique_type_id_as_string(unique_type_id) @@ -1610,8 +1606,8 @@ fn prepare_enum_metadata( enum_name.as_ptr(), file_metadata, UNKNOWN_LINE_NUMBER, - enum_type_size.bits(), - enum_type_align.abi_bits() as u32, + layout.size.bits(), + layout.align.abi_bits() as u32, DIFlags::FlagZero, None, 0, // RuntimeLang @@ -1695,8 +1691,8 @@ fn prepare_enum_metadata( ptr::null_mut(), file_metadata, UNKNOWN_LINE_NUMBER, - enum_type_size.bits(), - enum_type_align.abi_bits() as u32, + layout.size.bits(), + layout.align.abi_bits() as u32, DIFlags::FlagZero, discriminator_metadata, empty_array, @@ -1712,8 +1708,8 @@ fn prepare_enum_metadata( enum_name.as_ptr(), file_metadata, UNKNOWN_LINE_NUMBER, - enum_type_size.bits(), - enum_type_align.abi_bits() as u32, + layout.size.bits(), + layout.align.abi_bits() as u32, DIFlags::FlagZero, None, type_array, diff --git a/src/librustc_codegen_llvm/type_of.rs b/src/librustc_codegen_llvm/type_of.rs index 90c02cddb2b6..a07fa9448919 100644 --- a/src/librustc_codegen_llvm/type_of.rs +++ b/src/librustc_codegen_llvm/type_of.rs @@ -12,7 +12,7 @@ use abi::{FnType, FnTypeExt}; use common::*; use rustc::hir; use rustc::ty::{self, Ty, TypeFoldable}; -use rustc::ty::layout::{self, Align, LayoutOf, Size, TyLayout}; +use rustc::ty::layout::{self, AbiAndPrefAlign, LayoutOf, Size, TyLayout}; use rustc_target::abi::FloatTy; use rustc_mir::monomorphize::item::DefPathBasedNames; use type_::Type; @@ -80,7 +80,7 @@ fn uncached_llvm_type<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, match layout.fields { layout::FieldPlacement::Union(_) => { - let fill = cx.type_padding_filler( layout.size, layout.align); + let fill = cx.type_padding_filler(layout.size, layout.align); let packed = false; match name { None => { @@ -165,7 +165,7 @@ fn struct_llfields<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, } impl<'a, 'tcx> CodegenCx<'a, 'tcx> { - pub fn align_of(&self, ty: Ty<'tcx>) -> Align { + pub fn align_of(&self, ty: Ty<'tcx>) -> AbiAndPrefAlign { self.layout_of(ty).align } @@ -173,8 +173,9 @@ impl<'a, 'tcx> CodegenCx<'a, 'tcx> { self.layout_of(ty).size } - pub fn size_and_align_of(&self, ty: Ty<'tcx>) -> (Size, Align) { - self.layout_of(ty).size_and_align() + pub fn size_and_align_of(&self, ty: Ty<'tcx>) -> (Size, AbiAndPrefAlign) { + let layout = self.layout_of(ty); + (layout.size, layout.align) } } @@ -196,7 +197,7 @@ pub enum PointerKind { #[derive(Copy, Clone)] pub struct PointeeInfo { pub size: Size, - pub align: Align, + pub align: AbiAndPrefAlign, pub safe: Option, } diff --git a/src/librustc_codegen_ssa/base.rs b/src/librustc_codegen_ssa/base.rs index 856bb9533c85..e80ff8b65801 100644 --- a/src/librustc_codegen_ssa/base.rs +++ b/src/librustc_codegen_ssa/base.rs @@ -31,7 +31,7 @@ use rustc::middle::lang_items::StartFnLangItem; use rustc::middle::weak_lang_items; use rustc::mir::mono::{Stats, CodegenUnitNameBuilder}; use rustc::ty::{self, Ty, TyCtxt}; -use rustc::ty::layout::{self, Align, TyLayout, LayoutOf, VariantIdx, HasTyCtxt}; +use rustc::ty::layout::{self, AbiAndPrefAlign, TyLayout, LayoutOf, VariantIdx, HasTyCtxt}; use rustc::ty::query::Providers; use rustc::middle::cstore::{self, LinkagePreference}; use rustc::util::common::{time, print_time_passes_entry}; @@ -410,9 +410,9 @@ pub fn to_immediate_scalar<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>( pub fn memcpy_ty<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>( bx: &mut Bx, dst: Bx::Value, - dst_align: Align, + dst_align: AbiAndPrefAlign, src: Bx::Value, - src_align: Align, + src_align: AbiAndPrefAlign, layout: TyLayout<'tcx>, flags: MemFlags, ) { diff --git a/src/librustc_codegen_ssa/glue.rs b/src/librustc_codegen_ssa/glue.rs index 515f36b5c65d..bf4c53f228e3 100644 --- a/src/librustc_codegen_ssa/glue.rs +++ b/src/librustc_codegen_ssa/glue.rs @@ -25,14 +25,12 @@ pub fn size_and_align_of_dst<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>( t: Ty<'tcx>, info: Option ) -> (Bx::Value, Bx::Value) { - debug!("calculate size of DST: {}; with lost info: {:?}", - t, info); - if bx.cx().type_is_sized(t) { - let (size, align) = bx.cx().layout_of(t).size_and_align(); - debug!("size_and_align_of_dst t={} info={:?} size: {:?} align: {:?}", - t, info, size, align); - let size = bx.cx().const_usize(size.bytes()); - let align = bx.cx().const_usize(align.abi()); + let layout = bx.cx().layout_of(t); + debug!("size_and_align_of_dst(ty={}, info={:?}): layout: {:?}", + t, info, layout); + if !layout.is_unsized() { + let size = bx.cx().const_usize(layout.size.bytes()); + let align = bx.cx().const_usize(layout.align.abi()); return (size, align); } match t.sty { @@ -42,19 +40,17 @@ pub fn size_and_align_of_dst<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>( (meth::SIZE.get_usize(bx, vtable), meth::ALIGN.get_usize(bx, vtable)) } ty::Slice(_) | ty::Str => { - let unit = t.sequence_element_type(bx.tcx()); + let unit = layout.field(bx.cx(), 0); // 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().layout_of(unit).size_and_align(); - (bx.mul(info.unwrap(), bx.cx().const_usize(size.bytes())), - bx.cx().const_usize(align.abi())) + (bx.mul(info.unwrap(), bx.cx().const_usize(unit.size.bytes())), + bx.cx().const_usize(unit.align.abi())) } _ => { // First get the size of all statically known fields. // Don't use size_of because it also rounds up to alignment, which we // want to avoid, as the unsized field's alignment could be smaller. assert!(!t.is_simd()); - let layout = bx.cx().layout_of(t); debug!("DST {} layout: {:?}", t, layout); let i = layout.fields.count() - 1; diff --git a/src/librustc_codegen_ssa/meth.rs b/src/librustc_codegen_ssa/meth.rs index 06c4f7a87d88..d0b8c166b121 100644 --- a/src/librustc_codegen_ssa/meth.rs +++ b/src/librustc_codegen_ssa/meth.rs @@ -100,15 +100,15 @@ pub fn get_vtable<'tcx, Cx: CodegenMethods<'tcx>>( }) }); - let (size, align) = cx.layout_of(ty).size_and_align(); + let layout = cx.layout_of(ty); // ///////////////////////////////////////////////////////////////////////////////////////////// // If you touch this code, be sure to also make the corresponding changes to // `get_vtable` in rust_mir/interpret/traits.rs // ///////////////////////////////////////////////////////////////////////////////////////////// let components: Vec<_> = [ cx.get_fn(monomorphize::resolve_drop_in_place(cx.tcx(), ty)), - cx.const_usize(size.bytes()), - cx.const_usize(align.abi()) + cx.const_usize(layout.size.bytes()), + cx.const_usize(layout.align.abi()) ].iter().cloned().chain(methods).collect(); let vtable_const = cx.const_struct(&components, false); diff --git a/src/librustc_codegen_ssa/mir/operand.rs b/src/librustc_codegen_ssa/mir/operand.rs index d574d89d67e3..4c92ab7eda5b 100644 --- a/src/librustc_codegen_ssa/mir/operand.rs +++ b/src/librustc_codegen_ssa/mir/operand.rs @@ -11,7 +11,7 @@ use rustc::mir::interpret::{ConstValue, ErrorHandled}; use rustc::mir; use rustc::ty; -use rustc::ty::layout::{self, Align, LayoutOf, TyLayout}; +use rustc::ty::layout::{self, AbiAndPrefAlign, LayoutOf, TyLayout}; use base; use MemFlags; @@ -33,7 +33,7 @@ pub enum OperandValue { /// to be valid for the operand's lifetime. /// The second value, if any, is the extra data (vtable or length) /// which indicates that it refers to an unsized rvalue. - Ref(V, Option, Align), + Ref(V, Option, AbiAndPrefAlign), /// A single LLVM value. Immediate(V), /// A pair of immediate LLVM values. Used by fat pointers too. @@ -348,8 +348,8 @@ impl<'a, 'tcx: 'a, V: CodegenObject> OperandValue { }; // FIXME: choose an appropriate alignment, or use dynamic align somehow - let max_align = Align::from_bits(128, 128).unwrap(); - let min_align = Align::from_bits(8, 8).unwrap(); + let max_align = AbiAndPrefAlign::from_bits(128, 128).unwrap(); + let min_align = AbiAndPrefAlign::from_bits(8, 8).unwrap(); // Allocate an appropriate region on the stack, and copy the value into it let (llsize, _) = glue::size_and_align_of_dst(bx, unsized_ty, Some(llextra)); diff --git a/src/librustc_codegen_ssa/mir/place.rs b/src/librustc_codegen_ssa/mir/place.rs index 5b36ee8fd183..e6216c8724f5 100644 --- a/src/librustc_codegen_ssa/mir/place.rs +++ b/src/librustc_codegen_ssa/mir/place.rs @@ -9,7 +9,7 @@ // except according to those terms. use rustc::ty::{self, Ty}; -use rustc::ty::layout::{self, Align, TyLayout, LayoutOf, VariantIdx, HasTyCtxt}; +use rustc::ty::layout::{self, AbiAndPrefAlign, TyLayout, LayoutOf, VariantIdx, HasTyCtxt}; use rustc::mir; use rustc::mir::tcx::PlaceTy; use MemFlags; @@ -33,14 +33,14 @@ pub struct PlaceRef<'tcx, V> { pub layout: TyLayout<'tcx>, /// What alignment we know for this place - pub align: Align, + pub align: AbiAndPrefAlign, } impl<'a, 'tcx: 'a, V: CodegenObject> PlaceRef<'tcx, V> { pub fn new_sized( llval: V, layout: TyLayout<'tcx>, - align: Align, + align: AbiAndPrefAlign, ) -> PlaceRef<'tcx, V> { assert!(!layout.is_unsized()); PlaceRef { @@ -308,9 +308,8 @@ impl<'a, 'tcx: 'a, V: CodegenObject> PlaceRef<'tcx, V> { // Issue #34427: As workaround for LLVM bug on ARM, // use memset of 0 before assigning niche value. let fill_byte = bx.cx().const_u8(0); - let (size, align) = self.layout.size_and_align(); - let size = bx.cx().const_usize(size.bytes()); - bx.memset(self.llval, fill_byte, size, align, MemFlags::empty()); + let size = bx.cx().const_usize(self.layout.size.bytes()); + bx.memset(self.llval, fill_byte, size, self.align, MemFlags::empty()); } let niche = self.project_field(bx, 0); diff --git a/src/librustc_codegen_ssa/mir/rvalue.rs b/src/librustc_codegen_ssa/mir/rvalue.rs index 6b1efa060fda..167a143ec31e 100644 --- a/src/librustc_codegen_ssa/mir/rvalue.rs +++ b/src/librustc_codegen_ssa/mir/rvalue.rs @@ -496,10 +496,10 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } mir::Rvalue::NullaryOp(mir::NullOp::Box, content_ty) => { - let content_ty: Ty<'tcx> = self.monomorphize(&content_ty); - let (size, align) = bx.cx().layout_of(content_ty).size_and_align(); - let llsize = bx.cx().const_usize(size.bytes()); - let llalign = bx.cx().const_usize(align.abi()); + let content_ty = self.monomorphize(&content_ty); + let content_layout = bx.cx().layout_of(content_ty); + let llsize = bx.cx().const_usize(content_layout.size.bytes()); + let llalign = bx.cx().const_usize(content_layout.align.abi()); let box_layout = bx.cx().layout_of(bx.tcx().mk_box(content_ty)); let llty_ptr = bx.cx().backend_type(box_layout); diff --git a/src/librustc_codegen_ssa/traits/builder.rs b/src/librustc_codegen_ssa/traits/builder.rs index 3757c514d2ce..02be098599b3 100644 --- a/src/librustc_codegen_ssa/traits/builder.rs +++ b/src/librustc_codegen_ssa/traits/builder.rs @@ -15,10 +15,10 @@ use super::intrinsic::IntrinsicCallMethods; use super::type_::ArgTypeMethods; use super::HasCodegen; use common::{AtomicOrdering, AtomicRmwBinOp, IntPredicate, RealPredicate, SynchronizationScope}; -use std::ffi::CStr; use mir::operand::OperandRef; use mir::place::PlaceRef; -use rustc::ty::layout::{Align, Size}; +use rustc::ty::layout::{AbiAndPrefAlign, Size}; +use std::ffi::CStr; use MemFlags; use std::borrow::Cow; @@ -97,17 +97,18 @@ pub trait BuilderMethods<'a, 'tcx: 'a>: fn fneg(&mut self, v: Self::Value) -> Self::Value; fn not(&mut self, v: Self::Value) -> Self::Value; - fn alloca(&mut self, ty: Self::Type, name: &str, align: Align) -> Self::Value; - fn dynamic_alloca(&mut self, ty: Self::Type, name: &str, align: Align) -> Self::Value; + fn alloca(&mut self, ty: Self::Type, name: &str, align: AbiAndPrefAlign) -> Self::Value; + fn dynamic_alloca(&mut self, ty: Self::Type, name: &str, align: AbiAndPrefAlign) + -> Self::Value; fn array_alloca( &mut self, ty: Self::Type, len: Self::Value, name: &str, - align: Align, + align: AbiAndPrefAlign, ) -> Self::Value; - fn load(&mut self, ptr: Self::Value, align: Align) -> Self::Value; + fn load(&mut self, ptr: Self::Value, align: AbiAndPrefAlign) -> Self::Value; fn volatile_load(&mut self, ptr: Self::Value) -> Self::Value; fn atomic_load(&mut self, ptr: Self::Value, order: AtomicOrdering, size: Size) -> Self::Value; fn load_operand(&mut self, place: PlaceRef<'tcx, Self::Value>) @@ -116,12 +117,12 @@ pub trait BuilderMethods<'a, 'tcx: 'a>: fn range_metadata(&mut self, load: Self::Value, range: Range); fn nonnull_metadata(&mut self, load: Self::Value); - fn store(&mut self, val: Self::Value, ptr: Self::Value, align: Align) -> Self::Value; + fn store(&mut self, val: Self::Value, ptr: Self::Value, align: AbiAndPrefAlign) -> Self::Value; fn store_with_flags( &mut self, val: Self::Value, ptr: Self::Value, - align: Align, + align: AbiAndPrefAlign, flags: MemFlags, ) -> Self::Value; fn atomic_store( @@ -174,18 +175,18 @@ pub trait BuilderMethods<'a, 'tcx: 'a>: fn memcpy( &mut self, dst: Self::Value, - dst_align: Align, + dst_align: AbiAndPrefAlign, src: Self::Value, - src_align: Align, + src_align: AbiAndPrefAlign, size: Self::Value, flags: MemFlags, ); fn memmove( &mut self, dst: Self::Value, - dst_align: Align, + dst_align: AbiAndPrefAlign, src: Self::Value, - src_align: Align, + src_align: AbiAndPrefAlign, size: Self::Value, flags: MemFlags, ); @@ -194,7 +195,7 @@ pub trait BuilderMethods<'a, 'tcx: 'a>: ptr: Self::Value, fill_byte: Self::Value, size: Self::Value, - align: Align, + align: AbiAndPrefAlign, flags: MemFlags, ); diff --git a/src/librustc_codegen_ssa/traits/statics.rs b/src/librustc_codegen_ssa/traits/statics.rs index 172c48f8a85f..b66f4378c35f 100644 --- a/src/librustc_codegen_ssa/traits/statics.rs +++ b/src/librustc_codegen_ssa/traits/statics.rs @@ -10,13 +10,23 @@ use super::Backend; use rustc::hir::def_id::DefId; -use rustc::ty::layout::Align; +use rustc::ty::layout::AbiAndPrefAlign; pub trait StaticMethods<'tcx>: Backend<'tcx> { fn static_ptrcast(&self, val: Self::Value, ty: Self::Type) -> Self::Value; fn static_bitcast(&self, val: Self::Value, ty: Self::Type) -> Self::Value; - fn static_addr_of_mut(&self, cv: Self::Value, align: Align, kind: Option<&str>) -> Self::Value; - fn static_addr_of(&self, cv: Self::Value, align: Align, kind: Option<&str>) -> Self::Value; + fn static_addr_of_mut( + &self, + cv: Self::Value, + align: AbiAndPrefAlign, + kind: Option<&str>, + ) -> Self::Value; + fn static_addr_of( + &self, + cv: Self::Value, + align: AbiAndPrefAlign, + kind: Option<&str>, + ) -> Self::Value; fn get_static(&self, def_id: DefId) -> Self::Value; fn codegen_static(&self, def_id: DefId, is_mutable: bool); unsafe fn static_replace_all_uses(&self, old_g: Self::Value, new_g: Self::Value); diff --git a/src/librustc_codegen_ssa/traits/type_.rs b/src/librustc_codegen_ssa/traits/type_.rs index 1aa1f45f5174..275f378495d9 100644 --- a/src/librustc_codegen_ssa/traits/type_.rs +++ b/src/librustc_codegen_ssa/traits/type_.rs @@ -13,7 +13,7 @@ use super::Backend; use super::HasCodegen; use common::{self, TypeKind}; use mir::place::PlaceRef; -use rustc::ty::layout::{self, Align, Size, TyLayout}; +use rustc::ty::layout::{self, AbiAndPrefAlign, Size, TyLayout}; use rustc::ty::{self, Ty}; use rustc::util::nodemap::FxHashMap; use rustc_target::abi::call::{ArgType, CastTarget, FnType, Reg}; @@ -120,7 +120,7 @@ pub trait DerivedTypeMethods<'tcx>: BaseTypeMethods<'tcx> + MiscMethods<'tcx> { } } - fn type_pointee_for_abi_align(&self, align: Align) -> Self::Type { + fn type_pointee_for_abi_align(&self, align: AbiAndPrefAlign) -> Self::Type { // FIXME(eddyb) We could find a better approximation if ity.align < align. let ity = layout::Integer::approximate_abi_align(self, align); self.type_from_integer(ity) @@ -128,7 +128,7 @@ pub trait DerivedTypeMethods<'tcx>: BaseTypeMethods<'tcx> + MiscMethods<'tcx> { /// Return a LLVM type that has at most the required alignment, /// and exactly the required size, as a best-effort padding array. - fn type_padding_filler(&self, size: Size, align: Align) -> Self::Type { + fn type_padding_filler(&self, size: Size, align: AbiAndPrefAlign) -> Self::Type { let unit = layout::Integer::approximate_abi_align(self, align); let size = size.bytes(); let unit_size = unit.size().bytes(); diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index 590834135824..69db638270a5 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -16,7 +16,7 @@ use rustc::hir::def_id::DefId; use rustc::hir::def::Def; use rustc::mir; use rustc::ty::layout::{ - self, Size, Align, HasDataLayout, LayoutOf, TyLayout + self, Size, AbiAndPrefAlign, HasDataLayout, LayoutOf, TyLayout }; use rustc::ty::subst::{Subst, Substs}; use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; @@ -314,9 +314,9 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc &self, metadata: Option>, layout: TyLayout<'tcx>, - ) -> EvalResult<'tcx, Option<(Size, Align)>> { + ) -> EvalResult<'tcx, Option<(Size, AbiAndPrefAlign)>> { if !layout.is_unsized() { - return Ok(Some(layout.size_and_align())); + return Ok(Some((layout.size, layout.align))); } match layout.ty.sty { ty::Adt(..) | ty::Tuple(..) => { @@ -391,8 +391,8 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc ty::Slice(_) | ty::Str => { let len = metadata.expect("slice fat ptr must have vtable").to_usize(self)?; - let (elem_size, align) = layout.field(self, 0)?.size_and_align(); - Ok(Some((elem_size * len, align))) + let elem = layout.field(self, 0)?; + Ok(Some((elem.size * len, elem.align))) } ty::Foreign(_) => { @@ -406,7 +406,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc pub fn size_and_align_of_mplace( &self, mplace: MPlaceTy<'tcx, M::PointerTag> - ) -> EvalResult<'tcx, Option<(Size, Align)>> { + ) -> EvalResult<'tcx, Option<(Size, AbiAndPrefAlign)>> { self.size_and_align_of(mplace.meta, mplace.layout) } diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index 7dd42c666496..dbb0e5228748 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -21,7 +21,7 @@ use std::ptr; use std::borrow::Cow; use rustc::ty::{self, Instance, ParamEnv, query::TyCtxtAt}; -use rustc::ty::layout::{self, Align, TargetDataLayout, Size, HasDataLayout}; +use rustc::ty::layout::{self, AbiAndPrefAlign, TargetDataLayout, Size, HasDataLayout}; pub use rustc::mir::interpret::{truncate, write_target_uint, read_target_uint}; use rustc_data_structures::fx::{FxHashSet, FxHashMap}; @@ -71,7 +71,7 @@ pub struct Memory<'a, 'mir, 'tcx: 'a + 'mir, M: Machine<'a, 'mir, 'tcx>> { /// To be able to compare pointers with NULL, and to check alignment for accesses /// to ZSTs (where pointers may dangle), we keep track of the size even for allocations /// that do not exist any more. - dead_alloc_map: FxHashMap, + dead_alloc_map: FxHashMap, /// Lets us implement `HasDataLayout`, which is awfully convenient. pub(super) tcx: TyCtxtAt<'a, 'tcx, 'tcx>, @@ -130,7 +130,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { pub fn allocate( &mut self, size: Size, - align: Align, + align: AbiAndPrefAlign, kind: MemoryKind, ) -> EvalResult<'tcx, Pointer> { Ok(Pointer::from(self.allocate_with(Allocation::undef(size, align), kind)?)) @@ -140,9 +140,9 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { &mut self, ptr: Pointer, old_size: Size, - old_align: Align, + old_align: AbiAndPrefAlign, new_size: Size, - new_align: Align, + new_align: AbiAndPrefAlign, kind: MemoryKind, ) -> EvalResult<'tcx, Pointer> { if ptr.offset.bytes() != 0 { @@ -179,7 +179,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { pub fn deallocate( &mut self, ptr: Pointer, - size_and_align: Option<(Size, Align)>, + size_and_align: Option<(Size, AbiAndPrefAlign)>, kind: MemoryKind, ) -> EvalResult<'tcx> { trace!("deallocating: {}", ptr.alloc_id); @@ -244,7 +244,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { pub fn check_align( &self, ptr: Scalar, - required_align: Align + required_align: AbiAndPrefAlign ) -> EvalResult<'tcx> { // Check non-NULL/Undef, extract offset let (offset, alloc_align) = match ptr { @@ -279,7 +279,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { } else { let has = offset % required_align.abi(); err!(AlignmentCheckFailed { - has: Align::from_bytes(has, has).unwrap(), + has: AbiAndPrefAlign::from_bytes(has, has).unwrap(), required: required_align, }) } @@ -443,13 +443,15 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { } } - pub fn get_size_and_align(&self, id: AllocId) -> (Size, Align) { + pub fn get_size_and_align(&self, id: AllocId) -> (Size, AbiAndPrefAlign) { if let Ok(alloc) = self.get(id) { return (Size::from_bytes(alloc.bytes.len() as u64), alloc.align); } // Could also be a fn ptr or extern static match self.tcx.alloc_map.lock().get(id) { - Some(AllocType::Function(..)) => (Size::ZERO, Align::from_bytes(1, 1).unwrap()), + Some(AllocType::Function(..)) => { + (Size::ZERO, AbiAndPrefAlign::from_bytes(1, 1).unwrap()) + } Some(AllocType::Static(did)) => { // The only way `get` couldn't have worked here is if this is an extern static assert!(self.tcx.is_foreign_item(did)); @@ -622,7 +624,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { &self, ptr: Pointer, size: Size, - align: Align, + align: AbiAndPrefAlign, check_defined_and_ptr: bool, ) -> EvalResult<'tcx, &[u8]> { assert_ne!(size.bytes(), 0, "0-sized accesses should never even get a `Pointer`"); @@ -651,7 +653,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { &self, ptr: Pointer, size: Size, - align: Align + align: AbiAndPrefAlign ) -> EvalResult<'tcx, &[u8]> { self.get_bytes_internal(ptr, size, align, true) } @@ -663,7 +665,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { &self, ptr: Pointer, size: Size, - align: Align + align: AbiAndPrefAlign ) -> EvalResult<'tcx, &[u8]> { self.get_bytes_internal(ptr, size, align, false) } @@ -674,7 +676,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { &mut self, ptr: Pointer, size: Size, - align: Align, + align: AbiAndPrefAlign, ) -> EvalResult<'tcx, &mut [u8]> { assert_ne!(size.bytes(), 0, "0-sized accesses should never even get a `Pointer`"); self.check_align(ptr.into(), align)?; @@ -747,9 +749,9 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { pub fn copy( &mut self, src: Scalar, - src_align: Align, + src_align: AbiAndPrefAlign, dest: Scalar, - dest_align: Align, + dest_align: AbiAndPrefAlign, size: Size, nonoverlapping: bool, ) -> EvalResult<'tcx> { @@ -759,9 +761,9 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { pub fn copy_repeatedly( &mut self, src: Scalar, - src_align: Align, + src_align: AbiAndPrefAlign, dest: Scalar, - dest_align: Align, + dest_align: AbiAndPrefAlign, size: Size, length: u64, nonoverlapping: bool, @@ -863,7 +865,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { allow_ptr_and_undef: bool, ) -> EvalResult<'tcx> { // Empty accesses don't need to be valid pointers, but they should still be non-NULL - let align = Align::from_bytes(1, 1).unwrap(); + let align = AbiAndPrefAlign::from_bytes(1, 1).unwrap(); if size.bytes() == 0 { self.check_align(ptr, align)?; return Ok(()); @@ -881,7 +883,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { pub fn read_bytes(&self, ptr: Scalar, size: Size) -> EvalResult<'tcx, &[u8]> { // Empty accesses don't need to be valid pointers, but they should still be non-NULL - let align = Align::from_bytes(1, 1).unwrap(); + let align = AbiAndPrefAlign::from_bytes(1, 1).unwrap(); if size.bytes() == 0 { self.check_align(ptr, align)?; return Ok(&[]); @@ -891,7 +893,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { pub fn write_bytes(&mut self, ptr: Scalar, src: &[u8]) -> EvalResult<'tcx> { // Empty accesses don't need to be valid pointers, but they should still be non-NULL - let align = Align::from_bytes(1, 1).unwrap(); + let align = AbiAndPrefAlign::from_bytes(1, 1).unwrap(); if src.is_empty() { self.check_align(ptr, align)?; return Ok(()); @@ -908,7 +910,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { count: Size ) -> EvalResult<'tcx> { // Empty accesses don't need to be valid pointers, but they should still be non-NULL - let align = Align::from_bytes(1, 1).unwrap(); + let align = AbiAndPrefAlign::from_bytes(1, 1).unwrap(); if count.bytes() == 0 { self.check_align(ptr, align)?; return Ok(()); @@ -924,7 +926,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { pub fn read_scalar( &self, ptr: Pointer, - ptr_align: Align, + ptr_align: AbiAndPrefAlign, size: Size ) -> EvalResult<'tcx, ScalarMaybeUndef> { // get_bytes_unchecked tests alignment and relocation edges @@ -961,7 +963,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { pub fn read_ptr_sized( &self, ptr: Pointer, - ptr_align: Align + ptr_align: AbiAndPrefAlign ) -> EvalResult<'tcx, ScalarMaybeUndef> { self.read_scalar(ptr, ptr_align, self.pointer_size()) } @@ -970,7 +972,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { pub fn write_scalar( &mut self, ptr: Pointer, - ptr_align: Align, + ptr_align: AbiAndPrefAlign, val: ScalarMaybeUndef, type_size: Size, ) -> EvalResult<'tcx> { @@ -1017,14 +1019,14 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { pub fn write_ptr_sized( &mut self, ptr: Pointer, - ptr_align: Align, + ptr_align: AbiAndPrefAlign, val: ScalarMaybeUndef ) -> EvalResult<'tcx> { let ptr_size = self.pointer_size(); self.write_scalar(ptr.into(), ptr_align, val, ptr_size) } - fn int_align(&self, size: Size) -> Align { + fn int_align(&self, size: Size) -> AbiAndPrefAlign { // We assume pointer-sized integers have the same alignment as pointers. // We also assume signed and unsigned integers of the same size have the same alignment. let ity = match size.bytes() { diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs index 9f248d463507..bd713d4462d0 100644 --- a/src/librustc_mir/interpret/place.rs +++ b/src/librustc_mir/interpret/place.rs @@ -18,7 +18,7 @@ use std::hash::Hash; use rustc::hir; use rustc::mir; use rustc::ty::{self, Ty}; -use rustc::ty::layout::{self, Size, Align, LayoutOf, TyLayout, HasDataLayout, VariantIdx}; +use rustc::ty::layout::{self, Size, AbiAndPrefAlign, LayoutOf, TyLayout, HasDataLayout, VariantIdx}; use super::{ GlobalId, AllocId, Allocation, Scalar, EvalResult, Pointer, PointerArithmetic, @@ -32,7 +32,7 @@ pub struct MemPlace { /// be turned back into a reference before ever being dereferenced. /// However, it may never be undef. pub ptr: Scalar, - pub align: Align, + pub align: AbiAndPrefAlign, /// Metadata for unsized places. Interpretation is up to the type. /// Must not be present for sized types, but can be missing for unsized types /// (e.g. `extern type`). @@ -116,7 +116,7 @@ impl MemPlace { } #[inline(always)] - pub fn from_scalar_ptr(ptr: Scalar, align: Align) -> Self { + pub fn from_scalar_ptr(ptr: Scalar, align: AbiAndPrefAlign) -> Self { MemPlace { ptr, align, @@ -127,16 +127,16 @@ impl MemPlace { /// Produces a Place that will error if attempted to be read from or written to #[inline(always)] pub fn null(cx: &impl HasDataLayout) -> Self { - Self::from_scalar_ptr(Scalar::ptr_null(cx), Align::from_bytes(1, 1).unwrap()) + Self::from_scalar_ptr(Scalar::ptr_null(cx), AbiAndPrefAlign::from_bytes(1, 1).unwrap()) } #[inline(always)] - pub fn from_ptr(ptr: Pointer, align: Align) -> Self { + pub fn from_ptr(ptr: Pointer, align: AbiAndPrefAlign) -> Self { Self::from_scalar_ptr(ptr.into(), align) } #[inline(always)] - pub fn to_scalar_ptr_align(self) -> (Scalar, Align) { + pub fn to_scalar_ptr_align(self) -> (Scalar, AbiAndPrefAlign) { assert!(self.meta.is_none()); (self.ptr, self.align) } @@ -230,12 +230,12 @@ impl<'tcx, Tag: ::std::fmt::Debug> Place { } #[inline(always)] - pub fn from_scalar_ptr(ptr: Scalar, align: Align) -> Self { + pub fn from_scalar_ptr(ptr: Scalar, align: AbiAndPrefAlign) -> Self { Place::Ptr(MemPlace::from_scalar_ptr(ptr, align)) } #[inline(always)] - pub fn from_ptr(ptr: Pointer, align: Align) -> Self { + pub fn from_ptr(ptr: Pointer, align: AbiAndPrefAlign) -> Self { Place::Ptr(MemPlace::from_ptr(ptr, align)) } @@ -249,7 +249,7 @@ impl<'tcx, Tag: ::std::fmt::Debug> Place { } #[inline] - pub fn to_scalar_ptr_align(self) -> (Scalar, Align) { + pub fn to_scalar_ptr_align(self) -> (Scalar, AbiAndPrefAlign) { self.to_mem_place().to_scalar_ptr_align() } diff --git a/src/librustc_mir/interpret/snapshot.rs b/src/librustc_mir/interpret/snapshot.rs index 4b63335ad964..56475dffae42 100644 --- a/src/librustc_mir/interpret/snapshot.rs +++ b/src/librustc_mir/interpret/snapshot.rs @@ -16,7 +16,7 @@ use rustc::mir::interpret::{ }; use rustc::ty::{self, TyCtxt}; -use rustc::ty::layout::Align; +use rustc::ty::layout::AbiAndPrefAlign; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::indexed_vec::IndexVec; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; @@ -276,7 +276,7 @@ struct AllocationSnapshot<'a> { bytes: &'a [u8], relocations: Relocations<(), AllocIdSnapshot<'a>>, undef_mask: &'a UndefMask, - align: &'a Align, + align: &'a AbiAndPrefAlign, mutability: &'a Mutability, } diff --git a/src/librustc_mir/interpret/traits.rs b/src/librustc_mir/interpret/traits.rs index c5366a5ce6a4..f1bedd181e9e 100644 --- a/src/librustc_mir/interpret/traits.rs +++ b/src/librustc_mir/interpret/traits.rs @@ -9,7 +9,7 @@ // except according to those terms. use rustc::ty::{self, Ty}; -use rustc::ty::layout::{Size, Align, LayoutOf}; +use rustc::ty::layout::{Size, AbiAndPrefAlign, LayoutOf}; use rustc::mir::interpret::{Scalar, Pointer, EvalResult, PointerArithmetic}; use super::{EvalContext, Machine, MemoryKind}; @@ -101,7 +101,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> pub fn read_size_and_align_from_vtable( &self, vtable: Pointer, - ) -> EvalResult<'tcx, (Size, Align)> { + ) -> EvalResult<'tcx, (Size, AbiAndPrefAlign)> { let pointer_size = self.pointer_size(); let pointer_align = self.tcx.data_layout.pointer_align; let size = self.memory.read_ptr_sized(vtable.offset(pointer_size, self)?,pointer_align)? @@ -110,6 +110,6 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> vtable.offset(pointer_size * 2, self)?, pointer_align )?.to_bits(pointer_size)? as u64; - Ok((Size::from_bytes(size), Align::from_bytes(align, align).unwrap())) + Ok((Size::from_bytes(size), AbiAndPrefAlign::from_bytes(align, align).unwrap())) } } diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index ad7ffd291bed..41358fe0d848 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -13,7 +13,7 @@ use std::hash::Hash; use std::ops::RangeInclusive; use syntax_pos::symbol::Symbol; -use rustc::ty::layout::{self, Size, Align, TyLayout, LayoutOf, VariantIdx}; +use rustc::ty::layout::{self, Size, AbiAndPrefAlign, TyLayout, LayoutOf, VariantIdx}; use rustc::ty; use rustc_data_structures::fx::FxHashSet; use rustc::mir::interpret::{ @@ -355,7 +355,7 @@ impl<'rt, 'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> // for the purpose of validity, consider foreign types to have // alignment and size determined by the layout (size will be 0, // alignment should take attributes into account). - .unwrap_or_else(|| layout.size_and_align()); + .unwrap_or_else(|| (layout.size, layout.align)); match self.ecx.memory.check_align(ptr, align) { Ok(_) => {}, Err(err) => { @@ -463,7 +463,7 @@ impl<'rt, 'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> // for function pointers. let non_null = self.ecx.memory.check_align( - Scalar::Ptr(ptr), Align::from_bytes(1, 1).unwrap() + Scalar::Ptr(ptr), AbiAndPrefAlign::from_bytes(1, 1).unwrap() ).is_ok() || self.ecx.memory.get_fn(ptr).is_ok(); if !non_null { diff --git a/src/librustc_target/abi/call/mod.rs b/src/librustc_target/abi/call/mod.rs index 8f9ef2544e60..289a76eae8f5 100644 --- a/src/librustc_target/abi/call/mod.rs +++ b/src/librustc_target/abi/call/mod.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use abi::{self, Abi, Align, FieldPlacement, Size}; +use abi::{self, Abi, AbiAndPrefAlign, FieldPlacement, Size}; use abi::{HasDataLayout, LayoutOf, TyLayout, TyLayoutMethods}; use spec::HasTargetSpec; @@ -80,7 +80,7 @@ mod attr_impl { pub struct ArgAttributes { pub regular: ArgAttribute, pub pointee_size: Size, - pub pointee_align: Option + pub pointee_align: Option } impl ArgAttributes { @@ -137,7 +137,7 @@ impl Reg { } impl Reg { - pub fn align(&self, cx: &C) -> Align { + pub fn align(&self, cx: &C) -> AbiAndPrefAlign { let dl = cx.data_layout(); match self.kind { RegKind::Integer => { @@ -188,7 +188,7 @@ impl From for Uniform { } impl Uniform { - pub fn align(&self, cx: &C) -> Align { + pub fn align(&self, cx: &C) -> AbiAndPrefAlign { self.unit.align(cx) } } @@ -230,7 +230,7 @@ impl CastTarget { .abi_align(self.rest.align(cx)) + self.rest.total } - pub fn align(&self, cx: &C) -> Align { + pub fn align(&self, cx: &C) -> AbiAndPrefAlign { self.prefix.iter() .filter_map(|x| x.map(|kind| Reg { kind, size: self.prefix_chunk }.align(cx))) .fold(cx.data_layout().aggregate_align.max(self.rest.align(cx)), diff --git a/src/librustc_target/abi/call/powerpc64.rs b/src/librustc_target/abi/call/powerpc64.rs index f7ef1390f14d..93b8f79ccdc0 100644 --- a/src/librustc_target/abi/call/powerpc64.rs +++ b/src/librustc_target/abi/call/powerpc64.rs @@ -13,7 +13,7 @@ // need to be fixed when PowerPC vector support is added. use abi::call::{FnType, ArgType, Reg, RegKind, Uniform}; -use abi::{Align, Endian, HasDataLayout, LayoutOf, TyLayout, TyLayoutMethods}; +use abi::{AbiAndPrefAlign, Endian, HasDataLayout, LayoutOf, TyLayout, TyLayoutMethods}; use spec::HasTargetSpec; #[derive(Debug, Clone, Copy, PartialEq)] @@ -120,7 +120,7 @@ fn classify_arg_ty<'a, Ty, C>(cx: &C, arg: &mut ArgType<'a, Ty>, abi: ABI) } else { // Aggregates larger than a doubleword should be padded // at the tail to fill out a whole number of doublewords. - let align = Align::from_bits(64, 64).unwrap(); + let align = AbiAndPrefAlign::from_bits(64, 64).unwrap(); (Reg::i64(), size.abi_align(align)) }; diff --git a/src/librustc_target/abi/mod.rs b/src/librustc_target/abi/mod.rs index 22afb0da05bc..7b0b34e207ce 100644 --- a/src/librustc_target/abi/mod.rs +++ b/src/librustc_target/abi/mod.rs @@ -24,20 +24,21 @@ pub mod call; /// for a target, which contains everything needed to compute layouts. pub struct TargetDataLayout { pub endian: Endian, - pub i1_align: Align, - pub i8_align: Align, - pub i16_align: Align, - pub i32_align: Align, - pub i64_align: Align, - pub i128_align: Align, - pub f32_align: Align, - pub f64_align: Align, + pub i1_align: AbiAndPrefAlign, + pub i8_align: AbiAndPrefAlign, + pub i16_align: AbiAndPrefAlign, + pub i32_align: AbiAndPrefAlign, + pub i64_align: AbiAndPrefAlign, + pub i128_align: AbiAndPrefAlign, + pub f32_align: AbiAndPrefAlign, + pub f64_align: AbiAndPrefAlign, pub pointer_size: Size, - pub pointer_align: Align, - pub aggregate_align: Align, + pub pointer_align: AbiAndPrefAlign, + pub aggregate_align: AbiAndPrefAlign, /// Alignments for vector types. - pub vector_align: Vec<(Size, Align)>, + pub vector_align: Vec<(Size, AbiAndPrefAlign)>, + pub instruction_address_space: u32, } @@ -46,20 +47,20 @@ impl Default for TargetDataLayout { fn default() -> TargetDataLayout { TargetDataLayout { endian: Endian::Big, - i1_align: Align::from_bits(8, 8).unwrap(), - i8_align: Align::from_bits(8, 8).unwrap(), - i16_align: Align::from_bits(16, 16).unwrap(), - i32_align: Align::from_bits(32, 32).unwrap(), - i64_align: Align::from_bits(32, 64).unwrap(), - i128_align: Align::from_bits(32, 64).unwrap(), - f32_align: Align::from_bits(32, 32).unwrap(), - f64_align: Align::from_bits(64, 64).unwrap(), + i1_align: AbiAndPrefAlign::from_bits(8, 8).unwrap(), + i8_align: AbiAndPrefAlign::from_bits(8, 8).unwrap(), + i16_align: AbiAndPrefAlign::from_bits(16, 16).unwrap(), + i32_align: AbiAndPrefAlign::from_bits(32, 32).unwrap(), + i64_align: AbiAndPrefAlign::from_bits(32, 64).unwrap(), + i128_align: AbiAndPrefAlign::from_bits(32, 64).unwrap(), + f32_align: AbiAndPrefAlign::from_bits(32, 32).unwrap(), + f64_align: AbiAndPrefAlign::from_bits(64, 64).unwrap(), pointer_size: Size::from_bits(64), - pointer_align: Align::from_bits(64, 64).unwrap(), - aggregate_align: Align::from_bits(0, 64).unwrap(), + pointer_align: AbiAndPrefAlign::from_bits(64, 64).unwrap(), + aggregate_align: AbiAndPrefAlign::from_bits(0, 64).unwrap(), vector_align: vec![ - (Size::from_bits(64), Align::from_bits(64, 64).unwrap()), - (Size::from_bits(128), Align::from_bits(128, 128).unwrap()) + (Size::from_bits(64), AbiAndPrefAlign::from_bits(64, 64).unwrap()), + (Size::from_bits(128), AbiAndPrefAlign::from_bits(128, 128).unwrap()) ], instruction_address_space: 0, } @@ -96,7 +97,7 @@ impl TargetDataLayout { } let abi = parse_bits(s[0], "alignment", cause)?; let pref = s.get(1).map_or(Ok(abi), |pref| parse_bits(pref, "alignment", cause))?; - Align::from_bits(abi, pref).map_err(|err| { + AbiAndPrefAlign::from_bits(abi, pref).map_err(|err| { format!("invalid alignment for `{}` in \"data-layout\": {}", cause, err) }) @@ -205,7 +206,7 @@ impl TargetDataLayout { } } - pub fn vector_align(&self, vec_size: Size) -> Align { + pub fn vector_align(&self, vec_size: Size) -> AbiAndPrefAlign { for &(size, align) in &self.vector_align { if size == vec_size { return align; @@ -214,7 +215,7 @@ impl TargetDataLayout { // Default to natural alignment, which is what LLVM does. // That is, use the size, rounded up to a power of 2. let align = vec_size.bytes().next_power_of_two(); - Align::from_bytes(align, align).unwrap() + AbiAndPrefAlign::from_bytes(align, align).unwrap() } } @@ -270,13 +271,13 @@ impl Size { } #[inline] - pub fn abi_align(self, align: Align) -> Size { + pub fn abi_align(self, align: AbiAndPrefAlign) -> Size { let mask = align.abi() - 1; Size::from_bytes((self.bytes() + mask) & !mask) } #[inline] - pub fn is_abi_aligned(self, align: Align) -> bool { + pub fn is_abi_aligned(self, align: AbiAndPrefAlign) -> bool { let mask = align.abi() - 1; self.bytes() & mask == 0 } @@ -358,23 +359,23 @@ impl AddAssign for Size { } } -/// Alignment of a type in bytes, both ABI-mandated and preferred. +/// Alignments of a type in bytes, both ABI-mandated and preferred. /// Each field is a power of two, giving the alignment a maximum value /// of 2(28 - 1), which is limited by LLVM to a /// maximum capacity of 229 or 536870912. #[derive(Copy, Clone, PartialEq, Eq, Ord, PartialOrd, Hash, Debug, RustcEncodable, RustcDecodable)] -pub struct Align { +pub struct AbiAndPrefAlign { abi_pow2: u8, pref_pow2: u8, } -impl Align { - pub fn from_bits(abi: u64, pref: u64) -> Result { - Align::from_bytes(Size::from_bits(abi).bytes(), +impl AbiAndPrefAlign { + pub fn from_bits(abi: u64, pref: u64) -> Result { + AbiAndPrefAlign::from_bytes(Size::from_bits(abi).bytes(), Size::from_bits(pref).bytes()) } - pub fn from_bytes(abi: u64, pref: u64) -> Result { + pub fn from_bytes(abi: u64, pref: u64) -> Result { let log2 = |align: u64| { // Treat an alignment of 0 bytes like 1-byte alignment. if align == 0 { @@ -396,7 +397,7 @@ impl Align { } }; - Ok(Align { + Ok(AbiAndPrefAlign { abi_pow2: log2(abi)?, pref_pow2: log2(pref)?, }) @@ -418,15 +419,15 @@ impl Align { self.pref() * 8 } - pub fn min(self, other: Align) -> Align { - Align { + pub fn min(self, other: AbiAndPrefAlign) -> AbiAndPrefAlign { + AbiAndPrefAlign { abi_pow2: cmp::min(self.abi_pow2, other.abi_pow2), pref_pow2: cmp::min(self.pref_pow2, other.pref_pow2), } } - pub fn max(self, other: Align) -> Align { - Align { + pub fn max(self, other: AbiAndPrefAlign) -> AbiAndPrefAlign { + AbiAndPrefAlign { abi_pow2: cmp::max(self.abi_pow2, other.abi_pow2), pref_pow2: cmp::max(self.pref_pow2, other.pref_pow2), } @@ -436,9 +437,9 @@ impl Align { /// (the largest power of two that the offset is a multiple of). /// /// NB: for an offset of `0`, this happens to return `2^64`. - pub fn max_for_offset(offset: Size) -> Align { + pub fn max_for_offset(offset: Size) -> AbiAndPrefAlign { let pow2 = offset.bytes().trailing_zeros() as u8; - Align { + AbiAndPrefAlign { abi_pow2: pow2, pref_pow2: pow2, } @@ -446,8 +447,8 @@ impl Align { /// Lower the alignment, if necessary, such that the given offset /// is aligned to it (the offset is a multiple of the alignment). - pub fn restrict_for_offset(self, offset: Size) -> Align { - self.min(Align::max_for_offset(offset)) + pub fn restrict_for_offset(self, offset: Size) -> AbiAndPrefAlign { + self.min(AbiAndPrefAlign::max_for_offset(offset)) } } @@ -472,7 +473,7 @@ impl Integer { } } - pub fn align(self, cx: &C) -> Align { + pub fn align(self, cx: &C) -> AbiAndPrefAlign { let dl = cx.data_layout(); match self { @@ -507,7 +508,7 @@ impl Integer { } /// Find the smallest integer with the given alignment. - pub fn for_abi_align(cx: &C, align: Align) -> Option { + pub fn for_abi_align(cx: &C, align: AbiAndPrefAlign) -> Option { let dl = cx.data_layout(); let wanted = align.abi(); @@ -520,7 +521,7 @@ impl Integer { } /// Find the largest integer with the given alignment or less. - pub fn approximate_abi_align(cx: &C, align: Align) -> Integer { + pub fn approximate_abi_align(cx: &C, align: AbiAndPrefAlign) -> Integer { let dl = cx.data_layout(); let wanted = align.abi(); @@ -597,7 +598,7 @@ impl<'a, 'tcx> Primitive { } } - pub fn align(self, cx: &C) -> Align { + pub fn align(self, cx: &C) -> AbiAndPrefAlign { let dl = cx.data_layout(); match self { @@ -868,7 +869,7 @@ pub struct LayoutDetails { pub variants: Variants, pub fields: FieldPlacement, pub abi: Abi, - pub align: Align, + pub align: AbiAndPrefAlign, pub size: Size } @@ -949,8 +950,4 @@ impl<'a, Ty> TyLayout<'a, Ty> { Abi::Aggregate { sized } => sized && self.size.bytes() == 0 } } - - pub fn size_and_align(&self) -> (Size, Align) { - (self.size, self.align) - } }