Skip to content

Commit b3a69be

Browse files
committed
Compiler: wasmoo support for shapes
1 parent a2f5827 commit b3a69be

File tree

6 files changed

+80
-17
lines changed

6 files changed

+80
-17
lines changed

compiler/bin-wasm_of_ocaml/cmd_arg.ml

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ type t =
6363
; params : (string * string) list
6464
; include_dirs : string list
6565
; effects : Config.effects_backend
66+
; shape_files : string list
6667
}
6768

6869
let options () =
@@ -78,6 +79,10 @@ let options () =
7879
let doc = "Compile the bytecode program [$(docv)]. " in
7980
Arg.(required & pos ~rev:true 0 (some string) None & info [] ~docv:"PROGRAM" ~doc)
8081
in
82+
let shape_files =
83+
let doc = "load shape file [$(docv)]." in
84+
Arg.(value & opt_all string [] & info [ "load-shape" ] ~docv:"FILE" ~doc)
85+
in
8186
let profile =
8287
let doc = "Set optimization profile : [$(docv)]." in
8388
let profile =
@@ -140,7 +145,8 @@ let options () =
140145
output_file
141146
input_file
142147
runtime_files
143-
effects =
148+
effects
149+
shape_files =
144150
let chop_extension s = try Filename.chop_extension s with Invalid_argument _ -> s in
145151
let output_file =
146152
let ext =
@@ -172,6 +178,7 @@ let options () =
172178
; sourcemap_root
173179
; sourcemap_don't_inline_content
174180
; effects
181+
; shape_files
175182
}
176183
in
177184
let t =
@@ -189,7 +196,8 @@ let options () =
189196
$ output_file
190197
$ input_file
191198
$ runtime_files
192-
$ effects)
199+
$ effects
200+
$ shape_files)
193201
in
194202
Term.ret t
195203

@@ -270,6 +278,7 @@ let options_runtime_only () =
270278
; sourcemap_root
271279
; sourcemap_don't_inline_content
272280
; effects
281+
; shape_files = []
273282
}
274283
in
275284
let t =

compiler/bin-wasm_of_ocaml/cmd_arg.mli

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ type t =
3232
; params : (string * string) list
3333
; include_dirs : string list
3434
; effects : Config.effects_backend
35+
; shape_files : string list
3536
}
3637

3738
val options : unit -> t Cmdliner.Term.t

compiler/bin-wasm_of_ocaml/compile.ml

Lines changed: 62 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,15 @@ let generate_prelude ~out_file =
245245
@@ fun ch ->
246246
let code, uinfo = Parse_bytecode.predefined_exceptions () in
247247
let profile = Profile.O1 in
248-
let Driver.{ program; variable_uses; in_cps; deadcode_sentinal; _ }, global_flow_data =
248+
let ( Driver.
249+
{ program
250+
; variable_uses
251+
; in_cps
252+
; deadcode_sentinal
253+
; shapes = _
254+
; trampolined_calls = _
255+
}
256+
, global_flow_data ) =
249257
Driver.optimize_for_wasm ~profile ~shapes:false code
250258
in
251259
let context = Generate.start () in
@@ -328,6 +336,16 @@ let add_source_map sourcemap_don't_inline_content z opt_source_map =
328336
~name:(Link.source_name i j file)
329337
~contents:(Yojson.Basic.to_string (`String sm))))
330338

339+
let merge_shape a b =
340+
StringMap.union (fun _name s1 s2 -> if Shape.equal s1 s2 then Some s1 else None) a b
341+
342+
let sexp_of_shapes s =
343+
StringMap.bindings s
344+
|> List.map ~f:(fun (name, shape) ->
345+
Sexp.List [ Atom name; Atom (Shape.to_string shape) ])
346+
347+
let string_of_shapes s = Sexp.List (sexp_of_shapes s) |> Sexp.to_string
348+
331349
let run
332350
{ Cmd_arg.common
333351
; profile
@@ -341,11 +359,24 @@ let run
341359
; sourcemap_root
342360
; sourcemap_don't_inline_content
343361
; effects
362+
; shape_files
344363
} =
345364
Config.set_target `Wasm;
346365
Jsoo_cmdline.Arg.eval common;
347366
Config.set_effects_backend effects;
348367
Generate.init ();
368+
List.iter shape_files ~f:(fun s ->
369+
let z = Zip.open_in s in
370+
if Zip.has_entry z ~name:"shapes.sexp"
371+
then
372+
let s = Zip.read_entry z ~name:"shapes.sexp" in
373+
match Sexp.from_string s with
374+
| List l ->
375+
List.iter l ~f:(function
376+
| Sexp.List [ Atom name; Atom shape ] ->
377+
Shape.Store.set ~name (Shape.of_string shape)
378+
| _ -> ())
379+
| _ -> ());
349380
let output_file = fst output_file in
350381
if debug_mem () then Debug.start_profiling output_file;
351382
List.iter params ~f:(fun (s, v) -> Config.Param.set s v);
@@ -398,10 +429,18 @@ let run
398429
check_debug one;
399430
let code = one.code in
400431
let standalone = Option.is_none unit_name in
401-
let Driver.{ program; variable_uses; in_cps; deadcode_sentinal; _ }, global_flow_data
402-
=
403-
Driver.optimize_for_wasm ~profile ~shapes:false code
432+
let ( Driver.
433+
{ program
434+
; variable_uses
435+
; in_cps
436+
; deadcode_sentinal
437+
; shapes
438+
; trampolined_calls = _
439+
}
440+
, global_flow_data ) =
441+
Driver.optimize_for_wasm ~profile ~shapes:true code
404442
in
443+
StringMap.iter (fun name shape -> Shape.Store.set ~name shape) shapes;
405444
let context = Generate.start () in
406445
let toplevel_name, generated_js =
407446
Generate.f
@@ -423,7 +462,7 @@ let run
423462
Generate.output ch ~context;
424463
close_out ch);
425464
if times () then Format.eprintf "compilation: %a@." Timer.print t;
426-
generated_js
465+
generated_js, shapes
427466
in
428467
(if runtime_only
429468
then (
@@ -479,7 +518,7 @@ let run
479518
then Some (Filename.temp_file unit_name ".wasm.map")
480519
else None)
481520
@@ fun opt_tmp_map_file ->
482-
let unit_data =
521+
let unit_data, shapes =
483522
Fs.with_intermediate_file (Filename.temp_file unit_name ".wasm")
484523
@@ fun input_file ->
485524
opt_with
@@ -488,7 +527,7 @@ let run
488527
then Some (Filename.temp_file unit_name ".wasm.map")
489528
else None)
490529
@@ fun opt_input_sourcemap ->
491-
let fragments =
530+
let fragments, shapes =
492531
output
493532
code
494533
~wat_file:
@@ -504,9 +543,9 @@ let run
504543
~input_file
505544
~output_file:tmp_wasm_file
506545
();
507-
{ Link.unit_name; unit_info; fragments }
546+
{ Link.unit_name; unit_info; fragments }, shapes
508547
in
509-
cont unit_data unit_name tmp_wasm_file opt_tmp_map_file
548+
cont unit_data unit_name tmp_wasm_file opt_tmp_map_file shapes
510549
in
511550
(match kind with
512551
| `Exe ->
@@ -537,7 +576,7 @@ let run
537576
then Some (Filename.temp_file "code" ".wasm.map")
538577
else None
539578
in
540-
let generated_js =
579+
let generated_js, _shapes =
541580
output
542581
code
543582
~unit_name:None
@@ -601,8 +640,9 @@ let run
601640
@@ fun tmp_output_file ->
602641
let z = Zip.open_out tmp_output_file in
603642
let compile_cmo' z cmo =
604-
compile_cmo cmo (fun unit_data _ tmp_wasm_file opt_tmp_map_file ->
643+
compile_cmo cmo (fun unit_data _ tmp_wasm_file opt_tmp_map_file shapes ->
605644
Zip.add_file z ~name:"code.wasm" ~file:tmp_wasm_file;
645+
Zip.add_entry z ~name:"shapes.sexp" ~contents:(string_of_shapes shapes);
606646
add_source_map sourcemap_don't_inline_content z (`File opt_tmp_map_file);
607647
unit_data)
608648
in
@@ -618,8 +658,8 @@ let run
618658
List.fold_right
619659
~f:(fun cmo cont l ->
620660
compile_cmo cmo
621-
@@ fun unit_data unit_name tmp_wasm_file opt_tmp_map_file ->
622-
cont ((unit_data, unit_name, tmp_wasm_file, opt_tmp_map_file) :: l))
661+
@@ fun unit_data unit_name tmp_wasm_file opt_tmp_map_file shapes ->
662+
cont ((unit_data, unit_name, tmp_wasm_file, opt_tmp_map_file, shapes) :: l))
623663
cma.lib_units
624664
~init:(fun l ->
625665
Fs.with_intermediate_file (Filename.temp_file "wasm" ".wasm")
@@ -628,7 +668,7 @@ let run
628668
let source_map =
629669
Wasm_link.f
630670
(List.map
631-
~f:(fun (_, _, file, opt_source_map) ->
671+
~f:(fun (_, _, file, opt_source_map, _) ->
632672
{ Wasm_link.module_name = "OCaml"
633673
; file
634674
; code = None
@@ -641,10 +681,17 @@ let run
641681
~output_file:tmp_wasm_file
642682
in
643683
Zip.add_file z ~name:"code.wasm" ~file:tmp_wasm_file;
684+
let shapes =
685+
List.fold_left
686+
~init:StringMap.empty
687+
~f:(fun acc (_, _, _, _, shapes) -> merge_shape acc shapes)
688+
l
689+
in
690+
Zip.add_entry z ~name:"shapes.sexp" ~contents:(string_of_shapes shapes);
644691
if enable_source_maps
645692
then
646693
add_source_map sourcemap_don't_inline_content z (`Source_map source_map);
647-
List.map ~f:(fun (unit_data, _, _, _) -> unit_data) l)
694+
List.map ~f:(fun (unit_data, _, _, _, _) -> unit_data) l)
648695
[]
649696
in
650697
Link.add_info z ~build_info:(Build_info.create `Cma) ~unit_data ();

compiler/lib-wasm/link.ml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,7 @@ let info_from_sexp info =
345345
let build_info =
346346
info |> member "build_info" |> mandatory (single Build_info.from_sexp)
347347
in
348+
348349
let predefined_exceptions =
349350
info
350351
|> member "predefined_exceptions"

compiler/lib/driver.ml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,8 @@ let collects_shapes ~shapes (p : Code.program) =
120120
| Utf (Utf8 s) -> s
121121
in
122122
shapes := StringMap.add name block !shapes
123+
| Code.Let (_, Prim (Extern "caml_set_global", [ Pc (String name); Pv block ]))
124+
-> shapes := StringMap.add name block !shapes
123125
| _ -> ()))
124126
p.blocks;
125127
let map =

compiler/lib/parse_bytecode.ml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -842,6 +842,9 @@ let get_global state instrs i =
842842
let x, state = State.fresh_var state in
843843
if debug_parser ()
844844
then Format.printf "%a = get_global(%s)@." Var.print x name;
845+
(match Shape.Store.load ~name with
846+
| None -> ()
847+
| Some shape -> Shape.State.assign x shape);
845848
( x
846849
, state
847850
, Let (x, Prim (Extern "caml_get_global", [ Pc (String name) ])) :: instrs

0 commit comments

Comments
 (0)