summaryrefslogtreecommitdiff
path: root/test/spec/elem.wast
diff options
context:
space:
mode:
Diffstat (limited to 'test/spec/elem.wast')
-rw-r--r--test/spec/elem.wast381
1 files changed, 381 insertions, 0 deletions
diff --git a/test/spec/elem.wast b/test/spec/elem.wast
new file mode 100644
index 000000000..1ea2b0618
--- /dev/null
+++ b/test/spec/elem.wast
@@ -0,0 +1,381 @@
+;; Test the element section
+
+;; Syntax
+(module
+ (table $t 10 funcref)
+ (func $f)
+ (elem (i32.const 0))
+ (elem (i32.const 0) $f $f)
+ (elem (offset (i32.const 0)))
+ (elem (offset (i32.const 0)) $f $f)
+ (elem 0 (i32.const 0))
+ (elem 0x0 (i32.const 0) $f $f)
+ (elem 0x000 (offset (i32.const 0)))
+ (elem 0 (offset (i32.const 0)) $f $f)
+ (elem $t (i32.const 0))
+ (elem $t (i32.const 0) $f $f)
+ (elem $t (offset (i32.const 0)))
+ (elem $t (offset (i32.const 0)) $f $f)
+)
+
+;; Basic use
+
+(module
+ (table 10 funcref)
+ (func $f)
+ (elem (i32.const 0) $f)
+)
+(module
+ (import "spectest" "table" (table 10 funcref))
+ (func $f)
+ (elem (i32.const 0) $f)
+)
+
+(module
+ (table 10 funcref)
+ (func $f)
+ (elem (i32.const 0) $f)
+ (elem (i32.const 3) $f)
+ (elem (i32.const 7) $f)
+ (elem (i32.const 5) $f)
+ (elem (i32.const 3) $f)
+)
+(module
+ (import "spectest" "table" (table 10 funcref))
+ (func $f)
+ (elem (i32.const 9) $f)
+ (elem (i32.const 3) $f)
+ (elem (i32.const 7) $f)
+ (elem (i32.const 3) $f)
+ (elem (i32.const 5) $f)
+)
+
+(module
+ (global (import "spectest" "global_i32") i32)
+ (table 1000 funcref)
+ (func $f)
+ (elem (global.get 0) $f)
+)
+
+(module
+ (global $g (import "spectest" "global_i32") i32)
+ (table 1000 funcref)
+ (func $f)
+ (elem (global.get $g) $f)
+)
+
+(module
+ (type $out-i32 (func (result i32)))
+ (table 10 funcref)
+ (elem (i32.const 7) $const-i32-a)
+ (elem (i32.const 9) $const-i32-b)
+ (func $const-i32-a (type $out-i32) (i32.const 65))
+ (func $const-i32-b (type $out-i32) (i32.const 66))
+ (func (export "call-7") (type $out-i32)
+ (call_indirect (type $out-i32) (i32.const 7))
+ )
+ (func (export "call-9") (type $out-i32)
+ (call_indirect (type $out-i32) (i32.const 9))
+ )
+)
+(assert_return (invoke "call-7") (i32.const 65))
+(assert_return (invoke "call-9") (i32.const 66))
+
+;; Corner cases
+
+(module
+ (table 10 funcref)
+ (func $f)
+ (elem (i32.const 9) $f)
+)
+(module
+ (import "spectest" "table" (table 10 funcref))
+ (func $f)
+ (elem (i32.const 9) $f)
+)
+
+(module
+ (table 0 funcref)
+ (elem (i32.const 0))
+)
+(module
+ (import "spectest" "table" (table 0 funcref))
+ (elem (i32.const 0))
+)
+
+(module
+ (table 0 0 funcref)
+ (elem (i32.const 0))
+)
+
+(module
+ (table 20 funcref)
+ (elem (i32.const 20))
+)
+
+(module
+ (import "spectest" "table" (table 0 funcref))
+ (func $f)
+ (elem (i32.const 0) $f)
+)
+
+(module
+ (import "spectest" "table" (table 0 100 funcref))
+ (func $f)
+ (elem (i32.const 0) $f)
+)
+
+(module
+ (import "spectest" "table" (table 0 funcref))
+ (func $f)
+ (elem (i32.const 1) $f)
+)
+
+(module
+ (import "spectest" "table" (table 0 30 funcref))
+ (func $f)
+ (elem (i32.const 1) $f)
+)
+
+;; Invalid bounds for elements
+
+(assert_unlinkable
+ (module
+ (table 0 funcref)
+ (func $f)
+ (elem (i32.const 0) $f)
+ )
+ "elements segment does not fit"
+)
+
+(assert_unlinkable
+ (module
+ (table 0 0 funcref)
+ (func $f)
+ (elem (i32.const 0) $f)
+ )
+ "elements segment does not fit"
+)
+
+(assert_unlinkable
+ (module
+ (table 0 1 funcref)
+ (func $f)
+ (elem (i32.const 0) $f)
+ )
+ "elements segment does not fit"
+)
+
+(assert_unlinkable
+ (module
+ (table 0 funcref)
+ (elem (i32.const 1))
+ )
+ "elements segment does not fit"
+)
+
+(assert_unlinkable
+ (module
+ (table 10 funcref)
+ (func $f)
+ (elem (i32.const 10) $f)
+ )
+ "elements segment does not fit"
+)
+(assert_unlinkable
+ (module
+ (import "spectest" "table" (table 10 funcref))
+ (func $f)
+ (elem (i32.const 10) $f)
+ )
+ "elements segment does not fit"
+)
+
+(assert_unlinkable
+ (module
+ (table 10 20 funcref)
+ (func $f)
+ (elem (i32.const 10) $f)
+ )
+ "elements segment does not fit"
+)
+(assert_unlinkable
+ (module
+ (import "spectest" "table" (table 10 funcref))
+ (func $f)
+ (elem (i32.const 10) $f)
+ )
+ "elements segment does not fit"
+)
+
+(assert_unlinkable
+ (module
+ (table 10 funcref)
+ (func $f)
+ (elem (i32.const -1) $f)
+ )
+ "elements segment does not fit"
+)
+(assert_unlinkable
+ (module
+ (import "spectest" "table" (table 10 funcref))
+ (func $f)
+ (elem (i32.const -1) $f)
+ )
+ "elements segment does not fit"
+)
+
+(assert_unlinkable
+ (module
+ (table 10 funcref)
+ (func $f)
+ (elem (i32.const -10) $f)
+ )
+ "elements segment does not fit"
+)
+(assert_unlinkable
+ (module
+ (import "spectest" "table" (table 10 funcref))
+ (func $f)
+ (elem (i32.const -10) $f)
+ )
+ "elements segment does not fit"
+)
+
+;; Element without table
+
+(assert_invalid
+ (module
+ (func $f)
+ (elem (i32.const 0) $f)
+ )
+ "unknown table"
+)
+
+;; Invalid offsets
+
+(assert_invalid
+ (module
+ (table 1 funcref)
+ (elem (i64.const 0))
+ )
+ "type mismatch"
+)
+
+(assert_invalid
+ (module
+ (table 1 funcref)
+ (elem (i32.ctz (i32.const 0)))
+ )
+ "constant expression required"
+)
+
+(assert_invalid
+ (module
+ (table 1 funcref)
+ (elem (nop))
+ )
+ "constant expression required"
+)
+
+(assert_invalid
+ (module
+ (table 1 funcref)
+ (elem (offset (nop) (i32.const 0)))
+ )
+ "constant expression required"
+)
+
+(assert_invalid
+ (module
+ (table 1 funcref)
+ (elem (offset (i32.const 0) (nop)))
+ )
+ "constant expression required"
+)
+
+;; Use of internal globals in constant expressions is not allowed in MVP.
+;; (assert_invalid
+;; (module (memory 1) (data (global.get $g)) (global $g (mut i32) (i32.const 0)))
+;; "constant expression required"
+;; )
+
+;; Two elements target the same slot
+
+(module
+ (type $out-i32 (func (result i32)))
+ (table 10 funcref)
+ (elem (i32.const 9) $const-i32-a)
+ (elem (i32.const 9) $const-i32-b)
+ (func $const-i32-a (type $out-i32) (i32.const 65))
+ (func $const-i32-b (type $out-i32) (i32.const 66))
+ (func (export "call-overwritten") (type $out-i32)
+ (call_indirect (type $out-i32) (i32.const 9))
+ )
+)
+(assert_return (invoke "call-overwritten") (i32.const 66))
+
+(module
+ (type $out-i32 (func (result i32)))
+ (import "spectest" "table" (table 10 funcref))
+ (elem (i32.const 9) $const-i32-a)
+ (elem (i32.const 9) $const-i32-b)
+ (func $const-i32-a (type $out-i32) (i32.const 65))
+ (func $const-i32-b (type $out-i32) (i32.const 66))
+ (func (export "call-overwritten-element") (type $out-i32)
+ (call_indirect (type $out-i32) (i32.const 9))
+ )
+)
+(assert_return (invoke "call-overwritten-element") (i32.const 66))
+
+;; Element sections across multiple modules change the same table
+
+(module $module1
+ (type $out-i32 (func (result i32)))
+ (table (export "shared-table") 10 funcref)
+ (elem (i32.const 8) $const-i32-a)
+ (elem (i32.const 9) $const-i32-b)
+ (func $const-i32-a (type $out-i32) (i32.const 65))
+ (func $const-i32-b (type $out-i32) (i32.const 66))
+ (func (export "call-7") (type $out-i32)
+ (call_indirect (type $out-i32) (i32.const 7))
+ )
+ (func (export "call-8") (type $out-i32)
+ (call_indirect (type $out-i32) (i32.const 8))
+ )
+ (func (export "call-9") (type $out-i32)
+ (call_indirect (type $out-i32) (i32.const 9))
+ )
+)
+
+(register "module1" $module1)
+
+(assert_trap (invoke $module1 "call-7") "uninitialized element")
+(assert_return (invoke $module1 "call-8") (i32.const 65))
+(assert_return (invoke $module1 "call-9") (i32.const 66))
+
+(module $module2
+ (type $out-i32 (func (result i32)))
+ (import "module1" "shared-table" (table 10 funcref))
+ (elem (i32.const 7) $const-i32-c)
+ (elem (i32.const 8) $const-i32-d)
+ (func $const-i32-c (type $out-i32) (i32.const 67))
+ (func $const-i32-d (type $out-i32) (i32.const 68))
+)
+
+(assert_return (invoke $module1 "call-7") (i32.const 67))
+(assert_return (invoke $module1 "call-8") (i32.const 68))
+(assert_return (invoke $module1 "call-9") (i32.const 66))
+
+(module $module3
+ (type $out-i32 (func (result i32)))
+ (import "module1" "shared-table" (table 10 funcref))
+ (elem (i32.const 8) $const-i32-e)
+ (elem (i32.const 9) $const-i32-f)
+ (func $const-i32-e (type $out-i32) (i32.const 69))
+ (func $const-i32-f (type $out-i32) (i32.const 70))
+)
+
+(assert_return (invoke $module1 "call-7") (i32.const 67))
+(assert_return (invoke $module1 "call-8") (i32.const 69))
+(assert_return (invoke $module1 "call-9") (i32.const 70))