Skip to content

Commit

Permalink
[Interpreter] New syntax for passive elem segments (WebAssembly#65)
Browse files Browse the repository at this point in the history
It uses instruction encoding instead of assuming that each element is a
function variable:

```
0xd0 -> ref.null
0xd2 x -> ref.func x
```
  • Loading branch information
binji authored Mar 1, 2019
1 parent f574364 commit d97e8fb
Show file tree
Hide file tree
Showing 9 changed files with 103 additions and 29 deletions.
23 changes: 17 additions & 6 deletions interpreter/binary/decode.ml
Original file line number Diff line number Diff line change
Expand Up @@ -612,25 +612,36 @@ let code_section s =

(* Element section *)

let segment dat s =
let segment active passive s =
match vu32 s with
| 0l ->
let index = Source.(0l @@ Source.no_region) in
let offset = const s in
let init = dat s in
let init = active s in
Active {index; offset; init}
| 1l ->
let init = dat s in
let init = passive s in
Passive init
| 2l ->
let index = at var s in
let offset = const s in
let init = dat s in
let init = active s in
Active {index; offset; init}
| _ -> error s (pos s - 1) "invalid segment kind"

let active_elem s = Func (at var s)

let passive_elem s =
match u8 s with
| 0xd0 -> end_ s; Null
| 0xd2 ->
let x = at var s in
end_ s;
Func x
| _ -> error s (pos s - 1) "invalid elem"

let table_segment s =
segment (vec (at var)) s
segment (vec (at active_elem)) (vec (at passive_elem)) s

let elem_section s =
section `ElemSection (vec (at table_segment)) [] s
Expand All @@ -639,7 +650,7 @@ let elem_section s =
(* Data section *)

let memory_segment s =
segment string s
segment string string s

let data_section s =
section `DataSection (vec (at memory_segment)) [] s
Expand Down
20 changes: 15 additions & 5 deletions interpreter/binary/encode.ml
Original file line number Diff line number Diff line change
Expand Up @@ -477,7 +477,7 @@ let encode m =
section 10 (vec code) fs (fs <> [])

(* Element section *)
let segment dat seg =
let segment active passive seg =
match seg.it with
| Active {index; offset; init} ->
if index.it = 0l then
Expand All @@ -486,19 +486,29 @@ let encode m =
u8 0x02; var index
end;
const offset;
dat init
active init
| Passive init ->
u8 0x01; dat init
u8 0x01; passive init

let active_elem el =
match el.it with
| Null -> assert false
| Func x -> var x

let passive_elem el =
match el.it with
| Null -> u8 0xd0; end_ ()
| Func x -> u8 0xd2; var x; end_ ()

let table_segment seg =
segment (vec var) seg
segment (vec active_elem) (vec passive_elem) seg

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

(* Data section *)
let memory_segment seg =
segment string seg
segment string string seg

let data_section data =
section 11 (vec memory_segment) data (data <> [])
Expand Down
6 changes: 5 additions & 1 deletion interpreter/exec/eval.ml
Original file line number Diff line number Diff line change
Expand Up @@ -436,7 +436,11 @@ let create_export (inst : module_inst) (ex : export) : export_inst =
in name, ext

let elems_list inst init =
List.map (fun x -> (FuncElem (func inst x))) init
let to_elem el =
match el.it with
| Null -> Table.Uninitialized
| Func x -> FuncElem (func inst x)
in List.map to_elem init

let create_elems (inst : module_inst) (seg : table_segment) : elems_inst =
match seg.it with
Expand Down
9 changes: 7 additions & 2 deletions interpreter/syntax/ast.ml
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,12 @@ and 'data segment' =
| Active of {index : var; offset : const; init : 'data}
| Passive of 'data

type table_segment = var list segment
type elem = elem' Source.phrase
and elem' =
| Null
| Func of var

type table_segment = elem list segment
type memory_segment = string segment


Expand Down Expand Up @@ -191,7 +196,7 @@ and module_' =
memories : memory list;
funcs : func list;
start : var option;
elems : var list segment list;
elems : elem list segment list;
data : string segment list;
imports : import list;
exports : export list;
Expand Down
20 changes: 15 additions & 5 deletions interpreter/text/arrange.ml
Original file line number Diff line number Diff line change
Expand Up @@ -296,17 +296,27 @@ let memory off i mem =
let {mtype = MemoryType lim} = mem.it in
Node ("memory $" ^ nat (off + i) ^ " " ^ limits nat32 lim, [])

let segment head dat seg =
let segment head active passive seg =
match seg.it with
| Active {index; offset; init} ->
Node (head, atom var index :: Node ("offset", const offset) :: dat init)
| Passive init -> Node (head ^ " passive", dat init)
Node (head, atom var index :: Node ("offset", const offset) :: active init)
| Passive init -> Node (head ^ " passive", passive init)

let active_elem el =
match el.it with
| Null -> assert false
| Func x -> atom var x

let passive_elem el =
match el.it with
| Null -> Node ("ref.null", [])
| Func x -> Node ("ref.func", [atom var x])

let elems seg =
segment "elem" (list (atom var)) seg
segment "elem" (list active_elem) (list passive_elem) seg

let data seg =
segment "data" break_bytes seg
segment "data" break_bytes break_bytes seg


(* Modules *)
Expand Down
3 changes: 3 additions & 0 deletions interpreter/text/lexer.mll
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,9 @@ rule token = parse
| "elem.drop" { ELEM_DROP }
| "table.copy" { TABLE_COPY }

| "ref.null" { REF_NULL }
| "ref.func" { REF_FUNC }

| "passive" { PASSIVE }

| "type" { TYPE }
Expand Down
26 changes: 20 additions & 6 deletions interpreter/text/parser.mly
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ let inline_type_explicit (c : context) x ft at =
%token UNREACHABLE MEMORY_SIZE MEMORY_GROW
%token MEMORY_INIT DATA_DROP MEMORY_COPY MEMORY_FILL
%token TABLE_INIT ELEM_DROP TABLE_COPY
%token REF_NULL REF_FUNC
%token FUNC START TYPE PARAM RESULT LOCAL GLOBAL
%token TABLE ELEM MEMORY DATA OFFSET IMPORT EXPORT TABLE
%token PASSIVE
Expand Down Expand Up @@ -568,22 +569,35 @@ offset :
| LPAR OFFSET const_expr RPAR { $3 }
| expr { let at = at () in fun c -> $1 c @@ at } /* Sugar */
elemref :
| LPAR REF_NULL RPAR { let at = at () in fun c -> Null @@ at }
| LPAR REF_FUNC var RPAR { let at = at () in fun c -> Func ($3 c func) @@ at }
passive_elemref_list :
| /* empty */ { fun c -> [] }
| elemref passive_elemref_list { fun c -> $1 c :: $2 c }
active_elemref_list :
| var_list
{ let f = function {at; _} as x -> Func x @@ at in
fun c lookup -> List.map f ($1 c lookup) }
elem :
| LPAR ELEM bind_var_opt PASSIVE var_list RPAR
| LPAR ELEM bind_var_opt PASSIVE passive_elemref_list RPAR
{ let at = at () in
fun c -> ignore ($3 c anon_elem bind_elem);
fun () -> Passive ($5 c func) @@ at }
| LPAR ELEM bind_var var offset var_list RPAR
fun () -> Passive ($5 c) @@ at }
| LPAR ELEM bind_var var offset active_elemref_list RPAR
{ let at = at () in
fun c -> ignore (bind_elem c $3);
fun () ->
Active {index = $4 c table; offset = $5 c; init = $6 c func} @@ at }
| LPAR ELEM var offset var_list RPAR
| LPAR ELEM var offset active_elemref_list RPAR
{ let at = at () in
fun c -> ignore (anon_elem c);
fun () ->
Active {index = $3 c table; offset = $4 c; init = $5 c func} @@ at }
| LPAR ELEM offset var_list RPAR /* Sugar */
| LPAR ELEM offset active_elemref_list RPAR /* Sugar */
{ let at = at () in
fun c -> ignore (anon_elem c);
fun () ->
Expand All @@ -606,7 +620,7 @@ table_fields :
| inline_export table_fields /* Sugar */
{ fun c x at -> let tabs, elems, ims, exs = $2 c x at in
tabs, elems, ims, $1 (TableExport x) c :: exs }
| elem_type LPAR ELEM var_list RPAR /* Sugar */
| elem_type LPAR ELEM active_elemref_list RPAR /* Sugar */
{ fun c x at ->
let offset = [i32_const (0l @@ at) @@ at] @@ at in
let init = $4 c func in let size = Int32.of_int (List.length init) in
Expand Down
9 changes: 7 additions & 2 deletions interpreter/valid/valid.ml
Original file line number Diff line number Diff line change
Expand Up @@ -424,14 +424,19 @@ let check_memory (c : context) (mem : memory) =
let {mtype} = mem.it in
check_memory_type mtype mem.at

let check_elemref (c : context) (el : elem) =
match el.it with
| Null -> ()
| Func x -> ignore (func c x)

let check_elem (c : context) (seg : table_segment) =
match seg.it with
| Active {index; offset; init} ->
ignore (table c index);
check_const c offset I32Type;
ignore (List.map (func c) init)
List.iter (check_elemref c) init
| Passive init ->
ignore (List.map (func c) init)
List.iter (check_elemref c) init

let check_data (c : context) (seg : memory_segment) =
match seg.it with
Expand Down
16 changes: 14 additions & 2 deletions test/core/bulk.wast
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
;; Passive segment syntax
(module
(memory 1)
(data passive "foo"))

(module
(table 3 funcref)
(elem passive (ref.func 0) (ref.null) (ref.func 1))
(func)
(func))

;; memory.fill
(module
(memory 1)
Expand Down Expand Up @@ -171,7 +182,8 @@
;; table.init
(module
(table 3 funcref)
(elem passive $zero $one $zero $one)
(elem passive
(ref.func $zero) (ref.func $one) (ref.func $zero) (ref.func $one))

(func $zero (result i32) (i32.const 0))
(func $one (result i32) (i32.const 1))
Expand Down Expand Up @@ -215,7 +227,7 @@
(module
(table 1 funcref)
(func $f)
(elem $p passive $f)
(elem $p passive (ref.func $f))
(elem $a 0 (i32.const 0) $f)

(func (export "drop_passive") (elem.drop $p))
Expand Down

0 comments on commit d97e8fb

Please sign in to comment.