From 6f96abf7389c6a031c549a9df0b672b7989fbe8b Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Wed, 9 Jul 2014 22:24:23 -0700 Subject: [PATCH] libcore: Reexport a couple of widely-used low-level intrinsics to reduce code bloat. This didn't make a difference in any compile times that I saw, but it fits what we're doing with `transmute` and seems prudent. --- src/libcore/intrinsics.rs | 72 ++++++++++++++++++++++++++++----- src/libcore/ptr.rs | 84 ++------------------------------------- 2 files changed, 67 insertions(+), 89 deletions(-) diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index 161dd7cef7e13..002babf7df976 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -326,19 +326,73 @@ extern "rust-intrinsic" { /// integer, since the conversion would throw away aliasing information. pub fn offset(dst: *const T, offset: int) -> *const T; - /// Equivalent to the appropriate `llvm.memcpy.p0i8.0i8.*` intrinsic, with - /// a size of `count` * `size_of::()` and an alignment of - /// `min_align_of::()` + /// Copies data from one location to another. + /// + /// Copies `count` elements (not bytes) from `src` to `dst`. The source + /// and destination may *not* overlap. + /// + /// `copy_nonoverlapping_memory` is semantically equivalent to C's `memcpy`. + /// + /// # Example + /// + /// A safe swap function: + /// + /// ``` + /// use std::mem; + /// use std::ptr; + /// + /// fn swap(x: &mut T, y: &mut T) { + /// unsafe { + /// // Give ourselves some scratch space to work with + /// let mut t: T = mem::uninitialized(); + /// + /// // Perform the swap, `&mut` pointers never alias + /// ptr::copy_nonoverlapping_memory(&mut t, &*x, 1); + /// ptr::copy_nonoverlapping_memory(x, &*y, 1); + /// ptr::copy_nonoverlapping_memory(y, &t, 1); + /// + /// // y and t now point to the same thing, but we need to completely forget `tmp` + /// // because it's no longer relevant. + /// mem::forget(t); + /// } + /// } + /// ``` + /// + /// # Safety Note + /// + /// If the source and destination overlap then the behavior of this + /// function is undefined. + #[unstable] pub fn copy_nonoverlapping_memory(dst: *mut T, src: *const T, count: uint); - /// Equivalent to the appropriate `llvm.memmove.p0i8.0i8.*` intrinsic, with - /// a size of `count` * `size_of::()` and an alignment of - /// `min_align_of::()` + /// Copies data from one location to another. + /// + /// Copies `count` elements (not bytes) from `src` to `dst`. The source + /// and destination may overlap. + /// + /// `copy_memory` is semantically equivalent to C's `memmove`. + /// + /// # Example + /// + /// Efficiently create a Rust vector from an unsafe buffer: + /// + /// ``` + /// use std::ptr; + /// + /// unsafe fn from_buf_raw(ptr: *const T, elts: uint) -> Vec { + /// let mut dst = Vec::with_capacity(elts); + /// dst.set_len(elts); + /// ptr::copy_memory(dst.as_mut_ptr(), ptr, elts); + /// dst + /// } + /// ``` + /// + #[unstable] pub fn copy_memory(dst: *mut T, src: *const T, count: uint); - /// Equivalent to the appropriate `llvm.memset.p0i8.*` intrinsic, with a - /// size of `count` * `size_of::()` and an alignment of - /// `min_align_of::()` + /// Invokes memset on the specified pointer, setting `count * size_of::()` + /// bytes of memory starting at `dst` to `c`. + #[experimental = "uncertain about naming and semantics"] pub fn set_memory(dst: *mut T, val: u8, count: uint); /// Equivalent to the appropriate `llvm.memcpy.p0i8.0i8.*` intrinsic, with diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index 093591cd796d1..ed1d4d481100b 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -95,6 +95,10 @@ use option::{Some, None, Option}; use cmp::{PartialEq, Eq, PartialOrd, Equiv, Ordering, Less, Equal, Greater}; +pub use intrinsics::copy_memory; +pub use intrinsics::copy_nonoverlapping_memory; +pub use intrinsics::set_memory; + /// Create a null pointer. /// /// # Example @@ -123,86 +127,6 @@ pub fn null() -> *const T { 0 as *const T } #[unstable = "may need a different name after pending changes to pointer types"] pub fn mut_null() -> *mut T { 0 as *mut T } -/// Copies data from one location to another. -/// -/// Copies `count` elements (not bytes) from `src` to `dst`. The source -/// and destination may overlap. -/// -/// `copy_memory` is semantically equivalent to C's `memmove`. -/// -/// # Example -/// -/// Efficiently create a Rust vector from an unsafe buffer: -/// -/// ``` -/// use std::ptr; -/// -/// unsafe fn from_buf_raw(ptr: *const T, elts: uint) -> Vec { -/// let mut dst = Vec::with_capacity(elts); -/// dst.set_len(elts); -/// ptr::copy_memory(dst.as_mut_ptr(), ptr, elts); -/// dst -/// } -/// ``` -/// -#[inline] -#[unstable] -pub unsafe fn copy_memory(dst: *mut T, src: *const T, count: uint) { - intrinsics::copy_memory(dst, src, count) -} - -/// Copies data from one location to another. -/// -/// Copies `count` elements (not bytes) from `src` to `dst`. The source -/// and destination may *not* overlap. -/// -/// `copy_nonoverlapping_memory` is semantically equivalent to C's `memcpy`. -/// -/// # Example -/// -/// A safe swap function: -/// -/// ``` -/// use std::mem; -/// use std::ptr; -/// -/// fn swap(x: &mut T, y: &mut T) { -/// unsafe { -/// // Give ourselves some scratch space to work with -/// let mut t: T = mem::uninitialized(); -/// -/// // Perform the swap, `&mut` pointers never alias -/// ptr::copy_nonoverlapping_memory(&mut t, &*x, 1); -/// ptr::copy_nonoverlapping_memory(x, &*y, 1); -/// ptr::copy_nonoverlapping_memory(y, &t, 1); -/// -/// // y and t now point to the same thing, but we need to completely forget `tmp` -/// // because it's no longer relevant. -/// mem::forget(t); -/// } -/// } -/// ``` -/// -/// # Safety Note -/// -/// If the source and destination overlap then the behavior of this -/// function is undefined. -#[inline] -#[unstable] -pub unsafe fn copy_nonoverlapping_memory(dst: *mut T, - src: *const T, - count: uint) { - intrinsics::copy_nonoverlapping_memory(dst, src, count) -} - -/// Invokes memset on the specified pointer, setting `count * size_of::()` -/// bytes of memory starting at `dst` to `c`. -#[inline] -#[experimental = "uncertain about naming and semantics"] -pub unsafe fn set_memory(dst: *mut T, c: u8, count: uint) { - intrinsics::set_memory(dst, c, count) -} - /// Zeroes out `count * size_of::` bytes of memory at `dst` #[inline] #[experimental = "uncertain about naming and semantics"]