1 //
2 //  m3_api_meta_wasi.c
3 //
4 //  Created by Volodymyr Shymanskyy on 01/08/20.
5 //  Copyright © 2020 Volodymyr Shymanskyy. All rights reserved.
6 //
7 
8 #include "m3_api_wasi.h"
9 
10 #include "m3_env.h"
11 #include "m3_exception.h"
12 
13 #if defined(d_m3HasMetaWASI)
14 
15 // NOTE: MetaWASI mostly redirects WASI calls to the host WASI environment
16 
17 #if !defined(__wasi__)
18 # error "MetaWASI is only supported on WASI target"
19 #endif
20 
21 #if __has_include("wasi/api.h")
22 # include <wasi/api.h>
23 
24 #elif __has_include("wasi/core.h")
25 # warning "Using legacy WASI headers"
26 # include <wasi/core.h>
27 # define __WASI_ERRNO_SUCCESS   __WASI_ESUCCESS
28 # define __WASI_ERRNO_INVAL     __WASI_EINVAL
29 
30 #else
31 # error "Missing WASI headers"
32 #endif
33 
34 static m3_wasi_context_t* wasi_context;
35 
36 typedef size_t __wasi_size_t;
37 
38 static inline
copy_iov_to_host(void * _mem,__wasi_iovec_t * host_iov,__wasi_iovec_t * wasi_iov,int32_t iovs_len)39 void copy_iov_to_host(void* _mem, __wasi_iovec_t* host_iov, __wasi_iovec_t* wasi_iov, int32_t iovs_len)
40 {
41     // Convert wasi memory offsets to host addresses
42     for (int i = 0; i < iovs_len; i++) {
43         host_iov[i].buf = m3ApiOffsetToPtr(wasi_iov[i].buf);
44         host_iov[i].buf_len  = wasi_iov[i].buf_len;
45     }
46 }
47 
48 /*
49  * WASI API implementation
50  */
51 
m3ApiRawFunction(m3_wasi_generic_args_get)52 m3ApiRawFunction(m3_wasi_generic_args_get)
53 {
54     m3ApiReturnType  (uint32_t)
55     m3ApiGetArgMem   (uint32_t *           , argv)
56     m3ApiGetArgMem   (char *               , argv_buf)
57 
58     m3_wasi_context_t* context = (m3_wasi_context_t*)(_ctx->userdata);
59 
60     if (context == NULL) { m3ApiReturn(__WASI_ERRNO_INVAL); }
61 
62     m3ApiCheckMem(argv, context->argc * sizeof(uint32_t));
63 
64     for (u32 i = 0; i < context->argc; ++i)
65     {
66         m3ApiWriteMem32(&argv[i], m3ApiPtrToOffset(argv_buf));
67 
68         size_t len = strlen (context->argv[i]);
69 
70         m3ApiCheckMem(argv_buf, len);
71         memcpy (argv_buf, context->argv[i], len);
72         argv_buf += len;
73         * argv_buf++ = 0;
74     }
75 
76     m3ApiReturn(__WASI_ERRNO_SUCCESS);
77 }
78 
m3ApiRawFunction(m3_wasi_generic_args_sizes_get)79 m3ApiRawFunction(m3_wasi_generic_args_sizes_get)
80 {
81     m3ApiReturnType  (uint32_t)
82     m3ApiGetArgMem   (__wasi_size_t *      , argc)
83     m3ApiGetArgMem   (__wasi_size_t *      , argv_buf_size)
84 
85     m3ApiCheckMem(argc,             sizeof(__wasi_size_t));
86     m3ApiCheckMem(argv_buf_size,    sizeof(__wasi_size_t));
87 
88     m3_wasi_context_t* context = (m3_wasi_context_t*)(_ctx->userdata);
89 
90     if (context == NULL) { m3ApiReturn(__WASI_ERRNO_INVAL); }
91 
92     __wasi_size_t buf_len = 0;
93     for (u32 i = 0; i < context->argc; ++i)
94     {
95         buf_len += strlen (context->argv[i]) + 1;
96     }
97 
98     m3ApiWriteMem32(argc, context->argc);
99     m3ApiWriteMem32(argv_buf_size, buf_len);
100 
101     m3ApiReturn(__WASI_ERRNO_SUCCESS);
102 }
103 
m3ApiRawFunction(m3_wasi_generic_environ_get)104 m3ApiRawFunction(m3_wasi_generic_environ_get)
105 {
106     m3ApiReturnType  (uint32_t)
107     m3ApiGetArgMem   (uint32_t *           , env)
108     m3ApiGetArgMem   (char *               , env_buf)
109 
110     __wasi_errno_t ret;
111     __wasi_size_t env_count, env_buf_size;
112 
113     ret = __wasi_environ_sizes_get(&env_count, &env_buf_size);
114     if (ret != __WASI_ERRNO_SUCCESS) m3ApiReturn(ret);
115 
116     m3ApiCheckMem(env,      env_count * sizeof(uint32_t));
117     m3ApiCheckMem(env_buf,  env_buf_size);
118 
119     ret = __wasi_environ_get(env, env_buf);
120     if (ret != __WASI_ERRNO_SUCCESS) m3ApiReturn(ret);
121 
122     for (u32 i = 0; i < env_count; ++i) {
123         env[i] = m3ApiPtrToOffset (env[i]);
124     }
125 
126     m3ApiReturn(ret);
127 }
128 
m3ApiRawFunction(m3_wasi_generic_environ_sizes_get)129 m3ApiRawFunction(m3_wasi_generic_environ_sizes_get)
130 {
131     m3ApiReturnType  (uint32_t)
132     m3ApiGetArgMem   (__wasi_size_t *      , env_count)
133     m3ApiGetArgMem   (__wasi_size_t *      , env_buf_size)
134 
135     m3ApiCheckMem(env_count,    sizeof(__wasi_size_t));
136     m3ApiCheckMem(env_buf_size, sizeof(__wasi_size_t));
137 
138     __wasi_errno_t ret = __wasi_environ_sizes_get(env_count, env_buf_size);
139 
140     m3ApiReturn(ret);
141 }
142 
m3ApiRawFunction(m3_wasi_generic_fd_prestat_dir_name)143 m3ApiRawFunction(m3_wasi_generic_fd_prestat_dir_name)
144 {
145     m3ApiReturnType  (uint32_t)
146     m3ApiGetArg      (__wasi_fd_t          , fd)
147     m3ApiGetArgMem   (char *               , path)
148     m3ApiGetArg      (__wasi_size_t        , path_len)
149 
150     m3ApiCheckMem(path, path_len);
151 
152     __wasi_errno_t ret = __wasi_fd_prestat_dir_name(fd, path, path_len);
153 
154     m3ApiReturn(ret);
155 }
156 
m3ApiRawFunction(m3_wasi_generic_fd_prestat_get)157 m3ApiRawFunction(m3_wasi_generic_fd_prestat_get)
158 {
159     m3ApiReturnType  (uint32_t)
160     m3ApiGetArg      (__wasi_fd_t          , fd)
161     m3ApiGetArgMem   (__wasi_prestat_t *   , buf)
162 
163     m3ApiCheckMem(buf, sizeof(__wasi_prestat_t));
164 
165     __wasi_errno_t ret = __wasi_fd_prestat_get(fd, buf);
166 
167     m3ApiReturn(ret);
168 }
169 
m3ApiRawFunction(m3_wasi_generic_fd_fdstat_get)170 m3ApiRawFunction(m3_wasi_generic_fd_fdstat_get)
171 {
172     m3ApiReturnType  (uint32_t)
173     m3ApiGetArg      (__wasi_fd_t          , fd)
174     m3ApiGetArgMem   (__wasi_fdstat_t *    , fdstat)
175 
176     m3ApiCheckMem(fdstat, sizeof(__wasi_fdstat_t));
177 
178     __wasi_errno_t ret = __wasi_fd_fdstat_get(fd, fdstat);
179 
180     m3ApiReturn(ret);
181 }
182 
m3ApiRawFunction(m3_wasi_generic_fd_fdstat_set_flags)183 m3ApiRawFunction(m3_wasi_generic_fd_fdstat_set_flags)
184 {
185     m3ApiReturnType  (uint32_t)
186     m3ApiGetArg      (__wasi_fd_t          , fd)
187     m3ApiGetArg      (__wasi_fdflags_t     , flags)
188 
189     __wasi_errno_t ret = __wasi_fd_fdstat_set_flags(fd, flags);
190 
191     m3ApiReturn(ret);
192 }
193 
m3ApiRawFunction(m3_wasi_unstable_fd_filestat_get)194 m3ApiRawFunction(m3_wasi_unstable_fd_filestat_get)
195 {
196     m3ApiReturnType  (uint32_t)
197     m3ApiGetArg      (__wasi_fd_t          , fd)
198     m3ApiGetArgMem   (uint8_t *            , buf)
199 
200     m3ApiCheckMem(buf, 56); // wasi_filestat_t
201 
202     __wasi_filestat_t stat;
203 
204     __wasi_errno_t ret = __wasi_fd_filestat_get(fd, &stat);
205 
206     if (ret != __WASI_ERRNO_SUCCESS) {
207         m3ApiReturn(ret);
208     }
209 
210     memset(buf, 0, 56);
211     m3ApiWriteMem64(buf+0,  stat.st_dev);
212     m3ApiWriteMem64(buf+8,  stat.st_ino);
213     m3ApiWriteMem8 (buf+16, stat.st_filetype);
214     m3ApiWriteMem32(buf+20, stat.st_nlink);
215     m3ApiWriteMem64(buf+24, stat.st_size);
216     m3ApiWriteMem64(buf+32, stat.st_atim);
217     m3ApiWriteMem64(buf+40, stat.st_mtim);
218     m3ApiWriteMem64(buf+48, stat.st_ctim);
219 
220     m3ApiReturn(ret);
221 }
222 
m3ApiRawFunction(m3_wasi_snapshot_preview1_fd_filestat_get)223 m3ApiRawFunction(m3_wasi_snapshot_preview1_fd_filestat_get)
224 {
225     m3ApiReturnType  (uint32_t)
226     m3ApiGetArg      (__wasi_fd_t          , fd)
227     m3ApiGetArgMem   (uint8_t *            , buf)
228 
229     m3ApiCheckMem(buf, 64); // wasi_filestat_t
230 
231     __wasi_filestat_t stat;
232 
233     __wasi_errno_t ret = __wasi_fd_filestat_get(fd, &stat);
234 
235     if (ret != __WASI_ERRNO_SUCCESS) {
236         m3ApiReturn(ret);
237     }
238 
239     memset(buf, 0, 64);
240     m3ApiWriteMem64(buf+0,  stat.st_dev);
241     m3ApiWriteMem64(buf+8,  stat.st_ino);
242     m3ApiWriteMem8 (buf+16, stat.st_filetype);
243     m3ApiWriteMem64(buf+24, stat.st_nlink);
244     m3ApiWriteMem64(buf+32, stat.st_size);
245     m3ApiWriteMem64(buf+40, stat.st_atim);
246     m3ApiWriteMem64(buf+48, stat.st_mtim);
247     m3ApiWriteMem64(buf+56, stat.st_ctim);
248 
249     m3ApiReturn(ret);
250 }
251 
m3ApiRawFunction(m3_wasi_unstable_fd_seek)252 m3ApiRawFunction(m3_wasi_unstable_fd_seek)
253 {
254     m3ApiReturnType  (uint32_t)
255     m3ApiGetArg      (__wasi_fd_t          , fd)
256     m3ApiGetArg      (__wasi_filedelta_t   , offset)
257     m3ApiGetArg      (uint32_t             , wasi_whence)
258     m3ApiGetArgMem   (__wasi_filesize_t *  , result)
259 
260     m3ApiCheckMem(result, sizeof(__wasi_filesize_t));
261 
262     __wasi_whence_t whence;
263 
264     switch (wasi_whence) {
265     case 0: whence = __WASI_WHENCE_CUR; break;
266     case 1: whence = __WASI_WHENCE_END; break;
267     case 2: whence = __WASI_WHENCE_SET; break;
268     default:                m3ApiReturn(__WASI_ERRNO_INVAL);
269     }
270 
271     __wasi_errno_t ret = __wasi_fd_seek(fd, offset, whence, result);
272 
273     m3ApiReturn(ret);
274 }
275 
m3ApiRawFunction(m3_wasi_snapshot_preview1_fd_seek)276 m3ApiRawFunction(m3_wasi_snapshot_preview1_fd_seek)
277 {
278     m3ApiReturnType  (uint32_t)
279     m3ApiGetArg      (__wasi_fd_t          , fd)
280     m3ApiGetArg      (__wasi_filedelta_t   , offset)
281     m3ApiGetArg      (uint32_t             , wasi_whence)
282     m3ApiGetArgMem   (__wasi_filesize_t *  , result)
283 
284     m3ApiCheckMem(result, sizeof(__wasi_filesize_t));
285 
286     __wasi_whence_t whence;
287 
288     switch (wasi_whence) {
289     case 0: whence = __WASI_WHENCE_SET; break;
290     case 1: whence = __WASI_WHENCE_CUR; break;
291     case 2: whence = __WASI_WHENCE_END; break;
292     default:                m3ApiReturn(__WASI_ERRNO_INVAL);
293     }
294 
295     __wasi_errno_t ret = __wasi_fd_seek(fd, offset, whence, result);
296 
297     m3ApiReturn(ret);
298 }
299 
m3ApiRawFunction(m3_wasi_generic_path_create_directory)300 m3ApiRawFunction(m3_wasi_generic_path_create_directory)
301 {
302     m3ApiReturnType  (uint32_t)
303     m3ApiGetArg      (__wasi_fd_t          , fd)
304     m3ApiGetArgMem   (const char *         , path)
305     m3ApiGetArg      (__wasi_size_t        , path_len)
306 
307     m3ApiCheckMem(path, path_len);
308 
309     __wasi_errno_t ret = __wasi_path_create_directory(fd, path, path_len);
310 
311     m3ApiReturn(ret);
312 }
313 
m3ApiRawFunction(m3_wasi_generic_path_readlink)314 m3ApiRawFunction(m3_wasi_generic_path_readlink)
315 {
316     m3ApiReturnType  (uint32_t)
317     m3ApiGetArg      (__wasi_fd_t          , fd)
318     m3ApiGetArgMem   (const char *         , path)
319     m3ApiGetArg      (__wasi_size_t        , path_len)
320     m3ApiGetArgMem   (char *               , buf)
321     m3ApiGetArg      (__wasi_size_t        , buf_len)
322     m3ApiGetArgMem   (__wasi_size_t *      , bufused)
323 
324     m3ApiCheckMem(path, path_len);
325     m3ApiCheckMem(buf, buf_len);
326     m3ApiCheckMem(bufused, sizeof(__wasi_size_t));
327 
328     __wasi_errno_t ret = __wasi_path_readlink(fd, path, path_len, buf, buf_len, bufused);
329 
330     m3ApiReturn(ret);
331 }
332 
m3ApiRawFunction(m3_wasi_generic_path_remove_directory)333 m3ApiRawFunction(m3_wasi_generic_path_remove_directory)
334 {
335     m3ApiReturnType  (uint32_t)
336     m3ApiGetArg      (__wasi_fd_t          , fd)
337     m3ApiGetArgMem   (const char *         , path)
338     m3ApiGetArg      (__wasi_size_t        , path_len)
339 
340     m3ApiCheckMem(path, path_len);
341 
342     __wasi_errno_t ret = __wasi_path_remove_directory(fd, path, path_len);
343 
344     m3ApiReturn(ret);
345 }
346 
m3ApiRawFunction(m3_wasi_generic_path_rename)347 m3ApiRawFunction(m3_wasi_generic_path_rename)
348 {
349     m3ApiReturnType  (uint32_t)
350     m3ApiGetArg      (__wasi_fd_t          , old_fd)
351     m3ApiGetArgMem   (const char *         , old_path)
352     m3ApiGetArg      (__wasi_size_t        , old_path_len)
353     m3ApiGetArg      (__wasi_fd_t          , new_fd)
354     m3ApiGetArgMem   (const char *         , new_path)
355     m3ApiGetArg      (__wasi_size_t        , new_path_len)
356 
357     m3ApiCheckMem(old_path, old_path_len);
358     m3ApiCheckMem(new_path, new_path_len);
359 
360     __wasi_errno_t ret = __wasi_path_rename(old_fd, old_path, old_path_len,
361                                             new_fd, new_path, new_path_len);
362 
363     m3ApiReturn(ret);
364 }
365 
m3ApiRawFunction(m3_wasi_generic_path_unlink_file)366 m3ApiRawFunction(m3_wasi_generic_path_unlink_file)
367 {
368     m3ApiReturnType  (uint32_t)
369     m3ApiGetArg      (__wasi_fd_t          , fd)
370     m3ApiGetArgMem   (const char *         , path)
371     m3ApiGetArg      (__wasi_size_t        , path_len)
372 
373     m3ApiCheckMem(path, path_len);
374 
375     __wasi_errno_t ret = __wasi_path_unlink_file(fd, path, path_len);
376 
377     m3ApiReturn(ret);
378 }
379 
m3ApiRawFunction(m3_wasi_generic_path_open)380 m3ApiRawFunction(m3_wasi_generic_path_open)
381 {
382     m3ApiReturnType  (uint32_t)
383     m3ApiGetArg      (__wasi_fd_t          , dirfd)
384     m3ApiGetArg      (__wasi_lookupflags_t , dirflags)
385     m3ApiGetArgMem   (const char *         , path)
386     m3ApiGetArg      (__wasi_size_t        , path_len)
387     m3ApiGetArg      (__wasi_oflags_t      , oflags)
388     m3ApiGetArg      (__wasi_rights_t      , fs_rights_base)
389     m3ApiGetArg      (__wasi_rights_t      , fs_rights_inheriting)
390     m3ApiGetArg      (__wasi_fdflags_t     , fs_flags)
391     m3ApiGetArgMem   (__wasi_fd_t *        , fd)
392 
393     m3ApiCheckMem(path, path_len);
394     m3ApiCheckMem(fd,   sizeof(__wasi_fd_t));
395 
396     __wasi_errno_t ret = __wasi_path_open(dirfd,
397                                  dirflags,
398                                  path,
399                                  path_len,
400                                  oflags,
401                                  fs_rights_base,
402                                  fs_rights_inheriting,
403                                  fs_flags,
404                                  fd);
405 
406     m3ApiReturn(ret);
407 }
408 
m3ApiRawFunction(m3_wasi_unstable_path_filestat_get)409 m3ApiRawFunction(m3_wasi_unstable_path_filestat_get)
410 {
411     m3ApiReturnType  (uint32_t)
412     m3ApiGetArg      (__wasi_fd_t          , fd)
413     m3ApiGetArg      (__wasi_lookupflags_t , flags)
414     m3ApiGetArgMem   (const char *         , path)
415     m3ApiGetArg      (uint32_t             , path_len)
416     m3ApiGetArgMem   (uint8_t *            , buf)
417 
418     m3ApiCheckMem(path, path_len);
419     m3ApiCheckMem(buf,  56); // wasi_filestat_t
420 
421     __wasi_filestat_t stat;
422 
423     __wasi_errno_t ret = __wasi_path_filestat_get(fd, flags, path, path_len, &stat);
424 
425     if (ret != __WASI_ERRNO_SUCCESS) {
426         m3ApiReturn(ret);
427     }
428 
429     memset(buf, 0, 56);
430     m3ApiWriteMem64(buf+0,  stat.st_dev);
431     m3ApiWriteMem64(buf+8,  stat.st_ino);
432     m3ApiWriteMem8 (buf+16, stat.st_filetype);
433     m3ApiWriteMem32(buf+20, stat.st_nlink);
434     m3ApiWriteMem64(buf+24, stat.st_size);
435     m3ApiWriteMem64(buf+32, stat.st_atim);
436     m3ApiWriteMem64(buf+40, stat.st_mtim);
437     m3ApiWriteMem64(buf+48, stat.st_ctim);
438 
439     m3ApiReturn(ret);
440 }
441 
m3ApiRawFunction(m3_wasi_snapshot_preview1_path_filestat_get)442 m3ApiRawFunction(m3_wasi_snapshot_preview1_path_filestat_get)
443 {
444     m3ApiReturnType  (uint32_t)
445     m3ApiGetArg      (__wasi_fd_t          , fd)
446     m3ApiGetArg      (__wasi_lookupflags_t , flags)
447     m3ApiGetArgMem   (const char *         , path)
448     m3ApiGetArg      (uint32_t             , path_len)
449     m3ApiGetArgMem   (uint8_t *            , buf)
450 
451     m3ApiCheckMem(path, path_len);
452     m3ApiCheckMem(buf,  64); // wasi_filestat_t
453 
454     __wasi_filestat_t stat;
455 
456     __wasi_errno_t ret = __wasi_path_filestat_get(fd, flags, path, path_len, &stat);
457 
458     if (ret != __WASI_ERRNO_SUCCESS) {
459         m3ApiReturn(ret);
460     }
461 
462     memset(buf, 0, 64);
463     m3ApiWriteMem64(buf+0,  stat.st_dev);
464     m3ApiWriteMem64(buf+8,  stat.st_ino);
465     m3ApiWriteMem8 (buf+16, stat.st_filetype);
466     m3ApiWriteMem64(buf+24, stat.st_nlink);
467     m3ApiWriteMem64(buf+32, stat.st_size);
468     m3ApiWriteMem64(buf+40, stat.st_atim);
469     m3ApiWriteMem64(buf+48, stat.st_mtim);
470     m3ApiWriteMem64(buf+56, stat.st_ctim);
471 
472     m3ApiReturn(ret);
473 }
474 
m3ApiRawFunction(m3_wasi_generic_fd_pread)475 m3ApiRawFunction(m3_wasi_generic_fd_pread)
476 {
477     m3ApiReturnType  (uint32_t)
478     m3ApiGetArg      (__wasi_fd_t          , fd)
479     m3ApiGetArgMem   (__wasi_iovec_t *     , wasi_iovs)
480     m3ApiGetArg      (__wasi_size_t        , iovs_len)
481     m3ApiGetArg      (__wasi_filesize_t    , offset)
482     m3ApiGetArgMem   (__wasi_size_t *      , nread)
483 
484     m3ApiCheckMem(wasi_iovs,    iovs_len * sizeof(__wasi_iovec_t));
485     m3ApiCheckMem(nread,        sizeof(__wasi_size_t));
486 
487     __wasi_iovec_t iovs[iovs_len];
488     copy_iov_to_host(_mem, iovs, wasi_iovs, iovs_len);
489 
490     __wasi_errno_t ret = __wasi_fd_pread(fd, iovs, iovs_len, offset, nread);
491 
492     m3ApiReturn(ret);
493 }
494 
m3ApiRawFunction(m3_wasi_generic_fd_read)495 m3ApiRawFunction(m3_wasi_generic_fd_read)
496 {
497     m3ApiReturnType  (uint32_t)
498     m3ApiGetArg      (__wasi_fd_t          , fd)
499     m3ApiGetArgMem   (__wasi_iovec_t *     , wasi_iovs)
500     m3ApiGetArg      (__wasi_size_t        , iovs_len)
501     m3ApiGetArgMem   (__wasi_size_t *      , nread)
502 
503     m3ApiCheckMem(wasi_iovs,    iovs_len * sizeof(__wasi_iovec_t));
504     m3ApiCheckMem(nread,        sizeof(__wasi_size_t));
505 
506     __wasi_iovec_t iovs[iovs_len];
507     copy_iov_to_host(_mem, iovs, wasi_iovs, iovs_len);
508 
509     __wasi_errno_t ret = __wasi_fd_read(fd, iovs, iovs_len, nread);
510 
511     m3ApiReturn(ret);
512 }
513 
m3ApiRawFunction(m3_wasi_generic_fd_write)514 m3ApiRawFunction(m3_wasi_generic_fd_write)
515 {
516     m3ApiReturnType  (uint32_t)
517     m3ApiGetArg      (__wasi_fd_t          , fd)
518     m3ApiGetArgMem   (__wasi_iovec_t *     , wasi_iovs)
519     m3ApiGetArg      (__wasi_size_t        , iovs_len)
520     m3ApiGetArgMem   (__wasi_size_t *      , nwritten)
521 
522     m3ApiCheckMem(wasi_iovs,    iovs_len * sizeof(__wasi_iovec_t));
523     m3ApiCheckMem(nwritten,     sizeof(__wasi_size_t));
524 
525     __wasi_iovec_t iovs[iovs_len];
526     copy_iov_to_host(_mem, iovs, wasi_iovs, iovs_len);
527 
528     __wasi_errno_t ret = __wasi_fd_write(fd, (__wasi_ciovec_t*)iovs, iovs_len, nwritten);
529 
530     m3ApiReturn(ret);
531 }
532 
m3ApiRawFunction(m3_wasi_generic_fd_readdir)533 m3ApiRawFunction(m3_wasi_generic_fd_readdir)
534 {
535     m3ApiReturnType  (uint32_t)
536     m3ApiGetArg      (__wasi_fd_t          , fd)
537     m3ApiGetArgMem   (void *               , buf)
538     m3ApiGetArg      (__wasi_size_t        , buf_len)
539     m3ApiGetArg      (__wasi_dircookie_t   , cookie)
540     m3ApiGetArgMem   (__wasi_size_t *      , bufused)
541 
542     m3ApiCheckMem(buf,      buf_len);
543     m3ApiCheckMem(bufused,  sizeof(__wasi_size_t));
544 
545     __wasi_errno_t ret = __wasi_fd_readdir(fd, buf, buf_len, cookie, bufused);
546 
547     m3ApiReturn(ret);
548 }
549 
m3ApiRawFunction(m3_wasi_generic_fd_close)550 m3ApiRawFunction(m3_wasi_generic_fd_close)
551 {
552     m3ApiReturnType  (uint32_t)
553     m3ApiGetArg      (__wasi_fd_t, fd)
554 
555     __wasi_errno_t ret = __wasi_fd_close(fd);
556 
557     m3ApiReturn(ret);
558 }
559 
m3ApiRawFunction(m3_wasi_generic_fd_datasync)560 m3ApiRawFunction(m3_wasi_generic_fd_datasync)
561 {
562     m3ApiReturnType  (uint32_t)
563     m3ApiGetArg      (__wasi_fd_t, fd)
564 
565     __wasi_errno_t ret = __wasi_fd_datasync(fd);
566 
567     m3ApiReturn(ret);
568 }
569 
m3ApiRawFunction(m3_wasi_generic_random_get)570 m3ApiRawFunction(m3_wasi_generic_random_get)
571 {
572     m3ApiReturnType  (uint32_t)
573     m3ApiGetArgMem   (uint8_t *            , buf)
574     m3ApiGetArg      (__wasi_size_t        , buf_len)
575 
576     m3ApiCheckMem(buf, buf_len);
577 
578     __wasi_errno_t ret = __wasi_random_get(buf, buf_len);
579 
580     m3ApiReturn(ret);
581 }
582 
m3ApiRawFunction(m3_wasi_generic_clock_res_get)583 m3ApiRawFunction(m3_wasi_generic_clock_res_get)
584 {
585     m3ApiReturnType  (uint32_t)
586     m3ApiGetArg      (__wasi_clockid_t     , wasi_clk_id)
587     m3ApiGetArgMem   (__wasi_timestamp_t * , resolution)
588 
589     m3ApiCheckMem(resolution, sizeof(__wasi_timestamp_t));
590 
591     __wasi_errno_t ret = __wasi_clock_res_get(wasi_clk_id, resolution);
592 
593     m3ApiReturn(ret);
594 }
595 
m3ApiRawFunction(m3_wasi_generic_clock_time_get)596 m3ApiRawFunction(m3_wasi_generic_clock_time_get)
597 {
598     m3ApiReturnType  (uint32_t)
599     m3ApiGetArg      (__wasi_clockid_t     , wasi_clk_id)
600     m3ApiGetArg      (__wasi_timestamp_t   , precision)
601     m3ApiGetArgMem   (__wasi_timestamp_t * , time)
602 
603     m3ApiCheckMem(time, sizeof(__wasi_timestamp_t));
604 
605     __wasi_errno_t ret = __wasi_clock_time_get(wasi_clk_id, precision, time);
606 
607     m3ApiReturn(ret);
608 }
609 
m3ApiRawFunction(m3_wasi_generic_poll_oneoff)610 m3ApiRawFunction(m3_wasi_generic_poll_oneoff)
611 {
612     m3ApiReturnType  (uint32_t)
613     m3ApiGetArgMem   (const __wasi_subscription_t * , in)
614     m3ApiGetArgMem   (__wasi_event_t *              , out)
615     m3ApiGetArg      (__wasi_size_t                 , nsubscriptions)
616     m3ApiGetArgMem   (__wasi_size_t *               , nevents)
617 
618     m3ApiCheckMem(in,       nsubscriptions * sizeof(__wasi_subscription_t));
619     m3ApiCheckMem(out,      nsubscriptions * sizeof(__wasi_event_t));
620     m3ApiCheckMem(nevents,  sizeof(__wasi_size_t));
621 
622     __wasi_errno_t ret = __wasi_poll_oneoff(in, out, nsubscriptions, nevents);
623 
624     m3ApiReturn(ret);
625 }
626 
m3ApiRawFunction(m3_wasi_generic_proc_exit)627 m3ApiRawFunction(m3_wasi_generic_proc_exit)
628 {
629     m3ApiGetArg      (uint32_t, code)
630 
631     m3_wasi_context_t* context = (m3_wasi_context_t*)(_ctx->userdata);
632 
633     if (context) {
634         context->exit_code = code;
635     }
636 
637     m3ApiTrap(m3Err_trapExit);
638 }
639 
640 
641 static
SuppressLookupFailure(M3Result i_result)642 M3Result SuppressLookupFailure(M3Result i_result)
643 {
644     if (i_result == m3Err_functionLookupFailed)
645         return m3Err_none;
646     else
647         return i_result;
648 }
649 
m3_GetWasiContext()650 m3_wasi_context_t* m3_GetWasiContext()
651 {
652     return wasi_context;
653 }
654 
655 
m3_LinkWASI(IM3Module module)656 M3Result  m3_LinkWASI  (IM3Module module)
657 {
658     M3Result result = m3Err_none;
659 
660     if (!wasi_context) {
661         wasi_context = (m3_wasi_context_t*)malloc(sizeof(m3_wasi_context_t));
662         wasi_context->exit_code = 0;
663         wasi_context->argc = 0;
664         wasi_context->argv = 0;
665     }
666 
667     static const char* namespaces[2] = { "wasi_unstable", "wasi_snapshot_preview1" };
668 
669     // fd_seek is incompatible
670 _   (SuppressLookupFailure (m3_LinkRawFunction (module, "wasi_unstable",          "fd_seek",           "i(iIi*)",   &m3_wasi_unstable_fd_seek)));
671 _   (SuppressLookupFailure (m3_LinkRawFunction (module, "wasi_snapshot_preview1", "fd_seek",           "i(iIi*)",   &m3_wasi_snapshot_preview1_fd_seek)));
672 _   (SuppressLookupFailure (m3_LinkRawFunction (module, "wasi_unstable",          "fd_filestat_get",   "i(i*)",     &m3_wasi_unstable_fd_filestat_get)));
673 _   (SuppressLookupFailure (m3_LinkRawFunction (module, "wasi_snapshot_preview1", "fd_filestat_get",   "i(i*)",     &m3_wasi_snapshot_preview1_fd_filestat_get)));
674 _   (SuppressLookupFailure (m3_LinkRawFunction (module, "wasi_unstable",          "path_filestat_get", "i(ii*i*)",  &m3_wasi_unstable_path_filestat_get)));
675 _   (SuppressLookupFailure (m3_LinkRawFunction (module, "wasi_snapshot_preview1", "path_filestat_get", "i(ii*i*)",  &m3_wasi_snapshot_preview1_path_filestat_get)));
676 
677     for (int i=0; i<2; i++)
678     {
679         const char* wasi = namespaces[i];
680 
681 _       (SuppressLookupFailure (m3_LinkRawFunctionEx (module, wasi, "args_get",           "i(**)",   &m3_wasi_generic_args_get, wasi_context)));
682 _       (SuppressLookupFailure (m3_LinkRawFunctionEx (module, wasi, "args_sizes_get",     "i(**)",   &m3_wasi_generic_args_sizes_get, wasi_context)));
683 _       (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "clock_res_get",        "i(i*)",   &m3_wasi_generic_clock_res_get)));
684 _       (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "clock_time_get",       "i(iI*)",  &m3_wasi_generic_clock_time_get)));
685 _       (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "environ_get",          "i(**)",   &m3_wasi_generic_environ_get)));
686 _       (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "environ_sizes_get",    "i(**)",   &m3_wasi_generic_environ_sizes_get)));
687 
688 //_     (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_advise",            "i(iIIi)", )));
689 //_     (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_allocate",          "i(iII)",  )));
690 _       (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_close",             "i(i)",    &m3_wasi_generic_fd_close)));
691 _       (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_datasync",          "i(i)",    &m3_wasi_generic_fd_datasync)));
692 _       (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_fdstat_get",        "i(i*)",   &m3_wasi_generic_fd_fdstat_get)));
693 _       (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_fdstat_set_flags",  "i(ii)",   &m3_wasi_generic_fd_fdstat_set_flags)));
694 //_     (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_fdstat_set_rights", "i(iII)",  )));
695 //_     (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_filestat_set_size", "i(iI)",   )));
696 //_     (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_filestat_set_times","i(iIIi)", )));
697 _       (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_pread",             "i(i*iI*)",&m3_wasi_generic_fd_pread)));
698 _       (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_prestat_get",       "i(i*)",   &m3_wasi_generic_fd_prestat_get)));
699 _       (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_prestat_dir_name",  "i(i*i)",  &m3_wasi_generic_fd_prestat_dir_name)));
700 //_     (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_pwrite",            "i(i*iI*)",)));
701 _       (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_read",              "i(i*i*)", &m3_wasi_generic_fd_read)));
702 _       (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_readdir",           "i(i*iI*)",&m3_wasi_generic_fd_readdir)));
703 //_     (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_renumber",          "i(ii)",   )));
704 //_     (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_sync",              "i(i)",    )));
705 //_     (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_tell",              "i(i*)",   )));
706 _       (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_write",             "i(i*i*)", &m3_wasi_generic_fd_write)));
707 
708 _       (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_create_directory",    "i(i*i)",       &m3_wasi_generic_path_create_directory)));
709 //_     (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_filestat_set_times",  "i(ii*iIIi)",   )));
710 //_     (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_link",                "i(ii*ii*i)",   )));
711 _       (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_open",                "i(ii*iiIIi*)", &m3_wasi_generic_path_open)));
712 _       (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_readlink",            "i(i*i*i*)",    &m3_wasi_generic_path_readlink)));
713 _       (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_remove_directory",    "i(i*i)",       &m3_wasi_generic_path_remove_directory)));
714 _       (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_rename",              "i(i*ii*i)",    &m3_wasi_generic_path_rename)));
715 //_     (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_symlink",             "i(*ii*i)",     )));
716 _       (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_unlink_file",         "i(i*i)",       &m3_wasi_generic_path_unlink_file)));
717 
718 _       (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "poll_oneoff",          "i(**i*)", &m3_wasi_generic_poll_oneoff)));
719 _       (SuppressLookupFailure (m3_LinkRawFunctionEx (module, wasi, "proc_exit",          "v(i)",    &m3_wasi_generic_proc_exit, wasi_context)));
720 //_     (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "proc_raise",           "i(i)",    )));
721 _       (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "random_get",           "i(*i)",   &m3_wasi_generic_random_get)));
722 //_     (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "sched_yield",          "i()",     )));
723 
724 //_     (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "sock_recv",            "i(i*ii**)",        )));
725 //_     (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "sock_send",            "i(i*ii*)",         )));
726 //_     (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "sock_shutdown",        "i(ii)",            )));
727     }
728 
729 _catch:
730     return result;
731 }
732 
733 #endif // d_m3HasMetaWASI
734 
735