1 module libwasm.rt.memory; 2 3 version (WebAssembly) import libwasm.rt.allocator : WasmAllocator; 4 5 version (LDC) import ldc.attributes; 6 import libwasm.intrinsics; 7 8 version (WebAssembly) extern (C) void _d_print_throwable(Throwable t) 9 { 10 import libwasm.bindings.Console; 11 12 console.error(t.toString()); 13 } 14 15 nothrow: 16 17 extern (C) @safe 18 { 19 void[] FL_allocate(size_t); 20 void[] FL_reallocate(void[], size_t); 21 void FL_deallocate(void[]); 22 } 23 24 version (WebAssembly) 25 { 26 @safe nothrow void alloc_init(uint heap_base) 27 { 28 WasmAllocator.init(heap_base); 29 } 30 31 extern (C) export void* wasm_malloc(size_t num) 32 { 33 return WasmAllocator.allocate(num).ptr; 34 } 35 36 extern (C) export void wasm_free(void* ptr, size_t size) 37 { 38 // this doesn't free. Try to un-grow? 39 WasmAllocator.deallocate(ptr[0 .. size]); 40 import ldc.intrinsics; 41 42 memset(ptr, 0, size); 43 } 44 45 extern (C) export void* wasm_realloc(void* ptr, size_t oldsize, size_t size) 46 { 47 void* ret = WasmAllocator.allocate(size).ptr; 48 import ldc.intrinsics; 49 50 memcpy(ret, ptr, oldsize); 51 memset(ptr, 0, oldsize); 52 return ret; 53 } 54 55 extern (C) export void* memset(void* ptr, ubyte value, size_t num) 56 { 57 58 ubyte val = cast(ubyte) value; 59 ubyte* p = cast(ubyte*) ptr; 60 foreach (i; 0 .. num) 61 p[i] = val; 62 return ptr; 63 } 64 } 65 66 version (unittest) 67 { 68 import ldc.intrinsics : llvm_memset; 69 70 @safe nothrow void alloc_init(uint heap_base) 71 { 72 } 73 74 extern (C) export void* wasm_malloc(size_t num) 75 { 76 return (new ubyte[num]).ptr; 77 } 78 79 extern (C) export void wasm_free(void* ptr, size_t size) 80 { 81 // this doesn't free. Try to un-grow? 82 // WasmAllocator.deallocate(ptr[0 .. size]); 83 import ldc.intrinsics; 84 85 llvm_memset(ptr, 0, size); 86 } 87 88 extern (C) export void* wasm_realloc(void* ptr, size_t oldsize, size_t size) 89 { 90 void* ret = wasm_malloc(size); 91 import ldc.intrinsics; 92 93 memcpy(ret, ptr, oldsize); 94 llvm_memset(ptr, 0, oldsize); 95 return ret; 96 } 97 } 98 99 extern (C) export void* memcpy(void* destination, const void* source, size_t num) 100 { 101 foreach (i; 0 .. num) 102 { 103 (cast(ubyte*) destination)[i] = (cast(ubyte*) source)[i]; 104 } 105 return destination; 106 } 107 108 extern (C) export 109 int memcmp(void* a, void* b, size_t cnt) 110 { 111 foreach (i; 0 .. cnt) 112 { 113 if ((cast(byte*) a)[i] < (cast(byte*) b)[i]) 114 return -1; 115 if ((cast(byte*) a)[i] > (cast(byte*) b)[i]) 116 return 1; 117 } 118 return 0; 119 } 120 121 extern (C): 122 export void* memmove(void* dest, void* src, size_t num) 123 { 124 ubyte[] tmp = cast(ubyte[]) FL_allocate(num); 125 foreach (i; 0 .. num) 126 { 127 *cast(ubyte*)&tmp[i] = *cast(ubyte*)&src[i]; 128 } 129 foreach (i; 0 .. num) 130 { 131 *cast(ubyte*)&dest[i] = *cast(ubyte*)&tmp[i]; 132 } 133 FL_deallocate(tmp); 134 return dest; 135 } 136 // per-element array init routines 137 138 // void _d_array_init_i16(ushort* a, size_t n, ushort v) 139 // { 140 // auto p = a; 141 // auto end = a+n; 142 // while (p !is end) 143 // *p++ = v; 144 // } 145 146 // void _d_array_init_i32(uint* a, size_t n, uint v) 147 // { 148 // auto p = a; 149 // auto end = a+n; 150 // while (p !is end) 151 // *p++ = v; 152 // } 153 154 // void _d_array_init_i64(ulong* a, size_t n, ulong v) 155 // { 156 // auto p = a; 157 // auto end = a+n; 158 // while (p !is end) 159 // *p++ = v; 160 // } 161 162 // void _d_array_init_float(float* a, size_t n, float v) 163 // { 164 // auto p = a; 165 // auto end = a+n; 166 // while (p !is end) 167 // *p++ = v; 168 // } 169 170 // void _d_array_init_double(double* a, size_t n, double v) 171 // { 172 // auto p = a; 173 // auto end = a+n; 174 // while (p !is end) 175 // *p++ = v; 176 // } 177 178 // void _d_array_init_real(real* a, size_t n, real v) 179 // { 180 // auto p = a; 181 // auto end = a+n; 182 // while (p !is end) 183 // *p++ = v; 184 // } 185 186 // void _d_array_init_cfloat(cfloat* a, size_t n, cfloat v) 187 // { 188 // auto p = a; 189 // auto end = a+n; 190 // while (p !is end) 191 // *p++ = v; 192 // } 193 194 // void _d_array_init_cdouble(cdouble* a, size_t n, cdouble v) 195 // { 196 // auto p = a; 197 // auto end = a+n; 198 // while (p !is end) 199 // *p++ = v; 200 // } 201 202 // void _d_array_init_creal(creal* a, size_t n, creal v) 203 // { 204 // auto p = a; 205 // auto end = a+n; 206 // while (p !is end) 207 // *p++ = v; 208 // } 209 210 // void _d_array_init_pointer(void** a, size_t n, void* v) 211 // { 212 // auto p = a; 213 // auto end = a+n; 214 // while (p !is end) 215 // *p++ = v; 216 // } 217 218 // void _d_array_init_mem(void* a, size_t na, void* v, size_t nv) 219 // { 220 // auto p = a; 221 // auto end = a + na*nv; 222 // while (p !is end) { 223 // memcpy(p,v,nv); 224 // p += nv; 225 // } 226 // } 227 228 // deprecated("since ldc 1.14.0") 229 // size_t _d_array_cast_len(size_t len, size_t elemsz, size_t newelemsz) 230 // { 231 // if (newelemsz == 1) { 232 // return len*elemsz; 233 // } 234 // else if ((len*elemsz) % newelemsz) { 235 // assert(0); 236 // } 237 // return (len*elemsz)/newelemsz; 238 // } 239 240 // @trusted nothrow 241 // size_t _d_arraycast_len(size_t len, size_t elemsz, size_t newelemsz) { 242 // const size = len * elemsz; 243 // const newlen = size / newelemsz; 244 // if (newlen * newelemsz != size) 245 // assert(0); 246 // return newlen; 247 // } 248 249 // slice copy when assertions are enabled 250 // void _d_array_slice_copy(void* dst, size_t dstlen, void* src, size_t srclen, size_t elemsz) 251 // { 252 // if (dstlen != 0) assert(dst); 253 // if (dstlen != 0) assert(src); 254 // if (dstlen != srclen) 255 // assert(0); 256 // else if (dst+dstlen*elemsz <= src || src+srclen*elemsz <= dst) { 257 // version (LDC) { 258 // import ldc.intrinsics; 259 // llvm_memcpy!size_t(dst, src, dstlen * elemsz, 0); 260 // } else 261 // memcpy(dst, src, dstlen * elemsz); 262 // } 263 // else 264 // assert(0); 265 // }