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

Commit 1d7785d

Browse files
authored
[interpreter] Implement basic reference types and multiple tables (#2)
1 parent 7a8d371 commit 1d7785d

39 files changed

+1216
-442
lines changed

interpreter/README.md

Lines changed: 30 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -172,8 +172,8 @@ float: <num>.<num>?(e|E <num>)? | 0x<hexnum>.<hexnum>?(p|P <num>)?
172172
name: $(<letter> | <digit> | _ | . | + | - | * | / | \ | ^ | ~ | = | < | > | ! | ? | @ | # | $ | % | & | | | : | ' | `)+
173173
string: "(<char> | \n | \t | \\ | \' | \" | \<hex><hex> | \u{<hex>+})*"
174174
175-
value: <int> | <float>
176-
var: <nat> | <name>
175+
num: <int> | <float>
176+
var: <nat> | <name>
177177
178178
unop: ctz | clz | popcnt | ...
179179
binop: add | sub | mul | ...
@@ -183,12 +183,13 @@ offset: offset=<nat>
183183
align: align=(1|2|4|8|...)
184184
cvtop: trunc_s | trunc_u | extend_s | extend_u | ...
185185
186-
val_type: i32 | i64 | f32 | f64
187-
elem_type: anyfunc
186+
num_type: i32 | i64 | f32 | f64
187+
ref_type: anyref | anyfunc | anyeqref
188+
val_type: num_type | ref_type
188189
block_type : ( result <val_type>* )*
189190
func_type: ( type <var> )? <param>* <result>*
190191
global_type: <val_type> | ( mut <val_type> )
191-
table_type: <nat> <nat>? <elem_type>
192+
table_type: <nat> <nat>? <ref_type>
192193
memory_type: <nat> <nat>?
193194
194195
expr:
@@ -223,16 +224,21 @@ op:
223224
tee_local <var>
224225
get_global <var>
225226
set_global <var>
226-
<val_type>.load((8|16|32)_<sign>)? <offset>? <align>?
227-
<val_type>.store(8|16|32)? <offset>? <align>?
227+
get_table <var>
228+
set_table <var>
229+
<num_type>.load((8|16|32)_<sign>)? <offset>? <align>?
230+
<num_type>.store(8|16|32)? <offset>? <align>?
228231
current_memory
229232
grow_memory
230-
<val_type>.const <value>
231-
<val_type>.<unop>
232-
<val_type>.<binop>
233-
<val_type>.<testop>
234-
<val_type>.<relop>
235-
<val_type>.<cvtop>/<val_type>
233+
ref.null
234+
ref.isnull
235+
ref.eq
236+
<num_type>.const <num>
237+
<num_type>.<unop>
238+
<num_type>.<binop>
239+
<num_type>.<testop>
240+
<num_type>.<relop>
241+
<num_type>.<cvtop>/<num_type>
236242
237243
func: ( func <name>? <func_type> <local>* <instr>* )
238244
( func <name>? ( export <string> ) <...> ) ;; = (export <string> (func <N>)) (func <name>? <...>)
@@ -247,7 +253,7 @@ global: ( global <name>? <global_type> <instr>* )
247253
table: ( table <name>? <table_type> )
248254
( table <name>? ( export <string> ) <...> ) ;; = (export <string> (table <N>)) (table <name>? <...>)
249255
( table <name>? ( import <string> <string> ) <table_type> ) ;; = (import <name>? <string> <string> (table <table_type>))
250-
( table <name>? ( export <string> )* <elem_type> ( elem <var>* ) ) ;; = (table <name>? ( export <string> )* <size> <size> <elem_type>) (elem (i32.const 0) <var>*)
256+
( table <name>? ( export <string> )* <ref_type> ( elem <var>* ) ) ;; = (table <name>? ( export <string> )* <size> <size> <ref_type>) (elem (i32.const 0) <var>*)
251257
elem: ( elem <var>? (offset <instr>* ) <var>* )
252258
( elem <var>? <expr> <var>* ) ;; = (elem <var>? (offset <expr>) <var>*)
253259
memory: ( memory <name>? <memory_type> )
@@ -272,9 +278,9 @@ exkind: ( func <var> )
272278
( table <var> )
273279
( memory <var> )
274280
275-
module: ( module <name>? <typedef>* <func>* <import>* <export>* <table>? <memory>? <global>* <elem>* <data>* <start>? )
276-
<typedef>* <func>* <import>* <export>* <table>? <memory>? <global>* <elem>* <data>* <start>? ;; =
277-
( module <typedef>* <func>* <import>* <export>* <table>? <memory>? <global>* <elem>* <data>* <start>? )
281+
module: ( module <name>? <typedef>* <func>* <import>* <export>* <table>* <memory>? <global>* <elem>* <data>* <start>? )
282+
<typedef>* <func>* <import>* <export>* <table>* <memory>? <global>* <elem>* <data>* <start>? ;; =
283+
( module <typedef>* <func>* <import>* <export>* <table>* <memory>? <global>* <elem>* <data>* <start>? )
278284
```
279285

280286
Here, productions marked with respective comments are abbreviation forms for equivalent expansions (see the explanation of the AST below).
@@ -320,11 +326,16 @@ module:
320326
( module <name>? quote <string>* ) ;; module quoted in text (may be malformed)
321327
322328
action:
323-
( invoke <name>? <string> <expr>* ) ;; invoke function export
329+
( invoke <name>? <string> <const>* ) ;; invoke function export
324330
( get <name>? <string> ) ;; get global export
325331
332+
const:
333+
( <num_type>.const <num> ) ;; number value
334+
( ref.null ) ;; null reference
335+
( ref.host <nat> ) ;; host reference
336+
326337
assertion:
327-
( assert_return <action> <expr>* ) ;; assert action has expected results
338+
( assert_return <action> <const>* ) ;; assert action has expected results
328339
( assert_return_canonical_nan <action> ) ;; assert action results in NaN in a canonical form
329340
( assert_return_arithmetic_nan <action> ) ;; assert action results in NaN with 1 in MSB of fraction field
330341
( assert_trap <action> <failure> ) ;; assert action traps with given failure string

interpreter/binary/decode.ml

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -131,18 +131,25 @@ let sized f s =
131131

132132
open Types
133133

134-
let value_type s =
134+
let num_type s =
135135
match vs7 s with
136136
| -0x01 -> I32Type
137137
| -0x02 -> I64Type
138138
| -0x03 -> F32Type
139139
| -0x04 -> F64Type
140-
| _ -> error s (pos s - 1) "invalid value type"
140+
| _ -> error s (pos s - 1) "invalid number type"
141141

142-
let elem_type s =
142+
let ref_type s =
143143
match vs7 s with
144144
| -0x10 -> AnyFuncType
145-
| _ -> error s (pos s - 1) "invalid element type"
145+
| -0x11 -> AnyRefType
146+
| -0x12 -> AnyEqRefType
147+
| _ -> error s (pos s - 1) "invalid reference type"
148+
149+
let value_type s =
150+
match peek s with
151+
| Some n when n > 0x70 -> NumType (num_type s)
152+
| _ -> RefType (ref_type s)
146153

147154
let stack_type s =
148155
match peek s with
@@ -164,7 +171,7 @@ let limits vu s =
164171
{min; max}
165172

166173
let table_type s =
167-
let t = elem_type s in
174+
let t = ref_type s in
168175
let lim = limits vu32 s in
169176
TableType (lim, t)
170177

@@ -243,9 +250,9 @@ let rec instr s =
243250

244251
| 0x10 -> call (at var s)
245252
| 0x11 ->
253+
let y = at var s in
246254
let x = at var s in
247-
expect 0x00 s "zero flag expected";
248-
call_indirect x
255+
call_indirect x y
249256

250257
| 0x12 | 0x13 | 0x14 | 0x15 | 0x16 | 0x17 | 0x18 | 0x19 as b -> illegal s pos b
251258

@@ -259,8 +266,10 @@ let rec instr s =
259266
| 0x22 -> tee_local (at var s)
260267
| 0x23 -> get_global (at var s)
261268
| 0x24 -> set_global (at var s)
269+
| 0x25 -> get_table (at var s)
270+
| 0x26 -> set_table (at var s)
262271

263-
| 0x25 | 0x26 | 0x27 as b -> illegal s pos b
272+
| 0x27 as b -> illegal s pos b
264273

265274
| 0x28 -> let a, o = memop s in i32_load a o
266275
| 0x29 -> let a, o = memop s in i64_load a o
@@ -432,6 +441,14 @@ let rec instr s =
432441
| 0xbe -> f32_reinterpret_i32
433442
| 0xbf -> f64_reinterpret_i64
434443

444+
| 0xc0 | 0xc1 | 0xc2 | 0xc3 | 0xc4 | 0xc5 | 0xc6 | 0xc7
445+
| 0xc8 | 0xc9 | 0xca | 0xcb | 0xcc | 0xcd | 0xce | 0xcf as b -> illegal s pos b
446+
447+
(* TODO: Allocate more adequate opcodes *)
448+
| 0xd0 -> ref_null
449+
| 0xd1 -> ref_isnull
450+
| 0xd2 -> ref_eq
451+
435452
| b -> illegal s pos b
436453

437454
and instr_block s = List.rev (instr_block' s [])

interpreter/binary/encode.ml

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -90,14 +90,21 @@ let encode m =
9090

9191
open Types
9292

93-
let value_type = function
93+
let num_type = function
9494
| I32Type -> vs7 (-0x01)
9595
| I64Type -> vs7 (-0x02)
9696
| F32Type -> vs7 (-0x03)
9797
| F64Type -> vs7 (-0x04)
9898

99-
let elem_type = function
99+
let ref_type = function
100100
| AnyFuncType -> vs7 (-0x10)
101+
| AnyRefType -> vs7 (-0x11)
102+
| AnyEqRefType -> vs7 (-0x12)
103+
| NullRefType -> assert false
104+
105+
let value_type = function
106+
| NumType t -> num_type t
107+
| RefType t -> ref_type t
101108

102109
let stack_type = function
103110
| [] -> vs7 (-0x40)
@@ -107,13 +114,14 @@ let encode m =
107114
"cannot encode stack type with arity > 1 (yet)"
108115

109116
let func_type = function
110-
| FuncType (ins, out) -> vs7 (-0x20); vec value_type ins; vec value_type out
117+
| FuncType (ins, out) ->
118+
vs7 (-0x20); vec value_type ins; vec value_type out
111119

112120
let limits vu {min; max} =
113121
bool (max <> None); vu min; opt vu max
114122

115123
let table_type = function
116-
| TableType (lim, t) -> elem_type t; limits vu32 lim
124+
| TableType (lim, t) -> ref_type t; limits vu32 lim
117125

118126
let memory_type = function
119127
| MemoryType lim -> limits vu32 lim
@@ -156,7 +164,7 @@ let encode m =
156164
| BrTable (xs, x) -> op 0x0e; vec var xs; var x
157165
| Return -> op 0x0f
158166
| Call x -> op 0x10; var x
159-
| CallIndirect x -> op 0x11; var x; u8 0x00
167+
| CallIndirect (x, y) -> op 0x11; var y; var x
160168

161169
| Drop -> op 0x1a
162170
| Select -> op 0x1b
@@ -166,6 +174,8 @@ let encode m =
166174
| TeeLocal x -> op 0x22; var x
167175
| GetGlobal x -> op 0x23; var x
168176
| SetGlobal x -> op 0x24; var x
177+
| GetTable x -> op 0x25; var x
178+
| SetTable x -> op 0x26; var x
169179

170180
| Load ({ty = I32Type; sz = None; _} as mo) -> op 0x28; memop mo
171181
| Load ({ty = I64Type; sz = None; _} as mo) -> op 0x29; memop mo
@@ -363,6 +373,11 @@ let encode m =
363373
| Convert (F64 F64Op.DemoteF64) -> assert false
364374
| Convert (F64 F64Op.ReinterpretInt) -> op 0xbf
365375

376+
(* TODO: Allocate more adequate opcodes *)
377+
| Null -> op 0xd0
378+
| IsNull -> op 0xd1
379+
| Same -> op 0xd2
380+
366381
let const c =
367382
list instr c.it; end_ ()
368383

0 commit comments

Comments
 (0)