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

Commit d4bc208

Browse files
authored
[spec/interpreter/test] Allow nullref type externally (#66)
1 parent 303c942 commit d4bc208

File tree

16 files changed

+142
-35
lines changed

16 files changed

+142
-35
lines changed

document/core/appendix/index-types.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ Category Constructor
1515
(reserved) :math:`\hex{7B}` .. :math:`\hex{71}`
1616
:ref:`Reference type <syntax-reftype>` |FUNCREF| :math:`\hex{70}` (-16 as |Bs7|)
1717
:ref:`Reference type <syntax-reftype>` |ANYREF| :math:`\hex{6F}` (-17 as |Bs7|)
18-
(reserved) :math:`\hex{6E}` .. :math:`\hex{61}`
18+
:ref:`Reference type <syntax-reftype>` |NULLREF| :math:`\hex{6E}` (-18 as |Bs7|)
19+
(reserved) :math:`\hex{6D}` .. :math:`\hex{61}`
1920
:ref:`Function type <syntax-functype>` :math:`[\valtype^\ast] \to [\valtype^\ast]` :math:`\hex{60}` (-32 as |Bs7|)
2021
(reserved) :math:`\hex{5F}` .. :math:`\hex{41}`
2122
:ref:`Result type <syntax-resulttype>` :math:`[\epsilon]` :math:`\hex{40}` (-64 as |Bs7|)

document/core/binary/types.rst

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,10 @@ Reference Types
4242
\begin{array}{llclll@{\qquad\qquad}l}
4343
\production{reference type} & \Breftype &::=&
4444
\hex{70} &\Rightarrow& \FUNCREF \\ &&|&
45-
\hex{6F} &\Rightarrow& \ANYREF \\
45+
\hex{6F} &\Rightarrow& \ANYREF \\ &&|&
46+
\hex{6E} &\Rightarrow& \NULLREF \\
4647
\end{array}
4748
48-
.. note::
49-
The type :math:`\NULLREF` cannot occur in a module.
50-
5149
5250
.. index:: value type, number type, reference type
5351
pair: binary format; value type

document/core/syntax/types.rst

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,6 @@ The type |FUNCREF| denotes the infinite union of all references to :ref:`functio
6363

6464
The type |NULLREF| only contains a single value: the :ref:`null <syntax-ref.null>` reference.
6565
It is a :ref:`subtype <match-reftype>` of all other reference types.
66-
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;
67-
it only occurs during :ref:`validation <valid>`.
6866

6967
.. note::
7068
Future versions of WebAssembly may include reference types that do not include null and hence are not supertypes of |NULLREF|.

document/core/text/types.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ Reference Types
3333
\begin{array}{llcll@{\qquad\qquad}l}
3434
\production{reference type} & \Treftype &::=&
3535
\text{anyref} &\Rightarrow& \ANYREF \\ &&|&
36-
\text{funcref} &\Rightarrow& \FUNCREF \\
36+
\text{funcref} &\Rightarrow& \FUNCREF \\ &&|&
37+
\text{nullref} &\Rightarrow& \NULLREF \\
3738
\end{array}
3839
3940

document/js-api/index.bs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ urlPrefix: https://webassembly.github.io/spec/core/; spec: WebAssembly; type: df
152152
url: syntax/types.html#syntax-reftype
153153
text: anyref
154154
text: funcref
155+
text: nullref
155156
text: function element; url: exec/runtime.html#syntax-funcelem
156157
text: import component; url: syntax/modules.html#imports
157158
text: external value; url: exec/runtime.html#syntax-externval
@@ -704,6 +705,7 @@ Immediately after a WebAssembly [=memory.grow=] instruction executes, perform th
704705

705706
<pre class="idl">
706707
enum TableKind {
708+
"nullref",
707709
"anyref",
708710
"anyfunc",
709711
// Note: More values may be added in future iterations,
@@ -868,6 +870,10 @@ which can be simultaneously referenced by multiple {{Instance}} objects. Each
868870
1. If |s| equals "i64", return [=𝗂𝟨𝟦=].
869871
1. If |s| equals "f32", return [=𝖿𝟥𝟤=].
870872
1. If |s| equals "f64", return [=𝖿𝟨𝟦=].
873+
1. If |s| equals "anyref", return [=anyref=].
874+
1. If |s| equals "funcref", return [=funcref=].
875+
1. If |s| equals "nullref", return [=nullref=].
876+
1. Assert: This step is not reached.
871877
</div>
872878

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

882888
<div algorithm>
@@ -1063,11 +1069,14 @@ The algorithm <dfn>ToWebAssemblyValue</dfn>(|v|, |type|, |error|) coerces a Java
10631069
1. If |type| is [=𝖿𝟨𝟦=],
10641070
1. Let |f64| be ? [=ToNumber=](|v|).
10651071
1. Return [=𝖿𝟨𝟦.𝖼𝗈𝗇𝗌𝗍=] |f64|.
1072+
1. Assert: |type| is a reference type.
10661073
1. If |type| is [=anyref=],
1067-
1. Return the result of [=allocating a host address=] for |v|.
1074+
1. Do nothing.
10681075
1. If |type| is [=funcref=],
10691076
1. If |v| is not an [=Exported function=] or null, throw |error|.
1070-
1. Return the result of [=allocating a host address=] for |v|.
1077+
1. If |type| is [=nullref=],
1078+
1. If |v| is not null, throw |error|.
1079+
1. Return the result of [=allocating a host address=] for |v|.
10711080

10721081
</div>
10731082

interpreter/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ align: align=(1|2|4|8|...)
184184
cvtop: trunc | extend | wrap | ...
185185
186186
num_type: i32 | i64 | f32 | f64
187-
ref_type: anyref | funcref
187+
ref_type: anyref | funcref | nullref
188188
val_type: num_type | ref_type
189189
block_type : ( result <val_type>* )*
190190
func_type: ( type <var> )? <param>* <result>*

interpreter/binary/decode.ml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@ let ref_type s =
145145
match vs7 s with
146146
| -0x10 -> FuncRefType
147147
| -0x11 -> AnyRefType
148+
| -0x12 -> NullRefType
148149
| _ -> error s (pos s - 1) "invalid reference type"
149150

150151
let value_type s =

interpreter/binary/encode.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ let encode m =
9999
let ref_type = function
100100
| FuncRefType -> vs7 (-0x10)
101101
| AnyRefType -> vs7 (-0x11)
102-
| NullRefType -> assert false
102+
| NullRefType -> vs7 (-0x12)
103103

104104
let value_type = function
105105
| NumType t -> num_type t

interpreter/text/lexer.mll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,7 @@ rule token = parse
162162

163163
| "anyref" { ANYREF }
164164
| "funcref" { FUNCREF }
165+
| "nullref" { NULLREF }
165166
| (nxx as t) { NUM_TYPE (num_type t) }
166167
| "mut" { MUT }
167168

interpreter/text/parser.mly

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ let inline_type_explicit (c : context) x ft at =
147147

148148
%token LPAR RPAR
149149
%token NAT INT FLOAT STRING VAR
150-
%token ANYREF FUNCREF NUM_TYPE MUT
150+
%token ANYREF NULLREF FUNCREF NUM_TYPE MUT
151151
%token UNREACHABLE NOP DROP SELECT
152152
%token BLOCK END IF THEN ELSE LOOP BR BR_IF BR_TABLE
153153
%token CALL CALL_INDIRECT RETURN
@@ -209,6 +209,7 @@ string_list :
209209
ref_type :
210210
| ANYREF { AnyRefType }
211211
| FUNCREF { FuncRefType }
212+
| NULLREF { NullRefType }
212213

213214
value_type :
214215
| NUM_TYPE { NumType $1 }

proposals/reference-types/Overview.md

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ Get the most important parts soon!
2626

2727
Summary:
2828

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

3131
* Also allow `funcref` as a value type.
3232

@@ -49,8 +49,6 @@ Typing extensions:
4949

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

5553
* Value types (of locals, globals, function parameters and results) can now be either numeric types or reference types.
5654
- `numtype ::= i32 | i64 | f32 | f64`

test/core/br_table.wast

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1258,23 +1258,20 @@
12581258
)
12591259
)
12601260
)
1261-
12621261
(func (export "meet-funcref-2") (param i32) (result anyref)
12631262
(block $l1 (result anyref)
12641263
(block $l2 (result funcref)
12651264
(br_table $l2 $l2 $l1 (table.get 0 (i32.const 0)) (local.get 0))
12661265
)
12671266
)
12681267
)
1269-
12701268
(func (export "meet-funcref-3") (param i32) (result anyref)
12711269
(block $l1 (result anyref)
12721270
(block $l2 (result funcref)
12731271
(br_table $l2 $l1 $l2 (table.get 0 (i32.const 0)) (local.get 0))
12741272
)
12751273
)
12761274
)
1277-
12781275
(func (export "meet-funcref-4") (param i32) (result anyref)
12791276
(block $l1 (result anyref)
12801277
(block $l2 (result funcref)
@@ -1283,6 +1280,24 @@
12831280
)
12841281
)
12851282

1283+
(func (export "meet-nullref") (param i32) (result funcref)
1284+
(block $l1 (result funcref)
1285+
(block $l2 (result nullref)
1286+
(br_table $l1 $l2 $l1 (ref.null) (local.get 0))
1287+
)
1288+
)
1289+
)
1290+
1291+
(func (export "meet-multi-ref") (param i32) (result anyref)
1292+
(block $l1 (result anyref)
1293+
(block $l2 (result funcref)
1294+
(block $l3 (result nullref)
1295+
(br_table $l3 $l2 $l1 (ref.null) (local.get 0))
1296+
)
1297+
)
1298+
)
1299+
)
1300+
12861301
(func (export "meet-bottom")
12871302
(block (result f64)
12881303
(block (result f32)

test/core/linking.wast

Lines changed: 75 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -94,29 +94,63 @@
9494

9595

9696
(module $Mref_ex
97-
(global (export "g-const") funcref (ref.null))
98-
(global (export "g-var") (mut funcref) (ref.null))
97+
(global (export "g-const-null") nullref (ref.null))
98+
(global (export "g-var-null") (mut nullref) (ref.null))
99+
(global (export "g-const-func") funcref (ref.null))
100+
(global (export "g-var-func") (mut funcref) (ref.null))
101+
(global (export "g-const-any") anyref (ref.null))
102+
(global (export "g-var-any") (mut anyref) (ref.null))
99103
)
100104
(register "Mref_ex" $Mref_ex)
101105

102106
(module $Mref_im
103-
(global (import "Mref_ex" "g-const") anyref)
107+
(global (import "Mref_ex" "g-const-null") nullref)
108+
(global (import "Mref_ex" "g-const-null") funcref)
109+
(global (import "Mref_ex" "g-const-null") anyref)
110+
(global (import "Mref_ex" "g-const-func") funcref)
111+
(global (import "Mref_ex" "g-const-func") anyref)
112+
(global (import "Mref_ex" "g-const-any") anyref)
113+
114+
(global (import "Mref_ex" "g-var-null") (mut nullref))
115+
(global (import "Mref_ex" "g-var-func") (mut funcref))
116+
(global (import "Mref_ex" "g-var-any") (mut anyref))
104117
)
105118

106119
(assert_unlinkable
107-
(module (global (import "Mref_ex" "g-var") (mut anyref)))
120+
(module (global (import "Mref_ex" "g-const-func") nullref))
108121
"incompatible import type"
109122
)
110-
111-
112-
(module $Mglobal_ex
113-
(func $f)
114-
(global (export "g") anyref (ref.func $f))
123+
(assert_unlinkable
124+
(module (global (import "Mref_ex" "g-const-any") nullref))
125+
"incompatible import type"
126+
)
127+
(assert_unlinkable
128+
(module (global (import "Mref_ex" "g-const-any") funcref))
129+
"incompatible import type"
115130
)
116-
(register "Mglobal_ex" $Mglobal_ex)
117131

118132
(assert_unlinkable
119-
(module (global (import "Mglobal_ex" "g") funcref))
133+
(module (global (import "Mref_ex" "g-var-null") (mut funcref)))
134+
"incompatible import type"
135+
)
136+
(assert_unlinkable
137+
(module (global (import "Mref_ex" "g-var-null") (mut anyref)))
138+
"incompatible import type"
139+
)
140+
(assert_unlinkable
141+
(module (global (import "Mref_ex" "g-var-func") (mut nullref)))
142+
"incompatible import type"
143+
)
144+
(assert_unlinkable
145+
(module (global (import "Mref_ex" "g-var-func") (mut anyref)))
146+
"incompatible import type"
147+
)
148+
(assert_unlinkable
149+
(module (global (import "Mref_ex" "g-var-any") (mut nullref)))
150+
"incompatible import type"
151+
)
152+
(assert_unlinkable
153+
(module (global (import "Mref_ex" "g-var-any") (mut funcref)))
120154
"incompatible import type"
121155
)
122156

@@ -278,14 +312,40 @@
278312

279313

280314
(module $Mtable_ex
281-
(func $f)
282-
(table $t (export "t") 1 anyref)
283-
(elem (i32.const 0) $f)
315+
(table $t1 (export "t-null") 1 nullref)
316+
(table $t2 (export "t-func") 1 funcref)
317+
(table $t3 (export "t-any") 1 anyref)
284318
)
285319
(register "Mtable_ex" $Mtable_ex)
286320

321+
(module
322+
(table (import "Mtable_ex" "t-null") 1 nullref)
323+
(table (import "Mtable_ex" "t-func") 1 funcref)
324+
(table (import "Mtable_ex" "t-any") 1 anyref)
325+
)
326+
327+
(assert_unlinkable
328+
(module (table (import "Mtable_ex" "t-null") 1 funcref))
329+
"incompatible import type"
330+
)
331+
(assert_unlinkable
332+
(module (table (import "Mtable_ex" "t-null") 1 anyref))
333+
"incompatible import type"
334+
)
335+
(assert_unlinkable
336+
(module (table (import "Mtable_ex" "t-func") 1 nullref))
337+
"incompatible import type"
338+
)
339+
(assert_unlinkable
340+
(module (table (import "Mtable_ex" "t-func") 1 anyref))
341+
"incompatible import type"
342+
)
343+
(assert_unlinkable
344+
(module (table (import "Mtable_ex" "t-any") 1 nullref))
345+
"incompatible import type"
346+
)
287347
(assert_unlinkable
288-
(module (table (import "Mtable_ex" "t") 1 funcref))
348+
(module (table (import "Mtable_ex" "t-any") 1 funcref))
289349
"incompatible import type"
290350
)
291351

test/core/ref_is_null.wast

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
(module
2+
(func $f1 (export "nullref") (param $x nullref) (result i32)
3+
(ref.is_null (local.get $x))
4+
)
25
(func $f2 (export "anyref") (param $x anyref) (result i32)
36
(ref.is_null (local.get $x))
47
)
58
(func $f3 (export "funcref") (param $x funcref) (result i32)
69
(ref.is_null (local.get $x))
710
)
811

12+
(table $t1 2 nullref)
913
(table $t2 2 anyref)
1014
(table $t3 2 funcref) (elem $t3 (i32.const 1) $dummy)
1115
(func $dummy)
@@ -14,10 +18,14 @@
1418
(table.set $t2 (i32.const 1) (local.get $r))
1519
)
1620
(func (export "deinit")
21+
(table.set $t1 (i32.const 1) (ref.null))
1722
(table.set $t2 (i32.const 1) (ref.null))
1823
(table.set $t3 (i32.const 1) (ref.null))
1924
)
2025

26+
(func (export "nullref-elem") (param $x i32) (result i32)
27+
(call $f1 (table.get $t1 (local.get $x)))
28+
)
2129
(func (export "anyref-elem") (param $x i32) (result i32)
2230
(call $f2 (table.get $t2 (local.get $x)))
2331
)
@@ -26,23 +34,28 @@
2634
)
2735
)
2836

37+
(assert_return (invoke "nullref" (ref.null)) (i32.const 1))
2938
(assert_return (invoke "anyref" (ref.null)) (i32.const 1))
3039
(assert_return (invoke "funcref" (ref.null)) (i32.const 1))
3140

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

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

45+
(assert_return (invoke "nullref-elem" (i32.const 0)) (i32.const 1))
3646
(assert_return (invoke "anyref-elem" (i32.const 0)) (i32.const 1))
3747
(assert_return (invoke "funcref-elem" (i32.const 0)) (i32.const 1))
3848

49+
(assert_return (invoke "nullref-elem" (i32.const 1)) (i32.const 1))
3950
(assert_return (invoke "anyref-elem" (i32.const 1)) (i32.const 0))
4051
(assert_return (invoke "funcref-elem" (i32.const 1)) (i32.const 0))
4152

4253
(invoke "deinit")
4354

55+
(assert_return (invoke "nullref-elem" (i32.const 0)) (i32.const 1))
4456
(assert_return (invoke "anyref-elem" (i32.const 0)) (i32.const 1))
4557
(assert_return (invoke "funcref-elem" (i32.const 0)) (i32.const 1))
4658

59+
(assert_return (invoke "nullref-elem" (i32.const 0)) (i32.const 1))
4760
(assert_return (invoke "anyref-elem" (i32.const 1)) (i32.const 1))
4861
(assert_return (invoke "funcref-elem" (i32.const 1)) (i32.const 1))

0 commit comments

Comments
 (0)