1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
open Api
open Vectors
open Utils
module Resolver = Map.Make (struct
type t = string * string * Types.Externkind.t
let compare (l1, l2, l3) (r1, r2, r3) =
match
(String.compare l1 r1, String.compare l2 r2, Unsigned.UInt8.compare l3 r3)
with
| 0, 0, r -> r
| 0, r, _ -> r
| r, _, _ -> r
end)
type t = {
module_ : Module.t;
instance : Types.Instance.t Ctypes.ptr;
clean : unit -> unit;
}
exception
Unsatisfied_import of {
module_ : string;
name : string;
kind : Types.Externkind.t;
}
let resolve_imports store modul resolver =
let lookup import =
let module_ = Import_type.module_ import in
let name = Import_type.name import in
let kind = Import_type.type_ import |> Functions.Externtype.kind in
let match_ = Resolver.find_opt (module_, name, kind) resolver in
match match_ with
| None -> raise (Unsatisfied_import {module_; name; kind})
| Some m -> Extern.to_extern store m
in
let imports_vec = Module.imports modul in
let imports = Import_type_vector.to_array imports_vec |> Array.map lookup in
let externs = Extern_vector.from_array (Array.map fst imports) in
let clean () =
Array.fold_left
(fun clean_all (_, clean) ->
() ;
fun x ->
clean_all x ;
clean x)
Fun.id
imports
()
in
Functions.Importtype_vec.delete (Ctypes.addr imports_vec) ;
let clean_after_instantiation () =
Functions.Extern_vec.delete (Ctypes.addr externs)
in
(externs, clean_after_instantiation, clean)
let create store module_ externs =
let open Lwt.Syntax in
let externs_vec, clean_after_instantiation, clean =
externs
|> List.map (fun (module_, name, extern) ->
((module_, name, Extern.to_externkind extern), extern))
|> List.to_seq |> Resolver.of_seq
|> resolve_imports store module_
in
let trap = Ctypes.allocate_n (Ctypes.ptr Types.Trap.t) ~count:1 in
Ctypes.(trap <-@ Trap.none) ;
let instantiate () =
Lwt_preemptive.detach
(fun (store, module_, externs_vec, trap) ->
Functions.Instance.new_ store module_ (Ctypes.addr externs_vec) trap)
(store, module_, externs_vec, trap)
in
let+ instance =
Lwt.finalize instantiate (fun () ->
clean_after_instantiation () ;
Lwt.return_unit)
in
let trap = Ctypes.(!@trap) in
Trap.check trap ;
check_null_ptr Error.(make_exception Instantiate_module) instance ;
{module_; instance; clean}
let delete inst =
Functions.Instance.delete inst.instance ;
inst.clean ()