simplify memcpy/memmove/memset intrinsics
This moves the per-architecture difference into the compiler.
This commit is contained in:
parent
dc079e1596
commit
67966fa9de
@ -74,14 +74,24 @@ fn with_overflow_instrinsic(bcx: @mut Block, name: &'static str, t: ty::t) {
|
||||
}
|
||||
}
|
||||
|
||||
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 @@ fn memcpy_intrinsic(bcx: @mut Block, name: &'static str, tp_ty: ty::t, sizebits:
|
||||
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 @@ fn count_zeros_intrinsic(bcx: @mut Block, name: &'static str) {
|
||||
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),
|
||||
|
@ -3734,7 +3734,7 @@ fn param(ccx: @mut CrateCtxt, n: uint) -> ty::t {
|
||||
mutbl: ast::MutImmutable
|
||||
}))
|
||||
}
|
||||
"memcpy32" => {
|
||||
"copy_nonoverlapping_memory" => {
|
||||
(1,
|
||||
~[
|
||||
ty::mk_ptr(tcx, ty::mt {
|
||||
@ -3745,11 +3745,11 @@ fn param(ccx: @mut CrateCtxt, n: uint) -> ty::t {
|
||||
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,41 +3760,11 @@ fn param(ccx: @mut CrateCtxt, n: uint) -> ty::t {
|
||||
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" => {
|
||||
"set_memory" => {
|
||||
(1,
|
||||
~[
|
||||
ty::mk_ptr(tcx, ty::mt {
|
||||
@ -3802,19 +3772,7 @@ fn param(ccx: @mut CrateCtxt, n: uint) -> ty::t {
|
||||
mutbl: ast::MutMutable
|
||||
}),
|
||||
ty::mk_u8(),
|
||||
ty::mk_u32()
|
||||
],
|
||||
ty::mk_nil())
|
||||
}
|
||||
"memset64" => {
|
||||
(1,
|
||||
~[
|
||||
ty::mk_ptr(tcx, ty::mt {
|
||||
ty: param(ccx, 0),
|
||||
mutbl: ast::MutMutable
|
||||
}),
|
||||
ty::mk_u8(),
|
||||
ty::mk_u64()
|
||||
ty::mk_uint()
|
||||
],
|
||||
ty::mk_nil())
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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,13 +101,25 @@ 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),
|
||||
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<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.
|
||||
*
|
||||
@ -115,7 +127,7 @@ pub unsafe fn copy_memory<T,P:RawPtr<T>>(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<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) {
|
||||
@ -140,12 +152,26 @@ pub unsafe fn copy_nonoverlapping_memory<T,P:RawPtr<T>>(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<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,11 +181,21 @@ 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`
|
||||
*/
|
||||
|
@ -345,25 +345,40 @@ fn visit_leave_fn(&mut self, purity: uint, proto: uint,
|
||||
|
||||
/// 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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user