diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index 88f8b7cc51704..2a783cd73d9de 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -1036,6 +1036,19 @@ impl Align { // LLVM has a maximal supported alignment of 2^29, we inherit that. pub const MAX: Align = Align { pow2: 29 }; + /// Either `1 << (pointer_bits - 1)` or [`Align::MAX`], whichever is smaller. + #[inline] + pub fn max_for_target(tdl: &TargetDataLayout) -> Align { + let pointer_bits = tdl.pointer_size().bits(); + if let Ok(pointer_bits) = u8::try_from(pointer_bits) + && pointer_bits <= Align::MAX.pow2 + { + Align { pow2: pointer_bits - 1 } + } else { + Align::MAX + } + } + #[inline] pub fn from_bits(bits: u64) -> Result { Align::from_bytes(Size::from_bits(bits).bytes()) diff --git a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs index f5ee9406f4bf1..fd0c7c656ac21 100644 --- a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs +++ b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs @@ -1,4 +1,4 @@ -use rustc_abi::WrappingRange; +use rustc_abi::{Align, WrappingRange}; use rustc_middle::mir::SourceInfo; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::{bug, span_bug}; @@ -179,9 +179,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let size_bound = bx.data_layout().ptr_sized_integer().signed_max() as u128; bx.range_metadata(value, WrappingRange { start: 0, end: size_bound }); } - // Alignment is always nonzero. + // Alignment is always a power of two, thus 1..=0x800…000, + // but also bounded by the maximum we support in type layout. sym::vtable_align => { - bx.range_metadata(value, WrappingRange { start: 1, end: !0 }) + let align_bound = Align::max_for_target(bx.data_layout()).bytes().into(); + bx.range_metadata(value, WrappingRange { start: 1, end: align_bound }) } _ => {} } diff --git a/compiler/rustc_codegen_ssa/src/size_of_val.rs b/compiler/rustc_codegen_ssa/src/size_of_val.rs index e1bd8014d7a2f..52ffc321cbb6f 100644 --- a/compiler/rustc_codegen_ssa/src/size_of_val.rs +++ b/compiler/rustc_codegen_ssa/src/size_of_val.rs @@ -1,6 +1,6 @@ //! Computing the size and alignment of a value. -use rustc_abi::WrappingRange; +use rustc_abi::{Align, WrappingRange}; use rustc_hir::LangItem; use rustc_middle::bug; use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths}; @@ -36,8 +36,10 @@ pub fn size_and_align_of_dst<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( // Size is always <= isize::MAX. let size_bound = bx.data_layout().ptr_sized_integer().signed_max() as u128; bx.range_metadata(size, WrappingRange { start: 0, end: size_bound }); - // Alignment is always nonzero. - bx.range_metadata(align, WrappingRange { start: 1, end: !0 }); + // Alignment is always a power of two, thus 1..=0x800…000, + // but also bounded by the maximum we support in type layout. + let align_bound = Align::max_for_target(bx.data_layout()).bytes().into(); + bx.range_metadata(align, WrappingRange { start: 1, end: align_bound }); (size, align) } diff --git a/tests/codegen-llvm/dst-vtable-align-nonzero.rs b/tests/codegen-llvm/dst-vtable-align-nonzero.rs index 1404bd64f500c..2eee91876683c 100644 --- a/tests/codegen-llvm/dst-vtable-align-nonzero.rs +++ b/tests/codegen-llvm/dst-vtable-align-nonzero.rs @@ -64,4 +64,4 @@ pub unsafe fn align_load_from_vtable_align_intrinsic(x: &dyn Trait) -> usize { core::intrinsics::vtable_align(vtable) } -// CHECK: [[RANGE_META]] = !{[[USIZE]] 1, [[USIZE]] 0} +// CHECK: [[RANGE_META]] = !{[[USIZE]] 1, [[USIZE]] [[#0x20000001]]