Skip to content

Commit

Permalink
Add a wat2wasm subcommand
Browse files Browse the repository at this point in the history
  • Loading branch information
epatrizio committed May 6, 2024
1 parent a6e9274 commit f8102ca
Show file tree
Hide file tree
Showing 8 changed files with 203 additions and 6 deletions.
6 changes: 5 additions & 1 deletion example/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,13 @@ COMMANDS
Validate a module

wasm2wat [OPTION]… [ARG]…
Generate a text format file (.wat) file from a binary format file
Generate a text format file (.wat) from a binary format file
(.wasm)

wat2wasm [OPTION]… [ARG]…
Generate a binary format file (.wasm) from a text format file
(.wat)

COMMON OPTIONS
--help[=FMT] (default=auto)
Show this help in format FMT. The value FMT must be one of auto,
Expand Down
4 changes: 2 additions & 2 deletions example/wasm2wat/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ $ owi wasm2wat ./42.wasm
```sh
$ owi wasm2wat --help=plain
NAME
owi-wasm2wat - Generate a text format file (.wat) file from a binary
format file (.wasm)
owi-wasm2wat - Generate a text format file (.wat) from a binary format
file (.wasm)

SYNOPSIS
owi wasm2wat [OPTION]… [ARG]…
Expand Down
16 changes: 14 additions & 2 deletions src/bin/owi.ml
Original file line number Diff line number Diff line change
Expand Up @@ -191,14 +191,25 @@ let wasm2wat_cmd =
let open Cmdliner in
let info =
let doc =
"Generate a text format file (.wat) file from a binary format file \
(.wasm)"
"Generate a text format file (.wat) from a binary format file (.wasm)"
in
let man = [] @ shared_man in
Cmd.info "wasm2wat" ~version ~doc ~sdocs ~man
in
Cmd.v info Term.(const Cmd_wasm2wat.cmd $ files)

let wat2wasm_cmd =
let open Cmdliner in
let info =
let doc =
"Generate a binary format file (.wasm) from a text format file (.wat)"
in
let man = [] @ shared_man in
Cmd.info "wat2wasm" ~version ~doc ~sdocs ~man
in
Cmd.v info
Term.(const Cmd_wat2wasm.cmd $ profiling $ debug $ unsafe $ optimize $ files)

let cli =
let open Cmdliner in
let info =
Expand All @@ -219,6 +230,7 @@ let cli =
; sym_cmd
; validate_cmd
; wasm2wat_cmd
; wat2wasm_cmd
]

let exit_code =
Expand Down
152 changes: 152 additions & 0 deletions src/binary_to_text/binary_encoder.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
(* SPDX-License-Identifier: AGPL-3.0-or-later *)
(* Copyright © 2021-2024 OCamlPro *)
(* Written by the Owi programmers *)

open Binary
open Syntax
open Types

let magic = "\x00\x61\x73\x6d"

let version = "\x01\x00\x00\x00"

(* passer out_channel et pas passer par buffer
int -> char
let char_of_int i = Char.chr (i land 0xff)
int64 -> string ?
TODO : U64_encode -> string ?
Idem : val_type -> char
let valtype_encode vt =
...
*)

let add_int i buf =
let c = Char.chr (i land 0xff) in
Buffer.add_char buf c

let rec write_U64 i buf =
let b = Int64.to_int (Int64.logand i 0x7fL) in
if 0L <= i && i < 128L then add_int b buf
else (
add_int (b lor 0x80) buf;
write_U64 (Int64.shift_right_logical i 7) buf )

let write_U32 i = write_U64 (Int64.logand (Int64.of_int32 i) 0xffffffffL)

let indice_encode (id : Types.binary Types.indice) buf =
let (Raw id) = id in
write_U32 (Int32.of_int id) buf

let valtype_encode vt buf =
let c =
match vt with
| Num_type I32 -> '\x7F'
| Num_type I64 -> '\x7E'
| Num_type F32 -> '\x7D'
| Num_type F64 -> '\x7C'
| Ref_type (Null, Func_ht) -> '\x70'
| Ref_type (Null, Extern_ht) -> '\x6F'
| _ -> assert false (* vecttype v128 '\x7B' *)
in
Buffer.add_char buf c

let mut_encode mut buf =
let c = match mut with Const -> '\x00' | Var -> '\x01' in
Buffer.add_char buf c

(* let vector_encode len fct_encode buf =
write_U32 (Int32.of_int len) buf;
iter fct_encode buf
TODO
*)

let section_encode id encode_func data buf =
let section_buf = Buffer.create 16 in
encode_func data section_buf;
add_int id buf;
write_U32 (Int32.of_int (Buffer.length section_buf)) buf;
Buffer.add_buffer buf section_buf

(* type: section 1 *)
(* let type_encode func =
let { Named.values; _ } = func in
let len = List.length values in
let buf = Buffer.create 32 in
write_U32 (Int32.of_int len) buf;
List.iter
(fun v ->
Buffer.add_char buf '\x60';
let { Types.type_f = t; _ } = Indexed.get v in
match t with
| Bt_raw _t -> (* TODO *)
write_U32 0l buf;
write_U32 0l buf
| Bt_ind _ -> assert false
)
values;
buf *)

(* function: section 3 *)
let function_encode func buf =
let { Named.values; _ } = func in
let len = List.length values in
write_U32 (Int32.of_int len) buf;
List.iter
(fun v ->
let i = Indexed.get_index v in
write_U32 (Int32.of_int i) buf )
values

(* start: section 8 *)
let start_encode int_opt buf =
match int_opt with
| None -> ()
| Some funcidx -> write_U32 (Int32.of_int funcidx) buf

let encode (modul : Binary.modul) =
let buf = Buffer.create 256 in
Buffer.add_string buf magic;
Buffer.add_string buf version;
(* section_encode 1 type_encode modul.func buf; *)
section_encode 3 function_encode modul.func buf;
section_encode 8 start_encode modul.start buf;

(* function_encode modul.func buf; *)
(* table_encode modul.table buf; *)
(* memory_encode modul.mem buf; *)
(* global_encode modul.global buf; *)
(* export_encode modul.exports buf; *)
(* start_encode modul.start buf; *)
(* element_encode modul.elem buf; *)
(* data_encode modul.data buf; *)
Buffer.contents buf

(*
0 custom section
1 type section ?? dep autres
2 import section ?? dep autres
3 function section
4 table section
5 memory section
6 global section
7 export section
8 start section
9 element section
10 code section ?? dep autres
11 data section
12 data count section -- *)

let write_file filename content =
let filename = Fpath.filename filename in
let filename = filename ^ ".wasm" in
let oc = Out_channel.open_bin filename in
Out_channel.output_string oc content;
Out_channel.close oc

let convert (filename : Fpath.t) ~unsafe ~optimize m =
let+ m = Compile.Text.until_optimize ~unsafe ~optimize m in
let content = encode m in
let () = write_file filename content in
()
18 changes: 18 additions & 0 deletions src/cmd/cmd_wat2wasm.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
(* SPDX-License-Identifier: AGPL-3.0-or-later *)
(* Copyright © 2021-2024 OCamlPro *)
(* Written by the Owi programmers *)

open Syntax

let cmd_one ~unsafe ~optimize file =
let ext = Fpath.get_ext file in
match ext with
| ".wat" ->
let* modul = Parse.Text.Module.from_file file in
Binary_encoder.convert file ~unsafe ~optimize modul
| ext -> Error (`Unsupported_file_extension ext)

let cmd profiling debug unsafe optimize files =
if profiling then Log.profiling_on := true;
if debug then Log.debug_on := true;
list_iter (cmd_one ~unsafe ~optimize) files
5 changes: 5 additions & 0 deletions src/cmd/cmd_wat2wasm.mli
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
(* SPDX-License-Identifier: AGPL-3.0-or-later *)
(* Copyright © 2021-2024 OCamlPro *)
(* Written by the Owi programmers *)

val cmd : bool -> bool -> bool -> bool -> Fpath.t list -> unit Result.t
2 changes: 2 additions & 0 deletions src/dune
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
binary_parser
binary_to_text
binary_types
binary_encoder
c_instrumentor
c_share
c_share_site
Expand All @@ -21,6 +22,7 @@
cmd_sym
cmd_validate
cmd_wasm2wat
cmd_wat2wasm
compile
concrete
concrete_choice
Expand Down
6 changes: 5 additions & 1 deletion test/help/help.t
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,13 @@ no subcommand should print help
Validate a module

wasm2wat [OPTION]… [ARG]…
Generate a text format file (.wat) file from a binary format file
Generate a text format file (.wat) from a binary format file
(.wasm)

wat2wasm [OPTION]… [ARG]…
Generate a binary format file (.wasm) from a text format file
(.wat)

COMMON OPTIONS
--help[=FMT] (default=auto)
Show this help in format FMT. The value FMT must be one of auto,
Expand Down

0 comments on commit f8102ca

Please sign in to comment.