cherry/wasmtest: a test program for wasmexport

Change-Id: I54700d85b52e7be12f337fc72b39a479605dc38f
Reviewed-on: https://go-review.googlesource.com/c/scratch/+/604235
TryBot-Bypass: Cherry Mui <cherryyz@google.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
This commit is contained in:
Cherry Mui 2024-08-07 23:06:50 -04:00
Родитель 6cf087efc7
Коммит a6564155a7
4 изменённых файлов: 197 добавлений и 0 удалений

5
cherry/wasmtest/go.mod Normal file
Просмотреть файл

@ -0,0 +1,5 @@
module golang.org/x/scratch/cherry/wasmtest
go 1.22
require github.com/tetratelabs/wazero v1.7.3

2
cherry/wasmtest/go.sum Normal file
Просмотреть файл

@ -0,0 +1,2 @@
github.com/tetratelabs/wazero v1.7.3 h1:PBH5KVahrt3S2AHgEjKu4u+LlDbbk+nsGE3KLucy6Rw=
github.com/tetratelabs/wazero v1.7.3/go.mod h1:ytl6Zuh20R/eROuyDaGPkp82O9C/DJfXAwJfQ3X6/7Y=

Просмотреть файл

@ -0,0 +1,62 @@
package main
import (
"runtime"
"runtime/debug"
)
func init() {
println("init function called")
}
var ch = make(chan float64)
//go:wasmexport E
func E(a int64, b int32, c float64, d float32) { // various types of args, no result
println("=== E ===")
// goroutine
go func() { ch <- float64(a) + float64(b) + c + float64(d) + 100 }()
debug.PrintStack() // traceback
grow([100]int{10}) // stack growth
runtime.GC() // GC
println("=== E end ===")
}
//go:wasmexport F
func F() int64 { // no arg, has result
f := int64(<-ch * 100) // force a goroutine switch
println("F =", f)
return f
}
//go:wasmexport G
func G(x int32) {
println("G", x)
if x%2 == 0 {
G(x - 1) // simple recursion within this module
} else {
J(x - 1) // mutual recursion between host and this module
}
println("G", x, "end")
}
//go:wasmimport test I
func I() int64
//go:wasmimport test J
func J(int32)
func main() {
println("hello")
println("main: I =", I())
}
func grow(x [100]int) {
if x[0] == 0 {
println("=== grow ===")
debug.PrintStack()
return
}
x[0]--
grow(x)
}

128
cherry/wasmtest/w.go Normal file
Просмотреть файл

@ -0,0 +1,128 @@
// Copyright 2024 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// A program for testing wasmexport.
// This is the driver/host program, which provides the imports
// and calls the exports. testprog is the source of the Wasm
// module, which can be compiled to either an executable or a
// library.
//
// To build it as executable:
// GOARCH=wasm GOOS=wasip1 go build -o /tmp/x.wasm ./testprog
//
// To build it as a library:
// GOARCH=wasm GOOS=wasip1 go build -buildmode=c-shared -o /tmp/x.wasm ./testprog
//
// Then run the driver (which works for both modes):
// go run w.go /tmp/x.wasm
package main
import (
"context"
"fmt"
"os"
"github.com/tetratelabs/wazero"
"github.com/tetratelabs/wazero/api"
"github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1"
)
// exported from wasm
var E func(a int64, b int32, c float64, d float32)
var F func() int64
var G func(int32)
func I() int64 {
println("I start")
E(20, 3, 0.4, 0.05)
r := F() * 2
G(4)
println("I end =", r)
return r
}
func J(x int32) {
println("J", x)
if x > 0 {
G(x)
}
println("J", x, "end")
}
func main() {
ctx := context.Background()
r := wazero.NewRuntime(ctx)
defer r.Close(ctx)
// provide import functions from host
_, err := r.NewHostModuleBuilder("test").
NewFunctionBuilder().WithFunc(I).Export("I").
NewFunctionBuilder().WithFunc(J).Export("J").
Instantiate(ctx)
if err != nil {
panic(err)
}
buf, err := os.ReadFile(os.Args[1])
if err != nil {
panic(err)
}
config := wazero.NewModuleConfig().
WithStdout(os.Stdout).WithStderr(os.Stderr).
WithStartFunctions() // don't call _start
wasi_snapshot_preview1.MustInstantiate(ctx, r)
m, err := r.InstantiateWithConfig(ctx, buf, config)
if err != nil {
panic(err)
}
// get export functions from the module
E = func(a int64, b int32, c float64, d float32) {
exp := m.ExportedFunction("E")
_, err := exp.Call(ctx, api.EncodeI64(a), api.EncodeI32(b), api.EncodeF64(c), api.EncodeF32(d))
if err != nil {
panic(err)
}
}
F = func() int64 {
exp := m.ExportedFunction("F")
r, err := exp.Call(ctx)
if err != nil {
panic(err)
}
rr := int64(r[0])
println("host: F =", rr)
return rr
}
G = func(x int32) {
exp := m.ExportedFunction("G")
_, err := exp.Call(ctx, api.EncodeI32(x))
if err != nil {
panic(err)
}
}
entry := m.ExportedFunction("_start")
if entry != nil {
// Executable mode.
fmt.Println("Executable mode: start")
_, err := entry.Call(ctx)
fmt.Println(err)
return
}
// Library mode.
entry = m.ExportedFunction("_initialize")
fmt.Println("Library mode: initialize")
_, err = entry.Call(ctx)
if err != nil {
panic(err)
}
fmt.Println("\nLibrary mode: call export functions")
I()
}