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 //  }