summaryrefslogtreecommitdiff
path: root/test/spec/bulk-array.wast
diff options
context:
space:
mode:
authorThomas Lively <tlively@google.com>2023-04-06 13:35:12 -0700
committerGitHub <noreply@github.com>2023-04-06 20:35:12 +0000
commit4f91c6a569614275d906a825d3f495541aa8802d (patch)
tree26b438a2aeec65e93a219da792b928b7c9c0eece /test/spec/bulk-array.wast
parent6afbc200b57acd1b9111de7729d47fea1d04c5f6 (diff)
downloadbinaryen-4f91c6a569614275d906a825d3f495541aa8802d.tar.gz
binaryen-4f91c6a569614275d906a825d3f495541aa8802d.tar.bz2
binaryen-4f91c6a569614275d906a825d3f495541aa8802d.zip
Implement array.fill, array.init_data, and array.init_elem (#5637)
These complement array.copy, which we already supported, as an initial complete set of bulk array operations. Replace the WIP spec tests with the upstream spec tests, lightly edited for compatibility with Binaryen.
Diffstat (limited to 'test/spec/bulk-array.wast')
-rw-r--r--test/spec/bulk-array.wast528
1 files changed, 330 insertions, 198 deletions
diff --git a/test/spec/bulk-array.wast b/test/spec/bulk-array.wast
index 06c341000..565b21a2f 100644
--- a/test/spec/bulk-array.wast
+++ b/test/spec/bulk-array.wast
@@ -1,225 +1,357 @@
-(module
- ;; Array types used in tests.
- (type $i8 (array (mut i8)))
- (type $i16 (array (mut i16)))
- (type $i32 (array (mut i32)))
- (type $anyref (array (mut anyref)))
- (type $funcref (array (mut funcref)))
- (type $externref (array (mut externref)))
-
- ;; Array values used in tests. Reset in between tests with the "reset"
- ;; function.
- (global $i8 (mut (ref null $i8)) (ref.null none))
- (global $i16 (mut (ref null $i16)) (ref.null none))
- (global $i32 (mut (ref null $i32)) (ref.null none))
- (global $anyref (mut (ref null $anyref)) (ref.null none))
- (global $funcref (mut (ref null $funcref)) (ref.null none))
- (global $externref (mut (ref null $externref)) (ref.null none))
-
- ;; GC objects with distinct identities used in anyref tests.
- (global $g1 (export "g1") (mut anyref) (array.new_fixed $i8))
- (global $g2 (export "g2") (mut anyref) (array.new_fixed $i8))
- (global $g3 (export "g3") (mut anyref) (array.new_fixed $i8))
- (global $g4 (export "g4") (mut anyref) (array.new_fixed $i8))
- (global $g5 (export "g5") (mut anyref) (array.new_fixed $i8))
-
- ;; Functions with distinct return values used in funcref tests.
- (func $f1 (result i32) (i32.const 0))
- (func $f2 (result i32) (i32.const 1))
- (func $f3 (result i32) (i32.const 2))
- (func $f4 (result i32) (i32.const 3))
- (func $f5 (result i32) (i32.const 4))
-
- ;; Passive element segment used in array.init_elem tests.
- (elem $elem anyref
- (array.new_fixed $i8)
- (array.new_fixed $i8)
- (array.new_fixed $i8)
- (array.new_fixed $i8)
- (array.new_fixed $i8))
-
- (table $tab anyref 5 5)
-
- ;; Resets the array globals to known states.
- (func (export "reset")
- (global.set $i8
- (array.new_fixed $i8
- (i32.const 0)
- (i32.const 1)
- (i32.const 2)
- (i32.const 3)
- (i32.const 4)))
- (global.set $i16
- (array.new_fixed $i16
- (i32.const 0)
- (i32.const 1)
- (i32.const 2)
- (i32.const 3)
- (i32.const 4)))
- (global.set $i32
- (array.new_fixed $i32
- (i32.const 0)
- (i32.const 1)
- (i32.const 2)
- (i32.const 3)
- (i32.const 4)))
- (global.set $anyref
- (array.new_fixed $anyref
- (global.get $g1)
- (global.get $g2)
- (global.get $g3)
- (global.get $g4)
- (global.get $g5)))
- (global.set $funcref
- (array.new_fixed $funcref
- (ref.func $f1)
- (ref.func $f2)
- (ref.func $f3)
- (ref.func $f4)
- (ref.func $f5)))
- (global.set $externref
- (array.new_fixed $externref
- (extern.externalize (global.get $g1))
- (extern.externalize (global.get $g2))
- (extern.externalize (global.get $g3))
- (extern.externalize (global.get $g4))
- (extern.externalize (global.get $g5)))))
+;; Bulk instructions
+
+;; invalid uses
+
+;; array.copy
+(assert_invalid
+ (module
+ (type $a (array i8))
+ (type $b (array (mut i8)))
+
+ (func (export "array.copy-immutable") (param $1 (ref $a)) (param $2 (ref $b))
+ (array.copy $a $b (local.get $1) (i32.const 0) (local.get $2) (i32.const 0) (i32.const 0))
+ )
+ )
+ "destination array is immutable"
)
-;; array.fill
+(assert_invalid
+ (module
+ (type $a (array (mut i8)))
+ (type $b (array i16))
-;; basic i8
-;; basic i16
-;; basic i32
-;; basic anyref
-;; basic funcref
-;; basic externref
-;; basic ref subtype
-;; basic ref nullability subtype
+ (func (export "array.copy-packed-invalid") (param $1 (ref $a)) (param $2 (ref $b))
+ (array.copy $a $b (local.get $1) (i32.const 0) (local.get $2) (i32.const 0) (i32.const 0))
+ )
+ )
+ "array types do not match"
+)
-;; zero size in bounds
-;; zero size at bounds
-;; zero size out of bounds traps
+(assert_invalid
+ (module
+ (type $a (array (mut i8)))
+ (type $b (array (mut (ref $a))))
-;; out of bounds index traps
-;; out of bounds size traps
-;; out of bounds index + size traps
+ (func (export "array.copy-ref-invalid-1") (param $1 (ref $a)) (param $2 (ref $b))
+ (array.copy $a $b (local.get $1) (i32.const 0) (local.get $2) (i32.const 0) (i32.const 0))
+ )
+ )
+ "array types do not match"
+)
-;; null destination traps
+(assert_invalid
+ (module
+ (type $a (array (mut i8)))
+ (type $b (array (mut (ref $a))))
+ (type $c (array (mut (ref $b))))
+
+ (func (export "array.copy-ref-invalid-1") (param $1 (ref $b)) (param $2 (ref $c))
+ (array.copy $b $c (local.get $1) (i32.const 0) (local.get $2) (i32.const 0) (i32.const 0))
+ )
+ )
+ "array types do not match"
+)
-;; immutable field invalid
+;; array.fill
+(assert_invalid
+ (module
+ (type $a (array i8))
+
+ (func (export "array.fill-immutable") (param $1 (ref $a)) (param $2 i32)
+ (array.fill $a (local.get $1) (i32.const 0) (local.get $2) (i32.const 0))
+ )
+ )
+ "array is immutable"
+)
-;; ref supertype invalid
-;; ref nullability supertype invalid
+(assert_invalid
+ (module
+ (type $a (array (mut i8)))
-;; array.copy
+ (func (export "array.fill-invalid-1") (param $1 (ref $a)) (param $2 funcref)
+ (array.fill $a (local.get $1) (i32.const 0) (local.get $2) (i32.const 0))
+ )
+ )
+ "type mismatch"
+)
-;; basic i8
-;; basic i16
-;; basic i32
-;; basic anyref
-;; basic funcref
-;; basic externref
-;; basic ref subtype
-;; basic ref nullability subtype
-
-;; same i8 no overlap
-;; same i8 overlap src first
-;; same i8 overlap dest first
-;; same i8 overlap complete
-
-;; same i32 no overlap
-;; same i32 overlap src first
-;; same i32 overlap dest first
-;; same i32 overlap complete
-
-;; same anyref no overlap
-;; same anyref overloap
-;; same anyref src first
-;; same anyref dest first
-;; same anyref overlap complete
-
-;; zero size in bounds
-;; zero size at dest bounds
-;; zero size at src bounds
-;; zero size out of dest bounds traps
-;; zero size out of src bounds traps
-
-;; out of bounds dest index traps
-;; out of bounds src index traps
-;; out of bounds dest size traps
-;; out of bounds src index traps
-;; out of bounds dest index + size traps
-;; out of bounds src index + size traps
-
-;; null dest traps
-;; null src traps
-
-;; immutable dest field invalid
-;; immutable src field ok
-
-;; ref supertype invalid
-;; ref nullability supertype invalid
+(assert_invalid
+ (module
+ (type $b (array (mut funcref)))
+
+ (func (export "array.fill-invalid-1") (param $1 (ref $b)) (param $2 i32)
+ (array.fill $b (local.get $1) (i32.const 0) (local.get $2) (i32.const 0))
+ )
+ )
+ "type mismatch"
+)
;; array.init_data
+(assert_invalid
+ (module
+ (type $a (array i8))
-;; basic i8
-;; basic i16
-;; basic i32
-;; basic f32
+ (data $d1 "a")
-;; zero size in bounds
-;; zero size at dest bounds
-;; zero size at src bounds
-;; zero size out of dest bounds traps
-;; zero size out of src bounds traps
+ (func (export "array.init_data-immutable") (param $1 (ref $a))
+ (array.init_data $a $d1 (local.get $1) (i32.const 0) (i32.const 0) (i32.const 0))
+ )
+ )
+ "array is immutable"
+)
-;; out of bounds dest index traps
-;; out of bounds src index traps
-;; out of bounds dest size traps
-;; out of bounds src size traps
-;; out of bounds src multiplied size traps
-;; out of bounds dest index + size traps
-;; out of bounds src index + size traps
-;; out of bounds src index + multiplied size traps
+(assert_invalid
+ (module
+ (type $a (array (mut funcref)))
-;; null dest traps
-;; segment dropped traps
+ (data $d1 "a")
-;; immutable dest field invalid
+ (func (export "array.init_data-invalid-1") (param $1 (ref $a))
+ (array.init_data $a $d1 (local.get $1) (i32.const 0) (i32.const 0) (i32.const 0))
+ )
+ )
+ "array type is not numeric or vector"
+)
-;; ref supertype invalid
-;; ref nullability supertype invalid
+;; array.init_elem
+(assert_invalid
+ (module
+ (type $a (array funcref))
-;; out of bounds segment index invalid
+ (elem $e1 funcref)
-;; array.init_elem
+ (func (export "array.init_elem-immutable") (param $1 (ref $a))
+ (array.init_elem $a $e1 (local.get $1) (i32.const 0) (i32.const 0) (i32.const 0))
+ )
+ )
+ "array is immutable"
+)
+
+(assert_invalid
+ (module
+ (type $a (array (mut i8)))
-;; basic anyref
-;; basic funcref
-;; basic externref
-;; basic ref subtype
-;; basic ref nullability subtype
+ (elem $e1 funcref)
-;; zero size in bounds
-;; zero size at dest bounds
-;; zero size at src bounds
-;; zero size out of dest bounds traps
-;; zero size out of src bounds traps
+ (func (export "array.init_elem-invalid-1") (param $1 (ref $a))
+ (array.init_elem $a $e1 (local.get $1) (i32.const 0) (i32.const 0) (i32.const 0))
+ )
+ )
+ "type mismatch"
+)
-;; out of bounds dest index traps
-;; out of bounds src index traps
-;; out of bounds dest size traps
-;; out of bounds src size traps
-;; out of bounds dest index + size traps
-;; out of bounds src index + size traps
+(assert_invalid
+ (module
+ (type $a (array (mut funcref)))
-;; null dest traps
-;; segment dropped traps
+ (elem $e1 externref)
-;; immutable dest field invalid
+ (func (export "array.init_elem-invalid-2") (param $1 (ref $a))
+ (array.init_elem $a $e1 (local.get $1) (i32.const 0) (i32.const 0) (i32.const 0))
+ )
+ )
+ "type mismatch"
+)
-;; ref supertype invalid
-;; ref nullability supertype invalid
+(module
+ (type $t_f (func))
+ (type $arr8 (array i8))
+ (type $arr8_mut (array (mut i8)))
+ (type $arr16_mut (array (mut i16)))
+ (type $arrref (array (ref $t_f)))
+ (type $arrref_mut (array (mut funcref)))
+
+ (global $g_arr8 (ref $arr8) (array.new $arr8 (i32.const 10) (i32.const 12)))
+ (global $g_arr8_mut (mut (ref $arr8_mut)) (array.new_default $arr8_mut (i32.const 12)))
+ (global $g_arr16_mut (ref $arr16_mut) (array.new_default $arr16_mut (i32.const 6)))
+ (global $g_arrref (ref $arrref) (array.new $arrref (ref.func $dummy) (i32.const 12)))
+ (global $g_arrref_mut (ref $arrref_mut) (array.new_default $arrref_mut (i32.const 12)))
+
+ (table $t 1 funcref)
+
+ (data $d1 "abcdefghijkl")
+ (elem $e1 func $dummy $dummy $dummy $dummy $dummy $dummy $dummy $dummy $dummy $dummy $dummy $dummy)
+
+ (func $dummy
+ )
+
+ (func (export "array_get_nth") (param $1 i32) (result i32)
+ (array.get_u $arr8_mut (global.get $g_arr8_mut) (local.get $1))
+ )
+
+ (func (export "array_get_nth_i16") (param $1 i32) (result i32)
+ (array.get_u $arr16_mut (global.get $g_arr16_mut) (local.get $1))
+ )
+
+ (func (export "array_call_nth") (param $1 i32)
+ (table.set $t (i32.const 0) (array.get $arrref_mut (global.get $g_arrref_mut) (local.get $1)))
+ (call_indirect $t (i32.const 0))
+ )
+
+ (func (export "array_copy-null-left")
+ (array.copy $arr8_mut $arr8 (ref.null $arr8_mut) (i32.const 0) (global.get $g_arr8) (i32.const 0) (i32.const 0))
+ )
+
+ (func (export "array_copy-null-right")
+ (array.copy $arr8_mut $arr8 (global.get $g_arr8_mut) (i32.const 0) (ref.null $arr8) (i32.const 0) (i32.const 0))
+ )
+
+ (func (export "array_fill-null")
+ (array.fill $arr8_mut (ref.null $arr8_mut) (i32.const 0) (i32.const 0) (i32.const 0))
+ )
+
+ (func (export "array_init_data-null")
+ (array.init_data $arr8_mut $d1 (ref.null $arr8_mut) (i32.const 0) (i32.const 0) (i32.const 0))
+ )
+
+ (func (export "array_init_elem-null")
+ (array.init_elem $arrref_mut $e1 (ref.null $arrref_mut) (i32.const 0) (i32.const 0) (i32.const 0))
+ )
+
+ (func (export "array_copy") (param $1 i32) (param $2 i32) (param $3 i32)
+ (array.copy $arr8_mut $arr8 (global.get $g_arr8_mut) (local.get $1) (global.get $g_arr8) (local.get $2) (local.get $3))
+ )
+
+ (func (export "array_fill") (param $1 i32) (param $2 i32) (param $3 i32)
+ (array.fill $arr8_mut (global.get $g_arr8_mut) (local.get $1) (local.get $2) (local.get $3))
+ )
+
+ (func (export "array_init_data") (param $1 i32) (param $2 i32) (param $3 i32)
+ (array.init_data $arr8_mut $d1 (global.get $g_arr8_mut) (local.get $1) (local.get $2) (local.get $3))
+ )
+
+ (func (export "array_init_data_i16") (param $1 i32) (param $2 i32) (param $3 i32)
+ (array.init_data $arr16_mut $d1 (global.get $g_arr16_mut) (local.get $1) (local.get $2) (local.get $3))
+ )
+
+ (func (export "array_init_elem") (param $1 i32) (param $2 i32) (param $3 i32)
+ (array.init_elem $arrref_mut $e1 (global.get $g_arrref_mut) (local.get $1) (local.get $2) (local.get $3))
+ )
+
+ (func (export "array_copy_overlap_test-1")
+ (local $1 (ref $arr8_mut))
+ (local.set $1
+ (array.new_data $arr8_mut $d1 (i32.const 0) (i32.const 12))
+ )
+ (array.copy $arr8_mut $arr8_mut (local.get $1) (i32.const 1) (local.get $1) (i32.const 0) (i32.const 11))
+ (global.set $g_arr8_mut (local.get $1))
+ )
+
+ (func (export "array_copy_overlap_test-2")
+ (local $1 (ref $arr8_mut))
+ (local.set $1
+ (array.new_data $arr8_mut $d1 (i32.const 0) (i32.const 12))
+ )
+ (array.copy $arr8_mut $arr8_mut (local.get $1) (i32.const 0) (local.get $1) (i32.const 1) (i32.const 11))
+ (global.set $g_arr8_mut (local.get $1))
+ )
+
+ (func (export "drop_segs")
+ (data.drop $d1)
+ ;; (elem.drop $e1) ;; TODO: implement elem.drop
+ )
+)
-;; out of bounds segment index invalid
+;; null array argument traps
+(assert_trap (invoke "array_copy-null-left") "null array reference")
+(assert_trap (invoke "array_copy-null-right") "null array reference")
+(assert_trap (invoke "array_fill-null") "null array reference")
+(assert_trap (invoke "array_init_data-null") "null array reference")
+(assert_trap (invoke "array_init_elem-null") "null array reference")
+
+;; OOB initial index traps
+(assert_trap (invoke "array_copy" (i32.const 13) (i32.const 0) (i32.const 0)) "out of bounds array access")
+(assert_trap (invoke "array_copy" (i32.const 0) (i32.const 13) (i32.const 0)) "out of bounds array access")
+(assert_trap (invoke "array_fill" (i32.const 13) (i32.const 0) (i32.const 0)) "out of bounds array access")
+(assert_trap (invoke "array_init_data" (i32.const 13) (i32.const 0) (i32.const 0)) "out of bounds array access")
+(assert_trap (invoke "array_init_data" (i32.const 0) (i32.const 13) (i32.const 0)) "out of bounds memory access")
+(assert_trap (invoke "array_init_elem" (i32.const 13) (i32.const 0) (i32.const 0)) "out of bounds array access")
+(assert_trap (invoke "array_init_elem" (i32.const 0) (i32.const 13) (i32.const 0)) "out of bounds table access")
+
+;; OOB length traps
+(assert_trap (invoke "array_copy" (i32.const 0) (i32.const 0) (i32.const 13)) "out of bounds array access")
+(assert_trap (invoke "array_copy" (i32.const 0) (i32.const 0) (i32.const 13)) "out of bounds array access")
+(assert_trap (invoke "array_fill" (i32.const 0) (i32.const 0) (i32.const 13)) "out of bounds array access")
+(assert_trap (invoke "array_init_data" (i32.const 0) (i32.const 0) (i32.const 13)) "out of bounds array access")
+(assert_trap (invoke "array_init_data" (i32.const 0) (i32.const 0) (i32.const 13)) "out of bounds array access")
+(assert_trap (invoke "array_init_data_i16" (i32.const 0) (i32.const 0) (i32.const 7)) "out of bounds array access")
+(assert_trap (invoke "array_init_elem" (i32.const 0) (i32.const 0) (i32.const 13)) "out of bounds array access")
+(assert_trap (invoke "array_init_elem" (i32.const 0) (i32.const 0) (i32.const 13)) "out of bounds array access")
+
+;; start index = array size, len = 0 doesn't trap
+(assert_return (invoke "array_copy" (i32.const 12) (i32.const 0) (i32.const 0)))
+(assert_return (invoke "array_copy" (i32.const 0) (i32.const 12) (i32.const 0)))
+(assert_return (invoke "array_fill" (i32.const 12) (i32.const 0) (i32.const 0)))
+(assert_return (invoke "array_init_data" (i32.const 12) (i32.const 0) (i32.const 0)))
+(assert_return (invoke "array_init_data" (i32.const 0) (i32.const 12) (i32.const 0)))
+(assert_return (invoke "array_init_data_i16" (i32.const 0) (i32.const 6) (i32.const 0)))
+(assert_return (invoke "array_init_elem" (i32.const 12) (i32.const 0) (i32.const 0)))
+(assert_return (invoke "array_init_elem" (i32.const 0) (i32.const 12) (i32.const 0)))
+
+;; check arrays were not modified
+(assert_return (invoke "array_get_nth" (i32.const 0)) (i32.const 0))
+(assert_return (invoke "array_get_nth" (i32.const 5)) (i32.const 0))
+(assert_return (invoke "array_get_nth" (i32.const 11)) (i32.const 0))
+(assert_trap (invoke "array_get_nth" (i32.const 12)) "out of bounds array access")
+(assert_return (invoke "array_get_nth_i16" (i32.const 0)) (i32.const 0))
+(assert_return (invoke "array_get_nth_i16" (i32.const 2)) (i32.const 0))
+(assert_return (invoke "array_get_nth_i16" (i32.const 5)) (i32.const 0))
+(assert_trap (invoke "array_get_nth" (i32.const 12)) "out of bounds array access")
+(assert_trap (invoke "array_call_nth" (i32.const 0)) "uninitialized element")
+(assert_trap (invoke "array_call_nth" (i32.const 5)) "uninitialized element")
+(assert_trap (invoke "array_call_nth" (i32.const 11)) "uninitialized element")
+(assert_trap (invoke "array_call_nth" (i32.const 12)) "out of bounds array access")
+
+;; normal cases
+(assert_return (invoke "array_copy" (i32.const 0) (i32.const 0) (i32.const 2)))
+(assert_return (invoke "array_get_nth" (i32.const 0)) (i32.const 10))
+(assert_return (invoke "array_get_nth" (i32.const 1)) (i32.const 10))
+(assert_return (invoke "array_get_nth" (i32.const 2)) (i32.const 0))
+
+(assert_return (invoke "array_fill" (i32.const 2) (i32.const 11) (i32.const 2)))
+(assert_return (invoke "array_get_nth" (i32.const 1)) (i32.const 10))
+(assert_return (invoke "array_get_nth" (i32.const 2)) (i32.const 11))
+(assert_return (invoke "array_get_nth" (i32.const 3)) (i32.const 11))
+(assert_return (invoke "array_get_nth" (i32.const 4)) (i32.const 0))
+
+(assert_return (invoke "array_init_data" (i32.const 4) (i32.const 2) (i32.const 2)))
+(assert_return (invoke "array_get_nth" (i32.const 3)) (i32.const 11))
+(assert_return (invoke "array_get_nth" (i32.const 4)) (i32.const 99))
+(assert_return (invoke "array_get_nth" (i32.const 5)) (i32.const 100))
+(assert_return (invoke "array_get_nth" (i32.const 6)) (i32.const 0))
+
+(assert_return (invoke "array_init_data_i16" (i32.const 2) (i32.const 5) (i32.const 2)))
+(assert_return (invoke "array_get_nth_i16" (i32.const 1)) (i32.const 0))
+(assert_return (invoke "array_get_nth_i16" (i32.const 2)) (i32.const 0x6766))
+(assert_return (invoke "array_get_nth_i16" (i32.const 3)) (i32.const 0x6968))
+(assert_return (invoke "array_get_nth_i16" (i32.const 4)) (i32.const 0))
+
+(assert_return (invoke "array_init_elem" (i32.const 2) (i32.const 3) (i32.const 2)))
+(assert_trap (invoke "array_call_nth" (i32.const 1)) "uninitialized element")
+(assert_return (invoke "array_call_nth" (i32.const 2)))
+(assert_return (invoke "array_call_nth" (i32.const 3)))
+(assert_trap (invoke "array_call_nth" (i32.const 4)) "uninitialized element")
+
+;; test that overlapping array.copy works as if intermediate copy taken
+(assert_return (invoke "array_copy_overlap_test-1"))
+(assert_return (invoke "array_get_nth" (i32.const 0)) (i32.const 97))
+(assert_return (invoke "array_get_nth" (i32.const 1)) (i32.const 97))
+(assert_return (invoke "array_get_nth" (i32.const 2)) (i32.const 98))
+(assert_return (invoke "array_get_nth" (i32.const 5)) (i32.const 101))
+(assert_return (invoke "array_get_nth" (i32.const 10)) (i32.const 106))
+(assert_return (invoke "array_get_nth" (i32.const 11)) (i32.const 107))
+
+(assert_return (invoke "array_copy_overlap_test-2"))
+(assert_return (invoke "array_get_nth" (i32.const 0)) (i32.const 98))
+(assert_return (invoke "array_get_nth" (i32.const 1)) (i32.const 99))
+(assert_return (invoke "array_get_nth" (i32.const 5)) (i32.const 103))
+(assert_return (invoke "array_get_nth" (i32.const 9)) (i32.const 107))
+(assert_return (invoke "array_get_nth" (i32.const 10)) (i32.const 108))
+(assert_return (invoke "array_get_nth" (i32.const 11)) (i32.const 108))
+
+;; init_data/elem with dropped segments traps for non-zero length
+(assert_return (invoke "drop_segs"))
+(assert_return (invoke "array_init_data" (i32.const 0) (i32.const 0) (i32.const 0)))
+(assert_trap (invoke "array_init_data" (i32.const 0) (i32.const 0) (i32.const 1)) "out of bounds memory access")
+(assert_return (invoke "array_init_elem" (i32.const 0) (i32.const 0) (i32.const 0)))
+;; (assert_trap (invoke "array_init_elem" (i32.const 0) (i32.const 0) (i32.const 1)) "out of bounds table access") ;; TODO: implement elem.drop