blob: 8e1a37a45834966cfa217059e33d1a9f668586ef [file] [log] [blame] [edit]
open Source
open Ast
module Set = Set.Make(Int32)
type t =
{
types : Set.t;
globals : Set.t;
tables : Set.t;
memories : Set.t;
funcs : Set.t;
elems : Set.t;
datas : Set.t;
locals : Set.t;
labels : Set.t;
}
let empty : t =
{
types = Set.empty;
globals = Set.empty;
tables = Set.empty;
memories = Set.empty;
funcs = Set.empty;
elems = Set.empty;
datas = Set.empty;
locals = Set.empty;
labels = Set.empty;
}
let union (s1 : t) (s2 : t) : t =
{
types = Set.union s1.types s2.types;
globals = Set.union s1.globals s2.globals;
tables = Set.union s1.tables s2.tables;
memories = Set.union s1.memories s2.memories;
funcs = Set.union s1.funcs s2.funcs;
elems = Set.union s1.elems s2.elems;
datas = Set.union s1.datas s2.datas;
locals = Set.union s1.locals s2.locals;
labels = Set.union s1.labels s2.labels;
}
let types s = {empty with types = s}
let globals s = {empty with globals = s}
let tables s = {empty with tables = s}
let memories s = {empty with memories = s}
let funcs s = {empty with funcs = s}
let elems s = {empty with elems = s}
let datas s = {empty with datas = s}
let locals s = {empty with locals = s}
let labels s = {empty with labels = s}
let var x = Set.singleton x.it
let zero = Set.singleton 0l
let shift s = Set.map (Int32.add (-1l)) (Set.remove 0l s)
let (++) = union
let list free xs = List.fold_left union empty (List.map free xs)
let opt free xo = Lib.Option.get (Lib.Option.map free xo) empty
let block_type = function
| VarBlockType x -> types (var x)
| ValBlockType _ -> empty
let rec instr (e : instr) =
match e.it with
| Unreachable | Nop | Drop | Select _ -> empty
| RefNull _ | RefIsNull -> empty
| RefFunc x -> funcs (var x)
| Const _ | Test _ | Compare _ | Unary _ | Binary _ | Convert _ -> empty
| Block (bt, es) | Loop (bt, es) -> block_type bt ++ block es
| If (bt, es1, es2) -> block_type bt ++ block es1 ++ block es2
| Br x | BrIf x -> labels (var x)
| BrTable (xs, x) -> list (fun x -> labels (var x)) (x::xs)
| Return -> empty
| Call x -> funcs (var x)
| CallIndirect (x, y) -> tables (var x) ++ types (var y)
| LocalGet x | LocalSet x | LocalTee x -> locals (var x)
| GlobalGet x | GlobalSet x -> globals (var x)
| TableGet x | TableSet x | TableSize x | TableGrow x | TableFill x ->
tables (var x)
| TableCopy (x, y) -> tables (var x) ++ tables (var y)
| TableInit (x, y) -> tables (var x) ++ elems (var y)
| ElemDrop x -> elems (var x)
| Load _ | Store _
| VecLoad _ | VecStore _ | VecLoadLane _ | VecStoreLane _
| MemorySize | MemoryGrow | MemoryCopy | MemoryFill ->
memories zero
| VecConst _ | VecTest _ | VecUnary _ | VecBinary _ | VecCompare _
| VecConvert _ | VecShift _ | VecBitmask _
| VecTestBits _ | VecUnaryBits _ | VecBinaryBits _ | VecTernaryBits _
| VecSplat _ | VecExtract _ | VecReplace _ ->
memories zero
| MemoryInit x -> memories zero ++ datas (var x)
| DataDrop x -> datas (var x)
and block (es : instr list) =
let free = list instr es in {free with labels = shift free.labels}
let const (c : const) = block c.it
let global (g : global) = const g.it.ginit
let func (f : func) = {(block f.it.body) with locals = Set.empty}
let table (t : table) = empty
let memory (m : memory) = empty
let segment_mode f (m : segment_mode) =
match m.it with
| Passive | Declarative -> empty
| Active {index; offset} -> f (var index) ++ const offset
let elem (s : elem_segment) =
list const s.it.einit ++ segment_mode tables s.it.emode
let data (s : data_segment) =
segment_mode memories s.it.dmode
let type_ (t : type_) = empty
let export_desc (d : export_desc) =
match d.it with
| FuncExport x -> funcs (var x)
| TableExport x -> tables (var x)
| MemoryExport x -> memories (var x)
| GlobalExport x -> globals (var x)
let import_desc (d : import_desc) =
match d.it with
| FuncImport x -> types (var x)
| TableImport tt -> empty
| MemoryImport mt -> empty
| GlobalImport gt -> empty
let export (e : export) = export_desc e.it.edesc
let import (i : import) = import_desc i.it.idesc
let start (s : start) = funcs (var s.it.sfunc)
let module_ (m : module_) =
list type_ m.it.types ++
list global m.it.globals ++
list table m.it.tables ++
list memory m.it.memories ++
list func m.it.funcs ++
opt start m.it.start ++
list elem m.it.elems ++
list data m.it.datas ++
list import m.it.imports ++
list export m.it.exports