diff options
author | Thomas Lively <tlively@google.com> | 2024-11-21 15:55:52 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-11-21 15:55:52 -0800 |
commit | 7b12353fb2ef0240dd8bb3e6aaa764bc8408f9ad (patch) | |
tree | e2232de255f94ba6b1710f3e8ea6ee80b2c21b9e | |
parent | 4488a3e351214e038600f58e5806c31ad0bfae46 (diff) | |
download | binaryen-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.cpp | 17 | ||||
-rw-r--r-- | test/lit/wat-kitchen-sink.wast | 50 |
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) |