diff --git a/interpreter/binary/decode.ml b/interpreter/binary/decode.ml index 392f61b21b..fa3a0ef9e5 100644 --- a/interpreter/binary/decode.ml +++ b/interpreter/binary/decode.ml @@ -14,6 +14,7 @@ let stream name bs = {name; bytes = bs; pos = ref 0} let len s = String.length s.bytes let pos s = !(s.pos) let eos s = (pos s = len s) +let reset s pos = s.pos := pos 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 @@ -26,15 +27,16 @@ let get_string n s = let i = pos s in skip n s; String.sub s.bytes i n (* Errors *) +open Source + module Code = Error.Make () exception Code = Code.Error let string_of_byte b = Printf.sprintf "%02x" b let string_of_multi n = Printf.sprintf "%02lx" n -let position s pos = Source.({file = s.name; line = -1; column = pos}) -let region s left right = - Source.({left = position s left; right = position s right}) +let position s pos = {file = s.name; line = -1; column = pos} +let region s left right = {left = position s left; right = position s right} let error s pos msg = raise (Code (region s pos pos, msg)) let require b s pos msg = if not b then error s pos msg @@ -55,70 +57,76 @@ let at f s = let left = pos s in let x = f s in let right = pos s in - Source.(x @@ region s left right) - + x @@ region s left right (* Generic values *) -let u8 s = +let byte s = get s -let u16 s = - let lo = u8 s in - let hi = u8 s in +let word16 s = + let lo = byte s in + let hi = byte 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 word32 s = + let lo = Int32.of_int (word16 s) in + let hi = Int32.of_int (word16 s) 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 word64 s = + let lo = I64_convert.extend_i32_u (word32 s) in + let hi = I64_convert.extend_i32_u (word32 s) in Int64.(add lo (shift_left hi 32)) -let rec vuN n s = +let rec uN n s = require (n > 0) s (pos s) "integer representation too long"; - let b = u8 s in + let b = byte 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 x else Int64.(logor x (shift_left (uN (n - 7) s) 7)) -let rec vsN n s = +let rec sN n s = require (n > 0) s (pos s) "integer representation too long"; - let b = u8 s in + let b = byte s in let mask = (-1 lsl (n - 1)) land 0x7f in require (n >= 7 || b land mask = 0 || b land mask = mask) s (pos s - 1) "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)) - -let vu1 s = Int64.to_int (vuN 1 s) -let vu32 s = Int64.to_int32 (vuN 32 s) -let vs7 s = Int64.to_int (vsN 7 s) -let vs32 s = Int64.to_int32 (vsN 32 s) -let vs33 s = I32_convert.wrap_i64 (vsN 33 s) -let vs64 s = vsN 64 s -let f32 s = F32.of_bits (u32 s) -let f64 s = F64.of_bits (u64 s) + else Int64.(logor x (shift_left (sN (n - 7) s) 7)) + +let u1 s = Int64.to_int (uN 1 s) +let u32 s = Int64.to_int32 (uN 32 s) +let s7 s = Int64.to_int (sN 7 s) +let s32 s = Int64.to_int32 (sN 32 s) +let s33 s = I32_convert.wrap_i64 (sN 33 s) +let s64 s = sN 64 s +let f32 s = F32.of_bits (word32 s) +let f64 s = F64.of_bits (word64 s) let v128 s = V128.of_bits (get_string (Types.vec_size Types.V128Type) s) let len32 s = let pos = pos s in - let n = vu32 s in + let n = u32 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 = (u1 s = 1) let string s = let n = len32 s in get_string n s let rec list f n s = if n = 0 then [] else let x = f s in x :: list f (n - 1) s let opt f b s = if b then Some (f s) else None let vec f s = let n = len32 s in list f n s +let rec either fs s = + match fs with + | [] -> assert false + | [f] -> f s + | f::fs' -> + let pos = pos s in try f s with Code _ -> reset s pos; either fs' s + let name s = let pos = pos s in try Utf8.decode (string s) with Utf8.Utf8 -> @@ -137,7 +145,7 @@ let sized f s = open Types let num_type s = - match vs7 s with + match s7 s with | -0x01 -> I32Type | -0x02 -> I64Type | -0x03 -> F32Type @@ -145,48 +153,50 @@ let num_type s = | _ -> error s (pos s - 1) "malformed number type" let vec_type s = - match vs7 s with + match s7 s with | -0x05 -> V128Type | _ -> error s (pos s - 1) "malformed vector type" let ref_type s = - match vs7 s with + match s7 s 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) + either [ + (fun s -> NumType (num_type s)); + (fun s -> VecType (vec_type s)); + (fun s -> RefType (ref_type s)); + ] s let result_type s = vec value_type s + let func_type s = - match vs7 s with + match s7 s with | -0x20 -> - let ins = result_type s in - let out = result_type s in - FuncType (ins, out) + let ts1 = result_type s in + let ts2 = result_type s in + FuncType (ts1, ts2) | _ -> error s (pos s - 1) "malformed function type" -let limits vu s = +let limits uN s = let has_max = bool s in - let min = vu s in - let max = opt vu has_max s in + let min = uN s in + let max = opt uN has_max s in {min; max} let table_type s = let t = ref_type s in - let lim = limits vu32 s in + let lim = limits u32 s in TableType (lim, t) let memory_type s = - let lim = limits vu32 s in + let lim = limits u32 s in MemoryType lim let mutability s = - match u8 s with + match byte s with | 0 -> Immutable | 1 -> Mutable | _ -> error s (pos s - 1) "malformed mutability" @@ -197,28 +207,30 @@ let global_type s = GlobalType (t, mut) -(* Decode instructions *) +(* Instructions *) open Ast open Operators -let var s = vu32 s +let var s = u32 s -let op s = u8 s +let op s = byte s 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 align = u32 s in require (I32.le_u align 32l) s (pos s - 1) "malformed memop flags"; - let offset = vu32 s in + let offset = u32 s in Int32.to_int align, offset let block_type s = - match peek s with - | Some 0x40 -> skip 1 s; ValBlockType None - | Some b when b land 0xc0 = 0x40 -> ValBlockType (Some (value_type s)) - | _ -> VarBlockType (at vs33 s) + let p = pos s in + either [ + (fun s -> let x = at s33 s in require (x.it >= 0l) s p ""; VarBlockType x); + (fun s -> expect 0x40 s ""; ValBlockType None); + (fun s -> ValBlockType (Some (value_type s))); + ] s let rec instr s = let pos = pos s in @@ -313,8 +325,8 @@ let rec instr s = | 0x3f -> zero s; memory_size | 0x40 -> zero s; memory_grow - | 0x41 -> i32_const (at vs32 s) - | 0x42 -> i64_const (at vs64 s) + | 0x41 -> i32_const (at s32 s) + | 0x42 -> i64_const (at s64 s) | 0x43 -> f32_const (at f32 s) | 0x44 -> f64_const (at f64 s) @@ -465,7 +477,7 @@ let rec instr s = | 0xd2 -> ref_func (at var s) | 0xfc as b -> - (match vu32 s with + (match u32 s with | 0x00l -> i32_trunc_sat_f32_s | 0x01l -> i32_trunc_sat_f32_u | 0x02l -> i32_trunc_sat_f64_s @@ -499,7 +511,7 @@ let rec instr s = ) | 0xfd -> - (match vu32 s with + (match u32 s with | 0x00l -> let a, o = memop s in v128_load a o | 0x01l -> let a, o = memop s in v128_load8x8_s a o | 0x02l -> let a, o = memop s in v128_load8x8_u a o @@ -513,7 +525,7 @@ let rec instr s = | 0x0al -> let a, o = memop s in v128_load64_splat a o | 0x0bl -> 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)) + | 0x0dl -> i8x16_shuffle (List.init 16 (fun _ -> byte s)) | 0x0el -> i8x16_swizzle | 0x0fl -> i8x16_splat | 0x10l -> i16x8_splat @@ -521,20 +533,20 @@ let rec instr s = | 0x12l -> i64x2_splat | 0x13l -> f32x4_splat | 0x14l -> f64x2_splat - | 0x15l -> let i = u8 s in i8x16_extract_lane_s i - | 0x16l -> let i = u8 s in i8x16_extract_lane_u i - | 0x17l -> let i = u8 s in i8x16_replace_lane i - | 0x18l -> let i = u8 s in i16x8_extract_lane_s i - | 0x19l -> let i = u8 s in i16x8_extract_lane_u i - | 0x1al -> let i = u8 s in i16x8_replace_lane i - | 0x1bl -> let i = u8 s in i32x4_extract_lane i - | 0x1cl -> let i = u8 s in i32x4_replace_lane i - | 0x1dl -> let i = u8 s in i64x2_extract_lane i - | 0x1el -> let i = u8 s in i64x2_replace_lane i - | 0x1fl -> let i = u8 s in f32x4_extract_lane i - | 0x20l -> let i = u8 s in f32x4_replace_lane i - | 0x21l -> let i = u8 s in f64x2_extract_lane i - | 0x22l -> let i = u8 s in f64x2_replace_lane i + | 0x15l -> let i = byte s in i8x16_extract_lane_s i + | 0x16l -> let i = byte s in i8x16_extract_lane_u i + | 0x17l -> let i = byte s in i8x16_replace_lane i + | 0x18l -> let i = byte s in i16x8_extract_lane_s i + | 0x19l -> let i = byte s in i16x8_extract_lane_u i + | 0x1al -> let i = byte s in i16x8_replace_lane i + | 0x1bl -> let i = byte s in i32x4_extract_lane i + | 0x1cl -> let i = byte s in i32x4_replace_lane i + | 0x1dl -> let i = byte s in i64x2_extract_lane i + | 0x1el -> let i = byte s in i64x2_replace_lane i + | 0x1fl -> let i = byte s in f32x4_extract_lane i + | 0x20l -> let i = byte s in f32x4_replace_lane i + | 0x21l -> let i = byte s in f64x2_extract_lane i + | 0x22l -> let i = byte s in f64x2_replace_lane i | 0x23l -> i8x16_eq | 0x24l -> i8x16_ne | 0x25l -> i8x16_lt_s @@ -586,35 +598,35 @@ let rec instr s = | 0x53l -> v128_any_true | 0x54l -> let a, o = memop s in - let lane = u8 s in + let lane = byte s in v128_load8_lane a o lane | 0x55l -> let a, o = memop s in - let lane = u8 s in + let lane = byte s in v128_load16_lane a o lane | 0x56l -> let a, o = memop s in - let lane = u8 s in + let lane = byte s in v128_load32_lane a o lane | 0x57l -> let a, o = memop s in - let lane = u8 s in + let lane = byte s in v128_load64_lane a o lane | 0x58l -> let a, o = memop s in - let lane = u8 s in + let lane = byte s in v128_store8_lane a o lane | 0x59l -> let a, o = memop s in - let lane = u8 s in + let lane = byte s in v128_store16_lane a o lane | 0x5al -> let a, o = memop s in - let lane = u8 s in + let lane = byte s in v128_store32_lane a o lane | 0x5bl -> let a, o = memop s in - let lane = u8 s in + let lane = byte s in v128_store64_lane a o lane | 0x5cl -> let a, o = memop s in v128_load32_zero a o | 0x5dl -> let a, o = memop s in v128_load64_zero a o @@ -772,7 +784,7 @@ and instr_block' s es = | _ -> let pos = pos s in let e' = instr s in - instr_block' s (Source.(e' @@ region s pos pos) :: es) + instr_block' s ((e' @@ region s pos pos) :: es) let const s = let c = at instr_block s in @@ -804,7 +816,7 @@ let id s = let section_with_size tag f default s = match id s with - | Some tag' when tag' = tag -> ignore (u8 s); sized f s + | Some tag' when tag' = tag -> skip 1 s; sized f s | _ -> default let section tag f default s = @@ -822,7 +834,7 @@ let type_section s = (* Import section *) let import_desc s = - match u8 s with + match byte s with | 0x00 -> FuncImport (at var s) | 0x01 -> TableImport (table_type s) | 0x02 -> MemoryImport (memory_type s) @@ -879,7 +891,7 @@ let global_section s = (* Export section *) let export_desc s = - match u8 s with + match byte s with | 0x00 -> FuncExport (at var s) | 0x01 -> TableExport (at var s) | 0x02 -> MemoryExport (at var s) @@ -908,20 +920,23 @@ let start_section s = (* Code section *) let local s = - let n = vu32 s in + let n = u32 s in let t = value_type s in n, t -let code _ s = +let locals s = let pos = pos s in let nts = vec local s in let ns = List.map (fun (n, _) -> I64_convert.extend_i32_u n) nts in require (I64.lt_u (List.fold_left I64.add 0L ns) 0x1_0000_0000L) s pos "too many locals"; - let locals = List.flatten (List.map (Lib.Fun.uncurry Lib.List32.make) nts) in + List.flatten (List.map (Lib.Fun.uncurry Lib.List32.make) nts) + +let code _ s = + let locals = locals s in let body = instr_block s in end_ s; - {locals; body; ftype = Source.((-1l) @@ Source.no_region)} + {locals; body; ftype = -1l @@ no_region} let code_section s = section `CodeSection (vec (at (sized code))) [] s @@ -938,7 +953,7 @@ let active s = Active {index; offset} let active_zero s = - let index = Source.(0l @@ Source.no_region) in + let index = 0l @@ no_region in let offset = const s in Active {index; offset} @@ -947,15 +962,15 @@ let declarative s = let elem_index s = let x = at var s in - [Source.(ref_func x @@ x.at)] + [ref_func x @@ x.at] let elem_kind s = - match u8 s with + match byte s with | 0x00 -> FuncRefType | _ -> error s (pos s - 1) "malformed element kind" let elem s = - match vu32 s with + match u32 s with | 0x00l -> let emode = at active_zero s in let einit = vec (at elem_index) s in @@ -1003,7 +1018,7 @@ let elem_section s = (* Data section *) let data s = - match vu32 s with + match u32 s with | 0x00l -> let dmode = at active_zero s in let dinit = string s in @@ -1025,7 +1040,7 @@ let data_section s = (* DataCount section *) let data_count s = - Some (vu32 s) + Some (u32 s) let data_count_section s = section `DataCountSection data_count None s @@ -1055,9 +1070,9 @@ let rec iterate f s = if f s <> None then iterate f s let magic = 0x6d736100l let module_ s = - let header = u32 s in + let header = word32 s in require (header = magic) s 0 "magic header not detected"; - let version = u32 s in + let version = word32 s in require (version = Encode.version) s 4 "unknown binary version"; iterate custom_section s; let types = type_section s in @@ -1093,17 +1108,16 @@ let module_ s = List.for_all Free.(fun f -> (func f).datas = Set.empty) func_bodies) s (len s) "data count section required"; let funcs = - List.map2 Source.(fun t f -> {f.it with ftype = t} @@ f.at) - func_types func_bodies + List.map2 (fun t f -> {f.it with ftype = t} @@ f.at) func_types func_bodies in {types; tables; memories; globals; funcs; imports; exports; elems; datas; start} let decode name bs = at module_ (stream name bs) let all_custom tag s = - let header = u32 s in + let header = word32 s in require (header = magic) s 0 "magic header not detected"; - let version = u32 s in + let version = word32 s in require (version = Encode.version) s 4 "unknown binary version"; let rec collect () = iterate non_custom_section s; diff --git a/interpreter/binary/encode.ml b/interpreter/binary/encode.ml index aafc3d9860..f5665bb1cd 100644 --- a/interpreter/binary/encode.ml +++ b/interpreter/binary/encode.ml @@ -1,4 +1,4 @@ -(* Version *) +(* Binary format version *) let version = 1l @@ -8,6 +8,8 @@ let version = 1l module Code = Error.Make () exception Code = Code.Error +let error = Code.error + (* Encoding stream *) @@ -35,50 +37,50 @@ module E (S : sig val stream : stream end) = struct let s = S.stream + (* Generic values *) - let u8 i = put s (Char.chr (i land 0xff)) - let u16 i = u8 (i land 0xff); u8 (i lsr 8) - let u32 i = - Int32.(u16 (to_int (logand i 0xffffl)); - u16 (to_int (shift_right i 16))) - let u64 i = - Int64.(u32 (to_int32 (logand i 0xffffffffL)); - u32 (to_int32 (shift_right i 32))) + let byte i = put s (Char.chr (i land 0xff)) + let word16 i = byte (i land 0xff); byte (i lsr 8) + let word32 i = + Int32.(word16 (to_int (logand i 0xffffl)); + word16 (to_int (shift_right i 16))) + let word64 i = + Int64.(word32 (to_int32 (logand i 0xffffffffL)); + word32 (to_int32 (shift_right i 32))) - let rec vu64 i = + let rec u64 i = let b = Int64.(to_int (logand i 0x7fL)) in - if 0L <= i && i < 128L then u8 b - else (u8 (b lor 0x80); vu64 (Int64.shift_right_logical i 7)) + if 0L <= i && i < 128L then byte b + else (byte (b lor 0x80); u64 (Int64.shift_right_logical i 7)) - let rec vs64 i = + let rec s64 i = let b = Int64.(to_int (logand i 0x7fL)) in - if -64L <= i && i < 64L then u8 b - else (u8 (b lor 0x80); vs64 (Int64.shift_right i 7)) - - let vu1 i = vu64 Int64.(logand (of_int i) 1L) - let vu32 i = vu64 Int64.(logand (of_int32 i) 0xffffffffL) - let vs7 i = vs64 (Int64.of_int i) - let vs32 i = vs64 (Int64.of_int32 i) - let vs33 i = vs64 (I64_convert.extend_i32_s i) - let f32 x = u32 (F32.to_bits x) - let f64 x = u64 (F64.to_bits x) + if -64L <= i && i < 64L then byte b + else (byte (b lor 0x80); s64 (Int64.shift_right i 7)) + + let u1 i = u64 Int64.(logand (of_int i) 1L) + let u32 i = u64 Int64.(logand (of_int32 i) 0xffffffffL) + let s7 i = s64 (Int64.of_int i) + let s32 i = s64 (Int64.of_int32 i) + let s33 i = s64 (I64_convert.extend_i32_s i) + let f32 x = word32 (F32.to_bits x) + let f64 x = word64 (F64.to_bits x) let v128 v = String.iter (put s) (V128.to_bits v) let len i = if Int32.to_int (Int32.of_int i) <> i then - Code.error Source.no_region - "cannot encode length with more than 32 bit"; - vu32 (Int32.of_int i) + Code.error Source.no_region "length out of bounds"; + u32 (Int32.of_int i) - let bool b = vu1 (if b then 1 else 0) + let bool b = u1 (if b then 1 else 0) let string bs = len (String.length bs); put_string s bs let name n = string (Utf8.encode n) let list f xs = List.iter f xs let opt f xo = Lib.Option.app f xo let vec f xs = len (List.length xs); list f xs - let gap32 () = let p = pos s in u32 0l; u8 0; p + let gap32 () = let p = pos s in word32 0l; byte 0; p let patch_gap32 p n = assert (n <= 0x0fff_ffff); (* Strings cannot excess 2G anyway *) let lsb i = Char.chr (i land 0xff) in @@ -88,22 +90,23 @@ struct patch s (p + 3) (lsb ((n lsr 21) lor 0x80)); patch s (p + 4) (lsb (n lsr 28)) + (* Types *) open Types let num_type = function - | I32Type -> vs7 (-0x01) - | I64Type -> vs7 (-0x02) - | F32Type -> vs7 (-0x03) - | F64Type -> vs7 (-0x04) + | I32Type -> s7 (-0x01) + | I64Type -> s7 (-0x02) + | F32Type -> s7 (-0x03) + | F64Type -> s7 (-0x04) let vec_type = function - | V128Type -> vs7 (-0x05) + | V128Type -> s7 (-0x05) let ref_type = function - | FuncRefType -> vs7 (-0x10) - | ExternRefType -> vs7 (-0x11) + | FuncRefType -> s7 (-0x10) + | ExternRefType -> s7 (-0x11) let value_type = function | NumType t -> num_type t @@ -112,43 +115,45 @@ struct let func_type = function | FuncType (ts1, ts2) -> - vs7 (-0x20); vec value_type ts1; vec value_type ts2 + s7 (-0x20); vec value_type ts1; vec value_type ts2 + let limits vu {min; max} = bool (max <> None); vu min; opt vu max let table_type = function - | TableType (lim, t) -> ref_type t; limits vu32 lim + | TableType (lim, t) -> ref_type t; limits u32 lim let memory_type = function - | MemoryType lim -> limits vu32 lim + | MemoryType lim -> limits u32 lim let mutability = function - | Immutable -> u8 0 - | Mutable -> u8 1 + | Immutable -> byte 0 + | Mutable -> byte 1 let global_type = function | GlobalType (t, mut) -> value_type t; mutability mut - (* Expressions *) + + (* Instructions *) open Source open Ast open Values open V128 - let op n = u8 n - let vecop n = op 0xfd; vu32 n + let op n = byte n + let vecop n = op 0xfd; u32 n let end_ () = op 0x0b - let memop {align; offset; _} = vu32 (Int32.of_int align); vu32 offset + let memop {align; offset; _} = u32 (Int32.of_int align); u32 offset - let var x = vu32 x.it + let var x = u32 x.it let block_type = function - | VarBlockType x -> vs33 x.it - | ValBlockType None -> vs7 (-0x40) + | ValBlockType None -> s33 (-0x40l) | ValBlockType (Some t) -> value_type t + | VarBlockType x -> s33 x.it let rec instr e = match e.it with @@ -181,12 +186,12 @@ struct | TableGet x -> op 0x25; var x | TableSet x -> op 0x26; var x - | TableSize x -> op 0xfc; vu32 0x10l; var x - | TableGrow x -> op 0xfc; vu32 0x0fl; var x - | TableFill x -> op 0xfc; vu32 0x11l; var x - | TableCopy (x, y) -> op 0xfc; vu32 0x0el; var x; var y - | TableInit (x, y) -> op 0xfc; vu32 0x0cl; var y; var x - | ElemDrop x -> op 0xfc; vu32 0x0dl; var x + | TableSize x -> op 0xfc; u32 0x10l; var x + | TableGrow x -> op 0xfc; u32 0x0fl; var x + | TableFill x -> op 0xfc; u32 0x11l; var x + | TableCopy (x, y) -> op 0xfc; u32 0x0el; var x; var y + | TableInit (x, y) -> op 0xfc; u32 0x0cl; var y; var x + | ElemDrop x -> op 0xfc; u32 0x0dl; var x | Load ({ty = I32Type; pack = None; _} as mo) -> op 0x28; memop mo | Load ({ty = I64Type; pack = None; _} as mo) -> op 0x29; memop mo @@ -201,7 +206,7 @@ struct | Load ({ty = I32Type; pack = Some (Pack16, ZX); _} as mo) -> op 0x2f; memop mo | Load {ty = I32Type; pack = Some (Pack32, _); _} -> - assert false + error e.at "illegal instruction i32.load32" | Load ({ty = I64Type; pack = Some (Pack8, SX); _} as mo) -> op 0x30; memop mo | Load ({ty = I64Type; pack = Some (Pack8, ZX); _} as mo) -> @@ -215,9 +220,9 @@ struct | Load ({ty = I64Type; pack = Some (Pack32, ZX); _} as mo) -> op 0x35; memop mo | Load {ty = F32Type | F64Type; pack = Some _; _} -> - assert false + error e.at "illegal instruction fxx.loadN" | Load {ty = I32Type | I64Type; pack = Some (Pack64, _); _} -> - assert false + error e.at "illegal instruction ixx.load64" | Store ({ty = I32Type; pack = None; _} as mo) -> op 0x36; memop mo | Store ({ty = I64Type; pack = None; _} as mo) -> op 0x37; memop mo @@ -225,12 +230,15 @@ struct | Store ({ty = F64Type; pack = None; _} as mo) -> op 0x39; memop mo | Store ({ty = I32Type; pack = Some Pack8; _} as mo) -> op 0x3a; memop mo | Store ({ty = I32Type; pack = Some Pack16; _} as mo) -> op 0x3b; memop mo - | Store {ty = I32Type; pack = Some Pack32; _} -> assert false + | Store {ty = I32Type; pack = Some Pack32; _} -> + error e.at "illegal instruction i32.store32" | Store ({ty = I64Type; pack = Some Pack8; _} as mo) -> op 0x3c; memop mo | Store ({ty = I64Type; pack = Some Pack16; _} as mo) -> op 0x3d; memop mo | Store ({ty = I64Type; pack = Some Pack32; _} as mo) -> op 0x3e; memop mo - | Store {ty = F32Type | F64Type; pack = Some _; _} -> assert false - | Store {ty = (I32Type | I64Type); pack = Some Pack64; _} -> assert false + | Store {ty = F32Type | F64Type; pack = Some _; _} -> + error e.at "illegal instruction fxx.storeN" + | Store {ty = (I32Type | I64Type); pack = Some Pack64; _} -> + error e.at "illegal instruction ixx.store64" | VecLoad ({ty = V128Type; pack = None; _} as mo) -> vecop 0x00l; memop mo @@ -258,41 +266,42 @@ struct vecop 0x5cl; memop mo | VecLoad ({ty = V128Type; pack = Some (Pack64, ExtZero); _} as mo) -> vecop 0x5dl; memop mo - | VecLoad _ -> assert false + | VecLoad _ -> + error e.at "illegal instruction v128.loadNxM_" | VecLoadLane ({ty = V128Type; pack = Pack8; _} as mo, i) -> - vecop 0x54l; memop mo; u8 i; + vecop 0x54l; memop mo; byte i; | VecLoadLane ({ty = V128Type; pack = Pack16; _} as mo, i) -> - vecop 0x55l; memop mo; u8 i; + vecop 0x55l; memop mo; byte i; | VecLoadLane ({ty = V128Type; pack = Pack32; _} as mo, i) -> - vecop 0x56l; memop mo; u8 i; + vecop 0x56l; memop mo; byte i; | VecLoadLane ({ty = V128Type; pack = Pack64; _} as mo, i) -> - vecop 0x57l; memop mo; u8 i; + vecop 0x57l; memop mo; byte i; | VecStore ({ty = V128Type; _} as mo) -> vecop 0x0bl; memop mo | VecStoreLane ({ty = V128Type; pack = Pack8; _} as mo, i) -> - vecop 0x58l; memop mo; u8 i; + vecop 0x58l; memop mo; byte i; | VecStoreLane ({ty = V128Type; pack = Pack16; _} as mo, i) -> - vecop 0x59l; memop mo; u8 i; + vecop 0x59l; memop mo; byte i; | VecStoreLane ({ty = V128Type; pack = Pack32; _} as mo, i) -> - vecop 0x5al; memop mo; u8 i; + vecop 0x5al; memop mo; byte i; | VecStoreLane ({ty = V128Type; pack = Pack64; _} as mo, i) -> - vecop 0x5bl; memop mo; u8 i; + vecop 0x5bl; memop mo; byte i; - | MemorySize -> op 0x3f; u8 0x00 - | MemoryGrow -> op 0x40; u8 0x00 - | MemoryFill -> op 0xfc; vu32 0x0bl; u8 0x00 - | MemoryCopy -> op 0xfc; vu32 0x0al; u8 0x00; u8 0x00 - | MemoryInit x -> op 0xfc; vu32 0x08l; var x; u8 0x00 - | DataDrop x -> op 0xfc; vu32 0x09l; var x + | MemorySize -> op 0x3f; byte 0x00 + | MemoryGrow -> op 0x40; byte 0x00 + | MemoryFill -> op 0xfc; u32 0x0bl; byte 0x00 + | MemoryCopy -> op 0xfc; u32 0x0al; byte 0x00; byte 0x00 + | MemoryInit x -> op 0xfc; u32 0x08l; var x; byte 0x00 + | DataDrop x -> op 0xfc; u32 0x09l; var x | RefNull t -> op 0xd0; ref_type t | RefIsNull -> op 0xd1 | RefFunc x -> op 0xd2; var x - | Const {it = I32 c; _} -> op 0x41; vs32 c - | Const {it = I64 c; _} -> op 0x42; vs64 c + | Const {it = I32 c; _} -> op 0x41; s32 c + | Const {it = I64 c; _} -> op 0x42; s64 c | Const {it = F32 c; _} -> op 0x43; f32 c | Const {it = F64 c; _} -> op 0x44; f64 c @@ -341,7 +350,8 @@ struct | Unary (I32 I32Op.Popcnt) -> op 0x69 | Unary (I32 (I32Op.ExtendS Pack8)) -> op 0xc0 | Unary (I32 (I32Op.ExtendS Pack16)) -> op 0xc1 - | Unary (I32 (I32Op.ExtendS (Pack32 | Pack64))) -> assert false + | Unary (I32 (I32Op.ExtendS (Pack32 | Pack64))) -> + error e.at "illegal instruction i32.extendN_s" | Unary (I64 I64Op.Clz) -> op 0x79 | Unary (I64 I64Op.Ctz) -> op 0x7a @@ -349,7 +359,8 @@ struct | Unary (I64 (I64Op.ExtendS Pack8)) -> op 0xc2 | Unary (I64 (I64Op.ExtendS Pack16)) -> op 0xc3 | Unary (I64 (I64Op.ExtendS Pack32)) -> op 0xc4 - | Unary (I64 (I64Op.ExtendS Pack64)) -> assert false + | Unary (I64 (I64Op.ExtendS Pack64)) -> + error e.at "illegal instruction i64.extend64_s" | Unary (F32 F32Op.Abs) -> op 0x8b | Unary (F32 F32Op.Neg) -> op 0x8c @@ -415,37 +426,41 @@ struct | Binary (F64 F64Op.Max) -> op 0xa5 | Binary (F64 F64Op.CopySign) -> op 0xa6 - | Convert (I32 I32Op.ExtendSI32) -> assert false - | Convert (I32 I32Op.ExtendUI32) -> assert false + | Convert (I32 I32Op.ExtendSI32) -> + error e.at "illegal instruction i32.extend_i32_s" + | Convert (I32 I32Op.ExtendUI32) -> + error e.at "illegal instruction i32.extend_i32_u" | Convert (I32 I32Op.WrapI64) -> op 0xa7 | Convert (I32 I32Op.TruncSF32) -> op 0xa8 | Convert (I32 I32Op.TruncUF32) -> op 0xa9 | Convert (I32 I32Op.TruncSF64) -> op 0xaa | Convert (I32 I32Op.TruncUF64) -> op 0xab - | Convert (I32 I32Op.TruncSatSF32) -> op 0xfc; vu32 0x00l - | Convert (I32 I32Op.TruncSatUF32) -> op 0xfc; vu32 0x01l - | Convert (I32 I32Op.TruncSatSF64) -> op 0xfc; vu32 0x02l - | Convert (I32 I32Op.TruncSatUF64) -> op 0xfc; vu32 0x03l + | Convert (I32 I32Op.TruncSatSF32) -> op 0xfc; u32 0x00l + | Convert (I32 I32Op.TruncSatUF32) -> op 0xfc; u32 0x01l + | Convert (I32 I32Op.TruncSatSF64) -> op 0xfc; u32 0x02l + | Convert (I32 I32Op.TruncSatUF64) -> op 0xfc; u32 0x03l | Convert (I32 I32Op.ReinterpretFloat) -> op 0xbc | Convert (I64 I64Op.ExtendSI32) -> op 0xac | Convert (I64 I64Op.ExtendUI32) -> op 0xad - | Convert (I64 I64Op.WrapI64) -> assert false + | Convert (I64 I64Op.WrapI64) -> + error e.at "illegal instruction i64.wrap_i64" | Convert (I64 I64Op.TruncSF32) -> op 0xae | Convert (I64 I64Op.TruncUF32) -> op 0xaf | Convert (I64 I64Op.TruncSF64) -> op 0xb0 | Convert (I64 I64Op.TruncUF64) -> op 0xb1 - | Convert (I64 I64Op.TruncSatSF32) -> op 0xfc; vu32 0x04l - | Convert (I64 I64Op.TruncSatUF32) -> op 0xfc; vu32 0x05l - | Convert (I64 I64Op.TruncSatSF64) -> op 0xfc; vu32 0x06l - | Convert (I64 I64Op.TruncSatUF64) -> op 0xfc; vu32 0x07l + | Convert (I64 I64Op.TruncSatSF32) -> op 0xfc; u32 0x04l + | Convert (I64 I64Op.TruncSatUF32) -> op 0xfc; u32 0x05l + | Convert (I64 I64Op.TruncSatSF64) -> op 0xfc; u32 0x06l + | Convert (I64 I64Op.TruncSatUF64) -> op 0xfc; u32 0x07l | Convert (I64 I64Op.ReinterpretFloat) -> op 0xbd | Convert (F32 F32Op.ConvertSI32) -> op 0xb2 | Convert (F32 F32Op.ConvertUI32) -> op 0xb3 | Convert (F32 F32Op.ConvertSI64) -> op 0xb4 | Convert (F32 F32Op.ConvertUI64) -> op 0xb5 - | Convert (F32 F32Op.PromoteF32) -> assert false + | Convert (F32 F32Op.PromoteF32) -> + error e.at "illegal instruction f32.promote_f32" | Convert (F32 F32Op.DemoteF64) -> op 0xb6 | Convert (F32 F32Op.ReinterpretInt) -> op 0xbe @@ -454,7 +469,8 @@ struct | Convert (F64 F64Op.ConvertSI64) -> op 0xb9 | Convert (F64 F64Op.ConvertUI64) -> op 0xba | Convert (F64 F64Op.PromoteF32) -> op 0xbb - | Convert (F64 F64Op.DemoteF64) -> assert false + | Convert (F64 F64Op.DemoteF64) -> + error e.at "illegal instruction f64.demote_f64" | Convert (F64 F64Op.ReinterpretInt) -> op 0xbf | VecConst {it = V128 c; _} -> vecop 0x0cl; v128 c @@ -470,13 +486,16 @@ struct | VecUnary (V128 (I8x16 V128Op.Popcnt)) -> vecop 0x62l | VecUnary (V128 (I16x8 V128Op.Abs)) -> vecop 0x80l | VecUnary (V128 (I16x8 V128Op.Neg)) -> vecop 0x81l - | VecUnary (V128 (I16x8 V128Op.Popcnt)) -> assert false + | VecUnary (V128 (I16x8 V128Op.Popcnt)) -> + error e.at "illegal instruction i16x8.popcnt" | VecUnary (V128 (I32x4 V128Op.Abs)) -> vecop 0xa0l | VecUnary (V128 (I32x4 V128Op.Neg)) -> vecop 0xa1l - | VecUnary (V128 (I32x4 V128Op.Popcnt)) -> assert false + | VecUnary (V128 (I32x4 V128Op.Popcnt)) -> + error e.at "illegal instruction i32x4.popcnt" | VecUnary (V128 (I64x2 V128Op.Abs)) -> vecop 0xc0l | VecUnary (V128 (I64x2 V128Op.Neg)) -> vecop 0xc1l - | VecUnary (V128 (I64x2 V128Op.Popcnt)) -> assert false + | VecUnary (V128 (I64x2 V128Op.Popcnt)) -> + error e.at "illegal instruction i64x2.popcnt" | VecUnary (V128 (F32x4 V128Op.Ceil)) -> vecop 0x67l | VecUnary (V128 (F32x4 V128Op.Floor)) -> vecop 0x68l | VecUnary (V128 (F32x4 V128Op.Trunc)) -> vecop 0x69l @@ -525,13 +544,17 @@ struct | VecCompare (V128 (I64x2 V128Op.Eq)) -> vecop 0xd6l | VecCompare (V128 (I64x2 V128Op.Ne)) -> vecop 0xd7l | VecCompare (V128 (I64x2 V128Op.LtS)) -> vecop 0xd8l - | VecCompare (V128 (I64x2 V128Op.LtU)) -> assert false + | VecCompare (V128 (I64x2 V128Op.LtU)) -> + error e.at "illegal instruction i64x2.lt_u" | VecCompare (V128 (I64x2 V128Op.GtS)) -> vecop 0xd9l - | VecCompare (V128 (I64x2 V128Op.GtU)) -> assert false + | VecCompare (V128 (I64x2 V128Op.GtU)) -> + error e.at "illegal instruction i64x2.gt_u" | VecCompare (V128 (I64x2 V128Op.LeS)) -> vecop 0xdal - | VecCompare (V128 (I64x2 V128Op.LeU)) -> assert false + | VecCompare (V128 (I64x2 V128Op.LeU)) -> + error e.at "illegal instruction i64x2.le_u" | VecCompare (V128 (I64x2 V128Op.GeS)) -> vecop 0xdbl - | VecCompare (V128 (I64x2 V128Op.GeU)) -> assert false + | VecCompare (V128 (I64x2 V128Op.GeU)) -> + error e.at "illegal instruction i64x2.ge_u" | VecCompare (V128 (F32x4 V128Op.Eq)) -> vecop 0x41l | VecCompare (V128 (F32x4 V128Op.Ne)) -> vecop 0x42l | VecCompare (V128 (F32x4 V128Op.Lt)) -> vecop 0x43l @@ -545,7 +568,7 @@ struct | VecCompare (V128 (F64x2 V128Op.Le)) -> vecop 0x4bl | VecCompare (V128 (F64x2 V128Op.Ge)) -> vecop 0x4cl - | VecBinary (V128 (I8x16 (V128Op.Shuffle is))) -> vecop 0x0dl; List.iter u8 is + | VecBinary (V128 (I8x16 (V128Op.Shuffle is))) -> vecop 0x0dl; List.iter byte is | VecBinary (V128 (I8x16 V128Op.Swizzle)) -> vecop 0x0el | VecBinary (V128 (I8x16 V128Op.NarrowS)) -> vecop 0x65l | VecBinary (V128 (I8x16 V128Op.NarrowU)) -> vecop 0x66l @@ -614,16 +637,19 @@ struct | VecBinary (V128 (F64x2 V128Op.Max)) -> vecop 0xf5l | VecBinary (V128 (F64x2 V128Op.Pmin)) -> vecop 0xf6l | VecBinary (V128 (F64x2 V128Op.Pmax)) -> vecop 0xf7l - | VecBinary (V128 _) -> assert false + | VecBinary (V128 _) -> + error e.at "illegal binary vector instruction" - | VecConvert (V128 (I8x16 _)) -> assert false + | VecConvert (V128 (I8x16 _)) -> + error e.at "illegal i8x16 conversion instruction" | VecConvert (V128 (I16x8 V128Op.ExtendLowS)) -> vecop 0x87l | VecConvert (V128 (I16x8 V128Op.ExtendHighS)) -> vecop 0x88l | VecConvert (V128 (I16x8 V128Op.ExtendLowU)) -> vecop 0x89l | VecConvert (V128 (I16x8 V128Op.ExtendHighU)) -> vecop 0x8al | VecConvert (V128 (I16x8 V128Op.ExtAddPairwiseS)) -> vecop 0x7cl | VecConvert (V128 (I16x8 V128Op.ExtAddPairwiseU)) -> vecop 0x7dl - | VecConvert (V128 (I16x8 _)) -> assert false + | VecConvert (V128 (I16x8 _)) -> + error e.at "illegal i16x8 conversion instruction" | VecConvert (V128 (I32x4 V128Op.ExtendLowS)) -> vecop 0xa7l | VecConvert (V128 (I32x4 V128Op.ExtendHighS)) -> vecop 0xa8l | VecConvert (V128 (I32x4 V128Op.ExtendLowU)) -> vecop 0xa9l @@ -638,12 +664,15 @@ struct | VecConvert (V128 (I64x2 V128Op.ExtendHighS)) -> vecop 0xc8l | VecConvert (V128 (I64x2 V128Op.ExtendLowU)) -> vecop 0xc9l | VecConvert (V128 (I64x2 V128Op.ExtendHighU)) -> vecop 0xcal - | VecConvert (V128 (I64x2 _)) -> assert false + | VecConvert (V128 (I64x2 _)) -> + error e.at "illegal i64x2 conversion instruction" | VecConvert (V128 (F32x4 V128Op.DemoteZeroF64x2)) -> vecop 0x5el - | VecConvert (V128 (F32x4 V128Op.PromoteLowF32x4)) -> assert false + | VecConvert (V128 (F32x4 V128Op.PromoteLowF32x4)) -> + error e.at "illegal instruction f32x4.promote_low_f32x4" | VecConvert (V128 (F32x4 V128Op.ConvertSI32x4)) -> vecop 0xfal | VecConvert (V128 (F32x4 V128Op.ConvertUI32x4)) -> vecop 0xfbl - | VecConvert (V128 (F64x2 V128Op.DemoteZeroF64x2)) -> assert false + | VecConvert (V128 (F64x2 V128Op.DemoteZeroF64x2)) -> + error e.at "illegal instruction f64x2.demote_zero_f64x2" | VecConvert (V128 (F64x2 V128Op.PromoteLowF32x4)) -> vecop 0x5fl | VecConvert (V128 (F64x2 V128Op.ConvertSI32x4)) -> vecop 0xfel | VecConvert (V128 (F64x2 V128Op.ConvertUI32x4)) -> vecop 0xffl @@ -683,49 +712,54 @@ struct | VecSplat (V128 ((F32x4 V128Op.Splat))) -> vecop 0x13l | VecSplat (V128 ((F64x2 V128Op.Splat))) -> vecop 0x14l - | VecExtract (V128 (I8x16 (V128Op.Extract (i, SX)))) -> vecop 0x15l; u8 i - | VecExtract (V128 (I8x16 (V128Op.Extract (i, ZX)))) -> vecop 0x16l; u8 i - | VecExtract (V128 (I16x8 (V128Op.Extract (i, SX)))) -> vecop 0x18l; u8 i - | VecExtract (V128 (I16x8 (V128Op.Extract (i, ZX)))) -> vecop 0x19l; u8 i - | VecExtract (V128 (I32x4 (V128Op.Extract (i, ())))) -> vecop 0x1bl; u8 i - | VecExtract (V128 (I64x2 (V128Op.Extract (i, ())))) -> vecop 0x1dl; u8 i - | VecExtract (V128 (F32x4 (V128Op.Extract (i, ())))) -> vecop 0x1fl; u8 i - | VecExtract (V128 (F64x2 (V128Op.Extract (i, ())))) -> vecop 0x21l; u8 i - - | VecReplace (V128 (I8x16 (V128Op.Replace i))) -> vecop 0x17l; u8 i - | VecReplace (V128 (I16x8 (V128Op.Replace i))) -> vecop 0x1al; u8 i - | VecReplace (V128 (I32x4 (V128Op.Replace i))) -> vecop 0x1cl; u8 i - | VecReplace (V128 (I64x2 (V128Op.Replace i))) -> vecop 0x1el; u8 i - | VecReplace (V128 (F32x4 (V128Op.Replace i))) -> vecop 0x20l; u8 i - | VecReplace (V128 (F64x2 (V128Op.Replace i))) -> vecop 0x22l; u8 i + | VecExtract (V128 (I8x16 (V128Op.Extract (i, SX)))) -> vecop 0x15l; byte i + | VecExtract (V128 (I8x16 (V128Op.Extract (i, ZX)))) -> vecop 0x16l; byte i + | VecExtract (V128 (I16x8 (V128Op.Extract (i, SX)))) -> vecop 0x18l; byte i + | VecExtract (V128 (I16x8 (V128Op.Extract (i, ZX)))) -> vecop 0x19l; byte i + | VecExtract (V128 (I32x4 (V128Op.Extract (i, ())))) -> vecop 0x1bl; byte i + | VecExtract (V128 (I64x2 (V128Op.Extract (i, ())))) -> vecop 0x1dl; byte i + | VecExtract (V128 (F32x4 (V128Op.Extract (i, ())))) -> vecop 0x1fl; byte i + | VecExtract (V128 (F64x2 (V128Op.Extract (i, ())))) -> vecop 0x21l; byte i + + | VecReplace (V128 (I8x16 (V128Op.Replace i))) -> vecop 0x17l; byte i + | VecReplace (V128 (I16x8 (V128Op.Replace i))) -> vecop 0x1al; byte i + | VecReplace (V128 (I32x4 (V128Op.Replace i))) -> vecop 0x1cl; byte i + | VecReplace (V128 (I64x2 (V128Op.Replace i))) -> vecop 0x1el; byte i + | VecReplace (V128 (F32x4 (V128Op.Replace i))) -> vecop 0x20l; byte i + | VecReplace (V128 (F64x2 (V128Op.Replace i))) -> vecop 0x22l; byte i let const c = list instr c.it; end_ () + (* Sections *) let section id f x needed = if needed then begin - u8 id; + byte id; let g = gap32 () in let p = pos s in f x; patch_gap32 g (pos s - p) end + (* Type section *) + let type_ t = func_type t.it let type_section ts = section 1 (vec type_) ts (ts <> []) + (* Import section *) + let import_desc d = match d.it with - | FuncImport x -> u8 0x00; var x - | TableImport t -> u8 0x01; table_type t - | MemoryImport t -> u8 0x02; memory_type t - | GlobalImport t -> u8 0x03; global_type t + | FuncImport x -> byte 0x00; var x + | TableImport t -> byte 0x01; table_type t + | MemoryImport t -> byte 0x02; memory_type t + | GlobalImport t -> byte 0x03; global_type t let import im = let {module_name; item_name; idesc} = im.it in @@ -734,13 +768,17 @@ struct let import_section ims = section 2 (vec import) ims (ims <> []) + (* Function section *) + let func f = var f.it.ftype let func_section fs = section 3 (vec func) fs (fs <> []) + (* Table section *) + let table tab = let {ttype} = tab.it in table_type ttype @@ -748,7 +786,9 @@ struct let table_section tabs = section 4 (vec table) tabs (tabs <> []) + (* Memory section *) + let memory mem = let {mtype} = mem.it in memory_type mtype @@ -756,7 +796,9 @@ struct let memory_section mems = section 5 (vec memory) mems (mems <> []) + (* Global section *) + let global g = let {gtype; ginit} = g.it in global_type gtype; const ginit @@ -764,13 +806,15 @@ struct let global_section gs = section 6 (vec global) gs (gs <> []) + (* Export section *) + let export_desc d = match d.it with - | FuncExport x -> u8 0; var x - | TableExport x -> u8 1; var x - | MemoryExport x -> u8 2; var x - | GlobalExport x -> u8 3; var x + | FuncExport x -> byte 0; var x + | TableExport x -> byte 1; var x + | MemoryExport x -> byte 2; var x + | GlobalExport x -> byte 3; var x let export ex = let {name = n; edesc} = ex.it in @@ -779,7 +823,9 @@ struct let export_section exs = section 7 (vec export) exs (exs <> []) + (* Start section *) + let start st = let {sfunc} = st.it in var sfunc @@ -787,20 +833,22 @@ struct let start_section xo = section 8 (opt start) xo (xo <> None) + (* Code section *) - let compress ts = + + let local (t, n) = len n; value_type t + + let locals locs = let combine t = function | (t', n) :: ts when t = t' -> (t, n + 1) :: ts | ts -> (t, 1) :: ts - in List.fold_right combine ts [] - - let local (t, n) = len n; value_type t + in vec local (List.fold_right combine locs []) let code f = - let {locals; body; _} = f.it in + let {locals = locs; body; _} = f.it in let g = gap32 () in let p = pos s in - vec local (compress locals); + locals locs; list instr body; end_ (); patch_gap32 g (pos s - p) @@ -808,13 +856,15 @@ struct let code_section fs = section 10 (vec code) fs (fs <> []) + (* Element section *) + let is_elem_kind = function | FuncRefType -> true | _ -> false let elem_kind = function - | FuncRefType -> u8 0x00 + | FuncRefType -> byte 0x00 | _ -> assert false let is_elem_index e = @@ -832,49 +882,55 @@ struct if is_elem_kind etype && List.for_all is_elem_index einit then match emode.it with | Passive -> - vu32 0x01l; elem_kind etype; vec elem_index einit - | Active {index; offset} when index.it = 0l && etype = FuncRefType -> - vu32 0x00l; const offset; vec elem_index einit + u32 0x01l; elem_kind etype; vec elem_index einit + | Active {index; offset} when index.it = 0l && is_elem_kind etype -> + u32 0x00l; const offset; vec elem_index einit | Active {index; offset} -> - vu32 0x02l; + u32 0x02l; var index; const offset; elem_kind etype; vec elem_index einit | Declarative -> - vu32 0x03l; elem_kind etype; vec elem_index einit + u32 0x03l; elem_kind etype; vec elem_index einit else match emode.it with | Passive -> - vu32 0x05l; ref_type etype; vec const einit - | Active {index; offset} when index.it = 0l && etype = FuncRefType -> - vu32 0x04l; const offset; vec const einit + u32 0x05l; ref_type etype; vec const einit + | Active {index; offset} when index.it = 0l && is_elem_kind etype -> + u32 0x04l; const offset; vec const einit | Active {index; offset} -> - vu32 0x06l; var index; const offset; ref_type etype; vec const einit + u32 0x06l; var index; const offset; ref_type etype; vec const einit | Declarative -> - vu32 0x07l; ref_type etype; vec const einit + u32 0x07l; ref_type etype; vec const einit let elem_section elems = section 9 (vec elem) elems (elems <> []) + (* Data section *) + let data seg = let {dinit; dmode} = seg.it in match dmode.it with | Passive -> - vu32 0x01l; string dinit + u32 0x01l; string dinit | Active {index; offset} when index.it = 0l -> - vu32 0x00l; const offset; string dinit + u32 0x00l; const offset; string dinit | Active {index; offset} -> - vu32 0x02l; var index; const offset; string dinit + u32 0x02l; var index; const offset; string dinit | Declarative -> - assert false + error dmode.at "illegal declarative data segment" let data_section datas = section 11 (vec data) datas (datas <> []) + (* Data count section *) + let data_count_section datas m = section 12 len (List.length datas) Free.((module_ m).datas <> Set.empty) + (* Custom section *) + let custom (n, bs) = name n; put_string s bs @@ -882,10 +938,12 @@ struct let custom_section n bs = section 0 custom (n, bs) true + (* Module *) + let module_ m = - u32 0x6d736100l; - u32 version; + word32 0x6d736100l; + word32 version; type_section m.it.types; import_section m.it.imports; func_section m.it.funcs;