Fix operand arity of v128.storeN_lane in GetExprArity (#2764)
Found this fuzzing wasm-decompile under a debug build: a valid module
whose only instruction is v128.store8_lane aborts on the value-stack
assert in decompiler-ast.h Construct.
1. GetExprArity groups SimdLoadLane and SimdStoreLane together and
reports both as {2, 1}.
2. store_lane pops the address and the vector and pushes nothing, so its
real effect is {2, 0}; the spare result throws value_stack_depth out by
one.
The decompiler has since been removed, but GetExprArity still drives the
folded wat writer, where the phantom result is equally observable:
wasm2wat --fold-exprs folds the store into the next value consumer and
strands the value beneath it. Split the case so SimdStoreLane returns
{2, 0} and SimdLoadLane keeps {2, 1}. A reduced repro is added under
test/roundtrip.diff --git a/src/ir-util.cc b/src/ir-util.cc
index f7ce0c2..74fe45e 100644
--- a/src/ir-util.cc
+++ b/src/ir-util.cc
@@ -285,9 +285,10 @@
}
case ExprType::SimdLoadLane:
- case ExprType::SimdStoreLane: {
return {2, 1};
- }
+
+ case ExprType::SimdStoreLane:
+ return {2, 0};
case ExprType::SimdShuffleOp:
return {2, 1};
diff --git a/test/roundtrip/fold-simd-store-lane.txt b/test/roundtrip/fold-simd-store-lane.txt
new file mode 100644
index 0000000..37e8e39
--- /dev/null
+++ b/test/roundtrip/fold-simd-store-lane.txt
@@ -0,0 +1,36 @@
+;;; TOOL: run-roundtrip
+;;; ARGS: --stdout --fold-exprs
+(module
+ (memory 1)
+
+ ;; store_lane consumes the address and the vector and pushes nothing, so the
+ ;; f32 below it is what f32.neg consumes; the store must not be folded into
+ ;; f32.neg as if it produced a value.
+ (func (param i32 v128 f32) (result f32)
+ local.get 2
+ local.get 0
+ local.get 1
+ v128.store8_lane 0
+ f32.neg)
+
+ (func (param i32 v128)
+ local.get 0
+ local.get 1
+ v128.store16_lane offset=4 1)
+)
+(;; STDOUT ;;;
+(module
+ (type (;0;) (func (param i32 v128 f32) (result f32)))
+ (type (;1;) (func (param i32 v128)))
+ (func (;0;) (type 0) (param i32 v128 f32) (result f32)
+ (local.get 2)
+ (v128.store8_lane 0
+ (local.get 0)
+ (local.get 1))
+ (f32.neg))
+ (func (;1;) (type 1) (param i32 v128)
+ (v128.store16_lane offset=4 1
+ (local.get 0)
+ (local.get 1)))
+ (memory (;0;) 1))
+;;; STDOUT ;;)