summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorAlon Zakai <azakai@google.com>2024-08-16 12:53:52 -0700
committerGitHub <noreply@github.com>2024-08-16 12:53:52 -0700
commit958ff4115e542ef1d0ae712f4961e342386efe54 (patch)
tree7805d641d9a73b32650a053931c4bd8c3814d804 /test
parent7209629bec3961fcc12b150ba6df546d3997b6c2 (diff)
downloadbinaryen-958ff4115e542ef1d0ae712f4961e342386efe54.tar.gz
binaryen-958ff4115e542ef1d0ae712f4961e342386efe54.tar.bz2
binaryen-958ff4115e542ef1d0ae712f4961e342386efe54.zip
Implement table.init (#6827)
Also use TableInit in the interpreter to initialize module's table state, which will now handle traps properly, fixing #6431
Diffstat (limited to 'test')
-rw-r--r--test/binaryen.js/exception-handling.js.txt8
-rw-r--r--test/binaryen.js/kitchen-sink.js.txt58
-rw-r--r--test/lit/basic/table-operations.wast90
-rw-r--r--test/lit/ctor-eval/table.init.wat62
-rw-r--r--test/lit/passes/directize_all-features.wast95
-rw-r--r--test/lit/passes/simplify-locals-table_copy.wast73
-rw-r--r--test/lit/passes/table64-lowering.wast13
-rw-r--r--test/lit/passes/unsubtyping.wast32
-rw-r--r--test/spec/table_init.wast52
9 files changed, 423 insertions, 60 deletions
diff --git a/test/binaryen.js/exception-handling.js.txt b/test/binaryen.js/exception-handling.js.txt
index d2a0c6dd6..f8b713025 100644
--- a/test/binaryen.js/exception-handling.js.txt
+++ b/test/binaryen.js/exception-handling.js.txt
@@ -34,7 +34,7 @@
)
)
-getExpressionInfo(throw) = {"id":53,"type":1,"tag":"e"}
-getExpressionInfo(rethrow) = {"id":54,"type":1,"target":"l0"}
-getExpressionInfo(try_catch) = {"id":51,"type":1,"name":"l0","hasCatchAll":0,"delegateTarget":"","isDelegate":0}
-getExpressionInfo(try_delegate) = {"id":51,"type":0,"name":"try_outer","hasCatchAll":1,"delegateTarget":"","isDelegate":0}
+getExpressionInfo(throw) = {"id":54,"type":1,"tag":"e"}
+getExpressionInfo(rethrow) = {"id":55,"type":1,"target":"l0"}
+getExpressionInfo(try_catch) = {"id":52,"type":1,"name":"l0","hasCatchAll":0,"delegateTarget":"","isDelegate":0}
+getExpressionInfo(try_delegate) = {"id":52,"type":0,"name":"try_outer","hasCatchAll":1,"delegateTarget":"","isDelegate":0}
diff --git a/test/binaryen.js/kitchen-sink.js.txt b/test/binaryen.js/kitchen-sink.js.txt
index 28922c2a0..212194c9c 100644
--- a/test/binaryen.js/kitchen-sink.js.txt
+++ b/test/binaryen.js/kitchen-sink.js.txt
@@ -82,35 +82,35 @@ TableGetId: 45
TableSetId: 46
TableSizeId: 47
TableGrowId: 48
-TryId: 51
-ThrowId: 53
-RethrowId: 54
-TupleMakeId: 56
-TupleExtractId: 57
-RefI31Id: 58
-I31GetId: 59
-CallRefId: 60
-RefTestId: 61
-RefCastId: 62
-BrOnId: 63
-StructNewId: 64
-StructGetId: 65
-StructSetId: 66
-ArrayNewId: 67
-ArrayNewFixedId: 70
-ArrayGetId: 71
-ArraySetId: 72
-ArrayLenId: 73
-ArrayCopy: 74
-RefAs: 78
-StringNew: 79
-StringConst: 80
-StringMeasure: 81
-StringEncode: 82
-StringConcat: 83
-StringEq: 84
-StringWTF16Get: 85
-StringSliceWTF: 86
+TryId: 52
+ThrowId: 54
+RethrowId: 55
+TupleMakeId: 57
+TupleExtractId: 58
+RefI31Id: 59
+I31GetId: 60
+CallRefId: 61
+RefTestId: 62
+RefCastId: 63
+BrOnId: 64
+StructNewId: 65
+StructGetId: 66
+StructSetId: 67
+ArrayNewId: 68
+ArrayNewFixedId: 71
+ArrayGetId: 72
+ArraySetId: 73
+ArrayLenId: 74
+ArrayCopy: 75
+RefAs: 79
+StringNew: 80
+StringConst: 81
+StringMeasure: 82
+StringEncode: 83
+StringConcat: 84
+StringEq: 85
+StringWTF16Get: 86
+StringSliceWTF: 87
getExpressionInfo={"id":15,"type":4,"op":6}
(f32.neg
(f32.const -33.61199951171875)
diff --git a/test/lit/basic/table-operations.wast b/test/lit/basic/table-operations.wast
index 4ccbe6c6a..899981410 100644
--- a/test/lit/basic/table-operations.wast
+++ b/test/lit/basic/table-operations.wast
@@ -12,24 +12,24 @@
(module
;; CHECK-TEXT: (type $0 (func))
- ;; CHECK-TEXT: (type $1 (func (result i32)))
+ ;; CHECK-TEXT: (type $1 (func (param i32 i32 i32)))
- ;; CHECK-TEXT: (type $2 (func (param i32) (result i32)))
+ ;; CHECK-TEXT: (type $2 (func (result i32)))
- ;; CHECK-TEXT: (type $3 (func (param i32 funcref i32)))
+ ;; CHECK-TEXT: (type $3 (func (param i32) (result i32)))
- ;; CHECK-TEXT: (type $4 (func (param i32 i32 i32)))
+ ;; CHECK-TEXT: (type $4 (func (param i32 funcref i32)))
;; CHECK-TEXT: (table $table-1 1 1 funcref)
;; CHECK-BIN: (type $0 (func))
- ;; CHECK-BIN: (type $1 (func (result i32)))
+ ;; CHECK-BIN: (type $1 (func (param i32 i32 i32)))
- ;; CHECK-BIN: (type $2 (func (param i32) (result i32)))
+ ;; CHECK-BIN: (type $2 (func (result i32)))
- ;; CHECK-BIN: (type $3 (func (param i32 funcref i32)))
+ ;; CHECK-BIN: (type $3 (func (param i32) (result i32)))
- ;; CHECK-BIN: (type $4 (func (param i32 i32 i32)))
+ ;; CHECK-BIN: (type $4 (func (param i32 funcref i32)))
;; CHECK-BIN: (table $table-1 1 1 funcref)
(table $table-1 funcref
@@ -46,13 +46,17 @@
;; CHECK-TEXT: (elem $implicit-elem_1 (table $table-2) (i32.const 0) func $bar $bar $bar)
- ;; CHECK-TEXT: (func $foo (type $0)
- ;; CHECK-TEXT-NEXT: (nop)
- ;; CHECK-TEXT-NEXT: )
+ ;; CHECK-TEXT: (elem $elem func)
;; CHECK-BIN: (elem $0 (table $table-1) (i32.const 0) func $foo)
;; CHECK-BIN: (elem $1 (table $table-2) (i32.const 0) func $bar $bar $bar)
+ ;; CHECK-BIN: (elem $elem func)
+ (elem $elem funcref)
+
+ ;; CHECK-TEXT: (func $foo (type $0)
+ ;; CHECK-TEXT-NEXT: (nop)
+ ;; CHECK-TEXT-NEXT: )
;; CHECK-BIN: (func $foo (type $0)
;; CHECK-BIN-NEXT: (nop)
;; CHECK-BIN-NEXT: )
@@ -131,23 +135,23 @@
)
)
- ;; CHECK-TEXT: (func $get-table-size (type $1) (result i32)
+ ;; CHECK-TEXT: (func $get-table-size (type $2) (result i32)
;; CHECK-TEXT-NEXT: (table.size $table-1)
;; CHECK-TEXT-NEXT: )
- ;; CHECK-BIN: (func $get-table-size (type $1) (result i32)
+ ;; CHECK-BIN: (func $get-table-size (type $2) (result i32)
;; CHECK-BIN-NEXT: (table.size $table-1)
;; CHECK-BIN-NEXT: )
(func $get-table-size (result i32)
(table.size $table-1)
)
- ;; CHECK-TEXT: (func $table-grow (type $2) (param $sz i32) (result i32)
+ ;; CHECK-TEXT: (func $table-grow (type $3) (param $sz i32) (result i32)
;; CHECK-TEXT-NEXT: (table.grow $table-1
;; CHECK-TEXT-NEXT: (ref.null nofunc)
;; CHECK-TEXT-NEXT: (local.get $sz)
;; CHECK-TEXT-NEXT: )
;; CHECK-TEXT-NEXT: )
- ;; CHECK-BIN: (func $table-grow (type $2) (param $sz i32) (result i32)
+ ;; CHECK-BIN: (func $table-grow (type $3) (param $sz i32) (result i32)
;; CHECK-BIN-NEXT: (table.grow $table-1
;; CHECK-BIN-NEXT: (ref.null nofunc)
;; CHECK-BIN-NEXT: (local.get $sz)
@@ -157,14 +161,14 @@
(table.grow $table-1 (ref.null func) (local.get $sz))
)
- ;; CHECK-TEXT: (func $table-fill (type $3) (param $dest i32) (param $value funcref) (param $size i32)
+ ;; CHECK-TEXT: (func $table-fill (type $4) (param $dest i32) (param $value funcref) (param $size i32)
;; CHECK-TEXT-NEXT: (table.fill $table-1
;; CHECK-TEXT-NEXT: (local.get $dest)
;; CHECK-TEXT-NEXT: (local.get $value)
;; CHECK-TEXT-NEXT: (local.get $size)
;; CHECK-TEXT-NEXT: )
;; CHECK-TEXT-NEXT: )
- ;; CHECK-BIN: (func $table-fill (type $3) (param $dest i32) (param $value funcref) (param $size i32)
+ ;; CHECK-BIN: (func $table-fill (type $4) (param $dest i32) (param $value funcref) (param $size i32)
;; CHECK-BIN-NEXT: (table.fill $table-1
;; CHECK-BIN-NEXT: (local.get $dest)
;; CHECK-BIN-NEXT: (local.get $value)
@@ -179,14 +183,14 @@
)
)
- ;; CHECK-TEXT: (func $table-copy (type $4) (param $dest i32) (param $source i32) (param $size i32)
+ ;; CHECK-TEXT: (func $table-copy (type $1) (param $dest i32) (param $source i32) (param $size i32)
;; CHECK-TEXT-NEXT: (table.copy $table-1 $table-2
;; CHECK-TEXT-NEXT: (local.get $dest)
;; CHECK-TEXT-NEXT: (local.get $source)
;; CHECK-TEXT-NEXT: (local.get $size)
;; CHECK-TEXT-NEXT: )
;; CHECK-TEXT-NEXT: )
- ;; CHECK-BIN: (func $table-copy (type $4) (param $dest i32) (param $source i32) (param $size i32)
+ ;; CHECK-BIN: (func $table-copy (type $1) (param $dest i32) (param $source i32) (param $size i32)
;; CHECK-BIN-NEXT: (table.copy $table-1 $table-2
;; CHECK-BIN-NEXT: (local.get $dest)
;; CHECK-BIN-NEXT: (local.get $source)
@@ -200,16 +204,38 @@
(local.get $size)
)
)
+
+ ;; CHECK-TEXT: (func $table-init (type $1) (param $dest i32) (param $offset i32) (param $size i32)
+ ;; CHECK-TEXT-NEXT: (table.init $table-1 $elem
+ ;; CHECK-TEXT-NEXT: (local.get $dest)
+ ;; CHECK-TEXT-NEXT: (local.get $offset)
+ ;; CHECK-TEXT-NEXT: (local.get $size)
+ ;; CHECK-TEXT-NEXT: )
+ ;; CHECK-TEXT-NEXT: )
+ ;; CHECK-BIN: (func $table-init (type $1) (param $dest i32) (param $offset i32) (param $size i32)
+ ;; CHECK-BIN-NEXT: (table.init $table-1 $elem
+ ;; CHECK-BIN-NEXT: (local.get $dest)
+ ;; CHECK-BIN-NEXT: (local.get $offset)
+ ;; CHECK-BIN-NEXT: (local.get $size)
+ ;; CHECK-BIN-NEXT: )
+ ;; CHECK-BIN-NEXT: )
+ (func $table-init (param $dest i32) (param $offset i32) (param $size i32)
+ (table.init $table-1 $elem
+ (local.get $dest)
+ (local.get $offset)
+ (local.get $size)
+ )
+ )
)
;; CHECK-BIN-NODEBUG: (type $0 (func))
-;; CHECK-BIN-NODEBUG: (type $1 (func (result i32)))
+;; CHECK-BIN-NODEBUG: (type $1 (func (param i32 i32 i32)))
-;; CHECK-BIN-NODEBUG: (type $2 (func (param i32) (result i32)))
+;; CHECK-BIN-NODEBUG: (type $2 (func (result i32)))
-;; CHECK-BIN-NODEBUG: (type $3 (func (param i32 funcref i32)))
+;; CHECK-BIN-NODEBUG: (type $3 (func (param i32) (result i32)))
-;; CHECK-BIN-NODEBUG: (type $4 (func (param i32 i32 i32)))
+;; CHECK-BIN-NODEBUG: (type $4 (func (param i32 funcref i32)))
;; CHECK-BIN-NODEBUG: (table $0 1 1 funcref)
@@ -219,6 +245,8 @@
;; CHECK-BIN-NODEBUG: (elem $1 (table $1) (i32.const 0) func $1 $1 $1)
+;; CHECK-BIN-NODEBUG: (elem $2 func)
+
;; CHECK-BIN-NODEBUG: (func $0 (type $0)
;; CHECK-BIN-NODEBUG-NEXT: (nop)
;; CHECK-BIN-NODEBUG-NEXT: )
@@ -248,18 +276,18 @@
;; CHECK-BIN-NODEBUG-NEXT: )
;; CHECK-BIN-NODEBUG-NEXT: )
-;; CHECK-BIN-NODEBUG: (func $3 (type $1) (result i32)
+;; CHECK-BIN-NODEBUG: (func $3 (type $2) (result i32)
;; CHECK-BIN-NODEBUG-NEXT: (table.size $0)
;; CHECK-BIN-NODEBUG-NEXT: )
-;; CHECK-BIN-NODEBUG: (func $4 (type $2) (param $0 i32) (result i32)
+;; CHECK-BIN-NODEBUG: (func $4 (type $3) (param $0 i32) (result i32)
;; CHECK-BIN-NODEBUG-NEXT: (table.grow $0
;; CHECK-BIN-NODEBUG-NEXT: (ref.null nofunc)
;; CHECK-BIN-NODEBUG-NEXT: (local.get $0)
;; CHECK-BIN-NODEBUG-NEXT: )
;; CHECK-BIN-NODEBUG-NEXT: )
-;; CHECK-BIN-NODEBUG: (func $5 (type $3) (param $0 i32) (param $1 funcref) (param $2 i32)
+;; CHECK-BIN-NODEBUG: (func $5 (type $4) (param $0 i32) (param $1 funcref) (param $2 i32)
;; CHECK-BIN-NODEBUG-NEXT: (table.fill $0
;; CHECK-BIN-NODEBUG-NEXT: (local.get $0)
;; CHECK-BIN-NODEBUG-NEXT: (local.get $1)
@@ -267,10 +295,18 @@
;; CHECK-BIN-NODEBUG-NEXT: )
;; CHECK-BIN-NODEBUG-NEXT: )
-;; CHECK-BIN-NODEBUG: (func $6 (type $4) (param $0 i32) (param $1 i32) (param $2 i32)
+;; CHECK-BIN-NODEBUG: (func $6 (type $1) (param $0 i32) (param $1 i32) (param $2 i32)
;; CHECK-BIN-NODEBUG-NEXT: (table.copy $0 $1
;; CHECK-BIN-NODEBUG-NEXT: (local.get $0)
;; CHECK-BIN-NODEBUG-NEXT: (local.get $1)
;; CHECK-BIN-NODEBUG-NEXT: (local.get $2)
;; CHECK-BIN-NODEBUG-NEXT: )
;; CHECK-BIN-NODEBUG-NEXT: )
+
+;; CHECK-BIN-NODEBUG: (func $7 (type $1) (param $0 i32) (param $1 i32) (param $2 i32)
+;; CHECK-BIN-NODEBUG-NEXT: (table.init $0 $2
+;; CHECK-BIN-NODEBUG-NEXT: (local.get $0)
+;; CHECK-BIN-NODEBUG-NEXT: (local.get $1)
+;; CHECK-BIN-NODEBUG-NEXT: (local.get $2)
+;; CHECK-BIN-NODEBUG-NEXT: )
+;; CHECK-BIN-NODEBUG-NEXT: )
diff --git a/test/lit/ctor-eval/table.init.wat b/test/lit/ctor-eval/table.init.wat
new file mode 100644
index 000000000..7af2a09c6
--- /dev/null
+++ b/test/lit/ctor-eval/table.init.wat
@@ -0,0 +1,62 @@
+;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited.
+;; RUN: wasm-ctor-eval %s --ctors=run --kept-exports=run --quiet -all -S -o - | filecheck %s
+
+(module
+ ;; CHECK: (type $none_=>_none (func))
+ (type $none_=>_none (func))
+
+ ;; CHECK: (table $table 22 funcref)
+ (table $table 22 funcref)
+
+ ;; CHECK: (elem $init (i32.const 0) $nop)
+ (elem $init (i32.const 0) $nop)
+
+ ;; CHECK: (elem $later func $trap)
+ (elem $later $trap)
+
+ (export "run" (func $run))
+
+ (func $run (type $none_=>_none)
+ ;; This call can be evalled away (it does nothing as the target is a nop).
+ (call_indirect $table (type $none_=>_none)
+ (i32.const 0)
+ )
+
+ ;; We stop at this table.init, which is not handled yet. The call after it
+ ;; should also remain where it is.
+ (table.init $table $later
+ (i32.const 0)
+ (i32.const 0)
+ (i32.const 1)
+ )
+ (call_indirect $table (type $none_=>_none)
+ (i32.const 0)
+ )
+ )
+
+ ;; CHECK: (export "run" (func $run_3))
+
+ ;; CHECK: (func $nop (type $none_=>_none)
+ ;; CHECK-NEXT: (nop)
+ ;; CHECK-NEXT: )
+ (func $nop (type $none_=>_none)
+ (nop)
+ )
+
+ ;; CHECK: (func $trap (type $none_=>_none)
+ ;; CHECK-NEXT: (unreachable)
+ ;; CHECK-NEXT: )
+ (func $trap (type $none_=>_none)
+ (unreachable)
+ )
+)
+;; CHECK: (func $run_3 (type $none_=>_none)
+;; CHECK-NEXT: (table.init $table $later
+;; CHECK-NEXT: (i32.const 0)
+;; CHECK-NEXT: (i32.const 0)
+;; CHECK-NEXT: (i32.const 1)
+;; CHECK-NEXT: )
+;; CHECK-NEXT: (call_indirect $table (type $none_=>_none)
+;; CHECK-NEXT: (i32.const 0)
+;; CHECK-NEXT: )
+;; CHECK-NEXT: )
diff --git a/test/lit/passes/directize_all-features.wast b/test/lit/passes/directize_all-features.wast
index 997992b07..074558d95 100644
--- a/test/lit/passes/directize_all-features.wast
+++ b/test/lit/passes/directize_all-features.wast
@@ -1599,6 +1599,101 @@
)
)
+;; A table.init prevents optimization.
+(module
+ ;; CHECK: (type $i32 (func (result i32)))
+ ;; IMMUT: (type $i32 (func (result i32)))
+ (type $i32 (func (result i32)))
+
+ ;; CHECK: (type $1 (func))
+
+ ;; CHECK: (table $table 111 funcref)
+ ;; IMMUT: (type $1 (func))
+
+ ;; IMMUT: (table $table 111 funcref)
+ (table $table 111 funcref)
+ (elem (i32.const 0) $func-A)
+
+ ;; CHECK: (elem $0 (i32.const 0) $func-A)
+
+ ;; CHECK: (elem $elem func $func-B)
+ ;; IMMUT: (elem $0 (i32.const 0) $func-A)
+
+ ;; IMMUT: (elem $elem func $func-B)
+ (elem $elem $func-B)
+
+ ;; CHECK: (export "a" (func $init))
+ ;; IMMUT: (export "a" (func $init))
+ (export "a" (func $init))
+ ;; CHECK: (export "b" (func $call))
+ ;; IMMUT: (export "b" (func $call))
+ (export "b" (func $call))
+
+ ;; CHECK: (func $func-A (type $i32) (result i32)
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; IMMUT: (func $func-A (type $i32) (result i32)
+ ;; IMMUT-NEXT: (i32.const 0)
+ ;; IMMUT-NEXT: )
+ (func $func-A (result i32)
+ (i32.const 0)
+ )
+
+ ;; CHECK: (func $func-B (type $i32) (result i32)
+ ;; CHECK-NEXT: (unreachable)
+ ;; CHECK-NEXT: )
+ ;; IMMUT: (func $func-B (type $i32) (result i32)
+ ;; IMMUT-NEXT: (unreachable)
+ ;; IMMUT-NEXT: )
+ (func $func-B (result i32)
+ (unreachable)
+ )
+
+ ;; CHECK: (func $init (type $1)
+ ;; CHECK-NEXT: (table.init $table $elem
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; IMMUT: (func $init (type $1)
+ ;; IMMUT-NEXT: (table.init $table $elem
+ ;; IMMUT-NEXT: (i32.const 0)
+ ;; IMMUT-NEXT: (i32.const 0)
+ ;; IMMUT-NEXT: (i32.const 1)
+ ;; IMMUT-NEXT: )
+ ;; IMMUT-NEXT: )
+ (func $init
+ (table.init $table $elem
+ (i32.const 0)
+ (i32.const 0)
+ (i32.const 1)
+ )
+ )
+
+ ;; CHECK: (func $call (type $1)
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (call_indirect $table (type $i32)
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; IMMUT: (func $call (type $1)
+ ;; IMMUT-NEXT: (drop
+ ;; IMMUT-NEXT: (call $func-A)
+ ;; IMMUT-NEXT: )
+ ;; IMMUT-NEXT: )
+ (func $call
+ (drop
+ ;; This cannot be turned into a direct call due to the table.init, unless we
+ ;; assume initial contents are immutable.
+ (call_indirect (type $i32)
+ (i32.const 0)
+ )
+ )
+ )
+)
+
;; The elem's offset is way out of bounds, which we should not error on, and do
;; nothing otherwise.
(module
diff --git a/test/lit/passes/simplify-locals-table_copy.wast b/test/lit/passes/simplify-locals-table_copy.wast
new file mode 100644
index 000000000..a10c16b1b
--- /dev/null
+++ b/test/lit/passes/simplify-locals-table_copy.wast
@@ -0,0 +1,73 @@
+;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited.
+;; RUN: wasm-opt %s --simplify-locals -all -S -o - | filecheck %s
+
+(module
+ ;; CHECK: (table $table 10 funcref)
+ (table $table 10 funcref)
+
+ ;; CHECK: (elem $zero (i32.const 0) $zero)
+ (elem $zero (i32.const 0) $zero)
+
+ ;; CHECK: (elem $one func $one)
+ (elem $one $one)
+
+ ;; CHECK: (func $move (type $0) (result funcref)
+ ;; CHECK-NEXT: (local $temp funcref)
+ ;; CHECK-NEXT: (nop)
+ ;; CHECK-NEXT: (nop)
+ ;; CHECK-NEXT: (table.get $table
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $move (result funcref)
+ (local $temp funcref)
+ (local.set $temp
+ (table.get $table
+ (i32.const 0)
+ )
+ )
+ ;; We can move the table.get past the nop.
+ (nop)
+ (local.get $temp)
+ )
+
+ ;; CHECK: (func $no-move (type $0) (result funcref)
+ ;; CHECK-NEXT: (local $temp funcref)
+ ;; CHECK-NEXT: (local.set $temp
+ ;; CHECK-NEXT: (table.get $table
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (table.init $table $one
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.get $temp)
+ ;; CHECK-NEXT: )
+ (func $no-move (result funcref)
+ (local $temp funcref)
+ (local.set $temp
+ (table.get $table
+ (i32.const 0)
+ )
+ )
+ ;; table.init writes to the table, so table reads cannot cross it.
+ (table.init $table $one (i32.const 0) (i32.const 0) (i32.const 1))
+ (local.get $temp)
+ )
+
+ ;; CHECK: (func $zero (type $1) (result i32)
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ (func $zero (result i32)
+ (i32.const 0)
+ )
+
+ ;; CHECK: (func $one (type $1) (result i32)
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: )
+ (func $one (result i32)
+ (i32.const 1)
+ )
+)
diff --git a/test/lit/passes/table64-lowering.wast b/test/lit/passes/table64-lowering.wast
index 7e49d3e73..f3aaf4ef8 100644
--- a/test/lit/passes/table64-lowering.wast
+++ b/test/lit/passes/table64-lowering.wast
@@ -67,4 +67,17 @@
(func $test_table_fill
(table.fill $t64 (i64.const 0) (ref.null func) (i64.const 10))
)
+
+ ;; CHECK: (func $test_table_init
+ ;; CHECK-NEXT: (table.init $t64 $elem64
+ ;; CHECK-NEXT: (i32.wrap_i64
+ ;; CHECK-NEXT: (i64.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (i32.const 5)
+ ;; CHECK-NEXT: (i32.const 10)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $test_table_init
+ (table.init $t64 $elem64 (i64.const 0) (i32.const 5) (i32.const 10))
+ )
)
diff --git a/test/lit/passes/unsubtyping.wast b/test/lit/passes/unsubtyping.wast
index 5181b9a1c..590cc5ae1 100644
--- a/test/lit/passes/unsubtyping.wast
+++ b/test/lit/passes/unsubtyping.wast
@@ -820,6 +820,38 @@
(module
;; CHECK: (rec
+ ;; CHECK-NEXT: (type $0 (func))
+
+ ;; CHECK: (type $super (sub (struct)))
+ (type $super (sub (struct)))
+ ;; CHECK: (type $sub (sub $super (struct)))
+ (type $sub (sub $super (struct)))
+
+ ;; CHECK: (table $super 1 1 (ref null $super))
+ (table $super 1 1 (ref null $super))
+
+ ;; CHECK: (elem $sub (ref null $sub))
+ (elem $sub (ref null $sub))
+
+ ;; CHECK: (func $table-copy (type $0)
+ ;; CHECK-NEXT: (table.init $super $sub
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $table-copy
+ ;; This requires $sub <: $super.
+ (table.init $super $sub
+ (i32.const 0)
+ (i32.const 0)
+ (i32.const 0)
+ )
+ )
+)
+
+(module
+ ;; CHECK: (rec
;; CHECK-NEXT: (type $super (sub (struct)))
(type $super (sub (struct)))
;; CHECK: (type $sub (sub $super (struct)))
diff --git a/test/spec/table_init.wast b/test/spec/table_init.wast
new file mode 100644
index 000000000..09cc0afda
--- /dev/null
+++ b/test/spec/table_init.wast
@@ -0,0 +1,52 @@
+;; NOTE: Assertions have been generated by update_lit_checks.py --output=fuzz-exec and should not be edited.
+
+;; RUN: wasm-opt %s -all --fuzz-exec-before -q -o /dev/null 2>&1 | filecheck %s
+
+;; The elem is out of bounds, leading to a trap during initialization.
+(assert_unlinkable
+ (module
+ (table $table 1 1 funcref)
+ (elem $elem (i32.const 1) $foo)
+ (func $foo)
+ )
+ "trap"
+)
+
+;; Now it is in bounds, with the elem offset reduced to 0.
+(module
+ (table $table 1 1 funcref)
+ (elem $elem (i32.const 0) $foo)
+ (func $foo)
+)
+
+;; The table begins with a function that returns zero. table.init will replace
+;; it with one that returns 1.
+(module
+ (type $i (func (result i32)))
+
+ (table $table 10 funcref)
+ (elem $zero (i32.const 0) $zero)
+ (elem $one $one)
+
+ (func $call (export "call") (result i32)
+ (call_indirect (type $i) (i32.const 0))
+ )
+
+ (func $init (export "init") (result i32)
+ (table.init $table $one (i32.const 0) (i32.const 0) (i32.const 1))
+ (call $call)
+ )
+
+ (func $zero (result i32)
+ (i32.const 0)
+ )
+
+ (func $one (result i32)
+ (i32.const 1)
+ )
+)
+
+;; First we get 0, then 1.
+(assert_return (invoke "call") (i32.const 0))
+(assert_return (invoke "init") (i32.const 1))
+