blob: 884592772c1fb411a1e44880341dad9128e358b6 [file] [log] [blame] [edit]
(* Binary format version *)
let version = 1l
(* Errors *)
module Code = Error.Make ()
exception Code = Code.Error
let error = Code.error
(* Encoding stream *)
type stream =
{
buf : Buffer.t;
patches : (int * char) list ref
}
let stream () = {buf = Buffer.create 8192; patches = ref []}
let pos s = Buffer.length s.buf
let put s b = Buffer.add_char s.buf b
let put_string s bs = Buffer.add_string s.buf bs
let patch s pos b = s.patches := (pos, b) :: !(s.patches)
let to_string s =
let bs = Buffer.to_bytes s.buf in
List.iter (fun (pos, b) -> Bytes.set bs pos b) !(s.patches);
Bytes.to_string bs
(* Encoding *)
module E (S : sig val stream : stream end) =
struct
let s = S.stream
(* Generic values *)
let bit i b = (if b then 1 else 0) lsl i
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 u64 i =
let b = Int64.(to_int (logand i 0x7fL)) in
if 0L <= i && i < 128L then byte b
else (byte (b lor 0x80); u64 (Int64.shift_right_logical i 7))
let rec s64 i =
let b = Int64.(to_int (logand i 0x7fL)) in
if -64L <= i && i < 64L then byte b
else (byte (b lor 0x80); s64 (Int64.shift_right i 7))
let u8 i = u64 Int64.(logand (of_int (I8.to_int_u i)) 0xffL)
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 (Convert.I64_.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 flag b i = if b then 1 lsl i else 0
let len i =
if Int32.to_int (Int32.of_int i) <> i then
Code.error Source.no_region "length out of bounds";
u32 (Int32.of_int i)
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 = Option.iter f xo
let vec f xs = len (List.length xs); list f xs
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
patch s p (lsb (n lor 0x80));
patch s (p + 1) (lsb ((n lsr 7) lor 0x80));
patch s (p + 2) (lsb ((n lsr 14) lor 0x80));
patch s (p + 3) (lsb ((n lsr 21) lor 0x80));
patch s (p + 4) (lsb (n lsr 28))
(* Types *)
open Types
open Source
let idx x = u32 x.it
let mutability = function
| Cons -> byte 0
| Var -> byte 1
let typeuse idx = function
| Idx x -> idx x
| Rec _ | Def _ -> assert false
let numtype = function
| I32T -> s7 (-0x01)
| I64T -> s7 (-0x02)
| F32T -> s7 (-0x03)
| F64T -> s7 (-0x04)
let vectype = function
| V128T -> s7 (-0x05)
let heaptype = function
| AnyHT -> s7 (-0x12)
| EqHT -> s7 (-0x13)
| I31HT -> s7 (-0x14)
| StructHT -> s7 (-0x15)
| ArrayHT -> s7 (-0x16)
| NoneHT -> s7 (-0x0f)
| FuncHT -> s7 (-0x10)
| NoFuncHT -> s7 (-0x0d)
| ExnHT -> s7 (-0x17)
| NoExnHT -> s7 (-0x0c)
| ExternHT -> s7 (-0x11)
| NoExternHT -> s7 (-0x0e)
| UseHT ut -> typeuse s33 ut
| BotHT -> assert false
let reftype = function
| (Null, AnyHT) -> s7 (-0x12)
| (Null, EqHT) -> s7 (-0x13)
| (Null, I31HT) -> s7 (-0x14)
| (Null, StructHT) -> s7 (-0x15)
| (Null, ArrayHT) -> s7 (-0x16)
| (Null, NoneHT) -> s7 (-0x0f)
| (Null, FuncHT) -> s7 (-0x10)
| (Null, NoFuncHT) -> s7 (-0x0d)
| (Null, ExnHT) -> s7 (-0x17)
| (Null, NoExnHT) -> s7 (-0x0c)
| (Null, ExternHT) -> s7 (-0x11)
| (Null, NoExternHT) -> s7 (-0x0e)
| (Null, t) -> s7 (-0x1d); heaptype t
| (NoNull, t) -> s7 (-0x1c); heaptype t
let valtype = function
| NumT t -> numtype t
| VecT t -> vectype t
| RefT t -> reftype t
| BotT -> assert false
let resulttype ts = vec valtype ts
let packtype = function
| I8T -> s7 (-0x08)
| I16T -> s7 (-0x09)
let storagetype = function
| ValStorageT t -> valtype t
| PackStorageT t -> packtype t
let fieldtype = function
| FieldT (mut, t) -> storagetype t; mutability mut
let comptype = function
| StructT fts -> s7 (-0x21); vec fieldtype fts
| ArrayT ft -> s7 (-0x22); fieldtype ft
| FuncT (ts1, ts2) -> s7 (-0x20); resulttype ts1; resulttype ts2
let subtype = function
| SubT (Final, [], ct) -> comptype ct
| SubT (Final, uts, ct) -> s7 (-0x31); vec (typeuse u32) uts; comptype ct
| SubT (NoFinal, uts, ct) -> s7 (-0x30); vec (typeuse u32) uts; comptype ct
let rectype = function
| RecT [st] -> subtype st
| RecT sts -> s7 (-0x32); vec subtype sts
let limits at {min; max} =
let flags = flag (max <> None) 0 + flag (at = I64AT) 2 in
byte flags; u64 min; opt u64 max
let tagtype = function
| TagT ut -> u32 0x00l; typeuse u32 ut
let globaltype = function
| GlobalT (mut, t) -> valtype t; mutability mut
let memorytype = function
| MemoryT (at, lim) -> limits at lim
let tabletype = function
| TableT (at, lim, t) -> reftype t; limits at lim
let externtype = function
| ExternFuncT ut -> byte 0x00; typeuse u32 ut
| ExternTableT tt -> byte 0x01; tabletype tt
| ExternMemoryT mt -> byte 0x02; memorytype mt
| ExternGlobalT gt -> byte 0x03; globaltype gt
| ExternTagT tt -> byte 0x04; tagtype tt
(* Expressions *)
open Ast
open Value
open V128
open Pack
let op n = byte n
let vecop n = op 0xfd; u32 n
let end_ () = op 0x0b
let memop x {align; offset; _} =
let has_idx = x.it <> 0l in
let flags =
Int32.(logor (of_int align) (if has_idx then 0x40l else 0x00l)) in
u32 flags;
if has_idx then idx x;
u64 offset
let blocktype = function
| VarBlockType x -> typeuse s33 (Idx x.it)
| ValBlockType None -> s33 (-0x40l)
| ValBlockType (Some t) -> valtype t
let local (n, loc) =
let Local t = loc.it in
len n; valtype t
let locals locs =
let combine loc = function
| (n, loc') :: nlocs' when loc.it = loc'.it -> (n + 1, loc') :: nlocs'
| nlocs -> (1, loc) :: nlocs
in vec local (List.fold_right combine locs [])
let rec instr e =
match e.it with
| Unreachable -> op 0x00
| Nop -> op 0x01
| Drop -> op 0x1a
| Select None -> op 0x1b
| Select (Some ts) -> op 0x1c; vec valtype ts
| Block (bt, es) -> op 0x02; blocktype bt; list instr es; end_ ()
| Loop (bt, es) -> op 0x03; blocktype bt; list instr es; end_ ()
| If (bt, es1, es2) ->
op 0x04; blocktype bt; list instr es1;
if es2 <> [] then op 0x05;
list instr es2; end_ ()
| TryTable (bt, cs, es) ->
op 0x1f; blocktype bt; vec catch cs; list instr es; end_ ()
| Br x -> op 0x0c; idx x
| BrIf x -> op 0x0d; idx x
| BrTable (xs, x) -> op 0x0e; vec idx xs; idx x
| BrOnNull x -> op 0xd5; idx x
| BrOnNonNull x -> op 0xd6; idx x
| BrOnCast (x, (nul1, t1), (nul2, t2)) ->
let flags = bit 0 (nul1 = Null) + bit 1 (nul2 = Null) in
op 0xfb; op 0x18; byte flags; idx x; heaptype t1; heaptype t2
| BrOnCastFail (x, (nul1, t1), (nul2, t2)) ->
let flags = bit 0 (nul1 = Null) + bit 1 (nul2 = Null) in
op 0xfb; op 0x19; byte flags; idx x; heaptype t1; heaptype t2
| Return -> op 0x0f
| Call x -> op 0x10; idx x
| CallRef x -> op 0x14; idx x
| CallIndirect (x, y) -> op 0x11; idx y; idx x
| ReturnCall x -> op 0x12; idx x
| ReturnCallRef x -> op 0x15; idx x
| ReturnCallIndirect (x, y) -> op 0x13; idx y; idx x
| Throw x -> op 0x08; idx x
| ThrowRef -> op 0x0a
| LocalGet x -> op 0x20; idx x
| LocalSet x -> op 0x21; idx x
| LocalTee x -> op 0x22; idx x
| GlobalGet x -> op 0x23; idx x
| GlobalSet x -> op 0x24; idx x
| TableGet x -> op 0x25; idx x
| TableSet x -> op 0x26; idx x
| TableSize x -> op 0xfc; u32 0x10l; idx x
| TableGrow x -> op 0xfc; u32 0x0fl; idx x
| TableFill x -> op 0xfc; u32 0x11l; idx x
| TableCopy (x, y) -> op 0xfc; u32 0x0el; idx x; idx y
| TableInit (x, y) -> op 0xfc; u32 0x0cl; idx y; idx x
| ElemDrop x -> op 0xfc; u32 0x0dl; idx x
| Load (x, ({ty = I32T; pack = None; _} as mo)) ->
op 0x28; memop x mo
| Load (x, ({ty = I64T; pack = None; _} as mo)) ->
op 0x29; memop x mo
| Load (x, ({ty = F32T; pack = None; _} as mo)) ->
op 0x2a; memop x mo
| Load (x, ({ty = F64T; pack = None; _} as mo)) ->
op 0x2b; memop x mo
| Load (x, ({ty = I32T; pack = Some (Pack8, S); _} as mo)) ->
op 0x2c; memop x mo
| Load (x, ({ty = I32T; pack = Some (Pack8, U); _} as mo)) ->
op 0x2d; memop x mo
| Load (x, ({ty = I32T; pack = Some (Pack16, S); _} as mo)) ->
op 0x2e; memop x mo
| Load (x, ({ty = I32T; pack = Some (Pack16, U); _} as mo)) ->
op 0x2f; memop x mo
| Load (x, ({ty = I32T; pack = Some (Pack32, _); _})) ->
error e.at "illegal instruction i32.load32"
| Load (x, ({ty = I64T; pack = Some (Pack8, S); _} as mo)) ->
op 0x30; memop x mo
| Load (x, ({ty = I64T; pack = Some (Pack8, U); _} as mo)) ->
op 0x31; memop x mo
| Load (x, ({ty = I64T; pack = Some (Pack16, S); _} as mo)) ->
op 0x32; memop x mo
| Load (x, ({ty = I64T; pack = Some (Pack16, U); _} as mo)) ->
op 0x33; memop x mo
| Load (x, ({ty = I64T; pack = Some (Pack32, S); _} as mo)) ->
op 0x34; memop x mo
| Load (x, ({ty = I64T; pack = Some (Pack32, U); _} as mo)) ->
op 0x35; memop x mo
| Load (x, ({ty = I32T | I64T; pack = Some (Pack64, _); _})) ->
error e.at "illegal instruction ixx.load64"
| Load (x, ({ty = F32T | F64T; pack = Some _; _})) ->
error e.at "illegal instruction fxx.loadN"
| Store (x, ({ty = I32T; pack = None; _} as mo)) ->
op 0x36; memop x mo
| Store (x, ({ty = I64T; pack = None; _} as mo)) ->
op 0x37; memop x mo
| Store (x, ({ty = F32T; pack = None; _} as mo)) ->
op 0x38; memop x mo
| Store (x, ({ty = F64T; pack = None; _} as mo)) ->
op 0x39; memop x mo
| Store (x, ({ty = I32T; pack = Some Pack8; _} as mo)) ->
op 0x3a; memop x mo
| Store (x, ({ty = I32T; pack = Some Pack16; _} as mo)) ->
op 0x3b; memop x mo
| Store (x, {ty = I32T; pack = Some Pack32; _}) ->
error e.at "illegal instruction i32.store32"
| Store (x, ({ty = I64T; pack = Some Pack8; _} as mo)) ->
op 0x3c; memop x mo
| Store (x, ({ty = I64T; pack = Some Pack16; _} as mo)) ->
op 0x3d; memop x mo
| Store (x, ({ty = I64T; pack = Some Pack32; _} as mo)) ->
op 0x3e; memop x mo
| Store (x, ({ty = I32T | I64T; pack = Some Pack64; _})) ->
error e.at "illegal instruction ixx.store64"
| Store (x, ({ty = F32T | F64T; pack = Some _; _})) ->
error e.at "illegal instruction fxx.storeN"
| VecLoad (x, ({ty = V128T; pack = None; _} as mo)) ->
vecop 0x00l; memop x mo
| VecLoad (x, ({ty = V128T; pack = Some (Pack64, ExtLane (Pack8x8, S)); _} as mo)) ->
vecop 0x01l; memop x mo
| VecLoad (x, ({ty = V128T; pack = Some (Pack64, ExtLane (Pack8x8, U)); _} as mo)) ->
vecop 0x02l; memop x mo
| VecLoad (x, ({ty = V128T; pack = Some (Pack64, ExtLane (Pack16x4, S)); _} as mo)) ->
vecop 0x03l; memop x mo
| VecLoad (x, ({ty = V128T; pack = Some (Pack64, ExtLane (Pack16x4, U)); _} as mo)) ->
vecop 0x04l; memop x mo
| VecLoad (x, ({ty = V128T; pack = Some (Pack64, ExtLane (Pack32x2, S)); _} as mo)) ->
vecop 0x05l; memop x mo
| VecLoad (x, ({ty = V128T; pack = Some (Pack64, ExtLane (Pack32x2, U)); _} as mo)) ->
vecop 0x06l; memop x mo
| VecLoad (x, ({ty = V128T; pack = Some (Pack8, ExtSplat); _} as mo)) ->
vecop 0x07l; memop x mo
| VecLoad (x, ({ty = V128T; pack = Some (Pack16, ExtSplat); _} as mo)) ->
vecop 0x08l; memop x mo
| VecLoad (x, ({ty = V128T; pack = Some (Pack32, ExtSplat); _} as mo)) ->
vecop 0x09l; memop x mo
| VecLoad (x, ({ty = V128T; pack = Some (Pack64, ExtSplat); _} as mo)) ->
vecop 0x0al; memop x mo
| VecLoad (x, ({ty = V128T; pack = Some (Pack32, ExtZero); _} as mo)) ->
vecop 0x5cl; memop x mo
| VecLoad (x, ({ty = V128T; pack = Some (Pack64, ExtZero); _} as mo)) ->
vecop 0x5dl; memop x mo
| VecLoad _ ->
error e.at "illegal instruction v128.loadNxM_x"
| VecLoadLane (x, ({ty = V128T; pack = Pack8; _} as mo), i) ->
vecop 0x54l; memop x mo; u8 i;
| VecLoadLane (x, ({ty = V128T; pack = Pack16; _} as mo), i) ->
vecop 0x55l; memop x mo; u8 i;
| VecLoadLane (x, ({ty = V128T; pack = Pack32; _} as mo), i) ->
vecop 0x56l; memop x mo; u8 i;
| VecLoadLane (x, ({ty = V128T; pack = Pack64; _} as mo), i) ->
vecop 0x57l; memop x mo; u8 i;
| VecStore (x, ({ty = V128T; _} as mo)) ->
vecop 0x0bl; memop x mo
| VecStoreLane (x, ({ty = V128T; pack = Pack8; _} as mo), i) ->
vecop 0x58l; memop x mo; u8 i;
| VecStoreLane (x, ({ty = V128T; pack = Pack16; _} as mo), i) ->
vecop 0x59l; memop x mo; u8 i;
| VecStoreLane (x, ({ty = V128T; pack = Pack32; _} as mo), i) ->
vecop 0x5al; memop x mo; u8 i;
| VecStoreLane (x, ({ty = V128T; pack = Pack64; _} as mo), i) ->
vecop 0x5bl; memop x mo; u8 i;
| MemorySize x -> op 0x3f; idx x
| MemoryGrow x -> op 0x40; idx x
| MemoryFill x -> op 0xfc; u32 0x0bl; idx x
| MemoryCopy (x, y) -> op 0xfc; u32 0x0al; idx x; idx y
| MemoryInit (x, y) -> op 0xfc; u32 0x08l; idx y; idx x
| DataDrop x -> op 0xfc; u32 0x09l; idx x
| RefNull t -> op 0xd0; heaptype t
| RefFunc x -> op 0xd2; idx x
| RefEq -> op 0xd3
| RefIsNull -> op 0xd1
| RefAsNonNull -> op 0xd4
| RefTest (NoNull, t) -> op 0xfb; op 0x14; heaptype t
| RefTest (Null, t) -> op 0xfb; op 0x15; heaptype t
| RefCast (NoNull, t) -> op 0xfb; op 0x16; heaptype t
| RefCast (Null, t) -> op 0xfb; op 0x17; heaptype t
| RefI31 -> op 0xfb; op 0x1c
| I31Get S -> op 0xfb; op 0x1d
| I31Get U -> op 0xfb; op 0x1e
| StructNew (x, Explicit) -> op 0xfb; op 0x00; idx x
| StructNew (x, Implicit) -> op 0xfb; op 0x01; idx x
| StructGet (x, i, None) -> op 0xfb; op 0x02; idx x; u32 i
| StructGet (x, i, Some S) -> op 0xfb; op 0x03; idx x; u32 i
| StructGet (x, i, Some U) -> op 0xfb; op 0x04; idx x; u32 i
| StructSet (x, i) -> op 0xfb; op 0x05; idx x; u32 i
| ArrayNew (x, Explicit) -> op 0xfb; op 0x06; idx x
| ArrayNew (x, Implicit) -> op 0xfb; op 0x07; idx x
| ArrayNewFixed (x, n) -> op 0xfb; op 0x08; idx x; u32 n
| ArrayNewElem (x, y) -> op 0xfb; op 0x0a; idx x; idx y
| ArrayNewData (x, y) -> op 0xfb; op 0x09; idx x; idx y
| ArrayGet (x, None) -> op 0xfb; op 0x0b; idx x
| ArrayGet (x, Some S) -> op 0xfb; op 0x0c; idx x
| ArrayGet (x, Some U) -> op 0xfb; op 0x0d; idx x
| ArraySet x -> op 0xfb; op 0x0e; idx x
| ArrayLen -> op 0xfb; op 0x0f
| ArrayFill x -> op 0xfb; op 0x10; idx x
| ArrayCopy (x, y) -> op 0xfb; op 0x11; idx x; idx y
| ArrayInitData (x, y) -> op 0xfb; op 0x12; idx x; idx y
| ArrayInitElem (x, y) -> op 0xfb; op 0x13; idx x; idx y
| ExternConvert Internalize -> op 0xfb; op 0x1a
| ExternConvert Externalize -> op 0xfb; op 0x1b
| 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
| Test (I32 I32Op.Eqz) -> op 0x45
| Test (I64 I64Op.Eqz) -> op 0x50
| Test (F32 _ | F64 _) -> .
| Compare (I32 I32Op.Eq) -> op 0x46
| Compare (I32 I32Op.Ne) -> op 0x47
| Compare (I32 I32Op.(Lt S)) -> op 0x48
| Compare (I32 I32Op.(Lt U)) -> op 0x49
| Compare (I32 I32Op.(Gt S)) -> op 0x4a
| Compare (I32 I32Op.(Gt U)) -> op 0x4b
| Compare (I32 I32Op.(Le S)) -> op 0x4c
| Compare (I32 I32Op.(Le U)) -> op 0x4d
| Compare (I32 I32Op.(Ge S)) -> op 0x4e
| Compare (I32 I32Op.(Ge U)) -> op 0x4f
| Compare (I64 I64Op.Eq) -> op 0x51
| Compare (I64 I64Op.Ne) -> op 0x52
| Compare (I64 I64Op.(Lt S)) -> op 0x53
| Compare (I64 I64Op.(Lt U)) -> op 0x54
| Compare (I64 I64Op.(Gt S)) -> op 0x55
| Compare (I64 I64Op.(Gt U)) -> op 0x56
| Compare (I64 I64Op.(Le S)) -> op 0x57
| Compare (I64 I64Op.(Le U)) -> op 0x58
| Compare (I64 I64Op.(Ge S)) -> op 0x59
| Compare (I64 I64Op.(Ge U)) -> op 0x5a
| Compare (F32 F32Op.Eq) -> op 0x5b
| Compare (F32 F32Op.Ne) -> op 0x5c
| Compare (F32 F32Op.Lt) -> op 0x5d
| Compare (F32 F32Op.Gt) -> op 0x5e
| Compare (F32 F32Op.Le) -> op 0x5f
| Compare (F32 F32Op.Ge) -> op 0x60
| Compare (F64 F64Op.Eq) -> op 0x61
| Compare (F64 F64Op.Ne) -> op 0x62
| Compare (F64 F64Op.Lt) -> op 0x63
| Compare (F64 F64Op.Gt) -> op 0x64
| Compare (F64 F64Op.Le) -> op 0x65
| Compare (F64 F64Op.Ge) -> op 0x66
| Unary (I32 I32Op.Clz) -> op 0x67
| Unary (I32 I32Op.Ctz) -> op 0x68
| 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))) ->
error e.at "illegal instruction i32.extendN_s"
| Unary (I64 I64Op.Clz) -> op 0x79
| Unary (I64 I64Op.Ctz) -> op 0x7a
| Unary (I64 I64Op.Popcnt) -> op 0x7b
| 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)) ->
error e.at "illegal instruction i64.extend64_s"
| Unary (F32 F32Op.Abs) -> op 0x8b
| Unary (F32 F32Op.Neg) -> op 0x8c
| Unary (F32 F32Op.Ceil) -> op 0x8d
| Unary (F32 F32Op.Floor) -> op 0x8e
| Unary (F32 F32Op.Trunc) -> op 0x8f
| Unary (F32 F32Op.Nearest) -> op 0x90
| Unary (F32 F32Op.Sqrt) -> op 0x91
| Unary (F64 F64Op.Abs) -> op 0x99
| Unary (F64 F64Op.Neg) -> op 0x9a
| Unary (F64 F64Op.Ceil) -> op 0x9b
| Unary (F64 F64Op.Floor) -> op 0x9c
| Unary (F64 F64Op.Trunc) -> op 0x9d
| Unary (F64 F64Op.Nearest) -> op 0x9e
| Unary (F64 F64Op.Sqrt) -> op 0x9f
| Binary (I32 I32Op.Add) -> op 0x6a
| Binary (I32 I32Op.Sub) -> op 0x6b
| Binary (I32 I32Op.Mul) -> op 0x6c
| Binary (I32 I32Op.(Div S)) -> op 0x6d
| Binary (I32 I32Op.(Div U)) -> op 0x6e
| Binary (I32 I32Op.(Rem S)) -> op 0x6f
| Binary (I32 I32Op.(Rem U)) -> op 0x70
| Binary (I32 I32Op.And) -> op 0x71
| Binary (I32 I32Op.Or) -> op 0x72
| Binary (I32 I32Op.Xor) -> op 0x73
| Binary (I32 I32Op.Shl) -> op 0x74
| Binary (I32 I32Op.(Shr S)) -> op 0x75
| Binary (I32 I32Op.(Shr U)) -> op 0x76
| Binary (I32 I32Op.Rotl) -> op 0x77
| Binary (I32 I32Op.Rotr) -> op 0x78
| Binary (I64 I64Op.Add) -> op 0x7c
| Binary (I64 I64Op.Sub) -> op 0x7d
| Binary (I64 I64Op.Mul) -> op 0x7e
| Binary (I64 I64Op.(Div S)) -> op 0x7f
| Binary (I64 I64Op.(Div U)) -> op 0x80
| Binary (I64 I64Op.(Rem S)) -> op 0x81
| Binary (I64 I64Op.(Rem U)) -> op 0x82
| Binary (I64 I64Op.And) -> op 0x83
| Binary (I64 I64Op.Or) -> op 0x84
| Binary (I64 I64Op.Xor) -> op 0x85
| Binary (I64 I64Op.Shl) -> op 0x86
| Binary (I64 I64Op.(Shr S)) -> op 0x87
| Binary (I64 I64Op.(Shr U)) -> op 0x88
| Binary (I64 I64Op.Rotl) -> op 0x89
| Binary (I64 I64Op.Rotr) -> op 0x8a
| Binary (F32 F32Op.Add) -> op 0x92
| Binary (F32 F32Op.Sub) -> op 0x93
| Binary (F32 F32Op.Mul) -> op 0x94
| Binary (F32 F32Op.Div) -> op 0x95
| Binary (F32 F32Op.Min) -> op 0x96
| Binary (F32 F32Op.Max) -> op 0x97
| Binary (F32 F32Op.CopySign) -> op 0x98
| Binary (F64 F64Op.Add) -> op 0xa0
| Binary (F64 F64Op.Sub) -> op 0xa1
| Binary (F64 F64Op.Mul) -> op 0xa2
| Binary (F64 F64Op.Div) -> op 0xa3
| Binary (F64 F64Op.Min) -> op 0xa4
| Binary (F64 F64Op.Max) -> op 0xa5
| Binary (F64 F64Op.CopySign) -> op 0xa6
| Convert (I32 I32Op.(ExtendI32 _)) ->
error e.at "illegal instruction i32.extend_i32_s/u"
| Convert (I32 I32Op.WrapI64) -> op 0xa7
| Convert (I32 I32Op.(TruncF32 S)) -> op 0xa8
| Convert (I32 I32Op.(TruncF32 U)) -> op 0xa9
| Convert (I32 I32Op.(TruncF64 S)) -> op 0xaa
| Convert (I32 I32Op.(TruncF64 U)) -> op 0xab
| Convert (I32 I32Op.(TruncSatF32 S)) -> op 0xfc; u32 0x00l
| Convert (I32 I32Op.(TruncSatF32 U)) -> op 0xfc; u32 0x01l
| Convert (I32 I32Op.(TruncSatF64 S)) -> op 0xfc; u32 0x02l
| Convert (I32 I32Op.(TruncSatF64 U)) -> op 0xfc; u32 0x03l
| Convert (I32 I32Op.ReinterpretFloat) -> op 0xbc
| Convert (I64 I64Op.(ExtendI32 S)) -> op 0xac
| Convert (I64 I64Op.(ExtendI32 U)) -> op 0xad
| Convert (I64 I64Op.WrapI64) ->
error e.at "illegal instruction i64.wrap_i64"
| Convert (I64 I64Op.(TruncF32 S)) -> op 0xae
| Convert (I64 I64Op.(TruncF32 U)) -> op 0xaf
| Convert (I64 I64Op.(TruncF64 S)) -> op 0xb0
| Convert (I64 I64Op.(TruncF64 U)) -> op 0xb1
| Convert (I64 I64Op.(TruncSatF32 S)) -> op 0xfc; u32 0x04l
| Convert (I64 I64Op.(TruncSatF32 U)) -> op 0xfc; u32 0x05l
| Convert (I64 I64Op.(TruncSatF64 S)) -> op 0xfc; u32 0x06l
| Convert (I64 I64Op.(TruncSatF64 U)) -> op 0xfc; u32 0x07l
| Convert (I64 I64Op.ReinterpretFloat) -> op 0xbd
| Convert (F32 F32Op.(ConvertI32 S)) -> op 0xb2
| Convert (F32 F32Op.(ConvertI32 U)) -> op 0xb3
| Convert (F32 F32Op.(ConvertI64 S)) -> op 0xb4
| Convert (F32 F32Op.(ConvertI64 U)) -> op 0xb5
| Convert (F32 F32Op.PromoteF32) ->
error e.at "illegal instruction f32.promote_f32"
| Convert (F32 F32Op.DemoteF64) -> op 0xb6
| Convert (F32 F32Op.ReinterpretInt) -> op 0xbe
| Convert (F64 F64Op.(ConvertI32 S)) -> op 0xb7
| Convert (F64 F64Op.(ConvertI32 U)) -> op 0xb8
| Convert (F64 F64Op.(ConvertI64 S)) -> op 0xb9
| Convert (F64 F64Op.(ConvertI64 U)) -> op 0xba
| Convert (F64 F64Op.PromoteF32) -> op 0xbb
| 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
| VecTest (V128 (I8x16 V128Op.AllTrue)) -> vecop 0x63l
| VecTest (V128 (I16x8 V128Op.AllTrue)) -> vecop 0x83l
| VecTest (V128 (I32x4 V128Op.AllTrue)) -> vecop 0xa3l
| VecTest (V128 (I64x2 V128Op.AllTrue)) -> vecop 0xc3l
| VecTest (V128 _) -> .
| VecUnary (V128 (I8x16 V128Op.Abs)) -> vecop 0x60l
| VecUnary (V128 (I8x16 V128Op.Neg)) -> vecop 0x61l
| 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)) ->
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)) ->
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)) ->
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
| VecUnary (V128 (F32x4 V128Op.Nearest)) -> vecop 0x6al
| VecUnary (V128 (F64x2 V128Op.Ceil)) -> vecop 0x74l
| VecUnary (V128 (F64x2 V128Op.Floor)) -> vecop 0x75l
| VecUnary (V128 (F64x2 V128Op.Trunc)) -> vecop 0x7al
| VecUnary (V128 (F64x2 V128Op.Nearest)) -> vecop 0x94l
| VecUnary (V128 (F32x4 V128Op.Abs)) -> vecop 0xe0l
| VecUnary (V128 (F32x4 V128Op.Neg)) -> vecop 0xe1l
| VecUnary (V128 (F32x4 V128Op.Sqrt)) -> vecop 0xe3l
| VecUnary (V128 (F64x2 V128Op.Abs)) -> vecop 0xecl
| VecUnary (V128 (F64x2 V128Op.Neg)) -> vecop 0xedl
| VecUnary (V128 (F64x2 V128Op.Sqrt)) -> vecop 0xefl
| VecCompare (V128 (I8x16 V128Op.Eq)) -> vecop 0x23l
| VecCompare (V128 (I8x16 V128Op.Ne)) -> vecop 0x24l
| VecCompare (V128 (I8x16 V128Op.(Lt S))) -> vecop 0x25l
| VecCompare (V128 (I8x16 V128Op.(Lt U))) -> vecop 0x26l
| VecCompare (V128 (I8x16 V128Op.(Gt S))) -> vecop 0x27l
| VecCompare (V128 (I8x16 V128Op.(Gt U))) -> vecop 0x28l
| VecCompare (V128 (I8x16 V128Op.(Le S))) -> vecop 0x29l
| VecCompare (V128 (I8x16 V128Op.(Le U))) -> vecop 0x2al
| VecCompare (V128 (I8x16 V128Op.(Ge S))) -> vecop 0x2bl
| VecCompare (V128 (I8x16 V128Op.(Ge U))) -> vecop 0x2cl
| VecCompare (V128 (I16x8 V128Op.Eq)) -> vecop 0x2dl
| VecCompare (V128 (I16x8 V128Op.Ne)) -> vecop 0x2el
| VecCompare (V128 (I16x8 V128Op.(Lt S))) -> vecop 0x2fl
| VecCompare (V128 (I16x8 V128Op.(Lt U))) -> vecop 0x30l
| VecCompare (V128 (I16x8 V128Op.(Gt S))) -> vecop 0x31l
| VecCompare (V128 (I16x8 V128Op.(Gt U))) -> vecop 0x32l
| VecCompare (V128 (I16x8 V128Op.(Le S))) -> vecop 0x33l
| VecCompare (V128 (I16x8 V128Op.(Le U))) -> vecop 0x34l
| VecCompare (V128 (I16x8 V128Op.(Ge S))) -> vecop 0x35l
| VecCompare (V128 (I16x8 V128Op.(Ge U))) -> vecop 0x36l
| VecCompare (V128 (I32x4 V128Op.Eq)) -> vecop 0x37l
| VecCompare (V128 (I32x4 V128Op.Ne)) -> vecop 0x38l
| VecCompare (V128 (I32x4 V128Op.(Lt S))) -> vecop 0x39l
| VecCompare (V128 (I32x4 V128Op.(Lt U))) -> vecop 0x3al
| VecCompare (V128 (I32x4 V128Op.(Gt S))) -> vecop 0x3bl
| VecCompare (V128 (I32x4 V128Op.(Gt U))) -> vecop 0x3cl
| VecCompare (V128 (I32x4 V128Op.(Le S))) -> vecop 0x3dl
| VecCompare (V128 (I32x4 V128Op.(Le U))) -> vecop 0x3el
| VecCompare (V128 (I32x4 V128Op.(Ge S))) -> vecop 0x3fl
| VecCompare (V128 (I32x4 V128Op.(Ge U))) -> vecop 0x40l
| VecCompare (V128 (I64x2 V128Op.Eq)) -> vecop 0xd6l
| VecCompare (V128 (I64x2 V128Op.Ne)) -> vecop 0xd7l
| VecCompare (V128 (I64x2 V128Op.(Lt S))) -> vecop 0xd8l
| VecCompare (V128 (I64x2 V128Op.(Lt U))) ->
error e.at "illegal instruction i64x2.lt_u"
| VecCompare (V128 (I64x2 V128Op.(Gt S))) -> vecop 0xd9l
| VecCompare (V128 (I64x2 V128Op.(Gt U))) ->
error e.at "illegal instruction i64x2.gt_u"
| VecCompare (V128 (I64x2 V128Op.(Le S))) -> vecop 0xdal
| VecCompare (V128 (I64x2 V128Op.(Le U))) ->
error e.at "illegal instruction i64x2.le_u"
| VecCompare (V128 (I64x2 V128Op.(Ge S))) -> vecop 0xdbl
| VecCompare (V128 (I64x2 V128Op.(Ge U))) ->
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
| VecCompare (V128 (F32x4 V128Op.Gt)) -> vecop 0x44l
| VecCompare (V128 (F32x4 V128Op.Le)) -> vecop 0x45l
| VecCompare (V128 (F32x4 V128Op.Ge)) -> vecop 0x46l
| VecCompare (V128 (F64x2 V128Op.Eq)) -> vecop 0x47l
| VecCompare (V128 (F64x2 V128Op.Ne)) -> vecop 0x48l
| VecCompare (V128 (F64x2 V128Op.Lt)) -> vecop 0x49l
| VecCompare (V128 (F64x2 V128Op.Gt)) -> vecop 0x4al
| 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.Swizzle)) -> vecop 0x0el
| VecBinary (V128 (I8x16 V128Op.(Narrow S))) -> vecop 0x65l
| VecBinary (V128 (I8x16 V128Op.(Narrow U))) -> vecop 0x66l
| VecBinary (V128 (I8x16 V128Op.Add)) -> vecop 0x6el
| VecBinary (V128 (I8x16 V128Op.(AddSat S))) -> vecop 0x6fl
| VecBinary (V128 (I8x16 V128Op.(AddSat U))) -> vecop 0x70l
| VecBinary (V128 (I8x16 V128Op.Sub)) -> vecop 0x71l
| VecBinary (V128 (I8x16 V128Op.(SubSat S))) -> vecop 0x72l
| VecBinary (V128 (I8x16 V128Op.(SubSat U))) -> vecop 0x73l
| VecBinary (V128 (I8x16 V128Op.(Min S))) -> vecop 0x76l
| VecBinary (V128 (I8x16 V128Op.(Min U))) -> vecop 0x77l
| VecBinary (V128 (I8x16 V128Op.(Max S))) -> vecop 0x78l
| VecBinary (V128 (I8x16 V128Op.(Max U))) -> vecop 0x79l
| VecBinary (V128 (I8x16 V128Op.AvgrU)) -> vecop 0x7bl
| VecBinary (V128 (I8x16 V128Op.RelaxedSwizzle)) -> vecop 0x100l
| VecBinary (V128 (I16x8 V128Op.(Narrow S))) -> vecop 0x85l
| VecBinary (V128 (I16x8 V128Op.(Narrow U))) -> vecop 0x86l
| VecBinary (V128 (I16x8 V128Op.Add)) -> vecop 0x8el
| VecBinary (V128 (I16x8 V128Op.(AddSat S))) -> vecop 0x8fl
| VecBinary (V128 (I16x8 V128Op.(AddSat U))) -> vecop 0x90l
| VecBinary (V128 (I16x8 V128Op.Sub)) -> vecop 0x91l
| VecBinary (V128 (I16x8 V128Op.(SubSat S))) -> vecop 0x92l
| VecBinary (V128 (I16x8 V128Op.(SubSat U))) -> vecop 0x93l
| VecBinary (V128 (I16x8 V128Op.Mul)) -> vecop 0x95l
| VecBinary (V128 (I16x8 V128Op.(Min S))) -> vecop 0x96l
| VecBinary (V128 (I16x8 V128Op.(Min U))) -> vecop 0x97l
| VecBinary (V128 (I16x8 V128Op.(Max S))) -> vecop 0x98l
| VecBinary (V128 (I16x8 V128Op.(Max U))) -> vecop 0x99l
| VecBinary (V128 (I16x8 V128Op.AvgrU)) -> vecop 0x9bl
| VecBinary (V128 (I16x8 V128Op.(ExtMul (Low, S)))) -> vecop 0x9cl
| VecBinary (V128 (I16x8 V128Op.(ExtMul (High, S)))) -> vecop 0x9dl
| VecBinary (V128 (I16x8 V128Op.(ExtMul (Low, U)))) -> vecop 0x9el
| VecBinary (V128 (I16x8 V128Op.(ExtMul (High, U)))) -> vecop 0x9fl
| VecBinary (V128 (I16x8 V128Op.Q15MulRSatS)) -> vecop 0x82l
| VecBinary (V128 (I16x8 V128Op.RelaxedQ15MulRS)) -> vecop 0x111l
| VecBinary (V128 (I16x8 V128Op.RelaxedDot)) -> vecop 0x112l
| VecBinary (V128 (I32x4 V128Op.Add)) -> vecop 0xael
| VecBinary (V128 (I32x4 V128Op.Sub)) -> vecop 0xb1l
| VecBinary (V128 (I32x4 V128Op.(Min S))) -> vecop 0xb6l
| VecBinary (V128 (I32x4 V128Op.(Min U))) -> vecop 0xb7l
| VecBinary (V128 (I32x4 V128Op.(Max S))) -> vecop 0xb8l
| VecBinary (V128 (I32x4 V128Op.(Max U))) -> vecop 0xb9l
| VecBinary (V128 (I32x4 V128Op.DotS)) -> vecop 0xbal
| VecBinary (V128 (I32x4 V128Op.Mul)) -> vecop 0xb5l
| VecBinary (V128 (I32x4 V128Op.(ExtMul (Low, S)))) -> vecop 0xbcl
| VecBinary (V128 (I32x4 V128Op.(ExtMul (High, S)))) -> vecop 0xbdl
| VecBinary (V128 (I32x4 V128Op.(ExtMul (Low, U)))) -> vecop 0xbel
| VecBinary (V128 (I32x4 V128Op.(ExtMul (High, U)))) -> vecop 0xbfl
| VecBinary (V128 (I64x2 V128Op.Add)) -> vecop 0xcel
| VecBinary (V128 (I64x2 V128Op.Sub)) -> vecop 0xd1l
| VecBinary (V128 (I64x2 V128Op.Mul)) -> vecop 0xd5l
| VecBinary (V128 (I64x2 V128Op.(ExtMul (Low, S)))) -> vecop 0xdcl
| VecBinary (V128 (I64x2 V128Op.(ExtMul (High, S)))) -> vecop 0xddl
| VecBinary (V128 (I64x2 V128Op.(ExtMul (Low, U)))) -> vecop 0xdel
| VecBinary (V128 (I64x2 V128Op.(ExtMul (High, U)))) -> vecop 0xdfl
| VecBinary (V128 (F32x4 V128Op.Add)) -> vecop 0xe4l
| VecBinary (V128 (F32x4 V128Op.Sub)) -> vecop 0xe5l
| VecBinary (V128 (F32x4 V128Op.Mul)) -> vecop 0xe6l
| VecBinary (V128 (F32x4 V128Op.Div)) -> vecop 0xe7l
| VecBinary (V128 (F32x4 V128Op.Min)) -> vecop 0xe8l
| VecBinary (V128 (F32x4 V128Op.Max)) -> vecop 0xe9l
| VecBinary (V128 (F32x4 V128Op.Pmin)) -> vecop 0xeal
| VecBinary (V128 (F32x4 V128Op.Pmax)) -> vecop 0xebl
| VecBinary (V128 (F32x4 V128Op.RelaxedMin)) -> vecop 0x10dl
| VecBinary (V128 (F32x4 V128Op.RelaxedMax)) -> vecop 0x10el
| VecBinary (V128 (F64x2 V128Op.Add)) -> vecop 0xf0l
| VecBinary (V128 (F64x2 V128Op.Sub)) -> vecop 0xf1l
| VecBinary (V128 (F64x2 V128Op.Mul)) -> vecop 0xf2l
| VecBinary (V128 (F64x2 V128Op.Div)) -> vecop 0xf3l
| VecBinary (V128 (F64x2 V128Op.Min)) -> vecop 0xf4l
| VecBinary (V128 (F64x2 V128Op.Max)) -> vecop 0xf5l
| VecBinary (V128 (F64x2 V128Op.Pmin)) -> vecop 0xf6l
| VecBinary (V128 (F64x2 V128Op.Pmax)) -> vecop 0xf7l
| VecBinary (V128 (F64x2 V128Op.RelaxedMin)) -> vecop 0x10fl
| VecBinary (V128 (F64x2 V128Op.RelaxedMax)) -> vecop 0x110l
| VecBinary (V128 _) ->
error e.at "illegal binary vector instruction"
| VecTernary (V128 (F32x4 V128Op.RelaxedMadd)) -> vecop 0x105l
| VecTernary (V128 (F32x4 V128Op.RelaxedNmadd)) -> vecop 0x106l
| VecTernary (V128 (F64x2 V128Op.RelaxedMadd)) -> vecop 0x107l
| VecTernary (V128 (F64x2 V128Op.RelaxedNmadd)) -> vecop 0x108l
| VecTernary (V128 (I8x16 V128Op.RelaxedLaneselect)) -> vecop 0x109l
| VecTernary (V128 (I16x8 V128Op.RelaxedLaneselect)) -> vecop 0x10al
| VecTernary (V128 (I32x4 V128Op.RelaxedLaneselect)) -> vecop 0x10bl
| VecTernary (V128 (I64x2 V128Op.RelaxedLaneselect)) -> vecop 0x10cl
| VecTernary (V128 (I32x4 V128Op.RelaxedDotAddS)) -> vecop 0x113l
| VecTernary (V128 _) ->
error e.at "illegal ternary vector instruction"
| VecConvert (V128 (I8x16 _)) ->
error e.at "illegal i8x16 conversion instruction"
| VecConvert (V128 (I16x8 V128Op.(Extend (Low, S)))) -> vecop 0x87l
| VecConvert (V128 (I16x8 V128Op.(Extend (High, S)))) -> vecop 0x88l
| VecConvert (V128 (I16x8 V128Op.(Extend (Low, U)))) -> vecop 0x89l
| VecConvert (V128 (I16x8 V128Op.(Extend (High, U)))) -> vecop 0x8al
| VecConvert (V128 (I16x8 V128Op.(ExtAddPairwise S))) -> vecop 0x7cl
| VecConvert (V128 (I16x8 V128Op.(ExtAddPairwise U))) -> vecop 0x7dl
| VecConvert (V128 (I16x8 _)) ->
error e.at "illegal i16x8 conversion instruction"
| VecConvert (V128 (I32x4 V128Op.(Extend (Low, S)))) -> vecop 0xa7l
| VecConvert (V128 (I32x4 V128Op.(Extend (High, S)))) -> vecop 0xa8l
| VecConvert (V128 (I32x4 V128Op.(Extend (Low, U)))) -> vecop 0xa9l
| VecConvert (V128 (I32x4 V128Op.(Extend (High, U)))) -> vecop 0xaal
| VecConvert (V128 (I32x4 V128Op.(ExtAddPairwise S))) -> vecop 0x7el
| VecConvert (V128 (I32x4 V128Op.(ExtAddPairwise U))) -> vecop 0x7fl
| VecConvert (V128 (I32x4 V128Op.(TruncSatF32x4 S))) -> vecop 0xf8l
| VecConvert (V128 (I32x4 V128Op.(TruncSatF32x4 U))) -> vecop 0xf9l
| VecConvert (V128 (I32x4 V128Op.(TruncSatZeroF64x2 S))) -> vecop 0xfcl
| VecConvert (V128 (I32x4 V128Op.(TruncSatZeroF64x2 U))) -> vecop 0xfdl
| VecConvert (V128 (I32x4 V128Op.(RelaxedTruncF32x4 S))) -> vecop 0x101l
| VecConvert (V128 (I32x4 V128Op.(RelaxedTruncF32x4 U))) -> vecop 0x102l
| VecConvert (V128 (I32x4 V128Op.(RelaxedTruncZeroF64x2 S))) -> vecop 0x103l
| VecConvert (V128 (I32x4 V128Op.(RelaxedTruncZeroF64x2 U))) -> vecop 0x104l
| VecConvert (V128 (I64x2 V128Op.(Extend (Low, S)))) -> vecop 0xc7l
| VecConvert (V128 (I64x2 V128Op.(Extend (High, S)))) -> vecop 0xc8l
| VecConvert (V128 (I64x2 V128Op.(Extend (Low, U)))) -> vecop 0xc9l
| VecConvert (V128 (I64x2 V128Op.(Extend (High, U)))) -> vecop 0xcal
| VecConvert (V128 (I64x2 _)) ->
error e.at "illegal i64x2 conversion instruction"
| VecConvert (V128 (F32x4 V128Op.DemoteZeroF64x2)) -> vecop 0x5el
| VecConvert (V128 (F32x4 V128Op.PromoteLowF32x4)) ->
error e.at "illegal instruction f32x4.promote_low_f32x4"
| VecConvert (V128 (F32x4 V128Op.(ConvertI32x4 S))) -> vecop 0xfal
| VecConvert (V128 (F32x4 V128Op.(ConvertI32x4 U))) -> vecop 0xfbl
| 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.(ConvertI32x4 S))) -> vecop 0xfel
| VecConvert (V128 (F64x2 V128Op.(ConvertI32x4 U))) -> vecop 0xffl
| VecShift (V128 (I8x16 V128Op.Shl)) -> vecop 0x6bl
| VecShift (V128 (I8x16 V128Op.(Shr S))) -> vecop 0x6cl
| VecShift (V128 (I8x16 V128Op.(Shr U))) -> vecop 0x6dl
| VecShift (V128 (I16x8 V128Op.Shl)) -> vecop 0x8bl
| VecShift (V128 (I16x8 V128Op.(Shr S))) -> vecop 0x8cl
| VecShift (V128 (I16x8 V128Op.(Shr U))) -> vecop 0x8dl
| VecShift (V128 (I32x4 V128Op.Shl)) -> vecop 0xabl
| VecShift (V128 (I32x4 V128Op.(Shr S))) -> vecop 0xacl
| VecShift (V128 (I32x4 V128Op.(Shr U))) -> vecop 0xadl
| VecShift (V128 (I64x2 V128Op.Shl)) -> vecop 0xcbl
| VecShift (V128 (I64x2 V128Op.(Shr S))) -> vecop 0xccl
| VecShift (V128 (I64x2 V128Op.(Shr U))) -> vecop 0xcdl
| VecShift (V128 _) -> .
| VecBitmask (V128 (I8x16 V128Op.Bitmask)) -> vecop 0x64l
| VecBitmask (V128 (I16x8 V128Op.Bitmask)) -> vecop 0x84l
| VecBitmask (V128 (I32x4 V128Op.Bitmask)) -> vecop 0xa4l
| VecBitmask (V128 (I64x2 V128Op.Bitmask)) -> vecop 0xc4l
| VecBitmask (V128 _) -> .
| VecTestBits (V128 V128Op.AnyTrue) -> vecop 0x53l
| VecUnaryBits (V128 V128Op.Not) -> vecop 0x4dl
| VecBinaryBits (V128 V128Op.And) -> vecop 0x4el
| VecBinaryBits (V128 V128Op.AndNot) -> vecop 0x4fl
| VecBinaryBits (V128 V128Op.Or) -> vecop 0x50l
| VecBinaryBits (V128 V128Op.Xor) -> vecop 0x51l
| VecTernaryBits (V128 V128Op.Bitselect) -> vecop 0x52l
| VecSplat (V128 ((I8x16 V128Op.Splat))) -> vecop 0x0fl
| VecSplat (V128 ((I16x8 V128Op.Splat))) -> vecop 0x10l
| VecSplat (V128 ((I32x4 V128Op.Splat))) -> vecop 0x11l
| VecSplat (V128 ((I64x2 V128Op.Splat))) -> vecop 0x12l
| VecSplat (V128 ((F32x4 V128Op.Splat))) -> vecop 0x13l
| VecSplat (V128 ((F64x2 V128Op.Splat))) -> vecop 0x14l
| VecExtract (V128 (I8x16 V128Op.(Extract (i, S)))) -> vecop 0x15l; u8 i
| VecExtract (V128 (I8x16 V128Op.(Extract (i, U)))) -> vecop 0x16l; u8 i
| VecExtract (V128 (I16x8 V128Op.(Extract (i, S)))) -> vecop 0x18l; u8 i
| VecExtract (V128 (I16x8 V128Op.(Extract (i, U)))) -> 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
and catch c =
match c.it with
| Catch (x1, x2) -> byte 0x00; idx x1; idx x2
| CatchRef (x1, x2) -> byte 0x01; idx x1; idx x2
| CatchAll x -> byte 0x02; idx x
| CatchAllRef x -> byte 0x03; idx x
let const c =
list instr c.it; end_ ()
(* Sections *)
let section id f x needed =
if needed then begin
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 = rectype t.it
let type_section ts =
section 1 (vec type_) ts (ts <> [])
(* Import section *)
let import im =
let Import (module_name, item_name, xt) = im.it in
name module_name; name item_name; externtype xt
let import_section ims =
section 2 (vec import) ims (ims <> [])
(* Function section *)
let func f =
let Func (x, _, _) = f.it in
idx x
let func_section fs =
section 3 (vec func) fs (fs <> [])
(* Table section *)
let table tab =
let Table (tt, c) = tab.it in
match tt, c.it with
| TableT (_, _at, (_, ht1)), [{it = RefNull ht2; _}] when ht1 = ht2 ->
tabletype tt
| _ -> op 0x40; op 0x00; tabletype tt; const c
let table_section tabs =
section 4 (vec table) tabs (tabs <> [])
(* Memory section *)
let memory mem =
let Memory mt = mem.it in
memorytype mt
let memory_section mems =
section 5 (vec memory) mems (mems <> [])
(* Tag section *)
let tag tag =
let Tag tt = tag.it in
tagtype tt
let tag_section ts =
section 13 (vec tag) ts (ts <> [])
(* Global section *)
let global g =
let Global (gt, c) = g.it in
globaltype gt; const c
let global_section gs =
section 6 (vec global) gs (gs <> [])
(* Export section *)
let externidx xx =
match xx.it with
| FuncX x -> byte 0x00; idx x
| TableX x -> byte 0x01; idx x
| MemoryX x -> byte 0x02; idx x
| GlobalX x -> byte 0x03; idx x
| TagX x -> byte 0x04; idx x
let export ex =
let Export (n, xx) = ex.it in
name n; externidx xx
let export_section exs =
section 7 (vec export) exs (exs <> [])
(* Start section *)
let start st =
let Start x = st.it in
idx x
let start_section xo =
section 8 (opt start) xo (xo <> None)
(* Code section *)
let code f =
let Func (_x, ls, es) = f.it in
let g = gap32 () in
let p = pos s in
locals ls;
list instr es;
end_ ();
patch_gap32 g (pos s - p)
let code_section fs =
section 10 (vec code) fs (fs <> [])
(* Element section *)
let is_elem_kind = function
| (NoNull, FuncHT) -> true
| _ -> false
let elem_kind = function
| (NoNull, FuncHT) -> byte 0x00
| _ -> assert false
let is_elem_index e =
match e.it with
| [{it = RefFunc _; _}] -> true
| _ -> false
let elem_index e =
match e.it with
| [{it = RefFunc x; _}] -> idx x
| _ -> assert false
let elem seg =
let Elem (rt, cs, emode) = seg.it in
if is_elem_kind rt && List.for_all is_elem_index cs then
match emode.it with
| Passive ->
u32 0x01l; elem_kind rt; vec elem_index cs
| Active ({it = 0l; _}, c) ->
u32 0x00l; const c; vec elem_index cs
| Active (x, c) ->
u32 0x02l;
idx x; const c; elem_kind rt; vec elem_index cs
| Declarative ->
u32 0x03l; elem_kind rt; vec elem_index cs
else
match emode.it with
| Passive ->
u32 0x05l; reftype rt; vec const cs
| Active ({it = 0l; _}, c) when rt = (Null, FuncHT) ->
u32 0x04l; const c; vec const cs
| Active (x, c) ->
u32 0x06l; idx x; const c; reftype rt; vec const cs
| Declarative ->
u32 0x07l; reftype rt; vec const cs
let elem_section elems =
section 9 (vec elem) elems (elems <> [])
(* Data section *)
let data seg =
let Data (bs, dmode) = seg.it in
match dmode.it with
| Passive ->
u32 0x01l; string bs
| Active ({it = 0l; _}, c) ->
u32 0x00l; const c; string bs
| Active (x, c) ->
u32 0x02l; idx x; const c; string bs
| Declarative ->
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 c =
let Custom.{name = n; content; _} = c.it in
name n;
put_string s content
let custom_section place c =
let here = Custom.(compare_place c.it.place place) <= 0 in
if here then section 0 custom c true;
here
(* Module *)
let rec iterate f xs =
match xs with
| [] -> []
| x::xs' -> if f x then iterate f xs' else xs
let module_ m cs =
let open Custom in
word32 0x6d736100l;
word32 version;
let cs = iterate (custom_section (Before Type)) cs in
type_section m.it.types;
let cs = iterate (custom_section (Before Import)) cs in
import_section m.it.imports;
let cs = iterate (custom_section (Before Func)) cs in
func_section m.it.funcs;
let cs = iterate (custom_section (Before Table)) cs in
table_section m.it.tables;
let cs = iterate (custom_section (Before Memory)) cs in
memory_section m.it.memories;
let cs = iterate (custom_section (Before Tag)) cs in
tag_section m.it.tags;
let cs = iterate (custom_section (Before Global)) cs in
global_section m.it.globals;
let cs = iterate (custom_section (Before Export)) cs in
export_section m.it.exports;
let cs = iterate (custom_section (Before Start)) cs in
start_section m.it.start;
let cs = iterate (custom_section (Before Elem)) cs in
elem_section m.it.elems;
let cs = iterate (custom_section (Before DataCount)) cs in
data_count_section m.it.datas m;
let cs = iterate (custom_section (Before Code)) cs in
code_section m.it.funcs;
let cs = iterate (custom_section (Before Data)) cs in
data_section m.it.datas;
let cs = iterate (custom_section (After Data)) cs in
assert (cs = [])
end
let encode_custom m bs (module S : Custom.Section) =
let open Source in
let c = S.Handler.encode m bs S.it in
Custom.{c.it with place = S.Handler.place S.it} @@ c.at
let encode m =
let module E = E (struct let stream = stream () end) in
E.module_ m []; to_string E.s
let encode_with_custom (m, secs) =
let bs = encode m in
let module E = E (struct let stream = stream () end) in
let cs = List.map (encode_custom m bs) secs in
E.module_ m cs; to_string E.s