about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstd')
-rw-r--r--src/libstd/cast.rs24
-rw-r--r--src/libstd/ptr.rs84
-rw-r--r--src/libstd/unstable/intrinsics.rs33
3 files changed, 116 insertions, 25 deletions
diff --git a/src/libstd/cast.rs b/src/libstd/cast.rs
index cde22afd34a..30ad41f0ca2 100644
--- a/src/libstd/cast.rs
+++ b/src/libstd/cast.rs
@@ -14,8 +14,9 @@ use sys;
 use unstable::intrinsics;
 
 /// Casts the value at `src` to U. The two types must have the same length.
+#[cfg(stage0)]
 pub unsafe fn transmute_copy<T, U>(src: &T) -> U {
-    let mut dest: U = intrinsics::init();
+    let mut dest: U = intrinsics::uninit();
     {
         let dest_ptr: *mut u8 = transmute(&mut dest);
         let src_ptr: *u8 = transmute(src);
@@ -26,6 +27,26 @@ pub unsafe fn transmute_copy<T, U>(src: &T) -> U {
     dest
 }
 
+#[cfg(target_word_size = "32", not(stage0))]
+#[inline(always)]
+pub unsafe fn transmute_copy<T, U>(src: &T) -> U {
+    let mut dest: U = intrinsics::uninit();
+    let dest_ptr: *mut u8 = transmute(&mut dest);
+    let src_ptr: *u8 = transmute(src);
+    intrinsics::memcpy32(dest_ptr, src_ptr, sys::size_of::<U>() as u32);
+    dest
+}
+
+#[cfg(target_word_size = "64", not(stage0))]
+#[inline(always)]
+pub unsafe fn transmute_copy<T, U>(src: &T) -> U {
+    let mut dest: U = intrinsics::uninit();
+    let dest_ptr: *mut u8 = transmute(&mut dest);
+    let src_ptr: *u8 = transmute(src);
+    intrinsics::memcpy64(dest_ptr, src_ptr, sys::size_of::<U>() as u64);
+    dest
+}
+
 /**
  * Move a thing into the void
  *
@@ -43,6 +64,7 @@ pub unsafe fn forget<T>(thing: T) { intrinsics::forget(thing); }
  * and/or reinterpret_cast when such calls would otherwise scramble a box's
  * reference count
  */
+#[inline(always)]
 pub unsafe fn bump_box_refcount<T>(t: @T) { forget(t); }
 
 /**
diff --git a/src/libstd/ptr.rs b/src/libstd/ptr.rs
index d1c0ffe7953..309129b7f13 100644
--- a/src/libstd/ptr.rs
+++ b/src/libstd/ptr.rs
@@ -19,6 +19,7 @@ use sys;
 #[cfg(not(test))] use cmp::{Eq, Ord};
 use uint;
 
+#[cfg(stage0)]
 pub mod libc_ {
     use libc::c_void;
     use libc;
@@ -27,12 +28,6 @@ pub mod libc_ {
     #[abi = "cdecl"]
     pub extern {
         #[rust_stack]
-        unsafe fn memmove(dest: *mut c_void,
-                          src: *const c_void,
-                          n: libc::size_t)
-                       -> *c_void;
-
-        #[rust_stack]
         unsafe fn memset(dest: *mut c_void,
                          c: libc::c_int,
                          len: libc::size_t)
@@ -97,15 +92,28 @@ pub fn is_not_null<T>(ptr: *const T) -> bool { !is_null(ptr) }
  * and destination may overlap.
  */
 #[inline(always)]
-#[cfg(target_word_size = "32")]
+#[cfg(target_word_size = "32", stage0)]
 pub unsafe fn copy_memory<T>(dst: *mut T, src: *const T, count: uint) {
     use unstable::intrinsics::memmove32;
     let n = count * sys::size_of::<T>();
     memmove32(dst as *mut u8, src as *u8, n as u32);
 }
 
+/**
+ * Copies data from one location to another
+ *
+ * Copies `count` elements (not bytes) from `src` to `dst`. The source
+ * and destination may overlap.
+ */
 #[inline(always)]
-#[cfg(target_word_size = "64")]
+#[cfg(target_word_size = "32", not(stage0))]
+pub unsafe fn copy_memory<T>(dst: *mut T, src: *const T, count: uint) {
+    use unstable::intrinsics::memmove32;
+    memmove32(dst, src as *T, count as u32);
+}
+
+#[inline(always)]
+#[cfg(target_word_size = "64", stage0)]
 pub unsafe fn copy_memory<T>(dst: *mut T, src: *const T, count: uint) {
     use unstable::intrinsics::memmove64;
     let n = count * sys::size_of::<T>();
@@ -113,33 +121,63 @@ pub unsafe fn copy_memory<T>(dst: *mut T, src: *const T, count: uint) {
 }
 
 #[inline(always)]
-#[cfg(target_word_size = "32")]
+#[cfg(target_word_size = "64", not(stage0))]
+pub unsafe fn copy_memory<T>(dst: *mut T, src: *const T, count: uint) {
+    use unstable::intrinsics::memmove64;
+    memmove64(dst, src as *T, count as u64);
+}
+
+#[inline(always)]
+#[cfg(target_word_size = "32", stage0)]
+pub unsafe fn copy_nonoverlapping_memory<T>(dst: *mut T, src: *const T, count: uint) {
+    use unstable::intrinsics::memmove32;
+    let n = count * sys::size_of::<T>();
+    memmove32(dst as *mut u8, src as *u8, n as u32);
+}
+
+#[inline(always)]
+#[cfg(target_word_size = "32", not(stage0))]
 pub unsafe fn copy_nonoverlapping_memory<T>(dst: *mut T, src: *const T, count: uint) {
-    #[cfg(stage0)]
-    use memcpy32 = unstable::intrinsics::memmove32;
-    #[cfg(not(stage0))]
     use unstable::intrinsics::memcpy32;
+    memcpy32(dst, src as *T, count as u32);
+}
+
+#[inline(always)]
+#[cfg(target_word_size = "64", stage0)]
+pub unsafe fn copy_nonoverlapping_memory<T>(dst: *mut T, src: *const T, count: uint) {
+    use unstable::intrinsics::memmove64;
     let n = count * sys::size_of::<T>();
-    memcpy32(dst as *mut u8, src as *u8, n as u32);
+    memmove64(dst as *mut u8, src as *u8, n as u64);
 }
 
 #[inline(always)]
-#[cfg(target_word_size = "64")]
+#[cfg(target_word_size = "64", not(stage0))]
 pub unsafe fn copy_nonoverlapping_memory<T>(dst: *mut T, src: *const T, count: uint) {
-    #[cfg(stage0)]
-    use memcpy64 = unstable::intrinsics::memmove64;
-    #[cfg(not(stage0))]
     use unstable::intrinsics::memcpy64;
-    let n = count * sys::size_of::<T>();
-    memcpy64(dst as *mut u8, src as *u8, n as u64);
+    memcpy64(dst, src as *T, count as u64);
 }
 
 #[inline(always)]
+#[cfg(stage0)]
 pub unsafe fn set_memory<T>(dst: *mut T, c: int, count: uint) {
     let n = count * sys::size_of::<T>();
     libc_::memset(dst as *mut c_void, c as libc::c_int, n as size_t);
 }
 
+#[inline(always)]
+#[cfg(target_word_size = "32", not(stage0))]
+pub unsafe fn set_memory<T>(dst: *mut T, c: u8, count: uint) {
+    use unstable::intrinsics::memset32;
+    memset32(dst, c, count as u32);
+}
+
+#[inline(always)]
+#[cfg(target_word_size = "64", not(stage0))]
+pub unsafe fn set_memory<T>(dst: *mut T, c: u8, count: uint) {
+    use unstable::intrinsics::memset64;
+    memset64(dst, c, count as u64);
+}
+
 /**
   Transform a region pointer - &T - to an unsafe pointer - *T.
   This is safe, but is implemented with an unsafe block due to
@@ -581,4 +619,12 @@ pub mod ptr_tests {
             });
         }
     }
+
+    #[test]
+    fn test_set_memory() {
+        let mut xs = [0u8, ..20];
+        let ptr = vec::raw::to_mut_ptr(xs);
+        unsafe { set_memory(ptr, 5u8, xs.len()); }
+        assert_eq!(xs, [5u8, ..20]);
+    }
 }
diff --git a/src/libstd/unstable/intrinsics.rs b/src/libstd/unstable/intrinsics.rs
index 521708621fc..908c5e23ab0 100644
--- a/src/libstd/unstable/intrinsics.rs
+++ b/src/libstd/unstable/intrinsics.rs
@@ -16,7 +16,7 @@ The corresponding definitions are in librustc/middle/trans/foreign.rs.
 
 The atomic intrinsics provide common atomic operations on machine
 words, with multiple possible memory orderings. They obey the same
-semantics as C++0x. See the LLVM documentation on [[atomics]].
+semantics as C++11. See the LLVM documentation on [[atomics]].
 
 [atomics]: http://llvm.org/docs/Atomics.html
 
@@ -31,6 +31,7 @@ A quick refresher on memory ordering:
   with atomic types and is equivalent to Java's `volatile`.
 
 */
+
 #[abi = "rust-intrinsic"]
 pub extern "rust-intrinsic" {
 
@@ -127,18 +128,40 @@ pub extern "rust-intrinsic" {
     /// Get the address of the `__morestack` stack growth function.
     pub fn morestack_addr() -> *();
 
-    /// Equivalent to the `llvm.memcpy.p0i8.0i8.i32` intrinsic.
+    /// Equivalent to the `llvm.memcpy.p0i8.0i8.i32` intrinsic, with a size of
+    /// `count` * `size_of::<T>()` and an alignment of `min_align_of::<T>()`
     #[cfg(not(stage0))]
-    pub fn memcpy32(dst: *mut u8, src: *u8, size: u32);
-    /// Equivalent to the `llvm.memcpy.p0i8.0i8.i64` intrinsic.
+    pub fn memcpy32<T>(dst: *mut T, src: *T, count: u32);
+    /// Equivalent to the `llvm.memcpy.p0i8.0i8.i64` intrinsic, with a size of
+    /// `count` * `size_of::<T>()` and an alignment of `min_align_of::<T>()`
     #[cfg(not(stage0))]
-    pub fn memcpy64(dst: *mut u8, src: *u8, size: u64);
+    pub fn memcpy64<T>(dst: *mut T, src: *T, count: u64);
 
     /// Equivalent to the `llvm.memmove.p0i8.0i8.i32` intrinsic.
+    #[cfg(stage0)]
     pub fn memmove32(dst: *mut u8, src: *u8, size: u32);
     /// Equivalent to the `llvm.memmove.p0i8.0i8.i64` intrinsic.
+    #[cfg(stage0)]
     pub fn memmove64(dst: *mut u8, src: *u8, size: u64);
 
+    /// Equivalent to the `llvm.memmove.p0i8.0i8.i32` intrinsic, with a size of
+    /// `count` * `size_of::<T>()` and an alignment of `min_align_of::<T>()`
+    #[cfg(not(stage0))]
+    pub fn memmove32<T>(dst: *mut T, src: *T, count: u32);
+    /// Equivalent to the `llvm.memmove.p0i8.0i8.i64` intrinsic, with a size of
+    /// `count` * `size_of::<T>()` and an alignment of `min_align_of::<T>()`
+    #[cfg(not(stage0))]
+    pub fn memmove64<T>(dst: *mut T, src: *T, count: u64);
+
+    /// Equivalent to the `llvm.memset.p0i8.i32` intrinsic, with a size of
+    /// `count` * `size_of::<T>()` and an alignment of `min_align_of::<T>()`
+    #[cfg(not(stage0))]
+    pub fn memset32<T>(dst: *mut T, val: u8, count: u32);
+    /// Equivalent to the `llvm.memset.p0i8.i64` intrinsic, with a size of
+    /// `count` * `size_of::<T>()` and an alignment of `min_align_of::<T>()`
+    #[cfg(not(stage0))]
+    pub fn memset64<T>(dst: *mut T, val: u8, count: u64);
+
     pub fn sqrtf32(x: f32) -> f32;
     pub fn sqrtf64(x: f64) -> f64;