Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
emscripten-core
GitHub Repository: emscripten-core/emscripten
Path: blob/main/system/lib/libc/emscripten_memcpy.c
6162 views
1
/*
2
* A simple memcpy optimized for wasm.
3
*/
4
5
#include <stdint.h>
6
#include <string.h>
7
#include <emscripten/emscripten.h>
8
#include "libc.h"
9
#include "emscripten_internal.h"
10
11
// Use the simple/naive version of memcpy when building with asan
12
#if __has_feature(address_sanitizer)
13
14
static void *__memcpy(void *dest, const void *src, size_t n) {
15
unsigned char *d = (unsigned char *)dest;
16
const unsigned char *s = (const unsigned char *)src;
17
while(n--) *d++ = *s++;
18
return dest;
19
}
20
21
#elif defined(EMSCRIPTEN_OPTIMIZE_FOR_OZ)
22
23
static void *__memcpy(void *restrict dest, const void *restrict src, size_t n) {
24
// TODO: Ensure this is inlined with Binaryen or inline asm
25
return _emscripten_memcpy_bulkmem(dest, src, n);
26
}
27
28
#else
29
30
static void *__memcpy(void *restrict dest, const void *restrict src, size_t n) {
31
unsigned char *d = dest;
32
const unsigned char *s = src;
33
34
unsigned char *aligned_d_end;
35
unsigned char *block_aligned_d_end;
36
unsigned char *d_end;
37
38
if (n >= 512) {
39
// TODO: Re-investigate the size threshold to enable this
40
return _emscripten_memcpy_bulkmem(dest, src, n);
41
}
42
43
d_end = d + n;
44
if ((((uintptr_t)d) & 3) == (((uintptr_t)s) & 3)) {
45
// The initial unaligned < 4-byte front.
46
while ((((uintptr_t)d) & 3) && d < d_end) {
47
*d++ = *s++;
48
}
49
aligned_d_end = (unsigned char *)(((uintptr_t)d_end) & -4);
50
if (((uintptr_t)aligned_d_end) >= 64) {
51
block_aligned_d_end = aligned_d_end - 64;
52
while (d <= block_aligned_d_end) {
53
// TODO: we could use 64-bit ops here, but we'd need to make sure the
54
// alignment is 64-bit, which might cost us
55
*(((uint32_t*)d)) = *(((uint32_t*)s));
56
*(((uint32_t*)d) + 1) = *(((uint32_t*)s) + 1);
57
*(((uint32_t*)d) + 2) = *(((uint32_t*)s) + 2);
58
*(((uint32_t*)d) + 3) = *(((uint32_t*)s) + 3);
59
*(((uint32_t*)d) + 4) = *(((uint32_t*)s) + 4);
60
*(((uint32_t*)d) + 5) = *(((uint32_t*)s) + 5);
61
*(((uint32_t*)d) + 6) = *(((uint32_t*)s) + 6);
62
*(((uint32_t*)d) + 7) = *(((uint32_t*)s) + 7);
63
*(((uint32_t*)d) + 8) = *(((uint32_t*)s) + 8);
64
*(((uint32_t*)d) + 9) = *(((uint32_t*)s) + 9);
65
*(((uint32_t*)d) + 10) = *(((uint32_t*)s) + 10);
66
*(((uint32_t*)d) + 11) = *(((uint32_t*)s) + 11);
67
*(((uint32_t*)d) + 12) = *(((uint32_t*)s) + 12);
68
*(((uint32_t*)d) + 13) = *(((uint32_t*)s) + 13);
69
*(((uint32_t*)d) + 14) = *(((uint32_t*)s) + 14);
70
*(((uint32_t*)d) + 15) = *(((uint32_t*)s) + 15);
71
d += 64;
72
s += 64;
73
}
74
}
75
while (d < aligned_d_end) {
76
*((uint32_t *)d) = *((uint32_t *)s);
77
d += 4;
78
s += 4;
79
}
80
} else {
81
// In the unaligned copy case, unroll a bit as well.
82
if (((uintptr_t)d_end) >= 4) {
83
aligned_d_end = d_end - 4;
84
while (d <= aligned_d_end) {
85
*d = *s;
86
*(d + 1) = *(s + 1);
87
*(d + 2) = *(s + 2);
88
*(d + 3) = *(s + 3);
89
d += 4;
90
s += 4;
91
}
92
}
93
}
94
// The remaining unaligned < 4 byte tail.
95
while (d < d_end) {
96
*d++ = *s++;
97
}
98
return dest;
99
}
100
101
#endif
102
103
weak_alias(__memcpy, emscripten_builtin_memcpy);
104
weak_alias(__memcpy, memcpy);
105
106