From 3e02a2e2d1edf5c2091e2a17b4b1b99f1182e6a9 Mon Sep 17 00:00:00 2001 From: Thomas Letan Date: Wed, 27 Jul 2022 18:28:13 +0200 Subject: [PATCH] WASM: Parse a chunked byte vector instead of a string --- src/lib_webassembly/bin/script/js.ml | 5 +- src/lib_webassembly/bin/script/run.ml | 2 +- src/lib_webassembly/bin/text/arrange.ml | 11 +- src/lib_webassembly/binary/decode.ml | 1543 +++++++++++++---------- src/lib_webassembly/binary/decode.mli | 16 +- src/lib_webassembly/binary/utf8.ml | 33 +- src/lib_webassembly/binary/utf8.mli | 2 +- 7 files changed, 936 insertions(+), 676 deletions(-) diff --git a/src/lib_webassembly/bin/script/js.ml b/src/lib_webassembly/bin/script/js.ml index 5fcfa032a5bd..177c34c0a190 100644 --- a/src/lib_webassembly/bin/script/js.ml +++ b/src/lib_webassembly/bin/script/js.ml @@ -716,7 +716,10 @@ let of_command mods cmd = let rec unquote def = match def.it with | Textual m -> Lwt.return m - | Encoded (_, bytes) -> Decode.decode ~name:"binary" ~bytes + | Encoded (_, bytes) -> + Decode.decode + ~name:"binary" + ~bytes:(Chunked_byte_vector.Lwt.of_string bytes) | Quoted (_, s) -> unquote (Parse.string_to_module s) in let* unquoted = unquote def in diff --git a/src/lib_webassembly/bin/script/run.ml b/src/lib_webassembly/bin/script/run.ml index 165266bb9d2e..ba455f0f525b 100644 --- a/src/lib_webassembly/bin/script/run.ml +++ b/src/lib_webassembly/bin/script/run.ml @@ -365,7 +365,7 @@ let rec run_definition def : Ast.module_ Lwt.t = | Textual m -> Lwt.return m | Encoded (name, bytes) -> let* () = trace_lwt "Decoding..." in - Decode.decode ~name ~bytes + Decode.decode ~name ~bytes:(Chunked_byte_vector.Lwt.of_string bytes) | Quoted (_, s) -> let* () = trace_lwt "Parsing quote..." in let def' = Parse.string_to_module s in diff --git a/src/lib_webassembly/bin/text/arrange.ml b/src/lib_webassembly/bin/text/arrange.ml index e2d11eefdca1..520b5ae4dbd9 100644 --- a/src/lib_webassembly/bin/text/arrange.ml +++ b/src/lib_webassembly/bin/text/arrange.ml @@ -752,7 +752,10 @@ let definition mode x_opt def = let rec unquote def = match def.it with | Textual m -> Lwt.return m - | Encoded (_, bytes) -> Decode.decode ~name:"" ~bytes + | Encoded (_, bytes) -> + Decode.decode + ~name:"" + ~bytes:(Chunked_byte_vector.Lwt.of_string bytes) | Quoted (_, s) -> unquote (Parse.string_to_module s) in let* unquoted = unquote def in @@ -762,7 +765,11 @@ let definition mode x_opt def = match def.it with | Textual m -> Encode.encode m | Encoded (_, bytes) -> - let* m = Decode.decode ~name:"" ~bytes in + let* m = + Decode.decode + ~name:"" + ~bytes:(Chunked_byte_vector.Lwt.of_string bytes) + in Encode.encode m | Quoted (_, s) -> unquote (Parse.string_to_module s) in diff --git a/src/lib_webassembly/binary/decode.ml b/src/lib_webassembly/binary/decode.ml index 24acac0f9fe3..c2371e05d730 100644 --- a/src/lib_webassembly/binary/decode.ml +++ b/src/lib_webassembly/binary/decode.ml @@ -3,15 +3,26 @@ open Binary_exn module Vector = Lazy_vector.LwtInt32Vector -type stream = {name : string; bytes : string; pos : int ref} +let lwt_ignore p = + let open Lwt.Syntax in + let* _ = p in + Lwt.return () + +type stream = { + name : string; + bytes : Chunked_byte_vector.Lwt.t; + mutable pos : int; +} -let make_stream ~name ~bytes = {name; bytes; pos = ref 0} +let make_stream ~name ~bytes = {name; bytes; pos = 0} let empty_block = Ast.Block_label 0l -let len s = String.length s.bytes +let len64 s = Chunked_byte_vector.Lwt.length s.bytes -let pos s = !(s.pos) +let len s = Int64.to_int @@ len64 s + +let pos s = s.pos let eos s = pos s = len s @@ -19,22 +30,39 @@ let check n s = if pos s + n > len s then raise EOS let skip n s = if n < 0 then raise EOS else check n s ; - s.pos := !(s.pos) + n + s.pos <- s.pos + n -let read s = Char.code s.bytes.[!(s.pos)] +let read s = Chunked_byte_vector.Lwt.load_byte s.bytes (Int64.of_int s.pos) -let peek s = if eos s then None else Some (read s) +let peek s = + let open Lwt.Syntax in + if eos s then Lwt.return None + else + let+ x = read s in + Some x let get s = + let open Lwt.Syntax in check 1 s ; - let b = read s in + let+ b = read s in skip 1 s ; b let get_string n s = - let i = pos s in - skip n s ; - String.sub s.bytes i n + let open Lwt.Syntax in + let rec ( -- ) x y () = + Lwt.return @@ if x = y then Lwt_seq.Nil else Lwt_seq.Cons (x, x + 1 -- y) + in + if n < 0 then raise EOS else check n s ; + let buffer = Bytes.make n '\000' in + let+ () = + Lwt_seq.iter_s + (fun i -> + let+ b = get s in + Bytes.set buffer i (Char.chr b)) + (0 -- n) + in + Bytes.to_string buffer (* Errors *) @@ -62,7 +90,10 @@ let get_string n = guard (get_string n) let skip n = guard (skip n) -let expect b s msg = require (guard get s = b) s (pos s - 1) msg +let expect b s msg = + let open Lwt.Syntax in + let+ x = guard get s in + require (x = b) s (pos s - 1) msg let illegal s pos b = error s pos ("illegal opcode " ^ string_of_byte b) @@ -70,8 +101,9 @@ let illegal2 s pos b n = error s pos ("illegal opcode " ^ string_of_byte b ^ " " ^ string_of_multi n) let at f s = + let open Lwt.Syntax in let left = pos s in - let x = f s in + let+ x = f s in let right = pos s in Source.(x @@ region s left right) @@ -87,30 +119,42 @@ let at_s f s = let u8 s = get s let u16 s = - let lo = u8 s in - let hi = u8 s in + let open Lwt.Syntax in + let* lo = u8 s in + let+ hi = u8 s in (hi lsl 8) + lo let u32 s = - let lo = Int32.of_int (u16 s) in - let hi = Int32.of_int (u16 s) in + let open Lwt.Syntax in + let* lo = u16 s in + let lo = Int32.of_int lo in + let+ hi = u16 s in + let hi = Int32.of_int hi in Int32.(add lo (shift_left hi 16)) let u64 s = - let lo = I64_convert.extend_i32_u (u32 s) in - let hi = I64_convert.extend_i32_u (u32 s) in + let open Lwt.Syntax in + let* lo = u32 s in + let lo = I64_convert.extend_i32_u lo in + let+ hi = u32 s in + let hi = I64_convert.extend_i32_u hi in Int64.(add lo (shift_left hi 32)) let rec vuN n s = + let open Lwt.Syntax in require (n > 0) s (pos s) "integer representation too long" ; - let b = u8 s in + let* b = u8 s in require (n >= 7 || b land 0x7f < 1 lsl n) s (pos s - 1) "integer too large" ; let x = Int64.of_int (b land 0x7f) in - if b land 0x80 = 0 then x else Int64.(logor x (shift_left (vuN (n - 7) s) 7)) + if b land 0x80 = 0 then Lwt.return x + else + let+ v = vuN (n - 7) s in + Int64.(logor x (shift_left v 7)) let rec vsN n s = + let open Lwt.Syntax in require (n > 0) s (pos s) "integer representation too long" ; - let b = u8 s in + let* b = u8 s in let mask = (-1 lsl (n - 1)) land 0x7f in require (n >= 7 || b land mask = 0 || b land mask = mask) @@ -119,51 +163,91 @@ let rec vsN n s = "integer too large" ; let x = Int64.of_int (b land 0x7f) in if b land 0x80 = 0 then - if b land 0x40 = 0 then x else Int64.(logor x (logxor (-1L) 0x7fL)) - else Int64.(logor x (shift_left (vsN (n - 7) s) 7)) + if b land 0x40 = 0 then Lwt.return x + else Lwt.return Int64.(logor x (logxor (-1L) 0x7fL)) + else + let+ v = vsN (n - 7) s in + Int64.(logor x (shift_left v 7)) -let vu1 s = Int64.to_int (vuN 1 s) +let vu1 s = + let open Lwt.Syntax in + let+ x = vuN 1 s in + Int64.to_int x -let vu32 s = Int64.to_int32 (vuN 32 s) +let vu32 s = + let open Lwt.Syntax in + let+ x = vuN 32 s in + Int64.to_int32 x -let vs7 s = Int64.to_int (vsN 7 s) +let vs7 s = + let open Lwt.Syntax in + let+ x = vsN 7 s in + Int64.to_int x -let vs32 s = Int64.to_int32 (vsN 32 s) +let vs32 s = + let open Lwt.Syntax in + let+ x = vsN 32 s in + Int64.to_int32 x -let vs33 s = I32_convert.wrap_i64 (vsN 33 s) +let vs33 s = + let open Lwt.Syntax in + let+ x = vsN 33 s in + I32_convert.wrap_i64 x let vs64 s = vsN 64 s -let f32 s = F32.of_bits (u32 s) +let f32 s = + let open Lwt.Syntax in + let+ x = u32 s in + F32.of_bits x -let f64 s = F64.of_bits (u64 s) +let f64 s = + let open Lwt.Syntax in + let+ x = u64 s in + F64.of_bits x -let v128 s = V128.of_bits (get_string (Types.vec_size Types.V128Type) s) +let v128 s = + let open Lwt.Syntax in + let+ x = get_string (Types.vec_size Types.V128Type) s in + V128.of_bits x let len32 s = + let open Lwt.Syntax in let pos = pos s in - let n = vu32 s in + let+ n = vu32 s in if I32.le_u n (Int32.of_int (len s - pos)) then Int32.to_int n else error s pos "length out of bounds" -let bool s = vu1 s = 1 +let bool s = + let open Lwt.Syntax in + let+ x = vu1 s in + x = 1 let rec list f n s = - if n = 0 then [] + let open Lwt.Syntax in + if n = 0 then Lwt.return [] else - let x = f s in - x :: list f (n - 1) s + let* x = f s in + let+ rst = list f (n - 1) s in + x :: rst -let opt f b s = if b then Some (f s) else None +let opt f b s = + let open Lwt.Syntax in + if b then + let+ x = f s in + Some x + else Lwt.return None let vec f s = - let n = len32 s in + let open Lwt.Syntax in + let* n = len32 s in list f n s let sized f s = - let size = len32 s in + let open Lwt.Syntax in + let* size = len32 s in let start = pos s in - let x = f size s in + let+ x = f size s in require (pos s = start + size) s start "section size mismatch" ; x @@ -179,13 +263,14 @@ let byte_vector_step vecs s = let open Lwt.Syntax in function | VKStart -> - let len = len32 s |> Int64.of_int in + let* len = len32 s in + let len = Int64.of_int len in let vector = Ast.alloc_data vecs len in VKRead (vector, 0L, len) |> Lwt.return | VKRead (vector, index, len) when Int64.compare index len >= 0 -> VKStop vector |> Lwt.return | VKRead (vector, index, len) -> - let c = get s in + let* c = get s in let+ () = Ast.add_to_data vecs vector index c in VKRead (vector, Int64.succ index, len) (* Final step, cannot reduce *) @@ -196,7 +281,9 @@ let byte_vector_step vecs s = open Types let num_type s = - match vs7 s with + let open Lwt.Syntax in + let+ x = vs7 s in + match x with | -0x01 -> I32Type | -0x02 -> I64Type | -0x03 -> F32Type @@ -204,46 +291,64 @@ let num_type s = | _ -> error s (pos s - 1) "malformed number type" let vec_type s = - match vs7 s with + let open Lwt.Syntax in + let+ x = vs7 s in + match x with | -0x05 -> V128Type | _ -> error s (pos s - 1) "malformed vector type" let ref_type s = - match vs7 s with + let open Lwt.Syntax in + let+ x = vs7 s in + match x with | -0x10 -> FuncRefType | -0x11 -> ExternRefType | _ -> error s (pos s - 1) "malformed reference type" let value_type s = - match peek s with - | Some n when n >= -0x04 land 0x7f -> NumType (num_type s) - | Some n when n >= -0x0f land 0x7f -> VecType (vec_type s) - | _ -> RefType (ref_type s) + let open Lwt.Syntax in + let* x = peek s in + match x with + | Some n when n >= -0x04 land 0x7f -> + let+ x = num_type s in + NumType x + | Some n when n >= -0x0f land 0x7f -> + let+ x = vec_type s in + VecType x + | _ -> + let+ x = ref_type s in + RefType x let limits vu s = - let has_max = bool s in - let min = vu s in - let max = opt vu has_max s in + let open Lwt.Syntax in + let* has_max = bool s in + let* min = vu s in + let+ max = opt vu has_max s in {min; max} let table_type s = - let t = ref_type s in - let lim = limits vu32 s in + let open Lwt.Syntax in + let* t = ref_type s in + let+ lim = limits vu32 s in TableType (lim, t) let memory_type s = - let lim = limits vu32 s in + let open Lwt.Syntax in + let+ lim = limits vu32 s in MemoryType lim let mutability s = - match u8 s with + let open Lwt.Syntax in + let+ x = u8 s in + match x with | 0 -> Immutable | 1 -> Mutable | _ -> error s (pos s - 1) "malformed mutability" let global_type s = - let t = value_type s in - let mut = mutability s in + let open Lwt.Syntax in + let* t = value_type s in + let+ mut = mutability s in GlobalType (t, mut) (* Decode instructions *) @@ -260,18 +365,25 @@ let end_ s = expect 0x0b s "END opcode expected" let zero s = expect 0x00 s "zero byte expected" let memop s = - let align = vu32 s in + let open Lwt.Syntax in + let* align = vu32 s in require (I32.le_u align 32l) s (pos s - 1) "malformed memop flags" ; - let offset = vu32 s in + let+ offset = vu32 s in (Int32.to_int align, offset) let block_type s = - match peek s with + let open Lwt.Syntax in + let* x = peek s in + match x with | Some 0x40 -> skip 1 s ; - ValBlockType None - | Some b when b land 0xc0 = 0x40 -> ValBlockType (Some (value_type s)) - | _ -> VarBlockType (at vs33 s) + Lwt.return @@ ValBlockType None + | Some b when b land 0xc0 = 0x40 -> + let+ x = value_type s in + ValBlockType (Some x) + | _ -> + let+ x = at vs33 s in + VarBlockType x type 'a lazy_stack = LazyStack of {length : int32; vector : 'a Vector.t} @@ -319,607 +431,660 @@ type instr_block_kont = | IKIf2 of block_type * int * block_label (** If .. else parsing step. *) let instr s pos tag = + let open Lwt.Syntax in match tag with (* These tags corresponds to resp. block, loop and if, and are now handled directly by the main step loop (see `IKBlock`, `IKLoop` and `IKIf1`. *) | 0x02 | 0x03 | 0x04 -> assert false - | 0x00 -> unreachable - | 0x01 -> nop + | 0x00 -> Lwt.return unreachable + | 0x01 -> Lwt.return nop | 0x05 -> error s pos "misplaced ELSE opcode" | (0x06 | 0x07 | 0x08 | 0x09 | 0x0a) as b -> illegal s pos b | 0x0b -> error s pos "misplaced END opcode" - | 0x0c -> br (at var s) - | 0x0d -> br_if (at var s) + | 0x0c -> + let+ x = at var s in + br x + | 0x0d -> + let+ x = at var s in + br_if x | 0x0e -> - let xs = vec (at var) s in - let x = at var s in + let* xs = vec (at var) s in + let+ x = at var s in br_table xs x - | 0x0f -> return - | 0x10 -> call (at var s) + | 0x0f -> Lwt.return return + | 0x10 -> + let+ x = at var s in + call x | 0x11 -> - let y = at var s in - let x = at var s in + let* y = at var s in + let+ x = at var s in call_indirect x y | (0x12 | 0x13 | 0x14 | 0x15 | 0x16 | 0x17 | 0x18 | 0x19) as b -> illegal s pos b - | 0x1a -> drop - | 0x1b -> select None - | 0x1c -> select (Some (vec value_type s)) + | 0x1a -> Lwt.return drop + | 0x1b -> Lwt.return @@ select None + | 0x1c -> + let+ x = vec value_type s in + select (Some x) | (0x1d | 0x1e | 0x1f) as b -> illegal s pos b - | 0x20 -> local_get (at var s) - | 0x21 -> local_set (at var s) - | 0x22 -> local_tee (at var s) - | 0x23 -> global_get (at var s) - | 0x24 -> global_set (at var s) - | 0x25 -> table_get (at var s) - | 0x26 -> table_set (at var s) + | 0x20 -> + let+ x = at var s in + local_get x + | 0x21 -> + let+ x = at var s in + local_set x + | 0x22 -> + let+ x = at var s in + local_tee x + | 0x23 -> + let+ x = at var s in + global_get x + | 0x24 -> + let+ x = at var s in + global_set x + | 0x25 -> + let+ x = at var s in + table_get x + | 0x26 -> + let+ x = at var s in + table_set x | 0x27 as b -> illegal s pos b | 0x28 -> - let a, o = memop s in + let+ a, o = memop s in i32_load a o | 0x29 -> - let a, o = memop s in + let+ a, o = memop s in i64_load a o | 0x2a -> - let a, o = memop s in + let+ a, o = memop s in f32_load a o | 0x2b -> - let a, o = memop s in + let+ a, o = memop s in f64_load a o | 0x2c -> - let a, o = memop s in + let+ a, o = memop s in i32_load8_s a o | 0x2d -> - let a, o = memop s in + let+ a, o = memop s in i32_load8_u a o | 0x2e -> - let a, o = memop s in + let+ a, o = memop s in i32_load16_s a o | 0x2f -> - let a, o = memop s in + let+ a, o = memop s in i32_load16_u a o | 0x30 -> - let a, o = memop s in + let+ a, o = memop s in i64_load8_s a o | 0x31 -> - let a, o = memop s in + let+ a, o = memop s in i64_load8_u a o | 0x32 -> - let a, o = memop s in + let+ a, o = memop s in i64_load16_s a o | 0x33 -> - let a, o = memop s in + let+ a, o = memop s in i64_load16_u a o | 0x34 -> - let a, o = memop s in + let+ a, o = memop s in i64_load32_s a o | 0x35 -> - let a, o = memop s in + let+ a, o = memop s in i64_load32_u a o | 0x36 -> - let a, o = memop s in + let+ a, o = memop s in i32_store a o | 0x37 -> - let a, o = memop s in + let+ a, o = memop s in i64_store a o | 0x38 -> - let a, o = memop s in + let+ a, o = memop s in f32_store a o | 0x39 -> - let a, o = memop s in + let+ a, o = memop s in f64_store a o | 0x3a -> - let a, o = memop s in + let+ a, o = memop s in i32_store8 a o | 0x3b -> - let a, o = memop s in + let+ a, o = memop s in i32_store16 a o | 0x3c -> - let a, o = memop s in + let+ a, o = memop s in i64_store8 a o | 0x3d -> - let a, o = memop s in + let+ a, o = memop s in i64_store16 a o | 0x3e -> - let a, o = memop s in + let+ a, o = memop s in i64_store32 a o | 0x3f -> - zero s ; + let+ () = zero s in memory_size | 0x40 -> - zero s ; + let+ () = zero s in memory_grow - | 0x41 -> i32_const (at vs32 s) - | 0x42 -> i64_const (at vs64 s) - | 0x43 -> f32_const (at f32 s) - | 0x44 -> f64_const (at f64 s) - | 0x45 -> i32_eqz - | 0x46 -> i32_eq - | 0x47 -> i32_ne - | 0x48 -> i32_lt_s - | 0x49 -> i32_lt_u - | 0x4a -> i32_gt_s - | 0x4b -> i32_gt_u - | 0x4c -> i32_le_s - | 0x4d -> i32_le_u - | 0x4e -> i32_ge_s - | 0x4f -> i32_ge_u - | 0x50 -> i64_eqz - | 0x51 -> i64_eq - | 0x52 -> i64_ne - | 0x53 -> i64_lt_s - | 0x54 -> i64_lt_u - | 0x55 -> i64_gt_s - | 0x56 -> i64_gt_u - | 0x57 -> i64_le_s - | 0x58 -> i64_le_u - | 0x59 -> i64_ge_s - | 0x5a -> i64_ge_u - | 0x5b -> f32_eq - | 0x5c -> f32_ne - | 0x5d -> f32_lt - | 0x5e -> f32_gt - | 0x5f -> f32_le - | 0x60 -> f32_ge - | 0x61 -> f64_eq - | 0x62 -> f64_ne - | 0x63 -> f64_lt - | 0x64 -> f64_gt - | 0x65 -> f64_le - | 0x66 -> f64_ge - | 0x67 -> i32_clz - | 0x68 -> i32_ctz - | 0x69 -> i32_popcnt - | 0x6a -> i32_add - | 0x6b -> i32_sub - | 0x6c -> i32_mul - | 0x6d -> i32_div_s - | 0x6e -> i32_div_u - | 0x6f -> i32_rem_s - | 0x70 -> i32_rem_u - | 0x71 -> i32_and - | 0x72 -> i32_or - | 0x73 -> i32_xor - | 0x74 -> i32_shl - | 0x75 -> i32_shr_s - | 0x76 -> i32_shr_u - | 0x77 -> i32_rotl - | 0x78 -> i32_rotr - | 0x79 -> i64_clz - | 0x7a -> i64_ctz - | 0x7b -> i64_popcnt - | 0x7c -> i64_add - | 0x7d -> i64_sub - | 0x7e -> i64_mul - | 0x7f -> i64_div_s - | 0x80 -> i64_div_u - | 0x81 -> i64_rem_s - | 0x82 -> i64_rem_u - | 0x83 -> i64_and - | 0x84 -> i64_or - | 0x85 -> i64_xor - | 0x86 -> i64_shl - | 0x87 -> i64_shr_s - | 0x88 -> i64_shr_u - | 0x89 -> i64_rotl - | 0x8a -> i64_rotr - | 0x8b -> f32_abs - | 0x8c -> f32_neg - | 0x8d -> f32_ceil - | 0x8e -> f32_floor - | 0x8f -> f32_trunc - | 0x90 -> f32_nearest - | 0x91 -> f32_sqrt - | 0x92 -> f32_add - | 0x93 -> f32_sub - | 0x94 -> f32_mul - | 0x95 -> f32_div - | 0x96 -> f32_min - | 0x97 -> f32_max - | 0x98 -> f32_copysign - | 0x99 -> f64_abs - | 0x9a -> f64_neg - | 0x9b -> f64_ceil - | 0x9c -> f64_floor - | 0x9d -> f64_trunc - | 0x9e -> f64_nearest - | 0x9f -> f64_sqrt - | 0xa0 -> f64_add - | 0xa1 -> f64_sub - | 0xa2 -> f64_mul - | 0xa3 -> f64_div - | 0xa4 -> f64_min - | 0xa5 -> f64_max - | 0xa6 -> f64_copysign - | 0xa7 -> i32_wrap_i64 - | 0xa8 -> i32_trunc_f32_s - | 0xa9 -> i32_trunc_f32_u - | 0xaa -> i32_trunc_f64_s - | 0xab -> i32_trunc_f64_u - | 0xac -> i64_extend_i32_s - | 0xad -> i64_extend_i32_u - | 0xae -> i64_trunc_f32_s - | 0xaf -> i64_trunc_f32_u - | 0xb0 -> i64_trunc_f64_s - | 0xb1 -> i64_trunc_f64_u - | 0xb2 -> f32_convert_i32_s - | 0xb3 -> f32_convert_i32_u - | 0xb4 -> f32_convert_i64_s - | 0xb5 -> f32_convert_i64_u - | 0xb6 -> f32_demote_f64 - | 0xb7 -> f64_convert_i32_s - | 0xb8 -> f64_convert_i32_u - | 0xb9 -> f64_convert_i64_s - | 0xba -> f64_convert_i64_u - | 0xbb -> f64_promote_f32 - | 0xbc -> i32_reinterpret_f32 - | 0xbd -> i64_reinterpret_f64 - | 0xbe -> f32_reinterpret_i32 - | 0xbf -> f64_reinterpret_i64 - | 0xc0 -> i32_extend8_s - | 0xc1 -> i32_extend16_s - | 0xc2 -> i64_extend8_s - | 0xc3 -> i64_extend16_s - | 0xc4 -> i64_extend32_s + | 0x41 -> + let+ x = at vs32 s in + i32_const x + | 0x42 -> + let+ x = at vs64 s in + i64_const x + | 0x43 -> + let+ x = at f32 s in + f32_const x + | 0x44 -> + let+ x = at f64 s in + f64_const x + | 0x45 -> Lwt.return i32_eqz + | 0x46 -> Lwt.return i32_eq + | 0x47 -> Lwt.return i32_ne + | 0x48 -> Lwt.return i32_lt_s + | 0x49 -> Lwt.return i32_lt_u + | 0x4a -> Lwt.return i32_gt_s + | 0x4b -> Lwt.return i32_gt_u + | 0x4c -> Lwt.return i32_le_s + | 0x4d -> Lwt.return i32_le_u + | 0x4e -> Lwt.return i32_ge_s + | 0x4f -> Lwt.return i32_ge_u + | 0x50 -> Lwt.return i64_eqz + | 0x51 -> Lwt.return i64_eq + | 0x52 -> Lwt.return i64_ne + | 0x53 -> Lwt.return i64_lt_s + | 0x54 -> Lwt.return i64_lt_u + | 0x55 -> Lwt.return i64_gt_s + | 0x56 -> Lwt.return i64_gt_u + | 0x57 -> Lwt.return i64_le_s + | 0x58 -> Lwt.return i64_le_u + | 0x59 -> Lwt.return i64_ge_s + | 0x5a -> Lwt.return i64_ge_u + | 0x5b -> Lwt.return f32_eq + | 0x5c -> Lwt.return f32_ne + | 0x5d -> Lwt.return f32_lt + | 0x5e -> Lwt.return f32_gt + | 0x5f -> Lwt.return f32_le + | 0x60 -> Lwt.return f32_ge + | 0x61 -> Lwt.return f64_eq + | 0x62 -> Lwt.return f64_ne + | 0x63 -> Lwt.return f64_lt + | 0x64 -> Lwt.return f64_gt + | 0x65 -> Lwt.return f64_le + | 0x66 -> Lwt.return f64_ge + | 0x67 -> Lwt.return i32_clz + | 0x68 -> Lwt.return i32_ctz + | 0x69 -> Lwt.return i32_popcnt + | 0x6a -> Lwt.return i32_add + | 0x6b -> Lwt.return i32_sub + | 0x6c -> Lwt.return i32_mul + | 0x6d -> Lwt.return i32_div_s + | 0x6e -> Lwt.return i32_div_u + | 0x6f -> Lwt.return i32_rem_s + | 0x70 -> Lwt.return i32_rem_u + | 0x71 -> Lwt.return i32_and + | 0x72 -> Lwt.return i32_or + | 0x73 -> Lwt.return i32_xor + | 0x74 -> Lwt.return i32_shl + | 0x75 -> Lwt.return i32_shr_s + | 0x76 -> Lwt.return i32_shr_u + | 0x77 -> Lwt.return i32_rotl + | 0x78 -> Lwt.return i32_rotr + | 0x79 -> Lwt.return i64_clz + | 0x7a -> Lwt.return i64_ctz + | 0x7b -> Lwt.return i64_popcnt + | 0x7c -> Lwt.return i64_add + | 0x7d -> Lwt.return i64_sub + | 0x7e -> Lwt.return i64_mul + | 0x7f -> Lwt.return i64_div_s + | 0x80 -> Lwt.return i64_div_u + | 0x81 -> Lwt.return i64_rem_s + | 0x82 -> Lwt.return i64_rem_u + | 0x83 -> Lwt.return i64_and + | 0x84 -> Lwt.return i64_or + | 0x85 -> Lwt.return i64_xor + | 0x86 -> Lwt.return i64_shl + | 0x87 -> Lwt.return i64_shr_s + | 0x88 -> Lwt.return i64_shr_u + | 0x89 -> Lwt.return i64_rotl + | 0x8a -> Lwt.return i64_rotr + | 0x8b -> Lwt.return f32_abs + | 0x8c -> Lwt.return f32_neg + | 0x8d -> Lwt.return f32_ceil + | 0x8e -> Lwt.return f32_floor + | 0x8f -> Lwt.return f32_trunc + | 0x90 -> Lwt.return f32_nearest + | 0x91 -> Lwt.return f32_sqrt + | 0x92 -> Lwt.return f32_add + | 0x93 -> Lwt.return f32_sub + | 0x94 -> Lwt.return f32_mul + | 0x95 -> Lwt.return f32_div + | 0x96 -> Lwt.return f32_min + | 0x97 -> Lwt.return f32_max + | 0x98 -> Lwt.return f32_copysign + | 0x99 -> Lwt.return f64_abs + | 0x9a -> Lwt.return f64_neg + | 0x9b -> Lwt.return f64_ceil + | 0x9c -> Lwt.return f64_floor + | 0x9d -> Lwt.return f64_trunc + | 0x9e -> Lwt.return f64_nearest + | 0x9f -> Lwt.return f64_sqrt + | 0xa0 -> Lwt.return f64_add + | 0xa1 -> Lwt.return f64_sub + | 0xa2 -> Lwt.return f64_mul + | 0xa3 -> Lwt.return f64_div + | 0xa4 -> Lwt.return f64_min + | 0xa5 -> Lwt.return f64_max + | 0xa6 -> Lwt.return f64_copysign + | 0xa7 -> Lwt.return i32_wrap_i64 + | 0xa8 -> Lwt.return i32_trunc_f32_s + | 0xa9 -> Lwt.return i32_trunc_f32_u + | 0xaa -> Lwt.return i32_trunc_f64_s + | 0xab -> Lwt.return i32_trunc_f64_u + | 0xac -> Lwt.return i64_extend_i32_s + | 0xad -> Lwt.return i64_extend_i32_u + | 0xae -> Lwt.return i64_trunc_f32_s + | 0xaf -> Lwt.return i64_trunc_f32_u + | 0xb0 -> Lwt.return i64_trunc_f64_s + | 0xb1 -> Lwt.return i64_trunc_f64_u + | 0xb2 -> Lwt.return f32_convert_i32_s + | 0xb3 -> Lwt.return f32_convert_i32_u + | 0xb4 -> Lwt.return f32_convert_i64_s + | 0xb5 -> Lwt.return f32_convert_i64_u + | 0xb6 -> Lwt.return f32_demote_f64 + | 0xb7 -> Lwt.return f64_convert_i32_s + | 0xb8 -> Lwt.return f64_convert_i32_u + | 0xb9 -> Lwt.return f64_convert_i64_s + | 0xba -> Lwt.return f64_convert_i64_u + | 0xbb -> Lwt.return f64_promote_f32 + | 0xbc -> Lwt.return i32_reinterpret_f32 + | 0xbd -> Lwt.return i64_reinterpret_f64 + | 0xbe -> Lwt.return f32_reinterpret_i32 + | 0xbf -> Lwt.return f64_reinterpret_i64 + | 0xc0 -> Lwt.return i32_extend8_s + | 0xc1 -> Lwt.return i32_extend16_s + | 0xc2 -> Lwt.return i64_extend8_s + | 0xc3 -> Lwt.return i64_extend16_s + | 0xc4 -> Lwt.return i64_extend32_s | (0xc5 | 0xc6 | 0xc7 | 0xc8 | 0xc9 | 0xca | 0xcb | 0xcc | 0xcd | 0xce | 0xcf) as b -> illegal s pos b - | 0xd0 -> ref_null (ref_type s) - | 0xd1 -> ref_is_null - | 0xd2 -> ref_func (at var s) + | 0xd0 -> + let+ x = ref_type s in + ref_null x + | 0xd1 -> Lwt.return ref_is_null + | 0xd2 -> + let+ x = at var s in + ref_func x | 0xfc as b -> ( - match vu32 s with - | 0x00l -> i32_trunc_sat_f32_s - | 0x01l -> i32_trunc_sat_f32_u - | 0x02l -> i32_trunc_sat_f64_s - | 0x03l -> i32_trunc_sat_f64_u - | 0x04l -> i64_trunc_sat_f32_s - | 0x05l -> i64_trunc_sat_f32_u - | 0x06l -> i64_trunc_sat_f64_s - | 0x07l -> i64_trunc_sat_f64_u + let* x = vu32 s in + match x with + | 0x00l -> Lwt.return i32_trunc_sat_f32_s + | 0x01l -> Lwt.return i32_trunc_sat_f32_u + | 0x02l -> Lwt.return i32_trunc_sat_f64_s + | 0x03l -> Lwt.return i32_trunc_sat_f64_u + | 0x04l -> Lwt.return i64_trunc_sat_f32_s + | 0x05l -> Lwt.return i64_trunc_sat_f32_u + | 0x06l -> Lwt.return i64_trunc_sat_f64_s + | 0x07l -> Lwt.return i64_trunc_sat_f64_u | 0x08l -> - let x = at var s in - zero s ; + let* x = at var s in + let+ () = zero s in memory_init x - | 0x09l -> data_drop (at var s) + | 0x09l -> + let+ x = at var s in + data_drop x | 0x0al -> - zero s ; - zero s ; + let* () = zero s in + let+ () = zero s in memory_copy | 0x0bl -> - zero s ; + let+ () = zero s in memory_fill | 0x0cl -> - let y = at var s in - let x = at var s in + let* y = at var s in + let+ x = at var s in table_init x y - | 0x0dl -> elem_drop (at var s) + | 0x0dl -> + let+ x = at var s in + elem_drop x | 0x0el -> - let x = at var s in - let y = at var s in + let* x = at var s in + let+ y = at var s in table_copy x y - | 0x0fl -> table_grow (at var s) - | 0x10l -> table_size (at var s) - | 0x11l -> table_fill (at var s) + | 0x0fl -> + let+ x = at var s in + table_grow x + | 0x10l -> + let+ x = at var s in + table_size x + | 0x11l -> + let+ x = at var s in + table_fill x | n -> illegal2 s pos b n) | 0xfd -> ( - match vu32 s with + let* x = vu32 s in + match x with | 0x00l -> - let a, o = memop s in + let+ a, o = memop s in v128_load a o | 0x01l -> - let a, o = memop s in + let+ a, o = memop s in v128_load8x8_s a o | 0x02l -> - let a, o = memop s in + let+ a, o = memop s in v128_load8x8_u a o | 0x03l -> - let a, o = memop s in + let+ a, o = memop s in v128_load16x4_s a o | 0x04l -> - let a, o = memop s in + let+ a, o = memop s in v128_load16x4_u a o | 0x05l -> - let a, o = memop s in + let+ a, o = memop s in v128_load32x2_s a o | 0x06l -> - let a, o = memop s in + let+ a, o = memop s in v128_load32x2_u a o | 0x07l -> - let a, o = memop s in + let+ a, o = memop s in v128_load8_splat a o | 0x08l -> - let a, o = memop s in + let+ a, o = memop s in v128_load16_splat a o | 0x09l -> - let a, o = memop s in + let+ a, o = memop s in v128_load32_splat a o | 0x0al -> - let a, o = memop s in + let+ a, o = memop s in v128_load64_splat a o | 0x0bl -> - let a, o = memop s in + let+ a, o = memop s in v128_store a o - | 0x0cl -> v128_const (at v128 s) - | 0x0dl -> i8x16_shuffle (List.init 16 (fun x -> u8 s)) - | 0x0el -> i8x16_swizzle - | 0x0fl -> i8x16_splat - | 0x10l -> i16x8_splat - | 0x11l -> i32x4_splat - | 0x12l -> i64x2_splat - | 0x13l -> f32x4_splat - | 0x14l -> f64x2_splat + | 0x0cl -> + let+ x = at v128 s in + v128_const x + | 0x0dl -> + let+ l = + Lwt_list.map_s (fun () -> u8 s) (List.init 16 (fun _ -> ())) + in + i8x16_shuffle l + | 0x0el -> Lwt.return i8x16_swizzle + | 0x0fl -> Lwt.return i8x16_splat + | 0x10l -> Lwt.return i16x8_splat + | 0x11l -> Lwt.return i32x4_splat + | 0x12l -> Lwt.return i64x2_splat + | 0x13l -> Lwt.return f32x4_splat + | 0x14l -> Lwt.return f64x2_splat | 0x15l -> - let i = u8 s in + let+ i = u8 s in i8x16_extract_lane_s i | 0x16l -> - let i = u8 s in + let+ i = u8 s in i8x16_extract_lane_u i | 0x17l -> - let i = u8 s in + let+ i = u8 s in i8x16_replace_lane i | 0x18l -> - let i = u8 s in + let+ i = u8 s in i16x8_extract_lane_s i | 0x19l -> - let i = u8 s in + let+ i = u8 s in i16x8_extract_lane_u i | 0x1al -> - let i = u8 s in + let+ i = u8 s in i16x8_replace_lane i | 0x1bl -> - let i = u8 s in + let+ i = u8 s in i32x4_extract_lane i | 0x1cl -> - let i = u8 s in + let+ i = u8 s in i32x4_replace_lane i | 0x1dl -> - let i = u8 s in + let+ i = u8 s in i64x2_extract_lane i | 0x1el -> - let i = u8 s in + let+ i = u8 s in i64x2_replace_lane i | 0x1fl -> - let i = u8 s in + let+ i = u8 s in f32x4_extract_lane i | 0x20l -> - let i = u8 s in + let+ i = u8 s in f32x4_replace_lane i | 0x21l -> - let i = u8 s in + let+ i = u8 s in f64x2_extract_lane i | 0x22l -> - let i = u8 s in + let+ i = u8 s in f64x2_replace_lane i - | 0x23l -> i8x16_eq - | 0x24l -> i8x16_ne - | 0x25l -> i8x16_lt_s - | 0x26l -> i8x16_lt_u - | 0x27l -> i8x16_gt_s - | 0x28l -> i8x16_gt_u - | 0x29l -> i8x16_le_s - | 0x2al -> i8x16_le_u - | 0x2bl -> i8x16_ge_s - | 0x2cl -> i8x16_ge_u - | 0x2dl -> i16x8_eq - | 0x2el -> i16x8_ne - | 0x2fl -> i16x8_lt_s - | 0x30l -> i16x8_lt_u - | 0x31l -> i16x8_gt_s - | 0x32l -> i16x8_gt_u - | 0x33l -> i16x8_le_s - | 0x34l -> i16x8_le_u - | 0x35l -> i16x8_ge_s - | 0x36l -> i16x8_ge_u - | 0x37l -> i32x4_eq - | 0x38l -> i32x4_ne - | 0x39l -> i32x4_lt_s - | 0x3al -> i32x4_lt_u - | 0x3bl -> i32x4_gt_s - | 0x3cl -> i32x4_gt_u - | 0x3dl -> i32x4_le_s - | 0x3el -> i32x4_le_u - | 0x3fl -> i32x4_ge_s - | 0x40l -> i32x4_ge_u - | 0x41l -> f32x4_eq - | 0x42l -> f32x4_ne - | 0x43l -> f32x4_lt - | 0x44l -> f32x4_gt - | 0x45l -> f32x4_le - | 0x46l -> f32x4_ge - | 0x47l -> f64x2_eq - | 0x48l -> f64x2_ne - | 0x49l -> f64x2_lt - | 0x4al -> f64x2_gt - | 0x4bl -> f64x2_le - | 0x4cl -> f64x2_ge - | 0x4dl -> v128_not - | 0x4el -> v128_and - | 0x4fl -> v128_andnot - | 0x50l -> v128_or - | 0x51l -> v128_xor - | 0x52l -> v128_bitselect - | 0x53l -> v128_any_true + | 0x23l -> Lwt.return i8x16_eq + | 0x24l -> Lwt.return i8x16_ne + | 0x25l -> Lwt.return i8x16_lt_s + | 0x26l -> Lwt.return i8x16_lt_u + | 0x27l -> Lwt.return i8x16_gt_s + | 0x28l -> Lwt.return i8x16_gt_u + | 0x29l -> Lwt.return i8x16_le_s + | 0x2al -> Lwt.return i8x16_le_u + | 0x2bl -> Lwt.return i8x16_ge_s + | 0x2cl -> Lwt.return i8x16_ge_u + | 0x2dl -> Lwt.return i16x8_eq + | 0x2el -> Lwt.return i16x8_ne + | 0x2fl -> Lwt.return i16x8_lt_s + | 0x30l -> Lwt.return i16x8_lt_u + | 0x31l -> Lwt.return i16x8_gt_s + | 0x32l -> Lwt.return i16x8_gt_u + | 0x33l -> Lwt.return i16x8_le_s + | 0x34l -> Lwt.return i16x8_le_u + | 0x35l -> Lwt.return i16x8_ge_s + | 0x36l -> Lwt.return i16x8_ge_u + | 0x37l -> Lwt.return i32x4_eq + | 0x38l -> Lwt.return i32x4_ne + | 0x39l -> Lwt.return i32x4_lt_s + | 0x3al -> Lwt.return i32x4_lt_u + | 0x3bl -> Lwt.return i32x4_gt_s + | 0x3cl -> Lwt.return i32x4_gt_u + | 0x3dl -> Lwt.return i32x4_le_s + | 0x3el -> Lwt.return i32x4_le_u + | 0x3fl -> Lwt.return i32x4_ge_s + | 0x40l -> Lwt.return i32x4_ge_u + | 0x41l -> Lwt.return f32x4_eq + | 0x42l -> Lwt.return f32x4_ne + | 0x43l -> Lwt.return f32x4_lt + | 0x44l -> Lwt.return f32x4_gt + | 0x45l -> Lwt.return f32x4_le + | 0x46l -> Lwt.return f32x4_ge + | 0x47l -> Lwt.return f64x2_eq + | 0x48l -> Lwt.return f64x2_ne + | 0x49l -> Lwt.return f64x2_lt + | 0x4al -> Lwt.return f64x2_gt + | 0x4bl -> Lwt.return f64x2_le + | 0x4cl -> Lwt.return f64x2_ge + | 0x4dl -> Lwt.return v128_not + | 0x4el -> Lwt.return v128_and + | 0x4fl -> Lwt.return v128_andnot + | 0x50l -> Lwt.return v128_or + | 0x51l -> Lwt.return v128_xor + | 0x52l -> Lwt.return v128_bitselect + | 0x53l -> Lwt.return v128_any_true | 0x54l -> - let a, o = memop s in - let lane = u8 s in + let* a, o = memop s in + let+ lane = u8 s in v128_load8_lane a o lane | 0x55l -> - let a, o = memop s in - let lane = u8 s in + let* a, o = memop s in + let+ lane = u8 s in v128_load16_lane a o lane | 0x56l -> - let a, o = memop s in - let lane = u8 s in + let* a, o = memop s in + let+ lane = u8 s in v128_load32_lane a o lane | 0x57l -> - let a, o = memop s in - let lane = u8 s in + let* a, o = memop s in + let+ lane = u8 s in v128_load64_lane a o lane | 0x58l -> - let a, o = memop s in - let lane = u8 s in + let* a, o = memop s in + let+ lane = u8 s in v128_store8_lane a o lane | 0x59l -> - let a, o = memop s in - let lane = u8 s in + let* a, o = memop s in + let+ lane = u8 s in v128_store16_lane a o lane | 0x5al -> - let a, o = memop s in - let lane = u8 s in + let* a, o = memop s in + let+ lane = u8 s in v128_store32_lane a o lane | 0x5bl -> - let a, o = memop s in - let lane = u8 s in + let* a, o = memop s in + let+ lane = u8 s in v128_store64_lane a o lane | 0x5cl -> - let a, o = memop s in + let+ a, o = memop s in v128_load32_zero a o | 0x5dl -> - let a, o = memop s in + let+ a, o = memop s in v128_load64_zero a o - | 0x5el -> f32x4_demote_f64x2_zero - | 0x5fl -> f64x2_promote_low_f32x4 - | 0x60l -> i8x16_abs - | 0x61l -> i8x16_neg - | 0x62l -> i8x16_popcnt - | 0x63l -> i8x16_all_true - | 0x64l -> i8x16_bitmask - | 0x65l -> i8x16_narrow_i16x8_s - | 0x66l -> i8x16_narrow_i16x8_u - | 0x67l -> f32x4_ceil - | 0x68l -> f32x4_floor - | 0x69l -> f32x4_trunc - | 0x6al -> f32x4_nearest - | 0x6bl -> i8x16_shl - | 0x6cl -> i8x16_shr_s - | 0x6dl -> i8x16_shr_u - | 0x6el -> i8x16_add - | 0x6fl -> i8x16_add_sat_s - | 0x70l -> i8x16_add_sat_u - | 0x71l -> i8x16_sub - | 0x72l -> i8x16_sub_sat_s - | 0x73l -> i8x16_sub_sat_u - | 0x74l -> f64x2_ceil - | 0x75l -> f64x2_floor - | 0x76l -> i8x16_min_s - | 0x77l -> i8x16_min_u - | 0x78l -> i8x16_max_s - | 0x79l -> i8x16_max_u - | 0x7al -> f64x2_trunc - | 0x7bl -> i8x16_avgr_u - | 0x7cl -> i16x8_extadd_pairwise_i8x16_s - | 0x7dl -> i16x8_extadd_pairwise_i8x16_u - | 0x7el -> i32x4_extadd_pairwise_i16x8_s - | 0x7fl -> i32x4_extadd_pairwise_i16x8_u - | 0x80l -> i16x8_abs - | 0x81l -> i16x8_neg - | 0x82l -> i16x8_q15mulr_sat_s - | 0x83l -> i16x8_all_true - | 0x84l -> i16x8_bitmask - | 0x85l -> i16x8_narrow_i32x4_s - | 0x86l -> i16x8_narrow_i32x4_u - | 0x87l -> i16x8_extend_low_i8x16_s - | 0x88l -> i16x8_extend_high_i8x16_s - | 0x89l -> i16x8_extend_low_i8x16_u - | 0x8al -> i16x8_extend_high_i8x16_u - | 0x8bl -> i16x8_shl - | 0x8cl -> i16x8_shr_s - | 0x8dl -> i16x8_shr_u - | 0x8el -> i16x8_add - | 0x8fl -> i16x8_add_sat_s - | 0x90l -> i16x8_add_sat_u - | 0x91l -> i16x8_sub - | 0x92l -> i16x8_sub_sat_s - | 0x93l -> i16x8_sub_sat_u - | 0x94l -> f64x2_nearest - | 0x95l -> i16x8_mul - | 0x96l -> i16x8_min_s - | 0x97l -> i16x8_min_u - | 0x98l -> i16x8_max_s - | 0x99l -> i16x8_max_u - | 0x9bl -> i16x8_avgr_u - | 0x9cl -> i16x8_extmul_low_i8x16_s - | 0x9dl -> i16x8_extmul_high_i8x16_s - | 0x9el -> i16x8_extmul_low_i8x16_u - | 0x9fl -> i16x8_extmul_high_i8x16_u - | 0xa0l -> i32x4_abs - | 0xa1l -> i32x4_neg - | 0xa3l -> i32x4_all_true - | 0xa4l -> i32x4_bitmask - | 0xa7l -> i32x4_extend_low_i16x8_s - | 0xa8l -> i32x4_extend_high_i16x8_s - | 0xa9l -> i32x4_extend_low_i16x8_u - | 0xaal -> i32x4_extend_high_i16x8_u - | 0xabl -> i32x4_shl - | 0xacl -> i32x4_shr_s - | 0xadl -> i32x4_shr_u - | 0xael -> i32x4_add - | 0xb1l -> i32x4_sub - | 0xb5l -> i32x4_mul - | 0xb6l -> i32x4_min_s - | 0xb7l -> i32x4_min_u - | 0xb8l -> i32x4_max_s - | 0xb9l -> i32x4_max_u - | 0xbal -> i32x4_dot_i16x8_s - | 0xbcl -> i32x4_extmul_low_i16x8_s - | 0xbdl -> i32x4_extmul_high_i16x8_s - | 0xbel -> i32x4_extmul_low_i16x8_u - | 0xbfl -> i32x4_extmul_high_i16x8_u - | 0xc0l -> i64x2_abs - | 0xc1l -> i64x2_neg - | 0xc3l -> i64x2_all_true - | 0xc4l -> i64x2_bitmask - | 0xc7l -> i64x2_extend_low_i32x4_s - | 0xc8l -> i64x2_extend_high_i32x4_s - | 0xc9l -> i64x2_extend_low_i32x4_u - | 0xcal -> i64x2_extend_high_i32x4_u - | 0xcbl -> i64x2_shl - | 0xccl -> i64x2_shr_s - | 0xcdl -> i64x2_shr_u - | 0xcel -> i64x2_add - | 0xd1l -> i64x2_sub - | 0xd5l -> i64x2_mul - | 0xd6l -> i64x2_eq - | 0xd7l -> i64x2_ne - | 0xd8l -> i64x2_lt_s - | 0xd9l -> i64x2_gt_s - | 0xdal -> i64x2_le_s - | 0xdbl -> i64x2_ge_s - | 0xdcl -> i64x2_extmul_low_i32x4_s - | 0xddl -> i64x2_extmul_high_i32x4_s - | 0xdel -> i64x2_extmul_low_i32x4_u - | 0xdfl -> i64x2_extmul_high_i32x4_u - | 0xe0l -> f32x4_abs - | 0xe1l -> f32x4_neg - | 0xe3l -> f32x4_sqrt - | 0xe4l -> f32x4_add - | 0xe5l -> f32x4_sub - | 0xe6l -> f32x4_mul - | 0xe7l -> f32x4_div - | 0xe8l -> f32x4_min - | 0xe9l -> f32x4_max - | 0xeal -> f32x4_pmin - | 0xebl -> f32x4_pmax - | 0xecl -> f64x2_abs - | 0xedl -> f64x2_neg - | 0xefl -> f64x2_sqrt - | 0xf0l -> f64x2_add - | 0xf1l -> f64x2_sub - | 0xf2l -> f64x2_mul - | 0xf3l -> f64x2_div - | 0xf4l -> f64x2_min - | 0xf5l -> f64x2_max - | 0xf6l -> f64x2_pmin - | 0xf7l -> f64x2_pmax - | 0xf8l -> i32x4_trunc_sat_f32x4_s - | 0xf9l -> i32x4_trunc_sat_f32x4_u - | 0xfal -> f32x4_convert_i32x4_s - | 0xfbl -> f32x4_convert_i32x4_u - | 0xfcl -> i32x4_trunc_sat_f64x2_s_zero - | 0xfdl -> i32x4_trunc_sat_f64x2_u_zero - | 0xfel -> f64x2_convert_low_i32x4_s - | 0xffl -> f64x2_convert_low_i32x4_u + | 0x5el -> Lwt.return f32x4_demote_f64x2_zero + | 0x5fl -> Lwt.return f64x2_promote_low_f32x4 + | 0x60l -> Lwt.return i8x16_abs + | 0x61l -> Lwt.return i8x16_neg + | 0x62l -> Lwt.return i8x16_popcnt + | 0x63l -> Lwt.return i8x16_all_true + | 0x64l -> Lwt.return i8x16_bitmask + | 0x65l -> Lwt.return i8x16_narrow_i16x8_s + | 0x66l -> Lwt.return i8x16_narrow_i16x8_u + | 0x67l -> Lwt.return f32x4_ceil + | 0x68l -> Lwt.return f32x4_floor + | 0x69l -> Lwt.return f32x4_trunc + | 0x6al -> Lwt.return f32x4_nearest + | 0x6bl -> Lwt.return i8x16_shl + | 0x6cl -> Lwt.return i8x16_shr_s + | 0x6dl -> Lwt.return i8x16_shr_u + | 0x6el -> Lwt.return i8x16_add + | 0x6fl -> Lwt.return i8x16_add_sat_s + | 0x70l -> Lwt.return i8x16_add_sat_u + | 0x71l -> Lwt.return i8x16_sub + | 0x72l -> Lwt.return i8x16_sub_sat_s + | 0x73l -> Lwt.return i8x16_sub_sat_u + | 0x74l -> Lwt.return f64x2_ceil + | 0x75l -> Lwt.return f64x2_floor + | 0x76l -> Lwt.return i8x16_min_s + | 0x77l -> Lwt.return i8x16_min_u + | 0x78l -> Lwt.return i8x16_max_s + | 0x79l -> Lwt.return i8x16_max_u + | 0x7al -> Lwt.return f64x2_trunc + | 0x7bl -> Lwt.return i8x16_avgr_u + | 0x7cl -> Lwt.return i16x8_extadd_pairwise_i8x16_s + | 0x7dl -> Lwt.return i16x8_extadd_pairwise_i8x16_u + | 0x7el -> Lwt.return i32x4_extadd_pairwise_i16x8_s + | 0x7fl -> Lwt.return i32x4_extadd_pairwise_i16x8_u + | 0x80l -> Lwt.return i16x8_abs + | 0x81l -> Lwt.return i16x8_neg + | 0x82l -> Lwt.return i16x8_q15mulr_sat_s + | 0x83l -> Lwt.return i16x8_all_true + | 0x84l -> Lwt.return i16x8_bitmask + | 0x85l -> Lwt.return i16x8_narrow_i32x4_s + | 0x86l -> Lwt.return i16x8_narrow_i32x4_u + | 0x87l -> Lwt.return i16x8_extend_low_i8x16_s + | 0x88l -> Lwt.return i16x8_extend_high_i8x16_s + | 0x89l -> Lwt.return i16x8_extend_low_i8x16_u + | 0x8al -> Lwt.return i16x8_extend_high_i8x16_u + | 0x8bl -> Lwt.return i16x8_shl + | 0x8cl -> Lwt.return i16x8_shr_s + | 0x8dl -> Lwt.return i16x8_shr_u + | 0x8el -> Lwt.return i16x8_add + | 0x8fl -> Lwt.return i16x8_add_sat_s + | 0x90l -> Lwt.return i16x8_add_sat_u + | 0x91l -> Lwt.return i16x8_sub + | 0x92l -> Lwt.return i16x8_sub_sat_s + | 0x93l -> Lwt.return i16x8_sub_sat_u + | 0x94l -> Lwt.return f64x2_nearest + | 0x95l -> Lwt.return i16x8_mul + | 0x96l -> Lwt.return i16x8_min_s + | 0x97l -> Lwt.return i16x8_min_u + | 0x98l -> Lwt.return i16x8_max_s + | 0x99l -> Lwt.return i16x8_max_u + | 0x9bl -> Lwt.return i16x8_avgr_u + | 0x9cl -> Lwt.return i16x8_extmul_low_i8x16_s + | 0x9dl -> Lwt.return i16x8_extmul_high_i8x16_s + | 0x9el -> Lwt.return i16x8_extmul_low_i8x16_u + | 0x9fl -> Lwt.return i16x8_extmul_high_i8x16_u + | 0xa0l -> Lwt.return i32x4_abs + | 0xa1l -> Lwt.return i32x4_neg + | 0xa3l -> Lwt.return i32x4_all_true + | 0xa4l -> Lwt.return i32x4_bitmask + | 0xa7l -> Lwt.return i32x4_extend_low_i16x8_s + | 0xa8l -> Lwt.return i32x4_extend_high_i16x8_s + | 0xa9l -> Lwt.return i32x4_extend_low_i16x8_u + | 0xaal -> Lwt.return i32x4_extend_high_i16x8_u + | 0xabl -> Lwt.return i32x4_shl + | 0xacl -> Lwt.return i32x4_shr_s + | 0xadl -> Lwt.return i32x4_shr_u + | 0xael -> Lwt.return i32x4_add + | 0xb1l -> Lwt.return i32x4_sub + | 0xb5l -> Lwt.return i32x4_mul + | 0xb6l -> Lwt.return i32x4_min_s + | 0xb7l -> Lwt.return i32x4_min_u + | 0xb8l -> Lwt.return i32x4_max_s + | 0xb9l -> Lwt.return i32x4_max_u + | 0xbal -> Lwt.return i32x4_dot_i16x8_s + | 0xbcl -> Lwt.return i32x4_extmul_low_i16x8_s + | 0xbdl -> Lwt.return i32x4_extmul_high_i16x8_s + | 0xbel -> Lwt.return i32x4_extmul_low_i16x8_u + | 0xbfl -> Lwt.return i32x4_extmul_high_i16x8_u + | 0xc0l -> Lwt.return i64x2_abs + | 0xc1l -> Lwt.return i64x2_neg + | 0xc3l -> Lwt.return i64x2_all_true + | 0xc4l -> Lwt.return i64x2_bitmask + | 0xc7l -> Lwt.return i64x2_extend_low_i32x4_s + | 0xc8l -> Lwt.return i64x2_extend_high_i32x4_s + | 0xc9l -> Lwt.return i64x2_extend_low_i32x4_u + | 0xcal -> Lwt.return i64x2_extend_high_i32x4_u + | 0xcbl -> Lwt.return i64x2_shl + | 0xccl -> Lwt.return i64x2_shr_s + | 0xcdl -> Lwt.return i64x2_shr_u + | 0xcel -> Lwt.return i64x2_add + | 0xd1l -> Lwt.return i64x2_sub + | 0xd5l -> Lwt.return i64x2_mul + | 0xd6l -> Lwt.return i64x2_eq + | 0xd7l -> Lwt.return i64x2_ne + | 0xd8l -> Lwt.return i64x2_lt_s + | 0xd9l -> Lwt.return i64x2_gt_s + | 0xdal -> Lwt.return i64x2_le_s + | 0xdbl -> Lwt.return i64x2_ge_s + | 0xdcl -> Lwt.return i64x2_extmul_low_i32x4_s + | 0xddl -> Lwt.return i64x2_extmul_high_i32x4_s + | 0xdel -> Lwt.return i64x2_extmul_low_i32x4_u + | 0xdfl -> Lwt.return i64x2_extmul_high_i32x4_u + | 0xe0l -> Lwt.return f32x4_abs + | 0xe1l -> Lwt.return f32x4_neg + | 0xe3l -> Lwt.return f32x4_sqrt + | 0xe4l -> Lwt.return f32x4_add + | 0xe5l -> Lwt.return f32x4_sub + | 0xe6l -> Lwt.return f32x4_mul + | 0xe7l -> Lwt.return f32x4_div + | 0xe8l -> Lwt.return f32x4_min + | 0xe9l -> Lwt.return f32x4_max + | 0xeal -> Lwt.return f32x4_pmin + | 0xebl -> Lwt.return f32x4_pmax + | 0xecl -> Lwt.return f64x2_abs + | 0xedl -> Lwt.return f64x2_neg + | 0xefl -> Lwt.return f64x2_sqrt + | 0xf0l -> Lwt.return f64x2_add + | 0xf1l -> Lwt.return f64x2_sub + | 0xf2l -> Lwt.return f64x2_mul + | 0xf3l -> Lwt.return f64x2_div + | 0xf4l -> Lwt.return f64x2_min + | 0xf5l -> Lwt.return f64x2_max + | 0xf6l -> Lwt.return f64x2_pmin + | 0xf7l -> Lwt.return f64x2_pmax + | 0xf8l -> Lwt.return i32x4_trunc_sat_f32x4_s + | 0xf9l -> Lwt.return i32x4_trunc_sat_f32x4_u + | 0xfal -> Lwt.return f32x4_convert_i32x4_s + | 0xfbl -> Lwt.return f32x4_convert_i32x4_u + | 0xfcl -> Lwt.return i32x4_trunc_sat_f64x2_s_zero + | 0xfdl -> Lwt.return i32x4_trunc_sat_f64x2_u_zero + | 0xfel -> Lwt.return f64x2_convert_low_i32x4_s + | 0xffl -> Lwt.return f64x2_convert_low_i32x4_u | n -> illegal s pos (I32.to_int_u n)) | b -> illegal s pos b @@ -932,42 +1097,44 @@ let instr_block_step s allocs cont = (* Enforces the number of values popped from the stack, which shouldn't fail. *) | [IKStop lbl] -> invalid_arg "instr_block" | [IKStop lbl; IKBlock (bt, pos); IKNext plbl] -> - end_ s ; + let* () = end_ s in let e = Source.(block bt lbl @@ region s pos pos) in let+ () = add_to_block allocs plbl e in push_stack (IKNext plbl) stack | [IKStop lbl; IKLoop (bt, pos); IKNext plbl] -> - end_ s ; + let* () = end_ s in let e = Source.(loop bt lbl @@ region s pos pos) in let+ () = add_to_block allocs plbl e in push_stack (IKNext plbl) stack | [IKStop lbl1; IKIf1 (bt, pos); IKNext plbl] -> - if peek s = Some 0x05 then + let* x = peek s in + if x = Some 0x05 then (skip 1 s ; push_rev_values [IKNext (alloc_block allocs); IKIf2 (bt, pos, lbl1); IKNext plbl] stack) |> Lwt.return - else ( - end_ s ; + else + let* () = end_ s in let e = Source.(if_ bt lbl1 empty_block @@ region s pos pos) in let+ () = add_to_block allocs plbl e in - push_stack (IKNext plbl) stack) + push_stack (IKNext plbl) stack | [IKStop lbl2; IKIf2 (bt, pos, lbl1); IKNext plbl] -> - end_ s ; + let* () = end_ s in let e = Source.(if_ bt lbl1 lbl2 @@ region s pos pos) in let+ () = add_to_block allocs plbl e in push_stack (IKNext plbl) stack | IKNext lbl :: ks -> ( - match peek s with + let* x = peek s in + match x with | None | Some (0x05 | 0x0b) -> push_rev_values (IKStop lbl :: ks) stack |> Lwt.return | _ -> ( let pos = pos s in - let tag = op s in + let* tag = op s in match tag with | 0x02 -> - let bt = block_type s in + let* bt = block_type s in push_rev_values (IKNext (alloc_block allocs) :: IKBlock (bt, pos) @@ -975,7 +1142,7 @@ let instr_block_step s allocs cont = stack |> Lwt.return | 0x03 -> - let bt = block_type s in + let* bt = block_type s in push_rev_values (IKNext (alloc_block allocs) :: IKLoop (bt, pos) @@ -983,7 +1150,7 @@ let instr_block_step s allocs cont = stack |> Lwt.return | 0x04 -> - let bt = block_type s in + let* bt = block_type s in push_rev_values (IKNext (alloc_block allocs) :: IKIf1 (bt, pos) @@ -991,7 +1158,8 @@ let instr_block_step s allocs cont = stack |> Lwt.return | _ -> - let e = Source.(instr s pos tag @@ region s pos pos) in + let* i = instr s pos tag in + let e = Source.(i @@ region s pos pos) in let+ () = add_to_block allocs lbl e in push_rev_values (IKNext lbl :: ks) stack)) (* Stop can only be followed a new block, or being the final state. *) @@ -1045,7 +1213,8 @@ type pos = int type size = {size : int; start : pos} let size s = - let size = len32 s in + let open Lwt.Syntax in + let+ size = len32 s in let start = pos s in {size; start} @@ -1057,23 +1226,31 @@ type name_step = | NKParse of pos * int lazy_vec_kont * int (** UTF8 char parsing. *) | NKStop of int Vector.t (** UTF8 name final step.*) -let name_step s = function +let name_step s = + let open Lwt.Syntax in + function | NKStart -> let pos = pos s in - let len = len32 s in + let+ len = len32 s in NKParse (pos, init_lazy_vec 0l, len) - | NKParse (pos, LazyVec {vector; _}, 0) -> NKStop vector + | NKParse (pos, LazyVec {vector; _}, 0) -> Lwt.return @@ NKStop vector | NKParse (pos, LazyVec lv, len) -> - let d, offset = + let* d, offset = try Utf8.decode_step get s with Utf8 -> error s pos "malformed UTF-8 encoding" in let vec = LazyVec {lv with vector = Vector.grow 1l lv.vector} in - NKParse (pos, lazy_vec_step d vec, len - offset) + Lwt.return @@ NKParse (pos, lazy_vec_step d vec, len - offset) | NKStop l -> assert false (* final step, cannot reduce. *) let name s = - let rec step = function NKStop n -> n | k -> step (name_step s k) in + let open Lwt.Syntax in + let rec step = function + | NKStop n -> Lwt.return n + | k -> + let* x = name_step s k in + step x + in step NKStart (* Sections *) @@ -1095,7 +1272,8 @@ type section_tag = | `TypeSection ] let id s = - let bo = peek s in + let open Lwt.Syntax in + let+ bo = peek s in Lib.Option.map (function | 0 -> `CustomSection @@ -1115,11 +1293,13 @@ let id s = bo let section_with_size tag f default s = - match id s with + let open Lwt.Syntax in + let* x = id s in + match x with | Some tag' when tag' = tag -> - ignore (u8 s) ; + let* () = lwt_ignore @@ u8 s in sized f s - | _ -> default + | _ -> Lwt.return default let section tag f default s = section_with_size tag (fun _ -> f) default s @@ -1131,23 +1311,25 @@ type func_type_kont = | FKOut of value_type Vector.t * value_type lazy_vec_kont | FKStop of func_type -let func_type_step s = function +let func_type_step s = + let open Lwt.Syntax in + function | FKStart -> - let tag = vs7 s in - let len = len32 s in + let* tag = vs7 s in + let+ len = len32 s in if tag = -0x20 then FKIns (init_lazy_vec (Int32.of_int len)) else error s (pos s - 1) "malformed function type" | FKIns (LazyVec {vector = ins; _} as vec) when is_end_of_vec vec -> - let len = len32 s in + let+ len = len32 s in FKOut (ins, init_lazy_vec (Int32.of_int len)) | FKIns ins -> - let vt = value_type s in + let+ vt = value_type s in FKIns (lazy_vec_step vt ins) | FKOut (ins, (LazyVec {vector = out; _} as out_vec)) when is_end_of_vec out_vec -> - FKStop (FuncType (ins, out)) + Lwt.return @@ FKStop (FuncType (ins, out)) | FKOut (ins, out_vec) -> - let vt = value_type s in + let+ vt = value_type s in FKOut (ins, lazy_vec_step vt out_vec) | FKStop _ -> assert false (* cannot reduce *) @@ -1156,11 +1338,21 @@ let func_type_step s = function (* Import section *) let import_desc s = - match u8 s with - | 0x00 -> FuncImport (at var s) - | 0x01 -> TableImport (table_type s) - | 0x02 -> MemoryImport (memory_type s) - | 0x03 -> GlobalImport (global_type s) + let open Lwt.Syntax in + let* x = u8 s in + match x with + | 0x00 -> + let+ x = at var s in + FuncImport x + | 0x01 -> + let+ x = table_type s in + TableImport x + | 0x02 -> + let+ x = memory_type s in + MemoryImport x + | 0x03 -> + let+ x = global_type s in + GlobalImport x | _ -> error s (pos s - 1) "malformed import kind" type import_kont = @@ -1171,36 +1363,55 @@ type import_kont = (** Import item name parsing UTF8 char per char step. *) | ImpKStop of import' (** Import final step. *) -let import_step s = function - | ImpKStart -> ImpKModuleName NKStart - | ImpKModuleName (NKStop module_name) -> ImpKItemName (module_name, NKStart) - | ImpKModuleName nk -> ImpKModuleName (name_step s nk) +let import_step s = + let open Lwt.Syntax in + function + | ImpKStart -> Lwt.return @@ ImpKModuleName NKStart + | ImpKModuleName (NKStop module_name) -> + Lwt.return @@ ImpKItemName (module_name, NKStart) + | ImpKModuleName nk -> + let+ x = name_step s nk in + ImpKModuleName x | ImpKItemName (module_name, NKStop item_name) -> - let idesc = at import_desc s in + let+ idesc = at import_desc s in ImpKStop {module_name; item_name; idesc} - | ImpKItemName (module_name, nk) -> ImpKItemName (module_name, name_step s nk) + | ImpKItemName (module_name, nk) -> + let+ x = name_step s nk in + ImpKItemName (module_name, x) | ImpKStop _ -> assert false (* Final step, cannot reduce *) (* Table section *) let table s = - let ttype = table_type s in + let open Lwt.Syntax in + let+ ttype = table_type s in {ttype} (* Memory section *) let memory s = - let mtype = memory_type s in + let open Lwt.Syntax in + let+ mtype = memory_type s in {mtype} (* Export section *) let export_desc s = - match u8 s with - | 0x00 -> FuncExport (at var s) - | 0x01 -> TableExport (at var s) - | 0x02 -> MemoryExport (at var s) - | 0x03 -> GlobalExport (at var s) + let open Lwt.Syntax in + let* x = u8 s in + match x with + | 0x00 -> + let+ x = at var s in + FuncExport x + | 0x01 -> + let+ x = at var s in + TableExport x + | 0x02 -> + let+ x = at var s in + MemoryExport x + | 0x03 -> + let+ x = at var s in + GlobalExport x | _ -> error s (pos s - 1) "malformed export kind" type export_kont = @@ -1208,18 +1419,23 @@ type export_kont = | ExpKName of name_step (** Export name parsing UTF8 char per char step. *) | ExpKStop of export' (** Export final step. *) -let export_step s = function - | ExpKStart -> ExpKName NKStart +let export_step s = + let open Lwt.Syntax in + function + | ExpKStart -> Lwt.return @@ ExpKName NKStart | ExpKName (NKStop name) -> - let edesc = at export_desc s in + let+ edesc = at export_desc s in ExpKStop {name; edesc} - | ExpKName nk -> ExpKName (name_step s nk) + | ExpKName nk -> + let+ x = name_step s nk in + ExpKName x | ExpKStop _ -> assert false (* Final step, cannot reduce *) (* Start section *) let start s = - let sfunc = at var s in + let open Lwt.Syntax in + let+ sfunc = at var s in {sfunc} let start_section s = section `StartSection (opt (at start) true) None s @@ -1227,8 +1443,9 @@ let start_section s = section `StartSection (opt (at start) true) None s (* Code section *) let local s = - let n = vu32 s in - let t = value_type s in + let open Lwt.Syntax in + let* n = vu32 s in + let+ t = value_type s in (n, t) (** Code section parsing. *) @@ -1267,10 +1484,10 @@ let code_step s allocs = | CKStart -> (* `at` left *) let left = pos s in - let size = size s in + let* size = size s in let pos = pos s in (* `vec` size *) - let n = len32 s in + let+ n = len32 s in CKLocalsParse { left; @@ -1279,7 +1496,6 @@ let code_step s allocs = locals_size = 0L; vec_kont = init_lazy_vec (Int32.of_int n); } - |> Lwt.return | CKLocalsParse { left; @@ -1302,7 +1518,7 @@ let code_step s allocs = } |> Lwt.return | CKLocalsParse {left; size; pos; vec_kont; locals_size} -> - let local = local s in + let* local = local s in (* small enough to fit in a tick *) let locals_size = I64.add locals_size (I64_convert.extend_i32_u (fst local)) @@ -1348,7 +1564,7 @@ let code_step s allocs = } |> Lwt.return | CKBody {left; size; locals; const_kont = BlockStop body} -> - end_ s ; + let* () = end_ s in check_size size s ; let func = at' left s @@ {locals; body; ftype = Source.(-1l @@ Source.no_region)} @@ -1363,13 +1579,15 @@ let code_step s allocs = let elem_index allocs s = let open Lwt.Syntax in - let x = at var s in + let* x = at var s in let b = alloc_block allocs in let+ () = add_to_block allocs b Source.(ref_func x @@ x.at) in b let elem_kind s = - match u8 s with + let open Lwt.Syntax in + let+ x = u8 s in + match x with | 0x00 -> FuncRefType | _ -> error s (pos s - 1) "malformed element kind" @@ -1400,31 +1618,33 @@ type elem_kont = | EKStop of elem_segment' (** Final step of a segment parsing. *) let ek_start s allocs = - let v = vu32 s in + let open Lwt.Syntax in + let* v = vu32 s in match v with | 0x00l -> (* active_zero *) let index = Source.(0l @@ Source.no_region) in let left = pos s in - EKMode - { - left; - index; - index_kind = Indexed; - early_ref_type = Some FuncRefType; - offset_kont = (left, BlockStart); - } + Lwt.return + @@ EKMode + { + left; + index; + index_kind = Indexed; + early_ref_type = Some FuncRefType; + offset_kont = (left, BlockStart); + } | 0x01l -> (* passive *) let mode_pos = pos s in - let ref_type = elem_kind s in - let n = len32 s in + let* ref_type = elem_kind s in + let+ n = len32 s in let mode = Source.(Passive @@ region s mode_pos mode_pos) in EKInitIndexed {mode; ref_type; einit_vec = init_lazy_vec (Int32.of_int n)} | 0x02l -> (* active *) let left = pos s in - let index = at var s in + let+ index = at var s in let left_offset = pos s in EKMode { @@ -1438,27 +1658,28 @@ let ek_start s allocs = (* declarative *) let mode_pos = pos s in let mode = Source.(Declarative @@ region s mode_pos mode_pos) in - let ref_type = elem_kind s in - let n = len32 s in + let* ref_type = elem_kind s in + let+ n = len32 s in EKInitIndexed {mode; ref_type; einit_vec = init_lazy_vec (Int32.of_int n)} | 0x04l -> (* active_zero *) let index = Source.(0l @@ Source.no_region) in let left = pos s in - EKMode - { - left; - index; - index_kind = Const; - early_ref_type = Some FuncRefType; - offset_kont = (left, BlockStart); - } + Lwt.return + @@ EKMode + { + left; + index; + index_kind = Const; + early_ref_type = Some FuncRefType; + offset_kont = (left, BlockStart); + } | 0x05l -> (* passive *) let mode_pos = pos s in let mode = Source.(Passive @@ region s mode_pos mode_pos) in - let ref_type = ref_type s in - let n = len32 s in + let* ref_type = ref_type s in + let+ n = len32 s in let left = pos s in EKInitConst { @@ -1470,7 +1691,7 @@ let ek_start s allocs = | 0x06l -> (* active *) let left = pos s in - let index = at var s in + let+ index = at var s in let left_offset = pos s in EKMode { @@ -1484,8 +1705,8 @@ let ek_start s allocs = (* declarative *) let mode_pos = pos s in let mode = Source.(Declarative @@ region s mode_pos mode_pos) in - let ref_type = ref_type s in - let n = len32 s in + let* ref_type = ref_type s in + let+ n = len32 s in let left = pos s in EKInitConst { @@ -1499,7 +1720,7 @@ let ek_start s allocs = let elem_step s allocs = let open Lwt.Syntax in function - | EKStart -> ek_start s allocs |> Lwt.return + | EKStart -> ek_start s allocs | EKMode { left; @@ -1508,21 +1729,20 @@ let elem_step s allocs = early_ref_type; offset_kont = left_offset, BlockStop offset; } -> - end_ s ; + let* () = end_ s in let right = pos s in let offset = Source.(offset @@ region s left_offset right) in let mode = Source.(Active {index; offset} @@ region s left right) in - let ref_type = + let* ref_type = match early_ref_type with - | Some t -> t + | Some t -> Lwt.return t | None -> if index_kind = Indexed then elem_kind s else ref_type s in (* `vec` size *) - let n = len32 s in + let+ n = len32 s in if index_kind = Indexed then EKInitIndexed {mode; ref_type; einit_vec = init_lazy_vec (Int32.of_int n)} - |> Lwt.return else let left = pos s in EKInitConst @@ -1532,7 +1752,6 @@ let elem_step s allocs = einit_vec = init_lazy_vec (Int32.of_int n); einit_kont = (left, BlockStart); } - |> Lwt.return | EKMode {left; index; index_kind; early_ref_type; offset_kont = left_offset, k} -> let+ k' = block_step s allocs k in @@ -1559,7 +1778,7 @@ let elem_step s allocs = (* Const *) | EKInitConst {mode; ref_type; einit_vec; einit_kont = left, BlockStop einit} -> - end_ s ; + let* () = end_ s in let right = pos s in let einit = Source.(einit @@ region s left right) in EKInitConst @@ -1588,21 +1807,23 @@ type data_kont = | DKStop of data_segment' (** Final step of a data segment parsing. *) let data_start s allocs = - match vu32 s with + let open Lwt.Syntax in + let* x = vu32 s in + match x with | 0x00l -> (* active_zero *) let index = Source.(0l @@ Source.no_region) in let left = pos s in - DKMode {left; index; offset_kont = (left, BlockStart)} + Lwt.return @@ DKMode {left; index; offset_kont = (left, BlockStart)} | 0x01l -> (* passive *) let mode_pos = pos s in let dmode = Source.(Passive @@ region s mode_pos mode_pos) in - DKInit {dmode; init_kont = VKStart} + Lwt.return @@ DKInit {dmode; init_kont = VKStart} | 0x02l -> (* active *) let left = pos s in - let index = at var s in + let+ index = at var s in let left_offset = pos s in DKMode {left; index; offset_kont = (left_offset, BlockStart)} | _ -> error s (pos s - 1) "malformed data segment kind" @@ -1610,9 +1831,9 @@ let data_start s allocs = let data_step s allocs = let open Lwt.Syntax in function - | DKStart -> data_start s allocs |> Lwt.return + | DKStart -> data_start s allocs | DKMode {left; index; offset_kont = left_offset, BlockStop offset} -> - end_ s ; + let* () = end_ s in let right = pos s in let offset = Source.(offset @@ region s left_offset right) in let dmode = Source.(Active {index; offset} @@ region s left right) in @@ -1629,31 +1850,40 @@ let data_step s allocs = (* DataCount section *) -let data_count s = Some (vu32 s) +let data_count s = + let open Lwt.Syntax in + let+ x = vu32 s in + Some x let data_count_section s = section `DataCountSection data_count None s (* Custom section *) let custom size s = + let open Lwt.Syntax in let start = pos s in - let id = name s in - let bs = get_string (size - (pos s - start)) s in + let* id = name s in + let+ bs = get_string (size - (pos s - start)) s in Some (id, bs) let custom_section s = section_with_size `CustomSection custom None s let non_custom_section s = - match id s with - | None | Some `CustomSection -> None + let open Lwt.Syntax in + let* x = id s in + match x with + | None | Some `CustomSection -> Lwt.return None | _ -> skip 1 s ; - sized skip s ; + let+ () = sized (fun pos s -> skip pos s |> Lwt.return) s in Some () (* Modules *) -let rec iterate f s = if f s <> None then iterate f s +let rec iterate f s = + let open Lwt.Syntax in + let* x = f s in + if x <> None then iterate f s else Lwt.return () let magic = 0x6d736100l @@ -1795,19 +2025,20 @@ let module_step state = match state.module_kont with | MKStart -> (* Module header *) - let header = u32 s in + let* header = u32 s in require (header = magic) s 0 "magic header not detected" ; - let version = u32 s in + let* version = u32 s in require (version = Encode.version) s 4 "unknown binary version" ; (* Module header *) next @@ MKSkipCustom (Some (TypeField, `TypeSection)) | MKSkipCustom k -> ( - match id s with + let* x = id s in + match x with | Some `CustomSection -> (* section_with_size *) - ignore (u8 s) ; + let* () = lwt_ignore @@ u8 s in (* sized *) - let l = len32 s in + let* l = len32 s in (* custom *) let start = pos s in let _id = name s in @@ -1829,31 +2060,32 @@ let module_step state = true ) | Some (ty, tag) -> next @@ MKFieldStart (ty, tag))) | MKFieldStart (DataCountField, `DataCountSection) -> - let v = data_count_section s in + let* v = data_count_section s in next_with_field (SingleField (DataCountField, v)) (MKSkipCustom (Some (CodeField, `CodeSection))) | MKFieldStart (StartField, `StartSection) -> - let v = start_section s in + let* v = start_section s in next_with_field (SingleField (StartField, v)) (MKSkipCustom (Some (ElemField, `ElemSection))) (* Parsing of fields vector. *) | MKFieldStart (ty, tag) -> ( - match id s with + let* x = id s in + match x with | Some t when t = tag -> - ignore (u8 s) ; - let size = size s in + let* () = lwt_ignore @@ u8 s in + let* size = size s in (* length of `vec` *) - let l = len32 s in + let* l = len32 s in next @@ MKField (ty, size, init_lazy_vec (Int32.of_int l)) | _ -> let size = {size = 0; start = pos s} in next @@ MKField (ty, size, init_lazy_vec 0l) - (* Transitions steps from the end of a section to the next one. + (* Transitions steps from the end of a section to the next one. - The values accumulated from the section are accumulated into the building - state..*)) + The values accumulated from the section are accumulated into the building + state..*)) (* TODO (https://gitlab.com/tezos/tezos/-/issues/3120): maybe we can factor-out these similarly shaped module section transitions *) | MKField (TypeField, size, vec) when is_end_of_vec vec -> check_size size s ; @@ -1911,19 +2143,19 @@ let module_step state = | TypeField -> next @@ MKTypes (FKStart, pos s, size, vec) | ImportField -> next @@ MKImport (ImpKStart, pos s, size, vec) | FuncField -> - let f = at var s in + let* f = at var s in (* small enough to fit in a tick *) next @@ MKField (ty, size, lazy_vec_step f vec) | TableField -> - let f = at table s in + let* f = at table s in (* small enough to fit in a tick *) next @@ MKField (ty, size, lazy_vec_step f vec) | MemoryField -> - let f = at memory s in + let* f = at memory s in (* small enough to fit in a tick *) next @@ MKField (ty, size, lazy_vec_step f vec) | GlobalField -> - let gtype = global_type s in + let* gtype = global_type s in next @@ MKGlobal (gtype, pos s, BlockStart, size, vec) | ExportField -> next @@ MKExport (ExpKStart, pos s, size, vec) | StartField -> @@ -1941,19 +2173,22 @@ let module_step state = let f = Source.(func_type @@ region s left (pos s)) in next @@ MKField (TypeField, size, lazy_vec_step f vec) | MKTypes (k, pos, size, curr_vec) -> - next @@ MKTypes (func_type_step s k, pos, size, curr_vec) + let* x = func_type_step s k in + next @@ MKTypes (x, pos, size, curr_vec) | MKImport (ImpKStop import, left, size, vec) -> let f = Source.(import @@ region s left (pos s)) in next @@ MKField (ImportField, size, lazy_vec_step f vec) | MKImport (k, pos, size, curr_vec) -> - next @@ MKImport (import_step s k, pos, size, curr_vec) + let* x = import_step s k in + next @@ MKImport (x, pos, size, curr_vec) | MKExport (ExpKStop import, left, size, vec) -> let f = Source.(import @@ region s left (pos s)) in next @@ MKField (ExportField, size, lazy_vec_step f vec) | MKExport (k, pos, size, curr_vec) -> - next @@ MKExport (export_step s k, pos, size, curr_vec) + let* x = export_step s k in + next @@ MKExport (x, pos, size, curr_vec) | MKGlobal (gtype, left, BlockStop res, size, vec) -> - end_ s ; + let* () = end_ s in let ginit = Source.(res @@ region s left (pos s)) in let f = Source.({gtype; ginit} @@ region s left (pos s)) in next @@ MKField (GlobalField, size, lazy_vec_step f vec) @@ -2083,15 +2318,19 @@ let decode ~name ~bytes = Source.(m @@ region s left right) let all_custom tag s = - let header = u32 s in + let open Lwt.Syntax in + let* header = u32 s in require (header = magic) s 0 "magic header not detected" ; - let version = u32 s in + let* version = u32 s in require (version = Encode.version) s 4 "unknown binary version" ; let rec collect () = - iterate non_custom_section s ; - match custom_section s with - | None -> [] - | Some (n, s) when n = tag -> s :: collect () + let* () = iterate non_custom_section s in + let* x = custom_section s in + match x with + | None -> Lwt.return [] + | Some (n, s) when n = tag -> + let+ rst = collect () in + s :: rst | Some _ -> collect () in collect () diff --git a/src/lib_webassembly/binary/decode.mli b/src/lib_webassembly/binary/decode.mli index 991b15fb98f1..fd9a6a6ac0b7 100644 --- a/src/lib_webassembly/binary/decode.mli +++ b/src/lib_webassembly/binary/decode.mli @@ -240,7 +240,11 @@ type module_kont = the section. *) (** Parsed bytes with the current reading position. *) -type stream = {name : string; bytes : string; pos : pos ref} +type stream = { + name : string; + bytes : Chunked_byte_vector.Lwt.t; + mutable pos : int; +} (** Accumulator of parsed fields *) type building_state = { @@ -268,7 +272,7 @@ type decode_kont = { } (** [make_stream filename bytes] returns a new stream to decode. *) -val make_stream : name:string -> bytes:string -> stream +val make_stream : name:string -> bytes:Chunked_byte_vector.Lwt.t -> stream (** [module_step kont] takes one step of parsing from a continuation and returns a new continuation. Fails when the contination of the module is [MKStop] @@ -278,10 +282,14 @@ val module_step : decode_kont -> decode_kont Lwt.t (** [decode ~name ~bytes] decodes a module [name] from its [bytes] encoding. @raise Code on parsing errors. *) -val decode : name:string -> bytes:string -> Ast.module_ Lwt.t +val decode : name:string -> bytes:Chunked_byte_vector.Lwt.t -> Ast.module_ Lwt.t (** [decode ~name ~bytes] decodes a custom section of name [name] from its [bytes] encoding. @raise Code on parsing errors. *) -val decode_custom : Ast.name -> name:string -> bytes:string -> string list +val decode_custom : + Ast.name -> + name:string -> + bytes:Chunked_byte_vector.Lwt.t -> + string list Lwt.t diff --git a/src/lib_webassembly/binary/utf8.ml b/src/lib_webassembly/binary/utf8.ml index 058e84323059..d6eeb71ebc0f 100644 --- a/src/lib_webassembly/binary/utf8.ml +++ b/src/lib_webassembly/binary/utf8.ml @@ -41,6 +41,7 @@ let code min n = else n let decode_step get s = + let open Lwt.Syntax in let i = ref 0 in let get s = (* In the testsuite, some tests are supposed to break during reading the @@ -54,29 +55,31 @@ let decode_step get s = get s with Decode_error.Error _ -> raise Utf8 in - let b1 = get s in - let code = - if b1 < 0x80 then code 0x0 b1 + let* b1 = get s in + let* code = + if b1 < 0x80 then Lwt.return @@ code 0x0 b1 else if b1 < 0xc0 then raise Utf8 else - let b2 = get s in - if b1 < 0xe0 then code 0x80 (((b1 land 0x1f) lsl 6) + con b2) + let* b2 = get s in + if b1 < 0xe0 then Lwt.return @@ code 0x80 (((b1 land 0x1f) lsl 6) + con b2) else - let b3 = get s in + let* b3 = get s in if b1 < 0xf0 then - code 0x800 (((b1 land 0x0f) lsl 12) + (con b2 lsl 6) + con b3) + Lwt.return + @@ code 0x800 (((b1 land 0x0f) lsl 12) + (con b2 lsl 6) + con b3) else - let b4 = get s in + let* b4 = get s in if b1 < 0xf8 then - code - 0x10000 - (((b1 land 0x07) lsl 18) - + (con b2 lsl 12) - + (con b3 lsl 6) - + con b4) + Lwt.return + @@ code + 0x10000 + (((b1 land 0x07) lsl 18) + + (con b2 lsl 12) + + (con b3 lsl 6) + + con b4) else raise Utf8 in - (code, !i) + Lwt.return (code, !i) let rec decode s = Lazy_vector.LwtInt32Vector.of_list diff --git a/src/lib_webassembly/binary/utf8.mli b/src/lib_webassembly/binary/utf8.mli index 05d55d72aa1b..0a61ab149a11 100644 --- a/src/lib_webassembly/binary/utf8.mli +++ b/src/lib_webassembly/binary/utf8.mli @@ -4,7 +4,7 @@ @raise Binary_exn.Utf8 in case the encoding is illformed with regards to the Utf8 conventions. *) -val decode_step : ('a -> int) -> 'a -> int * int +val decode_step : ('a -> int Lwt.t) -> 'a -> (int * int) Lwt.t (** [encode_int i] encodes an Utf8 represented into an integer into its char codes. -- GitLab