about summary refs log tree commit diff
diff options
context:
space:
mode:
authorDaniel Micay <danielmicay@gmail.com>2013-05-24 13:58:55 -0400
committerDaniel Micay <danielmicay@gmail.com>2013-05-26 10:26:03 -0400
commitcf8e9f9aec25b6441d3198d7ddb4bd6a6b9e1475 (patch)
treed6e7e72c11ed6ab0c10a8210596af1d530069007
parentf254d119eab514c91fbd6590fba821ec7a0bfd7f (diff)
downloadrust-cf8e9f9aec25b6441d3198d7ddb4bd6a6b9e1475.tar.gz
rust-cf8e9f9aec25b6441d3198d7ddb4bd6a6b9e1475.zip
make the memcpy/memmove intrinsics higher-level
This allows them to make use of the type's alignment, instead of being
pessimistic and assuming it is only 1.
-rw-r--r--src/librustc/middle/trans/foreign.rs68
-rw-r--r--src/librustc/middle/trans/type_use.rs2
-rw-r--r--src/librustc/middle/typeck/check/mod.rs24
-rw-r--r--src/libstd/ptr.rs60
-rw-r--r--src/libstd/unstable/intrinsics.rs21
5 files changed, 111 insertions, 64 deletions
diff --git a/src/librustc/middle/trans/foreign.rs b/src/librustc/middle/trans/foreign.rs
index 58c77f037de..6f420fc44ca 100644
--- a/src/librustc/middle/trans/foreign.rs
+++ b/src/librustc/middle/trans/foreign.rs
@@ -846,44 +846,56 @@ pub fn trans_intrinsic(ccx: @CrateContext,
             Store(bcx, morestack_addr, fcx.llretptr.get());
         }
         ~"memcpy32" => {
-            let dst_ptr = get_param(decl, first_real_arg);
-            let src_ptr = get_param(decl, first_real_arg + 1);
-            let size = get_param(decl, first_real_arg + 2);
-            let align = C_i32(1);
+            let tp_ty = substs.tys[0];
+            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 = C_i32(machine::llsize_of_real(ccx, lltp_ty) as i32);
+
+            let dst_ptr = PointerCast(bcx, get_param(decl, first_real_arg), T_ptr(T_i8()));
+            let src_ptr = PointerCast(bcx, get_param(decl, first_real_arg + 1), T_ptr(T_i8()));
+            let count = get_param(decl, first_real_arg + 2);
             let volatile = C_i1(false);
-            let llfn = *bcx.ccx().intrinsics.get(
-                &~"llvm.memcpy.p0i8.p0i8.i32");
-            Call(bcx, llfn, [dst_ptr, src_ptr, size, align, volatile]);
+            let llfn = *bcx.ccx().intrinsics.get(&~"llvm.memcpy.p0i8.p0i8.i32");
+            Call(bcx, llfn, [dst_ptr, src_ptr, Mul(bcx, size, count), align, volatile]);
         }
         ~"memcpy64" => {
-            let dst_ptr = get_param(decl, first_real_arg);
-            let src_ptr = get_param(decl, first_real_arg + 1);
-            let size = get_param(decl, first_real_arg + 2);
-            let align = C_i32(1);
+            let tp_ty = substs.tys[0];
+            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 = C_i64(machine::llsize_of_real(ccx, lltp_ty) as i64);
+
+            let dst_ptr = PointerCast(bcx, get_param(decl, first_real_arg), T_ptr(T_i8()));
+            let src_ptr = PointerCast(bcx, get_param(decl, first_real_arg + 1), T_ptr(T_i8()));
+            let count = get_param(decl, first_real_arg + 2);
             let volatile = C_i1(false);
-            let llfn = *bcx.ccx().intrinsics.get(
-                &~"llvm.memcpy.p0i8.p0i8.i64");
-            Call(bcx, llfn, [dst_ptr, src_ptr, size, align, volatile]);
+            let llfn = *bcx.ccx().intrinsics.get(&~"llvm.memcpy.p0i8.p0i8.i64");
+            Call(bcx, llfn, [dst_ptr, src_ptr, Mul(bcx, size, count), align, volatile]);
         }
         ~"memmove32" => {
-            let dst_ptr = get_param(decl, first_real_arg);
-            let src_ptr = get_param(decl, first_real_arg + 1);
-            let size = get_param(decl, first_real_arg + 2);
-            let align = C_i32(1);
+            let tp_ty = substs.tys[0];
+            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 = C_i32(machine::llsize_of_real(ccx, lltp_ty) as i32);
+
+            let dst_ptr = PointerCast(bcx, get_param(decl, first_real_arg), T_ptr(T_i8()));
+            let src_ptr = PointerCast(bcx, get_param(decl, first_real_arg + 1), T_ptr(T_i8()));
+            let count = get_param(decl, first_real_arg + 2);
             let volatile = C_i1(false);
-            let llfn = *bcx.ccx().intrinsics.get(
-                &~"llvm.memmove.p0i8.p0i8.i32");
-            Call(bcx, llfn, [dst_ptr, src_ptr, size, align, volatile]);
+            let llfn = *bcx.ccx().intrinsics.get(&~"llvm.memmove.p0i8.p0i8.i32");
+            Call(bcx, llfn, [dst_ptr, src_ptr, Mul(bcx, size, count), align, volatile]);
         }
         ~"memmove64" => {
-            let dst_ptr = get_param(decl, first_real_arg);
-            let src_ptr = get_param(decl, first_real_arg + 1);
-            let size = get_param(decl, first_real_arg + 2);
-            let align = C_i32(1);
+            let tp_ty = substs.tys[0];
+            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 = C_i64(machine::llsize_of_real(ccx, lltp_ty) as i64);
+
+            let dst_ptr = PointerCast(bcx, get_param(decl, first_real_arg), T_ptr(T_i8()));
+            let src_ptr = PointerCast(bcx, get_param(decl, first_real_arg + 1), T_ptr(T_i8()));
+            let count = get_param(decl, first_real_arg + 2);
             let volatile = C_i1(false);
-            let llfn = *bcx.ccx().intrinsics.get(
-                &~"llvm.memmove.p0i8.p0i8.i64");
-            Call(bcx, llfn, [dst_ptr, src_ptr, size, align, volatile]);
+            let llfn = *bcx.ccx().intrinsics.get(&~"llvm.memmove.p0i8.p0i8.i64");
+            Call(bcx, llfn, [dst_ptr, src_ptr, Mul(bcx, size, count), align, volatile]);
         }
         ~"sqrtf32" => {
             let x = get_param(decl, first_real_arg);
diff --git a/src/librustc/middle/trans/type_use.rs b/src/librustc/middle/trans/type_use.rs
index d4c34a3ace5..a9416a46ddf 100644
--- a/src/librustc/middle/trans/type_use.rs
+++ b/src/librustc/middle/trans/type_use.rs
@@ -135,7 +135,7 @@ pub fn type_uses_for(ccx: @CrateContext, fn_id: def_id, n_tps: uint)
                 ~"visit_tydesc"  | ~"forget" | ~"frame_address" |
                 ~"morestack_addr" => 0,
 
-                ~"memcpy32" | ~"memcpy64" | ~"memmove32" | ~"memmove64" => 0,
+                ~"memcpy32" | ~"memcpy64" | ~"memmove32" | ~"memmove64" => use_repr,
 
                 ~"sqrtf32" | ~"sqrtf64" | ~"powif32" | ~"powif64" |
                 ~"sinf32"  | ~"sinf64"  | ~"cosf32"  | ~"cosf64"  |
diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs
index 6ae03ee4506..1d959a54c0e 100644
--- a/src/librustc/middle/typeck/check/mod.rs
+++ b/src/librustc/middle/typeck/check/mod.rs
@@ -3538,14 +3538,14 @@ pub fn check_intrinsic_type(ccx: @mut CrateCtxt, it: @ast::foreign_item) {
           (0u, ~[], ty::mk_nil_ptr(ccx.tcx))
         }
         ~"memcpy32" => {
-          (0,
+          (1,
            ~[
               ty::mk_ptr(tcx, ty::mt {
-                  ty: ty::mk_u8(),
+                  ty: param(ccx, 0),
                   mutbl: ast::m_mutbl
               }),
               ty::mk_ptr(tcx, ty::mt {
-                  ty: ty::mk_u8(),
+                  ty: param(ccx, 0),
                   mutbl: ast::m_imm
               }),
               ty::mk_u32()
@@ -3553,14 +3553,14 @@ pub fn check_intrinsic_type(ccx: @mut CrateCtxt, it: @ast::foreign_item) {
            ty::mk_nil())
         }
         ~"memcpy64" => {
-          (0,
+          (1,
            ~[
               ty::mk_ptr(tcx, ty::mt {
-                  ty: ty::mk_u8(),
+                  ty: param(ccx, 0),
                   mutbl: ast::m_mutbl
               }),
               ty::mk_ptr(tcx, ty::mt {
-                  ty: ty::mk_u8(),
+                  ty: param(ccx, 0),
                   mutbl: ast::m_imm
               }),
               ty::mk_u64()
@@ -3568,14 +3568,14 @@ pub fn check_intrinsic_type(ccx: @mut CrateCtxt, it: @ast::foreign_item) {
            ty::mk_nil())
         }
         ~"memmove32" => {
-          (0,
+          (1,
            ~[
               ty::mk_ptr(tcx, ty::mt {
-                  ty: ty::mk_u8(),
+                  ty: param(ccx, 0),
                   mutbl: ast::m_mutbl
               }),
               ty::mk_ptr(tcx, ty::mt {
-                  ty: ty::mk_u8(),
+                  ty: param(ccx, 0),
                   mutbl: ast::m_imm
               }),
               ty::mk_u32()
@@ -3583,14 +3583,14 @@ pub fn check_intrinsic_type(ccx: @mut CrateCtxt, it: @ast::foreign_item) {
            ty::mk_nil())
         }
         ~"memmove64" => {
-          (0,
+          (1,
            ~[
               ty::mk_ptr(tcx, ty::mt {
-                  ty: ty::mk_u8(),
+                  ty: param(ccx, 0),
                   mutbl: ast::m_mutbl
               }),
               ty::mk_ptr(tcx, ty::mt {
-                  ty: ty::mk_u8(),
+                  ty: param(ccx, 0),
                   mutbl: ast::m_imm
               }),
               ty::mk_u64()
diff --git a/src/libstd/ptr.rs b/src/libstd/ptr.rs
index d1c0ffe7953..97a7d0e11a6 100644
--- a/src/libstd/ptr.rs
+++ b/src/libstd/ptr.rs
@@ -27,12 +27,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 +91,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 = "32", not(stage0))]
+pub unsafe fn copy_memory<T>(dst: *mut T, src: *const T, count: uint) {
+    use unstable::intrinsics::memmove32;
+    memmove32(dst, src, count as u32);
+}
+
 #[inline(always)]
-#[cfg(target_word_size = "64")]
+#[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,25 +120,40 @@ 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)]
diff --git a/src/libstd/unstable/intrinsics.rs b/src/libstd/unstable/intrinsics.rs
index 521708621fc..c0975d6a526 100644
--- a/src/libstd/unstable/intrinsics.rs
+++ b/src/libstd/unstable/intrinsics.rs
@@ -127,18 +127,31 @@ 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);
+
     pub fn sqrtf32(x: f32) -> f32;
     pub fn sqrtf64(x: f64) -> f64;