blob: 815f18c54fa227f1547acc666d81fb064d1aea3b [file] [edit]
;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited.
;; RUN: wasm-opt %s -all --generate-stack-ir --print-stack-ir | filecheck %s
;; RUN: wasm-opt %s -all --roundtrip -S -o - | filecheck %s --check-prefix=RTRIP
;; We normally skip emitting instructions after unreachables, but we must keep
;; local.sets of non-nullable locals in case there are later local.gets that
;; would be invalid without them.
(module
;; CHECK: (func $end-of-block (type $0) (param $ref (ref struct)) (result (ref struct))
;; CHECK-NEXT: (local $local (ref struct))
;; CHECK-NEXT: nop
;; CHECK-NEXT: unreachable
;; CHECK-NEXT: unreachable
;; CHECK-NEXT: local.set $local
;; CHECK-NEXT: drop
;; CHECK-NEXT: local.get $local
;; CHECK-NEXT: )
;; RTRIP: (func $end-of-block (type $0) (param $ref (ref struct)) (result (ref struct))
;; RTRIP-NEXT: (local $local (ref struct))
;; RTRIP-NEXT: (nop)
;; RTRIP-NEXT: (drop
;; RTRIP-NEXT: (local.set $local
;; RTRIP-NEXT: (unreachable)
;; RTRIP-NEXT: )
;; RTRIP-NEXT: )
;; RTRIP-NEXT: (local.get $local)
;; RTRIP-NEXT: )
(func $end-of-block (param $ref (ref struct)) (result (ref struct))
(local $local (ref struct))
(drop
(block (result i32)
(nop)
(local.set $local
(unreachable)
)
)
)
(local.get $local)
)
;; CHECK: (func $middle-of-block (type $0) (param $ref (ref struct)) (result (ref struct))
;; CHECK-NEXT: (local $local (ref struct))
;; CHECK-NEXT: nop
;; CHECK-NEXT: unreachable
;; CHECK-NEXT: unreachable
;; CHECK-NEXT: local.set $local
;; CHECK-NEXT: drop
;; CHECK-NEXT: local.get $local
;; CHECK-NEXT: )
;; RTRIP: (func $middle-of-block (type $0) (param $ref (ref struct)) (result (ref struct))
;; RTRIP-NEXT: (local $local (ref struct))
;; RTRIP-NEXT: (nop)
;; RTRIP-NEXT: (drop
;; RTRIP-NEXT: (local.set $local
;; RTRIP-NEXT: (unreachable)
;; RTRIP-NEXT: )
;; RTRIP-NEXT: )
;; RTRIP-NEXT: (local.get $local)
;; RTRIP-NEXT: )
(func $middle-of-block (param $ref (ref struct)) (result (ref struct))
(local $local (ref struct))
(drop
(block (result i32)
(nop)
(local.set $local
(unreachable)
)
(i32.const 0)
)
)
(local.get $local)
)
;; CHECK: (func $after-unreachable (type $0) (param $ref (ref struct)) (result (ref struct))
;; CHECK-NEXT: (local $local (ref struct))
;; CHECK-NEXT: unreachable
;; CHECK-NEXT: unreachable
;; CHECK-NEXT: local.set $local
;; CHECK-NEXT: drop
;; CHECK-NEXT: local.get $local
;; CHECK-NEXT: )
;; RTRIP: (func $after-unreachable (type $0) (param $ref (ref struct)) (result (ref struct))
;; RTRIP-NEXT: (local $local (ref struct))
;; RTRIP-NEXT: (drop
;; RTRIP-NEXT: (local.set $local
;; RTRIP-NEXT: (unreachable)
;; RTRIP-NEXT: )
;; RTRIP-NEXT: )
;; RTRIP-NEXT: (local.get $local)
;; RTRIP-NEXT: )
(func $after-unreachable (param $ref (ref struct)) (result (ref struct))
(local $local (ref struct))
(drop
(block (result i32)
(unreachable)
(local.set $local
(local.get $ref)
)
(i32.const 0)
)
)
(local.get $local)
)
;; CHECK: (func $after-unreachable-tuple (type $2) (param $i32 i32) (param $ref (ref struct)) (result i32 (ref struct))
;; CHECK-NEXT: (local $local (tuple i32 (ref struct)))
;; CHECK-NEXT: unreachable
;; CHECK-NEXT: unreachable
;; CHECK-NEXT: local.set $local
;; CHECK-NEXT: drop
;; CHECK-NEXT: local.get $local
;; CHECK-NEXT: )
;; RTRIP: (func $after-unreachable-tuple (type $2) (param $i32 i32) (param $ref (ref struct)) (result i32 (ref struct))
;; RTRIP-NEXT: (local $local i32)
;; RTRIP-NEXT: (local $3 (ref struct))
;; RTRIP-NEXT: (drop
;; RTRIP-NEXT: (local.set $local
;; RTRIP-NEXT: (local.set $3
;; RTRIP-NEXT: (unreachable)
;; RTRIP-NEXT: )
;; RTRIP-NEXT: )
;; RTRIP-NEXT: )
;; RTRIP-NEXT: (tuple.make 2
;; RTRIP-NEXT: (local.get $local)
;; RTRIP-NEXT: (local.get $3)
;; RTRIP-NEXT: )
;; RTRIP-NEXT: )
(func $after-unreachable-tuple (param $i32 i32) (param $ref (ref struct)) (result i32 (ref struct))
(local $local (tuple i32 (ref struct)))
(drop
(block (result i32)
(unreachable)
(local.set $local
(tuple.make 2
(local.get $i32)
(local.get $ref)
)
)
(i32.const 0)
)
)
(local.get $local)
)
;; CHECK: (func $nested-exprs (type $0) (param $ref (ref struct)) (result (ref struct))
;; CHECK-NEXT: (local $local (ref struct))
;; CHECK-NEXT: unreachable
;; CHECK-NEXT: unreachable
;; CHECK-NEXT: local.set $local
;; CHECK-NEXT: drop
;; CHECK-NEXT: local.get $local
;; CHECK-NEXT: )
;; RTRIP: (func $nested-exprs (type $0) (param $ref (ref struct)) (result (ref struct))
;; RTRIP-NEXT: (local $local (ref struct))
;; RTRIP-NEXT: (drop
;; RTRIP-NEXT: (local.set $local
;; RTRIP-NEXT: (unreachable)
;; RTRIP-NEXT: )
;; RTRIP-NEXT: )
;; RTRIP-NEXT: (local.get $local)
;; RTRIP-NEXT: )
(func $nested-exprs (param $ref (ref struct)) (result (ref struct))
(local $local (ref struct))
(drop
(block (result (ref struct))
(ref.eq
(unreachable)
(ref.as_non_null
(local.tee $local
(local.get $ref)
)
)
)
)
)
(local.get $local)
)
;; CHECK: (func $renumbered-locals (type $0) (param $ref (ref struct)) (result (ref struct))
;; CHECK-NEXT: (local $tuple (tuple i32 i32))
;; CHECK-NEXT: (local $local (ref struct))
;; CHECK-NEXT: nop
;; CHECK-NEXT: unreachable
;; CHECK-NEXT: unreachable
;; CHECK-NEXT: local.set $local
;; CHECK-NEXT: drop
;; CHECK-NEXT: local.get $local
;; CHECK-NEXT: )
;; RTRIP: (func $renumbered-locals (type $0) (param $ref (ref struct)) (result (ref struct))
;; RTRIP-NEXT: (local $tuple i32)
;; RTRIP-NEXT: (local $2 i32)
;; RTRIP-NEXT: (local $local (ref struct))
;; RTRIP-NEXT: (nop)
;; RTRIP-NEXT: (drop
;; RTRIP-NEXT: (local.set $local
;; RTRIP-NEXT: (unreachable)
;; RTRIP-NEXT: )
;; RTRIP-NEXT: )
;; RTRIP-NEXT: (local.get $local)
;; RTRIP-NEXT: )
(func $renumbered-locals (param $ref (ref struct)) (result (ref struct))
;; When the tuple is lowered, it causes subsequent locals to be mapped to
;; new indices. We should respect that remapping when writing unreachable
;; local.sets.
(local $tuple (tuple i32 i32))
(local $local (ref struct))
(drop
(block (result i32)
(nop)
(local.set $local
(unreachable)
)
)
)
(local.get $local)
)
;; CHECK: (func $unnamed-nested-block (type $1) (result (ref struct))
;; CHECK-NEXT: (local $local (ref struct))
;; CHECK-NEXT: block $block (result (ref struct))
;; CHECK-NEXT: ref.null none
;; CHECK-NEXT: br_on_non_null $block
;; CHECK-NEXT: ref.null none
;; CHECK-NEXT: ref.as_non_null
;; CHECK-NEXT: local.set $local
;; CHECK-NEXT: local.get $local
;; CHECK-NEXT: drop
;; CHECK-NEXT: unreachable
;; CHECK-NEXT: end
;; CHECK-NEXT: )
;; RTRIP: (func $unnamed-nested-block (type $1) (result (ref struct))
;; RTRIP-NEXT: (local $local (ref struct))
;; RTRIP-NEXT: (block $block (result (ref struct))
;; RTRIP-NEXT: (br_on_non_null $block
;; RTRIP-NEXT: (ref.null none)
;; RTRIP-NEXT: )
;; RTRIP-NEXT: (local.set $local
;; RTRIP-NEXT: (ref.as_non_null
;; RTRIP-NEXT: (ref.null none)
;; RTRIP-NEXT: )
;; RTRIP-NEXT: )
;; RTRIP-NEXT: (drop
;; RTRIP-NEXT: (local.get $local)
;; RTRIP-NEXT: )
;; RTRIP-NEXT: (unreachable)
;; RTRIP-NEXT: )
;; RTRIP-NEXT: )
(func $unnamed-nested-block (result (ref struct))
(local $local (ref struct))
(block $block (result (ref struct))
;; This unnamed intermediate block must be elided for the later local.get to
;; be valid.
(block
;; Use the label to ensure the outer block is emitted.
(br_on_non_null $block
(ref.null none)
)
(local.set $local
(ref.as_non_null (ref.null none))
)
)
(drop
(local.get $local)
)
(unreachable)
)
)
;; CHECK: (func $tuple (type $1) (result (ref struct))
;; CHECK-NEXT: (local $local (tuple i32 (ref struct)))
;; CHECK-NEXT: unreachable
;; CHECK-NEXT: unreachable
;; CHECK-NEXT: local.set $local
;; CHECK-NEXT: drop
;; CHECK-NEXT: local.get $local
;; CHECK-NEXT: tuple.extract 2 1
;; CHECK-NEXT: )
;; RTRIP: (func $tuple (type $1) (result (ref struct))
;; RTRIP-NEXT: (local $local i32)
;; RTRIP-NEXT: (local $1 (ref struct))
;; RTRIP-NEXT: (drop
;; RTRIP-NEXT: (local.set $local
;; RTRIP-NEXT: (local.set $1
;; RTRIP-NEXT: (unreachable)
;; RTRIP-NEXT: )
;; RTRIP-NEXT: )
;; RTRIP-NEXT: )
;; RTRIP-NEXT: (local.get $1)
;; RTRIP-NEXT: )
(func $tuple (result (ref struct))
;; unreachable sets of tuples containing non-nullable references also need
;; to be kept.
(local $local (tuple i32 (ref struct)))
(drop
(block (result i32)
(local.set $local
(unreachable)
)
(i32.const 0)
)
)
(tuple.extract 2 1
(local.get $local)
)
)
)