Skip to content

Commit e2ed182

Browse files
authored
feat: lazy wasm imports (#5276)
1 parent 7086c4c commit e2ed182

File tree

10 files changed

+293
-271
lines changed

10 files changed

+293
-271
lines changed

src/codegen/compile_classical.ml

Lines changed: 26 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ open Mo_config
1717

1818
open Wasm_exts.Ast
1919
open Source
20-
(* Re-shadow Source.(@@), to get Stdlib.(@@) *)
21-
let (@@) = Stdlib.(@@)
20+
21+
open Compile_common
2222

2323
module Wasm = struct
2424
include Wasm
@@ -28,17 +28,11 @@ end
2828

2929
open Wasm.Types
3030

31-
module G = InstrList
32-
let (^^) = G.(^^) (* is this how we import a single operator from a module that we otherwise use qualified? *)
33-
3431
(* WebAssembly pages are 64kb. *)
3532
let page_size = Int32.of_int (64*1024)
3633
let page_size64 = Int64.of_int32 page_size
3734
let page_size_bits = 16
3835

39-
(* Our code depends on OCaml int having at least 32 bits *)
40-
let _ = assert (Sys.int_size >= 32)
41-
4236
(* Scalar Tagging Scheme *)
4337

4438
(* Rationale:
@@ -169,17 +163,6 @@ See documentation of module BitTagged for more detail.
169163
let ptr_skew = -1l
170164
let ptr_unskew = 1l
171165

172-
(* Generating function names for functions parametrized by prim types *)
173-
let prim_fun_name p stem = Printf.sprintf "%s<%s>" stem (Type.string_of_prim p)
174-
175-
(* Helper functions to produce annotated terms (Wasm.AST) *)
176-
let nr x = Wasm.Source.{ it = x; at = no_region }
177-
178-
let todo fn se x = Printf.eprintf "%s: %s" fn (Wasm.Sexpr.to_string 80 se); x
179-
180-
exception CodegenError of string
181-
let fatal fmt = Printf.ksprintf (fun s -> raise (CodegenError s)) fmt
182-
183166
module StaticBytes = struct
184167
(* A very simple DSL to describe static memory *)
185168

@@ -379,6 +362,7 @@ The fields fall into the following categories:
379362
(* Before we can define the environment, we need some auxillary types *)
380363

381364
module E = struct
365+
include Compile_common.E
382366

383367
(* Utilities, internal to E *)
384368
let reg (ref : 'a list ref) (x : 'a) : int32 =
@@ -394,15 +378,11 @@ module E = struct
394378

395379

396380
(* The environment type *)
397-
module NameEnv = Env.Make(String)
398381
module StringEnv = Env.Make(String)
399382
module LabSet = Set.Make(String)
400383
module FeatureSet = Set.Make(String)
401384

402385
module FunEnv = Env.Make(Int32)
403-
type local_names = (int32 * string) list (* For the debug section: Names of locals *)
404-
type func_with_names = func * local_names
405-
type lazy_function = (int32, func_with_names) Lib.AllocOnUse.t
406386
type t = {
407387
(* Global fields *)
408388
(* Static *)
@@ -415,16 +395,12 @@ module E = struct
415395
(* Immutable *)
416396

417397
(* Mutable *)
418-
func_types : func_type list ref;
419-
func_imports : import list ref;
420-
other_imports : import list ref;
398+
imports : Imports.t;
421399
exports : export list ref;
422-
funcs : (func * string * local_names) Lib.Promise.t list ref;
423400
func_ptrs : int32 FunEnv.t ref;
424401
end_of_table : int32 ref;
425402
globals : (global Lib.Promise.t * string) list ref;
426403
global_names : int32 NameEnv.t ref;
427-
named_imports : int32 NameEnv.t ref;
428404
built_in_funcs : lazy_function NameEnv.t ref;
429405
static_strings : int32 StringEnv.t ref;
430406
(* Pool for shared static objects. Their lookup needs to be specifically
@@ -474,16 +450,12 @@ module E = struct
474450
mode;
475451
rts;
476452
trap_with;
477-
func_types = ref [];
478-
func_imports = ref [];
479-
other_imports = ref [];
453+
imports = Imports.empty ();
480454
exports = ref [];
481-
funcs = ref [];
482455
func_ptrs = ref FunEnv.empty;
483456
end_of_table = ref 0l;
484457
globals = ref [];
485458
global_names = ref NameEnv.empty;
486-
named_imports = ref NameEnv.empty;
487459
built_in_funcs = ref NameEnv.empty;
488460
static_strings = ref StringEnv.empty;
489461
object_pool = ref StringEnv.empty;
@@ -539,9 +511,6 @@ module E = struct
539511
let get_locals (env : t) = !(env.locals)
540512
let get_local_names (env : t) : (int32 * string) list = !(env.local_names)
541513

542-
let _add_other_import (env : t) m =
543-
ignore (reg env.other_imports m)
544-
545514
let add_export (env : t) e =
546515
ignore (reg env.exports e)
547516

@@ -594,17 +563,9 @@ module E = struct
594563

595564
let get_globals (env : t) = List.map (fun (g,n) -> Lib.Promise.value g) !(env.globals)
596565

597-
let reserve_fun (env : t) name =
598-
let (j, fill) = reserve_promise env.funcs name in
599-
let n = Int32.of_int (List.length !(env.func_imports)) in
600-
let fi = Int32.add j n in
601-
let fill_ (f, local_names) = fill (f, name, local_names) in
602-
(fi, fill_)
566+
let reserve_fun (env : t) = Imports.reserve_fun env.imports
603567

604-
let add_fun (env : t) name (f, local_names) =
605-
let (fi, fill) = reserve_fun env name in
606-
fill (f, local_names);
607-
fi
568+
let add_fun (env : t) = Imports.add_fun env.imports
608569

609570
let make_lazy_function env name : lazy_function =
610571
Lib.AllocOnUse.make (fun () -> reserve_fun env name)
@@ -625,48 +586,20 @@ module E = struct
625586

626587
let get_return_arity (env : t) = env.return_arity
627588

628-
let get_func_imports (env : t) = !(env.func_imports)
629-
let get_other_imports (env : t) = !(env.other_imports)
630589
let get_exports (env : t) = !(env.exports)
631-
let get_funcs (env : t) = List.map Lib.Promise.value !(env.funcs)
632-
633-
let func_type (env : t) ty =
634-
let rec go i = function
635-
| [] -> env.func_types := !(env.func_types) @ [ ty ]; Int32.of_int i
636-
| ty'::tys when ty = ty' -> Int32.of_int i
637-
| _ :: tys -> go (i+1) tys
638-
in
639-
go 0 !(env.func_types)
640-
641-
let get_types (env : t) = !(env.func_types)
642-
643-
let add_func_import (env : t) modname funcname arg_tys ret_tys =
644-
if !(env.funcs) <> [] then
645-
raise (CodegenError "Add all imports before all functions!");
646-
647-
let i = {
648-
module_name = Lib.Utf8.decode modname;
649-
item_name = Lib.Utf8.decode funcname;
650-
idesc = nr (FuncImport (nr (func_type env (FuncType (arg_tys, ret_tys)))))
651-
} in
652-
let fi = reg env.func_imports (nr i) in
653-
let name = modname ^ "." ^ funcname in
654-
assert (not (NameEnv.mem name !(env.named_imports)));
655-
env.named_imports := NameEnv.add name fi !(env.named_imports)
656-
657-
let call_import (env : t) modname funcname =
658-
let name = modname ^ "." ^ funcname in
659-
match NameEnv.find_opt name !(env.named_imports) with
660-
| Some fi -> G.i (Call (nr fi))
661-
| _ ->
662-
raise (Invalid_argument (Printf.sprintf "Function import not declared: %s\n" name))
590+
let get_funcs (env : t) = Imports.get_funcs env.imports
663591

664-
let reuse_import (env : t) modname funcname =
665-
let name = modname ^ "." ^ funcname in
666-
match NameEnv.find_opt name !(env.named_imports) with
667-
| Some fi -> fi
668-
| _ ->
669-
raise (Invalid_argument (Printf.sprintf "Function import not declared: %s\n" name))
592+
let func_type (env : t) = Imports.func_type env.imports
593+
594+
let get_types (env : t) = Imports.get_types env.imports
595+
596+
let add_func_import (env : t) = Imports.add_func_import env.imports
597+
598+
let call_import (env : t) = Imports.call_import env.imports
599+
600+
let reuse_import (env : t) = Imports.reuse_import env.imports
601+
602+
let finalize_func_imports (env : t) = Imports.finalize_func_imports env.imports
670603

671604
let get_rts (env : t) = env.rts
672605

@@ -13376,11 +13309,7 @@ and conclude_module env set_serialization_globals start_fi_o =
1337613309

1337713310
IC.default_exports env;
1337813311

13379-
let func_imports = E.get_func_imports env in
13380-
let ni = List.length func_imports in
13381-
let ni' = Int32.of_int ni in
13382-
13383-
let other_imports = E.get_other_imports env in
13312+
let func_imports, ni, remapping = E.finalize_func_imports env in
1338413313

1338513314
let memories = E.get_memories env in
1338613315

@@ -13402,15 +13331,15 @@ and conclude_module env set_serialization_globals start_fi_o =
1340213331

1340313332
let table_sz = E.get_end_of_table env in
1340413333

13405-
let module_ = {
13334+
let module_ = rename_funcs remapping {
1340613335
types = List.map nr (E.get_types env);
1340713336
funcs = List.map (fun (f,_,_) -> f) funcs;
1340813337
tables = [ nr { ttype = TableType ({min = table_sz; max = Some table_sz}, FuncRefType) } ];
1340913338
elems;
1341013339
start = Some (nr rts_start_fi);
1341113340
globals = E.get_globals env;
1341213341
memories;
13413-
imports = func_imports @ other_imports;
13342+
imports = func_imports;
1341413343
exports = E.get_exports env;
1341513344
datas
1341613345
} in
@@ -13419,10 +13348,10 @@ and conclude_module env set_serialization_globals start_fi_o =
1341913348
let open Wasm_exts.CustomModule in
1342013349
{ module_;
1342113350
dylink0 = [];
13422-
name = { empty_name_section with function_names =
13423-
List.mapi (fun i (f,n,_) -> Int32.(add ni' (of_int i), n)) funcs;
13424-
locals_names =
13425-
List.mapi (fun i (f,_,ln) -> Int32.(add ni' (of_int i), ln)) funcs; };
13351+
name = { empty_name_section with
13352+
function_names = List.mapi (fun i (f,n,_) -> Int32.(add ni (of_int i), n)) funcs;
13353+
locals_names = List.mapi (fun i (f,_,ln) -> Int32.(add ni (of_int i), ln)) funcs;
13354+
};
1342613355
motoko = {
1342713356
labels = E.get_labs env;
1342813357
stable_types = !(env.E.stable_types);

0 commit comments

Comments
 (0)