diff --git a/internal/engine/compiler/impl_amd64.go b/internal/engine/compiler/impl_amd64.go index a19626c3..efd6356b 100644 --- a/internal/engine/compiler/impl_amd64.go +++ b/internal/engine/compiler/impl_amd64.go @@ -4096,6 +4096,10 @@ func (c *amd64Compiler) compileTableFill(o *wazeroir.OperationTableFill) error { // compileRefFunc implements compiler.compileRefFunc for the amd64 architecture. func (c *amd64Compiler) compileRefFunc(o *wazeroir.OperationRefFunc) error { + if err := c.maybeCompileMoveTopConditionalToGeneralPurposeRegister(); err != nil { + return err + } + ref, err := c.allocateRegister(registerTypeGeneralPurpose) if err != nil { return err diff --git a/internal/engine/compiler/impl_arm64.go b/internal/engine/compiler/impl_arm64.go index 0b8d9608..45786306 100644 --- a/internal/engine/compiler/impl_arm64.go +++ b/internal/engine/compiler/impl_arm64.go @@ -3696,6 +3696,10 @@ func (c *arm64Compiler) compileLoadElemInstanceAddress(elemIndex uint32, dst asm // compileRefFunc implements compiler.compileRefFunc for the arm64 architecture. func (c *arm64Compiler) compileRefFunc(o *wazeroir.OperationRefFunc) error { + if err := c.maybeCompileMoveTopConditionalToGeneralPurposeRegister(); err != nil { + return err + } + ref, err := c.allocateRegister(registerTypeGeneralPurpose) if err != nil { return err diff --git a/internal/integration_test/fuzzcases/fuzzcases_test.go b/internal/integration_test/fuzzcases/fuzzcases_test.go index a1e642fd..ad8a6cf8 100644 --- a/internal/integration_test/fuzzcases/fuzzcases_test.go +++ b/internal/integration_test/fuzzcases/fuzzcases_test.go @@ -29,6 +29,8 @@ var ( case709 []byte //go:embed testdata/715.wasm case715 []byte + //go:embed testdata/716.wasm + case716 []byte ) func runWithCompiler(t *testing.T, runner func(t *testing.T, r wazero.Runtime)) { @@ -159,3 +161,17 @@ func Test715(t *testing.T) { require.Equal(t, uint64(1), res[0]) }) } + +func Test716(t *testing.T) { + run(t, func(t *testing.T, r wazero.Runtime) { + mod, err := r.InstantiateModuleFromBinary(ctx, case716) + require.NoError(t, err) + + f := mod.ExportedFunction("select on ref.func") + require.NotNil(t, f) + res, err := f.Call(ctx) + require.NoError(t, err) + + require.Equal(t, uint64(1), res[0]) + }) +} diff --git a/internal/integration_test/fuzzcases/testdata/716.wasm b/internal/integration_test/fuzzcases/testdata/716.wasm new file mode 100644 index 00000000..7ab9786c Binary files /dev/null and b/internal/integration_test/fuzzcases/testdata/716.wasm differ diff --git a/internal/integration_test/fuzzcases/testdata/716.wat b/internal/integration_test/fuzzcases/testdata/716.wat new file mode 100644 index 00000000..eb849d6f --- /dev/null +++ b/internal/integration_test/fuzzcases/testdata/716.wat @@ -0,0 +1,14 @@ +(module + (func (result i32) + i32.const 123 + ref.null func + ref.is_null ;; -> 1 + ;; At this point, the result of ref.is_null (=1) is on the conditional register. + ;; If table.size doesn't save the value into a general purpose register, + ;; the result of select below becomes incorrect. + ref.func 0 + ref.is_null ;; -> 0 + select ;; should select 1 + ) + (export "select on ref.func" (func 0)) +)