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 @@ -26,12 +26,6 @@ pub mod libc_ { #[nolink] #[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, @@ -97,15 +91,28 @@ pub fn is_not_null(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(dst: *mut T, src: *const T, count: uint) { use unstable::intrinsics::memmove32; let n = count * sys::size_of::(); 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(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", stage0)] pub unsafe fn copy_memory(dst: *mut T, src: *const T, count: uint) { use unstable::intrinsics::memmove64; let n = count * sys::size_of::(); @@ -113,25 +120,40 @@ pub unsafe fn copy_memory(dst: *mut T, src: *const T, count: uint) { } #[inline(always)] -#[cfg(target_word_size = "32")] -pub unsafe fn copy_nonoverlapping_memory(dst: *mut T, src: *const T, count: uint) { - #[cfg(stage0)] - use memcpy32 = unstable::intrinsics::memmove32; - #[cfg(not(stage0))] - use unstable::intrinsics::memcpy32; - let n = count * sys::size_of::(); - memcpy32(dst as *mut u8, src as *u8, n as u32); +#[cfg(target_word_size = "64", not(stage0))] +pub unsafe fn copy_memory(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 = "64")] +#[cfg(target_word_size = "32", stage0)] pub unsafe fn copy_nonoverlapping_memory(dst: *mut T, src: *const T, count: uint) { - #[cfg(stage0)] - use memcpy64 = unstable::intrinsics::memmove64; - #[cfg(not(stage0))] - use unstable::intrinsics::memcpy64; + use unstable::intrinsics::memmove32; let n = count * sys::size_of::(); - memcpy64(dst as *mut u8, src as *u8, n as u64); + 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(dst: *mut T, src: *const T, count: uint) { + 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(dst: *mut T, src: *const T, count: uint) { + use unstable::intrinsics::memmove64; + let n = count * sys::size_of::(); + memmove64(dst as *mut u8, src as *u8, n as u64); +} + +#[inline(always)] +#[cfg(target_word_size = "64", not(stage0))] +pub unsafe fn copy_nonoverlapping_memory(dst: *mut T, src: *const T, count: uint) { + use unstable::intrinsics::memcpy64; + 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::()` and an alignment of `min_align_of::()` #[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(dst: *mut T, src: *T, count: u32); + /// Equivalent to the `llvm.memcpy.p0i8.0i8.i64` intrinsic, with a size of + /// `count` * `size_of::()` and an alignment of `min_align_of::()` #[cfg(not(stage0))] - pub fn memcpy64(dst: *mut u8, src: *u8, size: u64); + pub fn memcpy64(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::()` and an alignment of `min_align_of::()` + #[cfg(not(stage0))] + pub fn memmove32(dst: *mut T, src: *T, count: u32); + /// Equivalent to the `llvm.memmove.p0i8.0i8.i64` intrinsic, with a size of + /// `count` * `size_of::()` and an alignment of `min_align_of::()` + #[cfg(not(stage0))] + pub fn memmove64(dst: *mut T, src: *T, count: u64); + pub fn sqrtf32(x: f32) -> f32; pub fn sqrtf64(x: f64) -> f64;