about summary refs log tree commit diff
diff options
context:
space:
mode:
authorDaniel Micay <danielmicay@gmail.com>2013-11-03 16:54:58 -0500
committerDaniel Micay <danielmicay@gmail.com>2013-11-03 20:31:57 -0500
commit67966fa9de062cfe05604ed7e11e9ab58bb55225 (patch)
tree7f482c3b0df8fc813098699418268130883512bb
parentdc079e1596bb5fd7b601fe1b605c8f30326ee748 (diff)
downloadrust-67966fa9de062cfe05604ed7e11e9ab58bb55225.tar.gz
rust-67966fa9de062cfe05604ed7e11e9ab58bb55225.zip
simplify memcpy/memmove/memset intrinsics
This moves the per-architecture difference into the compiler.
-rw-r--r--src/librustc/middle/trans/intrinsic.rs40
-rw-r--r--src/librustc/middle/typeck/check/mod.rs54
-rw-r--r--src/libstd/cast.rs15
-rw-r--r--src/libstd/ptr.rs48
-rw-r--r--src/libstd/unstable/intrinsics.rs15
5 files changed, 89 insertions, 83 deletions
diff --git a/src/librustc/middle/trans/intrinsic.rs b/src/librustc/middle/trans/intrinsic.rs
index ce62b26c9ab..4618cdf45ee 100644
--- a/src/librustc/middle/trans/intrinsic.rs
+++ b/src/librustc/middle/trans/intrinsic.rs
@@ -74,14 +74,24 @@ pub fn trans_intrinsic(ccx: @mut CrateContext,
         }
     }
 
-    fn memcpy_intrinsic(bcx: @mut Block, name: &'static str, tp_ty: ty::t, sizebits: u8) {
+    fn copy_intrinsic(bcx: @mut Block, allow_overlap: bool, tp_ty: ty::t) {
         let ccx = bcx.ccx();
         let lltp_ty = type_of::type_of(ccx, tp_ty);
         let align = C_i32(machine::llalign_of_min(ccx, lltp_ty) as i32);
-        let size = match sizebits {
-            32 => C_i32(machine::llsize_of_real(ccx, lltp_ty) as i32),
-            64 => C_i64(machine::llsize_of_real(ccx, lltp_ty) as i64),
-            _ => ccx.sess.fatal("Invalid value for sizebits")
+        let size = machine::llsize_of(ccx, lltp_ty);
+        let int_size = machine::llbitsize_of_real(ccx, ccx.int_type);
+        let name = if allow_overlap {
+            if int_size == 32 {
+                "llvm.memmove.p0i8.p0i8.i32"
+            } else {
+                "llvm.memmove.p0i8.p0i8.i64"
+            }
+        } else {
+            if int_size == 32 {
+                "llvm.memcpy.p0i8.p0i8.i32"
+            } else {
+                "llvm.memcpy.p0i8.p0i8.i64"
+            }
         };
 
         let decl = bcx.fcx.llfn;
@@ -95,14 +105,15 @@ pub fn trans_intrinsic(ccx: @mut CrateContext,
         RetVoid(bcx);
     }
 
-    fn memset_intrinsic(bcx: @mut Block, name: &'static str, tp_ty: ty::t, sizebits: u8) {
+    fn memset_intrinsic(bcx: @mut Block, tp_ty: ty::t) {
         let ccx = bcx.ccx();
         let lltp_ty = type_of::type_of(ccx, tp_ty);
         let align = C_i32(machine::llalign_of_min(ccx, lltp_ty) as i32);
-        let size = match sizebits {
-            32 => C_i32(machine::llsize_of_real(ccx, lltp_ty) as i32),
-            64 => C_i64(machine::llsize_of_real(ccx, lltp_ty) as i64),
-            _ => ccx.sess.fatal("Invalid value for sizebits")
+        let size = machine::llsize_of(ccx, lltp_ty);
+        let name = if machine::llbitsize_of_real(ccx, ccx.int_type) == 32 {
+            "llvm.memset.p0i8.i32"
+        } else {
+            "llvm.memset.p0i8.i64"
         };
 
         let decl = bcx.fcx.llfn;
@@ -399,12 +410,9 @@ pub fn trans_intrinsic(ccx: @mut CrateContext,
             let lladdr = InBoundsGEP(bcx, ptr, [offset]);
             Ret(bcx, lladdr);
         }
-        "memcpy32" => memcpy_intrinsic(bcx, "llvm.memcpy.p0i8.p0i8.i32", substs.tys[0], 32),
-        "memcpy64" => memcpy_intrinsic(bcx, "llvm.memcpy.p0i8.p0i8.i64", substs.tys[0], 64),
-        "memmove32" => memcpy_intrinsic(bcx, "llvm.memmove.p0i8.p0i8.i32", substs.tys[0], 32),
-        "memmove64" => memcpy_intrinsic(bcx, "llvm.memmove.p0i8.p0i8.i64", substs.tys[0], 64),
-        "memset32" => memset_intrinsic(bcx, "llvm.memset.p0i8.i32", substs.tys[0], 32),
-        "memset64" => memset_intrinsic(bcx, "llvm.memset.p0i8.i64", substs.tys[0], 64),
+        "copy_nonoverlapping_memory" => copy_intrinsic(bcx, false, substs.tys[0]),
+        "copy_memory" => copy_intrinsic(bcx, true, substs.tys[0]),
+        "set_memory" => memset_intrinsic(bcx, substs.tys[0]),
         "sqrtf32" => simple_llvm_intrinsic(bcx, "llvm.sqrt.f32", 1),
         "sqrtf64" => simple_llvm_intrinsic(bcx, "llvm.sqrt.f64", 1),
         "powif32" => simple_llvm_intrinsic(bcx, "llvm.powi.f32", 2),
diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs
index b0196010cb0..011d39af7a8 100644
--- a/src/librustc/middle/typeck/check/mod.rs
+++ b/src/librustc/middle/typeck/check/mod.rs
@@ -3734,7 +3734,7 @@ pub fn check_intrinsic_type(ccx: @mut CrateCtxt, it: @ast::foreign_item) {
                    mutbl: ast::MutImmutable
                }))
             }
-            "memcpy32" => {
+            "copy_nonoverlapping_memory" => {
               (1,
                ~[
                   ty::mk_ptr(tcx, ty::mt {
@@ -3745,11 +3745,11 @@ pub fn check_intrinsic_type(ccx: @mut CrateCtxt, it: @ast::foreign_item) {
                       ty: param(ccx, 0),
                       mutbl: ast::MutImmutable
                   }),
-                  ty::mk_u32()
+                  ty::mk_uint()
                ],
                ty::mk_nil())
             }
-            "memcpy64" => {
+            "copy_memory" => {
               (1,
                ~[
                   ty::mk_ptr(tcx, ty::mt {
@@ -3760,53 +3760,11 @@ pub fn check_intrinsic_type(ccx: @mut CrateCtxt, it: @ast::foreign_item) {
                       ty: param(ccx, 0),
                       mutbl: ast::MutImmutable
                   }),
-                  ty::mk_u64()
+                  ty::mk_uint()
                ],
                ty::mk_nil())
             }
-            "memmove32" => {
-              (1,
-               ~[
-                  ty::mk_ptr(tcx, ty::mt {
-                      ty: param(ccx, 0),
-                      mutbl: ast::MutMutable
-                  }),
-                  ty::mk_ptr(tcx, ty::mt {
-                      ty: param(ccx, 0),
-                      mutbl: ast::MutImmutable
-                  }),
-                  ty::mk_u32()
-               ],
-               ty::mk_nil())
-            }
-            "memmove64" => {
-              (1,
-               ~[
-                  ty::mk_ptr(tcx, ty::mt {
-                      ty: param(ccx, 0),
-                      mutbl: ast::MutMutable
-                  }),
-                  ty::mk_ptr(tcx, ty::mt {
-                      ty: param(ccx, 0),
-                      mutbl: ast::MutImmutable
-                  }),
-                  ty::mk_u64()
-               ],
-               ty::mk_nil())
-            }
-            "memset32" => {
-              (1,
-               ~[
-                  ty::mk_ptr(tcx, ty::mt {
-                      ty: param(ccx, 0),
-                      mutbl: ast::MutMutable
-                  }),
-                  ty::mk_u8(),
-                  ty::mk_u32()
-               ],
-               ty::mk_nil())
-            }
-            "memset64" => {
+            "set_memory" => {
               (1,
                ~[
                   ty::mk_ptr(tcx, ty::mt {
@@ -3814,7 +3772,7 @@ pub fn check_intrinsic_type(ccx: @mut CrateCtxt, it: @ast::foreign_item) {
                       mutbl: ast::MutMutable
                   }),
                   ty::mk_u8(),
-                  ty::mk_u64()
+                  ty::mk_uint()
                ],
                ty::mk_nil())
             }
diff --git a/src/libstd/cast.rs b/src/libstd/cast.rs
index a4f2ee0d09c..05a72dc4109 100644
--- a/src/libstd/cast.rs
+++ b/src/libstd/cast.rs
@@ -13,26 +13,15 @@
 use ptr::RawPtr;
 use mem;
 use unstable::intrinsics;
+use ptr::copy_nonoverlapping_memory;
 
 /// Casts the value at `src` to U. The two types must have the same length.
-#[cfg(target_word_size = "32")]
 #[inline]
 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, mem::size_of::<U>() as u32);
-    dest
-}
-
-/// Casts the value at `src` to U. The two types must have the same length.
-#[cfg(target_word_size = "64")]
-#[inline]
-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, mem::size_of::<U>() as u64);
+    copy_nonoverlapping_memory(dest_ptr, src_ptr, mem::size_of::<U>());
     dest
 }
 
diff --git a/src/libstd/ptr.rs b/src/libstd/ptr.rs
index 376d178f8f7..65ae9f40403 100644
--- a/src/libstd/ptr.rs
+++ b/src/libstd/ptr.rs
@@ -87,7 +87,7 @@ pub fn is_not_null<T,P:RawPtr<T>>(ptr: P) -> bool { ptr.is_not_null() }
  * and destination may overlap.
  */
 #[inline]
-#[cfg(target_word_size = "32")]
+#[cfg(target_word_size = "32", stage0)]
 pub unsafe fn copy_memory<T,P:RawPtr<T>>(dst: *mut T, src: P, count: uint) {
     intrinsics::memmove32(dst,
                           cast::transmute_immut_unsafe(src),
@@ -101,7 +101,7 @@ pub unsafe fn copy_memory<T,P:RawPtr<T>>(dst: *mut T, src: P, count: uint) {
  * and destination may overlap.
  */
 #[inline]
-#[cfg(target_word_size = "64")]
+#[cfg(target_word_size = "64", stage0)]
 pub unsafe fn copy_memory<T,P:RawPtr<T>>(dst: *mut T, src: P, count: uint) {
     intrinsics::memmove64(dst,
                           cast::transmute_immut_unsafe(src),
@@ -112,10 +112,22 @@ pub unsafe fn copy_memory<T,P:RawPtr<T>>(dst: *mut T, src: P, count: uint) {
  * Copies data from one location to another.
  *
  * Copies `count` elements (not bytes) from `src` to `dst`. The source
+ * and destination may overlap.
+ */
+#[inline]
+#[cfg(not(stage0))]
+pub unsafe fn copy_memory<T,P:RawPtr<T>>(dst: *mut T, src: P, count: uint) {
+    intrinsics::copy_memory(dst, cast::transmute_immut_unsafe(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.
  */
 #[inline]
-#[cfg(target_word_size = "32")]
+#[cfg(target_word_size = "32", stage0)]
 pub unsafe fn copy_nonoverlapping_memory<T,P:RawPtr<T>>(dst: *mut T,
                                                         src: P,
                                                         count: uint) {
@@ -131,7 +143,7 @@ pub unsafe fn copy_nonoverlapping_memory<T,P:RawPtr<T>>(dst: *mut T,
  * and destination may *not* overlap.
  */
 #[inline]
-#[cfg(target_word_size = "64")]
+#[cfg(target_word_size = "64", stage0)]
 pub unsafe fn copy_nonoverlapping_memory<T,P:RawPtr<T>>(dst: *mut T,
                                                         src: P,
                                                         count: uint) {
@@ -141,11 +153,25 @@ pub unsafe fn copy_nonoverlapping_memory<T,P:RawPtr<T>>(dst: *mut T,
 }
 
 /**
+ * Copies data from one location to another.
+ *
+ * Copies `count` elements (not bytes) from `src` to `dst`. The source
+ * and destination may *not* overlap.
+ */
+#[inline]
+#[cfg(not(stage0))]
+pub unsafe fn copy_nonoverlapping_memory<T,P:RawPtr<T>>(dst: *mut T,
+                                                        src: P,
+                                                        count: uint) {
+    intrinsics::copy_nonoverlapping_memory(dst, cast::transmute_immut_unsafe(src), count)
+}
+
+/**
  * Invokes memset on the specified pointer, setting `count * size_of::<T>()`
  * bytes of memory starting at `dst` to `c`.
  */
 #[inline]
-#[cfg(target_word_size = "32")]
+#[cfg(target_word_size = "32", stage0)]
 pub unsafe fn set_memory<T>(dst: *mut T, c: u8, count: uint) {
     intrinsics::memset32(dst, c, count as u32);
 }
@@ -155,12 +181,22 @@ pub unsafe fn set_memory<T>(dst: *mut T, c: u8, count: uint) {
  * bytes of memory starting at `dst` to `c`.
  */
 #[inline]
-#[cfg(target_word_size = "64")]
+#[cfg(target_word_size = "64", stage0)]
 pub unsafe fn set_memory<T>(dst: *mut T, c: u8, count: uint) {
     intrinsics::memset64(dst, c, count as u64);
 }
 
 /**
+ * Invokes memset on the specified pointer, setting `count * size_of::<T>()`
+ * bytes of memory starting at `dst` to `c`.
+ */
+#[inline]
+#[cfg(not(stage0))]
+pub unsafe fn set_memory<T>(dst: *mut T, c: u8, count: uint) {
+    intrinsics::set_memory(dst, c, count)
+}
+
+/**
  * Zeroes out `count * size_of::<T>` bytes of memory at `dst`
  */
 #[inline]
diff --git a/src/libstd/unstable/intrinsics.rs b/src/libstd/unstable/intrinsics.rs
index 9d3e3446a4b..c086e13d740 100644
--- a/src/libstd/unstable/intrinsics.rs
+++ b/src/libstd/unstable/intrinsics.rs
@@ -345,25 +345,40 @@ extern "rust-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(stage0)]
     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(stage0)]
     pub fn memcpy64<T>(dst: *mut T, src: *T, count: 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(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(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(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(stage0)]
     pub fn memset64<T>(dst: *mut T, val: u8, count: u64);
 
+    #[cfg(not(stage0))]
+    pub fn copy_nonoverlapping_memory<T>(dst: *mut T, src: *T, count: uint);
+
+    #[cfg(not(stage0))]
+    pub fn copy_memory<T>(dst: *mut T, src: *T, count: uint);
+
+    #[cfg(not(stage0))]
+    pub fn set_memory<T>(dst: *mut T, val: u8, count: uint);
+
     pub fn sqrtf32(x: f32) -> f32;
     pub fn sqrtf64(x: f64) -> f64;