blob: d723212fc4b3468a01e69383376323c015901179 [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 -all --inlining -S -o - | filecheck %s
;; Test that we inline functions with unreachable bodies. This is important to
;; propagate the trap to the caller (where it might lead to DCE).
(module
(func $trap
(unreachable)
)
;; CHECK: (type $0 (func))
;; CHECK: (type $1 (func (result i32)))
;; CHECK: (func $call-trap (type $0)
;; CHECK-NEXT: (block $__inlined_func$trap
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $call-trap
;; In this case the call had type none, but the inlined code is unreachable,
;; so we'll add a br to the new block to keep the type as none (the br is
;; not actually reached, and other opts will remove it).
(call $trap)
)
(func $trap-result (result i32)
;; As above, but now there is a declared result.
(unreachable)
)
;; CHECK: (func $call-trap-result (type $1) (result i32)
;; CHECK-NEXT: (block $__inlined_func$trap-result$1
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $call-trap-result (result i32)
(call $trap-result)
)
(func $contents-then-trap
;; Add some contents in addition to the trap.
(nop)
(drop
(i32.const 1337)
)
(nop)
(unreachable)
)
;; CHECK: (func $call-contents-then-trap (type $0)
;; CHECK-NEXT: (block $__inlined_func$contents-then-trap$2
;; CHECK-NEXT: (block
;; CHECK-NEXT: (nop)
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.const 1337)
;; CHECK-NEXT: )
;; CHECK-NEXT: (nop)
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $call-contents-then-trap
(call $contents-then-trap)
)
)
(module
;; CHECK: (type $0 (func))
;; CHECK: (type $1 (func (param i32) (result i32)))
;; CHECK: (import "env" "imported" (func $imported (type $1) (param i32) (result i32)))
(import "env" "imported" (func $imported (param i32) (result i32)))
;; CHECK: (func $caller (type $0)
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (block $__inlined_func$callee
;; CHECK-NEXT: (call $imported
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $caller
(drop
(call $callee)
)
)
;; After inlining, this return_call will turn into a call, but should still be
;; unreachable. Validation will fail if it is not.
(func $callee (result i32)
(return_call $imported
(unreachable)
)
)
;; CHECK: (func $caller-2 (type $0)
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (block $__inlined_func$callee-2$1
;; CHECK-NEXT: (block
;; CHECK-NEXT: (block $__return_call
;; CHECK-NEXT: (block
;; CHECK-NEXT: (try
;; CHECK-NEXT: (do
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: (br $__return_call)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (call $imported
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $caller-2
(drop
(call $callee-2)
)
)
;; Same as above, but with a return_call with a try block
(func $callee-2 (result i32)
(try
(do
(return_call $imported
(unreachable)
)
)
)
)
)
(module
;; CHECK: (type $A (func))
(type $A (func))
(func $0
(nop)
(call_ref $A
(ref.null nofunc) ;; In Binaryen IR this makes the call_ref unreachable.
)
)
;; CHECK: (func $1 (type $A)
;; CHECK-NEXT: (block $__inlined_func$0
;; CHECK-NEXT: (block
;; CHECK-NEXT: (nop)
;; CHECK-NEXT: (block ;; (replaces unreachable CallRef we can't emit)
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (ref.null nofunc)
;; CHECK-NEXT: )
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $1 (type $A)
;; After inlining, this function body will become unreachable.
(call $0)
)
)
(module
;; CHECK: (type $0 (func (result f64)))
;; CHECK: (func $0 (type $0) (result f64)
;; CHECK-NEXT: (block $block
;; CHECK-NEXT: (br_if $block
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (return
;; CHECK-NEXT: (block $__inlined_func$1
;; CHECK-NEXT: (block $block0
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $0 (result f64)
(block $block
(br_if $block
(i32.const 0)
)
)
(return
;; The inlined function has the same label, $block. We should not be
;; confused by that when we inline the unreachable code (an error can
;; occur if we mix up the two blocks or think they are identical; to avoid
;; that we should fix up the duplicate labels before doing anything that
;; depends on valid label names, like refinalization).
(call $1)
)
)
(func $1 (result f64)
(block $block
(unreachable)
)
)
)