Skip to content

Commit 9e5d497

Browse files
author
Lukas Markeffsky
committed
fix const align_offset implementation
1 parent 8717455 commit 9e5d497

File tree

2 files changed

+69
-44
lines changed

2 files changed

+69
-44
lines changed

compiler/rustc_const_eval/src/const_eval/machine.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -278,9 +278,8 @@ impl<'mir, 'tcx: 'mir> CompileTimeEvalContext<'mir, 'tcx> {
278278
return u64::MAX;
279279
}
280280

281-
let byte_offset = align - addr_mod_align;
282-
283281
if align % stride == 0 {
282+
let byte_offset = align - addr_mod_align;
284283
if byte_offset % stride == 0 {
285284
return byte_offset / stride;
286285
} else {
@@ -296,8 +295,11 @@ impl<'mir, 'tcx: 'mir> CompileTimeEvalContext<'mir, 'tcx> {
296295
return u64::MAX;
297296
}
298297

298+
// Instead of `(addr + offset * stride) % align == 0`, we solve
299+
// `((addr + offset * stride) / gcd) % (align / gcd) == 0`.
300+
let addr2 = addr / gcd;
299301
let align2 = align / gcd;
300-
let stride2 = (stride / gcd) % align2;
302+
let stride2 = stride / gcd;
301303

302304
let mut stride_inv = 1u64;
303305
let mut mod_gate = 2u64;
@@ -308,6 +310,7 @@ impl<'mir, 'tcx: 'mir> CompileTimeEvalContext<'mir, 'tcx> {
308310
(mod_gate, overflow) = mod_gate.overflowing_mul(mod_gate);
309311
}
310312

313+
let byte_offset = align2 - addr2 % align2;
311314
byte_offset.wrapping_mul(stride_inv) % align2
312315
}
313316

library/core/tests/ptr.rs

Lines changed: 63 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -510,49 +510,53 @@ fn align_offset_various_strides_const() {
510510
assert!(got == expected);
511511
}
512512

513-
// For pointers of stride != 1, we verify the algorithm against the naivest possible
514-
// implementation
515-
let mut align = 1;
516-
let limit = 1024;
517-
while align < limit {
518-
for ptr in 1usize..4 * align {
519-
unsafe {
520-
#[repr(packed)]
521-
struct A3(u16, u8);
522-
test_stride::<A3>(ptr::invalid::<A3>(ptr), ptr, align);
523-
524-
struct A4(u32);
525-
test_stride::<A4>(ptr::invalid::<A4>(ptr), ptr, align);
526-
527-
#[repr(packed)]
528-
struct A5(u32, u8);
529-
test_stride::<A5>(ptr::invalid::<A5>(ptr), ptr, align);
530-
531-
#[repr(packed)]
532-
struct A6(u32, u16);
533-
test_stride::<A6>(ptr::invalid::<A6>(ptr), ptr, align);
534-
535-
#[repr(packed)]
536-
struct A7(u32, u16, u8);
537-
test_stride::<A7>(ptr::invalid::<A7>(ptr), ptr, align);
538-
539-
#[repr(packed)]
540-
struct A8(u32, u32);
541-
test_stride::<A8>(ptr::invalid::<A8>(ptr), ptr, align);
542-
543-
#[repr(packed)]
544-
struct A9(u32, u32, u8);
545-
test_stride::<A9>(ptr::invalid::<A9>(ptr), ptr, align);
546-
547-
#[repr(packed)]
548-
struct A10(u32, u32, u16);
549-
test_stride::<A10>(ptr::invalid::<A10>(ptr), ptr, align);
550-
551-
test_stride::<u32>(ptr::invalid::<u32>(ptr), ptr, align);
552-
test_stride::<u128>(ptr::invalid::<u128>(ptr), ptr, align);
513+
const {
514+
// For pointers of stride != 1, we verify the algorithm against the naivest possible
515+
// implementation
516+
let mut align = 1;
517+
let limit = 32;
518+
while align < limit {
519+
let mut ptr = 1;
520+
while ptr < 4 * align {
521+
unsafe {
522+
#[repr(packed)]
523+
struct A3(u16, u8);
524+
test_stride::<A3>(ptr::invalid::<A3>(ptr), ptr, align);
525+
526+
struct A4(u32);
527+
test_stride::<A4>(ptr::invalid::<A4>(ptr), ptr, align);
528+
529+
#[repr(packed)]
530+
struct A5(u32, u8);
531+
test_stride::<A5>(ptr::invalid::<A5>(ptr), ptr, align);
532+
533+
#[repr(packed)]
534+
struct A6(u32, u16);
535+
test_stride::<A6>(ptr::invalid::<A6>(ptr), ptr, align);
536+
537+
#[repr(packed)]
538+
struct A7(u32, u16, u8);
539+
test_stride::<A7>(ptr::invalid::<A7>(ptr), ptr, align);
540+
541+
#[repr(packed)]
542+
struct A8(u32, u32);
543+
test_stride::<A8>(ptr::invalid::<A8>(ptr), ptr, align);
544+
545+
#[repr(packed)]
546+
struct A9(u32, u32, u8);
547+
test_stride::<A9>(ptr::invalid::<A9>(ptr), ptr, align);
548+
549+
#[repr(packed)]
550+
struct A10(u32, u32, u16);
551+
test_stride::<A10>(ptr::invalid::<A10>(ptr), ptr, align);
552+
553+
test_stride::<u32>(ptr::invalid::<u32>(ptr), ptr, align);
554+
test_stride::<u128>(ptr::invalid::<u128>(ptr), ptr, align);
555+
}
556+
ptr += 1;
553557
}
558+
align = (align + 1).next_power_of_two();
554559
}
555-
align = (align + 1).next_power_of_two();
556560
}
557561
}
558562

@@ -632,6 +636,24 @@ fn align_offset_issue_103361() {
632636
let _ = (SIZE as *const HugeSize).align_offset(SIZE);
633637
}
634638

639+
#[test]
640+
#[cfg(not(bootstrap))]
641+
fn align_offset_issue_103361_const() {
642+
#[cfg(target_pointer_width = "64")]
643+
const SIZE: usize = 1 << 47;
644+
#[cfg(target_pointer_width = "32")]
645+
const SIZE: usize = 1 << 30;
646+
#[cfg(target_pointer_width = "16")]
647+
const SIZE: usize = 1 << 13;
648+
struct HugeSize([u8; SIZE - 1]);
649+
650+
const {
651+
assert!(ptr::invalid::<HugeSize>(SIZE - 1).align_offset(SIZE) == SIZE - 1);
652+
assert!(ptr::invalid::<HugeSize>(SIZE).align_offset(SIZE) == 0);
653+
assert!(ptr::invalid::<HugeSize>(SIZE + 1).align_offset(SIZE) == 1);
654+
}
655+
}
656+
635657
#[test]
636658
fn is_aligned() {
637659
let data = 42;

0 commit comments

Comments
 (0)