Skip to content

Commit

Permalink
Merge remote-tracking branch 'gc/main' into wasm-3.0
Browse files Browse the repository at this point in the history
  • Loading branch information
rossberg committed Dec 9, 2024
2 parents 74654a4 + 756060f commit 9d91344
Show file tree
Hide file tree
Showing 7 changed files with 240 additions and 3 deletions.
2 changes: 2 additions & 0 deletions document/core/appendix/changes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -462,6 +462,8 @@ Added more precise types for references. [#proposal-typedref]_

* Refined typing of :ref:`local instructions <valid-instr-variable>` and :ref:`instruction sequences <valid-instr-seq>` to track the :ref:`initialization status <syntax-init>` of :ref:`locals <syntax-local>` with non-:ref:`defaultable <valid-defaultable>` type

* Refined decoding of :ref:`active <syntax-elemmode>` :ref:`element segments <binary-elem>` with implicit element type and plain function indices (opcode :math:`0`) to produce :ref:`non-nullable <syntax-nullable>` :ref:`reference type <syntax-reftype>`.

* Extended :ref:`table definitions <syntax-table>` with optional initializer expression


Expand Down
2 changes: 1 addition & 1 deletion document/core/appendix/index-instructions.py
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,7 @@ def Instruction(name, opcode, type=None, validation=None, execution=None, operat
Instruction(r'\STRUCTGETS~x~y', r'\hex{FB}~\hex{03}', r'[(\REF~\NULL~x)] \to [\I32]', r'valid-struct.get', r'exec-struct.get'),
Instruction(r'\STRUCTGETU~x~y', r'\hex{FB}~\hex{04}', r'[(\REF~\NULL~x)] \to [\I32]', r'valid-struct.get', r'exec-struct.get'),
Instruction(r'\STRUCTSET~x~y', r'\hex{FB}~\hex{05}', r'[(\REF~\NULL~x)~t] \to []', r'valid-struct.set', r'exec-struct.set'),
Instruction(r'\ARRAYNEW~x', r'\hex{FB}~\hex{06}', r'[t] \to [(\REF~x)]', r'valid-array.new', r'exec-array.new'),
Instruction(r'\ARRAYNEW~x', r'\hex{FB}~\hex{06}', r'[t~\I32] \to [(\REF~x)]', r'valid-array.new', r'exec-array.new'),
Instruction(r'\ARRAYNEWDEFAULT~x', r'\hex{FB}~\hex{07}', r'[\I32] \to [(\REF~x)]', r'valid-array.new', r'exec-array.new'),
Instruction(r'\ARRAYNEWFIXED~x~n', r'\hex{FB}~\hex{08}', r'[t^n] \to [(\REF~x)]', r'valid-array.new_fixed', r'exec-array.new_fixed'),
Instruction(r'\ARRAYNEWDATA~x~y', r'\hex{FB}~\hex{09}', r'[\I32~\I32] \to [(\REF~x)]', r'valid-array.new_data', r'exec-array.new_data'),
Expand Down
2 changes: 1 addition & 1 deletion document/core/exec/instructions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4753,7 +4753,7 @@ Control Instructions
\begin{array}[t]{@{}r@{~}l@{}}
(\iff & S.\STABLES[F.\AMODULE.\MITABLES[x]].\TIELEM[i] = \REFFUNCADDR~a \\
\wedge & S.\SFUNCS[a] = f \\
\wedge & S \vdashdeftypematch F.\AMODULE.\MITYPES[y] \matchesdeftype f.\FITYPE)
\wedge & S \vdashdeftypematch f.\FITYPE \matchesdeftype F.\AMODULE.\MITYPES[y])
\end{array}
\\[1ex]
\begin{array}{lcl@{\qquad}l}
Expand Down
68 changes: 68 additions & 0 deletions test/core/gc/array_new_data.wast
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
(module
(type $arr (array (mut i8)))

(data $d "abcd")

(func (export "array-new-data") (param i32 i32) (result (ref $arr))
(array.new_data $arr $d (local.get 0) (local.get 1))
)
)

;; In-bounds data segment accesses.
(assert_return (invoke "array-new-data" (i32.const 0) (i32.const 0)) (ref.array))
(assert_return (invoke "array-new-data" (i32.const 0) (i32.const 4)) (ref.array))
(assert_return (invoke "array-new-data" (i32.const 1) (i32.const 2)) (ref.array))
(assert_return (invoke "array-new-data" (i32.const 4) (i32.const 0)) (ref.array))

;; Out-of-bounds data segment accesses.
(assert_trap (invoke "array-new-data" (i32.const 0) (i32.const 5)) "out of bounds memory access")
(assert_trap (invoke "array-new-data" (i32.const 5) (i32.const 0)) "out of bounds memory access")
(assert_trap (invoke "array-new-data" (i32.const 1) (i32.const 4)) "out of bounds memory access")
(assert_trap (invoke "array-new-data" (i32.const 4) (i32.const 1)) "out of bounds memory access")


(module
(type $arr (array (mut i8)))

(data $d "\aa\bb\cc\dd")

(func (export "array-new-data-contents") (result i32 i32)
(local (ref $arr))
(local.set 0 (array.new_data $arr $d (i32.const 1) (i32.const 2)))
(array.get_u $arr (local.get 0) (i32.const 0))
(array.get_u $arr (local.get 0) (i32.const 1))
)
)

;; Array is initialized with the correct contents.
(assert_return (invoke "array-new-data-contents") (i32.const 0xbb) (i32.const 0xcc))

(module
(type $arr (array (mut i32)))

(data $d "\aa\bb\cc\dd")

(func (export "array-new-data-little-endian") (result i32)
(array.get $arr
(array.new_data $arr $d (i32.const 0) (i32.const 1))
(i32.const 0))
)
)

;; Data segments are interpreted as little-endian.
(assert_return (invoke "array-new-data-little-endian") (i32.const 0xddccbbaa))

(module
(type $arr (array (mut i16)))

(data $d "\00\11\22")

(func (export "array-new-data-unaligned") (result i32)
(array.get_u $arr
(array.new_data $arr $d (i32.const 1) (i32.const 1))
(i32.const 0))
)
)

;; Data inside the segment doesn't need to be aligned to the element size.
(assert_return (invoke "array-new-data-unaligned") (i32.const 0x2211))
103 changes: 103 additions & 0 deletions test/core/gc/array_new_elem.wast
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
;;;; Expression-style element segments.

(module
(type $arr (array i31ref))

(elem $e i31ref
(ref.i31 (i32.const 0xaa))
(ref.i31 (i32.const 0xbb))
(ref.i31 (i32.const 0xcc))
(ref.i31 (i32.const 0xdd)))

(func (export "array-new-elem") (param i32 i32) (result (ref $arr))
(array.new_elem $arr $e (local.get 0) (local.get 1))
)
)

;; In-bounds element segment accesses.
(assert_return (invoke "array-new-elem" (i32.const 0) (i32.const 0)) (ref.array))
(assert_return (invoke "array-new-elem" (i32.const 0) (i32.const 4)) (ref.array))
(assert_return (invoke "array-new-elem" (i32.const 1) (i32.const 2)) (ref.array))
(assert_return (invoke "array-new-elem" (i32.const 4) (i32.const 0)) (ref.array))

;; Out-of-bounds element segment accesses.
(assert_trap (invoke "array-new-elem" (i32.const 0) (i32.const 5)) "out of bounds table access")
(assert_trap (invoke "array-new-elem" (i32.const 5) (i32.const 0)) "out of bounds table access")
(assert_trap (invoke "array-new-elem" (i32.const 1) (i32.const 4)) "out of bounds table access")
(assert_trap (invoke "array-new-elem" (i32.const 4) (i32.const 1)) "out of bounds table access")

(module
(type $arr (array i31ref))

(elem $e i31ref
(ref.i31 (i32.const 0xaa))
(ref.i31 (i32.const 0xbb))
(ref.i31 (i32.const 0xcc))
(ref.i31 (i32.const 0xdd)))

(func (export "array-new-elem-contents") (result i32 i32)
(local (ref $arr))
(local.set 0 (array.new_elem $arr $e (i32.const 1) (i32.const 2)))
(i31.get_u (array.get $arr (local.get 0) (i32.const 0)))
(i31.get_u (array.get $arr (local.get 0) (i32.const 1)))
)
)

;; Array is initialized with the correct contents.
(assert_return (invoke "array-new-elem-contents") (i32.const 0xbb) (i32.const 0xcc))

;;;; MVP-style function-index segments.

(module
(type $arr (array funcref))

(elem $e func $aa $bb $cc $dd)
(func $aa (result i32) (i32.const 0xaa))
(func $bb (result i32) (i32.const 0xbb))
(func $cc (result i32) (i32.const 0xcc))
(func $dd (result i32) (i32.const 0xdd))

(func (export "array-new-elem") (param i32 i32) (result (ref $arr))
(array.new_elem $arr $e (local.get 0) (local.get 1))
)
)

;; In-bounds element segment accesses.
(assert_return (invoke "array-new-elem" (i32.const 0) (i32.const 0)) (ref.array))
(assert_return (invoke "array-new-elem" (i32.const 0) (i32.const 4)) (ref.array))
(assert_return (invoke "array-new-elem" (i32.const 1) (i32.const 2)) (ref.array))
(assert_return (invoke "array-new-elem" (i32.const 4) (i32.const 0)) (ref.array))

;; Out-of-bounds element segment accesses.
(assert_trap (invoke "array-new-elem" (i32.const 0) (i32.const 5)) "out of bounds table access")
(assert_trap (invoke "array-new-elem" (i32.const 5) (i32.const 0)) "out of bounds table access")
(assert_trap (invoke "array-new-elem" (i32.const 1) (i32.const 4)) "out of bounds table access")
(assert_trap (invoke "array-new-elem" (i32.const 4) (i32.const 1)) "out of bounds table access")

(module
(type $f (func (result i32)))
(type $arr (array funcref))

(elem $e func $aa $bb $cc $dd)
(func $aa (result i32) (i32.const 0xaa))
(func $bb (result i32) (i32.const 0xbb))
(func $cc (result i32) (i32.const 0xcc))
(func $dd (result i32) (i32.const 0xdd))

(table $t 2 2 funcref)

(func (export "array-new-elem-contents") (result i32 i32)
(local (ref $arr))
(local.set 0 (array.new_elem $arr $e (i32.const 1) (i32.const 2)))

(table.set $t (i32.const 0) (array.get $arr (local.get 0) (i32.const 0)))
(table.set $t (i32.const 1) (array.get $arr (local.get 0) (i32.const 1)))

(call_indirect (type $f) (i32.const 0))
(call_indirect (type $f) (i32.const 1))

)
)

;; Array is initialized with the correct contents.
(assert_return (invoke "array-new-elem-contents") (i32.const 0xbb) (i32.const 0xcc))
2 changes: 1 addition & 1 deletion test/core/gc/i31.wast
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
(i31.get_u (ref.null i31))
)
(func (export "get_s-null") (result i32)
(i31.get_u (ref.null i31))
(i31.get_s (ref.null i31))
)

(global $i (ref i31) (ref.i31 (i32.const 2)))
Expand Down
64 changes: 64 additions & 0 deletions test/core/gc/type-subtyping.wast
Original file line number Diff line number Diff line change
Expand Up @@ -824,6 +824,70 @@
"sub type"
)

(assert_invalid
(module
(type $a (sub (array (ref none))))
(type $b (sub $a (array (ref any))))
)
"sub type 1 does not match super type"
)

(assert_invalid
(module
(type $a (sub (array (mut (ref any)))))
(type $b (sub $a (array (mut (ref none)))))
)
"sub type 1 does not match super type"
)

(assert_invalid
(module
(type $a (sub (array (mut (ref any)))))
(type $b (sub $a (array (ref any))))
)
"sub type 1 does not match super type"
)

(assert_invalid
(module
(type $a (sub (array (ref any))))
(type $b (sub $a (array (mut (ref any)))))
)
"sub type 1 does not match super type"
)

(assert_invalid
(module
(type $a (sub (struct (field (ref none)))))
(type $b (sub $a (struct (field (ref any)))))
)
"sub type 1 does not match super type"
)

(assert_invalid
(module
(type $a (sub (struct (field (mut (ref any))))))
(type $b (sub $a (struct (field (mut (ref none))))))
)
"sub type 1 does not match super type"
)

(assert_invalid
(module
(type $a (sub (struct (field (mut (ref any))))))
(type $b (sub $a (struct (field (ref any)))))
)
"sub type 1 does not match super type"
)

(assert_invalid
(module
(type $a (sub (struct (field (ref any)))))
(type $b (sub $a (struct (field (mut (ref any))))))
)
"sub type 1 does not match super type"
)

(assert_invalid
(module
(type $f0 (sub (func)))
Expand Down

0 comments on commit 9d91344

Please sign in to comment.