From 33f15e692b492cccba702e49ac9ff67e1302987a Mon Sep 17 00:00:00 2001 From: Nick Fitzgerald Date: Thu, 4 Apr 2024 10:42:34 -0700 Subject: [PATCH 1/2] Add additional i31ref spec tests I noticed that Wasmtime was passing the spec tests despite having bits that were known to be unimplemented. This should help the tests exercise those corners of the spec. Notably: * Setting `i31ref` globals. * Initializing tables and globals with `(ref.i31 (global.get $g))`. * Table operations on `i31ref` tables. * Accessing `anyref` globals and tables that are actually `i31ref`s. This is interesting to exercise outside of general subtyping because we have different paths in our inline GC barriers for `anyref`s that are actually `i31ref`s. --- test/core/gc/i31.wast | 215 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 215 insertions(+) diff --git a/test/core/gc/i31.wast b/test/core/gc/i31.wast index 3b6c32fba..0a8b21e47 100644 --- a/test/core/gc/i31.wast +++ b/test/core/gc/i31.wast @@ -19,10 +19,17 @@ (global $i (ref i31) (ref.i31 (i32.const 2))) (global $m (mut (ref i31)) (ref.i31 (i32.const 3))) + (func (export "get_globals") (result i32 i32) (i31.get_u (global.get $i)) (i31.get_u (global.get $m)) ) + + (func (export "set_global") (param i32) + local.get 0 + ref.i31 + global.set $m + ) ) (assert_return (invoke "new" (i32.const 1)) (ref.i31)) @@ -49,3 +56,211 @@ (assert_trap (invoke "get_s-null") "null i31 reference") (assert_return (invoke "get_globals") (i32.const 2) (i32.const 3)) + +(invoke "set_global" (i32.const 1234)) +(assert_return (invoke "get_globals") (i32.const 2) (i32.const 1234)) + +(module $tables_of_i31ref + (table $table 3 10 i31ref) + (elem (table $table) (i32.const 0) i31ref (item (ref.i31 (i32.const 999))) + (item (ref.i31 (i32.const 888))) + (item (ref.i31 (i32.const 777)))) + + (func (export "size") (result i32) + table.size $table + ) + + (func (export "get") (param i32) (result i32) + local.get 0 + table.get $table + i31.get_u + ) + + (func (export "grow") (param i32 i32) (result i32) + (ref.i31 (local.get 1)) + local.get 0 + table.grow $table + ) + + (func (export "fill") (param i32 i32 i32) + local.get 0 + (ref.i31 (local.get 1)) + local.get 2 + table.fill $table + ) + + (func (export "copy") (param i32 i32 i32) + local.get 0 + local.get 1 + local.get 2 + table.copy $table $table + ) + + (elem $elem i31ref (item (ref.i31 (i32.const 123))) + (item (ref.i31 (i32.const 456))) + (item (ref.i31 (i32.const 789)))) + (func (export "init") (param i32 i32 i32) + local.get 0 + local.get 1 + local.get 2 + table.init $table $elem + ) +) + +;; Initial state. +(assert_return (invoke "size") (i32.const 3)) +(assert_return (invoke "get" (i32.const 0)) (i32.const 999)) +(assert_return (invoke "get" (i32.const 1)) (i32.const 888)) +(assert_return (invoke "get" (i32.const 2)) (i32.const 777)) + +;; Grow from size 3 to size 5. +(assert_return (invoke "grow" (i32.const 2) (i32.const 333)) (i32.const 3)) +(assert_return (invoke "size") (i32.const 5)) +(assert_return (invoke "get" (i32.const 3)) (i32.const 333)) +(assert_return (invoke "get" (i32.const 4)) (i32.const 333)) + +;; Fill table[2..4] = 111. +(invoke "fill" (i32.const 2) (i32.const 111) (i32.const 2)) +(assert_return (invoke "get" (i32.const 2)) (i32.const 111)) +(assert_return (invoke "get" (i32.const 3)) (i32.const 111)) + +;; Copy from table[0..2] to table[3..5]. +(invoke "copy" (i32.const 3) (i32.const 0) (i32.const 2)) +(assert_return (invoke "get" (i32.const 3)) (i32.const 999)) +(assert_return (invoke "get" (i32.const 4)) (i32.const 888)) + +;; Initialize the passive element at table[1..4]. +(invoke "init" (i32.const 1) (i32.const 0) (i32.const 3)) +(assert_return (invoke "get" (i32.const 1)) (i32.const 123)) +(assert_return (invoke "get" (i32.const 2)) (i32.const 456)) +(assert_return (invoke "get" (i32.const 3)) (i32.const 789)) + +(module $env + (global (export "g") i32 (i32.const 42)) +) +(register "env") + +(module $i31ref_of_global_table_initializer + (global $g (import "env" "g") i32) + (table $t 3 3 (ref i31) (ref.i31 (global.get $g))) + (func (export "get") (param i32) (result i32) + local.get 0 + table.get $t + i31.get_u + ) +) + +(assert_return (invoke "get" (i32.const 0)) (i32.const 42)) +(assert_return (invoke "get" (i32.const 0)) (i32.const 42)) +(assert_return (invoke "get" (i32.const 0)) (i32.const 42)) + +(module $i31ref_of_global_global_initializer + (global $g0 (import "env" "g") i32) + (global $g1 i31ref (ref.i31 (global.get $g0))) + (func (export "get") (result i32) + global.get $g1 + i31.get_u + ) +) + +(assert_return (invoke "get") (i32.const 42)) + +(module $anyref_global_of_i31ref + (global $c anyref (ref.i31 (i32.const 1234))) + (global $m (mut anyref) (ref.i31 (i32.const 5678))) + + (func (export "get_globals") (result i32 i32) + global.get $c + ref.cast i31ref + i31.get_u + global.get $m + ref.cast i31ref + i31.get_u + ) + + (func (export "set_global") (param i32) + local.get 0 + ref.i31 + global.set $m + ) +) + +(assert_return (invoke "get_globals") (i32.const 1234) (i32.const 5678)) +(invoke "set_global" (i32.const 0)) +(assert_return (invoke "get_globals") (i32.const 1234) (i32.const 0)) + +(module $anyref_table_of_i31ref + (table $table 3 10 anyref) + (elem (table $table) (i32.const 0) i31ref (item (ref.i31 (i32.const 999))) + (item (ref.i31 (i32.const 888))) + (item (ref.i31 (i32.const 777)))) + + (func (export "size") (result i32) + table.size $table + ) + + (func (export "get") (param i32) (result i32) + local.get 0 + table.get $table + ref.cast i31ref + i31.get_u + ) + + (func (export "grow") (param i32 i32) (result i32) + (ref.i31 (local.get 1)) + local.get 0 + table.grow $table + ) + + (func (export "fill") (param i32 i32 i32) + local.get 0 + (ref.i31 (local.get 1)) + local.get 2 + table.fill $table + ) + + (func (export "copy") (param i32 i32 i32) + local.get 0 + local.get 1 + local.get 2 + table.copy $table $table + ) + + (elem $elem i31ref (item (ref.i31 (i32.const 123))) + (item (ref.i31 (i32.const 456))) + (item (ref.i31 (i32.const 789)))) + (func (export "init") (param i32 i32 i32) + local.get 0 + local.get 1 + local.get 2 + table.init $table $elem + ) +) + +;; Initial state. +(assert_return (invoke "size") (i32.const 3)) +(assert_return (invoke "get" (i32.const 0)) (i32.const 999)) +(assert_return (invoke "get" (i32.const 1)) (i32.const 888)) +(assert_return (invoke "get" (i32.const 2)) (i32.const 777)) + +;; Grow from size 3 to size 5. +(assert_return (invoke "grow" (i32.const 2) (i32.const 333)) (i32.const 3)) +(assert_return (invoke "size") (i32.const 5)) +(assert_return (invoke "get" (i32.const 3)) (i32.const 333)) +(assert_return (invoke "get" (i32.const 4)) (i32.const 333)) + +;; Fill table[2..4] = 111. +(invoke "fill" (i32.const 2) (i32.const 111) (i32.const 2)) +(assert_return (invoke "get" (i32.const 2)) (i32.const 111)) +(assert_return (invoke "get" (i32.const 3)) (i32.const 111)) + +;; Copy from table[0..2] to table[3..5]. +(invoke "copy" (i32.const 3) (i32.const 0) (i32.const 2)) +(assert_return (invoke "get" (i32.const 3)) (i32.const 999)) +(assert_return (invoke "get" (i32.const 4)) (i32.const 888)) + +;; Initialize the passive element at table[1..4]. +(invoke "init" (i32.const 1) (i32.const 0) (i32.const 3)) +(assert_return (invoke "get" (i32.const 1)) (i32.const 123)) +(assert_return (invoke "get" (i32.const 2)) (i32.const 456)) +(assert_return (invoke "get" (i32.const 3)) (i32.const 789)) From 18ab40c8ea900f551f96ab705d9e4ea56ce08000 Mon Sep 17 00:00:00 2001 From: Nick Fitzgerald Date: Mon, 8 Apr 2024 13:41:33 -0700 Subject: [PATCH 2/2] Switch to nested operators --- test/core/gc/i31.wast | 70 ++++++++++--------------------------------- 1 file changed, 16 insertions(+), 54 deletions(-) diff --git a/test/core/gc/i31.wast b/test/core/gc/i31.wast index 0a8b21e47..1d98abb65 100644 --- a/test/core/gc/i31.wast +++ b/test/core/gc/i31.wast @@ -26,9 +26,7 @@ ) (func (export "set_global") (param i32) - local.get 0 - ref.i31 - global.set $m + (global.set $m (ref.i31 (local.get 0))) ) ) @@ -71,39 +69,26 @@ ) (func (export "get") (param i32) (result i32) - local.get 0 - table.get $table - i31.get_u + (i31.get_u (table.get $table (local.get 0))) ) (func (export "grow") (param i32 i32) (result i32) - (ref.i31 (local.get 1)) - local.get 0 - table.grow $table + (table.grow $table (ref.i31 (local.get 1)) (local.get 0)) ) (func (export "fill") (param i32 i32 i32) - local.get 0 - (ref.i31 (local.get 1)) - local.get 2 - table.fill $table + (table.fill $table (local.get 0) (ref.i31 (local.get 1)) (local.get 2)) ) (func (export "copy") (param i32 i32 i32) - local.get 0 - local.get 1 - local.get 2 - table.copy $table $table + (table.copy $table $table (local.get 0) (local.get 1) (local.get 2)) ) (elem $elem i31ref (item (ref.i31 (i32.const 123))) (item (ref.i31 (i32.const 456))) (item (ref.i31 (i32.const 789)))) (func (export "init") (param i32 i32 i32) - local.get 0 - local.get 1 - local.get 2 - table.init $table $elem + (table.init $table $elem (local.get 0) (local.get 1) (local.get 2)) ) ) @@ -144,9 +129,7 @@ (global $g (import "env" "g") i32) (table $t 3 3 (ref i31) (ref.i31 (global.get $g))) (func (export "get") (param i32) (result i32) - local.get 0 - table.get $t - i31.get_u + (i31.get_u (local.get 0) (table.get $t)) ) ) @@ -158,8 +141,7 @@ (global $g0 (import "env" "g") i32) (global $g1 i31ref (ref.i31 (global.get $g0))) (func (export "get") (result i32) - global.get $g1 - i31.get_u + (i31.get_u (global.get $g1)) ) ) @@ -170,18 +152,12 @@ (global $m (mut anyref) (ref.i31 (i32.const 5678))) (func (export "get_globals") (result i32 i32) - global.get $c - ref.cast i31ref - i31.get_u - global.get $m - ref.cast i31ref - i31.get_u + (i31.get_u (ref.cast i31ref (global.get $c))) + (i31.get_u (ref.cast i31ref (global.get $m))) ) (func (export "set_global") (param i32) - local.get 0 - ref.i31 - global.set $m + (global.set $m (ref.i31 (local.get 0))) ) ) @@ -200,40 +176,26 @@ ) (func (export "get") (param i32) (result i32) - local.get 0 - table.get $table - ref.cast i31ref - i31.get_u + (i31.get_u (ref.cast i31ref (table.get $table (local.get 0)))) ) (func (export "grow") (param i32 i32) (result i32) - (ref.i31 (local.get 1)) - local.get 0 - table.grow $table + (table.grow $table (ref.i31 (local.get 1)) (local.get 0)) ) (func (export "fill") (param i32 i32 i32) - local.get 0 - (ref.i31 (local.get 1)) - local.get 2 - table.fill $table + (table.fill $table (local.get 0) (ref.i31 (local.get 1)) (local.get 2)) ) (func (export "copy") (param i32 i32 i32) - local.get 0 - local.get 1 - local.get 2 - table.copy $table $table + (table.copy $table $table (local.get 0) (local.get 1) (local.get 2)) ) (elem $elem i31ref (item (ref.i31 (i32.const 123))) (item (ref.i31 (i32.const 456))) (item (ref.i31 (i32.const 789)))) (func (export "init") (param i32 i32 i32) - local.get 0 - local.get 1 - local.get 2 - table.init $table $elem + (table.init $table $elem (local.get 0) (local.get 1) (local.get 2)) ) )