1 //
2 //  m3_api_esp_wasi.c
3 //
4 //  Created by Volodymyr Shymanskyy on 01/07/20.
5 //  Copyright © 2019 Volodymyr Shymanskyy. All rights reserved.
6 //
7 
8 #define _POSIX_C_SOURCE 200809L
9 
10 #include "m3_api_esp_wasi.h"
11 
12 #include "m3/m3_env.h"
13 #include "m3/m3_exception.h"
14 
15 #if defined(ESP32)
16 
17 typedef uint32_t __wasi_size_t;
18 #include "m3/extra/wasi_core.h"
19 
20 #include <sys/types.h>
21 #include <sys/stat.h>
22 #include <time.h>
23 #include <errno.h>
24 #include <stdio.h>
25 #include <fcntl.h>
26 #include <unistd.h>
27 
28 typedef struct wasi_iovec_t
29 {
30     __wasi_size_t buf;
31     __wasi_size_t buf_len;
32 } wasi_iovec_t;
33 
34 #define PREOPEN_CNT   3
35 
36 typedef struct Preopen {
37     int         fd;
38     char*       path;
39 } Preopen;
40 
41 Preopen preopen[PREOPEN_CNT] = {
42     {  0, "<stdin>"  },
43     {  1, "<stdout>" },
44     {  2, "<stderr>" },
45 };
46 
47 static
errno_to_wasi(int errnum)48 __wasi_errno_t errno_to_wasi(int errnum) {
49     switch (errnum) {
50     case EPERM:   return __WASI_EPERM;   break;
51     case ENOENT:  return __WASI_ENOENT;  break;
52     case ESRCH:   return __WASI_ESRCH;   break;
53     case EINTR:   return __WASI_EINTR;   break;
54     case EIO:     return __WASI_EIO;     break;
55     case ENXIO:   return __WASI_ENXIO;   break;
56     case E2BIG:   return __WASI_E2BIG;   break;
57     case ENOEXEC: return __WASI_ENOEXEC; break;
58     case EBADF:   return __WASI_EBADF;   break;
59     case ECHILD:  return __WASI_ECHILD;  break;
60     case EAGAIN:  return __WASI_EAGAIN;  break;
61     case ENOMEM:  return __WASI_ENOMEM;  break;
62     case EACCES:  return __WASI_EACCES;  break;
63     case EFAULT:  return __WASI_EFAULT;  break;
64     case EBUSY:   return __WASI_EBUSY;   break;
65     case EEXIST:  return __WASI_EEXIST;  break;
66     case EXDEV:   return __WASI_EXDEV;   break;
67     case ENODEV:  return __WASI_ENODEV;  break;
68     case ENOTDIR: return __WASI_ENOTDIR; break;
69     case EISDIR:  return __WASI_EISDIR;  break;
70     case EINVAL:  return __WASI_EINVAL;  break;
71     case ENFILE:  return __WASI_ENFILE;  break;
72     case EMFILE:  return __WASI_EMFILE;  break;
73     case ENOTTY:  return __WASI_ENOTTY;  break;
74     case ETXTBSY: return __WASI_ETXTBSY; break;
75     case EFBIG:   return __WASI_EFBIG;   break;
76     case ENOSPC:  return __WASI_ENOSPC;  break;
77     case ESPIPE:  return __WASI_ESPIPE;  break;
78     case EROFS:   return __WASI_EROFS;   break;
79     case EMLINK:  return __WASI_EMLINK;  break;
80     case EPIPE:   return __WASI_EPIPE;   break;
81     case EDOM:    return __WASI_EDOM;    break;
82     case ERANGE:  return __WASI_ERANGE;  break;
83     default:      return __WASI_EINVAL;
84     }
85 }
86 
87 static inline
convert_clockid(__wasi_clockid_t in)88 int convert_clockid(__wasi_clockid_t in) {
89     switch (in) {
90     case __WASI_CLOCK_MONOTONIC:            return CLOCK_MONOTONIC;
91     //case __WASI_CLOCK_PROCESS_CPUTIME_ID:   return CLOCK_PROCESS_CPUTIME_ID;
92     case __WASI_CLOCK_REALTIME:             return CLOCK_REALTIME;
93     //case __WASI_CLOCK_THREAD_CPUTIME_ID:    return CLOCK_THREAD_CPUTIME_ID;
94     default: return -1;
95     }
96 }
97 
98 static inline
convert_timespec(const struct timespec * ts)99 __wasi_timestamp_t convert_timespec(const struct timespec *ts) {
100     if (ts->tv_sec < 0)
101         return 0;
102     if ((__wasi_timestamp_t)ts->tv_sec >= UINT64_MAX / 1000000000)
103         return UINT64_MAX;
104     return (__wasi_timestamp_t)ts->tv_sec * 1000000000 + ts->tv_nsec;
105 }
106 
107 
108 /*
109  * WASI API implementation
110  */
111 
m3ApiRawFunction(m3_wasi_unstable_args_get)112 m3ApiRawFunction(m3_wasi_unstable_args_get)
113 {
114     m3ApiReturnType  (uint32_t)
115     m3ApiGetArgMem   (uint32_t *           , argv)
116     m3ApiGetArgMem   (char *               , argv_buf)
117 
118     if (runtime == NULL) { m3ApiReturn(__WASI_EINVAL); }
119 
120     for (u32 i = 0; i < runtime->argc; ++i)
121     {
122         m3ApiWriteMem32(&argv[i], m3ApiPtrToOffset(argv_buf));
123 
124         size_t len = strlen (runtime->argv[i]);
125         memcpy (argv_buf, runtime->argv[i], len);
126         argv_buf += len;
127         * argv_buf++ = 0;
128     }
129 
130     m3ApiReturn(__WASI_ESUCCESS);
131 }
132 
m3ApiRawFunction(m3_wasi_unstable_args_sizes_get)133 m3ApiRawFunction(m3_wasi_unstable_args_sizes_get)
134 {
135     m3ApiReturnType  (uint32_t)
136     m3ApiGetArgMem   (__wasi_size_t *      , argc)
137     m3ApiGetArgMem   (__wasi_size_t *      , argv_buf_size)
138 
139     if (runtime == NULL) { m3ApiReturn(__WASI_EINVAL); }
140 
141     __wasi_size_t buflen = 0;
142     for (u32 i = 0; i < runtime->argc; ++i)
143     {
144         buflen += strlen (runtime->argv[i]) + 1;
145     }
146 
147     m3ApiWriteMem32(argc, runtime->argc);
148     m3ApiWriteMem32(argv_buf_size, buflen);
149 
150     m3ApiReturn(__WASI_ESUCCESS);
151 }
152 
m3ApiRawFunction(m3_wasi_unstable_environ_get)153 m3ApiRawFunction(m3_wasi_unstable_environ_get)
154 {
155     m3ApiReturnType  (uint32_t)
156     m3ApiGetArgMem   (uint32_t *           , env)
157     m3ApiGetArgMem   (char *               , env_buf)
158 
159     if (runtime == NULL) { m3ApiReturn(__WASI_EINVAL); }
160     // TODO
161     m3ApiReturn(__WASI_ESUCCESS);
162 }
163 
m3ApiRawFunction(m3_wasi_unstable_environ_sizes_get)164 m3ApiRawFunction(m3_wasi_unstable_environ_sizes_get)
165 {
166     m3ApiReturnType  (uint32_t)
167     m3ApiGetArgMem   (__wasi_size_t *      , env_count)
168     m3ApiGetArgMem   (__wasi_size_t *      , env_buf_size)
169 
170     if (runtime == NULL) { m3ApiReturn(__WASI_EINVAL); }
171 
172     // TODO
173     m3ApiWriteMem32(env_count,    0);
174     m3ApiWriteMem32(env_buf_size, 0);
175 
176     m3ApiReturn(__WASI_ESUCCESS);
177 }
178 
m3ApiRawFunction(m3_wasi_unstable_fd_prestat_dir_name)179 m3ApiRawFunction(m3_wasi_unstable_fd_prestat_dir_name)
180 {
181     m3ApiReturnType  (uint32_t)
182     m3ApiGetArg      (__wasi_fd_t          , fd)
183     m3ApiGetArgMem   (char *               , path)
184     m3ApiGetArg      (__wasi_size_t        , path_len)
185 
186     if (runtime == NULL) { m3ApiReturn(__WASI_EINVAL); }
187     if (fd < 3 || fd >= PREOPEN_CNT) { m3ApiReturn(__WASI_EBADF); }
188     size_t slen = strlen(preopen[fd].path);
189     memcpy(path, preopen[fd].path, M3_MIN(slen, path_len));
190     m3ApiReturn(__WASI_ESUCCESS);
191 }
192 
m3ApiRawFunction(m3_wasi_unstable_fd_prestat_get)193 m3ApiRawFunction(m3_wasi_unstable_fd_prestat_get)
194 {
195     m3ApiReturnType  (uint32_t)
196     m3ApiGetArg      (__wasi_fd_t          , fd)
197     m3ApiGetArgMem   (uint32_t *           , buf)  // TODO: use actual struct
198 
199     if (runtime == NULL) { m3ApiReturn(__WASI_EINVAL); }
200     if (fd < 3 || fd >= PREOPEN_CNT) { m3ApiReturn(__WASI_EBADF); }
201     m3ApiWriteMem32(buf,    __WASI_PREOPENTYPE_DIR);
202     m3ApiWriteMem32(buf+1,  strlen(preopen[fd].path));
203     m3ApiReturn(__WASI_ESUCCESS);
204 }
205 
m3ApiRawFunction(m3_wasi_unstable_fd_fdstat_get)206 m3ApiRawFunction(m3_wasi_unstable_fd_fdstat_get)
207 {
208     m3ApiReturnType  (uint32_t)
209     m3ApiGetArg      (__wasi_fd_t          , fd)
210     m3ApiGetArgMem   (__wasi_fdstat_t *    , fdstat)
211 
212     if (runtime == NULL || fdstat == NULL) { m3ApiReturn(__WASI_EINVAL); }
213 
214     struct stat fd_stat;
215     int fl = fcntl(fd, F_GETFL);
216     if (fl < 0) { m3ApiReturn(errno_to_wasi(errno)); }
217     fstat(fd, &fd_stat);
218     int mode = fd_stat.st_mode;
219     fdstat->fs_filetype = (S_ISBLK(mode)   ? __WASI_FILETYPE_BLOCK_DEVICE     : 0) |
220                           (S_ISCHR(mode)   ? __WASI_FILETYPE_CHARACTER_DEVICE : 0) |
221                           (S_ISDIR(mode)   ? __WASI_FILETYPE_DIRECTORY        : 0) |
222                           (S_ISREG(mode)   ? __WASI_FILETYPE_REGULAR_FILE     : 0) |
223                           //(S_ISSOCK(mode)  ? __WASI_FILETYPE_SOCKET_STREAM    : 0) |
224                           (S_ISLNK(mode)   ? __WASI_FILETYPE_SYMBOLIC_LINK    : 0);
225     m3ApiWriteMem16(&fdstat->fs_flags,
226                        ((fl & O_APPEND)    ? __WASI_FDFLAG_APPEND    : 0) |
227                        //((fl & O_DSYNC)     ? __WASI_FDFLAG_DSYNC     : 0) |
228                        ((fl & O_NONBLOCK)  ? __WASI_FDFLAG_NONBLOCK  : 0) |
229                        //((fl & O_RSYNC)     ? __WASI_FDFLAG_RSYNC     : 0) |
230                        ((fl & O_SYNC)      ? __WASI_FDFLAG_SYNC      : 0));
231     fdstat->fs_rights_base = (uint64_t)-1; // all rights
232     fdstat->fs_rights_inheriting = (uint64_t)-1; // all rights
233     m3ApiReturn(__WASI_ESUCCESS);
234 }
235 
m3ApiRawFunction(m3_wasi_unstable_fd_fdstat_set_flags)236 m3ApiRawFunction(m3_wasi_unstable_fd_fdstat_set_flags)
237 {
238     m3ApiReturnType  (uint32_t)
239     m3ApiGetArg      (__wasi_fd_t          , fd)
240     m3ApiGetArg      (__wasi_fdflags_t     , flags)
241 
242     // TODO
243 
244     m3ApiReturn(__WASI_ESUCCESS);
245 }
246 
m3ApiRawFunction(m3_wasi_unstable_fd_seek)247 m3ApiRawFunction(m3_wasi_unstable_fd_seek)
248 {
249     m3ApiReturnType  (uint32_t)
250     m3ApiGetArg      (__wasi_fd_t          , fd)
251     m3ApiGetArg      (__wasi_filedelta_t   , offset)
252     m3ApiGetArg      (__wasi_whence_t      , wasi_whence)
253     m3ApiGetArgMem   (__wasi_filesize_t *  , result)
254 
255     if (runtime == NULL || result == NULL) { m3ApiReturn(__WASI_EINVAL); }
256 
257     int whence;
258     switch (wasi_whence) {
259     case __WASI_WHENCE_CUR: whence = SEEK_CUR; break;
260     case __WASI_WHENCE_END: whence = SEEK_END; break;
261     case __WASI_WHENCE_SET: whence = SEEK_SET; break;
262     default:                m3ApiReturn(__WASI_EINVAL);
263     }
264 
265     int64_t ret;
266     ret = lseek(fd, offset, whence);
267     if (ret < 0) { m3ApiReturn(errno_to_wasi(errno)); }
268     m3ApiWriteMem64(result, ret);
269     m3ApiReturn(__WASI_ESUCCESS);
270 }
271 
272 
m3ApiRawFunction(m3_wasi_unstable_path_open)273 m3ApiRawFunction(m3_wasi_unstable_path_open)
274 {
275     m3ApiReturnType  (uint32_t)
276     m3ApiGetArg      (__wasi_fd_t          , dirfd)
277     m3ApiGetArg      (__wasi_lookupflags_t , dirflags)
278     m3ApiGetArgMem   (const char *         , path)
279     m3ApiGetArg      (__wasi_size_t        , path_len)
280     m3ApiGetArg      (__wasi_oflags_t      , oflags)
281     m3ApiGetArg      (__wasi_rights_t      , fs_rights_base)
282     m3ApiGetArg      (__wasi_rights_t      , fs_rights_inheriting)
283     m3ApiGetArg      (__wasi_fdflags_t     , fs_flags)
284     m3ApiGetArgMem   (__wasi_fd_t *        , fd)
285 
286     if (path_len >= 512)
287         m3ApiReturn(__WASI_EINVAL);
288 
289     // copy path so we can ensure it is NULL terminated
290     char host_path [path_len+1];
291 
292     memcpy (host_path, path, path_len);
293     host_path[path_len] = '\0'; // NULL terminator
294 
295     // TODO
296     m3ApiReturn(__WASI_ENOSYS);
297 }
298 
m3ApiRawFunction(m3_wasi_unstable_fd_read)299 m3ApiRawFunction(m3_wasi_unstable_fd_read)
300 {
301     m3ApiReturnType  (uint32_t)
302     m3ApiGetArg      (__wasi_fd_t          , fd)
303     m3ApiGetArgMem   (wasi_iovec_t *       , wasi_iovs)
304     m3ApiGetArg      (__wasi_size_t        , iovs_len)
305     m3ApiGetArgMem   (__wasi_size_t *      , nread)
306 
307     if (runtime == NULL || nread == NULL) { m3ApiReturn(__WASI_EINVAL); }
308 
309     ssize_t res = 0;
310     for (__wasi_size_t i = 0; i < iovs_len; i++) {
311         void* addr = m3ApiOffsetToPtr(m3ApiReadMem32(&wasi_iovs[i].buf));
312         size_t len = m3ApiReadMem32(&wasi_iovs[i].buf_len);
313         if (len == 0) continue;
314 
315         int ret = read (fd, addr, len);
316         if (ret < 0) m3ApiReturn(errno_to_wasi(errno));
317         res += ret;
318         if ((size_t)ret < len) break;
319     }
320     m3ApiWriteMem32(nread, res);
321     m3ApiReturn(__WASI_ESUCCESS);
322 }
323 
m3ApiRawFunction(m3_wasi_unstable_fd_write)324 m3ApiRawFunction(m3_wasi_unstable_fd_write)
325 {
326     m3ApiReturnType  (uint32_t)
327     m3ApiGetArg      (__wasi_fd_t          , fd)
328     m3ApiGetArgMem   (wasi_iovec_t *       , wasi_iovs)
329     m3ApiGetArg      (__wasi_size_t        , iovs_len)
330     m3ApiGetArgMem   (__wasi_size_t *      , nwritten)
331 
332     if (runtime == NULL || nwritten == NULL) { m3ApiReturn(__WASI_EINVAL); }
333 
334     ssize_t res = 0;
335     for (__wasi_size_t i = 0; i < iovs_len; i++) {
336         void* addr = m3ApiOffsetToPtr(m3ApiReadMem32(&wasi_iovs[i].buf));
337         size_t len = m3ApiReadMem32(&wasi_iovs[i].buf_len);
338         if (len == 0) continue;
339 
340         int ret = write (fd, addr, len);
341         if (ret < 0) m3ApiReturn(errno_to_wasi(errno));
342         res += ret;
343         if ((size_t)ret < len) break;
344     }
345     m3ApiWriteMem32(nwritten, res);
346     m3ApiReturn(__WASI_ESUCCESS);
347 }
348 
m3ApiRawFunction(m3_wasi_unstable_fd_close)349 m3ApiRawFunction(m3_wasi_unstable_fd_close)
350 {
351     m3ApiReturnType  (uint32_t)
352     m3ApiGetArg      (__wasi_fd_t, fd)
353 
354     int ret = close(fd);
355     m3ApiReturn(ret == 0 ? __WASI_ESUCCESS : ret);
356 }
357 
m3ApiRawFunction(m3_wasi_unstable_fd_datasync)358 m3ApiRawFunction(m3_wasi_unstable_fd_datasync)
359 {
360     m3ApiReturnType  (uint32_t)
361     m3ApiGetArg      (__wasi_fd_t, fd)
362 
363     // TODO
364     m3ApiReturn(__WASI_ESUCCESS);
365 }
366 
m3ApiRawFunction(m3_wasi_unstable_random_get)367 m3ApiRawFunction(m3_wasi_unstable_random_get)
368 {
369     m3ApiReturnType  (uint32_t)
370     m3ApiGetArgMem   (uint8_t *            , buf)
371     m3ApiGetArg      (__wasi_size_t        , buflen)
372 
373     while (1) {
374         ssize_t retlen = 0;
375 
376 #if defined(__wasi__) || defined(__APPLE__) || defined(__ANDROID_API__) || defined(__OpenBSD__)
377         size_t reqlen = M3_MIN (buflen, 256);
378 #   if defined(__APPLE__) && (TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR)
379         retlen = SecRandomCopyBytes(kSecRandomDefault, reqlen, buf) < 0 ? -1 : reqlen;
380 #   else
381         retlen = getentropy(buf, reqlen) < 0 ? -1 : reqlen;
382 #   endif
383 #elif defined(__FreeBSD__) || defined(__linux__)
384         retlen = getrandom(buf, buflen, 0);
385 #elif defined(_WIN32)
386         if (RtlGenRandom(buf, buflen) == TRUE) {
387             m3ApiReturn(__WASI_ESUCCESS);
388         }
389 #else
390         m3ApiReturn(__WASI_ENOSYS);
391 #endif
392         if (retlen < 0) {
393             if (errno == EINTR || errno == EAGAIN) {
394                 continue;
395             }
396             m3ApiReturn(errno_to_wasi(errno));
397         } else if (retlen == buflen) {
398             m3ApiReturn(__WASI_ESUCCESS);
399         } else {
400             buf    += retlen;
401             buflen -= retlen;
402         }
403     }
404 }
405 
m3ApiRawFunction(m3_wasi_unstable_clock_res_get)406 m3ApiRawFunction(m3_wasi_unstable_clock_res_get)
407 {
408     m3ApiReturnType  (uint32_t)
409     m3ApiGetArg      (__wasi_clockid_t     , wasi_clk_id)
410     m3ApiGetArgMem   (__wasi_timestamp_t * , resolution)
411 
412     if (runtime == NULL || resolution == NULL) { m3ApiReturn(__WASI_EINVAL); }
413 
414     int clk = convert_clockid(wasi_clk_id);
415     if (clk < 0) m3ApiReturn(__WASI_EINVAL);
416 
417     struct timespec tp;
418     if (clock_getres(clk, &tp) != 0) {
419         m3ApiWriteMem64(resolution, 1000000);
420     } else {
421         m3ApiWriteMem64(resolution, convert_timespec(&tp));
422     }
423 
424     m3ApiReturn(__WASI_ESUCCESS);
425 }
426 
m3ApiRawFunction(m3_wasi_unstable_clock_time_get)427 m3ApiRawFunction(m3_wasi_unstable_clock_time_get)
428 {
429     m3ApiReturnType  (uint32_t)
430     m3ApiGetArg      (__wasi_clockid_t     , wasi_clk_id)
431     m3ApiGetArg      (__wasi_timestamp_t   , precision)
432     m3ApiGetArgMem   (__wasi_timestamp_t * , time)
433 
434     if (runtime == NULL || time == NULL) { m3ApiReturn(__WASI_EINVAL); }
435 
436     int clk = convert_clockid(wasi_clk_id);
437     if (clk < 0) m3ApiReturn(__WASI_EINVAL);
438 
439     struct timespec tp;
440     if (clock_gettime(clk, &tp) != 0) {
441         m3ApiReturn(errno_to_wasi(errno));
442     }
443 
444     m3ApiWriteMem64(time, convert_timespec(&tp));
445     m3ApiReturn(__WASI_ESUCCESS);
446 }
447 
m3ApiRawFunction(m3_wasi_unstable_proc_exit)448 m3ApiRawFunction(m3_wasi_unstable_proc_exit)
449 {
450     m3ApiGetArg      (uint32_t, code)
451 
452     runtime->exit_code = code;
453 
454     m3ApiTrap(m3Err_trapExit);
455 }
456 
457 
458 static
SuppressLookupFailure(M3Result i_result)459 M3Result SuppressLookupFailure(M3Result i_result)
460 {
461     if (i_result == m3Err_functionLookupFailed)
462         return m3Err_none;
463     else
464         return i_result;
465 }
466 
467 
m3_LinkEspWASI(IM3Module module)468 M3Result  m3_LinkEspWASI  (IM3Module module)
469 {
470     M3Result result = m3Err_none;
471 
472     // TODO: Preopen dirs
473 
474     static const char* namespaces[2] = { "wasi_unstable", "wasi_snapshot_preview1" };
475 
476     for (int i=0; i<2; i++)
477     {
478         const char* wasi = namespaces[i];
479 
480 _       (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "args_get",             "i(**)",   &m3_wasi_unstable_args_get)));
481 _       (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "args_sizes_get",       "i(**)",   &m3_wasi_unstable_args_sizes_get)));
482 _       (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "clock_res_get",        "i(i*)",   &m3_wasi_unstable_clock_res_get)));
483 _       (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "clock_time_get",       "i(iI*)",  &m3_wasi_unstable_clock_time_get)));
484 _       (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "environ_get",          "i(**)",   &m3_wasi_unstable_environ_get)));
485 _       (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "environ_sizes_get",    "i(**)",   &m3_wasi_unstable_environ_sizes_get)));
486 
487 //_     (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_advise",            "i(iIIi)", )));
488 //_     (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_allocate",          "i(iII)",  )));
489 _       (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_close",             "i(i)",    &m3_wasi_unstable_fd_close)));
490 _       (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_datasync",          "i(i)",    &m3_wasi_unstable_fd_datasync)));
491 _       (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_fdstat_get",        "i(i*)",   &m3_wasi_unstable_fd_fdstat_get)));
492 _       (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_fdstat_set_flags",  "i(ii)",   &m3_wasi_unstable_fd_fdstat_set_flags)));
493 //_     (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_fdstat_set_rights", "i(iII)",  )));
494 //_     (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_filestat_get",      "i(i*)",   )));
495 //_     (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_filestat_set_size", "i(iI)",   )));
496 //_     (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_filestat_set_times","i(iIIi)", )));
497 //_     (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_pread",             "i(i*iI*)",)));
498 _       (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_prestat_get",       "i(i*)",   &m3_wasi_unstable_fd_prestat_get)));
499 _       (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_prestat_dir_name",  "i(i*i)",  &m3_wasi_unstable_fd_prestat_dir_name)));
500 //_     (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_pwrite",            "i(i*iI*)",)));
501 _       (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_read",              "i(i*i*)", &m3_wasi_unstable_fd_read)));
502 //_     (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_readdir",           "i(i*iI*)",)));
503 //_     (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_renumber",          "i(ii)",   )));
504 _       (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_seek",              "i(iIi*)", &m3_wasi_unstable_fd_seek)));
505 //_     (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_sync",              "i(i)",    )));
506 //_     (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_tell",              "i(i*)",   )));
507 _       (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_write",             "i(i*i*)", &m3_wasi_unstable_fd_write)));
508 
509 //_     (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_create_directory",    "i(i*i)",       )));
510 //_     (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_filestat_get",        "i(ii*i*)",     &m3_wasi_unstable_path_filestat_get)));
511 //_     (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_filestat_set_times",  "i(ii*iIIi)",   )));
512 //_     (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_link",                "i(ii*ii*i)",   )));
513 _       (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_open",                "i(ii*iiIIi*)", &m3_wasi_unstable_path_open)));
514 //_     (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_readlink",            "i(i*i*i*)",    )));
515 //_     (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_remove_directory",    "i(i*i)",       )));
516 //_     (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_rename",              "i(i*ii*i)",    )));
517 //_     (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_symlink",             "i(*ii*i)",     )));
518 //_     (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_unlink_file",         "i(i*i)",       )));
519 
520 //_     (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "poll_oneoff",          "i(**i*)", &m3_wasi_unstable_poll_oneoff)));
521 _       (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "proc_exit",            "v(i)",    &m3_wasi_unstable_proc_exit)));
522 //_     (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "proc_raise",           "i(i)",    )));
523 _       (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "random_get",           "i(*i)",   &m3_wasi_unstable_random_get)));
524 //_     (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "sched_yield",          "i()",     )));
525 
526 //_     (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "sock_recv",            "i(i*ii**)",        )));
527 //_     (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "sock_send",            "i(i*ii*)",         )));
528 //_     (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "sock_shutdown",        "i(ii)",            )));
529     }
530 
531 _catch:
532     return result;
533 }
534 
535 #endif // ESP32
536 
537