Repository: tetratelabs/wazero (go)

Issue:
Signature mismatch running grain compiled wasm
@codefromthecrypt 

```
go run cmd/cli.go hello.gr.wasm
2022/03/14 19:22:23 import[12] func[wasi_snapshot_preview1.fd_pread]: signature mismatch: i32i32i32i64i32_i32 != i32i32i64i32_i32
exit status 1
```

```hello.gr
import Process from "sys/process"
import Array from "array"

print("==== Environment: ====")
match(Process.env()) {
	Ok(arr) => Array.forEach(print, arr),
	Err(err) => throw err
}


//print("==== Args: ====")
//Array.forEach( print, Process.argv())
```

```
grain --version
Grain cli 0.4.7
Grain compiler 0.4.6
wazero v0.0.0-20220307120532-336ebcf43668
```
[hello.gr.wasm.zip](https://github.com/tetratelabs/wazero/files/8200122/hello.gr.wasm.zip)



I've attached the grain program based on the source pasted above.

In case it's helpful:

```go
package main

import (
	"bytes"
	"fmt"
	"log"
	"os"
	"time"

	"github.com/tetratelabs/wazero"
)

func main() {
	now := time.Now()
	src := os.Args[1]
	source, _ := os.ReadFile(src)
	rt := wazero.NewRuntimeWithConfig(wazero.NewRuntimeConfig().WithFeatureSignExtensionOps(true))

	decoded, err := rt.CompileModule(source)
	if err != nil {
		log.Fatal(err)
	}

	stdinBuf := os.Stdin
	stdoutBuf := bytes.NewBuffer(nil)
	stderrBuf := bytes.NewBuffer(nil)

	wasiConfig := wazero.NewWASIConfig().
		WithStdin(stdinBuf).
		WithStdout(stdoutBuf).
		WithStderr(stderrBuf).
		WithEnviron(map[string]string{"bar": "baz"})

	if _, err = rt.InstantiateModule(wazero.WASISnapshotPreview1WithConfig(wasiConfig)); err != nil {
		log.Fatal(err)
	}
	if _, err = wazero.StartWASICommand(rt, decoded); err != nil {
		log.Fatal(err)
	}

	fmt.Println(stdoutBuf.String())
	fmt.Printf("took: %s\n", time.Since(now))
}
```

_Originally posted by @pims in https://github.com/tetratelabs/wazero/issues/66#issuecomment-1060816822_

Pull request:
wasi: fixes bad stubs
Fixes #370 Thanks to @pims for such a good capture of what to fix!

```bash
$ go run cmd/cli.go hello.gr.wasm
==== Environment: ====
bar=baz

took: 248.835102ms
```

Patch:
diff --git a/internal/wasi/wasi.go b/internal/wasi/wasi.go
index e2b115f3..d80819cb 100644
--- a/internal/wasi/wasi.go
+++ b/internal/wasi/wasi.go
@@ -165,7 +165,7 @@ const (
 
 	// ImportFdPread is the WebAssembly 1.0 (20191205) Text format import of FunctionFdPread.
 	ImportFdPread = `(import "wasi_snapshot_preview1" "fd_pread"
-    (func $wasi.fd_pread (param $fd i32) (param $iovs i32) (param $offset i64) (param $result.nread i32) (result (;errno;) i32)))`
+    (func $wasi.fd_pread (param $fd i32) (param $iovs i32) (param $iovs_len i32) (param $offset i64) (param $result.nread i32) (result (;errno;) i32)))`
 
 	// FunctionFdPrestatGet returns the prestat data of a file descriptor.
 	// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#fd_prestat_get
@@ -189,7 +189,7 @@ const (
 
 	// ImportFdPwrite is the WebAssembly 1.0 (20191205) Text format import of FunctionFdPwrite.
 	ImportFdPwrite = `(import "wasi_snapshot_preview1" "fd_pwrite"
-    (func $wasi.fd_pwrite (param $fd i32) (param $iovs i32) (param $offset i64) (param $result.nwritten i32) (result (;errno;) i32)))`
+    (func $wasi.fd_pwrite (param $fd i32) (param $iovs i32) (param $iovs_len i32) (param $offset i64) (param $result.nwritten i32) (result (;errno;) i32)))`
 
 	// FunctionFdRead read bytes from a file descriptor.
 	// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#fd_read
@@ -317,7 +317,7 @@ const (
 
 	// ImportPathSymlink is the WebAssembly 1.0 (20191205) Text format import of FunctionPathSymlink.
 	ImportPathSymlink = `(import "wasi_snapshot_preview1" "path_symlink"
-    (func $wasi.path_symlink (param $old_path i32) (param $old_path_len i32) (param $new_fd i32) (param $fd i32) (param $new_path i32) (param $new_path_len i32) (result (;errno;) i32)))`
+    (func $wasi.path_symlink (param $old_path i32) (param $old_path_len i32) (param $fd i32) (param $new_path i32) (param $new_path_len i32) (result (;errno;) i32)))`
 
 	// FunctionPathUnlinkFile unlinks a file.
 	// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-path_unlink_filefd-fd-path-string---errno
@@ -892,7 +892,7 @@ type SnapshotPreview1 interface {
 	PathRename(ctx wasm.Module, fd, oldPath, oldPathLen, newFd, newPath, newPathLen uint32) wasi.Errno
 
 	// PathSymlink is the WASI function named FunctionPathSymlink
-	PathSymlink(ctx wasm.Module, oldPath, oldPathLen, fd, newFd, newPath, newPathLen uint32) wasi.Errno
+	PathSymlink(ctx wasm.Module, oldPath, oldPathLen, fd, newPath, newPathLen uint32) wasi.Errno
 
 	// PathUnlinkFile is the WASI function named FunctionPathUnlinkFile
 	PathUnlinkFile(ctx wasm.Module, fd, path, pathLen uint32) wasi.Errno
@@ -1172,7 +1172,7 @@ func (a *wasiAPI) FdFilestatSetTimes(ctx wasm.Module, fd uint32, atim, mtim uint
 }
 
 // FdPread implements SnapshotPreview1.FdPread
-func (a *wasiAPI) FdPread(ctx wasm.Module, fd, iovs uint32, offset uint64, resultNread uint32) wasi.Errno {
+func (a *wasiAPI) FdPread(ctx wasm.Module, fd, iovs, iovsCount uint32, offset uint64, resultNread uint32) wasi.Errno {
 	return wasi.ErrnoNosys // stubbed for GrainLang per #271
 }
 
@@ -1198,7 +1198,7 @@ func (a *wasiAPI) FdPrestatDirName(ctx wasm.Module, fd uint32, pathPtr uint32, p
 }
 
 // FdPwrite implements SnapshotPreview1.FdPwrite
-func (a *wasiAPI) FdPwrite(ctx wasm.Module, fd, iovs uint32, offset uint64, resultNwritten uint32) wasi.Errno {
+func (a *wasiAPI) FdPwrite(ctx wasm.Module, fd, iovs, iovsCount uint32, offset uint64, resultNwritten uint32) wasi.Errno {
 	return wasi.ErrnoNosys // stubbed for GrainLang per #271
 }
 
@@ -1416,7 +1416,7 @@ func (a *wasiAPI) PathRename(ctx wasm.Module, fd, oldPath, oldPathLen, newFd, ne
 }
 
 // PathSymlink implements SnapshotPreview1.PathSymlink
-func (a *wasiAPI) PathSymlink(ctx wasm.Module, oldPath, oldPathLen, fd, newFd, newPath, newPathLen uint32) wasi.Errno {
+func (a *wasiAPI) PathSymlink(ctx wasm.Module, oldPath, oldPathLen, fd, newPath, newPathLen uint32) wasi.Errno {
 	return wasi.ErrnoNosys // stubbed for GrainLang per #271
 }
 


Test patch:
diff --git a/internal/wasi/wasi_test.go b/internal/wasi/wasi_test.go
index 53491294..4f71dec0 100644
--- a/internal/wasi/wasi_test.go
+++ b/internal/wasi/wasi_test.go
@@ -770,11 +770,11 @@ func TestSnapshotPreview1_FdPread(t *testing.T) {
 	mod, fn := instantiateModule(t, ctx, FunctionFdPread, ImportFdPread, moduleName, config)
 
 	t.Run("SnapshotPreview1.FdPread", func(t *testing.T) {
-		require.Equal(t, wasi.ErrnoNosys, NewAPI(config).FdPread(mod, 0, 0, 0, 0))
+		require.Equal(t, wasi.ErrnoNosys, NewAPI(config).FdPread(mod, 0, 0, 0, 0, 0))
 	})
 
 	t.Run(FunctionFdPread, func(t *testing.T) {
-		results, err := fn.Call(mod, 0, 0, 0, 0)
+		results, err := fn.Call(mod, 0, 0, 0, 0, 0)
 		require.NoError(t, err)
 		require.Equal(t, wasi.ErrnoNosys, wasi.Errno(results[0])) // cast because results are always uint64
 	})
@@ -894,11 +894,11 @@ func TestSnapshotPreview1_FdPwrite(t *testing.T) {
 	mod, fn := instantiateModule(t, ctx, FunctionFdPwrite, ImportFdPwrite, moduleName, config)
 
 	t.Run("SnapshotPreview1.FdPwrite", func(t *testing.T) {
-		require.Equal(t, wasi.ErrnoNosys, NewAPI(config).FdPwrite(mod, 0, 0, 0, 0))
+		require.Equal(t, wasi.ErrnoNosys, NewAPI(config).FdPwrite(mod, 0, 0, 0, 0, 0))
 	})
 
 	t.Run(FunctionFdPwrite, func(t *testing.T) {
-		results, err := fn.Call(mod, 0, 0, 0, 0)
+		results, err := fn.Call(mod, 0, 0, 0, 0, 0)
 		require.NoError(t, err)
 		require.Equal(t, wasi.ErrnoNosys, wasi.Errno(results[0])) // cast because results are always uint64
 	})
@@ -1743,11 +1743,11 @@ func TestSnapshotPreview1_PathSymlink(t *testing.T) {
 	mod, fn := instantiateModule(t, ctx, FunctionPathSymlink, ImportPathSymlink, moduleName, config)
 
 	t.Run("SnapshotPreview1.PathSymlink", func(t *testing.T) {
-		require.Equal(t, wasi.ErrnoNosys, NewAPI(config).PathSymlink(mod, 0, 0, 0, 0, 0, 0))
+		require.Equal(t, wasi.ErrnoNosys, NewAPI(config).PathSymlink(mod, 0, 0, 0, 0, 0))
 	})
 
 	t.Run(FunctionPathSymlink, func(t *testing.T) {
-		results, err := fn.Call(mod, 0, 0, 0, 0, 0, 0)
+		results, err := fn.Call(mod, 0, 0, 0, 0, 0)
 		require.NoError(t, err)
 		require.Equal(t, wasi.ErrnoNosys, wasi.Errno(results[0])) // cast because results are always uint64
 	})