summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Lively <tlively@google.com>2023-10-09 10:12:53 -0700
committerGitHub <noreply@github.com>2023-10-09 10:12:53 -0700
commit1cd81268627c71f36f45d6ef875dee84a79630f4 (patch)
treed2f5c9e6e5013d2582035f5a638244d896d88d19
parentb3775b5e4e150439276ad3d34f1bb564b28e8ef5 (diff)
downloadbinaryen-1cd81268627c71f36f45d6ef875dee84a79630f4.tar.gz
binaryen-1cd81268627c71f36f45d6ef875dee84a79630f4.tar.bz2
binaryen-1cd81268627c71f36f45d6ef875dee84a79630f4.zip
Fix a bug printing and emitting empty, passive element segments (#6002)
Empty, passive element segments were always emitted as having `func` type because all their elements trivially were RefFunc (because they have no elements) and because we were incorrectly checking table types if they existed instead of the element segment's type directly to see if it was non-func. Fix the bug by checking each element segment's type directly and add a test.
-rw-r--r--src/ir/table-utils.cpp11
-rw-r--r--test/lit/empty-elem.wast34
-rw-r--r--test/multi-table.wast.from-wast2
-rw-r--r--test/multi-table.wast.fromBinary2
-rw-r--r--test/multi-table.wast.fromBinary.noDebugInfo2
5 files changed, 41 insertions, 10 deletions
diff --git a/src/ir/table-utils.cpp b/src/ir/table-utils.cpp
index fb9285319..124eb2aa3 100644
--- a/src/ir/table-utils.cpp
+++ b/src/ir/table-utils.cpp
@@ -72,14 +72,11 @@ bool usesExpressions(ElementSegment* curr, Module* module) {
return entry->is<RefFunc>();
});
- // If the table has a specialized (non-MVP) type, then the segment must
- // declare a type that is a subtype of that, so it must use the post-MVP form
- // of using expressions.
- bool hasTableOfSpecializedType =
- curr->table.is() &&
- module->getTable(curr->table)->type != Type(HeapType::func, Nullable);
+ // If the segment has a specialized (non-MVP) type, then it must use the
+ // post-MVP form of using expressions.
+ bool hasSpecializedType = curr->type != Type(HeapType::func, Nullable);
- return !allElementsRefFunc || hasTableOfSpecializedType;
+ return !allElementsRefFunc || hasSpecializedType;
}
} // namespace wasm::TableUtils
diff --git a/test/lit/empty-elem.wast b/test/lit/empty-elem.wast
new file mode 100644
index 000000000..0eff01d3c
--- /dev/null
+++ b/test/lit/empty-elem.wast
@@ -0,0 +1,34 @@
+;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited.
+;; RUN: wasm-opt %s -all --roundtrip -S -o - | filecheck %s
+
+;; Regression test for a bug where empty passive segments were incorrectly
+;; printed and emitted as though they had func type even if they had a different
+;; type, resulting in invalid modules.
+
+(module
+ ;; CHECK: (type $struct (sub (struct )))
+ (type $struct (sub (struct)))
+
+ ;; CHECK: (type $array (sub (array (mut (ref null $struct)))))
+ (type $array (sub (array (mut (ref null $struct)))))
+
+ ;; CHECK: (elem $e (ref null $struct))
+ (elem $e (ref null $struct))
+
+ ;; CHECK: (func $array-init-elem (type $2)
+ ;; CHECK-NEXT: (array.init_elem $array $e
+ ;; CHECK-NEXT: (array.new_fixed $array 0)
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $array-init-elem
+ (array.init_elem $array $e
+ (array.new_fixed $array 0)
+ (i32.const 0)
+ (i32.const 0)
+ (i32.const 0)
+ )
+ )
+)
diff --git a/test/multi-table.wast.from-wast b/test/multi-table.wast.from-wast
index 6ff0120f7..426f474e5 100644
--- a/test/multi-table.wast.from-wast
+++ b/test/multi-table.wast.from-wast
@@ -11,7 +11,7 @@
(elem $1 (table $t2) (i32.const 0) func $f)
(elem $activeNonZeroOffset (table $t2) (i32.const 1) func $f $g)
(elem $e3-1 (table $t3) (global.get $g2) funcref (ref.func $f) (ref.null nofunc))
- (elem $e3-2 (table $t3) (i32.const 2) func $f $g)
+ (elem $e3-2 (table $t3) (i32.const 2) (ref null $none_=>_none) (ref.func $f) (ref.func $g))
(elem $passive-1 func $f $g)
(elem $passive-2 funcref (ref.func $f) (ref.func $g) (ref.null nofunc))
(elem $passive-3 (ref null $none_=>_none) (ref.func $f) (ref.func $g) (ref.null nofunc) (global.get $g1))
diff --git a/test/multi-table.wast.fromBinary b/test/multi-table.wast.fromBinary
index 938026af3..c27ec806f 100644
--- a/test/multi-table.wast.fromBinary
+++ b/test/multi-table.wast.fromBinary
@@ -11,7 +11,7 @@
(elem $1 (table $t2) (i32.const 0) func $f)
(elem $activeNonZeroOffset (table $t2) (i32.const 1) func $f $g)
(elem $e3-1 (table $t3) (global.get $g2) funcref (ref.func $f) (ref.null nofunc))
- (elem $e3-2 (table $t3) (i32.const 2) func $f $g)
+ (elem $e3-2 (table $t3) (i32.const 2) (ref null $none_=>_none) (ref.func $f) (ref.func $g))
(elem $passive-1 func $f $g)
(elem $passive-2 funcref (ref.func $f) (ref.func $g) (ref.null nofunc))
(elem $passive-3 (ref null $none_=>_none) (ref.func $f) (ref.func $g) (ref.null nofunc) (global.get $g1))
diff --git a/test/multi-table.wast.fromBinary.noDebugInfo b/test/multi-table.wast.fromBinary.noDebugInfo
index ef7f65167..c2a5ef858 100644
--- a/test/multi-table.wast.fromBinary.noDebugInfo
+++ b/test/multi-table.wast.fromBinary.noDebugInfo
@@ -11,7 +11,7 @@
(elem $1 (table $0) (i32.const 0) func $0)
(elem $2 (table $0) (i32.const 1) func $0 $1)
(elem $3 (table $1) (global.get $global$1) funcref (ref.func $0) (ref.null nofunc))
- (elem $4 (table $1) (i32.const 2) func $0 $1)
+ (elem $4 (table $1) (i32.const 2) (ref null $0) (ref.func $0) (ref.func $1))
(elem $5 func $0 $1)
(elem $6 funcref (ref.func $0) (ref.func $1) (ref.null nofunc))
(elem $7 (ref null $0) (ref.func $0) (ref.func $1) (ref.null nofunc) (global.get $global$0))