Skip to content

Commit cf8e9f9

Browse files
committed
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.
1 parent f254d11 commit cf8e9f9

File tree

5 files changed

+111
-64
lines changed

5 files changed

+111
-64
lines changed

src/librustc/middle/trans/foreign.rs

Lines changed: 40 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -846,44 +846,56 @@ pub fn trans_intrinsic(ccx: @CrateContext,
846846
Store(bcx, morestack_addr, fcx.llretptr.get());
847847
}
848848
~"memcpy32" => {
849-
let dst_ptr = get_param(decl, first_real_arg);
850-
let src_ptr = get_param(decl, first_real_arg + 1);
851-
let size = get_param(decl, first_real_arg + 2);
852-
let align = C_i32(1);
849+
let tp_ty = substs.tys[0];
850+
let lltp_ty = type_of::type_of(ccx, tp_ty);
851+
let align = C_i32(machine::llalign_of_min(ccx, lltp_ty) as i32);
852+
let size = C_i32(machine::llsize_of_real(ccx, lltp_ty) as i32);
853+
854+
let dst_ptr = PointerCast(bcx, get_param(decl, first_real_arg), T_ptr(T_i8()));
855+
let src_ptr = PointerCast(bcx, get_param(decl, first_real_arg + 1), T_ptr(T_i8()));
856+
let count = get_param(decl, first_real_arg + 2);
853857
let volatile = C_i1(false);
854-
let llfn = *bcx.ccx().intrinsics.get(
855-
&~"llvm.memcpy.p0i8.p0i8.i32");
856-
Call(bcx, llfn, [dst_ptr, src_ptr, size, align, volatile]);
858+
let llfn = *bcx.ccx().intrinsics.get(&~"llvm.memcpy.p0i8.p0i8.i32");
859+
Call(bcx, llfn, [dst_ptr, src_ptr, Mul(bcx, size, count), align, volatile]);
857860
}
858861
~"memcpy64" => {
859-
let dst_ptr = get_param(decl, first_real_arg);
860-
let src_ptr = get_param(decl, first_real_arg + 1);
861-
let size = get_param(decl, first_real_arg + 2);
862-
let align = C_i32(1);
862+
let tp_ty = substs.tys[0];
863+
let lltp_ty = type_of::type_of(ccx, tp_ty);
864+
let align = C_i32(machine::llalign_of_min(ccx, lltp_ty) as i32);
865+
let size = C_i64(machine::llsize_of_real(ccx, lltp_ty) as i64);
866+
867+
let dst_ptr = PointerCast(bcx, get_param(decl, first_real_arg), T_ptr(T_i8()));
868+
let src_ptr = PointerCast(bcx, get_param(decl, first_real_arg + 1), T_ptr(T_i8()));
869+
let count = get_param(decl, first_real_arg + 2);
863870
let volatile = C_i1(false);
864-
let llfn = *bcx.ccx().intrinsics.get(
865-
&~"llvm.memcpy.p0i8.p0i8.i64");
866-
Call(bcx, llfn, [dst_ptr, src_ptr, size, align, volatile]);
871+
let llfn = *bcx.ccx().intrinsics.get(&~"llvm.memcpy.p0i8.p0i8.i64");
872+
Call(bcx, llfn, [dst_ptr, src_ptr, Mul(bcx, size, count), align, volatile]);
867873
}
868874
~"memmove32" => {
869-
let dst_ptr = get_param(decl, first_real_arg);
870-
let src_ptr = get_param(decl, first_real_arg + 1);
871-
let size = get_param(decl, first_real_arg + 2);
872-
let align = C_i32(1);
875+
let tp_ty = substs.tys[0];
876+
let lltp_ty = type_of::type_of(ccx, tp_ty);
877+
let align = C_i32(machine::llalign_of_min(ccx, lltp_ty) as i32);
878+
let size = C_i32(machine::llsize_of_real(ccx, lltp_ty) as i32);
879+
880+
let dst_ptr = PointerCast(bcx, get_param(decl, first_real_arg), T_ptr(T_i8()));
881+
let src_ptr = PointerCast(bcx, get_param(decl, first_real_arg + 1), T_ptr(T_i8()));
882+
let count = get_param(decl, first_real_arg + 2);
873883
let volatile = C_i1(false);
874-
let llfn = *bcx.ccx().intrinsics.get(
875-
&~"llvm.memmove.p0i8.p0i8.i32");
876-
Call(bcx, llfn, [dst_ptr, src_ptr, size, align, volatile]);
884+
let llfn = *bcx.ccx().intrinsics.get(&~"llvm.memmove.p0i8.p0i8.i32");
885+
Call(bcx, llfn, [dst_ptr, src_ptr, Mul(bcx, size, count), align, volatile]);
877886
}
878887
~"memmove64" => {
879-
let dst_ptr = get_param(decl, first_real_arg);
880-
let src_ptr = get_param(decl, first_real_arg + 1);
881-
let size = get_param(decl, first_real_arg + 2);
882-
let align = C_i32(1);
888+
let tp_ty = substs.tys[0];
889+
let lltp_ty = type_of::type_of(ccx, tp_ty);
890+
let align = C_i32(machine::llalign_of_min(ccx, lltp_ty) as i32);
891+
let size = C_i64(machine::llsize_of_real(ccx, lltp_ty) as i64);
892+
893+
let dst_ptr = PointerCast(bcx, get_param(decl, first_real_arg), T_ptr(T_i8()));
894+
let src_ptr = PointerCast(bcx, get_param(decl, first_real_arg + 1), T_ptr(T_i8()));
895+
let count = get_param(decl, first_real_arg + 2);
883896
let volatile = C_i1(false);
884-
let llfn = *bcx.ccx().intrinsics.get(
885-
&~"llvm.memmove.p0i8.p0i8.i64");
886-
Call(bcx, llfn, [dst_ptr, src_ptr, size, align, volatile]);
897+
let llfn = *bcx.ccx().intrinsics.get(&~"llvm.memmove.p0i8.p0i8.i64");
898+
Call(bcx, llfn, [dst_ptr, src_ptr, Mul(bcx, size, count), align, volatile]);
887899
}
888900
~"sqrtf32" => {
889901
let x = get_param(decl, first_real_arg);

src/librustc/middle/trans/type_use.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ pub fn type_uses_for(ccx: @CrateContext, fn_id: def_id, n_tps: uint)
135135
~"visit_tydesc" | ~"forget" | ~"frame_address" |
136136
~"morestack_addr" => 0,
137137

138-
~"memcpy32" | ~"memcpy64" | ~"memmove32" | ~"memmove64" => 0,
138+
~"memcpy32" | ~"memcpy64" | ~"memmove32" | ~"memmove64" => use_repr,
139139

140140
~"sqrtf32" | ~"sqrtf64" | ~"powif32" | ~"powif64" |
141141
~"sinf32" | ~"sinf64" | ~"cosf32" | ~"cosf64" |

src/librustc/middle/typeck/check/mod.rs

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3538,59 +3538,59 @@ pub fn check_intrinsic_type(ccx: @mut CrateCtxt, it: @ast::foreign_item) {
35383538
(0u, ~[], ty::mk_nil_ptr(ccx.tcx))
35393539
}
35403540
~"memcpy32" => {
3541-
(0,
3541+
(1,
35423542
~[
35433543
ty::mk_ptr(tcx, ty::mt {
3544-
ty: ty::mk_u8(),
3544+
ty: param(ccx, 0),
35453545
mutbl: ast::m_mutbl
35463546
}),
35473547
ty::mk_ptr(tcx, ty::mt {
3548-
ty: ty::mk_u8(),
3548+
ty: param(ccx, 0),
35493549
mutbl: ast::m_imm
35503550
}),
35513551
ty::mk_u32()
35523552
],
35533553
ty::mk_nil())
35543554
}
35553555
~"memcpy64" => {
3556-
(0,
3556+
(1,
35573557
~[
35583558
ty::mk_ptr(tcx, ty::mt {
3559-
ty: ty::mk_u8(),
3559+
ty: param(ccx, 0),
35603560
mutbl: ast::m_mutbl
35613561
}),
35623562
ty::mk_ptr(tcx, ty::mt {
3563-
ty: ty::mk_u8(),
3563+
ty: param(ccx, 0),
35643564
mutbl: ast::m_imm
35653565
}),
35663566
ty::mk_u64()
35673567
],
35683568
ty::mk_nil())
35693569
}
35703570
~"memmove32" => {
3571-
(0,
3571+
(1,
35723572
~[
35733573
ty::mk_ptr(tcx, ty::mt {
3574-
ty: ty::mk_u8(),
3574+
ty: param(ccx, 0),
35753575
mutbl: ast::m_mutbl
35763576
}),
35773577
ty::mk_ptr(tcx, ty::mt {
3578-
ty: ty::mk_u8(),
3578+
ty: param(ccx, 0),
35793579
mutbl: ast::m_imm
35803580
}),
35813581
ty::mk_u32()
35823582
],
35833583
ty::mk_nil())
35843584
}
35853585
~"memmove64" => {
3586-
(0,
3586+
(1,
35873587
~[
35883588
ty::mk_ptr(tcx, ty::mt {
3589-
ty: ty::mk_u8(),
3589+
ty: param(ccx, 0),
35903590
mutbl: ast::m_mutbl
35913591
}),
35923592
ty::mk_ptr(tcx, ty::mt {
3593-
ty: ty::mk_u8(),
3593+
ty: param(ccx, 0),
35943594
mutbl: ast::m_imm
35953595
}),
35963596
ty::mk_u64()

src/libstd/ptr.rs

Lines changed: 41 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,6 @@ pub mod libc_ {
2626
#[nolink]
2727
#[abi = "cdecl"]
2828
pub extern {
29-
#[rust_stack]
30-
unsafe fn memmove(dest: *mut c_void,
31-
src: *const c_void,
32-
n: libc::size_t)
33-
-> *c_void;
34-
3529
#[rust_stack]
3630
unsafe fn memset(dest: *mut c_void,
3731
c: libc::c_int,
@@ -97,41 +91,69 @@ pub fn is_not_null<T>(ptr: *const T) -> bool { !is_null(ptr) }
9791
* and destination may overlap.
9892
*/
9993
#[inline(always)]
100-
#[cfg(target_word_size = "32")]
94+
#[cfg(target_word_size = "32", stage0)]
10195
pub unsafe fn copy_memory<T>(dst: *mut T, src: *const T, count: uint) {
10296
use unstable::intrinsics::memmove32;
10397
let n = count * sys::size_of::<T>();
10498
memmove32(dst as *mut u8, src as *u8, n as u32);
10599
}
106100

101+
/**
102+
* Copies data from one location to another
103+
*
104+
* Copies `count` elements (not bytes) from `src` to `dst`. The source
105+
* and destination may overlap.
106+
*/
107+
#[inline(always)]
108+
#[cfg(target_word_size = "32", not(stage0))]
109+
pub unsafe fn copy_memory<T>(dst: *mut T, src: *const T, count: uint) {
110+
use unstable::intrinsics::memmove32;
111+
memmove32(dst, src, count as u32);
112+
}
113+
107114
#[inline(always)]
108-
#[cfg(target_word_size = "64")]
115+
#[cfg(target_word_size = "64", stage0)]
109116
pub unsafe fn copy_memory<T>(dst: *mut T, src: *const T, count: uint) {
110117
use unstable::intrinsics::memmove64;
111118
let n = count * sys::size_of::<T>();
112119
memmove64(dst as *mut u8, src as *u8, n as u64);
113120
}
114121

115122
#[inline(always)]
116-
#[cfg(target_word_size = "32")]
123+
#[cfg(target_word_size = "64", not(stage0))]
124+
pub unsafe fn copy_memory<T>(dst: *mut T, src: *const T, count: uint) {
125+
use unstable::intrinsics::memmove64;
126+
memmove64(dst, src as *T, count as u64);
127+
}
128+
129+
#[inline(always)]
130+
#[cfg(target_word_size = "32", stage0)]
131+
pub unsafe fn copy_nonoverlapping_memory<T>(dst: *mut T, src: *const T, count: uint) {
132+
use unstable::intrinsics::memmove32;
133+
let n = count * sys::size_of::<T>();
134+
memmove32(dst as *mut u8, src as *u8, n as u32);
135+
}
136+
137+
#[inline(always)]
138+
#[cfg(target_word_size = "32", not(stage0))]
117139
pub unsafe fn copy_nonoverlapping_memory<T>(dst: *mut T, src: *const T, count: uint) {
118-
#[cfg(stage0)]
119-
use memcpy32 = unstable::intrinsics::memmove32;
120-
#[cfg(not(stage0))]
121140
use unstable::intrinsics::memcpy32;
141+
memcpy32(dst, src as *T, count as u32);
142+
}
143+
144+
#[inline(always)]
145+
#[cfg(target_word_size = "64", stage0)]
146+
pub unsafe fn copy_nonoverlapping_memory<T>(dst: *mut T, src: *const T, count: uint) {
147+
use unstable::intrinsics::memmove64;
122148
let n = count * sys::size_of::<T>();
123-
memcpy32(dst as *mut u8, src as *u8, n as u32);
149+
memmove64(dst as *mut u8, src as *u8, n as u64);
124150
}
125151

126152
#[inline(always)]
127-
#[cfg(target_word_size = "64")]
153+
#[cfg(target_word_size = "64", not(stage0))]
128154
pub unsafe fn copy_nonoverlapping_memory<T>(dst: *mut T, src: *const T, count: uint) {
129-
#[cfg(stage0)]
130-
use memcpy64 = unstable::intrinsics::memmove64;
131-
#[cfg(not(stage0))]
132155
use unstable::intrinsics::memcpy64;
133-
let n = count * sys::size_of::<T>();
134-
memcpy64(dst as *mut u8, src as *u8, n as u64);
156+
memcpy64(dst, src as *T, count as u64);
135157
}
136158

137159
#[inline(always)]

src/libstd/unstable/intrinsics.rs

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -127,18 +127,31 @@ pub extern "rust-intrinsic" {
127127
/// Get the address of the `__morestack` stack growth function.
128128
pub fn morestack_addr() -> *();
129129

130-
/// Equivalent to the `llvm.memcpy.p0i8.0i8.i32` intrinsic.
130+
/// Equivalent to the `llvm.memcpy.p0i8.0i8.i32` intrinsic, with a size of
131+
/// `count` * `size_of::<T>()` and an alignment of `min_align_of::<T>()`
131132
#[cfg(not(stage0))]
132-
pub fn memcpy32(dst: *mut u8, src: *u8, size: u32);
133-
/// Equivalent to the `llvm.memcpy.p0i8.0i8.i64` intrinsic.
133+
pub fn memcpy32<T>(dst: *mut T, src: *T, count: u32);
134+
/// Equivalent to the `llvm.memcpy.p0i8.0i8.i64` intrinsic, with a size of
135+
/// `count` * `size_of::<T>()` and an alignment of `min_align_of::<T>()`
134136
#[cfg(not(stage0))]
135-
pub fn memcpy64(dst: *mut u8, src: *u8, size: u64);
137+
pub fn memcpy64<T>(dst: *mut T, src: *T, count: u64);
136138

137139
/// Equivalent to the `llvm.memmove.p0i8.0i8.i32` intrinsic.
140+
#[cfg(stage0)]
138141
pub fn memmove32(dst: *mut u8, src: *u8, size: u32);
139142
/// Equivalent to the `llvm.memmove.p0i8.0i8.i64` intrinsic.
143+
#[cfg(stage0)]
140144
pub fn memmove64(dst: *mut u8, src: *u8, size: u64);
141145

146+
/// Equivalent to the `llvm.memmove.p0i8.0i8.i32` intrinsic, with a size of
147+
/// `count` * `size_of::<T>()` and an alignment of `min_align_of::<T>()`
148+
#[cfg(not(stage0))]
149+
pub fn memmove32<T>(dst: *mut T, src: *T, count: u32);
150+
/// Equivalent to the `llvm.memmove.p0i8.0i8.i64` intrinsic, with a size of
151+
/// `count` * `size_of::<T>()` and an alignment of `min_align_of::<T>()`
152+
#[cfg(not(stage0))]
153+
pub fn memmove64<T>(dst: *mut T, src: *T, count: u64);
154+
142155
pub fn sqrtf32(x: f32) -> f32;
143156
pub fn sqrtf64(x: f64) -> f64;
144157

0 commit comments

Comments
 (0)