;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited.
;; RUN: wasm-opt %s --inlining -all -S -o - | filecheck %s

(module
  ;; ---------------------------------------------------------------------------
  ;; CHECK:      (import "a" "b" (func $foo (type $2) (result i32)))
  (import "a" "b" (func $foo (result i32)))
  ;; CHECK:      (tag $tag$0 (param i32))
  (tag $tag$0 (param i32))
  (func $callee-with-label
    (try $label
      (do)
      (catch $tag$0
        (drop
          (pop i32)
        )
      )
    )
  )

  ;; Properly ensure unique try labels after an inlining

  ;; CHECK:      (func $caller-with-label (type $1) (param $x i32)
  ;; CHECK-NEXT:  (loop $label
  ;; CHECK-NEXT:   (block $__inlined_func$callee-with-label
  ;; CHECK-NEXT:    (try $label0
  ;; CHECK-NEXT:     (do
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:     (catch $tag$0
  ;; CHECK-NEXT:      (drop
  ;; CHECK-NEXT:       (pop i32)
  ;; CHECK-NEXT:      )
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (br_if $label
  ;; CHECK-NEXT:    (call $foo)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $caller-with-label (param $x i32)
    (loop $label ;; The same label as the try that will be inlined into here
      (call $callee-with-label)
      (br_if $label
        (call $foo)
      )
    )
  )

  ;; ---------------------------------------------------------------------------
  ;; CHECK:      (func $callee-with-try-delegate (type $0)
  ;; CHECK-NEXT:  (try $label$3
  ;; CHECK-NEXT:   (do
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (delegate 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $callee-with-try-delegate
    (try $label$3
      (do)
      (delegate 0)
    )
  )

  ;; For now, do not inline a try-delegate

  ;; CHECK:      (func $caller (type $0)
  ;; CHECK-NEXT:  (call $callee-with-try-delegate)
  ;; CHECK-NEXT: )
  (func $caller
    (call $callee-with-try-delegate)
  )

  ;; ---------------------------------------------------------------------------
  (func $callee-a (result i32)
    (i32.const 42)
  )

  ;; Properly support inlining into a function with a try-delegate

  ;; CHECK:      (func $caller-with-try-delegate (type $2) (result i32)
  ;; CHECK-NEXT:  (try $label$3
  ;; CHECK-NEXT:   (do
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (delegate 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (block $__inlined_func$callee-a$1 (result i32)
  ;; CHECK-NEXT:   (i32.const 42)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $caller-with-try-delegate (result i32)
    (try $label$3
      (do)
      (delegate 0)
    )
    (call $callee-a)
  )


  ;; ---------------------------------------------------------------------------
  (func $callee-b (param i32))

  ;; CHECK:      (func $caller-with-pop (type $0)
  ;; CHECK-NEXT:  (local $0 i32)
  ;; CHECK-NEXT:  (try
  ;; CHECK-NEXT:   (do
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (catch $tag$0
  ;; CHECK-NEXT:    (block $__inlined_func$callee-b$2
  ;; CHECK-NEXT:     (local.set $0
  ;; CHECK-NEXT:      (pop i32)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:     (block
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $caller-with-pop
    (try
      (do)
      (catch $tag$0
        ;; After this $callee-b is inlined, there will be an additional block
        ;; surrouding this 'pop'. However, that block has no breaks to it, and
        ;; will be considered the implicit block of the catch scope, so no
        ;; fixups are done.
        (call $callee-b
          (pop i32)
        )
      )
    )
  )

  (func $callee-c (param $x i32) (result i32)
    (local.get $x)
  )

  ;; CHECK:      (func $caller-with-pop-twice (type $0)
  ;; CHECK-NEXT:  (local $0 i32)
  ;; CHECK-NEXT:  (local $1 i32)
  ;; CHECK-NEXT:  (local $2 i32)
  ;; CHECK-NEXT:  (try
  ;; CHECK-NEXT:   (do
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (catch $tag$0
  ;; CHECK-NEXT:    (local.set $2
  ;; CHECK-NEXT:     (pop i32)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (block $__inlined_func$callee-b$4
  ;; CHECK-NEXT:     (local.set $1
  ;; CHECK-NEXT:      (block $__inlined_func$callee-c$3 (result i32)
  ;; CHECK-NEXT:       (local.set $0
  ;; CHECK-NEXT:        (local.get $2)
  ;; CHECK-NEXT:       )
  ;; CHECK-NEXT:       (local.get $0)
  ;; CHECK-NEXT:      )
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:     (block
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $caller-with-pop-twice
    (try
      (do)
      (catch $tag$0
        ;; As above, but now with two calls here, both of whom will be inlined.
        ;; As a result we have two blocks that nest the pops. We fix that by
        ;; creating a new local to set the result of 'pop' and later use
        ;; local.get to get the value within the inlined function body.
        (call $callee-b
          (call $callee-c
            (pop i32)
          )
        )
      )
    )
  )
)
