summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Lively <tlively@google.com>2024-03-08 08:10:37 -0800
committerGitHub <noreply@github.com>2024-03-08 08:10:37 -0800
commit7af0b474304c30134ef875567668bb6cd36e21aa (patch)
treeeb7aeba1ef0f84e172afe720c138db5f513bd6e4
parentd6c5e4ab15df271521df7b35665c7463b2c490ca (diff)
downloadbinaryen-7af0b474304c30134ef875567668bb6cd36e21aa.tar.gz
binaryen-7af0b474304c30134ef875567668bb6cd36e21aa.tar.bz2
binaryen-7af0b474304c30134ef875567668bb6cd36e21aa.zip
Fix printing of bulk array ops (#6387)
When the bulk array ops had unreachable or null array types, they were replaced with blocks, but not using the correct code that also prints all their children as dropped followed by an unreachable. This meant that the text output in those cases did not parse as a valid module. Fix the bug. A follow-up PR will simplify the code to prevent similar bugs from occurring in the future.
-rw-r--r--src/passes/Print.cpp19
-rw-r--r--test/lit/passes/gufa-refs.wast17
-rw-r--r--test/lit/passes/type-generalizing.wast126
-rw-r--r--test/lit/passes/unsubtyping.wast116
4 files changed, 212 insertions, 66 deletions
diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp
index b0c83c437..af91a3194 100644
--- a/src/passes/Print.cpp
+++ b/src/passes/Print.cpp
@@ -289,6 +289,25 @@ struct PrintSExpression : public UnifiedExpressionVisitor<PrintSExpression> {
void visitArrayGet(ArrayGet* curr) {
maybePrintUnreachableOrNullReplacement(curr, curr->ref->type);
}
+ void visitArrayCopy(ArrayCopy* curr) {
+ if (curr->srcRef->type == Type::unreachable ||
+ curr->destRef->type == Type::unreachable ||
+ curr->srcRef->type.isNull() || curr->destRef->type.isNull()) {
+ maybePrintUnreachableOrNullReplacement(curr, Type::unreachable);
+ return;
+ }
+ visitExpression(curr);
+ }
+ void visitArrayFill(ArrayFill* curr) {
+ maybePrintUnreachableOrNullReplacement(curr, curr->ref->type);
+ }
+ void visitArrayInitData(ArrayInitData* curr) {
+ maybePrintUnreachableOrNullReplacement(curr, curr->ref->type);
+ }
+ void visitArrayInitElem(ArrayInitElem* curr) {
+ maybePrintUnreachableOrNullReplacement(curr, curr->ref->type);
+ }
+
// Module-level visitors
void handleSignature(HeapType curr, Name name = Name());
void visitExport(Export* curr);
diff --git a/test/lit/passes/gufa-refs.wast b/test/lit/passes/gufa-refs.wast
index e6e5d0bde..4be45e4ca 100644
--- a/test/lit/passes/gufa-refs.wast
+++ b/test/lit/passes/gufa-refs.wast
@@ -5632,11 +5632,20 @@
(data $0 "")
;; CHECK: (func $test (type $0)
- ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (block ;; (replaces unreachable ArrayInitData we can't emit)
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (unreachable)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: )
;; CHECK-NEXT: (unreachable)
- ;; CHECK-NEXT: (i32.const 0)
- ;; CHECK-NEXT: (i32.const 0)
- ;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $test
diff --git a/test/lit/passes/type-generalizing.wast b/test/lit/passes/type-generalizing.wast
index 2c1714a46..f927086de 100644
--- a/test/lit/passes/type-generalizing.wast
+++ b/test/lit/passes/type-generalizing.wast
@@ -1383,12 +1383,23 @@
;; CHECK: (func $array-copy-impossible-dest (type $0)
;; CHECK-NEXT: (local $dest nullref)
;; CHECK-NEXT: (local $src anyref)
- ;; CHECK-NEXT: (block
- ;; CHECK-NEXT: (local.get $dest)
- ;; CHECK-NEXT: (i32.const 0)
- ;; CHECK-NEXT: (local.get $src)
- ;; CHECK-NEXT: (i32.const 0)
- ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: (block ;; (replaces unreachable ArrayCopy we can't emit)
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (local.get $dest)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (local.get $src)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $array-copy-impossible-dest
@@ -1408,12 +1419,23 @@
;; CHECK: (func $array-copy-impossible-src (type $0)
;; CHECK-NEXT: (local $dest anyref)
;; CHECK-NEXT: (local $src nullref)
- ;; CHECK-NEXT: (block
- ;; CHECK-NEXT: (local.get $dest)
- ;; CHECK-NEXT: (i32.const 0)
- ;; CHECK-NEXT: (local.get $src)
- ;; CHECK-NEXT: (i32.const 0)
- ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: (block ;; (replaces unreachable ArrayCopy we can't emit)
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (local.get $dest)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (local.get $src)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $array-copy-impossible-src
@@ -1433,12 +1455,23 @@
;; CHECK: (func $array-copy-impossible-both (type $0)
;; CHECK-NEXT: (local $dest nullref)
;; CHECK-NEXT: (local $src nullref)
- ;; CHECK-NEXT: (block
- ;; CHECK-NEXT: (local.get $dest)
- ;; CHECK-NEXT: (i32.const 0)
- ;; CHECK-NEXT: (local.get $src)
- ;; CHECK-NEXT: (i32.const 0)
- ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: (block ;; (replaces unreachable ArrayCopy we can't emit)
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (local.get $dest)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (local.get $src)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $array-copy-impossible-both
@@ -1481,11 +1514,20 @@
;; CHECK: (func $array-fill-impossible (type $0)
;; CHECK-NEXT: (local $ref nullref)
;; CHECK-NEXT: (local $val anyref)
- ;; CHECK-NEXT: (block
- ;; CHECK-NEXT: (local.get $ref)
- ;; CHECK-NEXT: (i32.const 0)
- ;; CHECK-NEXT: (local.get $val)
- ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: (block ;; (replaces unreachable ArrayFill we can't emit)
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (local.get $ref)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (local.get $val)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $array-fill-impossible
@@ -1522,11 +1564,20 @@
;; CHECK: (func $array-init-data-impossible (type $0)
;; CHECK-NEXT: (local $ref nullref)
- ;; CHECK-NEXT: (block
- ;; CHECK-NEXT: (local.get $ref)
- ;; CHECK-NEXT: (i32.const 0)
- ;; CHECK-NEXT: (i32.const 0)
- ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: (block ;; (replaces unreachable ArrayInitData we can't emit)
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (local.get $ref)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $array-init-data-impossible
@@ -1562,11 +1613,20 @@
;; CHECK: (func $array-init-elem-impossible (type $0)
;; CHECK-NEXT: (local $ref nullref)
- ;; CHECK-NEXT: (block
- ;; CHECK-NEXT: (local.get $ref)
- ;; CHECK-NEXT: (i32.const 0)
- ;; CHECK-NEXT: (i32.const 0)
- ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: (block ;; (replaces unreachable ArrayInitElem we can't emit)
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (local.get $ref)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $array-init-elem-impossible
diff --git a/test/lit/passes/unsubtyping.wast b/test/lit/passes/unsubtyping.wast
index 8408c2e7d..204b76ef7 100644
--- a/test/lit/passes/unsubtyping.wast
+++ b/test/lit/passes/unsubtyping.wast
@@ -1441,19 +1441,41 @@
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
- ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (block ;; (replaces unreachable ArrayCopy we can't emit)
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (unreachable)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (array.new_fixed $sub-array 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
;; CHECK-NEXT: (unreachable)
- ;; CHECK-NEXT: (i32.const 0)
- ;; CHECK-NEXT: (array.new_fixed $sub-array 0)
- ;; CHECK-NEXT: (i32.const 0)
- ;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
- ;; CHECK-NEXT: (block
- ;; CHECK-NEXT: (array.new_fixed $super-array 0)
- ;; CHECK-NEXT: (i32.const 0)
- ;; CHECK-NEXT: (ref.null none)
- ;; CHECK-NEXT: (i32.const 0)
- ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: (block ;; (replaces unreachable ArrayCopy we can't emit)
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (array.new_fixed $super-array 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (ref.null none)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $array-copy
@@ -1503,17 +1525,35 @@
;; CHECK-NEXT: (struct.new_default $sub)
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
- ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (block ;; (replaces unreachable ArrayFill we can't emit)
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (unreachable)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (struct.new_default $sub)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
;; CHECK-NEXT: (unreachable)
- ;; CHECK-NEXT: (i32.const 0)
- ;; CHECK-NEXT: (struct.new_default $sub)
- ;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
- ;; CHECK-NEXT: (block
- ;; CHECK-NEXT: (ref.null none)
- ;; CHECK-NEXT: (i32.const 0)
- ;; CHECK-NEXT: (struct.new_default $sub)
- ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: (block ;; (replaces unreachable ArrayFill we can't emit)
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (ref.null none)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (struct.new_default $sub)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $array-fill
@@ -1564,17 +1604,35 @@
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
- ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (block ;; (replaces unreachable ArrayInitElem we can't emit)
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (unreachable)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
;; CHECK-NEXT: (unreachable)
- ;; CHECK-NEXT: (i32.const 0)
- ;; CHECK-NEXT: (i32.const 0)
- ;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
- ;; CHECK-NEXT: (block
- ;; CHECK-NEXT: (ref.null none)
- ;; CHECK-NEXT: (i32.const 0)
- ;; CHECK-NEXT: (i32.const 0)
- ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: (block ;; (replaces unreachable ArrayInitElem we can't emit)
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (ref.null none)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $array-init-elem