Skip to content

Commit 997b86d

Browse files
committed
Implement LLVM's elementwise unordered atomic memory intrinsics
Allows uses of intrinsics of the form llvm.(memcpy|memmove|memset).element.unordered.atomic.* to be linked.
1 parent 36da64f commit 997b86d

File tree

1 file changed

+106
-0
lines changed

1 file changed

+106
-0
lines changed

src/mem.rs

+106
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ type c_int = i16;
55
#[cfg(not(target_pointer_width = "16"))]
66
type c_int = i32;
77

8+
use core::intrinsics::{atomic_load_unordered, atomic_store_unordered, unchecked_div};
9+
use core::mem;
10+
use core::ops::{BitOr, Shl};
11+
812
#[cfg_attr(all(feature = "mem", not(feature = "mangled-names")), no_mangle)]
913
pub unsafe extern "C" fn memcpy(dest: *mut u8, src: *const u8, n: usize) -> *mut u8 {
1014
let mut i = 0;
@@ -58,3 +62,105 @@ pub unsafe extern "C" fn memcmp(s1: *const u8, s2: *const u8, n: usize) -> i32 {
5862
}
5963
0
6064
}
65+
66+
fn memcpy_element_unordered_atomic<T: Copy>(dest: *mut T, src: *const T, bytes: usize) {
67+
unsafe {
68+
let n = unchecked_div(bytes, mem::size_of::<T>());
69+
let mut i = 0;
70+
while i < n {
71+
atomic_store_unordered(dest.add(i), atomic_load_unordered(src.add(i)));
72+
i += 1;
73+
}
74+
}
75+
}
76+
77+
fn memmove_element_unordered_atomic<T: Copy>(dest: *mut T, src: *const T, bytes: usize) {
78+
unsafe {
79+
let n = unchecked_div(bytes, mem::size_of::<T>());
80+
if src < dest as *const T {
81+
// copy from end
82+
let mut i = n;
83+
while i != 0 {
84+
i -= 1;
85+
atomic_store_unordered(dest.add(i), atomic_load_unordered(src.add(i)));
86+
}
87+
} else {
88+
// copy from beginning
89+
let mut i = 0;
90+
while i < n {
91+
atomic_store_unordered(dest.add(i), atomic_load_unordered(src.add(i)));
92+
i += 1;
93+
}
94+
}
95+
}
96+
}
97+
98+
fn memset_element_unordered_atomic<T>(s: *mut T, c: u8, bytes: usize)
99+
where
100+
T: Copy + From<u8> + Shl<u32, Output = T> + BitOr<T, Output = T>,
101+
{
102+
unsafe {
103+
let n = unchecked_div(bytes, mem::size_of::<T>());
104+
let mut x = T::from(c);
105+
let mut i = 1;
106+
while i < mem::size_of::<T>() {
107+
x = x << 8 | T::from(c);
108+
i += 1;
109+
}
110+
let mut i = 0;
111+
while i < n {
112+
atomic_store_unordered(s.add(i), x);
113+
i += 1;
114+
}
115+
}
116+
}
117+
118+
intrinsics! {
119+
pub extern "C" fn __llvm_memcpy_element_unordered_atomic_1(dest: *mut u8, src: *const u8, bytes: usize) -> () {
120+
memcpy_element_unordered_atomic(dest, src, bytes);
121+
}
122+
pub extern "C" fn __llvm_memcpy_element_unordered_atomic_2(dest: *mut u16, src: *const u16, bytes: usize) -> () {
123+
memcpy_element_unordered_atomic(dest, src, bytes);
124+
}
125+
pub extern "C" fn __llvm_memcpy_element_unordered_atomic_4(dest: *mut u32, src: *const u32, bytes: usize) -> () {
126+
memcpy_element_unordered_atomic(dest, src, bytes);
127+
}
128+
pub extern "C" fn __llvm_memcpy_element_unordered_atomic_8(dest: *mut u64, src: *const u64, bytes: usize) -> () {
129+
memcpy_element_unordered_atomic(dest, src, bytes);
130+
}
131+
pub extern "C" fn __llvm_memcpy_element_unordered_atomic_16(dest: *mut u128, src: *const u128, bytes: usize) -> () {
132+
memcpy_element_unordered_atomic(dest, src, bytes);
133+
}
134+
135+
pub extern "C" fn __llvm_memmove_element_unordered_atomic_1(dest: *mut u8, src: *const u8, bytes: usize) -> () {
136+
memmove_element_unordered_atomic(dest, src, bytes);
137+
}
138+
pub extern "C" fn __llvm_memmove_element_unordered_atomic_2(dest: *mut u16, src: *const u16, bytes: usize) -> () {
139+
memmove_element_unordered_atomic(dest, src, bytes);
140+
}
141+
pub extern "C" fn __llvm_memmove_element_unordered_atomic_4(dest: *mut u32, src: *const u32, bytes: usize) -> () {
142+
memmove_element_unordered_atomic(dest, src, bytes);
143+
}
144+
pub extern "C" fn __llvm_memmove_element_unordered_atomic_8(dest: *mut u64, src: *const u64, bytes: usize) -> () {
145+
memmove_element_unordered_atomic(dest, src, bytes);
146+
}
147+
pub extern "C" fn __llvm_memmove_element_unordered_atomic_16(dest: *mut u128, src: *const u128, bytes: usize) -> () {
148+
memmove_element_unordered_atomic(dest, src, bytes);
149+
}
150+
151+
pub extern "C" fn __llvm_memset_element_unordered_atomic_1(s: *mut u8, c: u8, bytes: usize) -> () {
152+
memset_element_unordered_atomic(s, c, bytes);
153+
}
154+
pub extern "C" fn __llvm_memset_element_unordered_atomic_2(s: *mut u16, c: u8, bytes: usize) -> () {
155+
memset_element_unordered_atomic(s, c, bytes);
156+
}
157+
pub extern "C" fn __llvm_memset_element_unordered_atomic_4(s: *mut u32, c: u8, bytes: usize) -> () {
158+
memset_element_unordered_atomic(s, c, bytes);
159+
}
160+
pub extern "C" fn __llvm_memset_element_unordered_atomic_8(s: *mut u64, c: u8, bytes: usize) -> () {
161+
memset_element_unordered_atomic(s, c, bytes);
162+
}
163+
pub extern "C" fn __llvm_memset_element_unordered_atomic_16(s: *mut u128, c: u8, bytes: usize) -> () {
164+
memset_element_unordered_atomic(s, c, bytes);
165+
}
166+
}

0 commit comments

Comments
 (0)