Skip to content
This repository was archived by the owner on Apr 25, 2025. It is now read-only.

Commit c69a117

Browse files
authored
New element section encoding in the interpreter (#109)
1 parent aadc467 commit c69a117

File tree

16 files changed

+264
-131
lines changed

16 files changed

+264
-131
lines changed

document/core/syntax/modules.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,7 @@ The |MELEM| component of a module defines a vector of element segments. Each act
261261
.. math::
262262
\begin{array}{llll}
263263
\production{element segment} & \elem &::=&
264-
\{ \ETABLE~\tableidx, \EOFFSET~\expr, \EINIT~\vec(\elemexpr) \} \\&&|&
264+
\{ \ETABLE~\tableidx, \EOFFSET~\expr, \ETYPE~\elemtype, \EINIT~\vec(\elemexpr) \} \\&&|&
265265
\{ \ETYPE~\elemtype, \EINIT~\vec(\elemexpr) \} \\
266266
\production{elemexpr} & \elemexpr &::=&
267267
\REFNULL~\END \\&&|&

document/core/text/modules.rst

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,16 @@ An :ref:`element segment <text-elem>` can be given inline with a table definitio
293293
(\iff \Tid' = \Tid^? \neq \epsilon \vee \Tid' \idfresh) \\
294294
\end{array}
295295
296+
.. math::
297+
\begin{array}{llclll}
298+
\production{module field} &
299+
\text{(}~\text{table}~~\Tid^?~~\Telemtype~~\text{(}~\text{elem}~~x^n{:}\Tvec(\Texpr)~\text{)}~~\text{)} \quad\equiv \\ & \qquad
300+
\text{(}~\text{table}~~\Tid'~~n~~n~~\Telemtype~\text{)}~~
301+
\text{(}~\text{elem}~~\Tid'~~\text{(}~\text{i32.const}~~\text{0}~\text{)}~~\Tvec(\Texpr)~\text{)}
302+
\\ & \qquad\qquad
303+
(\iff \Tid' = \Tid^? \neq \epsilon \vee \Tid' \idfresh) \\
304+
\end{array}
305+
296306
Tables can be defined as :ref:`imports <text-import>` or :ref:`exports <text-export>` inline:
297307

298308
.. math::
@@ -483,10 +493,13 @@ Element segments allow for an optional :ref:`table index <text-tableidx>` to ide
483493
.. math::
484494
\begin{array}{llclll}
485495
\production{element segment} & \Telem_I &::=&
486-
\text{(}~\text{elem}~~\Tid^?~~x{:}\Ttableidx_I~~\text{(}~\text{offset}~~e{:}\Texpr_I~\text{)}~~y^\ast{:}\Tvec(\Tfuncidx_I)~\text{)} \\ &&& \qquad
487-
\Rightarrow\quad \{ \ETABLE~x, \EOFFSET~e, \EINIT~y^\ast \} \\ &&|&
488-
\text{(}~\text{elem}~~\Tid^?~~et{:}\Telemtype~~y^\ast{:}\Tvec(\Tfuncidx_I)~\text{)} \\ &&& \qquad
489-
\Rightarrow\quad \{ \ETYPE~et, \EINIT~y^\ast \} \\
496+
\text{(}~\text{elem}~~\Tid^?~~\text{(}~\text{table}~~x{:}\Ttableidx_I ~\text{)}~~\text{(}~\text{offset}~~e{:}\Texpr_I~\text{)}~~(et, y^\ast){:}\Telemlist~\text{)} \\ &&& \qquad
497+
\Rightarrow\quad \{ \ETABLE~x, \EOFFSET~e, \ETYPE~et, \EINIT~y^\ast \} \\ &&|&
498+
\text{(}~\text{elem}~~\Tid^?~~(et, y^\ast){:}\Telemlist~\text{)} \\ &&& \qquad
499+
\Rightarrow\quad \{\ETYPE~et,\EINIT~y^\ast \} \\
500+
\production{elemlist} & \Telemlist &::=&
501+
\text{func}~~y^\ast{:}\Tvec(\Tfuncidx_I) \qquad\Rightarrow\quad ( \ETYPE~\FUNCREF, \EINIT~y^\ast ) \\ &&|&
502+
et{:}\Telemtype~~y^\ast{:}\Tvec(\Texpr_I) \qquad\Rightarrow\quad ( \ETYPE~et, \EINIT~y^\ast ) \\
490503
\end{array}
491504
492505
.. note::
@@ -506,14 +519,14 @@ As an abbreviation, a single instruction may occur in place of the offset:
506519
\text{(}~\text{offset}~~\Tinstr~\text{)}
507520
\end{array}
508521
509-
Also, the table index can be omitted, defaulting to :math:`\T{0}`.
522+
Also, the table index can be omitted, defaulting to :math:`\T{0}`. If the table index is omitted, also the :math:`\text{func}` keyword can be omitted.
510523

511524
.. math::
512525
\begin{array}{llclll}
513526
\production{element segment} &
514527
\text{(}~\text{elem}~~\text{(}~\text{offset}~~\Texpr_I~\text{)}~~\dots~\text{)}
515528
&\equiv&
516-
\text{(}~\text{elem}~~0~~\text{(}~\text{offset}~~\Texpr_I~\text{)}~~\dots~\text{)}
529+
\text{(}~\text{elem}~~\text{(}~\text{table}~~\text{0}~\text{)}~~\text{(}~\text{offset}~~\Texpr_I~\text{)}~~\dots~\text{)}
517530
\end{array}
518531
519532
As another abbreviation, element segments may also be specified inline with :ref:`table <text-table>` definitions; see the respective section.

document/core/util/macros.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -702,6 +702,7 @@
702702
.. |Tmemarg| mathdef:: \xref{text/instructions}{text-memarg}{\T{memarg}}
703703
.. |Talign| mathdef:: \xref{text/instructions}{text-memarg}{\T{align}}
704704
.. |Toffset| mathdef:: \xref{text/instructions}{text-memarg}{\T{offset}}
705+
.. |Telemlist| mathdef:: \xref{text/instructions}{text-memarg}{\T{elemlist}}
705706

706707
.. |Tlabel| mathdef:: \xref{text/instructions}{text-label}{\T{label}}
707708
.. |Tinstr| mathdef:: \xref{text/instructions}{text-instr}{\T{instr}}

document/core/valid/modules.rst

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -147,8 +147,8 @@ Element Segments
147147

148148
Element segments :math:`\elem` are classified by :ref:`segment types <syntax-segtype>`.
149149

150-
:math:`\{ \ETABLE~x, \EOFFSET~\expr, \EINIT~e^\ast \}`
151-
......................................................
150+
:math:`\{ \ETABLE~x, \EOFFSET~\expr, \ETYPE~et, \EINIT~e^\ast \}`
151+
.................................................................
152152

153153
* The table :math:`C.\CTABLES[x]` must be defined in the context.
154154

@@ -160,6 +160,8 @@ Element segments :math:`\elem` are classified by :ref:`segment types <syntax-seg
160160

161161
* The expression :math:`\expr` must be :ref:`constant <valid-constant>`.
162162

163+
* The :ref:`element type <syntax-elemtype>` :math:`et` must be |FUNCREF|.
164+
163165
* For each :math:`e_i` in :math:`e^\ast`,
164166

165167
* The element expression :math:`e_i` must be :ref:`valid <valid-elemexpr>`.
@@ -175,15 +177,19 @@ Element segments :math:`\elem` are classified by :ref:`segment types <syntax-seg
175177
\qquad
176178
C \vdashexprconst \expr \const
177179
\qquad
180+
et = \FUNCREF
181+
\qquad
178182
(C \vdashelemexpr e \ok)^\ast
179183
}{
180-
C \vdashelem \{ \ETABLE~x, \EOFFSET~\expr, \EINIT~e^\ast \} : \SACTIVE
184+
C \vdashelem \{ \ETABLE~x, \EOFFSET~\expr, \ETYPE~et, \EINIT~e^\ast \} : \SACTIVE
181185
}
182186
183187
184188
:math:`\{ \ETYPE~et, \EINIT~e^\ast \}`
185189
......................................
186190

191+
* The :ref:`element type <syntax-elemtype>` :math:`et` must be |FUNCREF|.
192+
187193
* For each :math:`e_i` in :math:`e^\ast`,
188194

189195
* The element expression :math:`e_i` must be :ref:`valid <valid-elemexpr>`.
@@ -193,6 +199,8 @@ Element segments :math:`\elem` are classified by :ref:`segment types <syntax-seg
193199

194200
.. math::
195201
\frac{
202+
et = \FUNCREF
203+
\qquad
196204
(C \vdashelemexpr e \ok)^\ast
197205
}{
198206
C \vdashelem \{ \ETYPE~et, \EINIT~e^\ast \} : \SPASSIVE

interpreter/binary/decode.ml

Lines changed: 58 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -535,6 +535,11 @@ let func_section s =
535535

536536
(* Table section *)
537537

538+
let elem_kind s =
539+
match vs7 s with
540+
| 0x00 -> FuncRefType
541+
| _ -> error s (pos s - 1) "invalid elem kind"
542+
538543
let table s =
539544
let ttype = table_type s in
540545
{ttype}
@@ -613,27 +618,10 @@ let code_section s =
613618

614619
(* Element section *)
615620

616-
let segment active passive s =
617-
match vu32 s with
618-
| 0l ->
619-
let index = Source.(0l @@ Source.no_region) in
620-
let offset = const s in
621-
let init = active s in
622-
Active {index; offset; init}
623-
| 1l ->
624-
let etype, data = passive s in
625-
Passive {etype; data}
626-
| 2l ->
627-
let index = at var s in
628-
let offset = const s in
629-
let init = active s in
630-
Active {index; offset; init}
631-
| _ -> error s (pos s - 1) "invalid segment kind"
632-
633-
let active_elem s =
621+
let elem_index s =
634622
ref_func (at var s)
635623

636-
let passive_elem s =
624+
let elem_expr s =
637625
match u8 s with
638626
| 0xd0 -> end_ s; ref_null
639627
| 0xd2 ->
@@ -642,16 +630,45 @@ let passive_elem s =
642630
ref_func x
643631
| _ -> error s (pos s - 1) "invalid elem"
644632

645-
let active_elem_segment s =
646-
vec (at active_elem) s
633+
let elem_indices s =
634+
vec (at elem_index) s
647635

648-
let passive_elem_segment s =
649-
let etype = elem_type s in
650-
let init = vec (at passive_elem) s in
651-
etype, init
636+
let elem_refs s =
637+
vec (at elem_expr) s
652638

653639
let table_segment s =
654-
segment active_elem_segment passive_elem_segment s
640+
match vu32 s with
641+
| 0l ->
642+
let index = Source.(0l @@ Source.no_region) in
643+
let offset = const s in
644+
let init = elem_indices s in
645+
ActiveElem {index; offset; etype = FuncRefType; init}
646+
| 1l ->
647+
let etype = elem_kind s in
648+
let data = elem_indices s in
649+
PassiveElem {etype; data}
650+
| 2l ->
651+
let index = at var s in
652+
let offset = const s in
653+
let etype = elem_kind s in
654+
let init = elem_indices s in
655+
ActiveElem {index; offset; etype; init}
656+
| 4l ->
657+
let index = Source.(0l @@ Source.no_region) in
658+
let offset = const s in
659+
let init = elem_refs s in
660+
ActiveElem {index; offset; etype = FuncRefType; init}
661+
| 5l ->
662+
let etype = elem_type s in
663+
let data = elem_refs s in
664+
PassiveElem {etype; data}
665+
| 6l ->
666+
let index = at var s in
667+
let offset = const s in
668+
let etype = elem_type s in
669+
let init = elem_refs s in
670+
ActiveElem {index; offset; etype; init}
671+
| _ -> error s (pos s - 1) "invalid table segment kind"
655672

656673
let elem_section s =
657674
section `ElemSection (vec (at table_segment)) [] s
@@ -660,7 +677,21 @@ let elem_section s =
660677
(* Data section *)
661678

662679
let memory_segment s =
663-
segment string (fun s -> (), string s) s
680+
match vu32 s with
681+
| 0l ->
682+
let index = Source.(0l @@ Source.no_region) in
683+
let offset = const s in
684+
let init = string s in
685+
ActiveData {index; offset; init}
686+
| 1l ->
687+
let data = string s in
688+
PassiveData {data}
689+
| 2l ->
690+
let index = at var s in
691+
let offset = const s in
692+
let init = string s in
693+
ActiveData {index; offset; init}
694+
| _ -> error s (pos s - 1) "invalid memory segment kind"
664695

665696
let data_section s =
666697
section `DataSection (vec (at memory_segment)) [] s

interpreter/binary/encode.ml

Lines changed: 32 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -477,39 +477,50 @@ let encode m =
477477
section 10 (vec code) fs (fs <> [])
478478

479479
(* Element section *)
480-
let segment active passive seg =
481-
match seg.it with
482-
| Active {index; offset; init} ->
483-
if index.it = 0l then
484-
u8 0x00
485-
else begin
486-
u8 0x02; var index
487-
end;
488-
const offset; active init
489-
| Passive {etype; data} ->
490-
u8 0x01; passive etype data
491-
492-
let active_elem el =
480+
let elem_expr el =
481+
match el.it with
482+
| RefNull -> u8 0xd0; end_ ()
483+
| RefFunc x -> u8 0xd2; var x; end_ ()
484+
485+
let elem_index el =
493486
match el.it with
494487
| RefNull -> assert false
495488
| RefFunc x -> var x
496489

497-
let passive_elem el =
498-
match el.it with
499-
| RefNull -> u8 0xd0; end_ ()
500-
| RefFunc x -> u8 0xd2; var x; end_ ()
490+
let elem_indices data = vec elem_index data
491+
492+
let all_func_ref l = not (List.exists (fun elem -> elem.it = RefNull) l)
501493

502494
let table_segment seg =
503-
let active init = vec active_elem init in
504-
let passive etype data = elem_type etype; vec passive_elem data in
505-
segment active passive seg
495+
match seg.it with
496+
| ActiveElem {index = {it = 0l;_}; offset; init; _}
497+
when all_func_ref init ->
498+
u8 0x00; const offset; elem_indices init
499+
| PassiveElem {data; _}
500+
when all_func_ref data ->
501+
u8 0x01; u8 0x00; elem_indices data
502+
| ActiveElem {index; offset; init; _}
503+
when all_func_ref init ->
504+
u8 0x02; var index; const offset; u8 0x00; elem_indices init
505+
| ActiveElem {index = {it = 0l;_}; offset; etype; init} ->
506+
u8 0x04; const offset; vec elem_expr init
507+
| PassiveElem {etype; data} ->
508+
u8 0x05; elem_type etype; vec elem_expr data
509+
| ActiveElem {index; offset; etype; init} ->
510+
u8 0x06; var index; const offset; elem_type etype; vec elem_expr init
506511

507512
let elem_section elems =
508513
section 9 (vec table_segment) elems (elems <> [])
509514

510515
(* Data section *)
511516
let memory_segment seg =
512-
segment string (fun _ s -> string s) seg
517+
match seg.it with
518+
| ActiveData {index = {it = 0l;_}; offset; init} ->
519+
u8 0x00; const offset; string init
520+
| PassiveData {data} ->
521+
u8 0x01; string data
522+
| ActiveData {index; offset; init} ->
523+
u8 0x02; var index; const offset; string init
513524

514525
let data_section datas =
515526
section 11 (vec memory_segment) datas (datas <> [])

interpreter/exec/eval.ml

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -448,13 +448,13 @@ let elem_list inst init =
448448

449449
let create_elem (inst : module_inst) (seg : table_segment) : elem_inst =
450450
match seg.it with
451-
| Active _ -> ref None
452-
| Passive {data; _} -> ref (Some (elem_list inst data))
451+
| ActiveElem _ -> ref None
452+
| PassiveElem {data; _} -> ref (Some (elem_list inst data))
453453

454454
let create_data (inst : module_inst) (seg : memory_segment) : data_inst =
455455
match seg.it with
456-
| Active _ -> ref None
457-
| Passive {data; _} -> ref (Some data)
456+
| ActiveData _ -> ref None
457+
| PassiveData {data} -> ref (Some data)
458458

459459

460460
let init_func (inst : module_inst) (func : func_inst) =
@@ -464,25 +464,25 @@ let init_func (inst : module_inst) (func : func_inst) =
464464

465465
let init_table (inst : module_inst) (seg : table_segment) =
466466
match seg.it with
467-
| Active {index; offset = const; init} ->
467+
| ActiveElem {index; offset = const; init; _} ->
468468
let tab = table inst index in
469469
let offset = i32 (eval_const inst const) const.at in
470470
let elems = elem_list inst init in
471471
let len = Int32.of_int (List.length elems) in
472472
(try Table.init tab elems offset 0l len
473473
with Table.Bounds -> Link.error seg.at "elements segment does not fit table")
474-
| Passive _ -> ()
474+
| PassiveElem _ -> ()
475475

476476
let init_memory (inst : module_inst) (seg : memory_segment) =
477477
match seg.it with
478-
| Active {index; offset = const; init} ->
478+
| ActiveData {index; offset = const; init} ->
479479
let mem = memory inst index in
480480
let offset' = i32 (eval_const inst const) const.at in
481481
let offset = I64_convert.extend_i32_u offset' in
482482
let len = Int32.of_int (String.length init) in
483483
(try Memory.init mem init offset 0L len
484484
with Memory.Bounds -> Link.error seg.at "data segment does not fit memory")
485-
| Passive _ -> ()
485+
| PassiveData _ -> ()
486486

487487

488488
let add_import (m : module_) (ext : extern) (im : import) (inst : module_inst)

interpreter/syntax/ast.ml

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -140,18 +140,21 @@ and memory' =
140140
mtype : memory_type;
141141
}
142142

143-
type ('data, 'ty) segment = ('data, 'ty) segment' Source.phrase
144-
and ('data, 'ty) segment' =
145-
| Active of {index : var; offset : const; init : 'data}
146-
| Passive of {etype : 'ty; data : 'data}
147-
148143
type elem = elem' Source.phrase
149144
and elem' =
150145
| RefNull
151146
| RefFunc of var
152147

153-
type table_segment = (elem list, elem_type) segment
154-
type memory_segment = (string, unit) segment
148+
149+
type table_segment = table_segment' Source.phrase
150+
and table_segment' =
151+
| ActiveElem of {index : var; offset : const; etype : elem_type; init : elem list}
152+
| PassiveElem of {etype : elem_type; data : elem list}
153+
154+
type memory_segment = memory_segment' Source.phrase
155+
and memory_segment' =
156+
| ActiveData of {index : var; offset : const; init : string}
157+
| PassiveData of {data : string}
155158

156159

157160
(* Modules *)
@@ -264,3 +267,4 @@ let string_of_name n =
264267
in
265268
List.iter escape n;
266269
Buffer.contents b
270+

0 commit comments

Comments
 (0)