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.
This commit is contained in:
parent
f254d119ea
commit
cf8e9f9aec
@ -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);
|
||||
|
@ -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" |
|
||||
|
@ -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()
|
||||
|
@ -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<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 = "64")]
|
||||
#[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", 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")]
|
||||
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;
|
||||
let n = count * sys::size_of::<T>();
|
||||
memcpy32(dst as *mut u8, src as *u8, n as u32);
|
||||
#[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 = "64")]
|
||||
#[cfg(target_word_size = "32", 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;
|
||||
use unstable::intrinsics::memmove32;
|
||||
let n = count * sys::size_of::<T>();
|
||||
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<T>(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<T>(dst: *mut T, src: *const T, count: uint) {
|
||||
use unstable::intrinsics::memmove64;
|
||||
let n = count * sys::size_of::<T>();
|
||||
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<T>(dst: *mut T, src: *const T, count: uint) {
|
||||
use unstable::intrinsics::memcpy64;
|
||||
memcpy64(dst, src as *T, count as u64);
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user