| ;; 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 (i32.const 0)) |
| (elem 0x0 (i32.const 0) $f $f) |
| (elem 0x000 (offset (i32.const 0))) |
| (elem (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)) |