Path: blob/main/system/lib/libc/emscripten_memcpy.c
6162 views
/*1* A simple memcpy optimized for wasm.2*/34#include <stdint.h>5#include <string.h>6#include <emscripten/emscripten.h>7#include "libc.h"8#include "emscripten_internal.h"910// Use the simple/naive version of memcpy when building with asan11#if __has_feature(address_sanitizer)1213static void *__memcpy(void *dest, const void *src, size_t n) {14unsigned char *d = (unsigned char *)dest;15const unsigned char *s = (const unsigned char *)src;16while(n--) *d++ = *s++;17return dest;18}1920#elif defined(EMSCRIPTEN_OPTIMIZE_FOR_OZ)2122static void *__memcpy(void *restrict dest, const void *restrict src, size_t n) {23// TODO: Ensure this is inlined with Binaryen or inline asm24return _emscripten_memcpy_bulkmem(dest, src, n);25}2627#else2829static void *__memcpy(void *restrict dest, const void *restrict src, size_t n) {30unsigned char *d = dest;31const unsigned char *s = src;3233unsigned char *aligned_d_end;34unsigned char *block_aligned_d_end;35unsigned char *d_end;3637if (n >= 512) {38// TODO: Re-investigate the size threshold to enable this39return _emscripten_memcpy_bulkmem(dest, src, n);40}4142d_end = d + n;43if ((((uintptr_t)d) & 3) == (((uintptr_t)s) & 3)) {44// The initial unaligned < 4-byte front.45while ((((uintptr_t)d) & 3) && d < d_end) {46*d++ = *s++;47}48aligned_d_end = (unsigned char *)(((uintptr_t)d_end) & -4);49if (((uintptr_t)aligned_d_end) >= 64) {50block_aligned_d_end = aligned_d_end - 64;51while (d <= block_aligned_d_end) {52// TODO: we could use 64-bit ops here, but we'd need to make sure the53// alignment is 64-bit, which might cost us54*(((uint32_t*)d)) = *(((uint32_t*)s));55*(((uint32_t*)d) + 1) = *(((uint32_t*)s) + 1);56*(((uint32_t*)d) + 2) = *(((uint32_t*)s) + 2);57*(((uint32_t*)d) + 3) = *(((uint32_t*)s) + 3);58*(((uint32_t*)d) + 4) = *(((uint32_t*)s) + 4);59*(((uint32_t*)d) + 5) = *(((uint32_t*)s) + 5);60*(((uint32_t*)d) + 6) = *(((uint32_t*)s) + 6);61*(((uint32_t*)d) + 7) = *(((uint32_t*)s) + 7);62*(((uint32_t*)d) + 8) = *(((uint32_t*)s) + 8);63*(((uint32_t*)d) + 9) = *(((uint32_t*)s) + 9);64*(((uint32_t*)d) + 10) = *(((uint32_t*)s) + 10);65*(((uint32_t*)d) + 11) = *(((uint32_t*)s) + 11);66*(((uint32_t*)d) + 12) = *(((uint32_t*)s) + 12);67*(((uint32_t*)d) + 13) = *(((uint32_t*)s) + 13);68*(((uint32_t*)d) + 14) = *(((uint32_t*)s) + 14);69*(((uint32_t*)d) + 15) = *(((uint32_t*)s) + 15);70d += 64;71s += 64;72}73}74while (d < aligned_d_end) {75*((uint32_t *)d) = *((uint32_t *)s);76d += 4;77s += 4;78}79} else {80// In the unaligned copy case, unroll a bit as well.81if (((uintptr_t)d_end) >= 4) {82aligned_d_end = d_end - 4;83while (d <= aligned_d_end) {84*d = *s;85*(d + 1) = *(s + 1);86*(d + 2) = *(s + 2);87*(d + 3) = *(s + 3);88d += 4;89s += 4;90}91}92}93// The remaining unaligned < 4 byte tail.94while (d < d_end) {95*d++ = *s++;96}97return dest;98}99100#endif101102weak_alias(__memcpy, emscripten_builtin_memcpy);103weak_alias(__memcpy, memcpy);104105106