Skip to content

Commit 7339fc5

Browse files
authored
Rollup merge of rust-lang#152929 - scottmcm:better-alignment-ranges, r=mati865
Tighten the `!range` bounds on alignments in vtables Right now we're only telling LLVM that they're non-zero, but alignments must be powers of two so can't be more than `isize::MAX+1`. And we actually never emit anything beyond LLVM's limit of 2²⁹, so outside of 16-bit targets the limit is that. (Pulled out from rust-lang#152867 which is starting to have too much in it.)
2 parents 3fc3732 + 0187acc commit 7339fc5

File tree

4 files changed

+24
-7
lines changed

4 files changed

+24
-7
lines changed

‎compiler/rustc_abi/src/lib.rs‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1036,6 +1036,19 @@ impl Align {
10361036
// LLVM has a maximal supported alignment of 2^29, we inherit that.
10371037
pub const MAX: Align = Align { pow2: 29 };
10381038

1039+
/// Either `1 << (pointer_bits - 1)` or [`Align::MAX`], whichever is smaller.
1040+
#[inline]
1041+
pub fn max_for_target(tdl: &TargetDataLayout) -> Align {
1042+
let pointer_bits = tdl.pointer_size().bits();
1043+
if let Ok(pointer_bits) = u8::try_from(pointer_bits)
1044+
&& pointer_bits <= Align::MAX.pow2
1045+
{
1046+
Align { pow2: pointer_bits - 1 }
1047+
} else {
1048+
Align::MAX
1049+
}
1050+
}
1051+
10391052
#[inline]
10401053
pub fn from_bits(bits: u64) -> Result<Align, AlignFromBytesError> {
10411054
Align::from_bytes(Size::from_bits(bits).bytes())

‎compiler/rustc_codegen_ssa/src/mir/intrinsic.rs‎

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use rustc_abi::WrappingRange;
1+
use rustc_abi::{Align, WrappingRange};
22
use rustc_middle::mir::SourceInfo;
33
use rustc_middle::ty::{self, Ty, TyCtxt};
44
use rustc_middle::{bug, span_bug};
@@ -179,9 +179,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
179179
let size_bound = bx.data_layout().ptr_sized_integer().signed_max() as u128;
180180
bx.range_metadata(value, WrappingRange { start: 0, end: size_bound });
181181
}
182-
// Alignment is always nonzero.
182+
// Alignment is always a power of two, thus 1..=0x800…000,
183+
// but also bounded by the maximum we support in type layout.
183184
sym::vtable_align => {
184-
bx.range_metadata(value, WrappingRange { start: 1, end: !0 })
185+
let align_bound = Align::max_for_target(bx.data_layout()).bytes().into();
186+
bx.range_metadata(value, WrappingRange { start: 1, end: align_bound })
185187
}
186188
_ => {}
187189
}

‎compiler/rustc_codegen_ssa/src/size_of_val.rs‎

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! Computing the size and alignment of a value.
22
3-
use rustc_abi::WrappingRange;
3+
use rustc_abi::{Align, WrappingRange};
44
use rustc_hir::LangItem;
55
use rustc_middle::bug;
66
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>>(
3636
// Size is always <= isize::MAX.
3737
let size_bound = bx.data_layout().ptr_sized_integer().signed_max() as u128;
3838
bx.range_metadata(size, WrappingRange { start: 0, end: size_bound });
39-
// Alignment is always nonzero.
40-
bx.range_metadata(align, WrappingRange { start: 1, end: !0 });
39+
// Alignment is always a power of two, thus 1..=0x800…000,
40+
// but also bounded by the maximum we support in type layout.
41+
let align_bound = Align::max_for_target(bx.data_layout()).bytes().into();
42+
bx.range_metadata(align, WrappingRange { start: 1, end: align_bound });
4143

4244
(size, align)
4345
}

‎tests/codegen-llvm/dst-vtable-align-nonzero.rs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,4 +64,4 @@ pub unsafe fn align_load_from_vtable_align_intrinsic(x: &dyn Trait) -> usize {
6464
core::intrinsics::vtable_align(vtable)
6565
}
6666

67-
// CHECK: [[RANGE_META]] = !{[[USIZE]] 1, [[USIZE]] 0}
67+
// CHECK: [[RANGE_META]] = !{[[USIZE]] 1, [[USIZE]] [[#0x20000001]]

0 commit comments

Comments
 (0)