Skip to content

Commit bf0a511

Browse files
committed
WASI runtime
1 parent a81e1b2 commit bf0a511

File tree

55 files changed

+4366
-193
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+4366
-193
lines changed

compiler/bin-wasm_of_ocaml/cmd_arg.ml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ let normalize_effects (effects : [ `Disabled | `Cps | `Jspi ] option) common :
4646
[--effects cps] *)
4747
if List.mem ~eq:String.equal "effects" common.Jsoo_cmdline.Arg.optim.enable
4848
then `Cps
49+
else if List.mem ~eq:String.equal "wasi" common.Jsoo_cmdline.Arg.optim.enable
50+
then `Disabled
4951
else `Jspi
5052
| Some ((`Disabled | `Cps | `Jspi) as e) -> e
5153

compiler/bin-wasm_of_ocaml/compile.ml

Lines changed: 33 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -81,9 +81,11 @@ let preprocessor_variables () =
8181
[ ( "effects"
8282
, Wat_preprocess.String
8383
(match Config.effects () with
84-
| `Disabled | `Jspi -> "jspi"
84+
| `Disabled -> "disabled"
85+
| `Jspi -> "jspi"
8586
| `Cps -> "cps"
8687
| `Double_translation -> assert false) )
88+
; "wasi", Wat_preprocess.Bool (Config.Flag.wasi ())
8789
; "exnref", Wat_preprocess.Bool (Config.Flag.exnref ())
8890
]
8991

@@ -116,21 +118,26 @@ let build_runtime ~runtime_file =
116118
; file = module_name ^ ".wat"
117119
; source = Contents contents
118120
})
119-
Runtime_files.wat_files
121+
(if Config.Flag.wasi ()
122+
then ("libc", Runtime_files.wasi_libc) :: Runtime_files.wat_files
123+
else Runtime_files.wat_files)
120124
in
121125
Runtime.build
122126
~link_options:[ "-g" ]
123127
~opt_options:[ "-g"; "-O2" ]
124128
~variables
125129
~allowed_imports:
126130
(Some
127-
[ "bindings"
128-
; "Math"
129-
; "js"
130-
; "wasm:js-string"
131-
; "wasm:text-encoder"
132-
; "wasm:text-decoder"
133-
])
131+
(if Config.Flag.wasi ()
132+
then [ "wasi_snapshot_preview1"; "OCaml" ]
133+
else
134+
[ "bindings"
135+
; "Math"
136+
; "js"
137+
; "wasm:js-string"
138+
; "wasm:text-encoder"
139+
; "wasm:text-decoder"
140+
]))
134141
~inputs
135142
~output_file:runtime_file
136143

@@ -186,7 +193,10 @@ let link_and_optimize
186193
let t = Timer.make ~get_time:Unix.time () in
187194
let primitives =
188195
Binaryen.dead_code_elimination
189-
~dependencies:Runtime_files.dependencies
196+
~dependencies:
197+
(if Config.Flag.wasi ()
198+
then Runtime_files.wasi_dependencies
199+
else Runtime_files.dependencies)
190200
~opt_input_sourcemap:opt_temp_sourcemap
191201
~opt_output_sourcemap:opt_temp_sourcemap'
192202
~input_file:temp_file
@@ -303,7 +313,13 @@ let build_js_runtime ~primitives ?runtime_arguments () =
303313
| _ -> assert false
304314
in
305315
let init_fun =
306-
match Parse_js.parse (Parse_js.Lexer.of_string Runtime_files.js_runtime) with
316+
match
317+
Parse_js.parse
318+
(Parse_js.Lexer.of_string
319+
(if Config.Flag.wasi ()
320+
then Runtime_files.js_wasi_launcher
321+
else Runtime_files.js_launcher))
322+
with
307323
| [ (Expression_statement f, _) ] -> f
308324
| _ -> assert false
309325
in
@@ -601,9 +617,12 @@ let run
601617
if binaryen_times ()
602618
then Format.eprintf " link_and_optimize: %a@." Timer.print t2;
603619
let wasm_name =
604-
Printf.sprintf
605-
"code-%s"
606-
(String.sub (Digest.to_hex (Digest.file tmp_wasm_file)) ~pos:0 ~len:20)
620+
if Config.Flag.wasi ()
621+
then "code"
622+
else
623+
Printf.sprintf
624+
"code-%s"
625+
(String.sub (Digest.to_hex (Digest.file tmp_wasm_file)) ~pos:0 ~len:20)
607626
in
608627
let tmp_wasm_file' = Filename.concat tmp_dir (wasm_name ^ ".wasm") in
609628
Sys.rename tmp_wasm_file tmp_wasm_file';

compiler/bin-wasm_of_ocaml/dune

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@
2828
gen/gen.exe
2929
../../runtime/wasm/runtime.js
3030
../../runtime/wasm/deps.json
31+
../../runtime/wasm/runtime-wasi.js
32+
../../runtime/wasm/deps-wasi.json
33+
../../runtime/wasm/libc.wasm
3134
(glob_files ../../runtime/wasm/*.wat)
3235
(glob_files ../../runtime/wasm/runtime-*.wasm))
3336
(action

compiler/bin-wasm_of_ocaml/gen/gen.ml

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -77,13 +77,26 @@ let check_js_file fname =
7777

7878
let default_flags = [ "exnref", `B false ]
7979

80-
let interesting_runtimes = [ [ "effects", `S "jspi" ]; [ "effects", `S "cps" ] ]
80+
let interesting_runtimes =
81+
[ [ "effects", `S "jspi"; "wasi", `B false ]
82+
; [ "effects", `S "cps"; "wasi", `B false ]
83+
; [ "effects", `S "disabled"; "wasi", `B true ]
84+
; [ "effects", `S "cps"; "wasi", `B true ]
85+
]
86+
87+
let defaults = [ "effects", "disabled" ]
8188

8289
let name_runtime standard l =
8390
let flags =
8491
List.filter_map l ~f:(fun (k, v) ->
8592
match v with
86-
| `S s -> Some s
93+
| `S s ->
94+
if
95+
List.exists
96+
~f:(fun (k', s') -> String.equal k k' && String.equal s s')
97+
defaults
98+
then None
99+
else Some s
87100
| `B b -> if b then Some k else None)
88101
in
89102
String.concat ~sep:"-" ("runtime" :: (if standard then [ "standard" ] else flags))
@@ -110,25 +123,31 @@ let print_flags f flags =
110123

111124
let () =
112125
let () = set_binary_mode_out stdout true in
113-
let js_runtime, deps, wat_files, runtimes =
126+
let js_launcher, deps, js_wasi_launcher, wasi_deps, wasi_libc, wat_files, runtimes =
114127
match Array.to_list Sys.argv with
115-
| _ :: js_runtime :: deps :: rest ->
116-
assert (Filename.check_suffix js_runtime ".js");
128+
| _ :: js_launcher :: deps :: js_wasi_launcher :: wasi_deps :: wasi_libc :: rest ->
129+
assert (Filename.check_suffix js_launcher ".js");
130+
assert (Filename.check_suffix js_wasi_launcher ".js");
117131
assert (Filename.check_suffix deps ".json");
132+
assert (Filename.check_suffix wasi_deps ".json");
118133
let wat_files, rest =
119134
List.partition rest ~f:(fun f -> Filename.check_suffix f ".wat")
120135
in
121136
let wasm_files, rest =
122137
List.partition rest ~f:(fun f -> Filename.check_suffix f ".wasm")
123138
in
124139
assert (List.is_empty rest);
125-
js_runtime, deps, wat_files, wasm_files
140+
js_launcher, deps, js_wasi_launcher, wasi_deps, wasi_libc, wat_files, wasm_files
126141
| _ -> assert false
127142
in
128-
check_js_file js_runtime;
143+
check_js_file js_launcher;
144+
check_js_file js_wasi_launcher;
129145
Format.printf "open Wasm_of_ocaml_compiler@.";
130-
Format.printf "let js_runtime = {|\n%s\n|}@." (Fs.read_file js_runtime);
146+
Format.printf "let js_launcher = {|\n%s\n|}@." (Fs.read_file js_launcher);
131147
Format.printf "let dependencies = {|\n%s\n|}@." (Fs.read_file deps);
148+
Format.printf "let js_wasi_launcher = {|\n%s\n|}@." (Fs.read_file js_wasi_launcher);
149+
Format.printf "let wasi_dependencies = {|\n%s\n|}@." (Fs.read_file wasi_deps);
150+
Format.printf "let wasi_libc = %S@." (Fs.read_file wasi_libc);
132151
Format.printf
133152
"let wat_files = [%a]@."
134153
(Format.pp_print_list (fun f file ->

compiler/lib-wasm/binaryen.ml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ let common_options () =
3838
; "--enable-bulk-memory"
3939
; "--enable-nontrapping-float-to-int"
4040
; "--enable-strings"
41+
; "--enable-multimemory" (* To keep wasm-merge happy *)
4142
]
4243
in
4344
let l = if Config.Flag.pretty () then "-g" :: l else l in

compiler/lib-wasm/gc_target.ml

Lines changed: 56 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1331,8 +1331,8 @@ module Math = struct
13311331
let unary name x =
13321332
let* f =
13331333
register_import
1334-
~allow_tail_call:false
1335-
~import_module:"Math"
1334+
~allow_tail_call:(Config.Flag.wasi ())
1335+
~import_module:(if Config.Flag.wasi () then "env" else "Math")
13361336
~name
13371337
(Fun (float_func_type 1))
13381338
in
@@ -1380,8 +1380,8 @@ module Math = struct
13801380
let binary name x y =
13811381
let* f =
13821382
register_import
1383-
~allow_tail_call:false
1384-
~import_module:"Math"
1383+
~allow_tail_call:(Config.Flag.wasi ())
1384+
~import_module:(if Config.Flag.wasi () then "env" else "Math")
13851385
~name
13861386
(Fun (float_func_type 2))
13871387
in
@@ -1408,6 +1408,18 @@ module Bigarray = struct
14081408
(Memory.wasm_struct_get ty (Memory.wasm_cast ty a) 3)
14091409
(Arith.const (Int32.of_int n))
14101410

1411+
let little_endian () =
1412+
if Config.Flag.wasi ()
1413+
then Arith.(const 1l)
1414+
else
1415+
let* le =
1416+
register_import
1417+
~import_module:"bindings"
1418+
~name:"littleEndian"
1419+
(Global { mut = false; typ = I32 })
1420+
in
1421+
return (W.GlobalGet le)
1422+
14111423
let get_at_offset ~(kind : Typing.Bigarray.kind) a i =
14121424
let name, (typ : Wasm_ast.value_type), size, box =
14131425
match kind with
@@ -1448,19 +1460,14 @@ module Bigarray = struct
14481460
return (W.F64PromoteF32 x) )
14491461
| Complex64 -> "dv_get_f64", F64, 4, Fun.id
14501462
in
1451-
let* little_endian =
1452-
register_import
1453-
~import_module:"bindings"
1454-
~name:"littleEndian"
1455-
(Global { mut = false; typ = I32 })
1456-
in
1463+
let* little_endian = little_endian () in
14571464
let* f =
14581465
register_import
1459-
~import_module:"bindings"
1466+
~import_module:(if Config.Flag.wasi () then "env" else "bindings")
14601467
~name
14611468
(Fun
14621469
{ W.params =
1463-
Ref { nullable = true; typ = Extern }
1470+
Ref { nullable = not (Config.Flag.wasi ()); typ = Extern }
14641471
:: I32
14651472
:: (if size = 0 then [] else [ I32 ])
14661473
; result = [ typ ]
@@ -1482,14 +1489,12 @@ module Bigarray = struct
14821489
| Nativeint
14831490
| Float16 ->
14841491
box
1485-
(return
1486-
(W.Call
1487-
(f, ta :: ofs :: (if size = 0 then [] else [ W.GlobalGet little_endian ]))))
1492+
(return (W.Call (f, ta :: ofs :: (if size = 0 then [] else [ little_endian ]))))
14881493
| Complex32 | Complex64 ->
14891494
let delta = Int32.shift_left 1l (size - 1) in
14901495
let* ofs' = Arith.(return ofs + const delta) in
1491-
let* x = box (return (W.Call (f, [ ta; ofs; W.GlobalGet little_endian ]))) in
1492-
let* y = box (return (W.Call (f, [ ta; ofs'; W.GlobalGet little_endian ]))) in
1496+
let* x = box (return (W.Call (f, [ ta; ofs; little_endian ]))) in
1497+
let* y = box (return (W.Call (f, [ ta; ofs'; little_endian ]))) in
14931498
let* ty = Type.float_array_type in
14941499
return (W.ArrayNewFixed (ty, [ x; y ]))
14951500

@@ -1534,19 +1539,14 @@ module Bigarray = struct
15341539
let* ty = Type.bigarray_type in
15351540
let* ta = Memory.wasm_struct_get ty (Memory.wasm_cast ty a) 2 in
15361541
let* ofs = Arith.(i lsl const (Int32.of_int size)) in
1537-
let* little_endian =
1538-
register_import
1539-
~import_module:"bindings"
1540-
~name:"littleEndian"
1541-
(Global { mut = false; typ = I32 })
1542-
in
1542+
let* little_endian = little_endian () in
15431543
let* f =
15441544
register_import
1545-
~import_module:"bindings"
1545+
~import_module:(if Config.Flag.wasi () then "env" else "bindings")
15461546
~name
15471547
(Fun
15481548
{ W.params =
1549-
Ref { nullable = true; typ = Extern }
1549+
Ref { nullable = not (Config.Flag.wasi ()); typ = Extern }
15501550
:: I32
15511551
:: typ
15521552
:: (if size = 0 then [] else [ I32 ])
@@ -1567,18 +1567,15 @@ module Bigarray = struct
15671567
| Float16 ->
15681568
let* v = unbox v in
15691569
instr
1570-
(W.CallInstr
1571-
( f
1572-
, ta :: ofs :: v :: (if size = 0 then [] else [ W.GlobalGet little_endian ])
1573-
))
1570+
(W.CallInstr (f, ta :: ofs :: v :: (if size = 0 then [] else [ little_endian ])))
15741571
| Complex32 | Complex64 ->
15751572
let delta = Int32.shift_left 1l (size - 1) in
15761573
let* ofs' = Arith.(return ofs + const delta) in
15771574
let ty = Type.float_array_type in
15781575
let* x = unbox (Memory.wasm_array_get ~ty v (Arith.const 0l)) in
1579-
let* () = instr (W.CallInstr (f, [ ta; ofs; x; W.GlobalGet little_endian ])) in
1576+
let* () = instr (W.CallInstr (f, [ ta; ofs; x; little_endian ])) in
15801577
let* y = unbox (Memory.wasm_array_get ~ty v (Arith.const 1l)) in
1581-
instr (W.CallInstr (f, [ ta; ofs'; y; W.GlobalGet little_endian ]))
1578+
instr (W.CallInstr (f, [ ta; ofs'; y; little_endian ]))
15821579

15831580
let offset ~bound_error_index ~(layout : Typing.Bigarray.layout) ta ~indices =
15841581
let l =
@@ -1951,21 +1948,34 @@ let handle_exceptions ~result_typ ~fall_through ~context body x exn_handler =
19511948
x
19521949
(block_expr
19531950
{ params = []; result = [ Type.value ] }
1954-
(let* exn =
1955-
block_expr
1956-
{ params = []; result = [ externref ] }
1957-
(let* e =
1958-
try_expr
1959-
{ params = []; result = [ externref ] }
1960-
(body
1961-
~result_typ:[ externref ]
1962-
~fall_through:`Skip
1963-
~context:(`Skip :: `Skip :: `Catch :: context))
1964-
[ ocaml_tag, 1, Type.value; js_tag, 0, externref ]
1965-
in
1966-
instr (W.Push e))
1967-
in
1968-
instr (W.CallInstr (f, [ exn ]))))
1951+
(if Config.Flag.wasi ()
1952+
then
1953+
let* e =
1954+
try_expr
1955+
{ params = []; result = [ Type.value ] }
1956+
(body
1957+
~result_typ:[ Type.value ]
1958+
~fall_through:`Skip
1959+
~context:(`Skip :: `Catch :: context))
1960+
[ ocaml_tag, 0, Type.value ]
1961+
in
1962+
instr (W.Push e)
1963+
else
1964+
let* exn =
1965+
block_expr
1966+
{ params = []; result = [ externref ] }
1967+
(let* e =
1968+
try_expr
1969+
{ params = []; result = [ externref ] }
1970+
(body
1971+
~result_typ:[ externref ]
1972+
~fall_through:`Skip
1973+
~context:(`Skip :: `Skip :: `Catch :: context))
1974+
[ ocaml_tag, 1, Type.value; js_tag, 0, externref ]
1975+
in
1976+
instr (W.Push e))
1977+
in
1978+
instr (W.CallInstr (f, [ exn ]))))
19691979
in
19701980
let* () = no_event in
19711981
exn_handler ~result_typ ~fall_through ~context)

compiler/lib-wasm/generate.ml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,7 @@ module Generate (Target : Target_sig.S) = struct
225225
(if negate then Arith.( <> ) else Arith.( = ))
226226
Arith.(transl_prim_arg ctx ~typ:(Int Unnormalized) x lsl const 1l)
227227
Arith.(transl_prim_arg ctx ~typ:(Int Unnormalized) y lsl const 1l)
228-
| Top, Top ->
228+
| Top, Top when not (Config.Flag.wasi ()) ->
229229
Value.js_eqeqeq
230230
~negate
231231
(transl_prim_arg ctx ~typ:Top x)
@@ -236,7 +236,8 @@ module Generate (Target : Target_sig.S) = struct
236236
(transl_prim_arg ctx ~typ:Top x)
237237
(transl_prim_arg ctx ~typ:Top y)
238238
| (Int _ | Number _ | Tuple _ | Bigarray _), _
239-
| _, (Int _ | Number _ | Tuple _ | Bigarray _) ->
239+
| _, (Int _ | Number _ | Tuple _ | Bigarray _)
240+
| Top, Top (* when wasi is enabled *) ->
240241
(* Only Top may contain JavaScript values *)
241242
(if negate then Value.phys_neq else Value.phys_eq)
242243
(transl_prim_arg ctx ~typ:Top x)

compiler/lib/config.ml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,8 @@ module Flag = struct
108108
let load_shapes_auto = o ~name:"load-shapes-auto" ~default:false
109109

110110
let exnref = o ~name:"exnref" ~default:false
111+
112+
let wasi = o ~name:"wasi" ~default:false
111113
end
112114

113115
module Param = struct

compiler/lib/config.mli

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,8 @@ module Flag : sig
7878

7979
val exnref : unit -> bool
8080

81+
val wasi : unit -> bool
82+
8183
val enable : string -> unit
8284

8385
val disable : string -> unit

0 commit comments

Comments
 (0)