Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/wasm/wasm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1212,6 +1212,10 @@ void BrOn::finalize() {
if (castType.isNullable()) {
// Nulls take the branch, so the result is non-nullable.
type = ref->type.with(NonNullable);
} else if (desc && desc->type.isNull()) {
// Cast will never be executed and the instruction will not be emitted.
// Model this with an uninhabitable cast type.
type = desc->type.with(NonNullable);
} else {
// Nulls do not take the branch, so the result is non-nullable only if
// the input is.
Expand Down
68 changes: 68 additions & 0 deletions test/lit/passes/local-subtyping-desc.wast
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited.

;; RUN: wasm-opt %s -all --local-subtyping -S -o - | filecheck %s

(module
(rec
;; CHECK: (rec
;; CHECK-NEXT: (type $struct (sub (descriptor $desc) (struct)))
(type $struct (sub (descriptor $desc) (struct)))
;; CHECK: (type $desc (sub (describes $struct) (struct (field i32))))
(type $desc (sub (describes $struct) (struct (field i32))))
)

;; CHECK: (func $test (type $2) (result (ref null $struct))
;; CHECK-NEXT: (local $struct (ref none))
;; CHECK-NEXT: (block $block (result (ref none))
;; CHECK-NEXT: (local.set $struct
;; CHECK-NEXT: (block ;; (replaces unreachable BrOn we can't emit)
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (ref.null none)
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (block (result (ref none))
;; CHECK-NEXT: (ref.as_non_null
;; CHECK-NEXT: (ref.null none)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $test (result (ref null $struct))
;; We can refine the local to (ref none). While doing so we must
;; refinalize the br_on properly, below, to that same type (it is never
;; executed). In more detail:
;;
;; * Initially, after parsing, the types of its inputs are
;; ref=nullref, desc=(ref $desc).
;; That refinalizes into (ref none) for the BrOn.
;;
;; * When we refinalize, the types of its inputs are
;; ref=nullref, desc=(ref none).
;; This test verifies that we fixed a bug where the BrOn was given the
;; type of the ref, i.e., nullref - which led to an assert, as we refined
;; (ref $struct) into nullref. That is, the code path handling a null
;; descriptor type did not consider that it might need to emit a non-
;; nullable type even if the ref is nullable.
;;
(local $struct (ref $struct))
(block $block (result (ref null $struct))
(local.set $struct
(br_on_cast_desc_eq $block (ref null $struct) (ref null $struct)
(ref.null $struct)
(block (result (ref $desc))
(ref.as_non_null
(ref.null none)
)
)
)
)
(unreachable)
)
)
)

4 changes: 2 additions & 2 deletions test/lit/passes/monomorphize-desc.wast
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

;; CHECK: (type $3 (func (result anyref)))

;; CHECK: (type $4 (func (param nullref)))
;; CHECK: (type $4 (func (param (ref none))))

;; CHECK: (func $target (type $2) (param $0 i32)
;; CHECK-NEXT: (nop)
Expand Down Expand Up @@ -60,6 +60,6 @@
)
)

;; CHECK: (func $target_2 (type $4) (param $0 nullref)
;; CHECK: (func $target_2 (type $4) (param $0 (ref none))
;; CHECK-NEXT: (nop)
;; CHECK-NEXT: )
4 changes: 2 additions & 2 deletions test/lit/passes/vacuum-desc.wast
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@

;; CHECK: (func $br-on-cast-null-desc (type $2) (param $ref anyref) (param $desc nullref)
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (block $l (result anyref)
;; CHECK-NEXT: (block $l (result (ref none))
;; CHECK-NEXT: (block ;; (replaces unreachable BrOn we can't emit)
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (local.get $ref)
Expand All @@ -184,7 +184,7 @@
;; CHECK-NEXT: )
;; CKIIT: (func $br-on-cast-null-desc (type $2) (param $ref anyref) (param $desc nullref)
;; CKIIT-NEXT: (drop
;; CKIIT-NEXT: (block $l (result anyref)
;; CKIIT-NEXT: (block $l (result (ref none))
;; CKIIT-NEXT: (block ;; (replaces unreachable BrOn we can't emit)
;; CKIIT-NEXT: (drop
;; CKIIT-NEXT: (local.get $ref)
Expand Down
Loading