1 package adhoc
2
3 import (
4 "bytes"
5 "context"
6 _ "embed"
7 "errors"
8 "fmt"
9 "math"
10 "runtime"
11 "strconv"
12 "strings"
13 "testing"
14 "time"
15 "unsafe"
16
17 "github.com/tetratelabs/wazero"
18 "github.com/tetratelabs/wazero/api"
19 "github.com/tetratelabs/wazero/experimental"
20 "github.com/tetratelabs/wazero/experimental/logging"
21 "github.com/tetratelabs/wazero/experimental/opt"
22 "github.com/tetratelabs/wazero/experimental/table"
23 "github.com/tetratelabs/wazero/internal/leb128"
24 "github.com/tetratelabs/wazero/internal/platform"
25 "github.com/tetratelabs/wazero/internal/testing/binaryencoding"
26 "github.com/tetratelabs/wazero/internal/testing/proxy"
27 "github.com/tetratelabs/wazero/internal/testing/require"
28 "github.com/tetratelabs/wazero/internal/wasm"
29 "github.com/tetratelabs/wazero/internal/wasm/binary"
30 "github.com/tetratelabs/wazero/internal/wasmdebug"
31 "github.com/tetratelabs/wazero/internal/wasmruntime"
32 "github.com/tetratelabs/wazero/sys"
33 )
34
35 type testCase struct {
36 f func(t *testing.T, r wazero.Runtime)
37 wazevoSkip bool
38 }
39
40 var tests = map[string]testCase{
41 "imported mutable global": {f: testImportedMutableGlobalUpdate},
42 "huge stack": {f: testHugeStack},
43 "unreachable": {f: testUnreachable},
44 "recursive entry": {f: testRecursiveEntry},
45 "host func memory": {f: testHostFuncMemory},
46 "host function with context parameter": {f: testHostFunctionContextParameter},
47 "host function with nested context": {f: testNestedGoContext},
48 "host function with numeric parameter": {f: testHostFunctionNumericParameter},
49 "close module with in-flight calls": {f: testCloseInFlight},
50 "multiple instantiation from same source": {f: testMultipleInstantiation},
51 "exported function that grows memory": {f: testMemOps},
52 "import functions with reference type in signature": {f: testReftypeImports},
53 "overflow integer addition": {f: testOverflow},
54 "un-signed extend global": {f: testGlobalExtend},
55 "user-defined primitive in host func": {f: testUserDefinedPrimitiveHostFunc},
56 "ensures invocations terminate on module close": {f: testEnsureTerminationOnClose},
57 "call host function indirectly": {f: callHostFunctionIndirect},
58 "lookup function": {f: testLookupFunction},
59 "memory grow in recursive call": {f: testMemoryGrowInRecursiveCall},
60 "call": {f: testCall},
61 "module memory": {f: testModuleMemory},
62 "two indirection to host": {f: testTwoIndirection},
63 "before listener globals": {f: testBeforeListenerGlobals},
64 "before listener stack iterator": {f: testBeforeListenerStackIterator},
65 "before listener stack iterator offsets": {f: testListenerStackIteratorOffset},
66 "many params many results / doubler": {f: testManyParamsResultsDoubler},
67 "many params many results / doubler / listener": {f: testManyParamsResultsDoublerListener},
68 "many params many results / call_many_consts": {f: testManyParamsResultsCallManyConsts},
69 "many params many results / call_many_consts / listener": {f: testManyParamsResultsCallManyConstsListener},
70 "many params many results / swapper": {f: testManyParamsResultsSwapper},
71 "many params many results / swapper / listener": {f: testManyParamsResultsSwapperListener},
72 "many params many results / main": {f: testManyParamsResultsMain},
73 "many params many results / main / listener": {f: testManyParamsResultsMainListener},
74 "many params many results / call_many_consts_and_pick_last_vector": {f: testManyParamsResultsCallManyConstsAndPickLastVector},
75 "many params many results / call_many_consts_and_pick_last_vector / listener": {f: testManyParamsResultsCallManyConstsAndPickLastVectorListener},
76 }
77
78 func TestEngineCompiler(t *testing.T) {
79 if !platform.CompilerSupported() {
80 t.Skip()
81 }
82 runAllTests(t, tests, wazero.NewRuntimeConfigCompiler().WithCloseOnContextDone(true), false)
83 }
84
85 func TestEngineInterpreter(t *testing.T) {
86 runAllTests(t, tests, wazero.NewRuntimeConfigInterpreter().WithCloseOnContextDone(true), false)
87 }
88
89
90 var testCtx = context.WithValue(context.Background(), struct{}{}, "arbitrary")
91
92 const i32, i64, f32, f64, v128 = wasm.ValueTypeI32, wasm.ValueTypeI64, wasm.ValueTypeF32, wasm.ValueTypeF64, wasm.ValueTypeV128
93
94 var memoryCapacityPages = uint32(2)
95
96 func TestEngineWazevo(t *testing.T) {
97 if runtime.GOARCH != "arm64" {
98 t.Skip()
99 }
100 config := opt.NewRuntimeConfigOptimizingCompiler()
101 runAllTests(t, tests, config.WithCloseOnContextDone(true), true)
102 }
103
104 func runAllTests(t *testing.T, tests map[string]testCase, config wazero.RuntimeConfig, isWazevo bool) {
105 for name, tc := range tests {
106 name := name
107 tc := tc
108 if isWazevo && tc.wazevoSkip {
109 t.Logf("skipping %s because it is not supported by wazevo", name)
110 continue
111 }
112 t.Run(name, func(t *testing.T) {
113 t.Parallel()
114 tc.f(t, wazero.NewRuntimeWithConfig(testCtx, config))
115 })
116 }
117 }
118
119 var (
120
121 unreachableWasm []byte
122
123 recursiveWasm []byte
124
125 hostMemoryWasm []byte
126
127 hugestackWasm []byte
128
129 memoryWasm []byte
130
131 reftypeImportsWasm []byte
132
133 overflowWasm []byte
134
135 globalExtendWasm []byte
136
137 infiniteLoopWasm []byte
138 )
139
140 func testEnsureTerminationOnClose(t *testing.T, r wazero.Runtime) {
141 compiled, err := r.CompileModule(context.Background(), infiniteLoopWasm)
142 require.NoError(t, err)
143
144 newInfiniteLoopFn := func(t *testing.T) (m api.Module, infinite api.Function) {
145 var err error
146 m, err = r.InstantiateModule(context.Background(), compiled, wazero.NewModuleConfig().WithName(t.Name()))
147 require.NoError(t, err)
148 infinite = m.ExportedFunction("infinite_loop")
149 require.NotNil(t, infinite)
150 return
151 }
152
153 t.Run("context cancel", func(t *testing.T) {
154 _, infinite := newInfiniteLoopFn(t)
155 ctx, cancel := context.WithCancel(context.Background())
156 go func() {
157 time.Sleep(time.Second)
158 cancel()
159 }()
160 _, err = infinite.Call(ctx)
161 require.Error(t, err)
162 require.Contains(t, err.Error(), "module closed with context canceled")
163 })
164
165 t.Run("context cancel in advance", func(t *testing.T) {
166 _, infinite := newInfiniteLoopFn(t)
167 ctx, cancel := context.WithCancel(context.Background())
168 cancel()
169 _, err = infinite.Call(ctx)
170 require.Error(t, err)
171 require.Contains(t, err.Error(), "module closed with context canceled")
172 })
173
174 t.Run("context timeout", func(t *testing.T) {
175 _, infinite := newInfiniteLoopFn(t)
176 ctx, cancel := context.WithTimeout(context.Background(), time.Second)
177 defer cancel()
178 _, err = infinite.Call(ctx)
179 require.Error(t, err)
180 require.Contains(t, err.Error(), "module closed with context deadline exceeded")
181 })
182
183 t.Run("explicit close of module", func(t *testing.T) {
184 module, infinite := newInfiniteLoopFn(t)
185 go func() {
186 time.Sleep(time.Second)
187 require.NoError(t, module.CloseWithExitCode(context.Background(), 2))
188 }()
189 _, err = infinite.Call(context.Background())
190 require.Error(t, err)
191 require.Contains(t, err.Error(), "module closed with exit_code(2)")
192 })
193 }
194
195 func testUserDefinedPrimitiveHostFunc(t *testing.T, r wazero.Runtime) {
196 type u32 uint32
197 type u64 uint64
198 type f32 float32
199 type f64 float64
200
201 const fn = "fn"
202 hostCompiled, err := r.NewHostModuleBuilder("host").NewFunctionBuilder().
203 WithFunc(func(u1 u32, u2 u64, f1 f32, f2 f64) u64 {
204 return u64(u1) + u2 + u64(math.Float32bits(float32(f1))) + u64(math.Float64bits(float64(f2)))
205 }).Export(fn).Compile(testCtx)
206 require.NoError(t, err)
207
208 _, err = r.InstantiateModule(testCtx, hostCompiled, wazero.NewModuleConfig())
209 require.NoError(t, err)
210
211 proxyBin := proxy.NewModuleBinary("host", hostCompiled)
212
213 mod, err := r.Instantiate(testCtx, proxyBin)
214 require.NoError(t, err)
215
216 f := mod.ExportedFunction(fn)
217 require.NotNil(t, f)
218
219 const u1, u2, f1, f2 = 1, 2, float32(1234.123), 5431.123
220 res, err := f.Call(context.Background(), uint64(u1), uint64(u2), uint64(math.Float32bits(f1)), math.Float64bits(f2))
221 require.NoError(t, err)
222 require.Equal(t, res[0], uint64(u1)+uint64(u2)+uint64(math.Float32bits(f1))+math.Float64bits(f2))
223 }
224
225 func testReftypeImports(t *testing.T, r wazero.Runtime) {
226 type dog struct {
227 name string
228 }
229
230 hostObj := &dog{name: "hello"}
231 host, err := r.NewHostModuleBuilder("host").
232 NewFunctionBuilder().
233 WithFunc(func(ctx context.Context, externrefFromRefNull uintptr) uintptr {
234 require.Zero(t, externrefFromRefNull)
235 return uintptr(unsafe.Pointer(hostObj))
236 }).
237 Export("externref").
238 Instantiate(testCtx)
239 require.NoError(t, err)
240 defer func() {
241 require.NoError(t, host.Close(testCtx))
242 }()
243
244 module, err := r.Instantiate(testCtx, reftypeImportsWasm)
245 require.NoError(t, err)
246 defer func() {
247 require.NoError(t, module.Close(testCtx))
248 }()
249
250 actual, err := module.ExportedFunction("get_externref_by_host").Call(testCtx)
251 require.NoError(t, err)
252
253
254 require.Equal(t, uintptr(unsafe.Pointer(hostObj)), uintptr(actual[0]))
255 }
256
257 func testHugeStack(t *testing.T, r wazero.Runtime) {
258 module, err := r.Instantiate(testCtx, hugestackWasm)
259 require.NoError(t, err)
260 defer func() {
261 require.NoError(t, module.Close(testCtx))
262 }()
263
264 fn := module.ExportedFunction("main")
265 require.NotNil(t, fn)
266
267 res, err := fn.Call(testCtx, 0, 0, 0, 0, 0, 0)
268 require.NoError(t, err)
269
270 const resultNumInUint64 = 180
271 require.Equal(t, resultNumInUint64, len(res))
272 for i := uint64(1); i <= resultNumInUint64; i++ {
273 require.Equal(t, i, res[i-1])
274 }
275 }
276
277
278
279 func testOverflow(t *testing.T, r wazero.Runtime) {
280 module, err := r.Instantiate(testCtx, overflowWasm)
281 require.NoError(t, err)
282 defer func() {
283 require.NoError(t, module.Close(testCtx))
284 }()
285
286 for _, name := range []string{"i32", "i64"} {
287 i32 := module.ExportedFunction(name)
288 require.NotNil(t, i32)
289
290 res, err := i32.Call(testCtx)
291 require.NoError(t, err)
292
293 require.Equal(t, uint64(1), res[0])
294 }
295 }
296
297
298 func testGlobalExtend(t *testing.T, r wazero.Runtime) {
299 module, err := r.Instantiate(testCtx, globalExtendWasm)
300 require.NoError(t, err)
301 defer func() {
302 require.NoError(t, module.Close(testCtx))
303 }()
304
305 extend := module.ExportedFunction("extend")
306 require.NotNil(t, extend)
307
308 res, err := extend.Call(testCtx)
309 require.NoError(t, err)
310
311 require.Equal(t, uint64(0xffff_ffff), res[0])
312 }
313
314 func testUnreachable(t *testing.T, r wazero.Runtime) {
315 callUnreachable := func() {
316 panic("panic in host function")
317 }
318
319 _, err := r.NewHostModuleBuilder("host").
320 NewFunctionBuilder().WithFunc(callUnreachable).Export("cause_unreachable").
321 Instantiate(testCtx)
322 require.NoError(t, err)
323
324 module, err := r.Instantiate(testCtx, unreachableWasm)
325 require.NoError(t, err)
326 defer func() {
327 require.NoError(t, module.Close(testCtx))
328 }()
329
330 _, err = module.ExportedFunction("main").Call(testCtx)
331 exp := `panic in host function (recovered by wazero)
332 wasm stack trace:
333 host.cause_unreachable()
334 .two()
335 .one()
336 .main()`
337 require.Equal(t, exp, err.Error())
338 }
339
340 func testRecursiveEntry(t *testing.T, r wazero.Runtime) {
341 hostfunc := func(ctx context.Context, mod api.Module) {
342 _, err := mod.ExportedFunction("called_by_host_func").Call(testCtx)
343 require.NoError(t, err)
344 }
345
346 _, err := r.NewHostModuleBuilder("env").
347 NewFunctionBuilder().WithFunc(hostfunc).Export("host_func").
348 Instantiate(testCtx)
349 require.NoError(t, err)
350
351 module, err := r.Instantiate(testCtx, recursiveWasm)
352 require.NoError(t, err)
353 defer func() {
354 require.NoError(t, module.Close(testCtx))
355 }()
356
357 _, err = module.ExportedFunction("main").Call(testCtx, 1)
358 require.NoError(t, err)
359 }
360
361
362 func testHostFuncMemory(t *testing.T, r wazero.Runtime) {
363 var memory *wasm.MemoryInstance
364 storeInt := func(ctx context.Context, m api.Module, offset uint32, val uint64) uint32 {
365 if !m.Memory().WriteUint64Le(offset, val) {
366 return 1
367 }
368
369 memory = m.Memory().(*wasm.MemoryInstance)
370 return 0
371 }
372
373 host, err := r.NewHostModuleBuilder("host").
374 NewFunctionBuilder().WithFunc(storeInt).Export("store_int").
375 Instantiate(testCtx)
376 require.NoError(t, err)
377 defer func() {
378 require.NoError(t, host.Close(testCtx))
379 }()
380
381 module, err := r.Instantiate(testCtx, hostMemoryWasm)
382 require.NoError(t, err)
383 defer func() {
384 require.NoError(t, module.Close(testCtx))
385 }()
386
387
388 fn := module.ExportedFunction("store_int")
389 results, err := fn.Call(testCtx, 1, math.MaxUint64)
390 require.NoError(t, err)
391 require.Equal(t, uint64(0), results[0])
392
393
394 require.Equal(t, []byte{0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0}, memory.Buffer[0:10])
395 }
396
397
398 func testNestedGoContext(t *testing.T, r wazero.Runtime) {
399 nestedCtx := context.WithValue(context.Background(), struct{}{}, "nested")
400
401 importedName := t.Name() + "-imported"
402 importingName := t.Name() + "-importing"
403
404 var importing api.Module
405
406 imported, err := r.NewHostModuleBuilder(importedName).
407 NewFunctionBuilder().
408 WithFunc(func(ctx context.Context, p uint32) uint32 {
409
410 require.Equal(t, nestedCtx, ctx)
411 return p + 1
412 }).
413 Export("inner").
414 NewFunctionBuilder().
415 WithFunc(func(ctx context.Context, module api.Module, p uint32) uint32 {
416 require.Equal(t, testCtx, ctx)
417 results, err := module.ExportedFunction("inner").Call(nestedCtx, uint64(p))
418 require.NoError(t, err)
419 return uint32(results[0]) + 1
420 }).
421 Export("outer").
422 Instantiate(testCtx)
423 require.NoError(t, err)
424 defer func() {
425 require.NoError(t, imported.Close(testCtx))
426 }()
427
428
429 importing, err = r.Instantiate(testCtx, callOuterInnerWasm(t, importedName, importingName))
430 require.NoError(t, err)
431 defer func() {
432 require.NoError(t, importing.Close(testCtx))
433 }()
434
435 input := uint64(math.MaxUint32 - 2)
436 results, err := importing.ExportedFunction("call->outer").Call(testCtx, input)
437 require.NoError(t, err)
438 require.Equal(t, uint64(math.MaxUint32), results[0])
439 }
440
441
442 func testHostFunctionContextParameter(t *testing.T, r wazero.Runtime) {
443 importedName := t.Name() + "-imported"
444 importingName := t.Name() + "-importing"
445
446 var importing api.Module
447 fns := map[string]interface{}{
448 "ctx": func(ctx context.Context, p uint32) uint32 {
449 require.Equal(t, testCtx, ctx)
450 return p + 1
451 },
452 "ctx mod": func(ctx context.Context, module api.Module, p uint32) uint32 {
453 require.Equal(t, importing, module)
454 return p + 1
455 },
456 }
457
458 for test := range fns {
459 t.Run(test, func(t *testing.T) {
460 imported, err := r.NewHostModuleBuilder(importedName).
461 NewFunctionBuilder().WithFunc(fns[test]).Export("return_input").
462 Instantiate(testCtx)
463 require.NoError(t, err)
464 defer func() {
465 require.NoError(t, imported.Close(testCtx))
466 }()
467
468
469 importing, err = r.Instantiate(testCtx,
470 callReturnImportWasm(t, importedName, importingName, i32))
471 require.NoError(t, err)
472 defer func() {
473 require.NoError(t, importing.Close(testCtx))
474 }()
475
476 results, err := importing.ExportedFunction("call_return_input").Call(testCtx, math.MaxUint32-1)
477 require.NoError(t, err)
478 require.Equal(t, uint64(math.MaxUint32), results[0])
479 })
480 }
481 }
482
483
484 func testHostFunctionNumericParameter(t *testing.T, r wazero.Runtime) {
485 importedName := t.Name() + "-imported"
486 importingName := t.Name() + "-importing"
487
488 fns := map[string]interface{}{
489 "i32": func(ctx context.Context, p uint32) uint32 {
490 return p + 1
491 },
492 "i64": func(ctx context.Context, p uint64) uint64 {
493 return p + 1
494 },
495 "f32": func(ctx context.Context, p float32) float32 {
496 return p + 1
497 },
498 "f64": func(ctx context.Context, p float64) float64 {
499 return p + 1
500 },
501 }
502
503 for _, test := range []struct {
504 name string
505 vt wasm.ValueType
506 input, expected uint64
507 }{
508 {
509 name: "i32",
510 vt: i32,
511 input: math.MaxUint32 - 1,
512 expected: math.MaxUint32,
513 },
514 {
515 name: "i64",
516 vt: i64,
517 input: math.MaxUint64 - 1,
518 expected: math.MaxUint64,
519 },
520 {
521 name: "f32",
522 vt: wasm.ValueTypeF32,
523 input: api.EncodeF32(math.MaxFloat32 - 1),
524 expected: api.EncodeF32(math.MaxFloat32),
525 },
526 {
527 name: "f64",
528 vt: wasm.ValueTypeF64,
529 input: api.EncodeF64(math.MaxFloat64 - 1),
530 expected: api.EncodeF64(math.MaxFloat64),
531 },
532 } {
533 t.Run(test.name, func(t *testing.T) {
534 imported, err := r.NewHostModuleBuilder(importedName).
535 NewFunctionBuilder().WithFunc(fns[test.name]).Export("return_input").
536 Instantiate(testCtx)
537 require.NoError(t, err)
538 defer func() {
539 require.NoError(t, imported.Close(testCtx))
540 }()
541
542
543 importing, err := r.Instantiate(testCtx,
544 callReturnImportWasm(t, importedName, importingName, test.vt))
545 require.NoError(t, err)
546 defer func() {
547 require.NoError(t, importing.Close(testCtx))
548 }()
549
550 results, err := importing.ExportedFunction("call_return_input").Call(testCtx, test.input)
551 require.NoError(t, err)
552 require.Equal(t, test.expected, results[0])
553 })
554 }
555 }
556
557 func callHostFunctionIndirect(t *testing.T, r wazero.Runtime) {
558
559
560
561
562 const hostModule, importingWasmModule, originWasmModule = "host", "importing", "origin"
563 const hostFn, importingWasmModuleFn, originModuleFn = "host_fn", "call_host_func", "origin"
564 importingModule := &wasm.Module{
565 TypeSection: []wasm.FunctionType{{Params: []wasm.ValueType{}, Results: []wasm.ValueType{}}},
566 ImportSection: []wasm.Import{{Module: hostModule, Name: hostFn, Type: wasm.ExternTypeFunc, DescFunc: 0}},
567 FunctionSection: []wasm.Index{0},
568 ExportSection: []wasm.Export{{Name: importingWasmModuleFn, Type: wasm.ExternTypeFunc, Index: 1}},
569 CodeSection: []wasm.Code{{Body: []byte{wasm.OpcodeCall, 0, wasm.OpcodeEnd}}},
570 NameSection: &wasm.NameSection{ModuleName: importingWasmModule},
571 }
572
573 originModule := &wasm.Module{
574 TypeSection: []wasm.FunctionType{{Params: []wasm.ValueType{}, Results: []wasm.ValueType{}}},
575 ImportSection: []wasm.Import{{Module: importingWasmModule, Name: importingWasmModuleFn, Type: wasm.ExternTypeFunc, DescFunc: 0}},
576 FunctionSection: []wasm.Index{0},
577 ExportSection: []wasm.Export{{Name: "origin", Type: wasm.ExternTypeFunc, Index: 1}},
578 CodeSection: []wasm.Code{{Body: []byte{wasm.OpcodeCall, 0, wasm.OpcodeEnd}}},
579 NameSection: &wasm.NameSection{ModuleName: originWasmModule},
580 }
581
582 require.NoError(t, importingModule.Validate(api.CoreFeaturesV2))
583 require.NoError(t, originModule.Validate(api.CoreFeaturesV2))
584 importingModuleBytes := binaryencoding.EncodeModule(importingModule)
585 originModuleBytes := binaryencoding.EncodeModule(originModule)
586
587 var originInst, importingInst api.Module
588 _, err := r.NewHostModuleBuilder(hostModule).
589 NewFunctionBuilder().
590 WithFunc(func(ctx context.Context, mod api.Module) {
591
592 require.Equal(t, mod, importingInst)
593 require.NotEqual(t, mod, originInst)
594
595 require.Equal(t, importingWasmModule, mod.Name())
596 }).
597 Export(hostFn).
598 Instantiate(testCtx)
599 require.NoError(t, err)
600
601 importingInst, err = r.Instantiate(testCtx, importingModuleBytes)
602 require.NoError(t, err)
603 originInst, err = r.Instantiate(testCtx, originModuleBytes)
604 require.NoError(t, err)
605
606 originFn := originInst.ExportedFunction(originModuleFn)
607 require.NotNil(t, originFn)
608
609 _, err = originFn.Call(testCtx)
610 require.NoError(t, err)
611 }
612
613 func callReturnImportWasm(t *testing.T, importedModule, importingModule string, vt wasm.ValueType) []byte {
614
615 module := &wasm.Module{
616 TypeSection: []wasm.FunctionType{{Params: []wasm.ValueType{vt}, Results: []wasm.ValueType{vt}}},
617
618 ImportSection: []wasm.Import{
619 {Module: importedModule, Name: "return_input", Type: wasm.ExternTypeFunc, DescFunc: 0},
620 },
621 FunctionSection: []wasm.Index{0},
622 ExportSection: []wasm.Export{
623
624 {Name: "return_input", Type: wasm.ExternTypeFunc, Index: 0},
625
626 {Name: "call_return_input", Type: wasm.ExternTypeFunc, Index: 1},
627 },
628
629 CodeSection: []wasm.Code{
630 {Body: []byte{wasm.OpcodeLocalGet, 0, wasm.OpcodeCall, 0, wasm.OpcodeEnd}},
631 },
632 NameSection: &wasm.NameSection{
633 ModuleName: importingModule,
634 FunctionNames: wasm.NameMap{
635 {Index: 0, Name: "return_input"},
636 {Index: 1, Name: "call_return_input"},
637 },
638 },
639 }
640 require.NoError(t, module.Validate(api.CoreFeaturesV2))
641 return binaryencoding.EncodeModule(module)
642 }
643
644 func callOuterInnerWasm(t *testing.T, importedModule, importingModule string) []byte {
645 module := &wasm.Module{
646 TypeSection: []wasm.FunctionType{{Params: []wasm.ValueType{i32}, Results: []wasm.ValueType{i32}}},
647
648
649 ImportSection: []wasm.Import{
650 {Module: importedModule, Name: "outer", Type: wasm.ExternTypeFunc, DescFunc: 0},
651 {Module: importedModule, Name: "inner", Type: wasm.ExternTypeFunc, DescFunc: 0},
652 },
653 FunctionSection: []wasm.Index{0, 0},
654 ExportSection: []wasm.Export{
655
656 {Name: "call->outer", Type: wasm.ExternTypeFunc, Index: 2},
657
658 {Name: "inner", Type: wasm.ExternTypeFunc, Index: 3},
659 },
660 CodeSection: []wasm.Code{
661
662 {Body: []byte{wasm.OpcodeLocalGet, 0, wasm.OpcodeCall, 0, wasm.OpcodeEnd}},
663
664 {Body: []byte{wasm.OpcodeLocalGet, 0, wasm.OpcodeCall, 1, wasm.OpcodeEnd}},
665 },
666 NameSection: &wasm.NameSection{
667 ModuleName: importingModule,
668 FunctionNames: wasm.NameMap{
669 {Index: 0, Name: "outer"},
670 {Index: 1, Name: "inner"},
671 {Index: 2, Name: "call_outer"},
672 {Index: 3, Name: "call_inner"},
673 },
674 },
675 }
676 require.NoError(t, module.Validate(api.CoreFeaturesV2))
677 return binaryencoding.EncodeModule(module)
678 }
679
680 func testCloseInFlight(t *testing.T, r wazero.Runtime) {
681 tests := []struct {
682 name, function string
683 closeImporting, closeImported uint32
684 closeImportingCode, closeImportedCode bool
685 }{
686 {
687 name: "importing",
688 function: "call_return_input",
689 closeImporting: 1,
690 },
691
692 {
693 name: "both",
694 function: "call_return_input",
695 closeImporting: 1,
696 closeImported: 2,
697 },
698 {
699 name: "importing",
700 function: "call_return_input",
701 closeImporting: 1,
702 closeImportedCode: true,
703 },
704 {
705 name: "importing",
706 function: "call_return_input",
707 closeImporting: 1,
708 closeImportedCode: true,
709 closeImportingCode: true,
710 },
711
712 {
713 name: "both",
714 function: "call_return_input",
715 closeImporting: 1,
716 closeImported: 2,
717 closeImportingCode: true,
718 },
719 }
720 for _, tt := range tests {
721 tc := tt
722
723 t.Run(tc.name, func(t *testing.T) {
724 var importingCode, importedCode wazero.CompiledModule
725 var imported, importing api.Module
726 var err error
727 closeAndReturn := func(ctx context.Context, x uint32) uint32 {
728 if tc.closeImporting != 0 {
729 require.NoError(t, importing.CloseWithExitCode(ctx, tc.closeImporting))
730 }
731 if tc.closeImported != 0 {
732 require.NoError(t, imported.CloseWithExitCode(ctx, tc.closeImported))
733 }
734 if tc.closeImportedCode {
735 err = importedCode.Close(testCtx)
736 require.NoError(t, err)
737 }
738 if tc.closeImportingCode {
739 err = importingCode.Close(testCtx)
740 require.NoError(t, err)
741 }
742 return x
743 }
744
745
746 importedCode, err = r.NewHostModuleBuilder(t.Name() + "-imported").
747 NewFunctionBuilder().WithFunc(closeAndReturn).Export("return_input").
748 Compile(testCtx)
749 require.NoError(t, err)
750
751 imported, err = r.InstantiateModule(testCtx, importedCode, wazero.NewModuleConfig())
752 require.NoError(t, err)
753 defer func() {
754 require.NoError(t, imported.Close(testCtx))
755 }()
756
757
758 bin := callReturnImportWasm(t, imported.Name(), t.Name()+"-importing", i32)
759 importingCode, err = r.CompileModule(testCtx, bin)
760 require.NoError(t, err)
761
762 importing, err = r.InstantiateModule(testCtx, importingCode, wazero.NewModuleConfig())
763 require.NoError(t, err)
764 defer func() {
765 require.NoError(t, importing.Close(testCtx))
766 }()
767
768 var expectedErr error
769 if tc.closeImported != 0 && tc.closeImporting != 0 {
770
771 expectedErr = sys.NewExitError(tc.closeImporting)
772 } else if tc.closeImported != 0 {
773 expectedErr = sys.NewExitError(tc.closeImported)
774 } else if tc.closeImporting != 0 {
775 expectedErr = sys.NewExitError(tc.closeImporting)
776 } else {
777 t.Fatal("invalid test case")
778 }
779
780
781 _, err = importing.ExportedFunction(tc.function).Call(testCtx, 5)
782 require.Equal(t, expectedErr, err)
783 })
784 }
785 }
786
787 func testMemOps(t *testing.T, r wazero.Runtime) {
788
789 mod, err := r.Instantiate(testCtx, memoryWasm)
790 require.NoError(t, err)
791 defer func() {
792 require.NoError(t, mod.Close(testCtx))
793 }()
794
795
796 require.Equal(t, mod.Memory(), mod.ExportedMemory("memory"))
797 memory := mod.Memory()
798
799 sizeFn, storeFn, growFn := mod.ExportedFunction("size"), mod.ExportedFunction("store"), mod.ExportedFunction("grow")
800
801
802 results, err := sizeFn.Call(testCtx)
803 require.NoError(t, err)
804 require.Zero(t, results[0])
805 require.Zero(t, memory.Size())
806
807
808 _, err = storeFn.Call(testCtx, wasm.MemoryPagesToBytesNum(memoryCapacityPages)-8)
809 require.Error(t, err)
810
811
812 results, err = growFn.Call(testCtx, 1)
813 require.NoError(t, err)
814 require.Zero(t, results[0])
815
816
817 _, err = storeFn.Call(testCtx, wasm.MemoryPagesToBytesNum(memoryCapacityPages)-8)
818 require.Error(t, err)
819
820
821 results, err = sizeFn.Call(testCtx)
822 require.NoError(t, err)
823 require.Equal(t, uint64(1), results[0])
824 require.Equal(t, uint32(65536), memory.Size())
825
826
827 results, err = growFn.Call(testCtx, 1)
828 require.NoError(t, err)
829 require.Equal(t, uint64(1), results[0])
830
831
832 results, err = sizeFn.Call(testCtx)
833 require.NoError(t, err)
834 require.Equal(t, uint64(memoryCapacityPages), results[0])
835
836
837 _, err = storeFn.Call(testCtx, wasm.MemoryPagesToBytesNum(memoryCapacityPages)-8)
838 require.NoError(t, err)
839 }
840
841 func testMultipleInstantiation(t *testing.T, r wazero.Runtime) {
842 bin := binaryencoding.EncodeModule(&wasm.Module{
843 TypeSection: []wasm.FunctionType{{}},
844 FunctionSection: []wasm.Index{0},
845 MemorySection: &wasm.Memory{Min: 1, Cap: 1, Max: 1, IsMaxEncoded: true},
846 CodeSection: []wasm.Code{{
847 Body: []byte{
848 wasm.OpcodeI32Const, 1,
849 wasm.OpcodeI64Const, 0xe8, 0x7,
850 wasm.OpcodeI64Store, 0x3, 0x0,
851 wasm.OpcodeEnd,
852 },
853 }},
854 ExportSection: []wasm.Export{{Name: "store"}},
855 })
856 compiled, err := r.CompileModule(testCtx, bin)
857 require.NoError(t, err)
858 defer func() {
859 require.NoError(t, compiled.Close(testCtx))
860 }()
861
862
863 for i := 0; i < 100; i++ {
864 module, err := r.InstantiateModule(testCtx, compiled, wazero.NewModuleConfig().WithName(strconv.Itoa(i)))
865 require.NoError(t, err)
866
867
868 before, ok := module.Memory().ReadUint64Le(1)
869 require.True(t, ok)
870
871 require.Zero(t, before)
872
873 f := module.ExportedFunction("store")
874 require.NotNil(t, f)
875
876 _, err = f.Call(testCtx)
877 require.NoError(t, err)
878
879
880 after, ok := module.Memory().ReadUint64Le(1)
881 require.True(t, ok)
882 require.Equal(t, uint64(1000), after)
883
884 require.NoError(t, module.Close(testCtx))
885 }
886 }
887
888 func testLookupFunction(t *testing.T, r wazero.Runtime) {
889 bin := binaryencoding.EncodeModule(&wasm.Module{
890 TypeSection: []wasm.FunctionType{{Results: []wasm.ValueType{i32}}},
891 FunctionSection: []wasm.Index{0, 0, 0},
892 CodeSection: []wasm.Code{
893 {Body: []byte{wasm.OpcodeI32Const, 1, wasm.OpcodeEnd}},
894 {Body: []byte{wasm.OpcodeI32Const, 2, wasm.OpcodeEnd}},
895 {Body: []byte{wasm.OpcodeI32Const, 3, wasm.OpcodeEnd}},
896 },
897 TableSection: []wasm.Table{{Min: 10, Type: wasm.RefTypeFuncref}},
898 ElementSection: []wasm.ElementSegment{
899 {
900 OffsetExpr: wasm.ConstantExpression{
901 Opcode: wasm.OpcodeI32Const,
902 Data: []byte{0},
903 },
904 TableIndex: 0,
905 Init: []wasm.Index{2, 0},
906 },
907 },
908 })
909
910 inst, err := r.Instantiate(testCtx, bin)
911 require.NoError(t, err)
912
913 t.Run("null reference", func(t *testing.T) {
914 err = require.CapturePanic(func() {
915 table.LookupFunction(inst, 0, 3, nil, []wasm.ValueType{i32})
916 })
917 require.Equal(t, wasmruntime.ErrRuntimeInvalidTableAccess, err)
918 })
919
920 t.Run("out of range", func(t *testing.T) {
921 err = require.CapturePanic(func() {
922 table.LookupFunction(inst, 0, 1000, nil, []wasm.ValueType{i32})
923 })
924 require.Equal(t, wasmruntime.ErrRuntimeInvalidTableAccess, err)
925 })
926
927 t.Run("type mismatch", func(t *testing.T) {
928 err = require.CapturePanic(func() {
929 table.LookupFunction(inst, 0, 0, []wasm.ValueType{i32}, nil)
930 })
931 require.Equal(t, wasmruntime.ErrRuntimeIndirectCallTypeMismatch, err)
932 })
933 t.Run("ok", func(t *testing.T) {
934 f2 := table.LookupFunction(inst, 0, 0, nil, []wasm.ValueType{i32})
935 res, err := f2.Call(testCtx)
936 require.NoError(t, err)
937 require.Equal(t, uint64(3), res[0])
938
939 f0 := table.LookupFunction(inst, 0, 1, nil, []wasm.ValueType{i32})
940 res, err = f0.Call(testCtx)
941 require.NoError(t, err)
942 require.Equal(t, uint64(1), res[0])
943 })
944 }
945
946 func testMemoryGrowInRecursiveCall(t *testing.T, r wazero.Runtime) {
947 const hostModuleName = "env"
948 const hostFnName = "grow_memory"
949 var growFn api.Function
950 hostCompiled, err := r.NewHostModuleBuilder(hostModuleName).NewFunctionBuilder().
951 WithFunc(func() {
952
953 _, err := growFn.Call(testCtx)
954 require.NoError(t, err)
955 }).Export(hostFnName).Compile(testCtx)
956 require.NoError(t, err)
957
958 _, err = r.InstantiateModule(testCtx, hostCompiled, wazero.NewModuleConfig())
959 require.NoError(t, err)
960
961 bin := binaryencoding.EncodeModule(&wasm.Module{
962 ImportFunctionCount: 1,
963 TypeSection: []wasm.FunctionType{{Params: []wasm.ValueType{}, Results: []wasm.ValueType{}}},
964 FunctionSection: []wasm.Index{0, 0},
965 CodeSection: []wasm.Code{
966 {
967 Body: []byte{
968
969 wasm.OpcodeCall, 0,
970
971 wasm.OpcodeI32Const, 0,
972 wasm.OpcodeI32Load, 0x2, 0x0,
973 wasm.OpcodeDrop,
974 wasm.OpcodeEnd,
975 },
976 },
977 {
978
979 Body: []byte{wasm.OpcodeI32Const, 1, wasm.OpcodeMemoryGrow, 0, wasm.OpcodeDrop, wasm.OpcodeEnd},
980 },
981 },
982 MemorySection: &wasm.Memory{Max: 1000},
983 ImportSection: []wasm.Import{{Module: hostModuleName, Name: hostFnName, DescFunc: 0}},
984 ImportPerModule: map[string][]*wasm.Import{hostModuleName: {{Module: hostModuleName, Name: hostFnName, DescFunc: 0}}},
985 ExportSection: []wasm.Export{
986 {Name: "main", Type: wasm.ExternTypeFunc, Index: 1},
987 {Name: "grow_memory", Type: wasm.ExternTypeFunc, Index: 2},
988 },
989 })
990
991 inst, err := r.Instantiate(testCtx, bin)
992 require.NoError(t, err)
993
994 growFn = inst.ExportedFunction("grow_memory")
995 require.NotNil(t, growFn)
996 main := inst.ExportedFunction("main")
997 require.NotNil(t, main)
998
999 _, err = main.Call(testCtx)
1000 require.NoError(t, err)
1001 }
1002
1003 func testCall(t *testing.T, r wazero.Runtime) {
1004
1005
1006 bin := binaryencoding.EncodeModule(&wasm.Module{
1007 TypeSection: []wasm.FunctionType{
1008 {
1009 Params: []wasm.ValueType{i64, i64},
1010 Results: []wasm.ValueType{i64, i64},
1011 ParamNumInUint64: 2,
1012 ResultNumInUint64: 2,
1013 },
1014 },
1015 FunctionSection: []wasm.Index{0},
1016 CodeSection: []wasm.Code{
1017 {Body: []byte{wasm.OpcodeLocalGet, 0, wasm.OpcodeLocalGet, 1, wasm.OpcodeEnd}},
1018 },
1019 ExportSection: []wasm.Export{{Name: "func", Type: wasm.ExternTypeFunc, Index: 0}},
1020 })
1021
1022 inst, err := r.Instantiate(testCtx, bin)
1023 require.NoError(t, err)
1024
1025
1026 f := inst.ExportedFunction("func")
1027 require.NotNil(t, f)
1028
1029 t.Run("call with stack", func(t *testing.T) {
1030 stack := []uint64{1, 2}
1031 err = f.CallWithStack(testCtx, stack)
1032 require.NoError(t, err)
1033 require.Equal(t, []uint64{1, 2}, stack)
1034
1035 t.Run("errs when not enough parameters", func(t *testing.T) {
1036 err = f.CallWithStack(testCtx, nil)
1037 require.EqualError(t, err, "need 2 params, but stack size is 0")
1038 })
1039 })
1040
1041 t.Run("errs when not enough parameters", func(t *testing.T) {
1042 _, err = f.Call(testCtx)
1043 require.EqualError(t, err, "expected 2 params, but passed 0")
1044 })
1045
1046 t.Run("errs when too many parameters", func(t *testing.T) {
1047 _, err = f.Call(testCtx, 1, 2, 3)
1048 require.EqualError(t, err, "expected 2 params, but passed 3")
1049 })
1050 }
1051
1052
1053
1054
1055
1056
1057
1058
1059 func testModuleMemory(t *testing.T, r wazero.Runtime) {
1060 wasmPhrase := "Well, that'll be the day when you say goodbye."
1061 wasmPhraseSize := uint32(len(wasmPhrase))
1062
1063 one := uint32(1)
1064
1065 bin := binaryencoding.EncodeModule(&wasm.Module{
1066 TypeSection: []wasm.FunctionType{{Params: []api.ValueType{api.ValueTypeI32}, ParamNumInUint64: 1}, {}},
1067 FunctionSection: []wasm.Index{0, 1},
1068 MemorySection: &wasm.Memory{Min: 1, Cap: 1, Max: 2},
1069 DataSection: []wasm.DataSegment{
1070 {
1071 Passive: true,
1072 Init: []byte(wasmPhrase),
1073 },
1074 },
1075 DataCountSection: &one,
1076 CodeSection: []wasm.Code{
1077 {Body: []byte{
1078 wasm.OpcodeLocalGet, 0,
1079 wasm.OpcodeMemoryGrow, 0,
1080 wasm.OpcodeDrop,
1081 wasm.OpcodeEnd,
1082 }},
1083 {Body: []byte{
1084 wasm.OpcodeI32Const, 0,
1085 wasm.OpcodeI32Const, 0,
1086 wasm.OpcodeI32Const, byte(wasmPhraseSize),
1087 wasm.OpcodeMiscPrefix, wasm.OpcodeMiscMemoryInit, 0, 0,
1088 wasm.OpcodeEnd,
1089 }},
1090 },
1091 ExportSection: []wasm.Export{
1092 {Name: "grow", Type: wasm.ExternTypeFunc, Index: 0},
1093 {Name: "init", Type: wasm.ExternTypeFunc, Index: 1},
1094 },
1095 })
1096
1097 inst, err := r.Instantiate(testCtx, bin)
1098 require.NoError(t, err)
1099
1100 memory := inst.Memory()
1101
1102 buf, ok := memory.Read(0, wasmPhraseSize)
1103 require.True(t, ok)
1104 require.Equal(t, make([]byte, wasmPhraseSize), buf)
1105
1106
1107 initCallEngine := inst.ExportedFunction("init")
1108 _, err = initCallEngine.Call(testCtx)
1109 require.NoError(t, err)
1110
1111
1112 require.Equal(t, wasmPhrase, string(buf))
1113
1114 hostPhrase := "Goodbye, cruel world. I'm off to join the circus."
1115 hostPhraseSize := uint32(len(hostPhrase))
1116
1117
1118 copy(buf, hostPhrase)
1119 require.Equal(t, "Goodbye, cruel world. I'm off to join the circ", string(buf))
1120
1121
1122
1123 buf2, ok := memory.Read(0, wasmPhraseSize)
1124 require.True(t, ok)
1125 require.Equal(t, buf, buf2)
1126
1127
1128 buf = append(buf, 'u', 's', '.')
1129 require.Equal(t, hostPhrase, string(buf))
1130
1131
1132 buf2, ok = memory.Read(0, hostPhraseSize)
1133 require.True(t, ok)
1134 hostPhraseTruncated := "Goodbye, cruel world. I'm off to join the circ" + string([]byte{0, 0, 0})
1135 require.Equal(t, hostPhraseTruncated, string(buf2))
1136
1137
1138 growCallEngine := inst.ExportedFunction("grow")
1139 _, err = growCallEngine.Call(testCtx, 1)
1140 require.NoError(t, err)
1141
1142
1143 require.Equal(t, hostPhraseTruncated, string(buf2))
1144
1145
1146 initCallEngine2 := inst.ExportedFunction("init")
1147 _, err = initCallEngine2.Call(testCtx)
1148 require.NoError(t, err)
1149
1150
1151 require.Equal(t, hostPhraseTruncated, string(buf2))
1152 }
1153
1154 func testTwoIndirection(t *testing.T, r wazero.Runtime) {
1155 var buf bytes.Buffer
1156 ctx := context.WithValue(testCtx, experimental.FunctionListenerFactoryKey{}, logging.NewLoggingListenerFactory(&buf))
1157 _, err := r.NewHostModuleBuilder("host").NewFunctionBuilder().WithFunc(func(d uint32) uint32 {
1158 if d == math.MaxUint32 {
1159 panic(errors.New("host-function panic"))
1160 }
1161 return 1 / d
1162 }).Export("div").Instantiate(ctx)
1163 require.NoError(t, err)
1164
1165 ft := wasm.FunctionType{Params: []wasm.ValueType{i32}, Results: []wasm.ValueType{i32}}
1166 hostImporter := binaryencoding.EncodeModule(&wasm.Module{
1167 ImportSection: []wasm.Import{{Module: "host", Name: "div", DescFunc: 0}},
1168 TypeSection: []wasm.FunctionType{ft},
1169 FunctionSection: []wasm.Index{0},
1170 CodeSection: []wasm.Code{
1171
1172 {Body: []byte{wasm.OpcodeLocalGet, 0, wasm.OpcodeCall, 0, wasm.OpcodeEnd}},
1173 },
1174 ExportSection: []wasm.Export{{Name: "call_host_div", Type: wasm.ExternTypeFunc, Index: 1}},
1175 NameSection: &wasm.NameSection{
1176 ModuleName: "host_importer",
1177 FunctionNames: wasm.NameMap{{Index: wasm.Index(1), Name: "call_host_div"}},
1178 },
1179 })
1180
1181 _, err = r.Instantiate(ctx, hostImporter)
1182 require.NoError(t, err)
1183
1184 main := binaryencoding.EncodeModule(&wasm.Module{
1185 ImportFunctionCount: 1,
1186 TypeSection: []wasm.FunctionType{ft},
1187 ImportSection: []wasm.Import{{Module: "host_importer", Name: "call_host_div", DescFunc: 0}},
1188 FunctionSection: []wasm.Index{0},
1189 CodeSection: []wasm.Code{{Body: []byte{wasm.OpcodeLocalGet, 0, wasm.OpcodeCall, 0, wasm.OpcodeEnd}}},
1190 ExportSection: []wasm.Export{{Name: "main", Type: wasm.ExternTypeFunc, Index: 1}},
1191 NameSection: &wasm.NameSection{ModuleName: "main", FunctionNames: wasm.NameMap{{Index: wasm.Index(1), Name: "main"}}},
1192 })
1193
1194 inst, err := r.Instantiate(ctx, main)
1195 require.NoError(t, err)
1196
1197 t.Run("ok", func(t *testing.T) {
1198 mainFn := inst.ExportedFunction("main")
1199 require.NotNil(t, mainFn)
1200
1201 result1, err := mainFn.Call(testCtx, 1)
1202 require.NoError(t, err)
1203
1204 result2, err := mainFn.Call(testCtx, 2)
1205 require.NoError(t, err)
1206
1207 require.Equal(t, uint64(1), result1[0])
1208 require.Equal(t, uint64(0), result2[0])
1209 })
1210
1211 t.Run("errors", func(t *testing.T) {
1212 for _, tc := range []struct {
1213 name string
1214 input uint64
1215 expErr string
1216 }{
1217 {name: "host panic", input: math.MaxUint32, expErr: `host-function panic (recovered by wazero)
1218 wasm stack trace:
1219 host.div(i32) i32
1220 host_importer.call_host_div(i32) i32
1221 main.main(i32) i32`},
1222 {name: "go runtime panic", input: 0, expErr: `runtime error: integer divide by zero (recovered by wazero)
1223 wasm stack trace:
1224 host.div(i32) i32
1225 host_importer.call_host_div(i32) i32
1226 main.main(i32) i32`},
1227 } {
1228 tc := tc
1229 t.Run(tc.name, func(t *testing.T) {
1230 mainFn := inst.ExportedFunction("main")
1231 require.NotNil(t, mainFn)
1232
1233 _, err := mainFn.Call(testCtx, tc.input)
1234 require.Error(t, err)
1235 errStr := err.Error()
1236
1237
1238 if index := strings.Index(errStr, wasmdebug.GoRuntimeErrorTracePrefix); index > -1 {
1239 errStr = strings.TrimSpace(errStr[:index])
1240 }
1241 require.Equal(t, errStr, tc.expErr)
1242 })
1243 }
1244 })
1245
1246 require.Equal(t, `
1247 --> main.main(1)
1248 --> host_importer.call_host_div(1)
1249 ==> host.div(1)
1250 <== 1
1251 <-- 1
1252 <-- 1
1253 --> main.main(2)
1254 --> host_importer.call_host_div(2)
1255 ==> host.div(2)
1256 <== 0
1257 <-- 0
1258 <-- 0
1259 --> main.main(-1)
1260 --> host_importer.call_host_div(-1)
1261 ==> host.div(-1)
1262 --> main.main(0)
1263 --> host_importer.call_host_div(0)
1264 ==> host.div(0)
1265 `, "\n"+buf.String())
1266 }
1267
1268 func testBeforeListenerGlobals(t *testing.T, r wazero.Runtime) {
1269 type globals struct {
1270 values []uint64
1271 types []api.ValueType
1272 }
1273
1274 expectedGlobals := []globals{
1275 {values: []uint64{100, 200}, types: []api.ValueType{api.ValueTypeI32, api.ValueTypeI32}},
1276 {values: []uint64{42, 11}, types: []api.ValueType{api.ValueTypeI32, api.ValueTypeI32}},
1277 }
1278
1279 fnListener := &fnListener{
1280 beforeFn: func(ctx context.Context, mod api.Module, def api.FunctionDefinition, params []uint64, si experimental.StackIterator) {
1281 require.True(t, len(expectedGlobals) > 0)
1282
1283 imod := mod.(experimental.InternalModule)
1284 expected := expectedGlobals[0]
1285
1286 require.Equal(t, len(expected.values), imod.NumGlobal())
1287 for i := 0; i < imod.NumGlobal(); i++ {
1288 global := imod.Global(i)
1289 require.Equal(t, expected.types[i], global.Type())
1290 require.Equal(t, expected.values[i], global.Get())
1291 }
1292
1293 expectedGlobals = expectedGlobals[1:]
1294 },
1295 }
1296
1297 buf := binaryencoding.EncodeModule(&wasm.Module{
1298 TypeSection: []wasm.FunctionType{{}},
1299 FunctionSection: []wasm.Index{0, 0},
1300 GlobalSection: []wasm.Global{
1301 {
1302 Type: wasm.GlobalType{ValType: wasm.ValueTypeI32, Mutable: true},
1303 Init: wasm.ConstantExpression{Opcode: wasm.OpcodeI32Const, Data: leb128.EncodeInt32(100)},
1304 },
1305 {
1306 Type: wasm.GlobalType{ValType: wasm.ValueTypeI32, Mutable: true},
1307 Init: wasm.ConstantExpression{Opcode: wasm.OpcodeI32Const, Data: leb128.EncodeInt32(200)},
1308 },
1309 },
1310 CodeSection: []wasm.Code{
1311 {
1312 Body: []byte{
1313 wasm.OpcodeI32Const, 42,
1314 wasm.OpcodeGlobalSet, 0,
1315 wasm.OpcodeI32Const, 11,
1316 wasm.OpcodeGlobalSet, 1,
1317 wasm.OpcodeCall, 1,
1318 wasm.OpcodeEnd,
1319 },
1320 },
1321 {Body: []byte{wasm.OpcodeEnd}},
1322 },
1323 ExportSection: []wasm.Export{{Name: "f", Type: wasm.ExternTypeFunc, Index: 0}},
1324 })
1325
1326 ctx := context.WithValue(testCtx, experimental.FunctionListenerFactoryKey{}, fnListener)
1327 inst, err := r.Instantiate(ctx, buf)
1328 require.NoError(t, err)
1329
1330 f := inst.ExportedFunction("f")
1331 require.NotNil(t, f)
1332
1333 _, err = f.Call(ctx)
1334 require.NoError(t, err)
1335 require.True(t, len(expectedGlobals) == 0)
1336 }
1337
1338
1339
1340 func testBeforeListenerStackIterator(t *testing.T, r wazero.Runtime) {
1341 type stackEntry struct {
1342 debugName string
1343 }
1344
1345 expectedCallstacks := [][]stackEntry{
1346 {
1347 {debugName: "whatever.f1"},
1348 },
1349 {
1350 {debugName: "whatever.f2"},
1351 {debugName: "whatever.f1"},
1352 },
1353 {
1354 {debugName: "whatever.f3"},
1355 {debugName: "whatever.f2"},
1356 {debugName: "whatever.f1"},
1357 },
1358 {
1359 {debugName: "host.f4"},
1360 {debugName: "whatever.f3"},
1361 {debugName: "whatever.f2"},
1362 {debugName: "whatever.f1"},
1363 },
1364 }
1365
1366 fnListener := &fnListener{
1367 beforeFn: func(ctx context.Context, mod api.Module, def api.FunctionDefinition, params []uint64, si experimental.StackIterator) {
1368 require.True(t, len(expectedCallstacks) > 0)
1369 expectedCallstack := expectedCallstacks[0]
1370 for si.Next() {
1371 require.True(t, len(expectedCallstack) > 0)
1372 require.Equal(t, expectedCallstack[0].debugName, si.Function().Definition().DebugName())
1373 expectedCallstack = expectedCallstack[1:]
1374 }
1375 require.Equal(t, 0, len(expectedCallstack))
1376 expectedCallstacks = expectedCallstacks[1:]
1377 },
1378 }
1379
1380 ctx := context.WithValue(testCtx, experimental.FunctionListenerFactoryKey{}, fnListener)
1381 _, err := r.NewHostModuleBuilder("host").NewFunctionBuilder().WithFunc(func(x int32) int32 {
1382 return x + 100
1383 }).Export("f4").Instantiate(ctx)
1384 require.NoError(t, err)
1385
1386 m := binaryencoding.EncodeModule(&wasm.Module{
1387 TypeSection: []wasm.FunctionType{
1388
1389 {
1390 Params: []api.ValueType{api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32},
1391 Results: []api.ValueType{},
1392 },
1393
1394 {
1395 Params: []api.ValueType{},
1396 Results: []api.ValueType{api.ValueTypeI32},
1397 },
1398
1399 {
1400 Params: []api.ValueType{api.ValueTypeI32},
1401 Results: []api.ValueType{api.ValueTypeI32},
1402 },
1403
1404 {
1405 Params: []api.ValueType{api.ValueTypeI32},
1406 Results: []api.ValueType{api.ValueTypeI32},
1407 },
1408 },
1409 ImportFunctionCount: 1,
1410 ImportSection: []wasm.Import{{Name: "f4", Module: "host", DescFunc: 3}},
1411 FunctionSection: []wasm.Index{0, 1, 2},
1412 NameSection: &wasm.NameSection{
1413 ModuleName: "whatever",
1414 FunctionNames: wasm.NameMap{
1415 {Index: wasm.Index(1), Name: "f1"},
1416 {Index: wasm.Index(2), Name: "f2"},
1417 {Index: wasm.Index(3), Name: "f3"},
1418 {Index: wasm.Index(0), Name: "f4"},
1419 },
1420 },
1421 CodeSection: []wasm.Code{
1422 {
1423 Body: []byte{
1424 wasm.OpcodeCall,
1425 2,
1426 wasm.OpcodeDrop,
1427 wasm.OpcodeEnd,
1428 },
1429 },
1430 {
1431 LocalTypes: []wasm.ValueType{wasm.ValueTypeI32},
1432 Body: []byte{
1433 wasm.OpcodeI32Const, 42,
1434 wasm.OpcodeLocalSet, 0,
1435 wasm.OpcodeI32Const, 5,
1436 wasm.OpcodeCall,
1437 3,
1438 wasm.OpcodeEnd,
1439 },
1440 },
1441 {
1442 Body: []byte{
1443 wasm.OpcodeI32Const, 6,
1444 wasm.OpcodeCall,
1445 0,
1446 wasm.OpcodeEnd,
1447 },
1448 },
1449 },
1450 ExportSection: []wasm.Export{{Name: "f1", Type: wasm.ExternTypeFunc, Index: 1}},
1451 })
1452
1453 inst, err := r.Instantiate(ctx, m)
1454 require.NoError(t, err)
1455
1456 f1 := inst.ExportedFunction("f1")
1457 require.NotNil(t, f1)
1458
1459 _, err = f1.Call(ctx, 2, 3, 4)
1460 require.NoError(t, err)
1461 require.Equal(t, 0, len(expectedCallstacks))
1462 }
1463
1464 func testListenerStackIteratorOffset(t *testing.T, r wazero.Runtime) {
1465 type frame struct {
1466 function api.FunctionDefinition
1467 offset uint64
1468 }
1469
1470 var tape [][]frame
1471 fnListener := &fnListener{
1472 beforeFn: func(ctx context.Context, mod api.Module, def api.FunctionDefinition, params []uint64, si experimental.StackIterator) {
1473 var stack []frame
1474 for si.Next() {
1475 fn := si.Function()
1476 pc := si.ProgramCounter()
1477 stack = append(stack, frame{fn.Definition(), fn.SourceOffsetForPC(pc)})
1478 }
1479 tape = append(tape, stack)
1480 },
1481 }
1482 ctx := context.WithValue(testCtx, experimental.FunctionListenerFactoryKey{}, fnListener)
1483
1484
1485
1486 minimalDWARFInfo := []byte{
1487 0x7, 0x0, 0x0, 0x0,
1488 0x3, 0x0,
1489 0x0, 0x0, 0x0, 0x0,
1490 0x0,
1491 }
1492
1493 encoded := binaryencoding.EncodeModule(&wasm.Module{
1494 TypeSection: []wasm.FunctionType{
1495
1496 {Params: []api.ValueType{api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32}},
1497
1498 {Results: []api.ValueType{api.ValueTypeI32}},
1499
1500 {Params: []api.ValueType{api.ValueTypeI32}, Results: []api.ValueType{api.ValueTypeI32}},
1501 },
1502 FunctionSection: []wasm.Index{0, 1, 2},
1503 NameSection: &wasm.NameSection{
1504 ModuleName: "whatever",
1505 FunctionNames: wasm.NameMap{
1506 {Index: wasm.Index(0), Name: "f1"},
1507 {Index: wasm.Index(1), Name: "f2"},
1508 {Index: wasm.Index(2), Name: "f3"},
1509 },
1510 },
1511 CodeSection: []wasm.Code{
1512 {
1513 Body: []byte{
1514 wasm.OpcodeI32Const, 42,
1515 wasm.OpcodeLocalSet, 0,
1516 wasm.OpcodeI32Const, 11,
1517 wasm.OpcodeLocalSet, 1,
1518 wasm.OpcodeCall, 1,
1519 wasm.OpcodeDrop,
1520 wasm.OpcodeEnd,
1521 },
1522 },
1523 {
1524 Body: []byte{
1525 wasm.OpcodeI32Const, 6,
1526 wasm.OpcodeCall, 2,
1527 wasm.OpcodeEnd,
1528 },
1529 },
1530 {Body: []byte{wasm.OpcodeI32Const, 15, wasm.OpcodeEnd}},
1531 },
1532 ExportSection: []wasm.Export{
1533 {Name: "f1", Type: wasm.ExternTypeFunc, Index: 0},
1534 {Name: "f2", Type: wasm.ExternTypeFunc, Index: 1},
1535 {Name: "f3", Type: wasm.ExternTypeFunc, Index: 2},
1536 },
1537 CustomSections: []*wasm.CustomSection{{Name: ".debug_info", Data: minimalDWARFInfo}},
1538 })
1539 decoded, err := binary.DecodeModule(encoded, api.CoreFeaturesV2, 0, false, true, true)
1540 require.NoError(t, err)
1541
1542 f1offset := decoded.CodeSection[0].BodyOffsetInCodeSection
1543 f2offset := decoded.CodeSection[1].BodyOffsetInCodeSection
1544 f3offset := decoded.CodeSection[2].BodyOffsetInCodeSection
1545
1546 inst, err := r.Instantiate(ctx, encoded)
1547 require.NoError(t, err)
1548
1549 f1Fn := inst.ExportedFunction("f1")
1550 require.NotNil(t, f1Fn)
1551
1552 _, err = f1Fn.Call(ctx, 2, 3, 4)
1553 require.NoError(t, err)
1554
1555 module, ok := inst.(*wasm.ModuleInstance)
1556 require.True(t, ok)
1557
1558 defs := module.ExportedFunctionDefinitions()
1559 f1 := defs["f1"]
1560 f2 := defs["f2"]
1561 f3 := defs["f3"]
1562 t.Logf("f1 offset: %#x", f1offset)
1563 t.Logf("f2 offset: %#x", f2offset)
1564 t.Logf("f3 offset: %#x", f3offset)
1565
1566 expectedStacks := [][]frame{
1567 {
1568 {f1, f1offset + 0},
1569 },
1570 {
1571 {f2, f2offset + 0},
1572 {f1, f1offset + 8},
1573 },
1574 {
1575 {f3, f3offset},
1576 {f2, f2offset + 2},
1577 {f1, f1offset + 8},
1578 },
1579 }
1580
1581 for si, stack := range tape {
1582 t.Log("Recorded stack", si, ":")
1583 require.True(t, len(expectedStacks) > 0, "more recorded stacks than expected stacks")
1584 expectedStack := expectedStacks[0]
1585 expectedStacks = expectedStacks[1:]
1586 for fi, frame := range stack {
1587 t.Logf("\t%d -> %s :: %#x", fi, frame.function.Name(), frame.offset)
1588 require.True(t, len(expectedStack) > 0, "more frames in stack than expected")
1589 expectedFrame := expectedStack[0]
1590 expectedStack = expectedStack[1:]
1591 require.Equal(t, expectedFrame, frame)
1592 }
1593 require.Zero(t, len(expectedStack), "expected more frames in stack")
1594 }
1595 require.Zero(t, len(expectedStacks), "expected more stacks")
1596 }
1597
1598
1599 type fnListener struct {
1600 beforeFn func(context.Context, api.Module, api.FunctionDefinition, []uint64, experimental.StackIterator)
1601 afterFn func(context.Context, api.Module, api.FunctionDefinition, []uint64)
1602 abortFn func(context.Context, api.Module, api.FunctionDefinition, any)
1603 }
1604
1605
1606 func (f *fnListener) NewFunctionListener(api.FunctionDefinition) experimental.FunctionListener {
1607 return f
1608 }
1609
1610
1611 func (f *fnListener) Before(ctx context.Context, mod api.Module, def api.FunctionDefinition, params []uint64, stackIterator experimental.StackIterator) {
1612 if f.beforeFn != nil {
1613 f.beforeFn(ctx, mod, def, params, stackIterator)
1614 }
1615 }
1616
1617
1618 func (f *fnListener) After(ctx context.Context, mod api.Module, def api.FunctionDefinition, results []uint64) {
1619 if f.afterFn != nil {
1620 f.afterFn(ctx, mod, def, results)
1621 }
1622 }
1623
1624
1625 func (f *fnListener) Abort(ctx context.Context, mod api.Module, def api.FunctionDefinition, err error) {
1626 if f.abortFn != nil {
1627 f.abortFn(ctx, mod, def, err)
1628 }
1629 }
1630
1631 func manyParamsResultsMod() (bin []byte, params []uint64) {
1632 mainType := wasm.FunctionType{}
1633 swapperType := wasm.FunctionType{}
1634 doublerType := wasm.FunctionType{}
1635 manyConstsType := wasm.FunctionType{}
1636 callManyConstsType := wasm.FunctionType{}
1637 pickLastVectorType := wasm.FunctionType{Results: []wasm.ValueType{v128}}
1638 callManyConstsAndPickLastVectorType := wasm.FunctionType{Results: []wasm.ValueType{v128}}
1639 for i := 0; i < 20; i++ {
1640 swapperType.Params = append(swapperType.Params, i32, i64, f32, f64, v128)
1641 swapperType.Results = append(swapperType.Results, v128, f64, f32, i64, i32)
1642 mainType.Params = append(mainType.Params, i32, i64, f32, f64, v128)
1643 mainType.Results = append(mainType.Results, v128, f64, f32, i64, i32)
1644 doublerType.Params = append(doublerType.Results, v128, f64, f32, i64, i32)
1645 doublerType.Results = append(doublerType.Results, v128, f64, f32, i64, i32)
1646 manyConstsType.Results = append(manyConstsType.Results, i32, i64, f32, f64, v128)
1647 callManyConstsType.Results = append(callManyConstsType.Results, i32, i64, f32, f64, v128)
1648 pickLastVectorType.Params = append(pickLastVectorType.Params, i32, i64, f32, f64, v128)
1649 }
1650
1651 var mainBody []byte
1652 for i := 0; i < 100; i++ {
1653 mainBody = append(mainBody, wasm.OpcodeLocalGet)
1654 mainBody = append(mainBody, leb128.EncodeUint32(uint32(i))...)
1655 }
1656 mainBody = append(mainBody, wasm.OpcodeCall, 1)
1657 mainBody = append(mainBody, wasm.OpcodeCall, 2)
1658 mainBody = append(mainBody, wasm.OpcodeEnd)
1659
1660 var swapperBody []byte
1661 for i := 0; i < 100; i++ {
1662 swapperBody = append(swapperBody, wasm.OpcodeLocalGet)
1663 swapperBody = append(swapperBody, leb128.EncodeUint32(uint32(99-i))...)
1664 }
1665 swapperBody = append(swapperBody, wasm.OpcodeEnd)
1666
1667 var doublerBody []byte
1668 for i := 0; i < 100; i += 5 {
1669
1670 doublerBody = append(doublerBody, wasm.OpcodeLocalGet)
1671 doublerBody = append(doublerBody, leb128.EncodeUint32(uint32(i))...)
1672
1673 doublerBody = append(doublerBody, wasm.OpcodeLocalGet)
1674 doublerBody = append(doublerBody, leb128.EncodeUint32(uint32(i+1))...)
1675 doublerBody = append(doublerBody, wasm.OpcodeLocalGet)
1676 doublerBody = append(doublerBody, leb128.EncodeUint32(uint32(i+1))...)
1677 doublerBody = append(doublerBody, wasm.OpcodeF64Add)
1678
1679 doublerBody = append(doublerBody, wasm.OpcodeLocalGet)
1680 doublerBody = append(doublerBody, leb128.EncodeUint32(uint32(i+2))...)
1681 doublerBody = append(doublerBody, wasm.OpcodeLocalGet)
1682 doublerBody = append(doublerBody, leb128.EncodeUint32(uint32(i+2))...)
1683 doublerBody = append(doublerBody, wasm.OpcodeF32Add)
1684
1685 doublerBody = append(doublerBody, wasm.OpcodeLocalGet)
1686 doublerBody = append(doublerBody, leb128.EncodeUint32(uint32(i+3))...)
1687 doublerBody = append(doublerBody, wasm.OpcodeLocalGet)
1688 doublerBody = append(doublerBody, leb128.EncodeUint32(uint32(i+3))...)
1689 doublerBody = append(doublerBody, wasm.OpcodeI64Add)
1690
1691 doublerBody = append(doublerBody, wasm.OpcodeLocalGet)
1692 doublerBody = append(doublerBody, leb128.EncodeUint32(uint32(i+4))...)
1693 doublerBody = append(doublerBody, wasm.OpcodeLocalGet)
1694 doublerBody = append(doublerBody, leb128.EncodeUint32(uint32(i+4))...)
1695 doublerBody = append(doublerBody, wasm.OpcodeI32Add)
1696 }
1697 doublerBody = append(doublerBody, wasm.OpcodeEnd)
1698
1699 var manyConstsBody []byte
1700 for i := 0; i < 100; i += 5 {
1701 ib := byte(i)
1702 manyConstsBody = append(manyConstsBody, wasm.OpcodeI32Const)
1703 manyConstsBody = append(manyConstsBody, leb128.EncodeInt32(int32(i))...)
1704 manyConstsBody = append(manyConstsBody, wasm.OpcodeI64Const)
1705 manyConstsBody = append(manyConstsBody, leb128.EncodeInt64(int64(i))...)
1706 manyConstsBody = append(manyConstsBody, wasm.OpcodeF32Const)
1707 manyConstsBody = append(manyConstsBody, ib, ib, ib, ib)
1708 manyConstsBody = append(manyConstsBody, wasm.OpcodeF64Const)
1709 manyConstsBody = append(manyConstsBody, ib, ib, ib, ib, ib, ib, ib, ib)
1710 manyConstsBody = append(manyConstsBody, wasm.OpcodeVecPrefix, wasm.OpcodeVecV128Const)
1711 manyConstsBody = append(manyConstsBody, ib, ib, ib, ib, ib, ib, ib, ib, ib, ib, ib, ib, ib, ib, ib, ib)
1712 }
1713 manyConstsBody = append(manyConstsBody, wasm.OpcodeEnd)
1714
1715 var callManyConstsBody []byte
1716 callManyConstsBody = append(callManyConstsBody, wasm.OpcodeCall, 5, wasm.OpcodeEnd)
1717
1718 var pickLastVector []byte
1719 pickLastVector = append(pickLastVector, wasm.OpcodeLocalGet, 99, wasm.OpcodeEnd)
1720
1721 var callManyConstsAndPickLastVector []byte
1722 callManyConstsAndPickLastVector = append(callManyConstsAndPickLastVector, wasm.OpcodeCall, 5, wasm.OpcodeCall, 6, wasm.OpcodeEnd)
1723
1724 nameSection := wasm.NameSection{}
1725 nameSection.FunctionNames = []wasm.NameAssoc{
1726 {Index: 0, Name: "main"},
1727 {Index: 1, Name: "swapper"},
1728 {Index: 2, Name: "doubler"},
1729 {Index: 3, Name: "call_many_consts"},
1730 {Index: 4, Name: "call_many_consts_and_pick_last_vector"},
1731 {Index: 5, Name: "many_consts"},
1732 {Index: 6, Name: "pick_last_vector"},
1733 }
1734
1735 typeSection := []wasm.FunctionType{mainType, swapperType, doublerType, callManyConstsType, callManyConstsAndPickLastVectorType, manyConstsType, pickLastVectorType}
1736
1737 for i, typ := range typeSection {
1738 paramNames := wasm.NameMapAssoc{Index: wasm.Index(i)}
1739 for paramIndex, paramType := range typ.Params {
1740 name := fmt.Sprintf("[%d:%s]", paramIndex, wasm.ValueTypeName(paramType))
1741 paramNames.NameMap = append(paramNames.NameMap, wasm.NameAssoc{Index: wasm.Index(paramIndex), Name: name})
1742 }
1743 nameSection.LocalNames = append(nameSection.LocalNames, paramNames)
1744 }
1745
1746 bin = binaryencoding.EncodeModule(&wasm.Module{
1747 TypeSection: typeSection,
1748 ExportSection: []wasm.Export{
1749 {Name: "main", Type: wasm.ExternTypeFunc, Index: 0},
1750 {Name: "swapper", Type: wasm.ExternTypeFunc, Index: 1},
1751 {Name: "doubler", Type: wasm.ExternTypeFunc, Index: 2},
1752 {Name: "call_many_consts", Type: wasm.ExternTypeFunc, Index: 3},
1753 {Name: "call_many_consts_and_pick_last_vector", Type: wasm.ExternTypeFunc, Index: 4},
1754 },
1755 FunctionSection: []wasm.Index{0, 1, 2, 3, 4, 5, 6},
1756 CodeSection: []wasm.Code{
1757 {Body: mainBody},
1758 {Body: swapperBody},
1759 {Body: doublerBody},
1760 {Body: callManyConstsBody},
1761 {Body: callManyConstsAndPickLastVector},
1762 {Body: manyConstsBody},
1763 {Body: pickLastVector},
1764 },
1765 NameSection: &nameSection,
1766 })
1767
1768 for i := 0; i < 100; i += 5 {
1769 params = append(params, uint64(i))
1770 params = append(params, uint64(i+1))
1771 params = append(params, uint64(i+2))
1772 params = append(params, uint64(i+3))
1773
1774 params = append(params, uint64(i+3))
1775 params = append(params, uint64(i+3))
1776 }
1777 return
1778 }
1779
1780 func testManyParamsResultsCallManyConsts(t *testing.T, r wazero.Runtime) {
1781 ctx := context.Background()
1782
1783 bin, _ := manyParamsResultsMod()
1784 mod, err := r.Instantiate(ctx, bin)
1785 require.NoError(t, err)
1786
1787 main := mod.ExportedFunction("call_many_consts")
1788 require.NotNil(t, main)
1789
1790 results, err := main.Call(ctx)
1791 require.NoError(t, err)
1792
1793 exp := []uint64{
1794 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5, 0x5, 0x5050505, 0x505050505050505, 0x505050505050505,
1795 0x505050505050505, 0xa, 0xa, 0xa0a0a0a, 0xa0a0a0a0a0a0a0a, 0xa0a0a0a0a0a0a0a, 0xa0a0a0a0a0a0a0a,
1796 0xf, 0xf, 0xf0f0f0f, 0xf0f0f0f0f0f0f0f, 0xf0f0f0f0f0f0f0f, 0xf0f0f0f0f0f0f0f, 0x14, 0x14, 0x14141414,
1797 0x1414141414141414, 0x1414141414141414, 0x1414141414141414, 0x19, 0x19, 0x19191919, 0x1919191919191919,
1798 0x1919191919191919, 0x1919191919191919, 0x1e, 0x1e, 0x1e1e1e1e, 0x1e1e1e1e1e1e1e1e, 0x1e1e1e1e1e1e1e1e,
1799 0x1e1e1e1e1e1e1e1e, 0x23, 0x23, 0x23232323, 0x2323232323232323, 0x2323232323232323, 0x2323232323232323,
1800 0x28, 0x28, 0x28282828, 0x2828282828282828, 0x2828282828282828, 0x2828282828282828, 0x2d, 0x2d, 0x2d2d2d2d,
1801 0x2d2d2d2d2d2d2d2d, 0x2d2d2d2d2d2d2d2d, 0x2d2d2d2d2d2d2d2d, 0x32, 0x32, 0x32323232, 0x3232323232323232,
1802 0x3232323232323232, 0x3232323232323232, 0x37, 0x37, 0x37373737, 0x3737373737373737, 0x3737373737373737,
1803 0x3737373737373737, 0x3c, 0x3c, 0x3c3c3c3c, 0x3c3c3c3c3c3c3c3c, 0x3c3c3c3c3c3c3c3c, 0x3c3c3c3c3c3c3c3c,
1804 0x41, 0x41, 0x41414141, 0x4141414141414141, 0x4141414141414141, 0x4141414141414141, 0x46, 0x46, 0x46464646,
1805 0x4646464646464646, 0x4646464646464646, 0x4646464646464646, 0x4b, 0x4b, 0x4b4b4b4b, 0x4b4b4b4b4b4b4b4b,
1806 0x4b4b4b4b4b4b4b4b, 0x4b4b4b4b4b4b4b4b, 0x50, 0x50, 0x50505050, 0x5050505050505050, 0x5050505050505050,
1807 0x5050505050505050, 0x55, 0x55, 0x55555555, 0x5555555555555555, 0x5555555555555555, 0x5555555555555555,
1808 0x5a, 0x5a, 0x5a5a5a5a, 0x5a5a5a5a5a5a5a5a, 0x5a5a5a5a5a5a5a5a, 0x5a5a5a5a5a5a5a5a, 0x5f, 0x5f, 0x5f5f5f5f,
1809 0x5f5f5f5f5f5f5f5f, 0x5f5f5f5f5f5f5f5f, 0x5f5f5f5f5f5f5f5f,
1810 }
1811 require.Equal(t, exp, results)
1812 }
1813
1814 func testManyParamsResultsCallManyConstsListener(t *testing.T, r wazero.Runtime) {
1815 var buf bytes.Buffer
1816 ctx := context.WithValue(context.Background(), experimental.FunctionListenerFactoryKey{}, logging.NewLoggingListenerFactory(&buf))
1817
1818 bin, _ := manyParamsResultsMod()
1819 mod, err := r.Instantiate(ctx, bin)
1820 require.NoError(t, err)
1821
1822 main := mod.ExportedFunction("call_many_consts")
1823 require.NotNil(t, main)
1824
1825 results, err := main.Call(ctx)
1826 require.NoError(t, err)
1827
1828 require.Equal(t, `
1829 --> .call_many_consts()
1830 --> .many_consts()
1831 <-- (0,0,0,0,00000000000000000000000000000000,0,5,7e-45,4.16077606e-316,05050505050505050505050505050505,84215045,361700864190383365,1.4e-44,5e-323,000000000a0a0a0a0a0a0a0a0a0a0a0a,168430090,723401728380766730,6.6463464e-33,7.4e-323,000000000000000f000000000f0f0f0f,252645135,1085102592571150095,7.0533445e-30,3.815736827118017e-236,00000000000000140000000000000014,20,336860180,7.47605e-27,5.964208835435795e-212,14141414141414140000000000000019,25,25,7.914983e-24,9.01285756841504e-188,19191919191919191919191919191919,421075225,30,4.2e-44,2.496465636e-315,1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e,505290270,2170205185142300190,4.9e-44,1.73e-322,00000000232323232323232323232323,589505315,2531906049332683555,8.843688e-18,2e-322,00000000000000280000000028282828,673720360,2893606913523066920,9.334581e-15,3.0654356309538037e-115,000000000000002d000000000000002d,45,757935405,9.8439425e-12,4.4759381595361623e-91,2d2d2d2d2d2d2d2d0000000000000032,50,50,1.0372377e-08,6.749300603603778e-67,32323232323232323232323232323232,842150450,55,7.7e-44,4.576853666e-315,37373737373737373737373737373737,926365495,3978709506094217015,8.4e-44,2.96e-322,000000003c3c3c3c3c3c3c3c3c3c3c3c,1010580540,4340410370284600380,0.01148897,3.2e-322,00000000000000410000000041414141,1094795585,4702111234474983745,12.078431,2.2616345098039214e+06,00000000000000460000000000000046,70,1179010630,12689.568,3.5295369653413445e+30,4646464646464646000000000000004b,75,75,1.3323083e+07,5.2285141982483265e+54,4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b,1263225675,80,1.12e-43,6.657241696e-315,50505050505050505050505050505050)
1832 <-- (0,0,0,0,00000000000000000000000000000000,0,5,7e-45,4.16077606e-316,05050505050505050505050505050505,84215045,361700864190383365,1.4e-44,5e-323,000000000a0a0a0a0a0a0a0a0a0a0a0a,168430090,723401728380766730,6.6463464e-33,7.4e-323,000000000000000f000000000f0f0f0f,252645135,1085102592571150095,7.0533445e-30,3.815736827118017e-236,00000000000000140000000000000014,20,336860180,7.47605e-27,5.964208835435795e-212,14141414141414140000000000000019,25,25,7.914983e-24,9.01285756841504e-188,19191919191919191919191919191919,421075225,30,4.2e-44,2.496465636e-315,1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e,505290270,2170205185142300190,4.9e-44,1.73e-322,00000000232323232323232323232323,589505315,2531906049332683555,8.843688e-18,2e-322,00000000000000280000000028282828,673720360,2893606913523066920,9.334581e-15,3.0654356309538037e-115,000000000000002d000000000000002d,45,757935405,9.8439425e-12,4.4759381595361623e-91,2d2d2d2d2d2d2d2d0000000000000032,50,50,1.0372377e-08,6.749300603603778e-67,32323232323232323232323232323232,842150450,55,7.7e-44,4.576853666e-315,37373737373737373737373737373737,926365495,3978709506094217015,8.4e-44,2.96e-322,000000003c3c3c3c3c3c3c3c3c3c3c3c,1010580540,4340410370284600380,0.01148897,3.2e-322,00000000000000410000000041414141,1094795585,4702111234474983745,12.078431,2.2616345098039214e+06,00000000000000460000000000000046,70,1179010630,12689.568,3.5295369653413445e+30,4646464646464646000000000000004b,75,75,1.3323083e+07,5.2285141982483265e+54,4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b,1263225675,80,1.12e-43,6.657241696e-315,50505050505050505050505050505050)
1833 `, "\n"+buf.String())
1834
1835 exp := []uint64{
1836 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5, 0x5, 0x5050505, 0x505050505050505, 0x505050505050505,
1837 0x505050505050505, 0xa, 0xa, 0xa0a0a0a, 0xa0a0a0a0a0a0a0a, 0xa0a0a0a0a0a0a0a, 0xa0a0a0a0a0a0a0a,
1838 0xf, 0xf, 0xf0f0f0f, 0xf0f0f0f0f0f0f0f, 0xf0f0f0f0f0f0f0f, 0xf0f0f0f0f0f0f0f, 0x14, 0x14, 0x14141414,
1839 0x1414141414141414, 0x1414141414141414, 0x1414141414141414, 0x19, 0x19, 0x19191919, 0x1919191919191919,
1840 0x1919191919191919, 0x1919191919191919, 0x1e, 0x1e, 0x1e1e1e1e, 0x1e1e1e1e1e1e1e1e, 0x1e1e1e1e1e1e1e1e,
1841 0x1e1e1e1e1e1e1e1e, 0x23, 0x23, 0x23232323, 0x2323232323232323, 0x2323232323232323, 0x2323232323232323,
1842 0x28, 0x28, 0x28282828, 0x2828282828282828, 0x2828282828282828, 0x2828282828282828, 0x2d, 0x2d, 0x2d2d2d2d,
1843 0x2d2d2d2d2d2d2d2d, 0x2d2d2d2d2d2d2d2d, 0x2d2d2d2d2d2d2d2d, 0x32, 0x32, 0x32323232, 0x3232323232323232,
1844 0x3232323232323232, 0x3232323232323232, 0x37, 0x37, 0x37373737, 0x3737373737373737, 0x3737373737373737,
1845 0x3737373737373737, 0x3c, 0x3c, 0x3c3c3c3c, 0x3c3c3c3c3c3c3c3c, 0x3c3c3c3c3c3c3c3c, 0x3c3c3c3c3c3c3c3c,
1846 0x41, 0x41, 0x41414141, 0x4141414141414141, 0x4141414141414141, 0x4141414141414141, 0x46, 0x46, 0x46464646,
1847 0x4646464646464646, 0x4646464646464646, 0x4646464646464646, 0x4b, 0x4b, 0x4b4b4b4b, 0x4b4b4b4b4b4b4b4b,
1848 0x4b4b4b4b4b4b4b4b, 0x4b4b4b4b4b4b4b4b, 0x50, 0x50, 0x50505050, 0x5050505050505050, 0x5050505050505050,
1849 0x5050505050505050, 0x55, 0x55, 0x55555555, 0x5555555555555555, 0x5555555555555555, 0x5555555555555555,
1850 0x5a, 0x5a, 0x5a5a5a5a, 0x5a5a5a5a5a5a5a5a, 0x5a5a5a5a5a5a5a5a, 0x5a5a5a5a5a5a5a5a, 0x5f, 0x5f, 0x5f5f5f5f,
1851 0x5f5f5f5f5f5f5f5f, 0x5f5f5f5f5f5f5f5f, 0x5f5f5f5f5f5f5f5f,
1852 }
1853 require.Equal(t, exp, results)
1854 }
1855
1856 func testManyParamsResultsDoubler(t *testing.T, r wazero.Runtime) {
1857 ctx := context.Background()
1858
1859 bin, params := manyParamsResultsMod()
1860 mod, err := r.Instantiate(ctx, bin)
1861 require.NoError(t, err)
1862
1863 main := mod.ExportedFunction("doubler")
1864 require.NotNil(t, main)
1865
1866 results, err := main.Call(ctx, params...)
1867 require.NoError(t, err)
1868
1869 exp := []uint64{
1870 0x0, 0x1, 0x4, 0x6, 0x6, 0x6, 0x5, 0x6, 0xe, 0x10, 0x10, 0x10, 0xa,
1871 0xb, 0x18, 0x1a, 0x1a, 0x1a, 0xf, 0x10, 0x22, 0x24, 0x24, 0x24, 0x14,
1872 0x15, 0x2c, 0x2e, 0x2e, 0x2e, 0x19, 0x1a, 0x36, 0x38, 0x38, 0x38, 0x1e,
1873 0x1f, 0x40, 0x42, 0x42, 0x42, 0x23, 0x24, 0x4a, 0x4c, 0x4c, 0x4c, 0x28,
1874 0x29, 0x54, 0x56, 0x56, 0x56, 0x2d, 0x2e, 0x5e, 0x60, 0x60, 0x60, 0x32,
1875 0x33, 0x68, 0x6a, 0x6a, 0x6a, 0x37, 0x38, 0x72, 0x74, 0x74, 0x74, 0x3c,
1876 0x3d, 0x7c, 0x7e, 0x7e, 0x7e, 0x41, 0x42, 0x86, 0x88, 0x88, 0x88, 0x46,
1877 0x47, 0x90, 0x92, 0x92, 0x92, 0x4b, 0x4c, 0x9a, 0x9c, 0x9c, 0x9c, 0x50,
1878 0x51, 0xa4, 0xa6, 0xa6, 0xa6, 0x55, 0x56, 0xae, 0xb0, 0xb0, 0xb0, 0x5a,
1879 0x5b, 0xb8, 0xba, 0xba, 0xba, 0x5f, 0x60, 0xc2, 0xc4, 0xc4, 0xc4,
1880 }
1881 require.Equal(t, exp, results)
1882 }
1883
1884 func testManyParamsResultsDoublerListener(t *testing.T, r wazero.Runtime) {
1885 var buf bytes.Buffer
1886 ctx := context.WithValue(context.Background(), experimental.FunctionListenerFactoryKey{}, logging.NewLoggingListenerFactory(&buf))
1887
1888 bin, params := manyParamsResultsMod()
1889 mod, err := r.Instantiate(ctx, bin)
1890 require.NoError(t, err)
1891
1892 main := mod.ExportedFunction("doubler")
1893 require.NotNil(t, main)
1894
1895 results, err := main.Call(ctx, params...)
1896 require.NoError(t, err)
1897
1898 require.Equal(t, `
1899 --> .doubler([0:v128]=00000000000000000000000000000001,[1:f64]=5e-324,[2:f32]=3e-45,[3:i64]=3,[4:i32]=3,[5:v128]=00000000000000030000000000000005,[6:f64]=2.5e-323,[7:f32]=8e-45,[8:i64]=7,[9:i32]=8,[10:v128]=00000000000000080000000000000008,[11:f64]=4e-323,[12:f32]=1.4e-44,[13:i64]=11,[14:i32]=12,[15:v128]=000000000000000d000000000000000d,[16:f64]=6.4e-323,[17:f32]=1.8e-44,[18:i64]=15,[19:i32]=16,[20:v128]=00000000000000110000000000000012,[21:f64]=9e-323,[22:f32]=2.5e-44,[23:i64]=18,[24:i32]=20,[25:v128]=00000000000000150000000000000016,[26:f64]=1.1e-322,[27:f32]=3.2e-44,[28:i64]=23,[29:i32]=23,[30:v128]=0000000000000019000000000000001a,[31:f64]=1.3e-322,[32:f32]=3.8e-44,[33:i64]=28,[34:i32]=28,[35:v128]=000000000000001c000000000000001e,[36:f64]=1.5e-322,[37:f32]=4.3e-44,[38:i64]=32,[39:i32]=33,[40:v128]=00000000000000210000000000000021,[41:f64]=1.63e-322,[42:f32]=4.9e-44,[43:i64]=36,[44:i32]=37,[45:v128]=00000000000000260000000000000026,[46:f64]=1.9e-322,[47:f32]=5.3e-44,[48:i64]=40,[49:i32]=41,[50:v128]=000000000000002a000000000000002b,[51:f64]=2.1e-322,[52:f32]=6e-44,[53:i64]=43,[54:i32]=45,[55:v128]=000000000000002e000000000000002f,[56:f64]=2.3e-322,[57:f32]=6.7e-44,[58:i64]=48,[59:i32]=48,[60:v128]=00000000000000320000000000000033,[61:f64]=2.5e-322,[62:f32]=7.3e-44,[63:i64]=53,[64:i32]=53,[65:v128]=00000000000000350000000000000037,[66:f64]=2.7e-322,[67:f32]=7.8e-44,[68:i64]=57,[69:i32]=58,[70:v128]=000000000000003a000000000000003a,[71:f64]=2.87e-322,[72:f32]=8.4e-44,[73:i64]=61,[74:i32]=62,[75:v128]=000000000000003f000000000000003f,[76:f64]=3.1e-322,[77:f32]=8.8e-44,[78:i64]=65,[79:i32]=66,[80:v128]=00000000000000430000000000000044,[81:f64]=3.36e-322,[82:f32]=9.5e-44,[83:i64]=68,[84:i32]=70,[85:v128]=00000000000000470000000000000048,[86:f64]=3.56e-322,[87:f32]=1.02e-43,[88:i64]=73,[89:i32]=73,[90:v128]=000000000000004b000000000000004c,[91:f64]=3.75e-322,[92:f32]=1.08e-43,[93:i64]=78,[94:i32]=78,[95:v128]=000000000000004e0000000000000050,[96:f64]=3.95e-322,[97:f32]=1.14e-43,[98:i64]=82,[99:i32]=83)
1900 <-- (00000000000000000000000000000001,5e-324,6e-45,6,6,00000000000000060000000000000005,2.5e-323,8e-45,14,16,00000000000000100000000000000010,8e-323,1.4e-44,11,24,000000000000001a000000000000001a,1.3e-322,3.6e-44,15,16,00000000000000220000000000000024,1.8e-322,5e-44,36,20,0000000000000015000000000000002c,2.17e-322,6.4e-44,46,46,0000000000000019000000000000001a,1.3e-322,7.6e-44,56,56,0000000000000038000000000000001e,1.5e-322,4.3e-44,64,66,00000000000000420000000000000042,3.26e-322,4.9e-44,36,74,000000000000004c000000000000004c,3.75e-322,1.06e-43,40,41,00000000000000540000000000000056,4.25e-322,1.2e-43,86,45,000000000000002e000000000000005e,4.64e-322,1.35e-43,96,96,00000000000000320000000000000033,2.5e-322,1.46e-43,106,106,000000000000006a0000000000000037,2.7e-322,7.8e-44,114,116,00000000000000740000000000000074,5.73e-322,8.4e-44,61,124,000000000000007e000000000000007e,6.23e-322,1.77e-43,65,66,00000000000000860000000000000088,6.7e-322,1.9e-43,136,70,00000000000000470000000000000090,7.1e-322,2.05e-43,146,146,000000000000004b000000000000004c,3.75e-322,2.16e-43,156,156,000000000000009c0000000000000050,3.95e-322,1.14e-43,164,166)
1901 `, "\n"+buf.String())
1902
1903 exp := []uint64{
1904 0x0, 0x1, 0x4, 0x6, 0x6, 0x6, 0x5, 0x6, 0xe, 0x10, 0x10, 0x10, 0xa,
1905 0xb, 0x18, 0x1a, 0x1a, 0x1a, 0xf, 0x10, 0x22, 0x24, 0x24, 0x24, 0x14,
1906 0x15, 0x2c, 0x2e, 0x2e, 0x2e, 0x19, 0x1a, 0x36, 0x38, 0x38, 0x38, 0x1e,
1907 0x1f, 0x40, 0x42, 0x42, 0x42, 0x23, 0x24, 0x4a, 0x4c, 0x4c, 0x4c, 0x28,
1908 0x29, 0x54, 0x56, 0x56, 0x56, 0x2d, 0x2e, 0x5e, 0x60, 0x60, 0x60, 0x32,
1909 0x33, 0x68, 0x6a, 0x6a, 0x6a, 0x37, 0x38, 0x72, 0x74, 0x74, 0x74, 0x3c,
1910 0x3d, 0x7c, 0x7e, 0x7e, 0x7e, 0x41, 0x42, 0x86, 0x88, 0x88, 0x88, 0x46,
1911 0x47, 0x90, 0x92, 0x92, 0x92, 0x4b, 0x4c, 0x9a, 0x9c, 0x9c, 0x9c, 0x50,
1912 0x51, 0xa4, 0xa6, 0xa6, 0xa6, 0x55, 0x56, 0xae, 0xb0, 0xb0, 0xb0, 0x5a,
1913 0x5b, 0xb8, 0xba, 0xba, 0xba, 0x5f, 0x60, 0xc2, 0xc4, 0xc4, 0xc4,
1914 }
1915 require.Equal(t, exp, results)
1916 }
1917
1918 func testManyParamsResultsSwapper(t *testing.T, r wazero.Runtime) {
1919 ctx := context.Background()
1920
1921 bin, params := manyParamsResultsMod()
1922 mod, err := r.Instantiate(ctx, bin)
1923 require.NoError(t, err)
1924
1925 main := mod.ExportedFunction("swapper")
1926 require.NotNil(t, main)
1927
1928 results, err := main.Call(ctx, params...)
1929 require.NoError(t, err)
1930
1931 exp := []uint64{
1932 0x62, 0x62, 0x62, 0x61, 0x60, 0x5f, 0x5d, 0x5d, 0x5d, 0x5c, 0x5b, 0x5a, 0x58, 0x58, 0x58, 0x57,
1933 0x56, 0x55, 0x53, 0x53, 0x53, 0x52, 0x51, 0x50, 0x4e, 0x4e, 0x4e, 0x4d, 0x4c, 0x4b, 0x49, 0x49,
1934 0x49, 0x48, 0x47, 0x46, 0x44, 0x44, 0x44, 0x43, 0x42, 0x41, 0x3f, 0x3f, 0x3f, 0x3e, 0x3d, 0x3c,
1935 0x3a, 0x3a, 0x3a, 0x39, 0x38, 0x37, 0x35, 0x35, 0x35, 0x34, 0x33, 0x32, 0x30, 0x30, 0x30, 0x2f,
1936 0x2e, 0x2d, 0x2b, 0x2b, 0x2b, 0x2a, 0x29, 0x28, 0x26, 0x26, 0x26, 0x25, 0x24, 0x23, 0x21, 0x21,
1937 0x21, 0x20, 0x1f, 0x1e, 0x1c, 0x1c, 0x1c, 0x1b, 0x1a, 0x19, 0x17, 0x17, 0x17, 0x16, 0x15, 0x14,
1938 0x12, 0x12, 0x12, 0x11, 0x10, 0xf, 0xd, 0xd, 0xd, 0xc, 0xb, 0xa, 0x8, 0x8, 0x8, 0x7, 0x6, 0x5,
1939 0x3, 0x3, 0x3, 0x2, 0x1, 0x0,
1940 }
1941 require.Equal(t, exp, results)
1942 }
1943
1944 func testManyParamsResultsSwapperListener(t *testing.T, r wazero.Runtime) {
1945 var buf bytes.Buffer
1946 ctx := context.WithValue(context.Background(), experimental.FunctionListenerFactoryKey{}, logging.NewLoggingListenerFactory(&buf))
1947
1948 bin, params := manyParamsResultsMod()
1949 mod, err := r.Instantiate(ctx, bin)
1950 require.NoError(t, err)
1951
1952 main := mod.ExportedFunction("swapper")
1953 require.NotNil(t, main)
1954
1955 results, err := main.Call(ctx, params...)
1956 require.NoError(t, err)
1957
1958 require.Equal(t, `
1959 --> .swapper([0:i32]=0,[1:i64]=1,[2:f32]=3e-45,[3:f64]=1.5e-323,[4:v128]=00000000000000030000000000000003,[5:i32]=3,[6:i64]=5,[7:f32]=8e-45,[8:f64]=3.5e-323,[9:v128]=00000000000000080000000000000008,[10:i32]=8,[11:i64]=8,[12:f32]=1.4e-44,[13:f64]=5.4e-323,[14:v128]=000000000000000c000000000000000d,[15:i32]=13,[16:i64]=13,[17:f32]=1.8e-44,[18:f64]=7.4e-323,[19:v128]=00000000000000100000000000000011,[20:i32]=17,[21:i64]=18,[22:f32]=2.5e-44,[23:f64]=9e-323,[24:v128]=00000000000000140000000000000015,[25:i32]=21,[26:i64]=22,[27:f32]=3.2e-44,[28:f64]=1.14e-322,[29:v128]=00000000000000170000000000000019,[30:i32]=25,[31:i64]=26,[32:f32]=3.8e-44,[33:f64]=1.4e-322,[34:v128]=000000000000001c000000000000001c,[35:i32]=28,[36:i64]=30,[37:f32]=4.3e-44,[38:f64]=1.6e-322,[39:v128]=00000000000000210000000000000021,[40:i32]=33,[41:i64]=33,[42:f32]=4.9e-44,[43:f64]=1.8e-322,[44:v128]=00000000000000250000000000000026,[45:i32]=38,[46:i64]=38,[47:f32]=5.3e-44,[48:f64]=2e-322,[49:v128]=0000000000000029000000000000002a,[50:i32]=42,[51:i64]=43,[52:f32]=6e-44,[53:f64]=2.1e-322,[54:v128]=000000000000002d000000000000002e,[55:i32]=46,[56:i64]=47,[57:f32]=6.7e-44,[58:f64]=2.37e-322,[59:v128]=00000000000000300000000000000032,[60:i32]=50,[61:i64]=51,[62:f32]=7.3e-44,[63:f64]=2.6e-322,[64:v128]=00000000000000350000000000000035,[65:i32]=53,[66:i64]=55,[67:f32]=7.8e-44,[68:f64]=2.8e-322,[69:v128]=000000000000003a000000000000003a,[70:i32]=58,[71:i64]=58,[72:f32]=8.4e-44,[73:f64]=3e-322,[74:v128]=000000000000003e000000000000003f,[75:i32]=63,[76:i64]=63,[77:f32]=8.8e-44,[78:f64]=3.2e-322,[79:v128]=00000000000000420000000000000043,[80:i32]=67,[81:i64]=68,[82:f32]=9.5e-44,[83:f64]=3.36e-322,[84:v128]=00000000000000460000000000000047,[85:i32]=71,[86:i64]=72,[87:f32]=1.02e-43,[88:f64]=3.6e-322,[89:v128]=0000000000000049000000000000004b,[90:i32]=75,[91:i64]=76,[92:f32]=1.08e-43,[93:f64]=3.85e-322,[94:v128]=000000000000004e000000000000004e,[95:i32]=78,[96:i64]=80,[97:f32]=1.14e-43,[98:f64]=4.05e-322,[99:v128]=00000000000000530000000000000053)
1960 <-- (00000000000000620000000000000062,4.84e-322,1.37e-43,97,96,000000000000005f000000000000005d,4.6e-322,1.3e-43,93,92,000000000000005b000000000000005a,4.45e-322,1.23e-43,88,88,00000000000000570000000000000056,4.25e-322,1.19e-43,83,83,00000000000000530000000000000052,4.05e-322,1.14e-43,80,78,000000000000004e000000000000004e,3.85e-322,1.08e-43,76,75,00000000000000490000000000000049,3.6e-322,1.02e-43,72,71,00000000000000460000000000000044,3.36e-322,9.5e-44,68,67,00000000000000420000000000000041,3.2e-322,8.8e-44,63,63,000000000000003e000000000000003d,3e-322,8.4e-44,58,58,000000000000003a0000000000000039,2.8e-322,7.8e-44,55,53,00000000000000350000000000000035,2.6e-322,7.3e-44,51,50,00000000000000300000000000000030,2.37e-322,6.7e-44,47,46,000000000000002d000000000000002b,2.1e-322,6e-44,43,42,00000000000000290000000000000028,2e-322,5.3e-44,38,38,00000000000000250000000000000024,1.8e-322,4.9e-44,33,33,00000000000000210000000000000020,1.6e-322,4.3e-44,30,28,000000000000001c000000000000001c,1.4e-322,3.8e-44,26,25,00000000000000170000000000000017,1.14e-322,3.2e-44,22,21,00000000000000140000000000000012,9e-323,2.5e-44,18,17)
1961 `, "\n"+buf.String())
1962
1963 exp := []uint64{
1964 0x62, 0x62, 0x62, 0x61, 0x60, 0x5f, 0x5d, 0x5d, 0x5d, 0x5c, 0x5b, 0x5a, 0x58, 0x58, 0x58, 0x57,
1965 0x56, 0x55, 0x53, 0x53, 0x53, 0x52, 0x51, 0x50, 0x4e, 0x4e, 0x4e, 0x4d, 0x4c, 0x4b, 0x49, 0x49,
1966 0x49, 0x48, 0x47, 0x46, 0x44, 0x44, 0x44, 0x43, 0x42, 0x41, 0x3f, 0x3f, 0x3f, 0x3e, 0x3d, 0x3c,
1967 0x3a, 0x3a, 0x3a, 0x39, 0x38, 0x37, 0x35, 0x35, 0x35, 0x34, 0x33, 0x32, 0x30, 0x30, 0x30, 0x2f,
1968 0x2e, 0x2d, 0x2b, 0x2b, 0x2b, 0x2a, 0x29, 0x28, 0x26, 0x26, 0x26, 0x25, 0x24, 0x23, 0x21, 0x21,
1969 0x21, 0x20, 0x1f, 0x1e, 0x1c, 0x1c, 0x1c, 0x1b, 0x1a, 0x19, 0x17, 0x17, 0x17, 0x16, 0x15, 0x14,
1970 0x12, 0x12, 0x12, 0x11, 0x10, 0xf, 0xd, 0xd, 0xd, 0xc, 0xb, 0xa, 0x8, 0x8, 0x8, 0x7, 0x6, 0x5,
1971 0x3, 0x3, 0x3, 0x2, 0x1, 0x0,
1972 }
1973 require.Equal(t, exp, results)
1974 }
1975
1976 func testManyParamsResultsMain(t *testing.T, r wazero.Runtime) {
1977 ctx := context.Background()
1978
1979 bin, params := manyParamsResultsMod()
1980 mod, err := r.Instantiate(ctx, bin)
1981 require.NoError(t, err)
1982
1983 main := mod.ExportedFunction("main")
1984 require.NotNil(t, main)
1985
1986 results, err := main.Call(ctx, params...)
1987 require.NoError(t, err)
1988
1989 exp := []uint64{
1990 98, 98, 196, 194, 192, 190, 93, 93, 186, 184, 182, 180, 88, 88, 176, 174, 172, 170, 83, 83, 166, 164, 162,
1991 160, 78, 78, 156, 154, 152, 150, 73, 73, 146, 144, 142, 140, 68, 68, 136, 134, 132, 130, 63, 63, 126, 124,
1992 122, 120, 58, 58, 116, 114, 112, 110, 53, 53, 106, 104, 102, 100, 48, 48, 96, 94, 92, 90, 43, 43, 86, 84,
1993 82, 80, 38, 38, 76, 74, 72, 70, 33, 33, 66, 64, 62, 60, 28, 28, 56, 54, 52, 50, 23, 23, 46, 44, 42, 40, 18,
1994 18, 36, 34, 32, 30, 13, 13, 26, 24, 22, 20, 8, 8, 16, 14, 12, 10, 3, 3, 6, 4, 2, 0,
1995 }
1996 require.Equal(t, exp, results)
1997 }
1998
1999 func testManyParamsResultsMainListener(t *testing.T, r wazero.Runtime) {
2000 var buf bytes.Buffer
2001 ctx := context.WithValue(context.Background(), experimental.FunctionListenerFactoryKey{}, logging.NewLoggingListenerFactory(&buf))
2002
2003 bin, params := manyParamsResultsMod()
2004 mod, err := r.Instantiate(ctx, bin)
2005 require.NoError(t, err)
2006
2007 main := mod.ExportedFunction("main")
2008 require.NotNil(t, main)
2009
2010 results, err := main.Call(ctx, params...)
2011 require.NoError(t, err)
2012
2013 require.Equal(t, `
2014 --> .main([0:i32]=0,[1:i64]=1,[2:f32]=3e-45,[3:f64]=1.5e-323,[4:v128]=00000000000000030000000000000003,[5:i32]=3,[6:i64]=5,[7:f32]=8e-45,[8:f64]=3.5e-323,[9:v128]=00000000000000080000000000000008,[10:i32]=8,[11:i64]=8,[12:f32]=1.4e-44,[13:f64]=5.4e-323,[14:v128]=000000000000000c000000000000000d,[15:i32]=13,[16:i64]=13,[17:f32]=1.8e-44,[18:f64]=7.4e-323,[19:v128]=00000000000000100000000000000011,[20:i32]=17,[21:i64]=18,[22:f32]=2.5e-44,[23:f64]=9e-323,[24:v128]=00000000000000140000000000000015,[25:i32]=21,[26:i64]=22,[27:f32]=3.2e-44,[28:f64]=1.14e-322,[29:v128]=00000000000000170000000000000019,[30:i32]=25,[31:i64]=26,[32:f32]=3.8e-44,[33:f64]=1.4e-322,[34:v128]=000000000000001c000000000000001c,[35:i32]=28,[36:i64]=30,[37:f32]=4.3e-44,[38:f64]=1.6e-322,[39:v128]=00000000000000210000000000000021,[40:i32]=33,[41:i64]=33,[42:f32]=4.9e-44,[43:f64]=1.8e-322,[44:v128]=00000000000000250000000000000026,[45:i32]=38,[46:i64]=38,[47:f32]=5.3e-44,[48:f64]=2e-322,[49:v128]=0000000000000029000000000000002a,[50:i32]=42,[51:i64]=43,[52:f32]=6e-44,[53:f64]=2.1e-322,[54:v128]=000000000000002d000000000000002e,[55:i32]=46,[56:i64]=47,[57:f32]=6.7e-44,[58:f64]=2.37e-322,[59:v128]=00000000000000300000000000000032,[60:i32]=50,[61:i64]=51,[62:f32]=7.3e-44,[63:f64]=2.6e-322,[64:v128]=00000000000000350000000000000035,[65:i32]=53,[66:i64]=55,[67:f32]=7.8e-44,[68:f64]=2.8e-322,[69:v128]=000000000000003a000000000000003a,[70:i32]=58,[71:i64]=58,[72:f32]=8.4e-44,[73:f64]=3e-322,[74:v128]=000000000000003e000000000000003f,[75:i32]=63,[76:i64]=63,[77:f32]=8.8e-44,[78:f64]=3.2e-322,[79:v128]=00000000000000420000000000000043,[80:i32]=67,[81:i64]=68,[82:f32]=9.5e-44,[83:f64]=3.36e-322,[84:v128]=00000000000000460000000000000047,[85:i32]=71,[86:i64]=72,[87:f32]=1.02e-43,[88:f64]=3.6e-322,[89:v128]=0000000000000049000000000000004b,[90:i32]=75,[91:i64]=76,[92:f32]=1.08e-43,[93:f64]=3.85e-322,[94:v128]=000000000000004e000000000000004e,[95:i32]=78,[96:i64]=80,[97:f32]=1.14e-43,[98:f64]=4.05e-322,[99:v128]=00000000000000530000000000000053)
2015 --> .swapper([0:i32]=0,[1:i64]=1,[2:f32]=3e-45,[3:f64]=1.5e-323,[4:v128]=00000000000000030000000000000003,[5:i32]=3,[6:i64]=5,[7:f32]=8e-45,[8:f64]=3.5e-323,[9:v128]=00000000000000080000000000000008,[10:i32]=8,[11:i64]=8,[12:f32]=1.4e-44,[13:f64]=5.4e-323,[14:v128]=000000000000000c000000000000000d,[15:i32]=13,[16:i64]=13,[17:f32]=1.8e-44,[18:f64]=7.4e-323,[19:v128]=00000000000000100000000000000011,[20:i32]=17,[21:i64]=18,[22:f32]=2.5e-44,[23:f64]=9e-323,[24:v128]=00000000000000140000000000000015,[25:i32]=21,[26:i64]=22,[27:f32]=3.2e-44,[28:f64]=1.14e-322,[29:v128]=00000000000000170000000000000019,[30:i32]=25,[31:i64]=26,[32:f32]=3.8e-44,[33:f64]=1.4e-322,[34:v128]=000000000000001c000000000000001c,[35:i32]=28,[36:i64]=30,[37:f32]=4.3e-44,[38:f64]=1.6e-322,[39:v128]=00000000000000210000000000000021,[40:i32]=33,[41:i64]=33,[42:f32]=4.9e-44,[43:f64]=1.8e-322,[44:v128]=00000000000000250000000000000026,[45:i32]=38,[46:i64]=38,[47:f32]=5.3e-44,[48:f64]=2e-322,[49:v128]=0000000000000029000000000000002a,[50:i32]=42,[51:i64]=43,[52:f32]=6e-44,[53:f64]=2.1e-322,[54:v128]=000000000000002d000000000000002e,[55:i32]=46,[56:i64]=47,[57:f32]=6.7e-44,[58:f64]=2.37e-322,[59:v128]=00000000000000300000000000000032,[60:i32]=50,[61:i64]=51,[62:f32]=7.3e-44,[63:f64]=2.6e-322,[64:v128]=00000000000000350000000000000035,[65:i32]=53,[66:i64]=55,[67:f32]=7.8e-44,[68:f64]=2.8e-322,[69:v128]=000000000000003a000000000000003a,[70:i32]=58,[71:i64]=58,[72:f32]=8.4e-44,[73:f64]=3e-322,[74:v128]=000000000000003e000000000000003f,[75:i32]=63,[76:i64]=63,[77:f32]=8.8e-44,[78:f64]=3.2e-322,[79:v128]=00000000000000420000000000000043,[80:i32]=67,[81:i64]=68,[82:f32]=9.5e-44,[83:f64]=3.36e-322,[84:v128]=00000000000000460000000000000047,[85:i32]=71,[86:i64]=72,[87:f32]=1.02e-43,[88:f64]=3.6e-322,[89:v128]=0000000000000049000000000000004b,[90:i32]=75,[91:i64]=76,[92:f32]=1.08e-43,[93:f64]=3.85e-322,[94:v128]=000000000000004e000000000000004e,[95:i32]=78,[96:i64]=80,[97:f32]=1.14e-43,[98:f64]=4.05e-322,[99:v128]=00000000000000530000000000000053)
2016 <-- (00000000000000620000000000000062,4.84e-322,1.37e-43,97,96,000000000000005f000000000000005d,4.6e-322,1.3e-43,93,92,000000000000005b000000000000005a,4.45e-322,1.23e-43,88,88,00000000000000570000000000000056,4.25e-322,1.19e-43,83,83,00000000000000530000000000000052,4.05e-322,1.14e-43,80,78,000000000000004e000000000000004e,3.85e-322,1.08e-43,76,75,00000000000000490000000000000049,3.6e-322,1.02e-43,72,71,00000000000000460000000000000044,3.36e-322,9.5e-44,68,67,00000000000000420000000000000041,3.2e-322,8.8e-44,63,63,000000000000003e000000000000003d,3e-322,8.4e-44,58,58,000000000000003a0000000000000039,2.8e-322,7.8e-44,55,53,00000000000000350000000000000035,2.6e-322,7.3e-44,51,50,00000000000000300000000000000030,2.37e-322,6.7e-44,47,46,000000000000002d000000000000002b,2.1e-322,6e-44,43,42,00000000000000290000000000000028,2e-322,5.3e-44,38,38,00000000000000250000000000000024,1.8e-322,4.9e-44,33,33,00000000000000210000000000000020,1.6e-322,4.3e-44,30,28,000000000000001c000000000000001c,1.4e-322,3.8e-44,26,25,00000000000000170000000000000017,1.14e-322,3.2e-44,22,21,00000000000000140000000000000012,9e-323,2.5e-44,18,17)
2017 --> .doubler([0:v128]=00000000000000620000000000000062,[1:f64]=4.84e-322,[2:f32]=1.37e-43,[3:i64]=97,[4:i32]=96,[5:v128]=000000000000005f000000000000005d,[6:f64]=4.6e-322,[7:f32]=1.3e-43,[8:i64]=93,[9:i32]=92,[10:v128]=000000000000005b000000000000005a,[11:f64]=4.45e-322,[12:f32]=1.23e-43,[13:i64]=88,[14:i32]=88,[15:v128]=00000000000000570000000000000056,[16:f64]=4.25e-322,[17:f32]=1.19e-43,[18:i64]=83,[19:i32]=83,[20:v128]=00000000000000530000000000000052,[21:f64]=4.05e-322,[22:f32]=1.14e-43,[23:i64]=80,[24:i32]=78,[25:v128]=000000000000004e000000000000004e,[26:f64]=3.85e-322,[27:f32]=1.08e-43,[28:i64]=76,[29:i32]=75,[30:v128]=00000000000000490000000000000049,[31:f64]=3.6e-322,[32:f32]=1.02e-43,[33:i64]=72,[34:i32]=71,[35:v128]=00000000000000460000000000000044,[36:f64]=3.36e-322,[37:f32]=9.5e-44,[38:i64]=68,[39:i32]=67,[40:v128]=00000000000000420000000000000041,[41:f64]=3.2e-322,[42:f32]=8.8e-44,[43:i64]=63,[44:i32]=63,[45:v128]=000000000000003e000000000000003d,[46:f64]=3e-322,[47:f32]=8.4e-44,[48:i64]=58,[49:i32]=58,[50:v128]=000000000000003a0000000000000039,[51:f64]=2.8e-322,[52:f32]=7.8e-44,[53:i64]=55,[54:i32]=53,[55:v128]=00000000000000350000000000000035,[56:f64]=2.6e-322,[57:f32]=7.3e-44,[58:i64]=51,[59:i32]=50,[60:v128]=00000000000000300000000000000030,[61:f64]=2.37e-322,[62:f32]=6.7e-44,[63:i64]=47,[64:i32]=46,[65:v128]=000000000000002d000000000000002b,[66:f64]=2.1e-322,[67:f32]=6e-44,[68:i64]=43,[69:i32]=42,[70:v128]=00000000000000290000000000000028,[71:f64]=2e-322,[72:f32]=5.3e-44,[73:i64]=38,[74:i32]=38,[75:v128]=00000000000000250000000000000024,[76:f64]=1.8e-322,[77:f32]=4.9e-44,[78:i64]=33,[79:i32]=33,[80:v128]=00000000000000210000000000000020,[81:f64]=1.6e-322,[82:f32]=4.3e-44,[83:i64]=30,[84:i32]=28,[85:v128]=000000000000001c000000000000001c,[86:f64]=1.4e-322,[87:f32]=3.8e-44,[88:i64]=26,[89:i32]=25,[90:v128]=00000000000000170000000000000017,[91:f64]=1.14e-322,[92:f32]=3.2e-44,[93:i64]=22,[94:i32]=21,[95:v128]=00000000000000140000000000000012,[96:f64]=9e-323,[97:f32]=2.5e-44,[98:i64]=18,[99:i32]=17)
2018 <-- (00000000000000620000000000000062,4.84e-322,2.75e-43,194,192,00000000000000be000000000000005d,4.6e-322,1.3e-43,186,184,00000000000000b600000000000000b4,8.9e-322,1.23e-43,88,176,00000000000000ae00000000000000ac,8.5e-322,2.38e-43,83,83,00000000000000a600000000000000a4,8.1e-322,2.27e-43,160,78,000000000000004e000000000000009c,7.7e-322,2.16e-43,152,150,00000000000000490000000000000049,3.6e-322,2.05e-43,144,142,000000000000008c0000000000000044,3.36e-322,9.5e-44,136,134,00000000000000840000000000000082,6.4e-322,8.8e-44,63,126,000000000000007c000000000000007a,6.03e-322,1.68e-43,58,58,00000000000000740000000000000072,5.63e-322,1.57e-43,110,53,0000000000000035000000000000006a,5.24e-322,1.46e-43,102,100,00000000000000300000000000000030,2.37e-322,1.35e-43,94,92,000000000000005a000000000000002b,2.1e-322,6e-44,86,84,00000000000000520000000000000050,3.95e-322,5.3e-44,38,76,000000000000004a0000000000000048,3.56e-322,9.8e-44,33,33,00000000000000420000000000000040,3.16e-322,8.7e-44,60,28,000000000000001c0000000000000038,2.77e-322,7.6e-44,52,50,00000000000000170000000000000017,1.14e-322,6.4e-44,44,42,00000000000000280000000000000012,9e-323,2.5e-44,36,34)
2019 <-- (00000000000000620000000000000062,4.84e-322,2.75e-43,194,192,00000000000000be000000000000005d,4.6e-322,1.3e-43,186,184,00000000000000b600000000000000b4,8.9e-322,1.23e-43,88,176,00000000000000ae00000000000000ac,8.5e-322,2.38e-43,83,83,00000000000000a600000000000000a4,8.1e-322,2.27e-43,160,78,000000000000004e000000000000009c,7.7e-322,2.16e-43,152,150,00000000000000490000000000000049,3.6e-322,2.05e-43,144,142,000000000000008c0000000000000044,3.36e-322,9.5e-44,136,134,00000000000000840000000000000082,6.4e-322,8.8e-44,63,126,000000000000007c000000000000007a,6.03e-322,1.68e-43,58,58,00000000000000740000000000000072,5.63e-322,1.57e-43,110,53,0000000000000035000000000000006a,5.24e-322,1.46e-43,102,100,00000000000000300000000000000030,2.37e-322,1.35e-43,94,92,000000000000005a000000000000002b,2.1e-322,6e-44,86,84,00000000000000520000000000000050,3.95e-322,5.3e-44,38,76,000000000000004a0000000000000048,3.56e-322,9.8e-44,33,33,00000000000000420000000000000040,3.16e-322,8.7e-44,60,28,000000000000001c0000000000000038,2.77e-322,7.6e-44,52,50,00000000000000170000000000000017,1.14e-322,6.4e-44,44,42,00000000000000280000000000000012,9e-323,2.5e-44,36,34)
2020 `, "\n"+buf.String())
2021
2022 exp := []uint64{
2023 98, 98, 196, 194, 192, 190, 93, 93, 186, 184, 182, 180, 88, 88, 176, 174, 172, 170, 83, 83, 166, 164, 162,
2024 160, 78, 78, 156, 154, 152, 150, 73, 73, 146, 144, 142, 140, 68, 68, 136, 134, 132, 130, 63, 63, 126, 124,
2025 122, 120, 58, 58, 116, 114, 112, 110, 53, 53, 106, 104, 102, 100, 48, 48, 96, 94, 92, 90, 43, 43, 86, 84,
2026 82, 80, 38, 38, 76, 74, 72, 70, 33, 33, 66, 64, 62, 60, 28, 28, 56, 54, 52, 50, 23, 23, 46, 44, 42, 40, 18,
2027 18, 36, 34, 32, 30, 13, 13, 26, 24, 22, 20, 8, 8, 16, 14, 12, 10, 3, 3, 6, 4, 2, 0,
2028 }
2029 require.Equal(t, exp, results)
2030 }
2031
2032 func testManyParamsResultsCallManyConstsAndPickLastVector(t *testing.T, r wazero.Runtime) {
2033 ctx := context.Background()
2034
2035 bin, _ := manyParamsResultsMod()
2036 mod, err := r.Instantiate(ctx, bin)
2037 require.NoError(t, err)
2038
2039 main := mod.ExportedFunction("call_many_consts_and_pick_last_vector")
2040 require.NotNil(t, main)
2041
2042 results, err := main.Call(ctx)
2043 require.NoError(t, err)
2044 exp := []uint64{0x5f5f5f5f5f5f5f5f, 0x5f5f5f5f5f5f5f5f}
2045 require.Equal(t, exp, results)
2046 }
2047
2048 func testManyParamsResultsCallManyConstsAndPickLastVectorListener(t *testing.T, r wazero.Runtime) {
2049 var buf bytes.Buffer
2050 ctx := context.WithValue(context.Background(), experimental.FunctionListenerFactoryKey{}, logging.NewLoggingListenerFactory(&buf))
2051
2052 bin, _ := manyParamsResultsMod()
2053 mod, err := r.Instantiate(ctx, bin)
2054 require.NoError(t, err)
2055
2056 main := mod.ExportedFunction("call_many_consts_and_pick_last_vector")
2057 require.NotNil(t, main)
2058
2059 results, err := main.Call(ctx)
2060 require.NoError(t, err)
2061 exp := []uint64{0x5f5f5f5f5f5f5f5f, 0x5f5f5f5f5f5f5f5f}
2062 require.Equal(t, exp, results)
2063
2064 require.Equal(t, `
2065 --> .call_many_consts_and_pick_last_vector()
2066 --> .many_consts()
2067 <-- (0,0,0,0,00000000000000000000000000000000,0,5,7e-45,4.16077606e-316,05050505050505050505050505050505,84215045,361700864190383365,1.4e-44,5e-323,000000000a0a0a0a0a0a0a0a0a0a0a0a,168430090,723401728380766730,6.6463464e-33,7.4e-323,000000000000000f000000000f0f0f0f,252645135,1085102592571150095,7.0533445e-30,3.815736827118017e-236,00000000000000140000000000000014,20,336860180,7.47605e-27,5.964208835435795e-212,14141414141414140000000000000019,25,25,7.914983e-24,9.01285756841504e-188,19191919191919191919191919191919,421075225,30,4.2e-44,2.496465636e-315,1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e,505290270,2170205185142300190,4.9e-44,1.73e-322,00000000232323232323232323232323,589505315,2531906049332683555,8.843688e-18,2e-322,00000000000000280000000028282828,673720360,2893606913523066920,9.334581e-15,3.0654356309538037e-115,000000000000002d000000000000002d,45,757935405,9.8439425e-12,4.4759381595361623e-91,2d2d2d2d2d2d2d2d0000000000000032,50,50,1.0372377e-08,6.749300603603778e-67,32323232323232323232323232323232,842150450,55,7.7e-44,4.576853666e-315,37373737373737373737373737373737,926365495,3978709506094217015,8.4e-44,2.96e-322,000000003c3c3c3c3c3c3c3c3c3c3c3c,1010580540,4340410370284600380,0.01148897,3.2e-322,00000000000000410000000041414141,1094795585,4702111234474983745,12.078431,2.2616345098039214e+06,00000000000000460000000000000046,70,1179010630,12689.568,3.5295369653413445e+30,4646464646464646000000000000004b,75,75,1.3323083e+07,5.2285141982483265e+54,4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b,1263225675,80,1.12e-43,6.657241696e-315,50505050505050505050505050505050)
2068 --> .pick_last_vector([0:i32]=0,[1:i64]=0,[2:f32]=0,[3:f64]=0,[4:v128]=00000000000000000000000000000000,[5:i32]=0,[6:i64]=5,[7:f32]=7e-45,[8:f64]=4.16077606e-316,[9:v128]=05050505050505050505050505050505,[10:i32]=84215045,[11:i64]=361700864190383365,[12:f32]=1.4e-44,[13:f64]=5e-323,[14:v128]=000000000a0a0a0a0a0a0a0a0a0a0a0a,[15:i32]=168430090,[16:i64]=723401728380766730,[17:f32]=6.6463464e-33,[18:f64]=7.4e-323,[19:v128]=000000000000000f000000000f0f0f0f,[20:i32]=252645135,[21:i64]=1085102592571150095,[22:f32]=7.0533445e-30,[23:f64]=3.815736827118017e-236,[24:v128]=00000000000000140000000000000014,[25:i32]=20,[26:i64]=336860180,[27:f32]=7.47605e-27,[28:f64]=5.964208835435795e-212,[29:v128]=14141414141414140000000000000019,[30:i32]=25,[31:i64]=25,[32:f32]=7.914983e-24,[33:f64]=9.01285756841504e-188,[34:v128]=19191919191919191919191919191919,[35:i32]=421075225,[36:i64]=30,[37:f32]=4.2e-44,[38:f64]=2.496465636e-315,[39:v128]=1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e,[40:i32]=505290270,[41:i64]=2170205185142300190,[42:f32]=4.9e-44,[43:f64]=1.73e-322,[44:v128]=00000000232323232323232323232323,[45:i32]=589505315,[46:i64]=2531906049332683555,[47:f32]=8.843688e-18,[48:f64]=2e-322,[49:v128]=00000000000000280000000028282828,[50:i32]=673720360,[51:i64]=2893606913523066920,[52:f32]=9.334581e-15,[53:f64]=3.0654356309538037e-115,[54:v128]=000000000000002d000000000000002d,[55:i32]=45,[56:i64]=757935405,[57:f32]=9.8439425e-12,[58:f64]=4.4759381595361623e-91,[59:v128]=2d2d2d2d2d2d2d2d0000000000000032,[60:i32]=50,[61:i64]=50,[62:f32]=1.0372377e-08,[63:f64]=6.749300603603778e-67,[64:v128]=32323232323232323232323232323232,[65:i32]=842150450,[66:i64]=55,[67:f32]=7.7e-44,[68:f64]=4.576853666e-315,[69:v128]=37373737373737373737373737373737,[70:i32]=926365495,[71:i64]=3978709506094217015,[72:f32]=8.4e-44,[73:f64]=2.96e-322,[74:v128]=000000003c3c3c3c3c3c3c3c3c3c3c3c,[75:i32]=1010580540,[76:i64]=4340410370284600380,[77:f32]=0.01148897,[78:f64]=3.2e-322,[79:v128]=00000000000000410000000041414141,[80:i32]=1094795585,[81:i64]=4702111234474983745,[82:f32]=12.078431,[83:f64]=2.2616345098039214e+06,[84:v128]=00000000000000460000000000000046,[85:i32]=70,[86:i64]=1179010630,[87:f32]=12689.568,[88:f64]=3.5295369653413445e+30,[89:v128]=4646464646464646000000000000004b,[90:i32]=75,[91:i64]=75,[92:f32]=1.3323083e+07,[93:f64]=5.2285141982483265e+54,[94:v128]=4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b,[95:i32]=1263225675,[96:i64]=80,[97:f32]=1.12e-43,[98:f64]=6.657241696e-315,[99:v128]=50505050505050505050505050505050)
2069 <-- 5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f
2070 <-- 5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f
2071 `, "\n"+buf.String())
2072 }
2073
2074 func testImportedMutableGlobalUpdate(t *testing.T, r wazero.Runtime) {
2075 importedBin := binaryencoding.EncodeModule(&wasm.Module{
2076 ExportSection: []wasm.Export{
2077 {Name: "g", Type: wasm.ExternTypeGlobal, Index: 0},
2078 },
2079 GlobalSection: []wasm.Global{
2080 {
2081 Type: wasm.GlobalType{ValType: i32, Mutable: true},
2082 Init: wasm.ConstantExpression{Opcode: wasm.OpcodeI32Const, Data: []byte{1}},
2083 },
2084 },
2085 NameSection: &wasm.NameSection{ModuleName: "imported"},
2086 })
2087
2088 mainBin := binaryencoding.EncodeModule(&wasm.Module{
2089 ImportSection: []wasm.Import{{
2090 Type: wasm.ExternTypeGlobal,
2091 Module: "imported",
2092 Name: "g",
2093 DescGlobal: wasm.GlobalType{ValType: i32, Mutable: true},
2094 }},
2095 TypeSection: []wasm.FunctionType{{Results: []wasm.ValueType{i32}}},
2096 ExportSection: []wasm.Export{
2097 {Name: "", Type: wasm.ExternTypeFunc, Index: 0},
2098 {Name: "g", Type: wasm.ExternTypeGlobal, Index: 0},
2099 },
2100 FunctionSection: []wasm.Index{0},
2101 CodeSection: []wasm.Code{
2102 {Body: []byte{
2103 wasm.OpcodeGlobalGet, 0,
2104 wasm.OpcodeI32Const, 2,
2105 wasm.OpcodeGlobalSet, 0,
2106 wasm.OpcodeEnd,
2107 }},
2108 },
2109 })
2110
2111 ctx := context.Background()
2112 importedMod, err := r.Instantiate(ctx, importedBin)
2113 require.NoError(t, err)
2114
2115 mainMod, err := r.Instantiate(ctx, mainBin)
2116 require.NoError(t, err)
2117
2118 main := mainMod.ExportedFunction("")
2119 require.NotNil(t, main)
2120
2121 res, err := main.Call(ctx)
2122 require.NoError(t, err)
2123
2124 prevValue := res[0]
2125 require.Equal(t, uint64(1), prevValue)
2126
2127 g := importedMod.ExportedGlobal("g")
2128 require.NotNil(t, g)
2129
2130 v := g.Get()
2131 require.Equal(t, uint64(2), v)
2132
2133 reExportedG := mainMod.ExportedGlobal("g")
2134 v = reExportedG.Get()
2135 require.Equal(t, uint64(2), v)
2136 }
2137
View as plain text