Skip to content

Commit b32bc07

Browse files
committed
WASI runtime
1 parent 53a99e1 commit b32bc07

File tree

55 files changed

+4352
-164
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

+4352
-164
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: 40 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1312,7 +1312,12 @@ module Math = struct
13121312
{ W.params = List.init ~len:n ~f:(fun _ : W.value_type -> F64); result = [ F64 ] }
13131313

13141314
let unary name x =
1315-
let* f = register_import ~import_module:"Math" ~name (Fun (float_func_type 1)) in
1315+
let* f =
1316+
register_import
1317+
~import_module:(if Config.Flag.wasi () then "env" else "Math")
1318+
~name
1319+
(Fun (float_func_type 1))
1320+
in
13161321
let* x = x in
13171322
return (W.Call (f, [ x ]))
13181323

@@ -1355,7 +1360,12 @@ module Math = struct
13551360
let log10 f = unary "log10" f
13561361

13571362
let binary name x y =
1358-
let* f = register_import ~import_module:"Math" ~name (Fun (float_func_type 2)) in
1363+
let* f =
1364+
register_import
1365+
~import_module:(if Config.Flag.wasi () then "env" else "Math")
1366+
~name
1367+
(Fun (float_func_type 2))
1368+
in
13591369
let* x = x in
13601370
let* y = y in
13611371
return (W.Call (f, [ x; y ]))
@@ -1698,21 +1708,34 @@ let handle_exceptions ~result_typ ~fall_through ~context body x exn_handler =
16981708
x
16991709
(block_expr
17001710
{ params = []; result = [ Type.value ] }
1701-
(let* exn =
1702-
block_expr
1703-
{ params = []; result = [ externref ] }
1704-
(let* e =
1705-
try_expr
1706-
{ params = []; result = [ externref ] }
1707-
(body
1708-
~result_typ:[ externref ]
1709-
~fall_through:`Skip
1710-
~context:(`Skip :: `Skip :: `Catch :: context))
1711-
[ ocaml_tag, 1, Type.value; js_tag, 0, externref ]
1712-
in
1713-
instr (W.Push e))
1714-
in
1715-
instr (W.CallInstr (f, [ exn ]))))
1711+
(if Config.Flag.wasi ()
1712+
then
1713+
let* e =
1714+
try_expr
1715+
{ params = []; result = [ Type.value ] }
1716+
(body
1717+
~result_typ:[ Type.value ]
1718+
~fall_through:`Skip
1719+
~context:(`Skip :: `Catch :: context))
1720+
[ ocaml_tag, 0, Type.value ]
1721+
in
1722+
instr (W.Push e)
1723+
else
1724+
let* exn =
1725+
block_expr
1726+
{ params = []; result = [ externref ] }
1727+
(let* e =
1728+
try_expr
1729+
{ params = []; result = [ externref ] }
1730+
(body
1731+
~result_typ:[ externref ]
1732+
~fall_through:`Skip
1733+
~context:(`Skip :: `Skip :: `Catch :: context))
1734+
[ ocaml_tag, 1, Type.value; js_tag, 0, externref ]
1735+
in
1736+
instr (W.Push e))
1737+
in
1738+
instr (W.CallInstr (f, [ exn ]))))
17161739
in
17171740
let* () = no_event in
17181741
exn_handler ~result_typ ~fall_through ~context)

compiler/lib-wasm/generate.ml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,7 @@ module Generate (Target : Target_sig.S) = struct
227227
(if negate then Arith.( <> ) else Arith.( = ))
228228
Arith.(transl_prim_arg ctx ~typ:(Int Unnormalized) x lsl const 1l)
229229
Arith.(transl_prim_arg ctx ~typ:(Int Unnormalized) y lsl const 1l)
230-
| Top, Top ->
230+
| Top, Top when not (Config.Flag.wasi ()) ->
231231
Value.js_eqeqeq
232232
~negate
233233
(transl_prim_arg ctx ~typ:Top x)
@@ -237,7 +237,9 @@ module Generate (Target : Target_sig.S) = struct
237237
(if negate then Value.phys_neq else Value.phys_eq)
238238
(transl_prim_arg ctx ~typ:Top x)
239239
(transl_prim_arg ctx ~typ:Top y)
240-
| (Int _ | Number _ | Tuple _), _ | _, (Int _ | Number _ | Tuple _) ->
240+
| (Int _ | Number _ | Tuple _), _
241+
| _, (Int _ | Number _ | Tuple _)
242+
| Top, Top (* when wasi is enabled *) ->
241243
(* Only Top may contain JavaScript values *)
242244
(if negate then Value.phys_neq else Value.phys_eq)
243245
(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

compiler/tests-jsoo/dune

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
(enabled_if
1212
(>= %{ocaml_version} 4.14))
1313
(inline_tests
14+
(deps
15+
(sandbox preserve_file_kind))
1416
(modes js wasm best))
1517
(preprocess
1618
(pps ppx_expect)))
@@ -22,6 +24,8 @@
2224
(enabled_if
2325
(>= %{ocaml_version} 5.1.1))
2426
(inline_tests
27+
(deps
28+
(sandbox preserve_file_kind))
2529
(modes js wasm best))
2630
(preprocess
2731
(pps ppx_expect)))
@@ -33,6 +37,22 @@
3337
(enabled_if
3438
(>= %{ocaml_version} 5.1.1))
3539
(inline_tests
40+
(deps
41+
(sandbox preserve_file_kind))
42+
(modes js wasm best))
43+
(preprocess
44+
(pps ppx_expect)))
45+
46+
(library
47+
(name jsoo_testsuite_perms)
48+
(modules test_unix_perms)
49+
(libraries unix)
50+
;; WASI has no notion of file permissions (it uses capabilities instead)
51+
(enabled_if
52+
(<> %{profile} wasi))
53+
(inline_tests
54+
(deps
55+
(sandbox preserve_file_kind))
3656
(modes js wasm best))
3757
(preprocess
3858
(pps ppx_expect)))
@@ -48,13 +68,16 @@
4868
test_bigarray
4969
test_marshal_compressed
5070
test_parsing
71+
test_unix_perms
5172
calc_parser
5273
calc_lexer))
5374
(libraries unix compiler-libs.common js_of_ocaml-compiler)
5475
(foreign_stubs
5576
(language c)
5677
(names bigarray_stubs jsoo_runtime_stubs))
5778
(inline_tests
79+
(deps
80+
(sandbox preserve_file_kind))
5881
(modes js wasm best))
5982
(preprocess
6083
(pps ppx_expect)))

0 commit comments

Comments
 (0)