Skip to content

Commit

Permalink
wazevo(frontend): missing listener.After call in br_if target (tetrat…
Browse files Browse the repository at this point in the history
…elabs#2078)

Signed-off-by: Takeshi Yoneda <[email protected]>
  • Loading branch information
mathetake authored and evacchi committed Feb 28, 2024
1 parent 356379b commit 6eb679c
Show file tree
Hide file tree
Showing 8 changed files with 264 additions and 203 deletions.
25 changes: 25 additions & 0 deletions internal/engine/wazevo/frontend/lower.go
Original file line number Diff line number Diff line change
Expand Up @@ -1498,12 +1498,37 @@ func (c *Compiler) lowerCurrentOpcode() {

targetBlk, argNum := state.brTargetArgNumFor(labelIndex)
args := c.nPeekDup(argNum)
var sealTargetBlk bool
if c.needListener && targetBlk.ReturnBlock() { // In this case, we have to call the listener before returning.
// Save the currently active block.
current := builder.CurrentBlock()

// Allocate the trampoline block to the return where we call the listener.
targetBlk = builder.AllocateBasicBlock()
builder.SetCurrentBlock(targetBlk)
sealTargetBlk = true

c.callListenerAfter()

instr := builder.AllocateInstruction()
instr.AsReturn(args)
builder.InsertInstruction(instr)

args = ssa.ValuesNil

// Revert the current block.
builder.SetCurrentBlock(current)
}

// Insert the conditional jump to the target block.
brnz := builder.AllocateInstruction()
brnz.AsBrnz(v, args, targetBlk)
builder.InsertInstruction(brnz)

if sealTargetBlk {
builder.Seal(targetBlk)
}

// Insert the unconditional jump to the Else block which corresponds to after br_if.
elseBlk := builder.AllocateBasicBlock()
c.insertJumpToBlock(ssa.ValuesNil, elseBlk)
Expand Down
3 changes: 2 additions & 1 deletion internal/integration_test/fuzz/wazerolib/extern.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"github.com/tetratelabs/wazero/experimental/opt"
"github.com/tetratelabs/wazero/internal/leb128"
"github.com/tetratelabs/wazero/internal/testing/binaryencoding"
"github.com/tetratelabs/wazero/internal/testing/nodiff"
"github.com/tetratelabs/wazero/internal/wasm"
)

Expand All @@ -37,7 +38,7 @@ func require_no_diff(binaryPtr uintptr, binarySize int, checkMemory bool, checkL
}
}()

requireNoDiff(wasmBin, checkMemory, checkLogging, func(err error) {
nodiff.RequireNoDiff(wasmBin, checkMemory, checkLogging, func(err error) {
if err != nil {
panic(err)
}
Expand Down
201 changes: 2 additions & 199 deletions internal/integration_test/fuzz/wazerolib/nodiff_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import (
"os"
"testing"

"github.com/tetratelabs/wazero/internal/testing/nodiff"
"github.com/tetratelabs/wazero/internal/testing/require"
"github.com/tetratelabs/wazero/internal/wasm"
)

// TestReRunFailedRequireNoDiffCase re-runs the failed case specified by WASM_BINARY_NAME in testdata directory.
Expand All @@ -17,202 +17,5 @@ func TestReRunFailedRequireNoDiffCase(t *testing.T) {
t.Skip(err)
}

requireNoDiff(wasmBin, true, true, func(err error) { require.NoError(t, err) })
}

func Test_ensureMutableGlobalsMatch(t *testing.T) {
for _, tc := range []struct {
name string
cm, im *wasm.ModuleInstance
expErr string
}{
{
name: "no globals",
cm: &wasm.ModuleInstance{},
im: &wasm.ModuleInstance{},
},
{
name: "i32 match",
cm: &wasm.ModuleInstance{
Globals: []*wasm.GlobalInstance{
{Type: wasm.GlobalType{ValType: wasm.ValueTypeV128}},
{Val: 10, Type: wasm.GlobalType{Mutable: true, ValType: wasm.ValueTypeI32}},
},
},
im: &wasm.ModuleInstance{
Globals: []*wasm.GlobalInstance{
{Type: wasm.GlobalType{ValType: wasm.ValueTypeV128}},
{Val: 10, Type: wasm.GlobalType{Mutable: true, ValType: wasm.ValueTypeI32}},
},
},
},
{
name: "i32 match not match",
cm: &wasm.ModuleInstance{
Globals: []*wasm.GlobalInstance{
{Type: wasm.GlobalType{ValType: wasm.ValueTypeV128}},
{Val: 10, Type: wasm.GlobalType{Mutable: true, ValType: wasm.ValueTypeI32}},
},
},
im: &wasm.ModuleInstance{
Globals: []*wasm.GlobalInstance{
{Type: wasm.GlobalType{ValType: wasm.ValueTypeV128}},
{Val: 11, Type: wasm.GlobalType{Mutable: true, ValType: wasm.ValueTypeI32}},
},
},
expErr: `mutable globals mismatch:
[1] i32: 10 != 11`,
},
{
name: "i64 match",
cm: &wasm.ModuleInstance{
Globals: []*wasm.GlobalInstance{
{Type: wasm.GlobalType{ValType: wasm.ValueTypeV128}},
{Val: 1 << 62, Type: wasm.GlobalType{Mutable: true, ValType: wasm.ValueTypeI64}},
},
},
im: &wasm.ModuleInstance{
Globals: []*wasm.GlobalInstance{
{Type: wasm.GlobalType{ValType: wasm.ValueTypeV128}},
{Val: 1 << 62, Type: wasm.GlobalType{Mutable: true, ValType: wasm.ValueTypeI64}},
},
},
},
{
name: "i64 match not match",
cm: &wasm.ModuleInstance{
Globals: []*wasm.GlobalInstance{
{Type: wasm.GlobalType{ValType: wasm.ValueTypeV128}},
{Type: wasm.GlobalType{ValType: wasm.ValueTypeV128}},
{Val: 1 << 62, Type: wasm.GlobalType{Mutable: true, ValType: wasm.ValueTypeI64}},
},
},
im: &wasm.ModuleInstance{
Globals: []*wasm.GlobalInstance{
{Type: wasm.GlobalType{ValType: wasm.ValueTypeV128}},
{Type: wasm.GlobalType{ValType: wasm.ValueTypeV128}},
{Val: 1 << 63, Type: wasm.GlobalType{Mutable: true, ValType: wasm.ValueTypeI64}},
},
},
expErr: `mutable globals mismatch:
[2] i64: 4611686018427387904 != 9223372036854775808`,
},
{
name: "f32 match",
cm: &wasm.ModuleInstance{
Globals: []*wasm.GlobalInstance{
{Type: wasm.GlobalType{ValType: wasm.ValueTypeV128}},
{Val: 10, Type: wasm.GlobalType{Mutable: true, ValType: wasm.ValueTypeF32}},
},
},
im: &wasm.ModuleInstance{
Globals: []*wasm.GlobalInstance{
{Type: wasm.GlobalType{ValType: wasm.ValueTypeV128}},
{Val: 10, Type: wasm.GlobalType{Mutable: true, ValType: wasm.ValueTypeF32}},
},
},
},
{
name: "f32 match not match",
cm: &wasm.ModuleInstance{
Globals: []*wasm.GlobalInstance{
{Type: wasm.GlobalType{ValType: wasm.ValueTypeV128}},
{Val: 10, Type: wasm.GlobalType{Mutable: true, ValType: wasm.ValueTypeF32}},
},
},
im: &wasm.ModuleInstance{
Globals: []*wasm.GlobalInstance{
{Type: wasm.GlobalType{ValType: wasm.ValueTypeV128}},
{Val: 11, Type: wasm.GlobalType{Mutable: true, ValType: wasm.ValueTypeF32}},
},
},
expErr: `mutable globals mismatch:
[1] f32: 10 != 11`,
},
{
name: "f64 match",
cm: &wasm.ModuleInstance{
Globals: []*wasm.GlobalInstance{
{Type: wasm.GlobalType{ValType: wasm.ValueTypeV128}},
{Val: 1 << 62, Type: wasm.GlobalType{Mutable: true, ValType: wasm.ValueTypeF64}},
},
},
im: &wasm.ModuleInstance{
Globals: []*wasm.GlobalInstance{
{Type: wasm.GlobalType{ValType: wasm.ValueTypeV128}},
{Val: 1 << 62, Type: wasm.GlobalType{Mutable: true, ValType: wasm.ValueTypeF64}},
},
},
},
{
name: "f64 match not match",
cm: &wasm.ModuleInstance{
Globals: []*wasm.GlobalInstance{
{Type: wasm.GlobalType{ValType: wasm.ValueTypeV128}},
{Type: wasm.GlobalType{ValType: wasm.ValueTypeV128}},
{Val: 1 << 62, Type: wasm.GlobalType{Mutable: true, ValType: wasm.ValueTypeF64}},
},
},
im: &wasm.ModuleInstance{
Globals: []*wasm.GlobalInstance{
{Type: wasm.GlobalType{ValType: wasm.ValueTypeV128}},
{Type: wasm.GlobalType{ValType: wasm.ValueTypeV128}},
{Val: 1 << 63, Type: wasm.GlobalType{Mutable: true, ValType: wasm.ValueTypeF64}},
},
},
expErr: `mutable globals mismatch:
[2] f64: 4611686018427387904 != 9223372036854775808`,
},

{
name: "v128 match",
cm: &wasm.ModuleInstance{
Globals: []*wasm.GlobalInstance{
{Type: wasm.GlobalType{ValType: wasm.ValueTypeV128}},
{ValHi: 1 << 62, Type: wasm.GlobalType{Mutable: true, ValType: wasm.ValueTypeV128}},
},
},
im: &wasm.ModuleInstance{
Globals: []*wasm.GlobalInstance{
{Type: wasm.GlobalType{ValType: wasm.ValueTypeV128}},
{ValHi: 1 << 62, Type: wasm.GlobalType{Mutable: true, ValType: wasm.ValueTypeV128}},
},
},
},
{
name: "v128 match not match",
cm: &wasm.ModuleInstance{
Globals: []*wasm.GlobalInstance{
{Type: wasm.GlobalType{ValType: wasm.ValueTypeV128}},
{Type: wasm.GlobalType{ValType: wasm.ValueTypeV128}},
{Val: 1 << 62, Type: wasm.GlobalType{Mutable: true, ValType: wasm.ValueTypeV128}},
},
},
im: &wasm.ModuleInstance{
Globals: []*wasm.GlobalInstance{
{Type: wasm.GlobalType{ValType: wasm.ValueTypeV128}},
{Type: wasm.GlobalType{ValType: wasm.ValueTypeV128}},
{Val: 1 << 62, ValHi: 1234, Type: wasm.GlobalType{Mutable: true, ValType: wasm.ValueTypeV128}},
},
},
expErr: `mutable globals mismatch:
[2] v128: (4611686018427387904,0) != (4611686018427387904,1234)`,
},
} {
t.Run(tc.name, func(t *testing.T) {
var actualErr error

// Append the "fuel" inserted by the fuzzer, which will be ignored by ensureMutableGlobalsMatch.
tc.im.Globals = append(tc.im.Globals, &wasm.GlobalInstance{Type: wasm.GlobalType{Mutable: true, ValType: wasm.ValueTypeI32}, Val: 10000})
tc.cm.Globals = append(tc.cm.Globals, &wasm.GlobalInstance{Type: wasm.GlobalType{Mutable: true, ValType: wasm.ValueTypeI32}, Val: 1})
ensureMutableGlobalsMatch(tc.cm, tc.im, func(err error) {
actualErr = err
})
if tc.expErr == "" {
require.NoError(t, actualErr)
} else {
require.Equal(t, tc.expErr, actualErr.Error())
}
})
}
nodiff.RequireNoDiff(wasmBin, true, true, func(err error) { require.NoError(t, err) })
}
8 changes: 8 additions & 0 deletions internal/integration_test/fuzzcases/fuzzcases_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"github.com/tetratelabs/wazero/experimental/opt"
"github.com/tetratelabs/wazero/internal/platform"
"github.com/tetratelabs/wazero/internal/testing/binaryencoding"
"github.com/tetratelabs/wazero/internal/testing/nodiff"
"github.com/tetratelabs/wazero/internal/testing/require"
"github.com/tetratelabs/wazero/internal/wasm"
)
Expand Down Expand Up @@ -1003,3 +1004,10 @@ func Test2070(t *testing.T) {
require.NoError(t, err)
})
}

func Test2078(t *testing.T) {
if !platform.CompilerSupported() {
return
}
nodiff.RequireNoDiffT(t, getWasmBinary(t, "2078"), true, true)
}
Binary file not shown.
12 changes: 12 additions & 0 deletions internal/integration_test/fuzzcases/testdata/2078.wat
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
(module
(type (;0;) (func (param i64 i64)))
(func (;0;) (type 0) (param i64 i64)
i32.const 0
if ;; label = @1
unreachable
end
i32.const 1
br_if 0 (;@0;)
)
(export "" (func 0))
)
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package main
package nodiff

import (
"bytes"
Expand All @@ -7,6 +7,7 @@ import (
"fmt"
"sort"
"strings"
"testing"
"unsafe"

"github.com/tetratelabs/wazero"
Expand All @@ -15,6 +16,7 @@ import (
"github.com/tetratelabs/wazero/experimental/logging"
"github.com/tetratelabs/wazero/experimental/opt"
"github.com/tetratelabs/wazero/internal/testing/binaryencoding"
"github.com/tetratelabs/wazero/internal/testing/require"
"github.com/tetratelabs/wazero/internal/wasm"
)

Expand Down Expand Up @@ -42,8 +44,13 @@ func extractInternalWasmModuleFromCompiledModule(c wazero.CompiledModule) (*wasm
return cm.module, nil
}

// requireNoDiff ensures that the behavior is the same between the compiler and the interpreter for any given binary.
func requireNoDiff(wasmBin []byte, checkMemory, loggingCheck bool, requireNoError func(err error)) {
// RequireNoDiffT is a wrapper of RequireNoDiff for testing.T.
func RequireNoDiffT(t *testing.T, wasmBin []byte, checkMemory, loggingCheck bool) {
RequireNoDiff(wasmBin, checkMemory, loggingCheck, func(err error) { require.NoError(t, err) })
}

// RequireNoDiff ensures that the behavior is the same between the compiler and the interpreter for any given binary.
func RequireNoDiff(wasmBin []byte, checkMemory, loggingCheck bool, requireNoError func(err error)) {
const features = api.CoreFeaturesV2 | experimental.CoreFeaturesThreads
compiler := wazero.NewRuntimeWithConfig(context.Background(), opt.NewRuntimeConfigOptimizingCompiler().WithCoreFeatures(features))
interpreter := wazero.NewRuntimeWithConfig(context.Background(), wazero.NewRuntimeConfigInterpreter().WithCoreFeatures(features))
Expand Down
Loading

0 comments on commit 6eb679c

Please sign in to comment.