Skip to content
This repository was archived by the owner on Nov 3, 2021. It is now read-only.

[spec/interpreter/test] Allow nullref type externally #66

Merged
merged 1 commit into from
Dec 13, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion document/core/appendix/index-types.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ Category Constructor
(reserved) :math:`\hex{7B}` .. :math:`\hex{71}`
:ref:`Reference type <syntax-reftype>` |FUNCREF| :math:`\hex{70}` (-16 as |Bs7|)
:ref:`Reference type <syntax-reftype>` |ANYREF| :math:`\hex{6F}` (-17 as |Bs7|)
(reserved) :math:`\hex{6E}` .. :math:`\hex{61}`
:ref:`Reference type <syntax-reftype>` |NULLREF| :math:`\hex{6E}` (-18 as |Bs7|)
(reserved) :math:`\hex{6D}` .. :math:`\hex{61}`
:ref:`Function type <syntax-functype>` :math:`[\valtype^\ast] \to [\valtype^\ast]` :math:`\hex{60}` (-32 as |Bs7|)
(reserved) :math:`\hex{5F}` .. :math:`\hex{41}`
:ref:`Result type <syntax-resulttype>` :math:`[\epsilon]` :math:`\hex{40}` (-64 as |Bs7|)
Expand Down
6 changes: 2 additions & 4 deletions document/core/binary/types.rst
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,10 @@ Reference Types
\begin{array}{llclll@{\qquad\qquad}l}
\production{reference type} & \Breftype &::=&
\hex{70} &\Rightarrow& \FUNCREF \\ &&|&
\hex{6F} &\Rightarrow& \ANYREF \\
\hex{6F} &\Rightarrow& \ANYREF \\ &&|&
\hex{6E} &\Rightarrow& \NULLREF \\
\end{array}

.. note::
The type :math:`\NULLREF` cannot occur in a module.


.. index:: value type, number type, reference type
pair: binary format; value type
Expand Down
2 changes: 0 additions & 2 deletions document/core/syntax/types.rst
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,6 @@ The type |FUNCREF| denotes the infinite union of all references to :ref:`functio

The type |NULLREF| only contains a single value: the :ref:`null <syntax-ref.null>` reference.
It is a :ref:`subtype <match-reftype>` of all other reference types.
By virtue of being representable in neither the :ref:`binary format <binary-reftype>` nor the :ref:`text format <text-reftype>`, the |NULLREF| type cannot be used in a program;
it only occurs during :ref:`validation <valid>`.

.. note::
Future versions of WebAssembly may include reference types that do not include null and hence are not supertypes of |NULLREF|.
Expand Down
3 changes: 2 additions & 1 deletion document/core/text/types.rst
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ Reference Types
\begin{array}{llcll@{\qquad\qquad}l}
\production{reference type} & \Treftype &::=&
\text{anyref} &\Rightarrow& \ANYREF \\ &&|&
\text{funcref} &\Rightarrow& \FUNCREF \\
\text{funcref} &\Rightarrow& \FUNCREF \\ &&|&
\text{nullref} &\Rightarrow& \NULLREF \\
\end{array}


Expand Down
15 changes: 12 additions & 3 deletions document/js-api/index.bs
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ urlPrefix: https://webassembly.github.io/spec/core/; spec: WebAssembly; type: df
url: syntax/types.html#syntax-reftype
text: anyref
text: funcref
text: nullref
text: function element; url: exec/runtime.html#syntax-funcelem
text: import component; url: syntax/modules.html#imports
text: external value; url: exec/runtime.html#syntax-externval
Expand Down Expand Up @@ -704,6 +705,7 @@ Immediately after a WebAssembly [=memory.grow=] instruction executes, perform th

<pre class="idl">
enum TableKind {
"nullref",
"anyref",
"anyfunc",
// Note: More values may be added in future iterations,
Expand Down Expand Up @@ -868,6 +870,10 @@ which can be simultaneously referenced by multiple {{Instance}} objects. Each
1. If |s| equals "i64", return [=𝗂𝟨𝟦=].
1. If |s| equals "f32", return [=𝖿𝟥𝟤=].
1. If |s| equals "f64", return [=𝖿𝟨𝟦=].
1. If |s| equals "anyref", return [=anyref=].
1. If |s| equals "funcref", return [=funcref=].
1. If |s| equals "nullref", return [=nullref=].
1. Assert: This step is not reached.
</div>

<div algorithm>
Expand All @@ -876,7 +882,7 @@ which can be simultaneously referenced by multiple {{Instance}} objects. Each
1. If |valuetype| equals [=𝗂𝟨𝟦=], return [=𝗂𝟨𝟦.𝖼𝗈𝗇𝗌𝗍=] 0.
1. If |valuetype| equals [=𝖿𝟥𝟤=], return [=𝖿𝟥𝟤.𝖼𝗈𝗇𝗌𝗍=] 0.
1. If |valuetype| equals [=𝖿𝟨𝟦=], return [=𝖿𝟨𝟦.𝖼𝗈𝗇𝗌𝗍=] 0.
1. Assert: This step is not reached.
1. Else, return [=ref.null=].
</div>

<div algorithm>
Expand Down Expand Up @@ -1063,11 +1069,14 @@ The algorithm <dfn>ToWebAssemblyValue</dfn>(|v|, |type|, |error|) coerces a Java
1. If |type| is [=𝖿𝟨𝟦=],
1. Let |f64| be ? [=ToNumber=](|v|).
1. Return [=𝖿𝟨𝟦.𝖼𝗈𝗇𝗌𝗍=] |f64|.
1. Assert: |type| is a reference type.
1. If |type| is [=anyref=],
1. Return the result of [=allocating a host address=] for |v|.
1. Do nothing.
1. If |type| is [=funcref=],
1. If |v| is not an [=Exported function=] or null, throw |error|.
1. Return the result of [=allocating a host address=] for |v|.
1. If |type| is [=nullref=],
1. If |v| is not null, throw |error|.
1. Return the result of [=allocating a host address=] for |v|.

</div>

Expand Down
2 changes: 1 addition & 1 deletion interpreter/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ align: align=(1|2|4|8|...)
cvtop: trunc | extend | wrap | ...

num_type: i32 | i64 | f32 | f64
ref_type: anyref | funcref
ref_type: anyref | funcref | nullref
val_type: num_type | ref_type
block_type : ( result <val_type>* )*
func_type: ( type <var> )? <param>* <result>*
Expand Down
1 change: 1 addition & 0 deletions interpreter/binary/decode.ml
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ let ref_type s =
match vs7 s with
| -0x10 -> FuncRefType
| -0x11 -> AnyRefType
| -0x12 -> NullRefType
| _ -> error s (pos s - 1) "invalid reference type"

let value_type s =
Expand Down
2 changes: 1 addition & 1 deletion interpreter/binary/encode.ml
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ let encode m =
let ref_type = function
| FuncRefType -> vs7 (-0x10)
| AnyRefType -> vs7 (-0x11)
| NullRefType -> assert false
| NullRefType -> vs7 (-0x12)

let value_type = function
| NumType t -> num_type t
Expand Down
1 change: 1 addition & 0 deletions interpreter/text/lexer.mll
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ rule token = parse

| "anyref" { ANYREF }
| "funcref" { FUNCREF }
| "nullref" { NULLREF }
| (nxx as t) { NUM_TYPE (num_type t) }
| "mut" { MUT }

Expand Down
3 changes: 2 additions & 1 deletion interpreter/text/parser.mly
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ let inline_type_explicit (c : context) x ft at =

%token LPAR RPAR
%token NAT INT FLOAT STRING VAR
%token ANYREF FUNCREF NUM_TYPE MUT
%token ANYREF NULLREF FUNCREF NUM_TYPE MUT
%token UNREACHABLE NOP DROP SELECT
%token BLOCK END IF THEN ELSE LOOP BR BR_IF BR_TABLE
%token CALL CALL_INDIRECT RETURN
Expand Down Expand Up @@ -209,6 +209,7 @@ string_list :
ref_type :
| ANYREF { AnyRefType }
| FUNCREF { FuncRefType }
| NULLREF { NullRefType }

value_type :
| NUM_TYPE { NumType $1 }
Expand Down
4 changes: 1 addition & 3 deletions proposals/reference-types/Overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ Get the most important parts soon!

Summary:

* Add a new type `anyref` that can be used as both a value type and a table element type.
* Add new types `anyref` and `nullref` that can be used as both a value types and a table element types.

* Also allow `funcref` as a value type.

Expand All @@ -49,8 +49,6 @@ Typing extensions:

* Introduce `anyref`, `funcref`, and `nullref` as a new class of *reference types*.
- `reftype ::= anyref | funcref | nullref`
- `nullref` is merely an internal type and is neither expressible in the binary format, nor the text format, nor the JS API.
- Question: should it be?

* Value types (of locals, globals, function parameters and results) can now be either numeric types or reference types.
- `numtype ::= i32 | i64 | f32 | f64`
Expand Down
21 changes: 18 additions & 3 deletions test/core/br_table.wast
Original file line number Diff line number Diff line change
Expand Up @@ -1258,23 +1258,20 @@
)
)
)

(func (export "meet-funcref-2") (param i32) (result anyref)
(block $l1 (result anyref)
(block $l2 (result funcref)
(br_table $l2 $l2 $l1 (table.get 0 (i32.const 0)) (local.get 0))
)
)
)

(func (export "meet-funcref-3") (param i32) (result anyref)
(block $l1 (result anyref)
(block $l2 (result funcref)
(br_table $l2 $l1 $l2 (table.get 0 (i32.const 0)) (local.get 0))
)
)
)

(func (export "meet-funcref-4") (param i32) (result anyref)
(block $l1 (result anyref)
(block $l2 (result funcref)
Expand All @@ -1283,6 +1280,24 @@
)
)

(func (export "meet-nullref") (param i32) (result funcref)
(block $l1 (result funcref)
(block $l2 (result nullref)
(br_table $l1 $l2 $l1 (ref.null) (local.get 0))
)
)
)

(func (export "meet-multi-ref") (param i32) (result anyref)
(block $l1 (result anyref)
(block $l2 (result funcref)
(block $l3 (result nullref)
(br_table $l3 $l2 $l1 (ref.null) (local.get 0))
)
)
)
)

(func (export "meet-bottom")
(block (result f64)
(block (result f32)
Expand Down
90 changes: 75 additions & 15 deletions test/core/linking.wast
Original file line number Diff line number Diff line change
Expand Up @@ -94,29 +94,63 @@


(module $Mref_ex
(global (export "g-const") funcref (ref.null))
(global (export "g-var") (mut funcref) (ref.null))
(global (export "g-const-null") nullref (ref.null))
(global (export "g-var-null") (mut nullref) (ref.null))
(global (export "g-const-func") funcref (ref.null))
(global (export "g-var-func") (mut funcref) (ref.null))
(global (export "g-const-any") anyref (ref.null))
(global (export "g-var-any") (mut anyref) (ref.null))
)
(register "Mref_ex" $Mref_ex)

(module $Mref_im
(global (import "Mref_ex" "g-const") anyref)
(global (import "Mref_ex" "g-const-null") nullref)
(global (import "Mref_ex" "g-const-null") funcref)
(global (import "Mref_ex" "g-const-null") anyref)
(global (import "Mref_ex" "g-const-func") funcref)
(global (import "Mref_ex" "g-const-func") anyref)
(global (import "Mref_ex" "g-const-any") anyref)

(global (import "Mref_ex" "g-var-null") (mut nullref))
(global (import "Mref_ex" "g-var-func") (mut funcref))
(global (import "Mref_ex" "g-var-any") (mut anyref))
)

(assert_unlinkable
(module (global (import "Mref_ex" "g-var") (mut anyref)))
(module (global (import "Mref_ex" "g-const-func") nullref))
"incompatible import type"
)


(module $Mglobal_ex
(func $f)
(global (export "g") anyref (ref.func $f))
(assert_unlinkable
(module (global (import "Mref_ex" "g-const-any") nullref))
"incompatible import type"
)
(assert_unlinkable
(module (global (import "Mref_ex" "g-const-any") funcref))
"incompatible import type"
)
(register "Mglobal_ex" $Mglobal_ex)

(assert_unlinkable
(module (global (import "Mglobal_ex" "g") funcref))
(module (global (import "Mref_ex" "g-var-null") (mut funcref)))
"incompatible import type"
)
(assert_unlinkable
(module (global (import "Mref_ex" "g-var-null") (mut anyref)))
"incompatible import type"
)
(assert_unlinkable
(module (global (import "Mref_ex" "g-var-func") (mut nullref)))
"incompatible import type"
)
(assert_unlinkable
(module (global (import "Mref_ex" "g-var-func") (mut anyref)))
"incompatible import type"
)
(assert_unlinkable
(module (global (import "Mref_ex" "g-var-any") (mut nullref)))
"incompatible import type"
)
(assert_unlinkable
(module (global (import "Mref_ex" "g-var-any") (mut funcref)))
"incompatible import type"
)

Expand Down Expand Up @@ -278,14 +312,40 @@


(module $Mtable_ex
(func $f)
(table $t (export "t") 1 anyref)
(elem (i32.const 0) $f)
(table $t1 (export "t-null") 1 nullref)
(table $t2 (export "t-func") 1 funcref)
(table $t3 (export "t-any") 1 anyref)
)
(register "Mtable_ex" $Mtable_ex)

(module
(table (import "Mtable_ex" "t-null") 1 nullref)
(table (import "Mtable_ex" "t-func") 1 funcref)
(table (import "Mtable_ex" "t-any") 1 anyref)
)

(assert_unlinkable
(module (table (import "Mtable_ex" "t-null") 1 funcref))
"incompatible import type"
)
(assert_unlinkable
(module (table (import "Mtable_ex" "t-null") 1 anyref))
"incompatible import type"
)
(assert_unlinkable
(module (table (import "Mtable_ex" "t-func") 1 nullref))
"incompatible import type"
)
(assert_unlinkable
(module (table (import "Mtable_ex" "t-func") 1 anyref))
"incompatible import type"
)
(assert_unlinkable
(module (table (import "Mtable_ex" "t-any") 1 nullref))
"incompatible import type"
)
(assert_unlinkable
(module (table (import "Mtable_ex" "t") 1 funcref))
(module (table (import "Mtable_ex" "t-any") 1 funcref))
"incompatible import type"
)

Expand Down
13 changes: 13 additions & 0 deletions test/core/ref_is_null.wast
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
(module
(func $f1 (export "nullref") (param $x nullref) (result i32)
(ref.is_null (local.get $x))
)
(func $f2 (export "anyref") (param $x anyref) (result i32)
(ref.is_null (local.get $x))
)
(func $f3 (export "funcref") (param $x funcref) (result i32)
(ref.is_null (local.get $x))
)

(table $t1 2 nullref)
(table $t2 2 anyref)
(table $t3 2 funcref) (elem $t3 (i32.const 1) $dummy)
(func $dummy)
Expand All @@ -14,10 +18,14 @@
(table.set $t2 (i32.const 1) (local.get $r))
)
(func (export "deinit")
(table.set $t1 (i32.const 1) (ref.null))
(table.set $t2 (i32.const 1) (ref.null))
(table.set $t3 (i32.const 1) (ref.null))
)

(func (export "nullref-elem") (param $x i32) (result i32)
(call $f1 (table.get $t1 (local.get $x)))
)
(func (export "anyref-elem") (param $x i32) (result i32)
(call $f2 (table.get $t2 (local.get $x)))
)
Expand All @@ -26,23 +34,28 @@
)
)

(assert_return (invoke "nullref" (ref.null)) (i32.const 1))
(assert_return (invoke "anyref" (ref.null)) (i32.const 1))
(assert_return (invoke "funcref" (ref.null)) (i32.const 1))

(assert_return (invoke "anyref" (ref.host 1)) (i32.const 0))

(invoke "init" (ref.host 0))

(assert_return (invoke "nullref-elem" (i32.const 0)) (i32.const 1))
(assert_return (invoke "anyref-elem" (i32.const 0)) (i32.const 1))
(assert_return (invoke "funcref-elem" (i32.const 0)) (i32.const 1))

(assert_return (invoke "nullref-elem" (i32.const 1)) (i32.const 1))
(assert_return (invoke "anyref-elem" (i32.const 1)) (i32.const 0))
(assert_return (invoke "funcref-elem" (i32.const 1)) (i32.const 0))

(invoke "deinit")

(assert_return (invoke "nullref-elem" (i32.const 0)) (i32.const 1))
(assert_return (invoke "anyref-elem" (i32.const 0)) (i32.const 1))
(assert_return (invoke "funcref-elem" (i32.const 0)) (i32.const 1))

(assert_return (invoke "nullref-elem" (i32.const 0)) (i32.const 1))
(assert_return (invoke "anyref-elem" (i32.const 1)) (i32.const 1))
(assert_return (invoke "funcref-elem" (i32.const 1)) (i32.const 1))
Loading