Skip to content

Commit 2787a28

Browse files
committed
Add <*const T>::align_offset and use it in memchr
1 parent 1cdd689 commit 2787a28

File tree

5 files changed

+80
-41
lines changed

5 files changed

+80
-41
lines changed

src/libcore/intrinsics.rs

+1-32
Original file line numberDiff line numberDiff line change
@@ -1381,38 +1381,7 @@ extern "rust-intrinsic" {
13811381
}
13821382

13831383
#[cfg(stage0)]
1384-
/// Computes the byte offset that needs to be applied to `ptr` in order to
1385-
/// make it aligned to `align`.
1386-
/// If it is not possible to align `ptr`, the implementation returns
1387-
/// `usize::max_value()`.
1388-
///
1389-
/// There are no guarantees whatsover that offsetting the pointer will not
1390-
/// overflow or go beyond the allocation that `ptr` points into.
1391-
/// It is up to the caller to ensure that the returned offset is correct
1392-
/// in all terms other than alignment.
1393-
///
1394-
/// # Examples
1395-
///
1396-
/// Accessing adjacent `u8` as `u16`
1397-
///
1398-
/// ```
1399-
/// # #![feature(core_intrinsics)]
1400-
/// # fn foo(n: usize) {
1401-
/// # use std::intrinsics::align_offset;
1402-
/// # use std::mem::align_of;
1403-
/// # unsafe {
1404-
/// let x = [5u8, 6u8, 7u8, 8u8, 9u8];
1405-
/// let ptr = &x[n] as *const u8;
1406-
/// let offset = align_offset(ptr as *const (), align_of::<u16>());
1407-
/// if offset < x.len() - n - 1 {
1408-
/// let u16_ptr = ptr.offset(offset as isize) as *const u16;
1409-
/// assert_ne!(*u16_ptr, 500);
1410-
/// } else {
1411-
/// // while the pointer can be aligned via `offset`, it would point
1412-
/// // outside the allocation
1413-
/// }
1414-
/// # } }
1415-
/// ```
1384+
/// remove me after the next release
14161385
pub unsafe fn align_offset(ptr: *const (), align: usize) -> usize {
14171386
let offset = ptr as usize % align;
14181387
if offset == 0 {

src/libcore/ptr.rs

+74-1
Original file line numberDiff line numberDiff line change
@@ -1064,7 +1064,43 @@ impl<T: ?Sized> *const T {
10641064
copy_nonoverlapping(self, dest, count)
10651065
}
10661066

1067-
1067+
/// Computes the byte offset that needs to be applied in order to
1068+
/// make the pointer aligned to `align`.
1069+
/// If it is not possible to align the pointer, the implementation returns
1070+
/// `usize::max_value()`.
1071+
///
1072+
/// There are no guarantees whatsover that offsetting the pointer will not
1073+
/// overflow or go beyond the allocation that the pointer points into.
1074+
/// It is up to the caller to ensure that the returned offset is correct
1075+
/// in all terms other than alignment.
1076+
///
1077+
/// # Examples
1078+
///
1079+
/// Accessing adjacent `u8` as `u16`
1080+
///
1081+
/// ```
1082+
/// # #![feature(align_offset)]
1083+
/// # fn foo(n: usize) {
1084+
/// # use std::mem::align_of;
1085+
/// # unsafe {
1086+
/// let x = [5u8, 6u8, 7u8, 8u8, 9u8];
1087+
/// let ptr = &x[n] as *const u8;
1088+
/// let offset = ptr.align_offset(align_of::<u16>());
1089+
/// if offset < x.len() - n - 1 {
1090+
/// let u16_ptr = ptr.offset(offset as isize) as *const u16;
1091+
/// assert_ne!(*u16_ptr, 500);
1092+
/// } else {
1093+
/// // while the pointer can be aligned via `offset`, it would point
1094+
/// // outside the allocation
1095+
/// }
1096+
/// # } }
1097+
/// ```
1098+
#[unstable(feature = "align_offset", issue = "44488")]
1099+
pub fn align_offset(self, align: usize) -> usize {
1100+
unsafe {
1101+
intrinsics::align_offset(self as *const _, align)
1102+
}
1103+
}
10681104
}
10691105

10701106
#[lang = "mut_ptr"]
@@ -1284,6 +1320,43 @@ impl<T: ?Sized> *mut T {
12841320
}
12851321
}
12861322

1323+
/// Computes the byte offset that needs to be applied in order to
1324+
/// make the pointer aligned to `align`.
1325+
/// If it is not possible to align the pointer, the implementation returns
1326+
/// `usize::max_value()`.
1327+
///
1328+
/// There are no guarantees whatsover that offsetting the pointer will not
1329+
/// overflow or go beyond the allocation that the pointer points into.
1330+
/// It is up to the caller to ensure that the returned offset is correct
1331+
/// in all terms other than alignment.
1332+
///
1333+
/// # Examples
1334+
///
1335+
/// Accessing adjacent `u8` as `u16`
1336+
///
1337+
/// ```
1338+
/// # #![feature(align_offset)]
1339+
/// # fn foo(n: usize) {
1340+
/// # use std::mem::align_of;
1341+
/// # unsafe {
1342+
/// let x = [5u8, 6u8, 7u8, 8u8, 9u8];
1343+
/// let ptr = &x[n] as *const u8;
1344+
/// let offset = ptr.align_offset(align_of::<u16>());
1345+
/// if offset < x.len() - n - 1 {
1346+
/// let u16_ptr = ptr.offset(offset as isize) as *const u16;
1347+
/// assert_ne!(*u16_ptr, 500);
1348+
/// } else {
1349+
/// // while the pointer can be aligned via `offset`, it would point
1350+
/// // outside the allocation
1351+
/// }
1352+
/// # } }
1353+
/// ```
1354+
#[unstable(feature = "align_offset", issue = "44488")]
1355+
pub fn align_offset(self, align: usize) -> usize {
1356+
unsafe {
1357+
intrinsics::align_offset(self as *const _, align)
1358+
}
1359+
}
12871360

12881361
/// Calculates the offset from a pointer (convenience for `.offset(count as isize)`).
12891362
///

src/libcore/str/mod.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ use fmt;
2323
use iter::{Map, Cloned, FusedIterator};
2424
use slice::{self, SliceIndex};
2525
use mem;
26-
use intrinsics::align_offset;
2726

2827
pub mod pattern;
2928

@@ -1515,7 +1514,7 @@ fn run_utf8_validation(v: &[u8]) -> Result<(), Utf8Error> {
15151514
let ptr = v.as_ptr();
15161515
let align = unsafe {
15171516
// the offset is safe, because `index` is guaranteed inbounds
1518-
align_offset(ptr.offset(index as isize) as *const (), usize_bytes)
1517+
ptr.offset(index as isize).align_offset(usize_bytes)
15191518
};
15201519
if align == 0 {
15211520
while index < blocks_end {

src/libstd/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,7 @@
242242
#![feature(allocator_internals)]
243243
#![feature(allow_internal_unsafe)]
244244
#![feature(allow_internal_unstable)]
245+
#![feature(align_offset)]
245246
#![feature(asm)]
246247
#![feature(box_syntax)]
247248
#![feature(cfg_target_has_atomic)]

src/libstd/sys_common/memchr.rs

+3-6
Original file line numberDiff line numberDiff line change
@@ -65,15 +65,12 @@ pub mod fallback {
6565
let usize_bytes = mem::size_of::<usize>();
6666

6767
// search up to an aligned boundary
68-
let align = (ptr as usize) & (usize_bytes- 1);
69-
let mut offset;
70-
if align > 0 {
71-
offset = cmp::min(usize_bytes - align, len);
68+
let mut offset = ptr.align_offset(usize_bytes);
69+
if offset > 0 {
70+
offset = cmp::min(offset, len);
7271
if let Some(index) = text[..offset].iter().position(|elt| *elt == x) {
7372
return Some(index);
7473
}
75-
} else {
76-
offset = 0;
7774
}
7875

7976
// search the body of the text

0 commit comments

Comments
 (0)