summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Lively <tlively@google.com>2024-11-21 15:55:52 -0800
committerGitHub <noreply@github.com>2024-11-21 15:55:52 -0800
commit7b12353fb2ef0240dd8bb3e6aaa764bc8408f9ad (patch)
treee2232de255f94ba6b1710f3e8ea6ee80b2c21b9e
parent4488a3e351214e038600f58e5806c31ad0bfae46 (diff)
downloadbinaryen-7b12353fb2ef0240dd8bb3e6aaa764bc8408f9ad.tar.gz
binaryen-7b12353fb2ef0240dd8bb3e6aaa764bc8408f9ad.tar.bz2
binaryen-7b12353fb2ef0240dd8bb3e6aaa764bc8408f9ad.zip
Fix printing of unreachable br_on_cast{_fail} (#7102)
br_on_cast and br_on_cast_fail have two type annotations: one for their input type and one for their cast type. In cases where their operands were unreachable, we were previously printing "unreachable" for the input type annotation. This is not valid wat because "unreachable" is not a reference type. To fix the problem, print the bottom type of the cast type's hierarchy as the input type for br_on_cast and br_on_cast_fail when the operand is unreachable. This ensures that the instructions have the most precise possible output type according to Wasm typing rules, so it maximizes the number of contexts in which the printed instructions are valid.
-rw-r--r--src/passes/Print.cpp17
-rw-r--r--test/lit/wat-kitchen-sink.wast50
2 files changed, 65 insertions, 2 deletions
diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp
index 5a5d01299..5c8463f78 100644
--- a/src/passes/Print.cpp
+++ b/src/passes/Print.cpp
@@ -2219,7 +2219,15 @@ struct PrintExpressionContents
printMedium(o, "br_on_cast ");
curr->name.print(o);
o << ' ';
- printType(curr->ref->type);
+ if (curr->ref->type == Type::unreachable) {
+ // Need to print some reference type in the correct hierarchy rather
+ // than unreachable, and the bottom type is valid in the most
+ // contexts.
+ printType(
+ Type(curr->castType.getHeapType().getBottom(), NonNullable));
+ } else {
+ printType(curr->ref->type);
+ }
o << ' ';
printType(curr->castType);
return;
@@ -2227,7 +2235,12 @@ struct PrintExpressionContents
printMedium(o, "br_on_cast_fail ");
curr->name.print(o);
o << ' ';
- printType(curr->ref->type);
+ if (curr->ref->type == Type::unreachable) {
+ printType(
+ Type(curr->castType.getHeapType().getBottom(), NonNullable));
+ } else {
+ printType(curr->ref->type);
+ }
o << ' ';
printType(curr->castType);
return;
diff --git a/test/lit/wat-kitchen-sink.wast b/test/lit/wat-kitchen-sink.wast
index 8b77de74d..719cf2db3 100644
--- a/test/lit/wat-kitchen-sink.wast
+++ b/test/lit/wat-kitchen-sink.wast
@@ -4064,6 +4064,31 @@
drop
)
+ ;; CHECK: (func $br-on-cast-unreachable (type $0)
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (block $block (result i31ref)
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (block (result (ref any))
+ ;; CHECK-NEXT: (br_on_cast $block (ref none) i31ref
+ ;; CHECK-NEXT: (unreachable)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (unreachable)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $br-on-cast-unreachable
+ block (result i31ref)
+ block (result (ref any))
+ unreachable
+ br_on_cast 1 anyref i31ref
+ end
+ unreachable
+ end
+ drop
+ )
+
;; CHECK: (func $br-on-cast-fail (type $9) (param $0 anyref)
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (block $block (result (ref any))
@@ -4089,6 +4114,31 @@
drop
)
+ ;; CHECK: (func $br-on-cast-fail-unreachable (type $0)
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (block $block (result (ref any))
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (block (result i31ref)
+ ;; CHECK-NEXT: (br_on_cast_fail $block (ref none) i31ref
+ ;; CHECK-NEXT: (unreachable)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (unreachable)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $br-on-cast-fail-unreachable
+ block (result (ref any))
+ block (result i31ref)
+ unreachable
+ br_on_cast_fail 1 anyref i31ref
+ end
+ unreachable
+ end
+ drop
+ )
+
;; CHECK: (func $struct-new (type $63) (param $0 i32) (param $1 i64) (result (ref $pair))
;; CHECK-NEXT: (struct.new $pair
;; CHECK-NEXT: (local.get $0)