Include the Align::MAX limit in the !range metadata for loading alignment from a vtable

This commit is contained in:
Scott McMurray
2026-02-19 10:45:18 -08:00
parent ef70767064
commit 0187acccad
4 changed files with 24 additions and 7 deletions
+13
View File
@@ -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, AlignFromBytesError> {
Align::from_bytes(Size::from_bits(bits).bytes())
@@ -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 @@ pub fn codegen_intrinsic_call(
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 })
}
_ => {}
}
@@ -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)
}
@@ -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]]