diff --git a/src/librustc/middle/trans/intrinsic.rs b/src/librustc/middle/trans/intrinsic.rs index ce62b26c9ab8c..4618cdf45ee08 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 b0196010cb06b..011d39af7a8c8 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 a4f2ee0d09c78..05a72dc4109e7 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(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::() 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(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::() as u64); + copy_nonoverlapping_memory(dest_ptr, src_ptr, mem::size_of::()); dest } diff --git a/src/libstd/ptr.rs b/src/libstd/ptr.rs index 376d178f8f723..65ae9f40403b6 100644 --- a/src/libstd/ptr.rs +++ b/src/libstd/ptr.rs @@ -87,7 +87,7 @@ pub fn is_not_null>(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>(dst: *mut T, src: P, count: uint) { intrinsics::memmove32(dst, cast::transmute_immut_unsafe(src), @@ -101,13 +101,25 @@ pub unsafe fn copy_memory>(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>(dst: *mut T, src: P, count: uint) { intrinsics::memmove64(dst, cast::transmute_immut_unsafe(src), count as u64); } +/** + * 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>(dst: *mut T, src: P, count: uint) { + intrinsics::copy_memory(dst, cast::transmute_immut_unsafe(src), count) +} + /** * Copies data from one location to another. * @@ -115,7 +127,7 @@ pub unsafe fn copy_memory>(dst: *mut T, src: P, count: uint) { * and destination may *not* overlap. */ #[inline] -#[cfg(target_word_size = "32")] +#[cfg(target_word_size = "32", stage0)] pub unsafe fn copy_nonoverlapping_memory>(dst: *mut T, src: P, count: uint) { @@ -131,7 +143,7 @@ pub unsafe fn copy_nonoverlapping_memory>(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>(dst: *mut T, src: P, count: uint) { @@ -140,12 +152,26 @@ pub unsafe fn copy_nonoverlapping_memory>(dst: *mut T, count as u64); } +/** + * 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>(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::()` * 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(dst: *mut T, c: u8, count: uint) { intrinsics::memset32(dst, c, count as u32); } @@ -155,11 +181,21 @@ pub unsafe fn set_memory(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(dst: *mut T, c: u8, count: uint) { intrinsics::memset64(dst, c, count as u64); } +/** + * Invokes memset on the specified pointer, setting `count * size_of::()` + * bytes of memory starting at `dst` to `c`. + */ +#[inline] +#[cfg(not(stage0))] +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` */ diff --git a/src/libstd/unstable/intrinsics.rs b/src/libstd/unstable/intrinsics.rs index 9d3e3446a4bfd..c086e13d74024 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::()` and an alignment of `min_align_of::()` + #[cfg(stage0)] 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(stage0)] pub fn memcpy64(dst: *mut T, src: *T, count: 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(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(stage0)] pub fn memmove64(dst: *mut T, src: *T, count: u64); /// Equivalent to the `llvm.memset.p0i8.i32` intrinsic, with a size of /// `count` * `size_of::()` and an alignment of `min_align_of::()` + #[cfg(stage0)] pub fn memset32(dst: *mut T, val: u8, count: u32); /// Equivalent to the `llvm.memset.p0i8.i64` intrinsic, with a size of /// `count` * `size_of::()` and an alignment of `min_align_of::()` + #[cfg(stage0)] pub fn memset64(dst: *mut T, val: u8, count: u64); + #[cfg(not(stage0))] + pub fn copy_nonoverlapping_memory(dst: *mut T, src: *T, count: uint); + + #[cfg(not(stage0))] + pub fn copy_memory(dst: *mut T, src: *T, count: uint); + + #[cfg(not(stage0))] + pub fn set_memory(dst: *mut T, val: u8, count: uint); + pub fn sqrtf32(x: f32) -> f32; pub fn sqrtf64(x: f64) -> f64;