From c941423fbac0238917a63218041e9edab448df9f Mon Sep 17 00:00:00 2001 From: Louis Thibault Date: Fri, 31 Mar 2023 15:42:41 -0400 Subject: [PATCH] Add wazergo-based host module for ww. Change process schema. --- api/process.capnp | 10 +- cmd/ww/main.go | 8 +- go.mod | 1 + go.sum | 2 + guest/tinygo/imports.go | 7 + guest/tinygo/shims.go | 14 + guest/tinygo/testdata/main.go | 18 + guest/tinygo/testdata/main.wasm | Bin 0 -> 164491 bytes guest/tinygo/testdata/main.wat | 3984 +++++++++++++++++++++++++ guest/tinygo/ww.go | 6 + internal/api/process/process.capnp.go | 707 ++--- internal/cmd/cluster/process.go | 7 +- internal/cmd/run/run.go | 78 + pkg/csp/executor.go | 97 +- pkg/csp/executor_test.go | 88 +- pkg/csp/proc.go | 120 +- pkg/csp/proc/proc.go | 50 + pkg/server/config.go | 10 +- pkg/server/server.go | 9 +- 19 files changed, 4548 insertions(+), 668 deletions(-) create mode 100644 guest/tinygo/imports.go create mode 100644 guest/tinygo/shims.go create mode 100644 guest/tinygo/testdata/main.go create mode 100755 guest/tinygo/testdata/main.wasm create mode 100644 guest/tinygo/testdata/main.wat create mode 100644 guest/tinygo/ww.go create mode 100644 internal/cmd/run/run.go create mode 100644 pkg/csp/proc/proc.go diff --git a/api/process.capnp b/api/process.capnp index 518e6a63..15e95cf4 100644 --- a/api/process.capnp +++ b/api/process.capnp @@ -7,13 +7,11 @@ $Go.import("github.com/wetware/ww/internal/api/process"); interface Executor { - spawn @0 (byteCode :Data, entryPoint :Text = "run") -> (process :Process); - # spawn a WASM based process from the binary module with the target - # entry function + exec @0 (bytecode :Data) -> (process :Process); + # exec a WASM based process } interface Process { - start @0 () -> (); - stop @1 () -> (); - wait @2 () -> (exitCode :UInt32); + wait @0 () -> (exitCode :UInt32); + kill @1 () -> (); } diff --git a/cmd/ww/main.go b/cmd/ww/main.go index 4cf1812c..1d6e10a1 100644 --- a/cmd/ww/main.go +++ b/cmd/ww/main.go @@ -13,6 +13,7 @@ import ( "github.com/wetware/ww/internal/cmd/cluster" "github.com/wetware/ww/internal/cmd/debug" + "github.com/wetware/ww/internal/cmd/run" "github.com/wetware/ww/internal/cmd/start" ww "github.com/wetware/ww/pkg" ) @@ -58,11 +59,12 @@ var flags = []cli.Flag{ var commands = []*cli.Command{ start.Command(), cluster.Command(), + run.Command(), debug.Command(), } func main() { - run(&cli.App{ + app := &cli.App{ Name: "wetware", HelpName: "ww", Usage: "simple, secure clusters", @@ -75,10 +77,8 @@ func main() { Metadata: map[string]interface{}{ "version": ww.Version, }, - }) -} + } -func run(app *cli.App) { if err := app.Run(os.Args); err != nil { log.Fatal(err) } diff --git a/go.mod b/go.mod index 8284ff88..d9ee4df6 100644 --- a/go.mod +++ b/go.mod @@ -35,6 +35,7 @@ require ( github.com/ipfs/go-ds-badger2 v0.1.3 github.com/lthibault/go-libp2p-inproc-transport v0.4.0 github.com/multiformats/go-multistream v0.4.1 + github.com/stealthrocket/wazergo v0.11.0 github.com/stretchr/testify v1.8.2 github.com/tetratelabs/wazero v1.0.1 github.com/thejerf/suture/v4 v4.0.2 diff --git a/go.sum b/go.sum index dce7bdd9..d94ffe65 100644 --- a/go.sum +++ b/go.sum @@ -472,6 +472,8 @@ github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tL github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= +github.com/stealthrocket/wazergo v0.11.0 h1:uei6jlnTQxjpuhzW31QgSkHi4eVKUaQmOf7WVytOCq8= +github.com/stealthrocket/wazergo v0.11.0/go.mod h1:ONoLQpwgBDX9VGB+CCAbzTNDmJJi5kcnFLL+pWIGF5M= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= diff --git a/guest/tinygo/imports.go b/guest/tinygo/imports.go new file mode 100644 index 00000000..41877372 --- /dev/null +++ b/guest/tinygo/imports.go @@ -0,0 +1,7 @@ +//go:build wasm || tinygo.wasm || wasi + +package ww + +//go:wasm-module ww +//go:export __test +func test(a, b uint32) uint32 diff --git a/guest/tinygo/shims.go b/guest/tinygo/shims.go new file mode 100644 index 00000000..a04905f3 --- /dev/null +++ b/guest/tinygo/shims.go @@ -0,0 +1,14 @@ +//go:build !purego && !appengine && !wasm && !tinygo.wasm && !wasi + +package ww + +/* + + shims.go contains shim functions for WASM imports, which allows + symbol names to resolve on non-WASM architectures. + +*/ + +func test(a, b uint32) uint32 { + return a + b +} diff --git a/guest/tinygo/testdata/main.go b/guest/tinygo/testdata/main.go new file mode 100644 index 00000000..9b57ad4b --- /dev/null +++ b/guest/tinygo/testdata/main.go @@ -0,0 +1,18 @@ +package main + +import ( + "fmt" + + ww "github.com/wetware/ww/guest/tinygo" +) + +func main() { + // it, release := ww.Ls(context.Background()) + // defer release() + + // for name := it.Next(); name != ""; name = it.Next() { + // fmt.Println(name) + // } + + fmt.Println(ww.Test(40, 2)) +} diff --git a/guest/tinygo/testdata/main.wasm b/guest/tinygo/testdata/main.wasm new file mode 100755 index 0000000000000000000000000000000000000000..3e04215494a71141b92f8ead57af721ad6f1be45 GIT binary patch literal 164491 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 H7eW6I5^ti! literal 0 HcmV?d00001 diff --git a/guest/tinygo/testdata/main.wat b/guest/tinygo/testdata/main.wat new file mode 100644 index 00000000..933974f7 --- /dev/null +++ b/guest/tinygo/testdata/main.wat @@ -0,0 +1,3984 @@ +(module + (type $i32_i32_i32_i32_=>_i32 (func (param i32 i32 i32 i32) (result i32))) + (type $i32_=>_none (func (param i32))) + (type $none_=>_none (func)) + (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) + (type $i32_i32_=>_none (func (param i32 i32))) + (type $i32_=>_i32 (func (param i32) (result i32))) + (type $none_=>_i32 (func (result i32))) + (type $i32_i32_i32_i32_=>_none (func (param i32 i32 i32 i32))) + (type $i32_i64_i32_=>_i32 (func (param i32 i64 i32) (result i32))) + (import "ww" "__test" (func $github.com/wetware/ww/guest/tinygo.test (param i32 i32) (result i32))) + (import "wasi_snapshot_preview1" "fd_write" (func $runtime.fd_write (param i32 i32 i32 i32) (result i32))) + (import "wasi_snapshot_preview1" "clock_time_get" (func $runtime.clock_time_get (param i32 i64 i32) (result i32))) + (import "wasi_snapshot_preview1" "proc_exit" (func $runtime.proc_exit (param i32))) + (import "wasi_snapshot_preview1" "args_sizes_get" (func $runtime.args_sizes_get (param i32 i32) (result i32))) + (import "wasi_snapshot_preview1" "args_get" (func $runtime.args_get (param i32 i32) (result i32))) + (memory $0 2) + (data (i32.const 65536) "free: invalid pointer\00\00\00\00\00\01\00\15\00\00\00realloc: invalid pointer \00\01\00\18\00\00\00out of memorypanic: panic: runtime error: nil pointer dereferenceindex out of rangeslice out of range") + (data (i32.const 65704) "x\9c\19\f6\e8\00\01\00\00\00\00\00\ac\01\01\00\c1\82\01\00\00\00\00\00\04\00\00\00\0c\00\00\00\01\00\00\00\00\00\00\00\01\00\00\00\00\00\00\00\02") + (table $0 3 3 funcref) + (elem (i32.const 1) $runtime.memequal $runtime.hash32) + (global $__stack_pointer (mut i32) (i32.const 65536)) + (export "memory" (memory $0)) + (export "malloc" (func $malloc)) + (export "free" (func $free)) + (export "calloc" (func $calloc)) + (export "realloc" (func $realloc)) + (export "_start" (func $_start)) + (func $__wasm_call_ctors + (nop) + ) + (func $tinygo_getCurrentStackPointer (result i32) + (global.get $__stack_pointer) + ) + (func $strlen (param $0 i32) (result i32) + (local $1 i32) + (local $2 i32) + (local.set $1 + (local.get $0) + ) + (block $label$1 + (block $label$2 + (br_if $label$2 + (i32.eqz + (i32.and + (local.get $0) + (i32.const 3) + ) + ) + ) + (br_if $label$1 + (i32.eqz + (i32.load8_u + (local.get $0) + ) + ) + ) + (br_if $label$2 + (i32.eqz + (i32.and + (local.tee $1 + (i32.add + (local.get $0) + (i32.const 1) + ) + ) + (i32.const 3) + ) + ) + ) + (br_if $label$1 + (i32.eqz + (i32.load8_u + (local.get $1) + ) + ) + ) + (br_if $label$2 + (i32.eqz + (i32.and + (local.tee $1 + (i32.add + (local.get $0) + (i32.const 2) + ) + ) + (i32.const 3) + ) + ) + ) + (br_if $label$1 + (i32.eqz + (i32.load8_u + (local.get $1) + ) + ) + ) + (br_if $label$2 + (i32.eqz + (i32.and + (local.tee $1 + (i32.add + (local.get $0) + (i32.const 3) + ) + ) + (i32.const 3) + ) + ) + ) + (br_if $label$1 + (i32.eqz + (i32.load8_u + (local.get $1) + ) + ) + ) + (local.set $1 + (i32.add + (local.get $0) + (i32.const 4) + ) + ) + ) + (local.set $1 + (i32.sub + (local.get $1) + (i32.const 5) + ) + ) + (loop $label$3 + (local.set $2 + (i32.add + (local.get $1) + (i32.const 5) + ) + ) + (local.set $1 + (i32.add + (local.get $1) + (i32.const 4) + ) + ) + (br_if $label$3 + (i32.eqz + (i32.and + (i32.and + (i32.xor + (local.tee $2 + (i32.load + (local.get $2) + ) + ) + (i32.const -1) + ) + (i32.sub + (local.get $2) + (i32.const 16843009) + ) + ) + (i32.const -2139062144) + ) + ) + ) + ) + (loop $label$4 + (br_if $label$4 + (i32.load8_u + (local.tee $1 + (i32.add + (local.get $1) + (i32.const 1) + ) + ) + ) + ) + ) + ) + (i32.sub + (local.get $1) + (local.get $0) + ) + ) + (func $runtime.memequal (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (result i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (i32.ge_u + (local.tee $4 + (block $label$1 (result i32) + (loop $label$2 + (drop + (br_if $label$1 + (local.get $2) + (i32.eq + (local.get $2) + (local.get $4) + ) + ) + ) + (local.set $5 + (i32.add + (local.get $1) + (local.get $4) + ) + ) + (local.set $6 + (i32.add + (local.get $0) + (local.get $4) + ) + ) + (local.set $4 + (i32.add + (local.get $4) + (i32.const 1) + ) + ) + (br_if $label$2 + (i32.eq + (i32.load8_u + (local.get $6) + ) + (i32.load8_u + (local.get $5) + ) + ) + ) + ) + (i32.sub + (local.get $4) + (i32.const 1) + ) + ) + ) + (local.get $2) + ) + ) + (func $runtime.hash32 (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (result i32) + (local.set $2 + (i32.xor + (i32.xor + (i32.mul + (local.get $1) + (i32.const -962287725) + ) + (local.get $2) + ) + (i32.const -1130422988) + ) + ) + (loop $label$1 + (if + (i32.eqz + (i32.lt_s + (local.get $1) + (i32.const 4) + ) + ) + (block + (local.set $2 + (i32.xor + (i32.shr_u + (local.tee $2 + (i32.mul + (i32.add + (i32.load align=1 + (local.get $0) + ) + (local.get $2) + ) + (i32.const -962287725) + ) + ) + (i32.const 16) + ) + (local.get $2) + ) + ) + (local.set $1 + (i32.sub + (local.get $1) + (i32.const 4) + ) + ) + (local.set $0 + (i32.add + (local.get $0) + (i32.const 4) + ) + ) + (br $label$1) + ) + ) + ) + (block $label$3 + (block $label$4 + (block $label$5 + (block $label$6 + (br_table $label$4 $label$5 $label$6 $label$3 + (i32.sub + (local.get $1) + (i32.const 1) + ) + ) + ) + (local.set $2 + (i32.add + (i32.shl + (i32.load8_u offset=2 + (local.get $0) + ) + (i32.const 16) + ) + (local.get $2) + ) + ) + ) + (local.set $2 + (i32.add + (i32.shl + (i32.load8_u offset=1 + (local.get $0) + ) + (i32.const 8) + ) + (local.get $2) + ) + ) + ) + (local.set $2 + (i32.xor + (i32.shr_u + (local.tee $1 + (i32.mul + (i32.add + (local.get $2) + (i32.load8_u + (local.get $0) + ) + ) + (i32.const -962287725) + ) + ) + (i32.const 24) + ) + (local.get $1) + ) + ) + ) + (local.get $2) + ) + (func $runtime.lookupPanic + (call $runtime.runtimePanic + (i32.const 65665) + (i32.const 18) + ) + (unreachable) + ) + (func $runtime.runtimePanic (param $0 i32) (param $1 i32) + (call $runtime.printstring + (i32.const 65620) + (i32.const 22) + ) + (call $runtime.printstring + (local.get $0) + (local.get $1) + ) + (call $runtime.printnl) + (unreachable) + ) + (func $runtime.slicePanic + (call $runtime.runtimePanic + (i32.const 65683) + (i32.const 18) + ) + (unreachable) + ) + (func $runtime.printstring (param $0 i32) (param $1 i32) + (local.set $1 + (select + (local.get $1) + (i32.const 0) + (i32.gt_s + (local.get $1) + (i32.const 0) + ) + ) + ) + (loop $label$1 + (if + (local.get $1) + (block + (call $runtime.putchar + (i32.load8_u + (local.get $0) + ) + ) + (local.set $1 + (i32.sub + (local.get $1) + (i32.const 1) + ) + ) + (local.set $0 + (i32.add + (local.get $0) + (i32.const 1) + ) + ) + (br $label$1) + ) + ) + ) + ) + (func $runtime.printnl + (call $runtime.putchar + (i32.const 10) + ) + ) + (func $runtime.putchar (param $0 i32) + (local $1 i32) + (local $2 i32) + (if + (i32.le_u + (local.tee $1 + (i32.load + (i32.const 65764) + ) + ) + (i32.const 119) + ) + (block + (i32.store + (i32.const 65764) + (local.tee $2 + (i32.add + (local.get $1) + (i32.const 1) + ) + ) + ) + (i32.store8 + (i32.add + (local.get $1) + (i32.const 65768) + ) + (local.get $0) + ) + (if + (i32.eqz + (i32.and + (i32.ne + (i32.and + (local.get $0) + (i32.const 255) + ) + (i32.const 10) + ) + (i32.ne + (local.get $1) + (i32.const 119) + ) + ) + ) + (block + (i32.store + (i32.const 65712) + (local.get $2) + ) + (drop + (call $runtime.fd_write + (i32.const 1) + (i32.const 65708) + (i32.const 1) + (i32.const 65936) + ) + ) + (i32.store + (i32.const 65764) + (i32.const 0) + ) + ) + ) + (return) + ) + ) + (call $runtime.lookupPanic) + (unreachable) + ) + (func $runtime.alloc (param $0 i32) (result i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (if + (i32.eqz + (local.get $0) + ) + (return + (i32.const 65928) + ) + ) + (i64.store + (i32.const 65904) + (i64.add + (i64.load + (i32.const 65904) + ) + (i64.extend_i32_u + (local.get $0) + ) + ) + ) + (i64.store + (i32.const 65912) + (i64.add + (i64.load + (i32.const 65912) + ) + (i64.const 1) + ) + ) + (local.set $5 + (i32.shr_u + (i32.add + (local.get $0) + (i32.const 15) + ) + (i32.const 4) + ) + ) + (local.set $3 + (local.tee $4 + (i32.load + (i32.const 65892) + ) + ) + ) + (loop $label$2 + (block $label$3 + (block $label$4 + (block $label$5 + (block $label$6 + (if + (i32.ne + (local.get $3) + (local.get $4) + ) + (block + (local.set $1 + (local.get $2) + ) + (br $label$6) + ) + ) + (local.set $1 + (i32.const 1) + ) + (block $label$8 + (block $label$9 + (br_table $label$6 $label$9 $label$8 + (i32.and + (local.get $2) + (i32.const 255) + ) + ) + ) + (drop + (i32.load + (i32.const 65932) + ) + ) + (call $runtime.markRoots + (call $tinygo_getCurrentStackPointer) + (i32.const 65536) + ) + (call $runtime.markRoots + (i32.const 65536) + (i32.const 66336) + ) + (loop $label$10 + (if + (i32.eqz + (i32.load8_u + (i32.const 65929) + ) + ) + (block + (local.set $2 + (i32.const 0) + ) + (local.set $4 + (i32.const 0) + ) + (local.set $1 + (i32.const 0) + ) + (loop $label$12 + (block $label$13 + (block $label$14 + (if + (i32.gt_u + (i32.load + (i32.const 65896) + ) + (local.get $1) + ) + (block + (block $label$16 + (block $label$17 + (block $label$18 + (block $label$19 + (br_table $label$16 $label$19 $label$18 $label$17 $label$13 + (i32.and + (call $\28runtime.gcBlock\29.state + (local.get $1) + ) + (i32.const 255) + ) + ) + ) + (call $\28runtime.gcBlock\29.markFree + (local.get $1) + ) + (i64.store + (i32.const 65920) + (i64.add + (i64.load + (i32.const 65920) + ) + (i64.const 1) + ) + ) + (br $label$14) + ) + (local.set $7 + (i32.and + (local.get $4) + (i32.const 1) + ) + ) + (local.set $4 + (i32.const 0) + ) + (br_if $label$13 + (i32.eqz + (local.get $7) + ) + ) + (call $\28runtime.gcBlock\29.markFree + (local.get $1) + ) + (br $label$14) + ) + (local.set $4 + (i32.const 0) + ) + (i32.store8 + (local.tee $7 + (i32.add + (i32.load + (i32.const 65888) + ) + (i32.shr_u + (local.get $1) + (i32.const 2) + ) + ) + ) + (i32.and + (i32.load8_u + (local.get $7) + ) + (i32.xor + (i32.shl + (i32.const 2) + (i32.and + (i32.shl + (local.get $1) + (i32.const 1) + ) + (i32.const 6) + ) + ) + (i32.const -1) + ) + ) + ) + (br $label$13) + ) + (local.set $2 + (i32.add + (local.get $2) + (i32.const 16) + ) + ) + (br $label$13) + ) + ) + (local.set $1 + (i32.const 2) + ) + (br_if $label$6 + (i32.ge_u + (local.get $2) + (i32.div_u + (i32.sub + (i32.load + (i32.const 65888) + ) + (i32.const 66336) + ) + (i32.const 3) + ) + ) + ) + (drop + (call $runtime.growHeap) + ) + (br $label$6) + ) + (local.set $2 + (i32.add + (local.get $2) + (i32.const 16) + ) + ) + (local.set $4 + (i32.const 1) + ) + ) + (local.set $1 + (i32.add + (local.get $1) + (i32.const 1) + ) + ) + (br $label$12) + ) + ) + ) + (local.set $1 + (i32.const 0) + ) + (i32.store8 + (i32.const 65929) + (i32.const 0) + ) + (local.set $2 + (i32.load + (i32.const 65896) + ) + ) + (loop $label$20 + (br_if $label$10 + (i32.ge_u + (local.get $1) + (local.get $2) + ) + ) + (if + (i32.eq + (i32.and + (call $\28runtime.gcBlock\29.state + (local.get $1) + ) + (i32.const 255) + ) + (i32.const 3) + ) + (block + (call $runtime.startMark + (local.get $1) + ) + (local.set $2 + (i32.load + (i32.const 65896) + ) + ) + ) + ) + (local.set $1 + (i32.add + (local.get $1) + (i32.const 1) + ) + ) + (br $label$20) + ) + ) + ) + (local.set $1 + (local.get $2) + ) + (br_if $label$5 + (i32.eqz + (i32.and + (call $runtime.growHeap) + (i32.const 1) + ) + ) + ) + ) + (if + (i32.eq + (i32.load + (i32.const 65896) + ) + (local.get $3) + ) + (block + (local.set $3 + (i32.const 0) + ) + (br $label$4) + ) + ) + (if + (i32.and + (call $\28runtime.gcBlock\29.state + (local.get $3) + ) + (i32.const 255) + ) + (block + (local.set $3 + (i32.add + (local.get $3) + (i32.const 1) + ) + ) + (br $label$4) + ) + ) + (local.set $2 + (i32.add + (local.get $3) + (i32.const 1) + ) + ) + (if + (i32.ne + (local.get $5) + (local.tee $6 + (i32.add + (local.get $6) + (i32.const 1) + ) + ) + ) + (block + (local.set $3 + (local.get $2) + ) + (br $label$3) + ) + ) + (i32.store + (i32.const 65892) + (local.get $2) + ) + (call $\28runtime.gcBlock\29.setState + (local.tee $2 + (i32.sub + (local.get $2) + (local.get $5) + ) + ) + (i32.const 1) + ) + (local.set $1 + (i32.add + (i32.sub + (local.get $3) + (local.get $5) + ) + (i32.const 2) + ) + ) + (loop $label$25 + (if + (i32.eqz + (i32.eq + (local.get $1) + (i32.load + (i32.const 65892) + ) + ) + ) + (block + (call $\28runtime.gcBlock\29.setState + (local.get $1) + (i32.const 2) + ) + (local.set $1 + (i32.add + (local.get $1) + (i32.const 1) + ) + ) + (br $label$25) + ) + ) + ) + (memory.fill + (local.tee $1 + (i32.add + (i32.shl + (local.get $2) + (i32.const 4) + ) + (i32.const 66336) + ) + ) + (i32.const 0) + (local.get $0) + ) + (return + (local.get $1) + ) + ) + (call $runtime.runtimePanic + (i32.const 65600) + (i32.const 13) + ) + (unreachable) + ) + (local.set $6 + (i32.const 0) + ) + ) + (local.set $4 + (i32.load + (i32.const 65892) + ) + ) + (local.set $2 + (local.get $1) + ) + (br $label$2) + ) + ) + (func $runtime.markRoots (param $0 i32) (param $1 i32) + (local $2 i32) + (loop $label$1 + (if + (i32.eqz + (i32.ge_u + (local.get $0) + (local.get $1) + ) + ) + (block + (block $label$3 + (br_if $label$3 + (i32.lt_u + (local.tee $2 + (i32.load + (local.get $0) + ) + ) + (i32.const 66336) + ) + ) + (br_if $label$3 + (i32.ge_u + (local.get $2) + (i32.load + (i32.const 65888) + ) + ) + ) + (br_if $label$3 + (i32.eqz + (i32.and + (call $\28runtime.gcBlock\29.state + (local.tee $2 + (i32.shr_u + (i32.sub + (local.get $2) + (i32.const 66336) + ) + (i32.const 4) + ) + ) + ) + (i32.const 255) + ) + ) + ) + (br_if $label$3 + (i32.eq + (i32.and + (call $\28runtime.gcBlock\29.state + (local.tee $2 + (call $\28runtime.gcBlock\29.findHead + (local.get $2) + ) + ) + ) + (i32.const 255) + ) + (i32.const 3) + ) + ) + (call $runtime.startMark + (local.get $2) + ) + ) + (local.set $0 + (i32.add + (local.get $0) + (i32.const 4) + ) + ) + (br $label$1) + ) + ) + ) + ) + (func $\28runtime.gcBlock\29.state (param $0 i32) (result i32) + (i32.and + (i32.shr_u + (i32.load8_u + (i32.add + (i32.load + (i32.const 65888) + ) + (i32.shr_u + (local.get $0) + (i32.const 2) + ) + ) + ) + (i32.and + (i32.shl + (local.get $0) + (i32.const 1) + ) + (i32.const 6) + ) + ) + (i32.const 3) + ) + ) + (func $\28runtime.gcBlock\29.markFree (param $0 i32) + (local $1 i32) + (i32.store8 + (local.tee $1 + (i32.add + (i32.load + (i32.const 65888) + ) + (i32.shr_u + (local.get $0) + (i32.const 2) + ) + ) + ) + (i32.and + (i32.load8_u + (local.get $1) + ) + (i32.xor + (i32.shl + (i32.const 3) + (i32.and + (i32.shl + (local.get $0) + (i32.const 1) + ) + (i32.const 6) + ) + ) + (i32.const -1) + ) + ) + ) + ) + (func $runtime.growHeap (result i32) + (local $0 i32) + (local $1 i32) + (local $2 i32) + (if + (local.tee $1 + (i32.ne + (memory.grow + (memory.size) + ) + (i32.const -1) + ) + ) + (block + (local.set $0 + (memory.size) + ) + (local.set $2 + (i32.load + (i32.const 65760) + ) + ) + (i32.store + (i32.const 65760) + (i32.shl + (local.get $0) + (i32.const 16) + ) + ) + (local.set $0 + (i32.load + (i32.const 65888) + ) + ) + (call $runtime.calculateHeapAddresses) + (memory.copy + (i32.load + (i32.const 65888) + ) + (local.get $0) + (i32.sub + (local.get $2) + (local.get $0) + ) + ) + ) + ) + (local.get $1) + ) + (func $runtime.startMark (param $0 i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (global.set $__stack_pointer + (local.tee $3 + (i32.add + (global.get $__stack_pointer) + (i32.const -64) + ) + ) + ) + (memory.fill + (i32.add + (local.get $3) + (i32.const 4) + ) + (i32.const 0) + (i32.const 60) + ) + (i32.store + (local.get $3) + (local.get $0) + ) + (call $\28runtime.gcBlock\29.setState + (local.get $0) + (i32.const 3) + ) + (local.set $2 + (i32.const 1) + ) + (block $label$1 + (loop $label$2 + (if + (i32.gt_s + (local.get $2) + (i32.const 0) + ) + (block + (br_if $label$1 + (i32.gt_u + (local.tee $2 + (i32.sub + (local.get $2) + (i32.const 1) + ) + ) + (i32.const 15) + ) + ) + (local.set $0 + (i32.shl + (local.tee $1 + (i32.load + (i32.add + (local.get $3) + (i32.shl + (local.get $2) + (i32.const 2) + ) + ) + ) + ) + (i32.const 4) + ) + ) + (block $label$4 + (block $label$5 + (br_table $label$5 $label$4 $label$5 $label$4 + (i32.sub + (i32.and + (call $\28runtime.gcBlock\29.state + (local.get $1) + ) + (i32.const 255) + ) + (i32.const 1) + ) + ) + ) + (local.set $1 + (i32.add + (local.get $1) + (i32.const 1) + ) + ) + ) + (local.set $5 + (i32.add + (local.get $0) + (i32.const 66336) + ) + ) + (local.set $6 + (i32.sub + (local.tee $4 + (i32.shl + (local.get $1) + (i32.const 4) + ) + ) + (local.get $0) + ) + ) + (local.set $4 + (i32.add + (local.get $4) + (i32.const 66336) + ) + ) + (local.set $7 + (i32.load + (i32.const 65888) + ) + ) + (loop $label$6 + (block $label$7 + (local.set $0 + (local.get $6) + ) + (br_if $label$7 + (i32.ge_u + (local.get $4) + (local.get $7) + ) + ) + (local.set $6 + (i32.add + (local.get $0) + (i32.const 16) + ) + ) + (local.set $4 + (i32.add + (local.get $4) + (i32.const 16) + ) + ) + (local.set $8 + (call $\28runtime.gcBlock\29.state + (local.get $1) + ) + ) + (local.set $1 + (i32.add + (local.get $1) + (i32.const 1) + ) + ) + (br_if $label$6 + (i32.eq + (i32.and + (local.get $8) + (i32.const 255) + ) + (i32.const 2) + ) + ) + ) + ) + (loop $label$8 + (br_if $label$2 + (i32.eqz + (local.get $0) + ) + ) + (block $label$9 + (br_if $label$9 + (i32.lt_u + (local.tee $1 + (i32.load + (local.get $5) + ) + ) + (i32.const 66336) + ) + ) + (br_if $label$9 + (i32.ge_u + (local.get $1) + (i32.load + (i32.const 65888) + ) + ) + ) + (br_if $label$9 + (i32.eqz + (i32.and + (call $\28runtime.gcBlock\29.state + (local.tee $1 + (i32.shr_u + (i32.sub + (local.get $1) + (i32.const 66336) + ) + (i32.const 4) + ) + ) + ) + (i32.const 255) + ) + ) + ) + (br_if $label$9 + (i32.eq + (i32.and + (call $\28runtime.gcBlock\29.state + (local.tee $1 + (call $\28runtime.gcBlock\29.findHead + (local.get $1) + ) + ) + ) + (i32.const 255) + ) + (i32.const 3) + ) + ) + (call $\28runtime.gcBlock\29.setState + (local.get $1) + (i32.const 3) + ) + (if + (i32.eq + (local.get $2) + (i32.const 16) + ) + (block + (i32.store8 + (i32.const 65929) + (i32.const 1) + ) + (local.set $2 + (i32.const 16) + ) + (br $label$9) + ) + ) + (br_if $label$1 + (i32.gt_u + (local.get $2) + (i32.const 15) + ) + ) + (i32.store + (i32.add + (local.get $3) + (i32.shl + (local.get $2) + (i32.const 2) + ) + ) + (local.get $1) + ) + (local.set $2 + (i32.add + (local.get $2) + (i32.const 1) + ) + ) + ) + (local.set $0 + (i32.sub + (local.get $0) + (i32.const 4) + ) + ) + (local.set $5 + (i32.add + (local.get $5) + (i32.const 4) + ) + ) + (br $label$8) + ) + ) + ) + ) + (global.set $__stack_pointer + (i32.sub + (local.get $3) + (i32.const -64) + ) + ) + (return) + ) + (call $runtime.lookupPanic) + (unreachable) + ) + (func $\28runtime.gcBlock\29.setState (param $0 i32) (param $1 i32) + (local $2 i32) + (i32.store8 + (local.tee $2 + (i32.add + (i32.load + (i32.const 65888) + ) + (i32.shr_u + (local.get $0) + (i32.const 2) + ) + ) + ) + (i32.or + (i32.load8_u + (local.get $2) + ) + (i32.shl + (local.get $1) + (i32.and + (i32.shl + (local.get $0) + (i32.const 1) + ) + (i32.const 6) + ) + ) + ) + ) + ) + (func $runtime.nilPanic + (call $runtime.runtimePanic + (i32.const 65642) + (i32.const 23) + ) + (unreachable) + ) + (func $runtime.calculateHeapAddresses + (local $0 i32) + (i32.store + (i32.const 65888) + (local.tee $0 + (i32.sub + (local.tee $0 + (i32.load + (i32.const 65760) + ) + ) + (i32.div_u + (i32.sub + (local.get $0) + (i32.const 66272) + ) + (i32.const 65) + ) + ) + ) + ) + (i32.store + (i32.const 65896) + (i32.shr_u + (i32.sub + (local.get $0) + (i32.const 66336) + ) + (i32.const 4) + ) + ) + ) + (func $\28runtime.gcBlock\29.findHead (param $0 i32) (result i32) + (local $1 i32) + (local $2 i32) + (loop $label$1 + (local.set $1 + (call $\28runtime.gcBlock\29.state + (local.get $0) + ) + ) + (local.set $0 + (local.tee $2 + (i32.sub + (local.get $0) + (i32.const 1) + ) + ) + ) + (br_if $label$1 + (i32.eq + (i32.and + (local.get $1) + (i32.const 255) + ) + (i32.const 2) + ) + ) + ) + (i32.add + (local.get $2) + (i32.const 1) + ) + ) + (func $malloc (param $0 i32) (result i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (global.set $__stack_pointer + (local.tee $1 + (i32.sub + (global.get $__stack_pointer) + (i32.const 32) + ) + ) + ) + (i32.store offset=20 + (local.get $1) + (i32.const 2) + ) + (local.set $3 + (i32.load + (i32.const 65932) + ) + ) + (i32.store + (i32.const 65932) + (i32.add + (local.get $1) + (i32.const 16) + ) + ) + (i32.store offset=16 + (local.get $1) + (local.get $3) + ) + (block $label$1 + (if + (local.get $0) + (block + (br_if $label$1 + (i32.lt_s + (local.get $0) + (i32.const 0) + ) + ) + (i32.store offset=24 + (local.get $1) + (local.tee $2 + (call $runtime.alloc + (local.get $0) + ) + ) + ) + (i32.store offset=28 + (local.get $1) + (local.get $2) + ) + (i32.store offset=8 + (local.get $1) + (local.get $0) + ) + (i32.store offset=4 + (local.get $1) + (local.get $0) + ) + (i32.store + (local.get $1) + (local.get $2) + ) + (i32.store offset=12 + (local.get $1) + (local.get $2) + ) + (call $runtime.hashmapBinarySet + (i32.add + (local.get $1) + (i32.const 12) + ) + (local.get $1) + ) + ) + ) + (i32.store + (i32.const 65932) + (local.get $3) + ) + (global.set $__stack_pointer + (i32.add + (local.get $1) + (i32.const 32) + ) + ) + (return + (local.get $2) + ) + ) + (call $runtime.slicePanic) + (unreachable) + ) + (func $runtime.hashmapBinarySet (param $0 i32) (param $1 i32) + (call $runtime.hashmapSet + (i32.const 65716) + (local.get $0) + (local.get $1) + (call $runtime.hash32 + (local.get $0) + (i32.load + (i32.const 65728) + ) + (i32.load + (i32.const 65720) + ) + (local.get $0) + ) + ) + ) + (func $free (param $0 i32) + (local $1 i32) + (global.set $__stack_pointer + (local.tee $1 + (i32.sub + (global.get $__stack_pointer) + (i32.const 16) + ) + ) + ) + (block $label$1 + (if + (local.get $0) + (block + (i32.store offset=12 + (local.get $1) + (local.get $0) + ) + (br_if $label$1 + (i32.eqz + (i32.and + (call $runtime.hashmapBinaryGet + (i32.add + (local.get $1) + (i32.const 12) + ) + (local.get $1) + ) + (i32.const 1) + ) + ) + ) + (i32.store + (local.get $1) + (local.get $0) + ) + (call $runtime.hashmapBinaryDelete + (local.get $1) + ) + ) + ) + (global.set $__stack_pointer + (i32.add + (local.get $1) + (i32.const 16) + ) + ) + (return) + ) + (call $runtime._panic + (i32.const 65560) + ) + (unreachable) + ) + (func $runtime.hashmapBinaryGet (param $0 i32) (param $1 i32) (result i32) + (call $runtime.hashmapGet + (i32.const 65716) + (local.get $0) + (local.get $1) + (call $runtime.hash32 + (local.get $0) + (i32.load + (i32.const 65728) + ) + (i32.load + (i32.const 65720) + ) + (local.get $0) + ) + ) + ) + (func $runtime.hashmapBinaryDelete (param $0 i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (global.set $__stack_pointer + (local.tee $1 + (i32.sub + (global.get $__stack_pointer) + (i32.const 32) + ) + ) + ) + (i64.store + (i32.add + (local.get $1) + (i32.const 24) + ) + (i64.const 0) + ) + (i64.store offset=16 + (local.get $1) + (i64.const 0) + ) + (i32.store offset=4 + (local.get $1) + (i32.const 6) + ) + (local.set $6 + (i32.load + (i32.const 65932) + ) + ) + (i32.store + (i32.const 65932) + (local.get $1) + ) + (i32.store + (local.get $1) + (local.get $6) + ) + (local.set $3 + (call $runtime.hash32 + (local.get $0) + (local.tee $2 + (i32.load + (i32.const 65728) + ) + ) + (i32.load + (i32.const 65720) + ) + (i32.const 0) + ) + ) + (i32.store offset=8 + (local.get $1) + (local.tee $4 + (i32.load + (i32.const 65716) + ) + ) + ) + (local.set $7 + (select + (local.tee $5 + (i32.shr_u + (local.get $3) + (i32.const 24) + ) + ) + (i32.const 1) + (local.get $5) + ) + ) + (local.set $2 + (i32.add + (local.get $4) + (i32.mul + (i32.add + (i32.shl + (i32.add + (local.get $2) + (i32.load + (i32.const 65732) + ) + ) + (i32.const 3) + ) + (i32.const 12) + ) + (i32.and + (local.get $3) + (select + (i32.const -1) + (i32.xor + (i32.shl + (i32.const -1) + (local.tee $2 + (i32.load8_u + (i32.const 65736) + ) + ) + ) + (i32.const -1) + ) + (i32.gt_u + (local.get $2) + (i32.const 31) + ) + ) + ) + ) + ) + ) + (block $label$1 + (loop $label$2 + (i32.store offset=12 + (local.get $1) + (local.get $2) + ) + (i32.store offset=16 + (local.get $1) + (local.get $2) + ) + (br_if $label$1 + (i32.eqz + (local.get $2) + ) + ) + (local.set $3 + (i32.const 0) + ) + (block $label$3 + (loop $label$4 + (if + (i32.ne + (local.get $3) + (i32.const 8) + ) + (block + (block $label$6 + (br_if $label$6 + (i32.ne + (i32.load8_u + (local.tee $8 + (i32.add + (local.get $2) + (local.get $3) + ) + ) + ) + (local.get $7) + ) + ) + (local.set $5 + (i32.load + (i32.const 65728) + ) + ) + (i32.store offset=20 + (local.get $1) + (local.tee $9 + (i32.load + (i32.const 65740) + ) + ) + ) + (i32.store offset=24 + (local.get $1) + (local.tee $4 + (i32.load + (i32.const 65744) + ) + ) + ) + (br_if $label$3 + (i32.eqz + (local.get $4) + ) + ) + (br_if $label$6 + (i32.eqz + (i32.and + (call_indirect (type $i32_i32_i32_i32_=>_i32) + (local.get $0) + (i32.add + (i32.add + (i32.mul + (local.get $3) + (local.get $5) + ) + (local.get $2) + ) + (i32.const 12) + ) + (local.get $5) + (local.get $9) + (local.get $4) + ) + (i32.const 1) + ) + ) + ) + (i32.store8 + (local.get $8) + (i32.const 0) + ) + (i32.store + (i32.const 65724) + (i32.sub + (i32.load + (i32.const 65724) + ) + (i32.const 1) + ) + ) + (br $label$1) + ) + (local.set $3 + (i32.add + (local.get $3) + (i32.const 1) + ) + ) + (br $label$4) + ) + ) + ) + (i32.store offset=28 + (local.get $1) + (local.tee $2 + (i32.load offset=8 + (local.get $2) + ) + ) + ) + (br $label$2) + ) + ) + (call $runtime.nilPanic) + (unreachable) + ) + (i32.store + (i32.const 65932) + (local.get $6) + ) + (global.set $__stack_pointer + (i32.add + (local.get $1) + (i32.const 32) + ) + ) + ) + (func $runtime._panic (param $0 i32) + (call $runtime.printstring + (i32.const 65613) + (i32.const 7) + ) + (call $runtime.printitf + (local.get $0) + ) + (call $runtime.printnl) + (unreachable) + ) + (func $calloc (param $0 i32) (param $1 i32) (result i32) + (local $2 i32) + (local $3 i32) + (global.set $__stack_pointer + (local.tee $2 + (i32.sub + (global.get $__stack_pointer) + (i32.const 16) + ) + ) + ) + (local.set $3 + (i32.load + (i32.const 65932) + ) + ) + (i32.store + (i32.const 65932) + (local.get $2) + ) + (local.set $0 + (call $malloc + (i32.mul + (local.get $0) + (local.get $1) + ) + ) + ) + (i32.store + (i32.const 65932) + (local.get $3) + ) + (global.set $__stack_pointer + (i32.add + (local.get $2) + (i32.const 16) + ) + ) + (local.get $0) + ) + (func $realloc (param $0 i32) (param $1 i32) (result i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (global.set $__stack_pointer + (local.tee $2 + (i32.sub + (global.get $__stack_pointer) + (i32.const 32) + ) + ) + ) + (i32.store offset=20 + (local.get $2) + (i32.const 2) + ) + (local.set $4 + (i32.load + (i32.const 65932) + ) + ) + (i32.store + (i32.const 65932) + (i32.add + (local.get $2) + (i32.const 16) + ) + ) + (i32.store offset=16 + (local.get $2) + (local.get $4) + ) + (block $label$1 + (block $label$2 + (block $label$3 + (if + (i32.eqz + (local.get $1) + ) + (block + (call $free + (local.get $0) + ) + (br $label$3) + ) + ) + (br_if $label$2 + (i32.lt_s + (local.get $1) + (i32.const 0) + ) + ) + (i32.store offset=24 + (local.get $2) + (local.tee $3 + (call $runtime.alloc + (local.get $1) + ) + ) + ) + (i32.store offset=28 + (local.get $2) + (local.get $3) + ) + (if + (local.get $0) + (block + (i32.store offset=12 + (local.get $2) + (local.get $0) + ) + (br_if $label$1 + (i32.eqz + (i32.and + (call $runtime.hashmapBinaryGet + (i32.add + (local.get $2) + (i32.const 12) + ) + (local.get $2) + ) + (i32.const 1) + ) + ) + ) + (memory.copy + (local.get $3) + (i32.load + (local.get $2) + ) + (select + (local.tee $5 + (i32.load offset=4 + (local.get $2) + ) + ) + (local.get $1) + (i32.gt_u + (local.get $1) + (local.get $5) + ) + ) + ) + (i32.store + (local.get $2) + (local.get $0) + ) + (call $runtime.hashmapBinaryDelete + (local.get $2) + ) + ) + ) + (i32.store offset=8 + (local.get $2) + (local.get $1) + ) + (i32.store offset=4 + (local.get $2) + (local.get $1) + ) + (i32.store + (local.get $2) + (local.get $3) + ) + (i32.store offset=12 + (local.get $2) + (local.get $3) + ) + (call $runtime.hashmapBinarySet + (i32.add + (local.get $2) + (i32.const 12) + ) + (local.get $2) + ) + ) + (i32.store + (i32.const 65932) + (local.get $4) + ) + (global.set $__stack_pointer + (i32.add + (local.get $2) + (i32.const 32) + ) + ) + (return + (local.get $3) + ) + ) + (call $runtime.slicePanic) + (unreachable) + ) + (call $runtime._panic + (i32.const 65592) + ) + (unreachable) + ) + (func $_start + (local $0 i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (global.set $__stack_pointer + (local.tee $0 + (i32.sub + (global.get $__stack_pointer) + (i32.const 96) + ) + ) + ) + (i32.store offset=36 + (local.get $0) + (i32.const 13) + ) + (memory.fill + (i32.add + (local.get $0) + (i32.const 40) + ) + (i32.const 0) + (i32.const 52) + ) + (i32.store offset=32 + (local.get $0) + (local.tee $7 + (i32.load + (i32.const 65932) + ) + ) + ) + (i32.store + (i32.const 65932) + (i32.add + (local.get $0) + (i32.const 32) + ) + ) + (i32.store + (i32.const 65760) + (local.tee $5 + (i32.shl + (memory.size) + (i32.const 16) + ) + ) + ) + (call $runtime.calculateHeapAddresses) + (i32.store offset=44 + (local.get $0) + (local.tee $1 + (i32.load + (i32.const 65888) + ) + ) + ) + (i32.store offset=40 + (local.get $0) + (local.get $1) + ) + (memory.fill + (local.get $1) + (i32.const 0) + (i32.sub + (local.get $5) + (local.get $1) + ) + ) + (i32.store + (i32.const 65760) + (i32.shl + (memory.size) + (i32.const 16) + ) + ) + (call $__wasm_call_ctors) + (i32.store offset=48 + (local.get $0) + (local.tee $4 + (i32.load + (i32.const 65944) + ) + ) + ) + (block $label$1 + (block $label$2 + (block $label$3 + (local.set $3 + (block $label$4 (result i32) + (if + (local.get $4) + (block + (local.set $2 + (i32.load + (i32.const 65960) + ) + ) + (br $label$4 + (i32.load + (i32.const 65952) + ) + ) + ) + ) + (i32.store offset=16 + (local.get $0) + (i32.const 0) + ) + (i32.store offset=24 + (local.get $0) + (i32.const 0) + ) + (drop + (call $runtime.args_sizes_get + (i32.add + (local.get $0) + (i32.const 24) + ) + (i32.add + (local.get $0) + (i32.const 16) + ) + ) + ) + (if + (i32.eqz + (local.tee $2 + (i32.load offset=24 + (local.get $0) + ) + ) + ) + (block + (local.set $4 + (i32.const 0) + ) + (local.set $2 + (i32.const 0) + ) + (br $label$3) + ) + ) + (br_if $label$1 + (i32.gt_u + (local.get $2) + (i32.const 1073741823) + ) + ) + (i32.store offset=52 + (local.get $0) + (local.tee $5 + (call $runtime.alloc + (i32.shl + (local.get $2) + (i32.const 2) + ) + ) + ) + ) + (br_if $label$1 + (i32.lt_s + (local.tee $1 + (i32.load offset=16 + (local.get $0) + ) + ) + (i32.const 0) + ) + ) + (i32.store offset=56 + (local.get $0) + (local.tee $3 + (call $runtime.alloc + (local.get $1) + ) + ) + ) + (i32.store offset=60 + (local.get $0) + (local.get $3) + ) + (br_if $label$2 + (i32.eqz + (local.get $1) + ) + ) + (drop + (call $runtime.args_get + (local.get $5) + (local.get $3) + ) + ) + (br_if $label$1 + (i32.gt_u + (local.get $2) + (i32.const 536870911) + ) + ) + (i32.store + (i32.const 65944) + (local.tee $4 + (call $runtime.alloc + (i32.shl + (local.get $2) + (i32.const 3) + ) + ) + ) + ) + (i32.store + (i32.const 65952) + (local.get $2) + ) + (i32.store + (i32.const 65960) + (local.get $2) + ) + (i32.store offset=64 + (local.get $0) + (local.get $4) + ) + (local.set $3 + (local.get $4) + ) + (local.set $6 + (local.get $2) + ) + (loop $label$7 + (if + (local.get $6) + (block + (i32.store offset=80 + (local.get $0) + (local.tee $1 + (i32.load + (local.get $5) + ) + ) + ) + (i32.store offset=72 + (local.get $0) + (local.get $1) + ) + (i32.store offset=68 + (local.get $0) + (local.get $1) + ) + (i32.store + (i32.add + (local.get $3) + (i32.const 4) + ) + (local.tee $8 + (call $strlen + (local.get $1) + ) + ) + ) + (i32.store + (local.get $3) + (local.get $1) + ) + (i32.store offset=76 + (local.get $0) + (local.get $4) + ) + (local.set $5 + (i32.add + (local.get $5) + (i32.const 4) + ) + ) + (local.set $3 + (i32.add + (local.get $3) + (i32.const 8) + ) + ) + (local.set $6 + (i32.sub + (local.get $6) + (i32.const 1) + ) + ) + (br $label$7) + ) + ) + ) + (i32.store offset=8 + (local.get $0) + (local.get $1) + ) + (i32.store offset=12 + (local.get $0) + (local.get $8) + ) + (local.get $2) + ) + ) + (i32.store offset=84 + (local.get $0) + (local.get $4) + ) + ) + (i32.store + (i32.const 66312) + (local.get $4) + ) + (i32.store + (i32.const 66316) + (local.get $3) + ) + (i32.store + (i32.const 66320) + (local.get $2) + ) + (i32.store offset=88 + (local.get $0) + (local.get $4) + ) + (i64.store offset=8 + (local.get $0) + (i64.const 0) + ) + (drop + (call $runtime.clock_time_get + (i32.const 0) + (i64.const 1000) + (i32.add + (local.get $0) + (i32.const 8) + ) + ) + ) + (i32.store + (select + (i32.add + (local.get $0) + (i32.const 24) + ) + (i32.add + (local.get $0) + (i32.const 16) + ) + (i64.lt_u + (i64.add + (i64.div_s + (i64.load offset=8 + (local.get $0) + ) + (i64.const 1000000000) + ) + (i64.const 2682288000) + ) + (i64.const 8589934592) + ) + ) + (i32.const 66248) + ) + (call $runtime.proc_exit + (call $github.com/wetware/ww/guest/tinygo.test + (i32.const 40) + (i32.const 2) + ) + ) + (i32.store + (i32.const 65932) + (local.get $7) + ) + (global.set $__stack_pointer + (i32.add + (local.get $0) + (i32.const 96) + ) + ) + (return) + ) + (call $runtime.lookupPanic) + (unreachable) + ) + (call $runtime.slicePanic) + (unreachable) + ) + (func $runtime.hashmapGet (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (result i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (local $10 i32) + (local $11 i32) + (global.set $__stack_pointer + (local.tee $4 + (i32.sub + (global.get $__stack_pointer) + (i32.const 48) + ) + ) + ) + (i32.store + (i32.add + (local.get $4) + (i32.const 40) + ) + (i32.const 0) + ) + (i64.store offset=32 + (local.get $4) + (i64.const 0) + ) + (i32.store offset=12 + (local.get $4) + (i32.const 7) + ) + (local.set $7 + (i32.load + (i32.const 65932) + ) + ) + (i32.store + (i32.const 65932) + (i32.add + (local.get $4) + (i32.const 8) + ) + ) + (i32.store offset=8 + (local.get $4) + (local.get $7) + ) + (i32.store offset=16 + (local.get $4) + (local.tee $5 + (i32.load + (local.get $0) + ) + ) + ) + (local.set $5 + (i32.add + (local.get $5) + (i32.mul + (i32.add + (i32.shl + (i32.add + (i32.load offset=16 + (local.get $0) + ) + (i32.load offset=12 + (local.get $0) + ) + ) + (i32.const 3) + ) + (i32.const 12) + ) + (i32.and + (select + (i32.const -1) + (i32.xor + (i32.shl + (i32.const -1) + (local.tee $6 + (i32.load8_u offset=20 + (local.get $0) + ) + ) + ) + (i32.const -1) + ) + (i32.gt_u + (local.get $6) + (i32.const 31) + ) + ) + (local.get $3) + ) + ) + ) + ) + (local.set $9 + (select + (local.tee $3 + (i32.shr_u + (local.get $3) + (i32.const 24) + ) + ) + (i32.const 1) + (local.get $3) + ) + ) + (block $label$1 + (block $label$2 + (loop $label$3 + (block $label$4 + (i32.store offset=24 + (local.get $4) + (local.get $5) + ) + (i32.store offset=28 + (local.get $4) + (local.get $5) + ) + (i32.store offset=20 + (local.get $4) + (local.get $5) + ) + (br_if $label$4 + (i32.eqz + (local.get $5) + ) + ) + (local.set $3 + (i32.const 0) + ) + (loop $label$5 + (if + (i32.ne + (local.get $3) + (i32.const 8) + ) + (block + (block $label$7 + (br_if $label$7 + (i32.ne + (i32.load8_u + (i32.add + (local.get $3) + (local.get $5) + ) + ) + (local.get $9) + ) + ) + (local.set $6 + (i32.load offset=12 + (local.get $0) + ) + ) + (local.set $10 + (i32.load offset=16 + (local.get $0) + ) + ) + (i32.store offset=32 + (local.get $4) + (local.tee $11 + (i32.load offset=24 + (local.get $0) + ) + ) + ) + (i32.store offset=36 + (local.get $4) + (local.tee $8 + (i32.load offset=28 + (local.get $0) + ) + ) + ) + (br_if $label$2 + (i32.eqz + (local.get $8) + ) + ) + (br_if $label$7 + (i32.eqz + (i32.and + (call_indirect (type $i32_i32_i32_i32_=>_i32) + (local.get $1) + (i32.add + (i32.add + (i32.mul + (local.get $3) + (local.get $6) + ) + (local.get $5) + ) + (i32.const 12) + ) + (local.get $6) + (local.get $11) + (local.get $8) + ) + (i32.const 1) + ) + ) + ) + (memory.copy + (local.get $2) + (i32.add + (i32.add + (i32.add + (i32.mul + (local.get $3) + (local.get $10) + ) + (i32.shl + (local.get $6) + (i32.const 3) + ) + ) + (local.get $5) + ) + (i32.const 12) + ) + (i32.load offset=16 + (local.get $0) + ) + ) + (br $label$1) + ) + (local.set $3 + (i32.add + (local.get $3) + (i32.const 1) + ) + ) + (br $label$5) + ) + ) + ) + (i32.store offset=40 + (local.get $4) + (local.tee $5 + (i32.load offset=8 + (local.get $5) + ) + ) + ) + (br $label$3) + ) + ) + (memory.fill + (local.get $2) + (i32.const 0) + (i32.load offset=16 + (local.get $0) + ) + ) + (br $label$1) + ) + (call $runtime.nilPanic) + (unreachable) + ) + (i32.store + (i32.const 65932) + (local.get $7) + ) + (global.set $__stack_pointer + (i32.add + (local.get $4) + (i32.const 48) + ) + ) + (i32.ne + (local.get $5) + (i32.const 0) + ) + ) + (func $runtime.printitf (param $0 i32) + (call $runtime.printstring + (i32.load + (local.get $0) + ) + (i32.load offset=4 + (local.get $0) + ) + ) + ) + (func $runtime.hashmapSet (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (local $10 i32) + (local $11 i32) + (local $12 i32) + (local $13 i32) + (local $14 i32) + (local $15 i32) + (global.set $__stack_pointer + (local.tee $4 + (i32.sub + (global.get $__stack_pointer) + (i32.const 256) + ) + ) + ) + (i32.store offset=52 + (local.get $4) + (i32.const 50) + ) + (memory.fill + (i32.add + (local.get $4) + (i32.const 56) + ) + (i32.const 0) + (i32.const 200) + ) + (i32.store offset=48 + (local.get $4) + (local.tee $14 + (i32.load + (i32.const 65932) + ) + ) + ) + (i32.store + (i32.const 65932) + (i32.add + (local.get $4) + (i32.const 48) + ) + ) + (block $label$1 + (block $label$2 + (br_if $label$2 + (i32.eqz + (local.get $0) + ) + ) + (block $label$3 + (br_if $label$3 + (i32.gt_u + (local.tee $5 + (i32.load8_u offset=20 + (local.get $0) + ) + ) + (i32.const 29) + ) + ) + (br_if $label$3 + (i32.le_u + (i32.load offset=8 + (local.get $0) + ) + (i32.shl + (i32.const 6) + (local.get $5) + ) + ) + ) + (i64.store offset=24 + (local.get $4) + (i64.const 0) + ) + (i32.store offset=72 + (local.get $4) + (local.tee $3 + (i32.load offset=36 + (local.get $0) + ) + ) + ) + (i32.store offset=68 + (local.get $4) + (local.tee $7 + (i32.load offset=32 + (local.get $0) + ) + ) + ) + (i32.store offset=64 + (local.get $4) + (local.tee $6 + (i32.load offset=28 + (local.get $0) + ) + ) + ) + (i32.store offset=60 + (local.get $4) + (local.tee $8 + (i32.load offset=24 + (local.get $0) + ) + ) + ) + (i32.store offset=56 + (local.get $4) + (i32.load + (local.get $0) + ) + ) + (i32.store offset=44 + (local.get $4) + (local.get $3) + ) + (i32.store offset=40 + (local.get $4) + (local.get $7) + ) + (i32.store offset=36 + (local.get $4) + (local.get $6) + ) + (i32.store offset=32 + (local.get $4) + (local.get $8) + ) + (i32.store offset=24 + (local.get $4) + (i32.load offset=16 + (local.get $0) + ) + ) + (i32.store offset=20 + (local.get $4) + (i32.load offset=12 + (local.get $0) + ) + ) + (i32.store + (i32.const 65704) + (local.tee $3 + (i32.xor + (i32.shl + (local.tee $3 + (i32.xor + (i32.shr_u + (local.tee $3 + (i32.xor + (i32.shl + (local.tee $3 + (i32.load + (i32.const 65704) + ) + ) + (i32.const 7) + ) + (local.get $3) + ) + ) + (i32.const 1) + ) + (local.get $3) + ) + ) + (i32.const 9) + ) + (local.get $3) + ) + ) + ) + (i32.store offset=16 + (local.get $4) + (i32.const 0) + ) + (i32.store offset=12 + (local.get $4) + (local.get $3) + ) + (i32.store8 offset=28 + (local.get $4) + (local.tee $3 + (i32.add + (local.get $5) + (i32.const 1) + ) + ) + ) + (i32.store offset=8 + (local.get $4) + (local.tee $3 + (call $runtime.alloc + (i32.shl + (i32.add + (i32.shl + (i32.add + (i32.load offset=16 + (local.get $0) + ) + (i32.load offset=12 + (local.get $0) + ) + ) + (i32.const 3) + ) + (i32.const 12) + ) + (local.get $3) + ) + ) + ) + ) + (i32.store offset=76 + (local.get $4) + (local.get $3) + ) + (i32.store offset=80 + (local.get $4) + (local.tee $7 + (call $runtime.alloc + (i32.load offset=12 + (local.get $0) + ) + ) + ) + ) + (i32.store offset=84 + (local.get $4) + (local.tee $13 + (call $runtime.alloc + (i32.load offset=16 + (local.get $0) + ) + ) + ) + ) + (local.set $3 + (i32.const 0) + ) + (local.set $5 + (i32.const 0) + ) + (loop $label$4 + (i32.store offset=88 + (local.get $4) + (local.get $10) + ) + (if + (i32.eqz + (local.get $10) + ) + (block + (i32.store offset=92 + (local.get $4) + (local.tee $10 + (i32.load + (local.get $0) + ) + ) + ) + (local.set $12 + (select + (i32.shl + (i32.const 1) + (local.tee $6 + (i32.load8_u offset=20 + (local.get $0) + ) + ) + ) + (i32.const 0) + (i32.le_u + (local.get $6) + (i32.const 31) + ) + ) + ) + ) + ) + (i32.store offset=108 + (local.get $4) + (local.get $10) + ) + (i32.store offset=124 + (local.get $4) + (local.get $10) + ) + (block $label$6 + (loop $label$7 + (i32.store offset=96 + (local.get $4) + (local.get $3) + ) + (if + (i32.ge_u + (i32.and + (local.get $5) + (i32.const 255) + ) + (i32.const 8) + ) + (block + (br_if $label$2 + (i32.eqz + (local.get $3) + ) + ) + (i32.store offset=100 + (local.get $4) + (local.tee $3 + (i32.load offset=8 + (local.get $3) + ) + ) + ) + (local.set $5 + (i32.const 0) + ) + ) + ) + (i32.store offset=104 + (local.get $4) + (local.get $3) + ) + (if + (i32.eqz + (local.get $3) + ) + (block + (br_if $label$6 + (i32.ge_u + (local.get $9) + (local.get $12) + ) + ) + (local.set $3 + (i32.add + (local.get $10) + (i32.mul + (i32.add + (i32.shl + (i32.add + (i32.load offset=16 + (local.get $0) + ) + (i32.load offset=12 + (local.get $0) + ) + ) + (i32.const 3) + ) + (i32.const 12) + ) + (local.get $9) + ) + ) + ) + (local.set $9 + (i32.add + (local.get $9) + (i32.const 1) + ) + ) + ) + ) + (i32.store offset=116 + (local.get $4) + (local.get $3) + ) + (i32.store offset=120 + (local.get $4) + (local.get $3) + ) + (i32.store offset=112 + (local.get $4) + (local.get $3) + ) + (br_if $label$2 + (i32.eqz + (local.get $3) + ) + ) + (if + (i32.eqz + (i32.load8_u + (i32.add + (local.get $3) + (local.tee $8 + (i32.and + (local.get $5) + (i32.const 255) + ) + ) + ) + ) + ) + (block + (local.set $5 + (i32.add + (local.get $5) + (i32.const 1) + ) + ) + (br $label$7) + ) + ) + (memory.copy + (local.get $7) + (i32.add + (i32.add + (i32.mul + (local.tee $6 + (i32.load offset=12 + (local.get $0) + ) + ) + (local.get $8) + ) + (local.get $3) + ) + (i32.const 12) + ) + (local.get $6) + ) + (i32.store offset=128 + (local.get $4) + (local.tee $11 + (i32.load + (local.get $0) + ) + ) + ) + (block $label$11 + (if + (i32.eq + (local.get $10) + (local.get $11) + ) + (block + (memory.copy + (local.get $13) + (i32.add + (i32.add + (i32.add + (i32.shl + (local.get $6) + (i32.const 3) + ) + (i32.mul + (local.tee $6 + (i32.load offset=16 + (local.get $0) + ) + ) + (local.get $8) + ) + ) + (local.get $3) + ) + (i32.const 12) + ) + (local.get $6) + ) + (local.set $5 + (i32.add + (local.get $5) + (i32.const 1) + ) + ) + (br $label$11) + ) + ) + (i32.store offset=132 + (local.get $4) + (local.tee $11 + (i32.load offset=32 + (local.get $0) + ) + ) + ) + (i32.store offset=136 + (local.get $4) + (local.tee $8 + (i32.load offset=36 + (local.get $0) + ) + ) + ) + (br_if $label$2 + (i32.eqz + (local.get $8) + ) + ) + (local.set $5 + (i32.add + (local.get $5) + (i32.const 1) + ) + ) + (br_if $label$7 + (i32.eqz + (i32.and + (call $runtime.hashmapGet + (local.get $0) + (local.get $7) + (local.get $13) + (call_indirect (type $i32_i32_i32_i32_=>_i32) + (local.get $7) + (local.get $6) + (i32.load offset=4 + (local.get $0) + ) + (local.get $11) + (local.get $8) + ) + ) + (i32.const 1) + ) + ) + ) + ) + ) + (i32.store offset=140 + (local.get $4) + (local.tee $8 + (i32.load offset=40 + (local.get $4) + ) + ) + ) + (i32.store offset=144 + (local.get $4) + (local.tee $6 + (i32.load offset=44 + (local.get $4) + ) + ) + ) + (br_if $label$2 + (i32.eqz + (local.get $6) + ) + ) + (call $runtime.hashmapSet + (i32.add + (local.get $4) + (i32.const 8) + ) + (local.get $7) + (local.get $13) + (call_indirect (type $i32_i32_i32_i32_=>_i32) + (local.get $7) + (i32.load offset=20 + (local.get $4) + ) + (i32.load offset=12 + (local.get $4) + ) + (local.get $8) + (local.get $6) + ) + ) + (br $label$4) + ) + ) + (i32.store + (local.get $0) + (local.tee $3 + (i32.load offset=8 + (local.get $4) + ) + ) + ) + (i64.store offset=4 align=4 + (local.get $0) + (i64.load offset=12 align=4 + (local.get $4) + ) + ) + (i64.store offset=12 align=4 + (local.get $0) + (i64.load offset=20 align=4 + (local.get $4) + ) + ) + (i32.store8 offset=20 + (local.get $0) + (i32.load8_u offset=28 + (local.get $4) + ) + ) + (i32.store offset=24 + (local.get $0) + (local.tee $5 + (i32.load offset=32 + (local.get $4) + ) + ) + ) + (i32.store offset=28 + (local.get $0) + (local.tee $7 + (i32.load offset=36 + (local.get $4) + ) + ) + ) + (i32.store offset=32 + (local.get $0) + (local.tee $6 + (i32.load offset=40 + (local.get $4) + ) + ) + ) + (i32.store offset=36 + (local.get $0) + (local.tee $8 + (i32.load offset=44 + (local.get $4) + ) + ) + ) + (i32.store offset=148 + (local.get $4) + (local.get $3) + ) + (i32.store offset=152 + (local.get $4) + (local.get $5) + ) + (i32.store offset=156 + (local.get $4) + (local.get $7) + ) + (i32.store offset=160 + (local.get $4) + (local.get $6) + ) + (i32.store offset=164 + (local.get $4) + (local.get $8) + ) + (i32.store offset=168 + (local.get $4) + (local.tee $5 + (i32.load offset=32 + (local.get $0) + ) + ) + ) + (i32.store offset=172 + (local.get $4) + (local.tee $3 + (i32.load offset=36 + (local.get $0) + ) + ) + ) + (br_if $label$2 + (i32.eqz + (local.get $3) + ) + ) + (local.set $3 + (call_indirect (type $i32_i32_i32_i32_=>_i32) + (local.get $1) + (i32.load offset=12 + (local.get $0) + ) + (i32.load offset=4 + (local.get $0) + ) + (local.get $5) + (local.get $3) + ) + ) + (local.set $5 + (i32.load8_u offset=20 + (local.get $0) + ) + ) + ) + (i32.store offset=176 + (local.get $4) + (local.tee $7 + (i32.load + (local.get $0) + ) + ) + ) + (local.set $9 + (i32.add + (local.get $7) + (i32.mul + (i32.add + (i32.shl + (i32.add + (i32.load offset=16 + (local.get $0) + ) + (i32.load offset=12 + (local.get $0) + ) + ) + (i32.const 3) + ) + (i32.const 12) + ) + (i32.and + (select + (i32.const -1) + (i32.xor + (i32.shl + (i32.const -1) + (local.tee $5 + (i32.and + (local.get $5) + (i32.const 255) + ) + ) + ) + (i32.const -1) + ) + (i32.gt_u + (local.get $5) + (i32.const 31) + ) + ) + (local.get $3) + ) + ) + ) + ) + (local.set $12 + (select + (local.tee $3 + (i32.shr_u + (local.get $3) + (i32.const 24) + ) + ) + (i32.const 1) + (local.get $3) + ) + ) + (local.set $3 + (i32.const 0) + ) + (local.set $5 + (i32.const 0) + ) + (local.set $8 + (i32.const 0) + ) + (local.set $6 + (i32.const 0) + ) + (loop $label$13 + (block $label$14 + (i32.store offset=212 + (local.get $4) + (local.tee $7 + (local.get $9) + ) + ) + (i32.store offset=216 + (local.get $4) + (local.get $7) + ) + (i32.store offset=196 + (local.get $4) + (local.get $7) + ) + (i32.store offset=192 + (local.get $4) + (local.get $3) + ) + (i32.store offset=188 + (local.get $4) + (local.get $5) + ) + (i32.store offset=184 + (local.get $4) + (local.get $8) + ) + (i32.store offset=180 + (local.get $4) + (local.get $6) + ) + (br_if $label$14 + (i32.eqz + (local.get $7) + ) + ) + (local.set $3 + (i32.const 0) + ) + (loop $label$15 + (block $label$16 + (i32.store offset=204 + (local.get $4) + (local.get $8) + ) + (i32.store offset=208 + (local.get $4) + (local.get $5) + ) + (i32.store offset=200 + (local.get $4) + (local.get $6) + ) + (br_if $label$16 + (i32.eq + (local.get $3) + (i32.const 8) + ) + ) + (i32.store offset=220 + (local.get $4) + (local.tee $6 + (select + (local.get $6) + (local.tee $9 + (i32.add + (local.get $3) + (local.get $7) + ) + ) + (local.tee $11 + (i32.or + (i32.load8_u + (local.get $9) + ) + (local.get $5) + ) + ) + ) + ) + ) + (i32.store offset=228 + (local.get $4) + (local.tee $5 + (select + (local.get $5) + (local.tee $13 + (i32.add + (i32.add + (i32.mul + (local.tee $10 + (i32.load offset=12 + (local.get $0) + ) + ) + (local.get $3) + ) + (local.get $7) + ) + (i32.const 12) + ) + ) + (local.get $11) + ) + ) + ) + (i32.store offset=224 + (local.get $4) + (local.tee $8 + (select + (local.get $8) + (local.tee $15 + (i32.add + (i32.add + (i32.add + (i32.mul + (i32.load offset=16 + (local.get $0) + ) + (local.get $3) + ) + (i32.shl + (local.get $10) + (i32.const 3) + ) + ) + (local.get $7) + ) + (i32.const 12) + ) + ) + (local.get $11) + ) + ) + ) + (block $label$17 + (br_if $label$17 + (i32.ne + (i32.load8_u + (local.get $9) + ) + (local.get $12) + ) + ) + (i32.store offset=232 + (local.get $4) + (local.tee $11 + (i32.load offset=24 + (local.get $0) + ) + ) + ) + (i32.store offset=236 + (local.get $4) + (local.tee $9 + (i32.load offset=28 + (local.get $0) + ) + ) + ) + (br_if $label$2 + (i32.eqz + (local.get $9) + ) + ) + (br_if $label$17 + (i32.eqz + (i32.and + (call_indirect (type $i32_i32_i32_i32_=>_i32) + (local.get $1) + (local.get $13) + (local.get $10) + (local.get $11) + (local.get $9) + ) + (i32.const 1) + ) + ) + ) + (memory.copy + (local.get $15) + (local.get $2) + (i32.load offset=16 + (local.get $0) + ) + ) + (br $label$1) + ) + (local.set $3 + (i32.add + (local.get $3) + (i32.const 1) + ) + ) + (br $label$15) + ) + ) + (i32.store offset=240 + (local.get $4) + (local.tee $9 + (i32.load offset=8 + (local.get $7) + ) + ) + ) + (local.set $3 + (local.get $7) + ) + (br $label$13) + ) + ) + (if + (i32.eqz + (local.get $5) + ) + (block + (local.set $5 + (call $runtime.alloc + (i32.add + (i32.shl + (i32.add + (i32.load offset=16 + (local.get $0) + ) + (i32.load offset=12 + (local.get $0) + ) + ) + (i32.const 3) + ) + (i32.const 12) + ) + ) + ) + (i32.store offset=8 + (local.get $0) + (i32.add + (i32.load offset=8 + (local.get $0) + ) + (i32.const 1) + ) + ) + (i32.store offset=248 + (local.get $4) + (local.get $5) + ) + (i32.store offset=252 + (local.get $4) + (local.get $5) + ) + (i32.store offset=244 + (local.get $4) + (local.get $5) + ) + (memory.copy + (local.tee $7 + (i32.add + (local.get $5) + (i32.const 12) + ) + ) + (local.get $1) + (local.tee $6 + (i32.load offset=12 + (local.get $0) + ) + ) + ) + (memory.copy + (i32.add + (local.get $7) + (i32.shl + (local.get $6) + (i32.const 3) + ) + ) + (local.get $2) + (i32.load offset=16 + (local.get $0) + ) + ) + (i32.store8 + (local.get $5) + (local.get $12) + ) + (br_if $label$2 + (i32.eqz + (local.get $3) + ) + ) + (i32.store offset=8 + (local.get $3) + (local.get $5) + ) + (br $label$1) + ) + ) + (i32.store offset=8 + (local.get $0) + (i32.add + (i32.load offset=8 + (local.get $0) + ) + (i32.const 1) + ) + ) + (memory.copy + (local.get $5) + (local.get $1) + (i32.load offset=12 + (local.get $0) + ) + ) + (memory.copy + (local.get $8) + (local.get $2) + (i32.load offset=16 + (local.get $0) + ) + ) + (br_if $label$2 + (i32.eqz + (local.get $6) + ) + ) + (i32.store8 + (local.get $6) + (local.get $12) + ) + (br $label$1) + ) + (call $runtime.nilPanic) + (unreachable) + ) + (i32.store + (i32.const 65932) + (local.get $14) + ) + (global.set $__stack_pointer + (i32.add + (local.get $4) + (i32.const 256) + ) + ) + ) + ;; custom section ".debug_info", size 29604 + ;; custom section ".debug_pubtypes", size 2106 + ;; custom section ".debug_loc", size 8492 + ;; custom section ".debug_ranges", size 1440 + ;; custom section ".debug_aranges", size 80 + ;; custom section ".debug_abbrev", size 2027 + ;; custom section ".debug_line", size 11123 + ;; custom section ".debug_str", size 18173 + ;; custom section ".debug_pubnames", size 16895 + ;; custom section "producers", size 128 +) diff --git a/guest/tinygo/ww.go b/guest/tinygo/ww.go new file mode 100644 index 00000000..20bfa36f --- /dev/null +++ b/guest/tinygo/ww.go @@ -0,0 +1,6 @@ +// Package ww contains Wetware bindings for WASM guest-code. +package ww + +func Test(a, b uint32) uint32 { + return test(a, b) +} diff --git a/internal/api/process/process.capnp.go b/internal/api/process/process.capnp.go index f06d2d63..55a78f39 100644 --- a/internal/api/process/process.capnp.go +++ b/internal/api/process/process.capnp.go @@ -16,23 +16,23 @@ type Executor capnp.Client // Executor_TypeID is the unique identifier for the type Executor. const Executor_TypeID = 0xaf2e5ebaa58175d2 -func (c Executor) Spawn(ctx context.Context, params func(Executor_spawn_Params) error) (Executor_spawn_Results_Future, capnp.ReleaseFunc) { +func (c Executor) Exec(ctx context.Context, params func(Executor_exec_Params) error) (Executor_exec_Results_Future, capnp.ReleaseFunc) { s := capnp.Send{ Method: capnp.Method{ InterfaceID: 0xaf2e5ebaa58175d2, MethodID: 0, InterfaceName: "process.capnp:Executor", - MethodName: "spawn", + MethodName: "exec", }, } if params != nil { - s.ArgsSize = capnp.ObjectSize{DataSize: 0, PointerCount: 2} - s.PlaceArgs = func(s capnp.Struct) error { return params(Executor_spawn_Params(s)) } + s.ArgsSize = capnp.ObjectSize{DataSize: 0, PointerCount: 1} + s.PlaceArgs = func(s capnp.Struct) error { return params(Executor_exec_Params(s)) } } ans, release := capnp.Client(c).SendCall(ctx, s) - return Executor_spawn_Results_Future{Future: ans.Future()}, release + return Executor_exec_Results_Future{Future: ans.Future()}, release } @@ -109,7 +109,7 @@ func (c Executor) GetFlowLimiter() fc.FlowLimiter { // A Executor_Server is a Executor with a local implementation. type Executor_Server interface { - Spawn(context.Context, Executor_spawn) error + Exec(context.Context, Executor_exec) error } // Executor_NewServer creates a new Server from an implementation of Executor_Server. @@ -136,31 +136,31 @@ func Executor_Methods(methods []server.Method, s Executor_Server) []server.Metho InterfaceID: 0xaf2e5ebaa58175d2, MethodID: 0, InterfaceName: "process.capnp:Executor", - MethodName: "spawn", + MethodName: "exec", }, Impl: func(ctx context.Context, call *server.Call) error { - return s.Spawn(ctx, Executor_spawn{call}) + return s.Exec(ctx, Executor_exec{call}) }, }) return methods } -// Executor_spawn holds the state for a server call to Executor.spawn. +// Executor_exec holds the state for a server call to Executor.exec. // See server.Call for documentation. -type Executor_spawn struct { +type Executor_exec struct { *server.Call } // Args returns the call's arguments. -func (c Executor_spawn) Args() Executor_spawn_Params { - return Executor_spawn_Params(c.Call.Args()) +func (c Executor_exec) Args() Executor_exec_Params { + return Executor_exec_Params(c.Call.Args()) } // AllocResults allocates the results struct. -func (c Executor_spawn) AllocResults() (Executor_spawn_Results, error) { +func (c Executor_exec) AllocResults() (Executor_exec_Results, error) { r, err := c.Call.AllocResults(capnp.ObjectSize{DataSize: 0, PointerCount: 1}) - return Executor_spawn_Results(r), err + return Executor_exec_Results(r), err } // Executor_List is a list of Executor. @@ -172,158 +172,140 @@ func NewExecutor_List(s *capnp.Segment, sz int32) (Executor_List, error) { return capnp.CapList[Executor](l), err } -type Executor_spawn_Params capnp.Struct +type Executor_exec_Params capnp.Struct -// Executor_spawn_Params_TypeID is the unique identifier for the type Executor_spawn_Params. -const Executor_spawn_Params_TypeID = 0xf20b3dea95929312 +// Executor_exec_Params_TypeID is the unique identifier for the type Executor_exec_Params. +const Executor_exec_Params_TypeID = 0xf20b3dea95929312 -func NewExecutor_spawn_Params(s *capnp.Segment) (Executor_spawn_Params, error) { - st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 2}) - return Executor_spawn_Params(st), err +func NewExecutor_exec_Params(s *capnp.Segment) (Executor_exec_Params, error) { + st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 1}) + return Executor_exec_Params(st), err } -func NewRootExecutor_spawn_Params(s *capnp.Segment) (Executor_spawn_Params, error) { - st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 2}) - return Executor_spawn_Params(st), err +func NewRootExecutor_exec_Params(s *capnp.Segment) (Executor_exec_Params, error) { + st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 1}) + return Executor_exec_Params(st), err } -func ReadRootExecutor_spawn_Params(msg *capnp.Message) (Executor_spawn_Params, error) { +func ReadRootExecutor_exec_Params(msg *capnp.Message) (Executor_exec_Params, error) { root, err := msg.Root() - return Executor_spawn_Params(root.Struct()), err + return Executor_exec_Params(root.Struct()), err } -func (s Executor_spawn_Params) String() string { +func (s Executor_exec_Params) String() string { str, _ := text.Marshal(0xf20b3dea95929312, capnp.Struct(s)) return str } -func (s Executor_spawn_Params) EncodeAsPtr(seg *capnp.Segment) capnp.Ptr { +func (s Executor_exec_Params) EncodeAsPtr(seg *capnp.Segment) capnp.Ptr { return capnp.Struct(s).EncodeAsPtr(seg) } -func (Executor_spawn_Params) DecodeFromPtr(p capnp.Ptr) Executor_spawn_Params { - return Executor_spawn_Params(capnp.Struct{}.DecodeFromPtr(p)) +func (Executor_exec_Params) DecodeFromPtr(p capnp.Ptr) Executor_exec_Params { + return Executor_exec_Params(capnp.Struct{}.DecodeFromPtr(p)) } -func (s Executor_spawn_Params) ToPtr() capnp.Ptr { +func (s Executor_exec_Params) ToPtr() capnp.Ptr { return capnp.Struct(s).ToPtr() } -func (s Executor_spawn_Params) IsValid() bool { +func (s Executor_exec_Params) IsValid() bool { return capnp.Struct(s).IsValid() } -func (s Executor_spawn_Params) Message() *capnp.Message { +func (s Executor_exec_Params) Message() *capnp.Message { return capnp.Struct(s).Message() } -func (s Executor_spawn_Params) Segment() *capnp.Segment { +func (s Executor_exec_Params) Segment() *capnp.Segment { return capnp.Struct(s).Segment() } -func (s Executor_spawn_Params) ByteCode() ([]byte, error) { +func (s Executor_exec_Params) Bytecode() ([]byte, error) { p, err := capnp.Struct(s).Ptr(0) return []byte(p.Data()), err } -func (s Executor_spawn_Params) HasByteCode() bool { +func (s Executor_exec_Params) HasBytecode() bool { return capnp.Struct(s).HasPtr(0) } -func (s Executor_spawn_Params) SetByteCode(v []byte) error { +func (s Executor_exec_Params) SetBytecode(v []byte) error { return capnp.Struct(s).SetData(0, v) } -func (s Executor_spawn_Params) EntryPoint() (string, error) { - p, err := capnp.Struct(s).Ptr(1) - return p.TextDefault("run"), err -} - -func (s Executor_spawn_Params) HasEntryPoint() bool { - return capnp.Struct(s).HasPtr(1) -} - -func (s Executor_spawn_Params) EntryPointBytes() ([]byte, error) { - p, err := capnp.Struct(s).Ptr(1) - return p.TextBytesDefault("run"), err -} - -func (s Executor_spawn_Params) SetEntryPoint(v string) error { - return capnp.Struct(s).SetNewText(1, v) -} +// Executor_exec_Params_List is a list of Executor_exec_Params. +type Executor_exec_Params_List = capnp.StructList[Executor_exec_Params] -// Executor_spawn_Params_List is a list of Executor_spawn_Params. -type Executor_spawn_Params_List = capnp.StructList[Executor_spawn_Params] - -// NewExecutor_spawn_Params creates a new list of Executor_spawn_Params. -func NewExecutor_spawn_Params_List(s *capnp.Segment, sz int32) (Executor_spawn_Params_List, error) { - l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 0, PointerCount: 2}, sz) - return capnp.StructList[Executor_spawn_Params](l), err +// NewExecutor_exec_Params creates a new list of Executor_exec_Params. +func NewExecutor_exec_Params_List(s *capnp.Segment, sz int32) (Executor_exec_Params_List, error) { + l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 0, PointerCount: 1}, sz) + return capnp.StructList[Executor_exec_Params](l), err } -// Executor_spawn_Params_Future is a wrapper for a Executor_spawn_Params promised by a client call. -type Executor_spawn_Params_Future struct{ *capnp.Future } +// Executor_exec_Params_Future is a wrapper for a Executor_exec_Params promised by a client call. +type Executor_exec_Params_Future struct{ *capnp.Future } -func (f Executor_spawn_Params_Future) Struct() (Executor_spawn_Params, error) { +func (f Executor_exec_Params_Future) Struct() (Executor_exec_Params, error) { p, err := f.Future.Ptr() - return Executor_spawn_Params(p.Struct()), err + return Executor_exec_Params(p.Struct()), err } -type Executor_spawn_Results capnp.Struct +type Executor_exec_Results capnp.Struct -// Executor_spawn_Results_TypeID is the unique identifier for the type Executor_spawn_Results. -const Executor_spawn_Results_TypeID = 0xbb4f16b0a7d2d09b +// Executor_exec_Results_TypeID is the unique identifier for the type Executor_exec_Results. +const Executor_exec_Results_TypeID = 0xbb4f16b0a7d2d09b -func NewExecutor_spawn_Results(s *capnp.Segment) (Executor_spawn_Results, error) { +func NewExecutor_exec_Results(s *capnp.Segment) (Executor_exec_Results, error) { st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 1}) - return Executor_spawn_Results(st), err + return Executor_exec_Results(st), err } -func NewRootExecutor_spawn_Results(s *capnp.Segment) (Executor_spawn_Results, error) { +func NewRootExecutor_exec_Results(s *capnp.Segment) (Executor_exec_Results, error) { st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 1}) - return Executor_spawn_Results(st), err + return Executor_exec_Results(st), err } -func ReadRootExecutor_spawn_Results(msg *capnp.Message) (Executor_spawn_Results, error) { +func ReadRootExecutor_exec_Results(msg *capnp.Message) (Executor_exec_Results, error) { root, err := msg.Root() - return Executor_spawn_Results(root.Struct()), err + return Executor_exec_Results(root.Struct()), err } -func (s Executor_spawn_Results) String() string { +func (s Executor_exec_Results) String() string { str, _ := text.Marshal(0xbb4f16b0a7d2d09b, capnp.Struct(s)) return str } -func (s Executor_spawn_Results) EncodeAsPtr(seg *capnp.Segment) capnp.Ptr { +func (s Executor_exec_Results) EncodeAsPtr(seg *capnp.Segment) capnp.Ptr { return capnp.Struct(s).EncodeAsPtr(seg) } -func (Executor_spawn_Results) DecodeFromPtr(p capnp.Ptr) Executor_spawn_Results { - return Executor_spawn_Results(capnp.Struct{}.DecodeFromPtr(p)) +func (Executor_exec_Results) DecodeFromPtr(p capnp.Ptr) Executor_exec_Results { + return Executor_exec_Results(capnp.Struct{}.DecodeFromPtr(p)) } -func (s Executor_spawn_Results) ToPtr() capnp.Ptr { +func (s Executor_exec_Results) ToPtr() capnp.Ptr { return capnp.Struct(s).ToPtr() } -func (s Executor_spawn_Results) IsValid() bool { +func (s Executor_exec_Results) IsValid() bool { return capnp.Struct(s).IsValid() } -func (s Executor_spawn_Results) Message() *capnp.Message { +func (s Executor_exec_Results) Message() *capnp.Message { return capnp.Struct(s).Message() } -func (s Executor_spawn_Results) Segment() *capnp.Segment { +func (s Executor_exec_Results) Segment() *capnp.Segment { return capnp.Struct(s).Segment() } -func (s Executor_spawn_Results) Process() Process { +func (s Executor_exec_Results) Process() Process { p, _ := capnp.Struct(s).Ptr(0) return Process(p.Interface().Client()) } -func (s Executor_spawn_Results) HasProcess() bool { +func (s Executor_exec_Results) HasProcess() bool { return capnp.Struct(s).HasPtr(0) } -func (s Executor_spawn_Results) SetProcess(v Process) error { +func (s Executor_exec_Results) SetProcess(v Process) error { if !v.IsValid() { return capnp.Struct(s).SetPtr(0, capnp.Ptr{}) } @@ -332,23 +314,23 @@ func (s Executor_spawn_Results) SetProcess(v Process) error { return capnp.Struct(s).SetPtr(0, in.ToPtr()) } -// Executor_spawn_Results_List is a list of Executor_spawn_Results. -type Executor_spawn_Results_List = capnp.StructList[Executor_spawn_Results] +// Executor_exec_Results_List is a list of Executor_exec_Results. +type Executor_exec_Results_List = capnp.StructList[Executor_exec_Results] -// NewExecutor_spawn_Results creates a new list of Executor_spawn_Results. -func NewExecutor_spawn_Results_List(s *capnp.Segment, sz int32) (Executor_spawn_Results_List, error) { +// NewExecutor_exec_Results creates a new list of Executor_exec_Results. +func NewExecutor_exec_Results_List(s *capnp.Segment, sz int32) (Executor_exec_Results_List, error) { l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 0, PointerCount: 1}, sz) - return capnp.StructList[Executor_spawn_Results](l), err + return capnp.StructList[Executor_exec_Results](l), err } -// Executor_spawn_Results_Future is a wrapper for a Executor_spawn_Results promised by a client call. -type Executor_spawn_Results_Future struct{ *capnp.Future } +// Executor_exec_Results_Future is a wrapper for a Executor_exec_Results promised by a client call. +type Executor_exec_Results_Future struct{ *capnp.Future } -func (f Executor_spawn_Results_Future) Struct() (Executor_spawn_Results, error) { +func (f Executor_exec_Results_Future) Struct() (Executor_exec_Results, error) { p, err := f.Future.Ptr() - return Executor_spawn_Results(p.Struct()), err + return Executor_exec_Results(p.Struct()), err } -func (p Executor_spawn_Results_Future) Process() Process { +func (p Executor_exec_Results_Future) Process() Process { return Process(p.Future.Field(0, nil).Client()) } @@ -357,63 +339,43 @@ type Process capnp.Client // Process_TypeID is the unique identifier for the type Process. const Process_TypeID = 0xda23f0d3a8250633 -func (c Process) Start(ctx context.Context, params func(Process_start_Params) error) (Process_start_Results_Future, capnp.ReleaseFunc) { +func (c Process) Wait(ctx context.Context, params func(Process_wait_Params) error) (Process_wait_Results_Future, capnp.ReleaseFunc) { s := capnp.Send{ Method: capnp.Method{ InterfaceID: 0xda23f0d3a8250633, MethodID: 0, InterfaceName: "process.capnp:Process", - MethodName: "start", + MethodName: "wait", }, } if params != nil { s.ArgsSize = capnp.ObjectSize{DataSize: 0, PointerCount: 0} - s.PlaceArgs = func(s capnp.Struct) error { return params(Process_start_Params(s)) } + s.PlaceArgs = func(s capnp.Struct) error { return params(Process_wait_Params(s)) } } ans, release := capnp.Client(c).SendCall(ctx, s) - return Process_start_Results_Future{Future: ans.Future()}, release + return Process_wait_Results_Future{Future: ans.Future()}, release } -func (c Process) Stop(ctx context.Context, params func(Process_stop_Params) error) (Process_stop_Results_Future, capnp.ReleaseFunc) { +func (c Process) Kill(ctx context.Context, params func(Process_kill_Params) error) (Process_kill_Results_Future, capnp.ReleaseFunc) { s := capnp.Send{ Method: capnp.Method{ InterfaceID: 0xda23f0d3a8250633, MethodID: 1, InterfaceName: "process.capnp:Process", - MethodName: "stop", - }, - } - if params != nil { - s.ArgsSize = capnp.ObjectSize{DataSize: 0, PointerCount: 0} - s.PlaceArgs = func(s capnp.Struct) error { return params(Process_stop_Params(s)) } - } - - ans, release := capnp.Client(c).SendCall(ctx, s) - return Process_stop_Results_Future{Future: ans.Future()}, release - -} - -func (c Process) Wait(ctx context.Context, params func(Process_wait_Params) error) (Process_wait_Results_Future, capnp.ReleaseFunc) { - - s := capnp.Send{ - Method: capnp.Method{ - InterfaceID: 0xda23f0d3a8250633, - MethodID: 2, - InterfaceName: "process.capnp:Process", - MethodName: "wait", + MethodName: "kill", }, } if params != nil { s.ArgsSize = capnp.ObjectSize{DataSize: 0, PointerCount: 0} - s.PlaceArgs = func(s capnp.Struct) error { return params(Process_wait_Params(s)) } + s.PlaceArgs = func(s capnp.Struct) error { return params(Process_kill_Params(s)) } } ans, release := capnp.Client(c).SendCall(ctx, s) - return Process_wait_Results_Future{Future: ans.Future()}, release + return Process_kill_Results_Future{Future: ans.Future()}, release } @@ -490,11 +452,9 @@ func (c Process) GetFlowLimiter() fc.FlowLimiter { // A Process_Server is a Process with a local implementation. type Process_Server interface { - Start(context.Context, Process_start) error - - Stop(context.Context, Process_stop) error - Wait(context.Context, Process_wait) error + + Kill(context.Context, Process_kill) error } // Process_NewServer creates a new Server from an implementation of Process_Server. @@ -513,7 +473,7 @@ func Process_ServerToClient(s Process_Server) Process { // This can be used to create a more complicated Server. func Process_Methods(methods []server.Method, s Process_Server) []server.Method { if cap(methods) == 0 { - methods = make([]server.Method, 0, 3) + methods = make([]server.Method, 0, 2) } methods = append(methods, server.Method{ @@ -521,10 +481,10 @@ func Process_Methods(methods []server.Method, s Process_Server) []server.Method InterfaceID: 0xda23f0d3a8250633, MethodID: 0, InterfaceName: "process.capnp:Process", - MethodName: "start", + MethodName: "wait", }, Impl: func(ctx context.Context, call *server.Call) error { - return s.Start(ctx, Process_start{call}) + return s.Wait(ctx, Process_wait{call}) }, }) @@ -533,77 +493,48 @@ func Process_Methods(methods []server.Method, s Process_Server) []server.Method InterfaceID: 0xda23f0d3a8250633, MethodID: 1, InterfaceName: "process.capnp:Process", - MethodName: "stop", + MethodName: "kill", }, Impl: func(ctx context.Context, call *server.Call) error { - return s.Stop(ctx, Process_stop{call}) - }, - }) - - methods = append(methods, server.Method{ - Method: capnp.Method{ - InterfaceID: 0xda23f0d3a8250633, - MethodID: 2, - InterfaceName: "process.capnp:Process", - MethodName: "wait", - }, - Impl: func(ctx context.Context, call *server.Call) error { - return s.Wait(ctx, Process_wait{call}) + return s.Kill(ctx, Process_kill{call}) }, }) return methods } -// Process_start holds the state for a server call to Process.start. +// Process_wait holds the state for a server call to Process.wait. // See server.Call for documentation. -type Process_start struct { +type Process_wait struct { *server.Call } // Args returns the call's arguments. -func (c Process_start) Args() Process_start_Params { - return Process_start_Params(c.Call.Args()) +func (c Process_wait) Args() Process_wait_Params { + return Process_wait_Params(c.Call.Args()) } // AllocResults allocates the results struct. -func (c Process_start) AllocResults() (Process_start_Results, error) { - r, err := c.Call.AllocResults(capnp.ObjectSize{DataSize: 0, PointerCount: 0}) - return Process_start_Results(r), err +func (c Process_wait) AllocResults() (Process_wait_Results, error) { + r, err := c.Call.AllocResults(capnp.ObjectSize{DataSize: 8, PointerCount: 0}) + return Process_wait_Results(r), err } -// Process_stop holds the state for a server call to Process.stop. +// Process_kill holds the state for a server call to Process.kill. // See server.Call for documentation. -type Process_stop struct { +type Process_kill struct { *server.Call } // Args returns the call's arguments. -func (c Process_stop) Args() Process_stop_Params { - return Process_stop_Params(c.Call.Args()) +func (c Process_kill) Args() Process_kill_Params { + return Process_kill_Params(c.Call.Args()) } // AllocResults allocates the results struct. -func (c Process_stop) AllocResults() (Process_stop_Results, error) { +func (c Process_kill) AllocResults() (Process_kill_Results, error) { r, err := c.Call.AllocResults(capnp.ObjectSize{DataSize: 0, PointerCount: 0}) - return Process_stop_Results(r), err -} - -// Process_wait holds the state for a server call to Process.wait. -// See server.Call for documentation. -type Process_wait struct { - *server.Call -} - -// Args returns the call's arguments. -func (c Process_wait) Args() Process_wait_Params { - return Process_wait_Params(c.Call.Args()) -} - -// AllocResults allocates the results struct. -func (c Process_wait) AllocResults() (Process_wait_Results, error) { - r, err := c.Call.AllocResults(capnp.ObjectSize{DataSize: 8, PointerCount: 0}) - return Process_wait_Results(r), err + return Process_kill_Results(r), err } // Process_List is a list of Process. @@ -615,451 +546,311 @@ func NewProcess_List(s *capnp.Segment, sz int32) (Process_List, error) { return capnp.CapList[Process](l), err } -type Process_start_Params capnp.Struct +type Process_wait_Params capnp.Struct -// Process_start_Params_TypeID is the unique identifier for the type Process_start_Params. -const Process_start_Params_TypeID = 0xf9694ae208dbb3e3 +// Process_wait_Params_TypeID is the unique identifier for the type Process_wait_Params. +const Process_wait_Params_TypeID = 0xf9694ae208dbb3e3 -func NewProcess_start_Params(s *capnp.Segment) (Process_start_Params, error) { +func NewProcess_wait_Params(s *capnp.Segment) (Process_wait_Params, error) { st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 0}) - return Process_start_Params(st), err + return Process_wait_Params(st), err } -func NewRootProcess_start_Params(s *capnp.Segment) (Process_start_Params, error) { +func NewRootProcess_wait_Params(s *capnp.Segment) (Process_wait_Params, error) { st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 0}) - return Process_start_Params(st), err + return Process_wait_Params(st), err } -func ReadRootProcess_start_Params(msg *capnp.Message) (Process_start_Params, error) { +func ReadRootProcess_wait_Params(msg *capnp.Message) (Process_wait_Params, error) { root, err := msg.Root() - return Process_start_Params(root.Struct()), err + return Process_wait_Params(root.Struct()), err } -func (s Process_start_Params) String() string { +func (s Process_wait_Params) String() string { str, _ := text.Marshal(0xf9694ae208dbb3e3, capnp.Struct(s)) return str } -func (s Process_start_Params) EncodeAsPtr(seg *capnp.Segment) capnp.Ptr { +func (s Process_wait_Params) EncodeAsPtr(seg *capnp.Segment) capnp.Ptr { return capnp.Struct(s).EncodeAsPtr(seg) } -func (Process_start_Params) DecodeFromPtr(p capnp.Ptr) Process_start_Params { - return Process_start_Params(capnp.Struct{}.DecodeFromPtr(p)) +func (Process_wait_Params) DecodeFromPtr(p capnp.Ptr) Process_wait_Params { + return Process_wait_Params(capnp.Struct{}.DecodeFromPtr(p)) } -func (s Process_start_Params) ToPtr() capnp.Ptr { +func (s Process_wait_Params) ToPtr() capnp.Ptr { return capnp.Struct(s).ToPtr() } -func (s Process_start_Params) IsValid() bool { +func (s Process_wait_Params) IsValid() bool { return capnp.Struct(s).IsValid() } -func (s Process_start_Params) Message() *capnp.Message { +func (s Process_wait_Params) Message() *capnp.Message { return capnp.Struct(s).Message() } -func (s Process_start_Params) Segment() *capnp.Segment { +func (s Process_wait_Params) Segment() *capnp.Segment { return capnp.Struct(s).Segment() } -// Process_start_Params_List is a list of Process_start_Params. -type Process_start_Params_List = capnp.StructList[Process_start_Params] +// Process_wait_Params_List is a list of Process_wait_Params. +type Process_wait_Params_List = capnp.StructList[Process_wait_Params] -// NewProcess_start_Params creates a new list of Process_start_Params. -func NewProcess_start_Params_List(s *capnp.Segment, sz int32) (Process_start_Params_List, error) { +// NewProcess_wait_Params creates a new list of Process_wait_Params. +func NewProcess_wait_Params_List(s *capnp.Segment, sz int32) (Process_wait_Params_List, error) { l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 0, PointerCount: 0}, sz) - return capnp.StructList[Process_start_Params](l), err + return capnp.StructList[Process_wait_Params](l), err } -// Process_start_Params_Future is a wrapper for a Process_start_Params promised by a client call. -type Process_start_Params_Future struct{ *capnp.Future } +// Process_wait_Params_Future is a wrapper for a Process_wait_Params promised by a client call. +type Process_wait_Params_Future struct{ *capnp.Future } -func (f Process_start_Params_Future) Struct() (Process_start_Params, error) { +func (f Process_wait_Params_Future) Struct() (Process_wait_Params, error) { p, err := f.Future.Ptr() - return Process_start_Params(p.Struct()), err + return Process_wait_Params(p.Struct()), err } -type Process_start_Results capnp.Struct +type Process_wait_Results capnp.Struct -// Process_start_Results_TypeID is the unique identifier for the type Process_start_Results. -const Process_start_Results_TypeID = 0xd72ab4a0243047ac +// Process_wait_Results_TypeID is the unique identifier for the type Process_wait_Results. +const Process_wait_Results_TypeID = 0xd72ab4a0243047ac -func NewProcess_start_Results(s *capnp.Segment) (Process_start_Results, error) { - st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 0}) - return Process_start_Results(st), err +func NewProcess_wait_Results(s *capnp.Segment) (Process_wait_Results, error) { + st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 8, PointerCount: 0}) + return Process_wait_Results(st), err } -func NewRootProcess_start_Results(s *capnp.Segment) (Process_start_Results, error) { - st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 0}) - return Process_start_Results(st), err +func NewRootProcess_wait_Results(s *capnp.Segment) (Process_wait_Results, error) { + st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 8, PointerCount: 0}) + return Process_wait_Results(st), err } -func ReadRootProcess_start_Results(msg *capnp.Message) (Process_start_Results, error) { +func ReadRootProcess_wait_Results(msg *capnp.Message) (Process_wait_Results, error) { root, err := msg.Root() - return Process_start_Results(root.Struct()), err + return Process_wait_Results(root.Struct()), err } -func (s Process_start_Results) String() string { +func (s Process_wait_Results) String() string { str, _ := text.Marshal(0xd72ab4a0243047ac, capnp.Struct(s)) return str } -func (s Process_start_Results) EncodeAsPtr(seg *capnp.Segment) capnp.Ptr { +func (s Process_wait_Results) EncodeAsPtr(seg *capnp.Segment) capnp.Ptr { return capnp.Struct(s).EncodeAsPtr(seg) } -func (Process_start_Results) DecodeFromPtr(p capnp.Ptr) Process_start_Results { - return Process_start_Results(capnp.Struct{}.DecodeFromPtr(p)) +func (Process_wait_Results) DecodeFromPtr(p capnp.Ptr) Process_wait_Results { + return Process_wait_Results(capnp.Struct{}.DecodeFromPtr(p)) } -func (s Process_start_Results) ToPtr() capnp.Ptr { +func (s Process_wait_Results) ToPtr() capnp.Ptr { return capnp.Struct(s).ToPtr() } -func (s Process_start_Results) IsValid() bool { +func (s Process_wait_Results) IsValid() bool { return capnp.Struct(s).IsValid() } -func (s Process_start_Results) Message() *capnp.Message { +func (s Process_wait_Results) Message() *capnp.Message { return capnp.Struct(s).Message() } -func (s Process_start_Results) Segment() *capnp.Segment { +func (s Process_wait_Results) Segment() *capnp.Segment { return capnp.Struct(s).Segment() } - -// Process_start_Results_List is a list of Process_start_Results. -type Process_start_Results_List = capnp.StructList[Process_start_Results] - -// NewProcess_start_Results creates a new list of Process_start_Results. -func NewProcess_start_Results_List(s *capnp.Segment, sz int32) (Process_start_Results_List, error) { - l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 0, PointerCount: 0}, sz) - return capnp.StructList[Process_start_Results](l), err -} - -// Process_start_Results_Future is a wrapper for a Process_start_Results promised by a client call. -type Process_start_Results_Future struct{ *capnp.Future } - -func (f Process_start_Results_Future) Struct() (Process_start_Results, error) { - p, err := f.Future.Ptr() - return Process_start_Results(p.Struct()), err -} - -type Process_stop_Params capnp.Struct - -// Process_stop_Params_TypeID is the unique identifier for the type Process_stop_Params. -const Process_stop_Params_TypeID = 0xeea7ae19b02f5d47 - -func NewProcess_stop_Params(s *capnp.Segment) (Process_stop_Params, error) { - st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 0}) - return Process_stop_Params(st), err -} - -func NewRootProcess_stop_Params(s *capnp.Segment) (Process_stop_Params, error) { - st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 0}) - return Process_stop_Params(st), err -} - -func ReadRootProcess_stop_Params(msg *capnp.Message) (Process_stop_Params, error) { - root, err := msg.Root() - return Process_stop_Params(root.Struct()), err -} - -func (s Process_stop_Params) String() string { - str, _ := text.Marshal(0xeea7ae19b02f5d47, capnp.Struct(s)) - return str -} - -func (s Process_stop_Params) EncodeAsPtr(seg *capnp.Segment) capnp.Ptr { - return capnp.Struct(s).EncodeAsPtr(seg) -} - -func (Process_stop_Params) DecodeFromPtr(p capnp.Ptr) Process_stop_Params { - return Process_stop_Params(capnp.Struct{}.DecodeFromPtr(p)) -} - -func (s Process_stop_Params) ToPtr() capnp.Ptr { - return capnp.Struct(s).ToPtr() -} -func (s Process_stop_Params) IsValid() bool { - return capnp.Struct(s).IsValid() -} - -func (s Process_stop_Params) Message() *capnp.Message { - return capnp.Struct(s).Message() +func (s Process_wait_Results) ExitCode() uint32 { + return capnp.Struct(s).Uint32(0) } -func (s Process_stop_Params) Segment() *capnp.Segment { - return capnp.Struct(s).Segment() +func (s Process_wait_Results) SetExitCode(v uint32) { + capnp.Struct(s).SetUint32(0, v) } -// Process_stop_Params_List is a list of Process_stop_Params. -type Process_stop_Params_List = capnp.StructList[Process_stop_Params] +// Process_wait_Results_List is a list of Process_wait_Results. +type Process_wait_Results_List = capnp.StructList[Process_wait_Results] -// NewProcess_stop_Params creates a new list of Process_stop_Params. -func NewProcess_stop_Params_List(s *capnp.Segment, sz int32) (Process_stop_Params_List, error) { - l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 0, PointerCount: 0}, sz) - return capnp.StructList[Process_stop_Params](l), err +// NewProcess_wait_Results creates a new list of Process_wait_Results. +func NewProcess_wait_Results_List(s *capnp.Segment, sz int32) (Process_wait_Results_List, error) { + l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 8, PointerCount: 0}, sz) + return capnp.StructList[Process_wait_Results](l), err } -// Process_stop_Params_Future is a wrapper for a Process_stop_Params promised by a client call. -type Process_stop_Params_Future struct{ *capnp.Future } +// Process_wait_Results_Future is a wrapper for a Process_wait_Results promised by a client call. +type Process_wait_Results_Future struct{ *capnp.Future } -func (f Process_stop_Params_Future) Struct() (Process_stop_Params, error) { +func (f Process_wait_Results_Future) Struct() (Process_wait_Results, error) { p, err := f.Future.Ptr() - return Process_stop_Params(p.Struct()), err + return Process_wait_Results(p.Struct()), err } -type Process_stop_Results capnp.Struct +type Process_kill_Params capnp.Struct -// Process_stop_Results_TypeID is the unique identifier for the type Process_stop_Results. -const Process_stop_Results_TypeID = 0xc53168b273d497ee +// Process_kill_Params_TypeID is the unique identifier for the type Process_kill_Params. +const Process_kill_Params_TypeID = 0xeea7ae19b02f5d47 -func NewProcess_stop_Results(s *capnp.Segment) (Process_stop_Results, error) { +func NewProcess_kill_Params(s *capnp.Segment) (Process_kill_Params, error) { st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 0}) - return Process_stop_Results(st), err + return Process_kill_Params(st), err } -func NewRootProcess_stop_Results(s *capnp.Segment) (Process_stop_Results, error) { +func NewRootProcess_kill_Params(s *capnp.Segment) (Process_kill_Params, error) { st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 0}) - return Process_stop_Results(st), err + return Process_kill_Params(st), err } -func ReadRootProcess_stop_Results(msg *capnp.Message) (Process_stop_Results, error) { +func ReadRootProcess_kill_Params(msg *capnp.Message) (Process_kill_Params, error) { root, err := msg.Root() - return Process_stop_Results(root.Struct()), err + return Process_kill_Params(root.Struct()), err } -func (s Process_stop_Results) String() string { - str, _ := text.Marshal(0xc53168b273d497ee, capnp.Struct(s)) +func (s Process_kill_Params) String() string { + str, _ := text.Marshal(0xeea7ae19b02f5d47, capnp.Struct(s)) return str } -func (s Process_stop_Results) EncodeAsPtr(seg *capnp.Segment) capnp.Ptr { +func (s Process_kill_Params) EncodeAsPtr(seg *capnp.Segment) capnp.Ptr { return capnp.Struct(s).EncodeAsPtr(seg) } -func (Process_stop_Results) DecodeFromPtr(p capnp.Ptr) Process_stop_Results { - return Process_stop_Results(capnp.Struct{}.DecodeFromPtr(p)) +func (Process_kill_Params) DecodeFromPtr(p capnp.Ptr) Process_kill_Params { + return Process_kill_Params(capnp.Struct{}.DecodeFromPtr(p)) } -func (s Process_stop_Results) ToPtr() capnp.Ptr { +func (s Process_kill_Params) ToPtr() capnp.Ptr { return capnp.Struct(s).ToPtr() } -func (s Process_stop_Results) IsValid() bool { +func (s Process_kill_Params) IsValid() bool { return capnp.Struct(s).IsValid() } -func (s Process_stop_Results) Message() *capnp.Message { +func (s Process_kill_Params) Message() *capnp.Message { return capnp.Struct(s).Message() } -func (s Process_stop_Results) Segment() *capnp.Segment { +func (s Process_kill_Params) Segment() *capnp.Segment { return capnp.Struct(s).Segment() } -// Process_stop_Results_List is a list of Process_stop_Results. -type Process_stop_Results_List = capnp.StructList[Process_stop_Results] +// Process_kill_Params_List is a list of Process_kill_Params. +type Process_kill_Params_List = capnp.StructList[Process_kill_Params] -// NewProcess_stop_Results creates a new list of Process_stop_Results. -func NewProcess_stop_Results_List(s *capnp.Segment, sz int32) (Process_stop_Results_List, error) { +// NewProcess_kill_Params creates a new list of Process_kill_Params. +func NewProcess_kill_Params_List(s *capnp.Segment, sz int32) (Process_kill_Params_List, error) { l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 0, PointerCount: 0}, sz) - return capnp.StructList[Process_stop_Results](l), err + return capnp.StructList[Process_kill_Params](l), err } -// Process_stop_Results_Future is a wrapper for a Process_stop_Results promised by a client call. -type Process_stop_Results_Future struct{ *capnp.Future } +// Process_kill_Params_Future is a wrapper for a Process_kill_Params promised by a client call. +type Process_kill_Params_Future struct{ *capnp.Future } -func (f Process_stop_Results_Future) Struct() (Process_stop_Results, error) { +func (f Process_kill_Params_Future) Struct() (Process_kill_Params, error) { p, err := f.Future.Ptr() - return Process_stop_Results(p.Struct()), err + return Process_kill_Params(p.Struct()), err } -type Process_wait_Params capnp.Struct +type Process_kill_Results capnp.Struct -// Process_wait_Params_TypeID is the unique identifier for the type Process_wait_Params. -const Process_wait_Params_TypeID = 0xd22f75df06c187e8 +// Process_kill_Results_TypeID is the unique identifier for the type Process_kill_Results. +const Process_kill_Results_TypeID = 0xc53168b273d497ee -func NewProcess_wait_Params(s *capnp.Segment) (Process_wait_Params, error) { +func NewProcess_kill_Results(s *capnp.Segment) (Process_kill_Results, error) { st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 0}) - return Process_wait_Params(st), err + return Process_kill_Results(st), err } -func NewRootProcess_wait_Params(s *capnp.Segment) (Process_wait_Params, error) { +func NewRootProcess_kill_Results(s *capnp.Segment) (Process_kill_Results, error) { st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 0}) - return Process_wait_Params(st), err + return Process_kill_Results(st), err } -func ReadRootProcess_wait_Params(msg *capnp.Message) (Process_wait_Params, error) { +func ReadRootProcess_kill_Results(msg *capnp.Message) (Process_kill_Results, error) { root, err := msg.Root() - return Process_wait_Params(root.Struct()), err + return Process_kill_Results(root.Struct()), err } -func (s Process_wait_Params) String() string { - str, _ := text.Marshal(0xd22f75df06c187e8, capnp.Struct(s)) +func (s Process_kill_Results) String() string { + str, _ := text.Marshal(0xc53168b273d497ee, capnp.Struct(s)) return str } -func (s Process_wait_Params) EncodeAsPtr(seg *capnp.Segment) capnp.Ptr { +func (s Process_kill_Results) EncodeAsPtr(seg *capnp.Segment) capnp.Ptr { return capnp.Struct(s).EncodeAsPtr(seg) } -func (Process_wait_Params) DecodeFromPtr(p capnp.Ptr) Process_wait_Params { - return Process_wait_Params(capnp.Struct{}.DecodeFromPtr(p)) +func (Process_kill_Results) DecodeFromPtr(p capnp.Ptr) Process_kill_Results { + return Process_kill_Results(capnp.Struct{}.DecodeFromPtr(p)) } -func (s Process_wait_Params) ToPtr() capnp.Ptr { +func (s Process_kill_Results) ToPtr() capnp.Ptr { return capnp.Struct(s).ToPtr() } -func (s Process_wait_Params) IsValid() bool { +func (s Process_kill_Results) IsValid() bool { return capnp.Struct(s).IsValid() } -func (s Process_wait_Params) Message() *capnp.Message { +func (s Process_kill_Results) Message() *capnp.Message { return capnp.Struct(s).Message() } -func (s Process_wait_Params) Segment() *capnp.Segment { +func (s Process_kill_Results) Segment() *capnp.Segment { return capnp.Struct(s).Segment() } -// Process_wait_Params_List is a list of Process_wait_Params. -type Process_wait_Params_List = capnp.StructList[Process_wait_Params] +// Process_kill_Results_List is a list of Process_kill_Results. +type Process_kill_Results_List = capnp.StructList[Process_kill_Results] -// NewProcess_wait_Params creates a new list of Process_wait_Params. -func NewProcess_wait_Params_List(s *capnp.Segment, sz int32) (Process_wait_Params_List, error) { +// NewProcess_kill_Results creates a new list of Process_kill_Results. +func NewProcess_kill_Results_List(s *capnp.Segment, sz int32) (Process_kill_Results_List, error) { l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 0, PointerCount: 0}, sz) - return capnp.StructList[Process_wait_Params](l), err + return capnp.StructList[Process_kill_Results](l), err } -// Process_wait_Params_Future is a wrapper for a Process_wait_Params promised by a client call. -type Process_wait_Params_Future struct{ *capnp.Future } +// Process_kill_Results_Future is a wrapper for a Process_kill_Results promised by a client call. +type Process_kill_Results_Future struct{ *capnp.Future } -func (f Process_wait_Params_Future) Struct() (Process_wait_Params, error) { +func (f Process_kill_Results_Future) Struct() (Process_kill_Results, error) { p, err := f.Future.Ptr() - return Process_wait_Params(p.Struct()), err -} - -type Process_wait_Results capnp.Struct - -// Process_wait_Results_TypeID is the unique identifier for the type Process_wait_Results. -const Process_wait_Results_TypeID = 0x9d6074459fa0602b - -func NewProcess_wait_Results(s *capnp.Segment) (Process_wait_Results, error) { - st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 8, PointerCount: 0}) - return Process_wait_Results(st), err -} - -func NewRootProcess_wait_Results(s *capnp.Segment) (Process_wait_Results, error) { - st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 8, PointerCount: 0}) - return Process_wait_Results(st), err -} - -func ReadRootProcess_wait_Results(msg *capnp.Message) (Process_wait_Results, error) { - root, err := msg.Root() - return Process_wait_Results(root.Struct()), err -} - -func (s Process_wait_Results) String() string { - str, _ := text.Marshal(0x9d6074459fa0602b, capnp.Struct(s)) - return str -} - -func (s Process_wait_Results) EncodeAsPtr(seg *capnp.Segment) capnp.Ptr { - return capnp.Struct(s).EncodeAsPtr(seg) -} - -func (Process_wait_Results) DecodeFromPtr(p capnp.Ptr) Process_wait_Results { - return Process_wait_Results(capnp.Struct{}.DecodeFromPtr(p)) -} - -func (s Process_wait_Results) ToPtr() capnp.Ptr { - return capnp.Struct(s).ToPtr() -} -func (s Process_wait_Results) IsValid() bool { - return capnp.Struct(s).IsValid() -} - -func (s Process_wait_Results) Message() *capnp.Message { - return capnp.Struct(s).Message() -} - -func (s Process_wait_Results) Segment() *capnp.Segment { - return capnp.Struct(s).Segment() -} -func (s Process_wait_Results) ExitCode() uint32 { - return capnp.Struct(s).Uint32(0) -} - -func (s Process_wait_Results) SetExitCode(v uint32) { - capnp.Struct(s).SetUint32(0, v) -} - -// Process_wait_Results_List is a list of Process_wait_Results. -type Process_wait_Results_List = capnp.StructList[Process_wait_Results] - -// NewProcess_wait_Results creates a new list of Process_wait_Results. -func NewProcess_wait_Results_List(s *capnp.Segment, sz int32) (Process_wait_Results_List, error) { - l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 8, PointerCount: 0}, sz) - return capnp.StructList[Process_wait_Results](l), err -} - -// Process_wait_Results_Future is a wrapper for a Process_wait_Results promised by a client call. -type Process_wait_Results_Future struct{ *capnp.Future } - -func (f Process_wait_Results_Future) Struct() (Process_wait_Results, error) { - p, err := f.Future.Ptr() - return Process_wait_Results(p.Struct()), err -} - -const schema_9a51e53177277763 = "x\xda|\x92Oh\x13M\x18\xc6\xdfgf\xd3\x0d|" + - "\xc9W\xa6[\xab\xf6R\xac\x15\xb5\xd26\xb1\x1eT\x94" + - "\x06%\x14zq\xc7\x9b\x82\xd25.\x18h\x93\xb8\x7f" + - "H{\x10\xe9A\xc4\xa3\x8a\x88\x8aX\x0fR\x05\xd1R" + - "\xbdX\xf1\xe0\xa1x\x95\xa8\x14\xf4 (\x82\x08\x16\xf1" + - "\xe6ie6\xd95\xad\xa6\xb7\x19\xdew\x9e\xf7y\x7f" + - "\xf3dF\x90\xd3\xb2\xe9e\x8d\x98\xdc\x9bh\x0bv\x8d" + - "\xcf\xde\xc9{\xe3\xb7Iv\x01D\x9aN4,Y7" + - "\x08\xc616B\x08j\xfe\xcc\xbd\xc5\x93\x83\x8fI\xfc" + - "\xcf\x83Bu{5\xfbE\xde$\x82q\x8e-\x1a\x17" + - "\x98Nd\xcc\xb0Q\xe3\x81:\x05\xb7^\xd7\xe6\xe6\xbb" + - "\x8e<'\xb1\x11D\x09(\xb5\xcb\xac_\xa9\xdd\x08\xd5" + - "V\xae\xbfu\x17\xced\x97HtE\xd3\x9e\xa9iZ" + - "\xf0\xf5\xe2\xcb\xb6\x8f\xfeP\xad\xa9r\x97u\xa8\xca\xc3" + - "\xd1L\xdf\xec\xd3\xfe\xe5\xa6\xca%\xd6\xab*\xc3m\xdb" + - "\xee\xbf\xf9\xb1\xf5\xfd_\xde\xce\xb2\x05c:\xf4\xe6\xb3" + - "W\xc6\xf7\xd0\xdb\xe8\x89\xa1\xf9\xcd\x8f\xe6V\x9ad\xde" + - "\xd5\x07t\\\xbdr\xed\xdb\xc1\xff~6\\\xab\xee\xe1" + - "\x17j\x02\x8c%V%\x04\x9f\x9f|H~\x1a+\xfe" + - "jz:\xc0\xbbA\x99\xa0\xe2\x94\x0b\xb6\xeb\x0e\xf2\x82" + - "U)U\xf6\x9b\x8dk\xd5*z}Gm\xd7\x9f\xe0" + - "\x9e+5\xae\x11i \x12\xe91\"\x99\xe2\x90\x9b\x18" + - "\x02{\xaa\xe8\x1d.\x9f\xb6\x89\x08IbH\x12b=" + - "\xd4\xf5\xf2S#v\xc1\xf7\xca\x8e\x09H\x8d'\x88b" + - "\xb3\x88X\x0b\xb1\x9b\x98H\xe8=n\xc5\xaa\x96r0" + - "\x81\xb5\xb6\xf2Su\x95\xc1\xb0E\x19k\xf7'V\x1b" + - ";D$\x93\x1c\xb2\x93\xe1|\xe35\xc4\x1f\xc0\x04\x08" + - "B\xabu]\xaf\\\x89\xd7]\x97\x89i9\xd6$\xdc" + - "\xd6B\x96S\x07\xa7O4)!\xea\xea\x09\xef\x0aF" + - "*\x84\x11}\x0c\xa2\x8c\x08\xa9`\xe4u \xfeoD" + - "\x99\x13\xfb\xfa\x89\x89\x01\x1d,\x0e\x1b\xa2\xf8\x8b-\xaa" + - "\xb6A\xef\x09\x1d\xe4\xd0\xaeV\xca\xa1]\x99\xfe'\xd2" + - "U\xab\xb7\xd8j\x0dv\xd3rtk\xd2\x95\xc9\x98\xfa" + - "N\x15\x87\x1d\x1cr\x0f\x83\x00:\x01@d\x8f\x13\xc9" + - "\x0c\x87<\xc0\x10\x9c\x9a\xf6\xec(#ibH\x13\x02" + - "\xbb\xe49\xd3f\xb9H\xbc\xe4!E\x0c)\"\x81^" + - "\xdd\xf1K\xebsU6\xf9\xa4\xfb;\x00\x00\xff\xff\xdc" + - "a-[" + return Process_kill_Results(p.Struct()), err +} + +const schema_9a51e53177277763 = "x\xda|\x921h\x13Q\x18\xc7\xff\xffw/\xbd\x03" + + "=\xc3\xebi\xb4\x82\x08\xdaP\xe8\x10\x13\x8a\x8b \x0d" + + "\x8a\x04\x0bb\x9e\xbbB<\x0f\x0c&&\xe4.$N" + + "\xe2 \xee\x8a\x88\x8a\xe0\"u\x10-\xd5\xa9\xce\xeeR" + + "\x05A7\xc5\xc5\xa1\x88[\x079y\xd7\\<\xa9\xe9" + + "v\x8f\xef\xfb\xfe\xff\xff\xf7\xfb\xae,Y\x95\x15wN" + + "B\xe8rn*^\xef\xdfz\xb6v\xa9\xf4\x0aj\x8f" + + "\x15\xfb\x83\xb9A\xe5\xbb~\x04\xd0\xdb\xe4\x9aGa\x03" + + "\xdeo\xd6\xbc\xa2\xf9\x8a\x1f\xbf__^)\x9c\x7f\x0b" + + "\xb5\x9f@\x8e6\xb0\xe0\x8a#\x04\xbd}b\x11\x8c7" + + "\x1e|\x0cW\xafV\xdeA\x15\x08HS?.\x0e\x12" + + "2~Q+\xcf>}3\xff\x09\xba\xc0\xb4t\xc8\x94" + + "\xe8\x15\x93\xd1\x85\xa9\xe2\xf3\x0f?\x8f~\xde\x16\xe4\xac" + + "X\xf5t\x12\xe4\x9c\xb8\xe3=I\x82\xd4.\x1e[\x99" + + "y\xb9\xbc\x91\xf1\xb9-\xa6\x8d\xcf\xf4\xbd\xbb\xf7\x7f\x9c" + + "\xdc\xf5+\x1b\xb1\xbd\xe5\xd3O|\xbe\xbd\xfe\xe2|]" + + "jnfF\x1f\x9a\xd1r\xdc\xedu\xfc \x0cK\xf4" + + "\x1b\xdd\xeb\xdd\x13g\x86\x8b\x81\xdf\x8f:\xbd:\xa9\xa5" + + "\x95\x03\xc6\xe2LA(5\x0f\xa1rv>\x18\x06~" + + "\x95ur\xacb\xa5*[\"%\xd31{!\x08\xfb" + + "v+\x0a\xb5\xb4$ \x09(\xf7\x14\xa0\x1d\x8bz\xaf" + + "\xe0\xcd\xd10\xd5_\x1c \x15\xb6\xc9\xd6G\xcfk\xcd" + + "V+QmYQ8\xa9i\xd0hF\xe3\xa6\xac\xf5" + + "\x12\xa0w[\xd4\x07\x04\xe3`\xd8\x8cNw\xae\x04\x00" + + "\xe8@\xd0\xc9\x982\xd5;\x9c\xbc\x0d\x10'\x01\x92\xc2" + + "dz^U1@\x8a69\xbe\x11\xd3\x9fB\xcd\x98" + + "\x9ak\xe7M\x9e*\xf3&\xfb\x7f\x99\xfd\xb3\\\xbd\xd1" + + "k\xb4\x19\xee\xcc\xd54Y\xed\x89\xbb]\xbe\x11\x05\xfe" + + "h7\x17\x82\xeed\xa0\x09\xab\x91\xe7\x9f\x00\x00\x00\xff" + + "\xff8\xaa\xe7q" func RegisterSchema(reg *schemas.Registry) { reg.Register(&schemas.Schema{ String: schema_9a51e53177277763, Nodes: []uint64{ - 0x9d6074459fa0602b, 0xaf2e5ebaa58175d2, 0xbb4f16b0a7d2d09b, 0xc53168b273d497ee, - 0xd22f75df06c187e8, 0xd72ab4a0243047ac, 0xda23f0d3a8250633, 0xeea7ae19b02f5d47, diff --git a/internal/cmd/cluster/process.go b/internal/cmd/cluster/process.go index 9c82edc4..243aa2b5 100644 --- a/internal/cmd/cluster/process.go +++ b/internal/cmd/cluster/process.go @@ -32,14 +32,9 @@ func runAction() cli.ActionFunc { executor, release := node.Executor(ctx) defer release() - proc, release := executor.Spawn(ctx, src) + proc, release := executor.Exec(ctx, src) defer release() - if err := proc.Start(ctx); err != nil { - return err - } - defer proc.Stop(ctx) - return proc.Wait(ctx) } } diff --git a/internal/cmd/run/run.go b/internal/cmd/run/run.go new file mode 100644 index 00000000..9b83df95 --- /dev/null +++ b/internal/cmd/run/run.go @@ -0,0 +1,78 @@ +package run + +import ( + "crypto/rand" + "errors" + "io" + "os" + + "github.com/stealthrocket/wazergo" + "github.com/tetratelabs/wazero" + "github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1" + "github.com/urfave/cli/v2" + "github.com/wetware/ww/pkg/csp/proc" +) + +func Command() *cli.Command { + return &cli.Command{ + Name: "run", + Usage: "execute a local webassembly process", + Before: setup(), + After: teardown(), + Action: run(), + } +} + +var ( + r wazero.Runtime + h *wazergo.ModuleInstance[*proc.Module] +) + +func setup() cli.BeforeFunc { + return func(c *cli.Context) error { + r = wazero.NewRuntime(c.Context) + h = proc.BindModule(c.Context, r) + wasi_snapshot_preview1.MustInstantiate(c.Context, r) + return nil + } +} + +func teardown() cli.AfterFunc { + return func(c *cli.Context) error { + return r.Close(c.Context) + } +} + +func run() cli.ActionFunc { + return func(c *cli.Context) error { + b, err := bytecode(c) + if err != nil { + return err + } + + module, err := r.InstantiateWithConfig(c.Context, b, wazero.NewModuleConfig(). + WithRandSource(rand.Reader). + WithStartFunctions(). // disable auto-calling of _start + WithStdout(c.App.Writer). + WithStderr(c.App.ErrWriter)) + if err != nil { + return err + } + + fn := module.ExportedFunction("_start") + if fn == nil { + return errors.New("ww: missing export: _start") + } + + _, err = fn.Call(wazergo.WithModuleInstance(c.Context, h)) + return err + } +} + +func bytecode(c *cli.Context) ([]byte, error) { + if c.Args().Len() > 0 { + return os.ReadFile(c.Args().First()) // file path + } + + return io.ReadAll(c.App.Reader) // stdin +} diff --git a/pkg/csp/executor.go b/pkg/csp/executor.go index b9b0c94f..b5243217 100644 --- a/pkg/csp/executor.go +++ b/pkg/csp/executor.go @@ -4,14 +4,16 @@ import ( "context" "crypto/rand" "encoding/hex" - "fmt" + "errors" capnp "capnproto.org/go/capnp/v3" + "github.com/stealthrocket/wazergo" "github.com/tetratelabs/wazero" "lukechampine.com/blake3" wasm "github.com/tetratelabs/wazero/api" api "github.com/wetware/ww/internal/api/process" + "github.com/wetware/ww/pkg/csp/proc" ) // ByteCode is a representation of arbitrary executable data. @@ -39,79 +41,98 @@ func (ex Executor) Release() { capnp.Client(ex).Release() } -func (ex Executor) Spawn(ctx context.Context, src []byte) (Proc, capnp.ReleaseFunc) { - f, release := api.Executor(ex).Spawn(ctx, func(ps api.Executor_spawn_Params) error { - return ps.SetByteCode(src) +func (ex Executor) Exec(ctx context.Context, src []byte) (Proc, capnp.ReleaseFunc) { + f, release := api.Executor(ex).Exec(ctx, func(ps api.Executor_exec_Params) error { + return ps.SetBytecode(src) }) return Proc(f.Process()), release } -// Server is the main Executor implementation. It spawns WebAssembly- -// based processes. The zero-value Server panics. -type Server struct { - Runtime wazero.Runtime +// Runtime is the main Executor implementation. It spawns WebAssembly- +// based processes. The zero-value Runtime panics. +type Runtime struct { + Runtime wazero.Runtime + HostModule *wazergo.ModuleInstance[*proc.Module] } // Executor provides the Executor capability. -func (wx Server) Executor() Executor { - return Executor(api.Executor_ServerToClient(wx)) +func (r Runtime) Executor() Executor { + return Executor(api.Executor_ServerToClient(r)) } -// Spawn a process by creating a process server and converting it into -// a capability as a response to the call. -func (wx Server) Spawn(ctx context.Context, call api.Executor_spawn) error { +func (r Runtime) Exec(ctx context.Context, call api.Executor_exec) error { res, err := call.AllocResults() if err != nil { return err } - mod, err := wx.loadModule(ctx, call.Args()) + p, err := r.mkproc(ctx, call.Args()) if err != nil { return err } - p, err := wx.mkproc(ctx, mod, call.Args()) - if err == nil { - err = res.SetProcess(api.Process_ServerToClient(p)) - } - - return err + return res.SetProcess(api.Process_ServerToClient(p)) } -func (wx Server) mkproc(ctx context.Context, mod wasm.Module, args api.Executor_spawn_Params) (*process, error) { - name, err := args.EntryPoint() +func (r Runtime) mkproc(ctx context.Context, args api.Executor_exec_Params) (*process, error) { + mod, err := r.mkmod(ctx, args) if err != nil { return nil, err } - var proc process - if proc.fn = mod.ExportedFunction(name); proc.fn == nil { - err = fmt.Errorf("module %s: %s not found", mod.Name(), name) + fn := mod.ExportedFunction("_start") + if fn == nil { + return nil, errors.New("ww: missing export: _start") } - return &proc, err + done, cancel := r.spawn(fn) + return &process{ + done: done, + cancel: cancel, + }, nil } -func (wx Server) loadModule(ctx context.Context, args api.Executor_spawn_Params) (wasm.Module, error) { - bc, err := args.ByteCode() +func (r Runtime) mkmod(ctx context.Context, args api.Executor_exec_Params) (wasm.Module, error) { + bc, err := args.Bytecode() if err != nil { return nil, err } name := ByteCode(bc).String() - config := wazero. - NewModuleConfig(). - WithName(name). - WithRandSource(rand.Reader) - if mod := wx.Runtime.Module(name); mod != nil { - return mod, nil - } - - module, err := wx.Runtime.CompileModule(ctx, bc) + // TODO(perf): cache compiled modules so that we can instantiate module + // instances for concurrent use. + module, err := r.Runtime.CompileModule(ctx, bc) if err != nil { return nil, err } - return wx.Runtime.InstantiateModule(ctx, module, config) + return r.Runtime.InstantiateModule(ctx, module, wazero. + NewModuleConfig(). + WithName(name). + WithStartFunctions(). // disable automatic calling of _start (main) + WithRandSource(rand.Reader)) +} + +func (r Runtime) spawn(fn wasm.Function) (<-chan execResult, context.CancelFunc) { + out := make(chan execResult, 1) + + // NOTE: we use the runtime context rather than the context passed into the + // rpc handler. This ensures that a process can continue to run after + // the rpc handler has returned. Note also that this context is bound + // to the application lifetime, so processes cannot block a shutdown. + ctx, cancel := context.WithCancel(context.Background()) + + go func() { + defer close(out) + defer cancel() + + vs, err := fn.Call(wazergo.WithModuleInstance(ctx, r.HostModule)) + out <- execResult{ + Values: vs, + Err: err, + } + }() + + return out, cancel } diff --git a/pkg/csp/executor_test.go b/pkg/csp/executor_test.go index 4e30b28c..153992a4 100644 --- a/pkg/csp/executor_test.go +++ b/pkg/csp/executor_test.go @@ -1,46 +1,46 @@ package csp_test -import ( - "context" - "os" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "github.com/tetratelabs/wazero" - "github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1" - "github.com/tetratelabs/wazero/sys" - "github.com/wetware/ww/pkg/csp" -) - -func TestExecutor(t *testing.T) { - t.Parallel() - - r := wazero.NewRuntime(context.Background()) - wasi_snapshot_preview1.MustInstantiate(context.Background(), r) - - exec := csp.Server{Runtime: r}.Executor() - defer exec.Release() - - proc, release := exec.Spawn(context.Background(), testdata()) - defer release() - - err := proc.Start(context.Background()) - require.NoError(t, err, "should start process") - - err = proc.Wait(context.Background()) - require.Error(t, err, "should return an error from process") - - ee, ok := err.(*sys.ExitError) - require.True(t, ok, "should return sys.ExitError") - assert.Equal(t, uint32(99), ee.ExitCode()) -} - -func testdata() []byte { - b, err := os.ReadFile("testdata/main.wasm") - if err != nil { - panic(err) - } - - return b -} +// import ( +// "context" +// "os" +// "testing" + +// "github.com/stretchr/testify/assert" +// "github.com/stretchr/testify/require" +// "github.com/tetratelabs/wazero" +// "github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1" +// "github.com/tetratelabs/wazero/sys" +// "github.com/wetware/ww/pkg/csp" +// ) + +// func TestExecutor(t *testing.T) { +// t.Parallel() + +// r := wazero.NewRuntime(context.Background()) +// wasi_snapshot_preview1.MustInstantiate(context.Background(), r) + +// exec := csp.Runtime{Runtime: r}.Executor() +// defer exec.Release() + +// proc, release := exec.Spawn(context.Background(), testdata()) +// defer release() + +// err := proc.Start(context.Background()) +// require.NoError(t, err, "should start process") + +// err = proc.Wait(context.Background()) +// require.Error(t, err, "should return an error from process") + +// ee, ok := err.(*sys.ExitError) +// require.True(t, ok, "should return sys.ExitError") +// assert.Equal(t, uint32(99), ee.ExitCode()) +// } + +// func testdata() []byte { +// b, err := os.ReadFile("testdata/main.wasm") +// if err != nil { +// panic(err) +// } + +// return b +// } diff --git a/pkg/csp/proc.go b/pkg/csp/proc.go index 1cab4271..f1e270d2 100644 --- a/pkg/csp/proc.go +++ b/pkg/csp/proc.go @@ -3,10 +3,8 @@ package csp import ( "context" "errors" - "sync/atomic" capnp "capnproto.org/go/capnp/v3" - wasm "github.com/tetratelabs/wazero/api" "github.com/tetratelabs/wazero/sys" casm "github.com/wetware/casm/pkg" @@ -26,18 +24,10 @@ func (p Proc) AddRef() Proc { func (p Proc) Release() { capnp.Client(p).Release() - -} - -func (p Proc) Start(ctx context.Context) error { - f, release := api.Process(p).Start(ctx, nil) - defer release() - - return casm.Future(f).Await(ctx) } -func (p Proc) Stop(ctx context.Context) error { - f, release := api.Process(p).Stop(ctx, nil) +func (p Proc) Kill(ctx context.Context) error { + f, release := api.Process(p).Kill(ctx, nil) defer release() return casm.Future(f).Await(ctx) @@ -61,110 +51,36 @@ func (p Proc) Wait(ctx context.Context) error { // process is the main implementation of the Process capability. type process struct { - fn wasm.Function - handle procHandle -} - -// Stop calls the runtime cancellation function. -func (p *process) Stop(context.Context, api.Process_stop) error { - state := p.handle.Load() - if state.Err == nil { - state.Cancel() - } - - return state.Err + done <-chan execResult + cancel context.CancelFunc + result execResult } -// Start the process in the background. -func (p *process) Start(_ context.Context, call api.Process_start) error { - state := p.handle.Load() - if state.Err != ErrNotStarted { - return state.Err - } - - p.handle.Exec(p.fn) +func (p process) Kill(context.Context, api.Process_kill) error { + p.cancel() return nil } -// Wait for the process to finish running. func (p *process) Wait(ctx context.Context, call api.Process_wait) error { - state := p.handle.Load() - if state.Err == ErrNotStarted { - return state.Err - } - - results, err := call.AllocResults() - if err != nil { - return err - } - - call.Go() - select { + case res, ok := <-p.done: + if ok { + p.result = res + } + case <-ctx.Done(): return ctx.Err() - case <-state.Ctx.Done(): - return p.handle.Bind(results) } -} - -// procHandle encapsulates all the runtime state of a process. Its -// methods are safe for concurrent access. -type procHandle atomic.Pointer[state] - -// Exec sets the current state to ErrRunning, calls the function, and -// then sets the current state to the resulting error. -func (as *procHandle) Exec(fn wasm.Function) { - ctx, cancel := context.WithCancel(context.Background()) - - // set "running" state - (*atomic.Pointer[state])(as).Store(&state{ - Ctx: ctx, - Cancel: cancel, - Err: ErrRunning, - }) - - go func() { - defer cancel() - - // block until function call completes - _, err := fn.Call(ctx) - - // call entrypoint function & set "finished" state - (*atomic.Pointer[state])(as).Store(&state{ - Ctx: ctx, - Cancel: cancel, - Err: err, - }) - }() -} -// Bind the error from the entrypoint function to the results struct. -// Callers MUST NOT call Bind until the function has returned. -func (as *procHandle) Bind(res api.Process_wait_Results) error { - if state := as.Load(); state.Err != nil { - code := state.Err.(*sys.ExitError).ExitCode() - res.SetExitCode(code) - } - - return nil -} - -// Load the current state atomically. The resulting resulting state -// defaults to ErrNotStarted. -func (as *procHandle) Load() state { - if s := (*atomic.Pointer[state])(as).Load(); s != nil { - return *s + res, err := call.AllocResults() + if err != nil { + res.SetExitCode(err.(*sys.ExitError).ExitCode()) } - return state{ - Cancel: func() {}, - Err: ErrNotStarted, - } + return err } -type state struct { - Ctx context.Context - Cancel context.CancelFunc +type execResult struct { + Values []uint64 Err error } diff --git a/pkg/csp/proc/proc.go b/pkg/csp/proc/proc.go new file mode 100644 index 00000000..667c8dfb --- /dev/null +++ b/pkg/csp/proc/proc.go @@ -0,0 +1,50 @@ +// Package proc provides the WebAssembly host module for Wetware processes +package proc + +import ( + "context" + + "github.com/stealthrocket/wazergo" + "github.com/stealthrocket/wazergo/types" + wasm "github.com/tetratelabs/wazero" +) + +var fs wazergo.HostModule[*Module] = functions{ + "__test": wazergo.F2((*Module).Add), +} + +// BindModule instantiates a host module instance and binds it to the supplied +// runtime. The returned module instance is bound to the lifetime of r. +func BindModule(ctx context.Context, r wasm.Runtime) *wazergo.ModuleInstance[*Module] { + // We use BindModule to avoid exporting fs as a public variable, since this + // would allow users to mutate it. + return wazergo.MustInstantiate(ctx, r, fs) +} + +type functions wazergo.Functions[*Module] + +func (functions) Name() string { + return "ww" +} + +func (f functions) Functions() wazergo.Functions[*Module] { + return (wazergo.Functions[*Module])(f) +} + +func (f functions) Instantiate(ctx context.Context, opts ...Option) (*Module, error) { + module := &Module{} + wazergo.Configure(module, opts...) + return module, nil +} + +type Option = wazergo.Option[*Module] + +type Module struct{} + +func (m Module) Close(context.Context) error { + return nil +} + +func (m Module) Add(ctx context.Context, a, b types.Uint32) types.Uint32 { + return a + b +} diff --git a/pkg/server/config.go b/pkg/server/config.go index d41105b9..29d46bbf 100644 --- a/pkg/server/config.go +++ b/pkg/server/config.go @@ -13,6 +13,8 @@ import ( "github.com/wetware/casm/pkg/cluster/pulse" "github.com/wetware/casm/pkg/cluster/routing" "github.com/wetware/casm/pkg/debug" + "github.com/wetware/ww/pkg/csp" + "github.com/wetware/ww/pkg/csp/proc" ) type ClusterConfig struct { @@ -65,7 +67,7 @@ type RuntimeConfig struct { Config wazero.RuntimeConfig `optional:"true"` } -func (rc RuntimeConfig) New() wazero.Runtime { +func (rc RuntimeConfig) New() csp.Runtime { if rc.Ctx == nil { rc.Ctx = context.Background() } @@ -76,7 +78,11 @@ func (rc RuntimeConfig) New() wazero.Runtime { r := wazero.NewRuntimeWithConfig(rc.Ctx, rc.Config) wasi_snapshot_preview1.MustInstantiate(rc.Ctx, r) - return r + + return csp.Runtime{ + Runtime: r, + HostModule: proc.BindModule(rc.Ctx, r), + } } type DebugConfig struct { diff --git a/pkg/server/server.go b/pkg/server/server.go index df737fcc..d8e68d03 100644 --- a/pkg/server/server.go +++ b/pkg/server/server.go @@ -11,7 +11,6 @@ import ( casm "github.com/wetware/casm/pkg" "github.com/wetware/casm/pkg/cluster" "github.com/wetware/ww/pkg/anchor" - "github.com/wetware/ww/pkg/csp" "github.com/wetware/ww/pkg/host" "github.com/wetware/ww/pkg/pubsub" ) @@ -71,7 +70,7 @@ func (j Joiner) Join(vat casm.Vat, r Router) (*Node, error) { PubSubProvider: j.pubsub(vat.Logger, r), AnchorProvider: j.anchor(), DebugProvider: j.Debugger.New(), - ExecutorProvider: j.executor(), + ExecutorProvider: j.Runtime.New(), }) return &Node{ @@ -90,9 +89,3 @@ func (j Joiner) pubsub(log log.Logger, router pubsub.TopicJoiner) *pubsub.Server func (j Joiner) anchor() anchor.Server { return anchor.Root() } - -func (j Joiner) executor() csp.Server { - return csp.Server{ - Runtime: j.Runtime.New(), - } -}