;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. ;; NOTE: This test was ported using port_test.py and could be cleaned up. ;; RUN: foreach %s %t wasm-opt --directize --all-features -S -o - | filecheck %s (module ;; CHECK: (type $ii (func (param i32 i32))) (type $ii (func (param i32 i32))) ;; CHECK: (table $0 5 5 funcref) (table $0 5 5 funcref) (elem (i32.const 1) $foo) ;; CHECK: (elem (i32.const 1) $foo) ;; CHECK: (func $foo (param $0 i32) (param $1 i32) ;; CHECK-NEXT: (unreachable) ;; CHECK-NEXT: ) (func $foo (param i32) (param i32) (unreachable) ) ;; CHECK: (func $bar (param $x i32) (param $y i32) ;; CHECK-NEXT: (call $foo ;; CHECK-NEXT: (local.get $x) ;; CHECK-NEXT: (local.get $y) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $bar (param $x i32) (param $y i32) (call_indirect (type $ii) (local.get $x) (local.get $y) (i32.const 1) ) ) ) (module ;; CHECK: (type $ii (func (param i32 i32))) (type $ii (func (param i32 i32))) ;; CHECK: (type $i32_=>_i32 (func (param i32) (result i32))) ;; CHECK: (table $0 5 5 funcref) (table $0 5 5 funcref) ;; CHECK: (table $1 5 5 funcref) (table $1 5 5 funcref) (elem (table $0) (i32.const 1) func $dummy) (elem (table $1) (i32.const 1) func $f) ;; CHECK: (elem $0 (table $0) (i32.const 1) func $dummy) ;; CHECK: (elem $1 (table $1) (i32.const 1) func $f) ;; CHECK: (func $dummy (param $0 i32) (result i32) ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: ) (func $dummy (param i32) (result i32) (local.get 0) ) ;; CHECK: (func $f (param $0 i32) (param $1 i32) ;; CHECK-NEXT: (unreachable) ;; CHECK-NEXT: ) (func $f (param i32) (param i32) (unreachable) ) ;; CHECK: (func $g (param $x i32) (param $y i32) ;; CHECK-NEXT: (call $f ;; CHECK-NEXT: (local.get $x) ;; CHECK-NEXT: (local.get $y) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $g (param $x i32) (param $y i32) (call_indirect $1 (type $ii) (local.get $x) (local.get $y) (i32.const 1) ) ) ) ;; at table edges (module ;; CHECK: (type $ii (func (param i32 i32))) (type $ii (func (param i32 i32))) ;; CHECK: (table $0 5 5 funcref) (table $0 5 5 funcref) ;; CHECK: (table $1 5 5 funcref) (table $1 5 5 funcref) (elem (table $1) (i32.const 4) func $foo) ;; CHECK: (elem (table $1) (i32.const 4) func $foo) ;; CHECK: (func $foo (param $0 i32) (param $1 i32) ;; CHECK-NEXT: (unreachable) ;; CHECK-NEXT: ) (func $foo (param i32) (param i32) (unreachable) ) ;; CHECK: (func $bar (param $x i32) (param $y i32) ;; CHECK-NEXT: (call $foo ;; CHECK-NEXT: (local.get $x) ;; CHECK-NEXT: (local.get $y) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $bar (param $x i32) (param $y i32) (call_indirect $1 (type $ii) (local.get $x) (local.get $y) (i32.const 4) ) ) ) (module ;; CHECK: (type $ii (func (param i32 i32))) (type $ii (func (param i32 i32))) ;; CHECK: (table $0 5 5 funcref) (table $0 5 5 funcref) (elem (i32.const 0) $foo) ;; CHECK: (elem (i32.const 0) $foo) ;; CHECK: (func $foo (param $0 i32) (param $1 i32) ;; CHECK-NEXT: (unreachable) ;; CHECK-NEXT: ) (func $foo (param i32) (param i32) (unreachable) ) ;; CHECK: (func $bar (param $x i32) (param $y i32) ;; CHECK-NEXT: (call $foo ;; CHECK-NEXT: (local.get $x) ;; CHECK-NEXT: (local.get $y) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $bar (param $x i32) (param $y i32) (call_indirect (type $ii) (local.get $x) (local.get $y) (i32.const 0) ) ) ) (module ;; CHECK: (type $ii (func (param i32 i32))) (type $ii (func (param i32 i32))) ;; CHECK: (table $0 5 5 funcref) (table $0 5 5 funcref) ;; CHECK: (table $1 5 5 funcref) (table $1 5 5 funcref) (elem (i32.const 0) $foo $foo $foo $foo $foo) (elem (table $1) (i32.const 0) func $foo $foo $foo $foo $foo) ;; CHECK: (elem $0 (table $0) (i32.const 0) func $foo $foo $foo $foo $foo) ;; CHECK: (elem $1 (table $1) (i32.const 0) func $foo $foo $foo $foo $foo) ;; CHECK: (func $foo (param $0 i32) (param $1 i32) ;; CHECK-NEXT: (unreachable) ;; CHECK-NEXT: ) (func $foo (param i32) (param i32) (unreachable) ) ;; CHECK: (func $bar (param $x i32) (param $y i32) ;; CHECK-NEXT: (call $foo ;; CHECK-NEXT: (local.get $x) ;; CHECK-NEXT: (local.get $y) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $bar (param $x i32) (param $y i32) (call_indirect $1 (type $ii) (local.get $x) (local.get $y) (i32.const 2) ) ) ) ;; imported table (module ;; CHECK: (type $ii (func (param i32 i32))) (type $ii (func (param i32 i32))) ;; CHECK: (import "env" "table" (table $table 5 5 funcref)) (import "env" "table" (table $table 5 5 funcref)) (elem (i32.const 1) $foo) ;; CHECK: (elem (i32.const 1) $foo) ;; CHECK: (func $foo (param $0 i32) (param $1 i32) ;; CHECK-NEXT: (unreachable) ;; CHECK-NEXT: ) (func $foo (param i32) (param i32) (unreachable) ) ;; CHECK: (func $bar (param $x i32) (param $y i32) ;; CHECK-NEXT: (call_indirect $table (type $ii) ;; CHECK-NEXT: (local.get $x) ;; CHECK-NEXT: (local.get $y) ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $bar (param $x i32) (param $y i32) (call_indirect (type $ii) (local.get $x) (local.get $y) (i32.const 1) ) ) ) ;; exported table (module ;; CHECK: (type $ii (func (param i32 i32))) (type $ii (func (param i32 i32))) ;; CHECK: (table $0 5 5 funcref) (table $0 5 5 funcref) ;; CHECK: (elem (i32.const 1) $foo) ;; CHECK: (export "tab" (table $0)) (export "tab" (table $0)) (elem (i32.const 1) $foo) ;; CHECK: (func $foo (param $0 i32) (param $1 i32) ;; CHECK-NEXT: (unreachable) ;; CHECK-NEXT: ) (func $foo (param i32) (param i32) (unreachable) ) ;; CHECK: (func $bar (param $x i32) (param $y i32) ;; CHECK-NEXT: (call_indirect $0 (type $ii) ;; CHECK-NEXT: (local.get $x) ;; CHECK-NEXT: (local.get $y) ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $bar (param $x i32) (param $y i32) (call_indirect (type $ii) (local.get $x) (local.get $y) (i32.const 1) ) ) ) ;; non-constant table offset (module ;; CHECK: (type $ii (func (param i32 i32))) (type $ii (func (param i32 i32))) ;; CHECK: (global $g (mut i32) (i32.const 1)) ;; CHECK: (table $0 5 5 funcref) (table $0 5 5 funcref) (global $g (mut i32) (i32.const 1)) (elem (global.get $g) $foo) ;; CHECK: (elem (global.get $g) $foo) ;; CHECK: (func $foo (param $0 i32) (param $1 i32) ;; CHECK-NEXT: (unreachable) ;; CHECK-NEXT: ) (func $foo (param i32) (param i32) (unreachable) ) ;; CHECK: (func $bar (param $x i32) (param $y i32) ;; CHECK-NEXT: (call_indirect $0 (type $ii) ;; CHECK-NEXT: (local.get $x) ;; CHECK-NEXT: (local.get $y) ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $bar (param $x i32) (param $y i32) (call_indirect (type $ii) (local.get $x) (local.get $y) (i32.const 1) ) ) ) (module ;; CHECK: (type $ii (func (param i32 i32))) (type $ii (func (param i32 i32))) ;; CHECK: (global $g (mut i32) (i32.const 1)) ;; CHECK: (table $0 5 5 funcref) (table $0 5 5 funcref) ;; CHECK: (table $1 5 5 funcref) (table $1 5 5 funcref) (global $g (mut i32) (i32.const 1)) (elem (table $1) (global.get $g) func $foo) ;; CHECK: (elem (table $1) (global.get $g) func $foo) ;; CHECK: (func $foo (param $0 i32) (param $1 i32) ;; CHECK-NEXT: (unreachable) ;; CHECK-NEXT: ) (func $foo (param i32) (param i32) (unreachable) ) ;; CHECK: (func $bar (param $x i32) (param $y i32) ;; CHECK-NEXT: (call_indirect $1 (type $ii) ;; CHECK-NEXT: (local.get $x) ;; CHECK-NEXT: (local.get $y) ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $bar (param $x i32) (param $y i32) (call_indirect $1 (type $ii) (local.get $x) (local.get $y) (i32.const 1) ) ) ) ;; non-constant call index (module ;; CHECK: (type $ii (func (param i32 i32))) (type $ii (func (param i32 i32))) ;; CHECK: (type $i32_i32_i32_=>_none (func (param i32 i32 i32))) ;; CHECK: (table $0 5 5 funcref) (table $0 5 5 funcref) (elem (i32.const 1) $foo) ;; CHECK: (elem (i32.const 1) $foo) ;; CHECK: (func $foo (param $0 i32) (param $1 i32) ;; CHECK-NEXT: (unreachable) ;; CHECK-NEXT: ) (func $foo (param i32) (param i32) (unreachable) ) ;; CHECK: (func $bar (param $x i32) (param $y i32) (param $z i32) ;; CHECK-NEXT: (call_indirect $0 (type $ii) ;; CHECK-NEXT: (local.get $x) ;; CHECK-NEXT: (local.get $y) ;; CHECK-NEXT: (local.get $z) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $bar (param $x i32) (param $y i32) (param $z i32) (call_indirect (type $ii) (local.get $x) (local.get $y) (local.get $z) ) ) ) ;; bad index (module ;; CHECK: (type $ii (func (param i32 i32))) (type $ii (func (param i32 i32))) ;; CHECK: (table $0 5 5 funcref) (table $0 5 5 funcref) (elem (i32.const 1) $foo) ;; CHECK: (elem (i32.const 1) $foo) ;; CHECK: (func $foo (param $0 i32) (param $1 i32) ;; CHECK-NEXT: (unreachable) ;; CHECK-NEXT: ) (func $foo (param i32) (param i32) (unreachable) ) ;; CHECK: (func $bar (param $x i32) (param $y i32) ;; CHECK-NEXT: (block ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (local.get $x) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (local.get $y) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (unreachable) ;; CHECK-NEXT: ) (func $bar (param $x i32) (param $y i32) (call_indirect (type $ii) (local.get $x) (local.get $y) (i32.const 5) ) ) ) ;; missing index (module ;; CHECK: (type $ii (func (param i32 i32))) (type $ii (func (param i32 i32))) ;; CHECK: (table $0 5 5 funcref) (table $0 5 5 funcref) (elem (i32.const 1) $foo) ;; CHECK: (elem (i32.const 1) $foo) ;; CHECK: (func $foo (param $0 i32) (param $1 i32) ;; CHECK-NEXT: (unreachable) ;; CHECK-NEXT: ) (func $foo (param i32) (param i32) (unreachable) ) ;; CHECK: (func $bar (param $x i32) (param $y i32) ;; CHECK-NEXT: (block ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (local.get $x) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (local.get $y) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (unreachable) ;; CHECK-NEXT: ) (func $bar (param $x i32) (param $y i32) (call_indirect (type $ii) (local.get $x) (local.get $y) (i32.const 2) ) ) ) ;; bad type (module ;; CHECK: (type $i32_=>_none (func (param i32))) ;; CHECK: (type $ii (func (param i32 i32))) (type $ii (func (param i32 i32))) ;; CHECK: (table $0 5 5 funcref) (table $0 5 5 funcref) (elem (i32.const 1) $foo) ;; CHECK: (elem (i32.const 1) $foo) ;; CHECK: (func $foo (param $0 i32) ;; CHECK-NEXT: (unreachable) ;; CHECK-NEXT: ) (func $foo (param i32) (unreachable) ) ;; CHECK: (func $bar (param $x i32) (param $y i32) ;; CHECK-NEXT: (block ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (local.get $x) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (local.get $y) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (unreachable) ;; CHECK-NEXT: ) (func $bar (param $x i32) (param $y i32) (call_indirect (type $ii) (local.get $x) (local.get $y) (i32.const 1) ) ) ) ;; no table (module ;; CHECK: (type $i32_=>_none (func (param i32))) ;; CHECK: (func $foo (param $0 i32) ;; CHECK-NEXT: (unreachable) ;; CHECK-NEXT: ) (func $foo (param i32) (unreachable) ) ) ;; change types (module (type (func)) ;; CHECK: (type $none_=>_none (func)) ;; CHECK: (table $0 8 8 funcref) (table $0 8 8 funcref) ;; CHECK: (func $0 ;; CHECK-NEXT: (block $block ;; CHECK-NEXT: (nop) ;; CHECK-NEXT: (block ;; CHECK-NEXT: (block ;; CHECK-NEXT: ) ;; CHECK-NEXT: (unreachable) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $0 (block ;; the type of this block will change (nop) (call_indirect (type 0) (i32.const 15) ) ) ) ) (module ;; indirect tail call ;; CHECK: (type $ii (func (param i32 i32))) (type $ii (func (param i32 i32))) ;; CHECK: (table $0 5 5 funcref) (table $0 5 5 funcref) (elem (i32.const 1) $foo) ;; CHECK: (elem (i32.const 1) $foo) ;; CHECK: (func $foo (param $0 i32) (param $1 i32) ;; CHECK-NEXT: (unreachable) ;; CHECK-NEXT: ) (func $foo (param i32) (param i32) (unreachable) ) ;; CHECK: (func $bar (param $x i32) (param $y i32) ;; CHECK-NEXT: (return_call $foo ;; CHECK-NEXT: (local.get $x) ;; CHECK-NEXT: (local.get $y) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $bar (param $x i32) (param $y i32) (return_call_indirect (type $ii) (local.get $x) (local.get $y) (i32.const 1) ) ) )