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

Commit

Permalink
[spec/interpreter/test] Allow nullref type externally (#66)
Browse files Browse the repository at this point in the history
  • Loading branch information
rossberg authored Dec 13, 2019
1 parent 303c942 commit d4bc208
Show file tree
Hide file tree
Showing 16 changed files with 142 additions and 35 deletions.
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

0 comments on commit d4bc208

Please sign in to comment.