add coretests for const align_offset

This commit is contained in:
Lukas Markeffsky 2022-10-07 20:59:23 +02:00
parent 211743b2c8
commit 8cf6b16185
2 changed files with 166 additions and 0 deletions

View file

@ -4,6 +4,7 @@
#![feature(array_windows)]
#![feature(bigint_helper_methods)]
#![feature(cell_update)]
#![feature(const_align_offset)]
#![feature(const_assume)]
#![feature(const_align_of_val_raw)]
#![feature(const_black_box)]

View file

@ -358,6 +358,23 @@ fn align_offset_zst() {
}
}
#[test]
#[cfg(not(bootstrap))]
fn align_offset_zst_const() {
const {
// For pointers of stride = 0, the pointer is already aligned or it cannot be aligned at
// all, because no amount of elements will align the pointer.
let mut p = 1;
while p < 1024 {
assert!(ptr::invalid::<()>(p).align_offset(p) == 0);
if p != 1 {
assert!(ptr::invalid::<()>(p + 1).align_offset(p) == !0);
}
p = (p + 1).next_power_of_two();
}
}
}
#[test]
fn align_offset_stride_one() {
// For pointers of stride = 1, the pointer can always be aligned. The offset is equal to
@ -379,6 +396,26 @@ fn align_offset_stride_one() {
}
}
#[test]
#[cfg(not(bootstrap))]
fn align_offset_stride_one_const() {
const {
// For pointers of stride = 1, the pointer can always be aligned. The offset is equal to
// number of bytes.
let mut align = 1;
while align < 1024 {
let mut ptr = 1;
while ptr < 2 * align {
let expected = ptr % align;
let offset = if expected == 0 { 0 } else { align - expected };
assert!(ptr::invalid::<u8>(ptr).align_offset(align) == offset);
ptr += 1;
}
align = (align + 1).next_power_of_two();
}
}
}
#[test]
fn align_offset_various_strides() {
unsafe fn test_stride<T>(ptr: *const T, align: usize) -> bool {
@ -455,6 +492,134 @@ fn align_offset_various_strides() {
assert!(!x);
}
#[test]
#[cfg(not(bootstrap))]
fn align_offset_various_strides_const() {
const unsafe fn test_stride<T>(ptr: *const T, numptr: usize, align: usize) {
let mut expected = usize::MAX;
// Naive but definitely correct way to find the *first* aligned element of stride::<T>.
let mut el = 0;
while el < align {
if (numptr + el * ::std::mem::size_of::<T>()) % align == 0 {
expected = el;
break;
}
el += 1;
}
let got = ptr.align_offset(align);
assert!(got == expected);
}
// For pointers of stride != 1, we verify the algorithm against the naivest possible
// implementation
let mut align = 1;
let limit = 1024;
while align < limit {
for ptr in 1usize..4 * align {
unsafe {
#[repr(packed)]
struct A3(u16, u8);
test_stride::<A3>(ptr::invalid::<A3>(ptr), ptr, align);
struct A4(u32);
test_stride::<A4>(ptr::invalid::<A4>(ptr), ptr, align);
#[repr(packed)]
struct A5(u32, u8);
test_stride::<A5>(ptr::invalid::<A5>(ptr), ptr, align);
#[repr(packed)]
struct A6(u32, u16);
test_stride::<A6>(ptr::invalid::<A6>(ptr), ptr, align);
#[repr(packed)]
struct A7(u32, u16, u8);
test_stride::<A7>(ptr::invalid::<A7>(ptr), ptr, align);
#[repr(packed)]
struct A8(u32, u32);
test_stride::<A8>(ptr::invalid::<A8>(ptr), ptr, align);
#[repr(packed)]
struct A9(u32, u32, u8);
test_stride::<A9>(ptr::invalid::<A9>(ptr), ptr, align);
#[repr(packed)]
struct A10(u32, u32, u16);
test_stride::<A10>(ptr::invalid::<A10>(ptr), ptr, align);
test_stride::<u32>(ptr::invalid::<u32>(ptr), ptr, align);
test_stride::<u128>(ptr::invalid::<u128>(ptr), ptr, align);
}
}
align = (align + 1).next_power_of_two();
}
}
#[test]
#[cfg(not(bootstrap))]
fn align_offset_with_provenance_const() {
const {
let data = 42;
let ptr: *const i32 = &data;
assert!(ptr.align_offset(1) == 0);
assert!(ptr.align_offset(2) == 0);
assert!(ptr.align_offset(4) == 0);
assert!(ptr.align_offset(8) == usize::MAX);
assert!(ptr.wrapping_byte_add(1).align_offset(1) == 0);
assert!(ptr.wrapping_byte_add(1).align_offset(2) == usize::MAX);
assert!(ptr.wrapping_byte_add(2).align_offset(1) == 0);
assert!(ptr.wrapping_byte_add(2).align_offset(2) == 0);
assert!(ptr.wrapping_byte_add(2).align_offset(4) == usize::MAX);
assert!(ptr.wrapping_byte_add(3).align_offset(1) == 0);
assert!(ptr.wrapping_byte_add(3).align_offset(2) == usize::MAX);
assert!(ptr.wrapping_add(42).align_offset(4) == 0);
assert!(ptr.wrapping_add(42).align_offset(8) == usize::MAX);
let ptr1: *const i8 = ptr.cast();
assert!(ptr1.align_offset(1) == 0);
assert!(ptr1.align_offset(2) == 0);
assert!(ptr1.align_offset(4) == 0);
assert!(ptr1.align_offset(8) == usize::MAX);
assert!(ptr1.wrapping_byte_add(1).align_offset(1) == 0);
assert!(ptr1.wrapping_byte_add(1).align_offset(2) == 1);
assert!(ptr1.wrapping_byte_add(1).align_offset(4) == 3);
assert!(ptr1.wrapping_byte_add(1).align_offset(8) == usize::MAX);
assert!(ptr1.wrapping_byte_add(2).align_offset(1) == 0);
assert!(ptr1.wrapping_byte_add(2).align_offset(2) == 0);
assert!(ptr1.wrapping_byte_add(2).align_offset(4) == 2);
assert!(ptr1.wrapping_byte_add(2).align_offset(8) == usize::MAX);
assert!(ptr1.wrapping_byte_add(3).align_offset(1) == 0);
assert!(ptr1.wrapping_byte_add(3).align_offset(2) == 1);
assert!(ptr1.wrapping_byte_add(3).align_offset(4) == 1);
assert!(ptr1.wrapping_byte_add(3).align_offset(8) == usize::MAX);
let ptr2: *const i16 = ptr.cast();
assert!(ptr2.align_offset(1) == 0);
assert!(ptr2.align_offset(2) == 0);
assert!(ptr2.align_offset(4) == 0);
assert!(ptr2.align_offset(8) == usize::MAX);
assert!(ptr2.wrapping_byte_add(1).align_offset(1) == 0);
assert!(ptr2.wrapping_byte_add(1).align_offset(2) == usize::MAX);
assert!(ptr2.wrapping_byte_add(2).align_offset(1) == 0);
assert!(ptr2.wrapping_byte_add(2).align_offset(2) == 0);
assert!(ptr2.wrapping_byte_add(2).align_offset(4) == 1);
assert!(ptr2.wrapping_byte_add(2).align_offset(8) == usize::MAX);
assert!(ptr2.wrapping_byte_add(3).align_offset(1) == 0);
assert!(ptr2.wrapping_byte_add(3).align_offset(2) == usize::MAX);
let ptr3: *const i64 = ptr.cast();
assert!(ptr3.align_offset(1) == 0);
assert!(ptr3.align_offset(2) == 0);
assert!(ptr3.align_offset(4) == 0);
assert!(ptr3.align_offset(8) == usize::MAX);
assert!(ptr3.wrapping_byte_add(1).align_offset(1) == 0);
assert!(ptr3.wrapping_byte_add(1).align_offset(2) == usize::MAX);
}
}
#[test]
fn align_offset_issue_103361() {
#[cfg(target_pointer_width = "64")]