diff options
| author | bors <bors@rust-lang.org> | 2017-08-30 08:06:42 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2017-08-30 08:06:42 +0000 |
| commit | c66e7fa8dee0b6b2b5439e2bd527ab66c9fbde13 (patch) | |
| tree | 3aa5b315b66f38c18890c727d66e48b9f1e7ef7b /src/libcore | |
| parent | b58e31ac03d3f338385593496426534ad5a150a7 (diff) | |
| parent | be96ad2c85b680be68d38ab7aa115f0b9c32b3d5 (diff) | |
| download | rust-c66e7fa8dee0b6b2b5439e2bd527ab66c9fbde13.tar.gz rust-c66e7fa8dee0b6b2b5439e2bd527ab66c9fbde13.zip | |
Auto merge of #43903 - oli-obk:alignto, r=aturon
Add align_offset intrinsic see https://github.com/rust-lang/rfcs/pull/2043 for details and the plan towards stabilization (reexport in `core::mem` via various convenience functions) as per @scottmcm 's [comment](https://github.com/rust-lang/rfcs/pull/2043#issuecomment-316818169), this is just the intrinsic (which is obviously unstable).
Diffstat (limited to 'src/libcore')
| -rw-r--r-- | src/libcore/intrinsics.rs | 77 | ||||
| -rw-r--r-- | src/libcore/str/mod.rs | 6 |
2 files changed, 82 insertions, 1 deletions
diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index ad776c8605a..607f6f37017 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -1343,4 +1343,81 @@ extern "rust-intrinsic" { /// on MSVC it's `*mut [usize; 2]`. For more information see the compiler's /// source as well as std's catch implementation. pub fn try(f: fn(*mut u8), data: *mut u8, local_ptr: *mut u8) -> i32; + + /// Computes the byte offset that needs to be applied to `ptr` in order to + /// make it aligned to `align`. + /// If it is not possible to align `ptr`, the implementation returns + /// `usize::max_value()`. + /// + /// There are no guarantees whatsover that offsetting the pointer will not + /// overflow or go beyond the allocation that `ptr` points into. + /// It is up to the caller to ensure that the returned offset is correct + /// in all terms other than alignment. + /// + /// # Examples + /// + /// Accessing adjacent `u8` as `u16` + /// + /// ``` + /// # #![feature(core_intrinsics)] + /// # fn foo(n: usize) { + /// # use std::intrinsics::align_offset; + /// # use std::mem::align_of; + /// # unsafe { + /// let x = [5u8, 6u8, 7u8, 8u8, 9u8]; + /// let ptr = &x[n] as *const u8; + /// let offset = align_offset(ptr as *const (), align_of::<u16>()); + /// if offset < x.len() - n - 1 { + /// let u16_ptr = ptr.offset(offset as isize) as *const u16; + /// assert_ne!(*u16_ptr, 500); + /// } else { + /// // while the pointer can be aligned via `offset`, it would point + /// // outside the allocation + /// } + /// # } } + /// ``` + #[cfg(not(stage0))] + pub fn align_offset(ptr: *const (), align: usize) -> usize; +} + +#[cfg(stage0)] +/// Computes the byte offset that needs to be applied to `ptr` in order to +/// make it aligned to `align`. +/// If it is not possible to align `ptr`, the implementation returns +/// `usize::max_value()`. +/// +/// There are no guarantees whatsover that offsetting the pointer will not +/// overflow or go beyond the allocation that `ptr` points into. +/// It is up to the caller to ensure that the returned offset is correct +/// in all terms other than alignment. +/// +/// # Examples +/// +/// Accessing adjacent `u8` as `u16` +/// +/// ``` +/// # #![feature(core_intrinsics)] +/// # fn foo(n: usize) { +/// # use std::intrinsics::align_offset; +/// # use std::mem::align_of; +/// # unsafe { +/// let x = [5u8, 6u8, 7u8, 8u8, 9u8]; +/// let ptr = &x[n] as *const u8; +/// let offset = align_offset(ptr as *const (), align_of::<u16>()); +/// if offset < x.len() - n - 1 { +/// let u16_ptr = ptr.offset(offset as isize) as *const u16; +/// assert_ne!(*u16_ptr, 500); +/// } else { +/// // while the pointer can be aligned via `offset`, it would point +/// // outside the allocation +/// } +/// # } } +/// ``` +pub unsafe fn align_offset(ptr: *const (), align: usize) -> usize { + let offset = ptr as usize % align; + if offset == 0 { + 0 + } else { + align - offset + } } diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index a5f6e49a53b..62e84c9ebd0 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -23,6 +23,7 @@ use fmt; use iter::{Map, Cloned, FusedIterator}; use slice::{self, SliceIndex}; use mem; +use intrinsics::align_offset; pub mod pattern; @@ -1468,7 +1469,10 @@ fn run_utf8_validation(v: &[u8]) -> Result<(), Utf8Error> { // When the pointer is aligned, read 2 words of data per iteration // until we find a word containing a non-ascii byte. let ptr = v.as_ptr(); - let align = (ptr as usize + index) & (usize_bytes - 1); + let align = unsafe { + // the offset is safe, because `index` is guaranteed inbounds + align_offset(ptr.offset(index as isize) as *const (), usize_bytes) + }; if align == 0 { while index < blocks_end { unsafe { |
