diff --git a/internal/engine/interpreter/interpreter.go b/internal/engine/interpreter/interpreter.go index 15168940..999dbba5 100644 --- a/internal/engine/interpreter/interpreter.go +++ b/internal/engine/interpreter/interpreter.go @@ -3826,9 +3826,9 @@ func (ce *callEngine) callNativeFunc(ctx context.Context, callCtx *wasm.CallCont ce.pushValue(retHi) frame.pc++ case wazeroir.OperationKindV128FloatPromote: - hi, lo := ce.popValue(), ce.popValue() - ce.pushValue(math.Float64bits(float64(math.Float32frombits(uint32(lo))))) - ce.pushValue(math.Float64bits(float64(math.Float32frombits(uint32(hi))))) + _, toPromote := ce.popValue(), ce.popValue() + ce.pushValue(math.Float64bits(float64(math.Float32frombits(uint32(toPromote))))) + ce.pushValue(math.Float64bits(float64(math.Float32frombits(uint32(toPromote >> 32))))) frame.pc++ case wazeroir.OperationKindV128FloatDemote: hi, lo := ce.popValue(), ce.popValue() diff --git a/internal/integration_test/fuzzcases/fuzzcases_test.go b/internal/integration_test/fuzzcases/fuzzcases_test.go index bf986e2b..dad1e0be 100644 --- a/internal/integration_test/fuzzcases/fuzzcases_test.go +++ b/internal/integration_test/fuzzcases/fuzzcases_test.go @@ -25,6 +25,8 @@ var ( case704 []byte //go:embed testdata/708.wasm case708 []byte + //go:embed testdata/709.wasm + case709 []byte ) func newRuntimeCompiler() wazero.Runtime { @@ -193,3 +195,32 @@ func Test708(t *testing.T) { }) } } + +func Test709(t *testing.T) { + if !platform.CompilerSupported() { + return + } + + for _, tc := range []struct { + name string + r wazero.Runtime + }{ + {name: "compiler", r: newRuntimeCompiler()}, + {name: "interpreter", r: newRuntimeInterpreter()}, + } { + tc := tc + t.Run(tc.name, func(t *testing.T) { + defer tc.r.Close(ctx) + mod, err := tc.r.InstantiateModuleFromBinary(ctx, case709) + require.NoError(t, err) + + f := mod.ExportedFunction("f64x2.promote_low_f32x4") + require.NotNil(t, f) + res, err := f.Call(ctx) + require.NoError(t, err) + + require.NotEqual(t, uint64(0), res[0]) + require.NotEqual(t, uint64(0), res[1]) + }) + } +} diff --git a/internal/integration_test/fuzzcases/testdata/709.wasm b/internal/integration_test/fuzzcases/testdata/709.wasm new file mode 100644 index 00000000..684ce90b Binary files /dev/null and b/internal/integration_test/fuzzcases/testdata/709.wasm differ diff --git a/internal/integration_test/fuzzcases/testdata/709.wat b/internal/integration_test/fuzzcases/testdata/709.wat new file mode 100644 index 00000000..91a4ab81 --- /dev/null +++ b/internal/integration_test/fuzzcases/testdata/709.wat @@ -0,0 +1,9 @@ +(module + (func (result v128) + v128.const i32x4 0xffffffff 0xffffffff 0 0 + ;; This should promote two 32-bit floats on the lower 64-bits (0xffffffff x2) + ;; Therefore, the returned vector must have non zero lower and higher 64-bits. + f64x2.promote_low_f32x4 + ) + (export "f64x2.promote_low_f32x4" (func 0)) +) diff --git a/internal/wazeroir/operations.go b/internal/wazeroir/operations.go index e1c3f4e7..1ca8022f 100644 --- a/internal/wazeroir/operations.go +++ b/internal/wazeroir/operations.go @@ -2722,6 +2722,8 @@ func (OperationV128ExtAddPairwise) Kind() OperationKind { // OperationV128FloatPromote implements Operation. // // This corresponds to wasm.OpcodeVecF64x2PromoteLowF32x4ZeroName +// This discards the higher 64-bit of a vector, and promotes two +// 32-bit floats in the lower 64-bit as two 64-bit floats. type OperationV128FloatPromote struct{} // Kind implements Operation.Kind.