;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited.

;; RUN: foreach %s %t wasm-opt -all --gufa -S -o - | filecheck %s

(module
  ;; CHECK:      (type $0 (func (param i32)))

  ;; CHECK:      (type $1 (func (result i32)))

  ;; CHECK:      (type $2 (func))

  ;; CHECK:      (tag $e (type $0) (param i32))
  (tag $e (param i32))

  ;; CHECK:      (func $try_table-target-block-is-not-unreachable (type $1) (result i32)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (block $catch (result i32)
  ;; CHECK-NEXT:    (try_table (catch $e $catch)
  ;; CHECK-NEXT:     (throw $e
  ;; CHECK-NEXT:      (i32.const 0)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (i32.const 0)
  ;; CHECK-NEXT: )
  (func $try_table-target-block-is-not-unreachable (result i32)
    ;; Ensure that try_table connects caught tags with their branch targets.
    (block $catch (result i32)
      (try_table (catch $e $catch)
        (throw $e (i32.const 0))
      )
    )
  )

  ;; CHECK:      (func $try_table-materializes-exnref (type $2)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (block $catch (result exnref)
  ;; CHECK-NEXT:    (try_table (catch_all_ref $catch)
  ;; CHECK-NEXT:     (throw $e
  ;; CHECK-NEXT:      (i32.const 0)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $try_table-materializes-exnref
    ;; Ensure that catch_all_ref materializes a non-null exnref value. If we do
    ;; not connect a non-null exnref value to the branch target, GUFA will think
    ;; no value can possibly get out of that block, and will insert an
    ;; unreachable instruction after the block.
    (drop
      (block $catch (result exnref)
        (try_table (catch_all_ref $catch)
          (throw $e (i32.const 0))
        )
      )
    )
  )
)

(module
  ;; CHECK:      (type $func (func))
  (type $func (func))
  ;; CHECK:      (type $cont (cont $func))
  (type $cont (cont $func))

  ;; CHECK:      (type $2 (func (param i32)))

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

  ;; CHECK:      (elem declare func $func)

  ;; CHECK:      (tag $tag (type $2) (param i32))
  (tag $tag  (param i32))

  ;; CHECK:      (export "handle" (func $handle))

  ;; CHECK:      (func $func (type $func)
  ;; CHECK-NEXT:  (nop)
  ;; CHECK-NEXT: )
  (func $func (type $func)
    (nop)
  )

  ;; CHECK:      (func $handle (type $3) (result i32)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (block $block (result i32)
  ;; CHECK-NEXT:    (try_table (catch $tag $block)
  ;; CHECK-NEXT:     (resume_throw $cont $tag
  ;; CHECK-NEXT:      (i32.const 42)
  ;; CHECK-NEXT:      (cont.new $cont
  ;; CHECK-NEXT:       (ref.func $func)
  ;; CHECK-NEXT:      )
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:     (unreachable)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (i32.const 42)
  ;; CHECK-NEXT: )
  (func $handle (export "handle") (result i32)
    ;; Resume a new continuation and throw inside it immediately. We handle the
    ;; exception in the try_table, returning 42. GUFA should not think we do not
    ;; handle it (if it did, it would add an unreachable and trap). This tests
    ;; that we see that resume_throw sends values to the tag, like a throw.
    (block $block (result i32)
      (try_table (catch $tag $block)
        (resume_throw $cont $tag
          (i32.const 42)
          (cont.new $cont
            (ref.func $func)
          )
        )
        (unreachable)
      )
    )
  )
)

