Skip to content

Commit c2cd260

Browse files
authored
Replace decoding flag with condition on free vars (WebAssembly#72)
1 parent 0cf128e commit c2cd260

File tree

4 files changed

+182
-8
lines changed

4 files changed

+182
-8
lines changed

interpreter/binary/decode.ml

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,11 @@ type stream =
55
name : string;
66
bytes : string;
77
pos : int ref;
8-
need_data_count : bool ref;
98
}
109

1110
exception EOS
1211

13-
let stream name bs = {name; bytes = bs; pos = ref 0; need_data_count = ref false}
12+
let stream name bs = {name; bytes = bs; pos = ref 0}
1413

1514
let len s = String.length s.bytes
1615
let pos s = !(s.pos)
@@ -208,9 +207,8 @@ let misc_instr s =
208207
| 0x08 ->
209208
let x = at var s in
210209
zero_flag s;
211-
s.need_data_count := true;
212210
memory_init x
213-
| 0x09 -> s.need_data_count := true; data_drop (at var s)
211+
| 0x09 -> data_drop (at var s)
214212
| 0x0a -> zero_flag s; zero_flag s; memory_copy
215213
| 0x0b -> zero_flag s; memory_fill
216214
| 0x0c ->
@@ -727,7 +725,8 @@ let module_ s =
727725
s (len s) "function and code section have inconsistent lengths";
728726
require (data_count = None || data_count = Some (Lib.List32.length datas))
729727
s (len s) "data count and data section have inconsistent lengths";
730-
require (not !(s.need_data_count) || data_count <> None)
728+
require (data_count <> None ||
729+
List.for_all Free.(fun f -> (func f).datas = Set.empty) func_bodies)
731730
s (len s) "data count section required";
732731
let funcs =
733732
List.map2 Source.(fun t f -> {f.it with ftype = t} @@ f.at)

interpreter/binary/encode.ml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -515,8 +515,8 @@ let encode m =
515515
section 11 (vec memory_segment) datas (datas <> [])
516516

517517
(* Data count section *)
518-
let data_count_section datas =
519-
section 12 len (List.length datas) true
518+
let data_count_section datas m =
519+
section 12 len (List.length datas) Free.((module_ m).datas <> Set.empty)
520520

521521
(* Module *)
522522

@@ -532,7 +532,7 @@ let encode m =
532532
export_section m.it.exports;
533533
start_section m.it.start;
534534
elem_section m.it.elems;
535-
data_count_section m.it.datas;
535+
data_count_section m.it.datas m;
536536
code_section m.it.funcs;
537537
data_section m.it.datas
538538
end

interpreter/syntax/free.ml

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
open Source
2+
open Ast
3+
4+
module Set = Set.Make(Int32)
5+
6+
type t =
7+
{
8+
types : Set.t;
9+
globals : Set.t;
10+
tables : Set.t;
11+
memories : Set.t;
12+
funcs : Set.t;
13+
elems : Set.t;
14+
datas : Set.t;
15+
locals : Set.t;
16+
labels : Set.t;
17+
}
18+
19+
let empty : t =
20+
{
21+
types = Set.empty;
22+
globals = Set.empty;
23+
tables = Set.empty;
24+
memories = Set.empty;
25+
funcs = Set.empty;
26+
elems = Set.empty;
27+
datas = Set.empty;
28+
locals = Set.empty;
29+
labels = Set.empty;
30+
}
31+
32+
let union (s1 : t) (s2 : t) : t =
33+
{
34+
types = Set.union s1.types s2.types;
35+
globals = Set.union s1.globals s2.globals;
36+
tables = Set.union s1.tables s2.tables;
37+
memories = Set.union s1.memories s2.memories;
38+
funcs = Set.union s1.funcs s2.funcs;
39+
elems = Set.union s1.elems s2.elems;
40+
datas = Set.union s1.datas s2.datas;
41+
locals = Set.union s1.locals s2.locals;
42+
labels = Set.union s1.labels s2.labels;
43+
}
44+
45+
let types s = {empty with types = s}
46+
let globals s = {empty with globals = s}
47+
let tables s = {empty with tables = s}
48+
let memories s = {empty with memories = s}
49+
let funcs s = {empty with funcs = s}
50+
let elems s = {empty with elems = s}
51+
let datas s = {empty with datas = s}
52+
let locals s = {empty with locals = s}
53+
let labels s = {empty with labels = s}
54+
55+
let var x = Set.singleton x.it
56+
let zero = Set.singleton 0l
57+
let shift s = Set.map (Int32.add (-1l)) (Set.remove 0l s)
58+
59+
let (++) = union
60+
let list free xs = List.fold_left union empty (List.map free xs)
61+
62+
let rec instr (e : instr) =
63+
match e.it with
64+
| Unreachable | Nop | Drop | Select -> empty
65+
| Const _ | Test _ | Compare _ | Unary _ | Binary _ | Convert _ -> empty
66+
| Block (_, es) | Loop (_, es) -> block es
67+
| If (_, es1, es2) -> block es1 ++ block es2
68+
| Br x | BrIf x -> labels (var x)
69+
| BrTable (xs, x) -> list (fun x -> labels (var x)) (x::xs)
70+
| Return -> empty
71+
| Call x -> funcs (var x)
72+
| CallIndirect x -> types (var x) ++ tables zero
73+
| LocalGet x | LocalSet x | LocalTee x -> locals (var x)
74+
| GlobalGet x | GlobalSet x -> globals (var x)
75+
| Load _ | Store _ | MemorySize | MemoryGrow | MemoryCopy | MemoryFill ->
76+
memories zero
77+
| MemoryInit x -> memories zero ++ datas (var x)
78+
| TableCopy -> tables zero
79+
| TableInit x -> tables zero ++ elems (var x)
80+
| DataDrop x -> datas (var x)
81+
| ElemDrop x -> elems (var x)
82+
83+
and block (es : instr list) =
84+
let free = list instr es in {free with labels = shift free.labels}
85+
86+
let const (c : const) = block c.it
87+
88+
let global (g : global) = const g.it.value
89+
let func (f : func) = {(block f.it.body) with locals = Set.empty}
90+
let table (t : table) = empty
91+
let memory (m : memory) = empty
92+
93+
let elem (e : elem) =
94+
match e.it with
95+
| Null -> empty
96+
| Func x -> funcs (var x)
97+
98+
let table_segment (s : table_segment) =
99+
match s.it with
100+
| Active {index; offset; init} ->
101+
tables (var index) ++ const offset ++ list elem init
102+
| Passive {etype; data} -> list elem data
103+
104+
let memory_segment (s : memory_segment) =
105+
match s.it with
106+
| Active {index; offset; init} -> memories (var index) ++ const offset
107+
| Passive {etype; data} -> empty
108+
109+
let type_ (t : type_) = empty
110+
111+
let export_desc (d : export_desc) =
112+
match d.it with
113+
| FuncExport x -> funcs (var x)
114+
| TableExport x -> tables (var x)
115+
| MemoryExport x -> memories (var x)
116+
| GlobalExport x -> globals (var x)
117+
118+
let import_desc (d : import_desc) =
119+
match d.it with
120+
| FuncImport x -> types (var x)
121+
| TableImport tt -> empty
122+
| MemoryImport mt -> empty
123+
| GlobalImport gt -> empty
124+
125+
let export (e : export) = export_desc e.it.edesc
126+
let import (i : import) = import_desc i.it.idesc
127+
128+
let start (s : var option) =
129+
funcs (Lib.Option.get (Lib.Option.map var s) Set.empty)
130+
131+
let module_ (m : module_) =
132+
list type_ m.it.types ++
133+
list global m.it.globals ++
134+
list table m.it.tables ++
135+
list memory m.it.memories ++
136+
list func m.it.funcs ++
137+
start m.it.start ++
138+
list table_segment m.it.elems ++
139+
list memory_segment m.it.datas ++
140+
list import m.it.imports ++
141+
list export m.it.exports

interpreter/syntax/free.mli

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
module Set : Set.S with type elt = int32
2+
3+
type t =
4+
{
5+
types : Set.t;
6+
globals : Set.t;
7+
tables : Set.t;
8+
memories : Set.t;
9+
funcs : Set.t;
10+
elems : Set.t;
11+
datas : Set.t;
12+
locals : Set.t;
13+
labels : Set.t;
14+
}
15+
16+
val empty : t
17+
val union : t -> t -> t
18+
19+
val instr : Ast.instr -> t
20+
val block : Ast.instr list -> t
21+
val const : Ast.const -> t
22+
23+
val type_ : Ast.type_ -> t
24+
val global : Ast.global -> t
25+
val func : Ast.func -> t
26+
val table : Ast.table -> t
27+
val memory : Ast.memory -> t
28+
val table_segment : Ast.table_segment -> t
29+
val memory_segment : Ast.memory_segment -> t
30+
val export : Ast.export -> t
31+
val import : Ast.import -> t
32+
val start : Ast.var option -> t
33+
34+
val module_ : Ast.module_ -> t

0 commit comments

Comments
 (0)