diff --git a/scripts/test/fuzzing.py b/scripts/test/fuzzing.py index a9f450e5055..0f4a1befa74 100644 --- a/scripts/test/fuzzing.py +++ b/scripts/test/fuzzing.py @@ -104,6 +104,7 @@ # TODO: fuzzer support for exact references 'exact-references.wast', 'optimize-instructions-exact.wast', + 'local-subtyping-exact.wast', ] diff --git a/src/passes/LocalSubtyping.cpp b/src/passes/LocalSubtyping.cpp index 7b30e35387f..38f93b19435 100644 --- a/src/passes/LocalSubtyping.cpp +++ b/src/passes/LocalSubtyping.cpp @@ -152,7 +152,8 @@ struct LocalSubtyping : public WalkerPass> { // Remove non-nullability if we disallow that in locals. if (newType.isNonNullable()) { if (cannotBeNonNullable.count(i)) { - newType = Type(newType.getHeapType(), Nullable); + newType = + Type(newType.getHeapType(), Nullable, newType.getExactness()); } } else if (!newType.isDefaultable()) { // Aside from the case we just handled of allowed non-nullability, we diff --git a/test/lit/passes/local-subtyping-exact.wast b/test/lit/passes/local-subtyping-exact.wast new file mode 100644 index 00000000000..725c7d499fb --- /dev/null +++ b/test/lit/passes/local-subtyping-exact.wast @@ -0,0 +1,39 @@ +;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. + +;; Check that LocalSubtyping handles exact references properly when it +;; determines that a local that would otherwise be non-nullable must be nullable +;; because of control flow dominance constraints. + +;; RUN: wasm-opt %s -all --local-subtyping -S -o - | filecheck %s + +(module + ;; CHECK: (func $test (type $0) (param $0 (exact nullref)) (result anyref) + ;; CHECK-NEXT: (local $1 (exact nullref)) + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (then + ;; CHECK-NEXT: (local.set $1 + ;; CHECK-NEXT: (ref.as_non_null + ;; CHECK-NEXT: (local.get $0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.get $1) + ;; CHECK-NEXT: ) + (func $test (param (exact nullref)) (result anyref) + (local (exact nullref)) + (if + (i32.const 0) + (then + (local.set 1 + ;; This would let the local be (ref exact none) if it dominated the get. + (ref.as_non_null + (local.get 0) + ) + ) + ) + ) + (local.get 1) + ) +)