blob: 2f27193a1d0b6f941695d24c1b5a9f7677141f23 [file] [edit]
;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited.
;; RUN: foreach %s %t wasm-opt --gufa --closed-world -all -S -o - | filecheck %s
;; RUN: foreach %s %t wasm-opt --gufa -all -S -o - | filecheck %s --check-prefix OPEN_WORLD
(module
;; CHECK: (type $func (func))
;; OPEN_WORLD: (type $func (func))
(type $func (func))
;; CHECK: (type $cont (cont $func))
;; OPEN_WORLD: (type $cont (cont $func))
(type $cont (cont $func))
;; CHECK: (type $func-i32 (func (result i32)))
;; OPEN_WORLD: (type $func-i32 (func (result i32)))
(type $func-i32 (func (result i32)))
;; CHECK: (type $cont-i32 (cont $func-i32))
;; OPEN_WORLD: (type $cont-i32 (cont $func-i32))
(type $cont-i32 (cont $func-i32))
;; CHECK: (type $4 (func (result i32 (ref $cont))))
;; CHECK: (elem declare func $cont $cont-i32)
;; CHECK: (tag $tag (type $func))
;; OPEN_WORLD: (type $4 (func (result i32 (ref $cont))))
;; OPEN_WORLD: (elem declare func $cont $cont-i32)
;; OPEN_WORLD: (tag $tag (type $func))
(tag $tag (type $func))
;; CHECK: (tag $tag-i32 (type $func-i32) (result i32))
;; OPEN_WORLD: (tag $tag-i32 (type $func-i32) (result i32))
(tag $tag-i32 (type $func-i32))
;; CHECK: (export "resume" (func $resume))
;; CHECK: (export "resume_throw" (func $resume_throw))
;; CHECK: (export "resume-i32" (func $resume-i32))
;; CHECK: (func $cont (type $func)
;; CHECK-NEXT: (suspend $tag)
;; CHECK-NEXT: )
;; OPEN_WORLD: (export "resume" (func $resume))
;; OPEN_WORLD: (export "resume_throw" (func $resume_throw))
;; OPEN_WORLD: (export "resume-i32" (func $resume-i32))
;; OPEN_WORLD: (func $cont (type $func)
;; OPEN_WORLD-NEXT: (suspend $tag)
;; OPEN_WORLD-NEXT: )
(func $cont
;; Helper for below.
(suspend $tag)
)
;; CHECK: (func $resume (type $func)
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (block $block (result (ref $cont))
;; CHECK-NEXT: (resume $cont (on $tag $block)
;; CHECK-NEXT: (cont.new $cont
;; CHECK-NEXT: (ref.func $cont)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (return)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; OPEN_WORLD: (func $resume (type $func)
;; OPEN_WORLD-NEXT: (drop
;; OPEN_WORLD-NEXT: (block $block (result (ref $cont))
;; OPEN_WORLD-NEXT: (resume $cont (on $tag $block)
;; OPEN_WORLD-NEXT: (cont.new $cont
;; OPEN_WORLD-NEXT: (ref.func $cont)
;; OPEN_WORLD-NEXT: )
;; OPEN_WORLD-NEXT: )
;; OPEN_WORLD-NEXT: (return)
;; OPEN_WORLD-NEXT: )
;; OPEN_WORLD-NEXT: )
;; OPEN_WORLD-NEXT: )
(func $resume (export "resume")
;; A continuation is created, it suspends, and we handle that. There is
;; nothing to optimize or change here.
(drop
(block $block (result (ref $cont))
(resume $cont (on $tag $block)
(cont.new $cont
(ref.func $cont)
)
)
(return)
)
)
)
;; CHECK: (func $resume_throw (type $func)
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (block $block (result (ref $cont))
;; CHECK-NEXT: (resume_throw $cont $tag (on $tag $block)
;; CHECK-NEXT: (cont.new $cont
;; CHECK-NEXT: (ref.func $cont)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (return)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; OPEN_WORLD: (func $resume_throw (type $func)
;; OPEN_WORLD-NEXT: (drop
;; OPEN_WORLD-NEXT: (block $block (result (ref $cont))
;; OPEN_WORLD-NEXT: (resume_throw $cont $tag (on $tag $block)
;; OPEN_WORLD-NEXT: (cont.new $cont
;; OPEN_WORLD-NEXT: (ref.func $cont)
;; OPEN_WORLD-NEXT: )
;; OPEN_WORLD-NEXT: )
;; OPEN_WORLD-NEXT: (return)
;; OPEN_WORLD-NEXT: )
;; OPEN_WORLD-NEXT: )
;; OPEN_WORLD-NEXT: )
(func $resume_throw (export "resume_throw")
;; As above, but with resume_throw.
(drop
(block $block (result (ref $cont))
(resume_throw $cont $tag (on $tag $block)
(cont.new $cont
(ref.func $cont)
)
)
(return)
)
)
)
;; CHECK: (func $cont-i32 (type $func-i32) (result i32)
;; CHECK-NEXT: (suspend $tag)
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; OPEN_WORLD: (func $cont-i32 (type $func-i32) (result i32)
;; OPEN_WORLD-NEXT: (suspend $tag)
;; OPEN_WORLD-NEXT: (unreachable)
;; OPEN_WORLD-NEXT: (unreachable)
;; OPEN_WORLD-NEXT: )
(func $cont-i32 (result i32)
;; Helper for below.
(suspend $tag)
(unreachable)
)
;; CHECK: (func $resume-i32 (type $func)
;; CHECK-NEXT: (tuple.drop 2
;; CHECK-NEXT: (block $block (type $4) (result i32 (ref $cont))
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (resume $cont-i32 (on $tag-i32 $block)
;; CHECK-NEXT: (cont.new $cont-i32
;; CHECK-NEXT: (ref.func $cont-i32)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (return)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; OPEN_WORLD: (func $resume-i32 (type $func)
;; OPEN_WORLD-NEXT: (tuple.drop 2
;; OPEN_WORLD-NEXT: (block $block (type $4) (result i32 (ref $cont))
;; OPEN_WORLD-NEXT: (drop
;; OPEN_WORLD-NEXT: (resume $cont-i32 (on $tag-i32 $block)
;; OPEN_WORLD-NEXT: (cont.new $cont-i32
;; OPEN_WORLD-NEXT: (ref.func $cont-i32)
;; OPEN_WORLD-NEXT: )
;; OPEN_WORLD-NEXT: )
;; OPEN_WORLD-NEXT: )
;; OPEN_WORLD-NEXT: (return)
;; OPEN_WORLD-NEXT: )
;; OPEN_WORLD-NEXT: )
;; OPEN_WORLD-NEXT: )
(func $resume-i32 (export "resume-i32")
;; As above, but with more values sent than just the continuation.
(tuple.drop 2
(block $block (result i32 (ref $cont))
(resume $cont-i32 (on $tag-i32 $block)
(cont.new $cont-i32
(ref.func $cont-i32)
)
)
(return)
)
)
)
)
(module
;; CHECK: (type $func (func (param i32)))
;; CHECK: (type $cont (cont $func))
;; CHECK: (type $none (func))
;; OPEN_WORLD: (type $func (func (param i32)))
;; OPEN_WORLD: (type $cont (cont $func))
;; OPEN_WORLD: (type $none (func))
(type $none (func))
(type $func (func (param i32)))
(type $cont (cont $func))
;; CHECK: (elem declare func $func)
;; CHECK: (tag $tag (type $none))
;; OPEN_WORLD: (elem declare func $func)
;; OPEN_WORLD: (tag $tag (type $none))
(tag $tag (type $none))
;; CHECK: (export "run" (func $run))
;; CHECK: (func $func (type $func) (param $x i32)
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (local.get $x)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; OPEN_WORLD: (export "run" (func $run))
;; OPEN_WORLD: (func $func (type $func) (param $x i32)
;; OPEN_WORLD-NEXT: (drop
;; OPEN_WORLD-NEXT: (local.get $x)
;; OPEN_WORLD-NEXT: )
;; OPEN_WORLD-NEXT: )
(func $func (param $x i32)
;; This function is only ever referred to by a ref.func that is passed into
;; a cont.new, and that is the only source of values for this local. We should
;; not modify this to unreachable, which we would do if we didn't realize it
;; can be reached. (The only possible value is 42, from the caller below, but
;; we do not infer that yet TODO)
(drop
(local.get $x)
)
)
;; CHECK: (func $run (type $none)
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (block $block (result (ref $cont))
;; CHECK-NEXT: (resume $cont (on $tag $block)
;; CHECK-NEXT: (i32.const 42)
;; CHECK-NEXT: (cont.new $cont
;; CHECK-NEXT: (ref.func $func)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (return)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; OPEN_WORLD: (func $run (type $none)
;; OPEN_WORLD-NEXT: (drop
;; OPEN_WORLD-NEXT: (block $block (result (ref $cont))
;; OPEN_WORLD-NEXT: (resume $cont (on $tag $block)
;; OPEN_WORLD-NEXT: (i32.const 42)
;; OPEN_WORLD-NEXT: (cont.new $cont
;; OPEN_WORLD-NEXT: (ref.func $func)
;; OPEN_WORLD-NEXT: )
;; OPEN_WORLD-NEXT: )
;; OPEN_WORLD-NEXT: (return)
;; OPEN_WORLD-NEXT: )
;; OPEN_WORLD-NEXT: )
;; OPEN_WORLD-NEXT: )
(func $run (export "run")
(drop
(block $block (result (ref $cont))
(resume $cont (on $tag $block)
(cont.new $cont
(i32.const 42)
(ref.func $func)
)
)
(return)
)
)
)
)
(module
;; CHECK: (type $func (func))
;; OPEN_WORLD: (type $func (func))
(type $func (func))
;; CHECK: (type $cont (cont $func))
;; OPEN_WORLD: (type $cont (cont $func))
(type $cont (cont $func))
;; CHECK: (type $func-i32 (func (param i32)))
;; OPEN_WORLD: (type $func-i32 (func (param i32)))
(type $func-i32 (func (param i32)))
;; CHECK: (type $3 (func (result i32)))
;; CHECK: (type $4 (func (result i32 (ref $cont))))
;; CHECK: (elem declare func $cont)
;; CHECK: (tag $tag (type $func))
;; OPEN_WORLD: (type $3 (func (result i32)))
;; OPEN_WORLD: (type $4 (func (result i32 (ref $cont))))
;; OPEN_WORLD: (elem declare func $cont)
;; OPEN_WORLD: (tag $tag (type $func))
(tag $tag (type $func))
;; CHECK: (tag $tag-i32 (type $func-i32) (param i32))
;; OPEN_WORLD: (tag $tag-i32 (type $func-i32) (param i32))
(tag $tag-i32 (type $func-i32))
;; CHECK: (export "resume" (func $resume))
;; CHECK: (func $cont (type $func)
;; CHECK-NEXT: (suspend $tag-i32
;; CHECK-NEXT: (i32.const 1337)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; OPEN_WORLD: (export "resume" (func $resume))
;; OPEN_WORLD: (func $cont (type $func)
;; OPEN_WORLD-NEXT: (suspend $tag-i32
;; OPEN_WORLD-NEXT: (i32.const 1337)
;; OPEN_WORLD-NEXT: )
;; OPEN_WORLD-NEXT: )
(func $cont
;; Helper for below.
(suspend $tag-i32
(i32.const 1337)
)
)
;; CHECK: (func $resume (type $3) (result i32)
;; CHECK-NEXT: (tuple.drop 2
;; CHECK-NEXT: (block $block (type $4) (result i32 (ref $cont))
;; CHECK-NEXT: (resume $cont (on $tag-i32 $block)
;; CHECK-NEXT: (cont.new $cont
;; CHECK-NEXT: (ref.func $cont)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (return
;; CHECK-NEXT: (i32.const 42)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (i32.const 1337)
;; CHECK-NEXT: )
;; OPEN_WORLD: (func $resume (type $3) (result i32)
;; OPEN_WORLD-NEXT: (tuple.drop 2
;; OPEN_WORLD-NEXT: (block $block (type $4) (result i32 (ref $cont))
;; OPEN_WORLD-NEXT: (resume $cont (on $tag-i32 $block)
;; OPEN_WORLD-NEXT: (cont.new $cont
;; OPEN_WORLD-NEXT: (ref.func $cont)
;; OPEN_WORLD-NEXT: )
;; OPEN_WORLD-NEXT: )
;; OPEN_WORLD-NEXT: (return
;; OPEN_WORLD-NEXT: (i32.const 42)
;; OPEN_WORLD-NEXT: )
;; OPEN_WORLD-NEXT: )
;; OPEN_WORLD-NEXT: )
;; OPEN_WORLD-NEXT: (i32.const 1337)
;; OPEN_WORLD-NEXT: )
(func $resume (export "resume") (result i32)
;; A continuation is created, it suspends, and we handle that. We can even
;; infer the suspended value, 1337.
(tuple.extract 2 0
(block $block (result i32 (ref $cont))
(resume $cont (on $tag-i32 $block)
(cont.new $cont
(ref.func $cont)
)
)
(return
(i32.const 42)
)
)
)
)
)