0
votes

I am building a Webassembly runtime and am currently implementing the WASI APIs. I'm wondering how the ABI looks like, according to this document: https://github.com/WebAssembly/WASI/blob/main/phases/snapshot/docs.md

To test, I have compiled this C application with emscripten to a standalone WASM module.

#include <stdio.h>

int main() {
    printf("Hello, World!\n");
    return 0;
}

After checking with wasm-objdump, I can see the following function imports:

Import[2]:
 - func[0] sig=2 <__wasi_proc_exit> <- wasi_snapshot_preview1.proc_exit
 - func[1] sig=11 <__wasi_fd_write> <- wasi_snapshot_preview1.fd_write

with the type signatures:

 - type[2] (i32) -> nil
 - type[11] (i32, i32, i32, i32) -> i32

According to the spec, the fd_write function has the signature fd_write(fd: fd, iovs: ciovec_array) -> Result<size, errno>, which maps to the POSIX system call ssize_t writev(int fd, const struct iovec *iov, int iovcnt);.

But what is the fourth argument in the WASM file? It receives some pointer to a memory address. So I thought I would have to write Result<size, errno> to that address, but if I do that and return 0 (for success), the fd_write gets called just over and over again (presumably because the printf function assumes that nothing was written). If I return the written bytes, the program terminates correctly, but what is then the fourth argument? Also, how can I return more complex Results, which do not fit into an i32?