Files
2025-07-02 16:42:36 +00:00

678 lines
24 KiB
Forth

namespace WoofWare.PawPrint
open System.Collections.Immutable
type NullaryIlOp =
| Nop
/// Load the argument at index 0 onto the eval stack.
| LdArg0
/// Load the argument at index 1 onto the eval stack.
| LdArg1
/// Load the argument at index 2 onto the eval stack.
| LdArg2
/// Load the argument at index 3 onto the eval stack.
| LdArg3
/// Load the local variable at index 0 onto the eval stack.
| Ldloc_0
/// Load the local variable at index 1 onto the eval stack.
| Ldloc_1
/// Load the local variable at index 2 onto the eval stack.
| Ldloc_2
/// Load the local variable at index 3 onto the eval stack.
| Ldloc_3
/// Remove the value on top of the eval stack.
| Pop
/// Push another copy of the value on top of the eval stack onto the top of the eval stack.
| Dup
| Ret
/// Push the int32 value 0 to the eval stack.
| LdcI4_0
/// Push the int32 value 1 to the eval stack.
| LdcI4_1
/// Push the int32 value 2 to the eval stack.
| LdcI4_2
/// Push the int32 value 3 to the eval stack.
| LdcI4_3
/// Push the int32 value 4 to the eval stack.
| LdcI4_4
/// Push the int32 value 5 to the eval stack.
| LdcI4_5
/// Push the int32 value 6 to the eval stack.
| LdcI4_6
/// Push the int32 value 7 to the eval stack.
| LdcI4_7
/// Push the int32 value 8 to the eval stack.
| LdcI4_8
/// Push the int32 value -1 to the eval stack.
| LdcI4_m1
/// Push a null object reference onto the stack.
| LdNull
/// Pop two values from the stack; push 1 if they're equal, 0 otherwise
| Ceq
| Cgt
| Cgt_un
| Clt
| Clt_un
/// Pop from the eval stack and store the result in local variable 0
| Stloc_0
/// Pop from the eval stack and store the result in local variable 1
| Stloc_1
/// Pop from the eval stack and store the result in local variable 2
| Stloc_2
/// Pop from the eval stack and store the result in local variable 3
| Stloc_3
| Sub
| Sub_ovf
| Sub_ovf_un
| Add
| Add_ovf
| Add_ovf_un
| Mul
| Mul_ovf
| Mul_ovf_un
| Div
| Div_un
| Rem
| Rem_un
| Neg
| Not
| Shr
| Shr_un
/// Shifts an integer value to the left (in zeroes) by a specified number of bits, pushing the result onto the evaluation stack.
/// Top of stack is number of bits to be shifted.
/// Inserts a zero bit in the lowest positions.
| Shl
| Conv_ovf_i
| Conv_ovf_u
| And
| Or
| Xor
/// Converts the value on top of the eval stack to nativeint
| Conv_I
/// Converts the value on top of the eval stack to int8, then pads to int32
| Conv_I1
/// Converts the value on top of the eval stack to int16, then pads to int32
| Conv_I2
/// Converts the value on top of the eval stack to int32
| Conv_I4
/// Converts the value on top of the eval stack to int64
| Conv_I8
| Conv_R4
| Conv_R8
/// Converts the value on top of the eval stack to unsigned nativeint, then extends to nativeint
| Conv_U
/// Converts the value on top of the eval stack to uint8, then extends to int32
| Conv_U1
/// Converts the value on top of the eval stack to uint16, then extends to int 32
| Conv_U2
/// Converts the value on top of the eval stack to uint32, then extends to int32
| Conv_U4
/// Converts the value on top of the eval stack to uint64, then extends to int64
| Conv_U8
| Conv_ovf_u1
| Conv_ovf_u2
| Conv_ovf_u4
| Conv_ovf_u8
| Conv_ovf_i1
| Conv_ovf_i2
| Conv_ovf_i4
| Conv_ovf_i8
/// Pushes the number of elements of a zero-based, one-dimensional array onto the evaluation stack.
| LdLen
| Endfilter
| Endfinally
| Rethrow
| Throw
| Localloc
/// Dereferences the pointer on top of the stack, and pushes the target to the stack as a type O (object reference).
| Ldind_ref
/// Stores an object reference value at a supplied address.
| Stind_ref
| Stind_I
| Stind_I1
| Stind_I2
| Stind_I4
| Stind_I8
| Stind_R4
| Stind_R8
| Ldind_i
| Ldind_i1
| Ldind_i2
/// Loads a value of type int32 as an int32 onto the evaluation stack indirectly from the specified address.
| Ldind_i4
| Ldind_i8
| Ldind_u1
| Ldind_u2
| Ldind_u4
| Ldind_u8
| Ldind_r4
| Ldind_r8
| Volatile
| Tail
| Conv_ovf_i_un
| Conv_ovf_u_un
| Conv_ovf_i1_un
| Conv_ovf_u1_un
| Conv_ovf_i2_un
| Conv_ovf_u2_un
| Conv_ovf_i4_un
| Conv_ovf_u4_un
| Conv_ovf_i8_un
| Conv_ovf_u8_un
| Ldelem_i
| Ldelem_i1
| Ldelem_u1
| Ldelem_i2
| Ldelem_u2
| Ldelem_i4
| Ldelem_u4
| Ldelem_i8
| Ldelem_u8
| Ldelem_r4
| Ldelem_r8
/// Loads the element containing an object reference at a specified array index onto the top of the evaluation stack as type O (object reference).
| Ldelem_ref
/// Replaces the array element at a given index with the nativeint value on the evaluation stack.
| Stelem_i
/// Replaces the array element at a given index with the int8 value on the evaluation stack.
| Stelem_i1
| Stelem_u1
/// Replaces the array element at a given index with the int16 value on the evaluation stack.
| Stelem_i2
| Stelem_u2
/// Replaces the array element at a given index with the int32 value on the evaluation stack.
| Stelem_i4
| Stelem_u4
/// Replaces the array element at a given index with the int64 value on the evaluation stack.
| Stelem_i8
| Stelem_u8
| Stelem_r4
| Stelem_r8
/// Replaces the array element at a given index with the object ref value (type O) on the evaluation stack.
| Stelem_ref
| Cpblk
| Initblk
| Break
| Conv_r_un
| Arglist
| Ckfinite
| Readonly
| Refanytype
override this.ToString () =
match this with
| NullaryIlOp.Nop -> "Nop"
| NullaryIlOp.LdArg0 -> "LdArg0"
| NullaryIlOp.LdArg1 -> "LdArg1"
| NullaryIlOp.LdArg2 -> "LdArg2"
| NullaryIlOp.LdArg3 -> "LdArg3"
| NullaryIlOp.Ldloc_0 -> "Ldloc_0"
| NullaryIlOp.Ldloc_1 -> "Ldloc_1"
| NullaryIlOp.Ldloc_2 -> "Ldloc_2"
| NullaryIlOp.Ldloc_3 -> "Ldloc_3"
| NullaryIlOp.Pop -> "Pop"
| NullaryIlOp.Dup -> "Dup"
| NullaryIlOp.Ret -> "Ret"
| NullaryIlOp.LdcI4_0 -> "LdcI4_0"
| NullaryIlOp.LdcI4_1 -> "LdcI4_1"
| NullaryIlOp.LdcI4_2 -> "LdcI4_2"
| NullaryIlOp.LdcI4_3 -> "LdcI4_3"
| NullaryIlOp.LdcI4_4 -> "LdcI4_4"
| NullaryIlOp.LdcI4_5 -> "LdcI4_5"
| NullaryIlOp.LdcI4_6 -> "LdcI4_6"
| NullaryIlOp.LdcI4_7 -> "LdcI4_7"
| NullaryIlOp.LdcI4_8 -> "LdcI4_8"
| NullaryIlOp.LdcI4_m1 -> "LdcI4_m1"
| NullaryIlOp.LdNull -> "LdNull"
| NullaryIlOp.Ceq -> "Ceq"
| NullaryIlOp.Cgt -> "Cgt"
| NullaryIlOp.Cgt_un -> "Cgt_un"
| NullaryIlOp.Clt -> "Clt"
| NullaryIlOp.Clt_un -> "Clt_un"
| NullaryIlOp.Stloc_0 -> "Stloc_0"
| NullaryIlOp.Stloc_1 -> "Stloc_1"
| NullaryIlOp.Stloc_2 -> "Stloc_2"
| NullaryIlOp.Stloc_3 -> "Stloc_3"
| NullaryIlOp.Sub -> "Sub"
| NullaryIlOp.Sub_ovf -> "Sub_ovf"
| NullaryIlOp.Sub_ovf_un -> "Sub_ovf_un"
| NullaryIlOp.Add -> "Add"
| NullaryIlOp.Add_ovf -> "Add_ovf"
| NullaryIlOp.Add_ovf_un -> "Add_ovf_un"
| NullaryIlOp.Mul -> "Mul"
| NullaryIlOp.Mul_ovf -> "Mul_ovf"
| NullaryIlOp.Mul_ovf_un -> "Mul_ovf_un"
| NullaryIlOp.Div -> "Div"
| NullaryIlOp.Div_un -> "Div_un"
| NullaryIlOp.Rem -> "Rem"
| NullaryIlOp.Rem_un -> "Rem_un"
| NullaryIlOp.Neg -> "Neg"
| NullaryIlOp.Not -> "Not"
| NullaryIlOp.Shr -> "Shr"
| NullaryIlOp.Shr_un -> "Shr_un"
| NullaryIlOp.Shl -> "Shl"
| NullaryIlOp.Conv_ovf_i -> "Conv_ovf_i"
| NullaryIlOp.Conv_ovf_u -> "Conv_ovf_u"
| NullaryIlOp.And -> "And"
| NullaryIlOp.Or -> "Or"
| NullaryIlOp.Xor -> "Xor"
| NullaryIlOp.Conv_I -> "Conv_I"
| NullaryIlOp.Conv_I1 -> "Conv_I1"
| NullaryIlOp.Conv_I2 -> "Conv_I2"
| NullaryIlOp.Conv_I4 -> "Conv_I4"
| NullaryIlOp.Conv_I8 -> "Conv_I8"
| NullaryIlOp.Conv_R4 -> "Conv_R4"
| NullaryIlOp.Conv_R8 -> "Conv_R8"
| NullaryIlOp.Conv_U -> "Conv_U"
| NullaryIlOp.Conv_U1 -> "Conv_U1"
| NullaryIlOp.Conv_U2 -> "Conv_U2"
| NullaryIlOp.Conv_U4 -> "Conv_U4"
| NullaryIlOp.Conv_U8 -> "Conv_U8"
| NullaryIlOp.Conv_ovf_u1 -> "Conv_ovf_u1"
| NullaryIlOp.Conv_ovf_u2 -> "Conv_ovf_u2"
| NullaryIlOp.Conv_ovf_u4 -> "Conv_ovf_u4"
| NullaryIlOp.Conv_ovf_u8 -> "Conv_ovf_u8"
| NullaryIlOp.Conv_ovf_i1 -> "Conv_ovf_i1"
| NullaryIlOp.Conv_ovf_i2 -> "Conv_ovf_i2"
| NullaryIlOp.Conv_ovf_i4 -> "Conv_ovf_i4"
| NullaryIlOp.Conv_ovf_i8 -> "Conv_ovf_i8"
| NullaryIlOp.LdLen -> "LdLen"
| NullaryIlOp.Endfilter -> "Endfilter"
| NullaryIlOp.Endfinally -> "Endfinally"
| NullaryIlOp.Rethrow -> "Rethrow"
| NullaryIlOp.Throw -> "Throw"
| NullaryIlOp.Localloc -> "Localloc"
| NullaryIlOp.Ldind_ref -> "Ldind_ref"
| NullaryIlOp.Stind_ref -> "Stind_ref"
| NullaryIlOp.Stind_I -> "Stind_I"
| NullaryIlOp.Stind_I1 -> "Stind_I1"
| NullaryIlOp.Stind_I2 -> "Stind_I2"
| NullaryIlOp.Stind_I4 -> "Stind_I4"
| NullaryIlOp.Stind_I8 -> "Stind_I8"
| NullaryIlOp.Stind_R4 -> "Stind_R4"
| NullaryIlOp.Stind_R8 -> "Stind_R8"
| NullaryIlOp.Ldind_i -> "Ldind_i"
| NullaryIlOp.Ldind_i1 -> "Ldind_i1"
| NullaryIlOp.Ldind_i2 -> "Ldind_i2"
| NullaryIlOp.Ldind_i4 -> "Ldind_i4"
| NullaryIlOp.Ldind_i8 -> "Ldind_i8"
| NullaryIlOp.Ldind_u1 -> "Ldind_u1"
| NullaryIlOp.Ldind_u2 -> "Ldind_u2"
| NullaryIlOp.Ldind_u4 -> "Ldind_u4"
| NullaryIlOp.Ldind_u8 -> "Ldind_u8"
| NullaryIlOp.Ldind_r4 -> "Ldind_r4"
| NullaryIlOp.Ldind_r8 -> "Ldind_r8"
| NullaryIlOp.Volatile -> "Volatile"
| NullaryIlOp.Tail -> "Tail"
| NullaryIlOp.Conv_ovf_i_un -> "Conv_ovf_i_un"
| NullaryIlOp.Conv_ovf_u_un -> "Conv_ovf_u_un"
| NullaryIlOp.Conv_ovf_i1_un -> "Conv_ovf_i1_un"
| NullaryIlOp.Conv_ovf_u1_un -> "Conv_ovf_u1_un"
| NullaryIlOp.Conv_ovf_i2_un -> "Conv_ovf_i2_un"
| NullaryIlOp.Conv_ovf_u2_un -> "Conv_ovf_u2_un"
| NullaryIlOp.Conv_ovf_i4_un -> "Conv_ovf_i4_un"
| NullaryIlOp.Conv_ovf_u4_un -> "Conv_ovf_u4_un"
| NullaryIlOp.Conv_ovf_i8_un -> "Conv_ovf_i8_un"
| NullaryIlOp.Conv_ovf_u8_un -> "Conv_ovf_u8_un"
| NullaryIlOp.Ldelem_i -> "Ldelem_i"
| NullaryIlOp.Ldelem_i1 -> "Ldelem_i1"
| NullaryIlOp.Ldelem_u1 -> "Ldelem_u1"
| NullaryIlOp.Ldelem_i2 -> "Ldelem_i2"
| NullaryIlOp.Ldelem_u2 -> "Ldelem_u2"
| NullaryIlOp.Ldelem_i4 -> "Ldelem_i4"
| NullaryIlOp.Ldelem_u4 -> "Ldelem_u4"
| NullaryIlOp.Ldelem_i8 -> "Ldelem_i8"
| NullaryIlOp.Ldelem_u8 -> "Ldelem_u8"
| NullaryIlOp.Ldelem_r4 -> "Ldelem_r4"
| NullaryIlOp.Ldelem_r8 -> "Ldelem_r8"
| NullaryIlOp.Ldelem_ref -> "Ldelem_ref"
| NullaryIlOp.Stelem_i -> "Stelem_i"
| NullaryIlOp.Stelem_i1 -> "Stelem_i1"
| NullaryIlOp.Stelem_u1 -> "Stelem_u1"
| NullaryIlOp.Stelem_i2 -> "Stelem_i2"
| NullaryIlOp.Stelem_u2 -> "Stelem_u2"
| NullaryIlOp.Stelem_i4 -> "Stelem_i4"
| NullaryIlOp.Stelem_u4 -> "Stelem_u4"
| NullaryIlOp.Stelem_i8 -> "Stelem_i8"
| NullaryIlOp.Stelem_u8 -> "Stelem_u8"
| NullaryIlOp.Stelem_r4 -> "Stelem_r4"
| NullaryIlOp.Stelem_r8 -> "Stelem_r8"
| NullaryIlOp.Stelem_ref -> "Stelem_ref"
| NullaryIlOp.Cpblk -> "Cpblk"
| NullaryIlOp.Initblk -> "Initblk"
| NullaryIlOp.Break -> "Break"
| NullaryIlOp.Conv_r_un -> "Conv_r_un"
| NullaryIlOp.Arglist -> "Arglist"
| NullaryIlOp.Ckfinite -> "Ckfinite"
| NullaryIlOp.Readonly -> "Readonly"
| NullaryIlOp.Refanytype -> "Refanytype"
/// The number of bytes this instruction takes in memory.
static member NumberOfBytes (op : NullaryIlOp) : int =
match op with
| Arglist
| Ceq
| Cgt
| Cgt_un
| Clt
| Clt_un
| Localloc
| Endfilter
| Volatile
| Tail
| Cpblk
| Initblk
| Rethrow
| Refanytype
| Readonly -> 2
| _ -> 1
type UnaryConstIlOp =
| Stloc of uint16
| Stloc_s of int8
| Ldc_I8 of int64
| Ldc_I4 of int32
| Ldc_R4 of single
| Ldc_R8 of float
| Ldc_I4_s of int8
| Br of int32
| Br_s of int8
| Brfalse_s of int8
| Brtrue_s of int8
| Brfalse of int32
| Brtrue of int32
| Beq_s of int8
| Blt_s of int8
| Ble_s of int8
| Bgt_s of int8
| Bge_s of int8
| Beq of int32
| Blt of int32
| Ble of int32
| Bgt of int32
| Bge of int32
| Bne_un_s of int8
| Bge_un_s of int8
| Bgt_un_s of int8
| Ble_un_s of int8
/// Transfers control to a target instruction if the first value is less than the second value.
| Blt_un_s of int8
| Bne_un of int32
| Bge_un of int32
| Bgt_un of int32
| Ble_un of int32
| Blt_un of int32
/// Loads the local variable at a specific index onto the evaluation stack.
| Ldloc_s of uint8
| Ldloca_s of uint8
/// Load the address of an argument onto the stack.
| Ldarga of uint16
| Ldarg_s of uint8
/// Load the address of an argument onto the stack.
| Ldarga_s of uint8
/// Unconditionally transfer control to this offset from the next instruction;
/// like Br but can leave a try/filter/catch block too, and ensures surrounding `finally` blocks execute.
/// Unconditionally empties the evaluation stack; so a Leave outside an exception-handling block is just a Br which
/// also clears the eval stack.
| Leave of int32
/// Unconditionally transfer control to this offset from the next instruction;
/// like Br but can leave a try/filter/catch block too, and ensures surrounding `finally` blocks execute.
/// Unconditionally empties the evaluation stack; so a Leave outside an exception-handling block is just a Br which
/// also clears the eval stack.
| Leave_s of int8
| Starg_s of uint8
| Starg of uint16
| Unaligned of uint8
| Ldloc of uint16
| Ldloca of uint16
| Ldarg of uint16
/// The number of bytes this instruction takes in memory, including its constant argument that is inline in the
/// byte stream.
static member NumberOfBytes (op : UnaryConstIlOp) : int =
match op with
| Ldarg _uint16
| Ldarga _uint16
| Starg _uint16
| Ldloc _uint16
| Ldloca _uint16
| Stloc _uint16 -> 2 + 2 // Two-byte opcode + two-byte argument
| Ldarg_s _
| Ldarga_s _
| Starg_s _
| Ldloc_s _
| Ldloca_s _
| Stloc_s _
| Ldc_I4_s _
| Br_s _
| Brfalse_s _
| Brtrue_s _
| Beq_s _
| Blt_s _
| Ble_s _
| Bgt_s _
| Bge_s _
| Bne_un_s _
| Bge_un_s _
| Bgt_un_s _
| Ble_un_s _
| Blt_un_s _
| Leave_s _
| Unaligned _ -> 1 + 1 // One-byte opcode + one-byte argument
| Ldc_I8 _ -> 1 + 8 // One-byte opcode + 8-byte argument
| Ldc_I4 _
| Br _
| Brfalse _
| Brtrue _
| Beq _
| Blt _
| Ble _
| Bgt _
| Bge _
| Bne_un _
| Bge_un _
| Bgt_un _
| Ble_un _
| Blt_un _
| Leave _ -> 1 + 4 // One-byte opcode + 4-byte argument
| Ldc_R4 _ -> 1 + 4 // One-byte opcode + 4-byte argument
| Ldc_R8 _ -> 1 + 8 // One-byte opcode + 8-byte argument
override this.ToString () =
match this with
| UnaryConstIlOp.Stloc i -> $"Stloc %i{i}"
| UnaryConstIlOp.Stloc_s i -> $"Stloc_s %i{i}"
| UnaryConstIlOp.Ldc_I8 i -> $"Ldc_I8 %i{i}"
| UnaryConstIlOp.Ldc_I4 i -> $"Ldc_I4 %i{i}"
| UnaryConstIlOp.Ldc_R4 f -> $"Ldc_R4 %f{f}"
| UnaryConstIlOp.Ldc_R8 f -> $"Ldc_R8 %f{f}"
| UnaryConstIlOp.Ldc_I4_s i -> $"Ldc_I4_s %i{i}"
| UnaryConstIlOp.Br i -> $"Br %i{i}"
| UnaryConstIlOp.Br_s i -> $"Br_s %i{i}"
| UnaryConstIlOp.Brfalse_s i -> $"Brfalse_s %i{i}"
| UnaryConstIlOp.Brtrue_s i -> $"Brtrue_s %i{i}"
| UnaryConstIlOp.Brfalse i -> $"Brfalse %i{i}"
| UnaryConstIlOp.Brtrue i -> $"Brtrue %i{i}"
| UnaryConstIlOp.Beq_s i -> $"Beq_s %i{i}"
| UnaryConstIlOp.Blt_s i -> $"Blt_s %i{i}"
| UnaryConstIlOp.Ble_s i -> $"Ble_s %i{i}"
| UnaryConstIlOp.Bgt_s i -> $"Bgt_s %i{i}"
| UnaryConstIlOp.Bge_s i -> $"Bge_s %i{i}"
| UnaryConstIlOp.Beq i -> $"Beq %i{i}"
| UnaryConstIlOp.Blt i -> $"Blt %i{i}"
| UnaryConstIlOp.Ble i -> $"Ble %i{i}"
| UnaryConstIlOp.Bgt i -> $"Bgt %i{i}"
| UnaryConstIlOp.Bge i -> $"Bge %i{i}"
| UnaryConstIlOp.Bne_un_s i -> $"Bne_un_s %i{i}"
| UnaryConstIlOp.Bge_un_s i -> $"Bge_un_s %i{i}"
| UnaryConstIlOp.Bgt_un_s i -> $"Bgt_un_s %i{i}"
| UnaryConstIlOp.Ble_un_s i -> $"Ble_un_s %i{i}"
| UnaryConstIlOp.Blt_un_s i -> $"Blt_un_s %i{i}"
| UnaryConstIlOp.Bne_un i -> $"Bne_un %i{i}"
| UnaryConstIlOp.Bge_un i -> $"Bge_un %i{i}"
| UnaryConstIlOp.Bgt_un i -> $"Bgt_un %i{i}"
| UnaryConstIlOp.Ble_un i -> $"Ble_un %i{i}"
| UnaryConstIlOp.Blt_un i -> $"Blt_un %i{i}"
| UnaryConstIlOp.Ldloc_s i -> $"Ldloc_s %i{i}"
| UnaryConstIlOp.Ldloca_s i -> $"Ldloca_s %i{i}"
| UnaryConstIlOp.Ldarga i -> $"Ldarga %i{i}"
| UnaryConstIlOp.Ldarg_s i -> $"Ldarg_s %i{i}"
| UnaryConstIlOp.Ldarga_s i -> $"Ldarga_s %i{i}"
| UnaryConstIlOp.Leave i -> $"Leave %i{i}"
| UnaryConstIlOp.Leave_s i -> $"Leave_s %i{i}"
| UnaryConstIlOp.Starg_s i -> $"Starg_s %i{i}"
| UnaryConstIlOp.Starg i -> $"Starg %i{i}"
| UnaryConstIlOp.Unaligned i -> $"Unaligned %i{i}"
| UnaryConstIlOp.Ldloc i -> $"Ldloc %i{i}"
| UnaryConstIlOp.Ldloca i -> $"Ldloca %i{i}"
| UnaryConstIlOp.Ldarg i -> $"Ldarg %i{i}"
type UnaryMetadataTokenIlOp =
| Call
| Calli
| Callvirt
/// Attempts to cast an object passed by reference to the specified class.
/// If the class of the object on the top of the stack does not implement the new class
/// (assuming the new class is an interface)
/// and is not a derived class of the new class then an InvalidCastException is thrown.
/// If the object reference is a null reference, castclass succeeds
/// and returns the new object as a null reference.
| Castclass
| Newobj
| Newarr
| Box
/// Loads the address of the array element at a specified array index onto the top of the evaluation stack as type "managed pointer"
| Ldelema
| Isinst
/// Pop value from stack; pop object ref from stack; set specified field on that object to that value.
| Stfld
/// Pop value from eval stack; set specified static field to that value.
| Stsfld
/// Pop object ref from eval stack; look up specified field on that object; push field's value to eval stack.
| Ldfld
/// Pop object ref from eval stack; find address of specified field on that object; push address to eval stack.
| Ldflda
/// Push value of specified static field onto eval stack.
| Ldsfld
| Ldsflda
| Unbox_Any
/// Replaces the array element at a given index with the value on the eval stack
| Stelem
/// Pushes the element at a specified array index onto the eval stack
| Ldelem
| Initobj
/// Pushes an unmanaged pointer (native int) to the stack, pointing to native code.
| Ldftn
| Stobj
| Constrained
| Ldtoken
| Cpobj
| Ldobj
| Sizeof
| Unbox
| Ldvirtftn
| Mkrefany
| Refanyval
| Jmp
override this.ToString () =
match this with
| UnaryMetadataTokenIlOp.Call -> "Call"
| UnaryMetadataTokenIlOp.Calli -> "Calli"
| UnaryMetadataTokenIlOp.Callvirt -> "Callvirt"
| UnaryMetadataTokenIlOp.Castclass -> "Castclass"
| UnaryMetadataTokenIlOp.Newobj -> "Newobj"
| UnaryMetadataTokenIlOp.Newarr -> "Newarr"
| UnaryMetadataTokenIlOp.Box -> "Box"
| UnaryMetadataTokenIlOp.Ldelema -> "Ldelema"
| UnaryMetadataTokenIlOp.Isinst -> "Isinst"
| UnaryMetadataTokenIlOp.Stfld -> "Stfld"
| UnaryMetadataTokenIlOp.Stsfld -> "Stsfld"
| UnaryMetadataTokenIlOp.Ldfld -> "Ldfld"
| UnaryMetadataTokenIlOp.Ldflda -> "Ldflda"
| UnaryMetadataTokenIlOp.Ldsfld -> "Ldsfld"
| UnaryMetadataTokenIlOp.Ldsflda -> "Ldsflda"
| UnaryMetadataTokenIlOp.Unbox_Any -> "Unbox_Any"
| UnaryMetadataTokenIlOp.Stelem -> "Stelem"
| UnaryMetadataTokenIlOp.Ldelem -> "Ldelem"
| UnaryMetadataTokenIlOp.Initobj -> "Initobj"
| UnaryMetadataTokenIlOp.Ldftn -> "Ldftn"
| UnaryMetadataTokenIlOp.Stobj -> "Stobj"
| UnaryMetadataTokenIlOp.Constrained -> "Constrained"
| UnaryMetadataTokenIlOp.Ldtoken -> "Ldtoken"
| UnaryMetadataTokenIlOp.Cpobj -> "Cpobj"
| UnaryMetadataTokenIlOp.Ldobj -> "Ldobj"
| UnaryMetadataTokenIlOp.Sizeof -> "Sizeof"
| UnaryMetadataTokenIlOp.Unbox -> "Unbox"
| UnaryMetadataTokenIlOp.Ldvirtftn -> "Ldvirtftn"
| UnaryMetadataTokenIlOp.Mkrefany -> "Mkrefany"
| UnaryMetadataTokenIlOp.Refanyval -> "Refanyval"
| UnaryMetadataTokenIlOp.Jmp -> "Jmp"
/// The number of bytes this instruction takes in memory, including its metadata token argument.
static member NumberOfBytes (op : UnaryMetadataTokenIlOp) : int =
match op with
| Ldftn
| Ldvirtftn
| Initobj
| Constrained
| Sizeof -> 2 + 4 // Two-byte opcode + 4-byte token
| Call
| Calli
| Callvirt
| Castclass
| Newobj
| Newarr
| Box
| Ldelema
| Isinst
| Stfld
| Stsfld
| Ldfld
| Ldflda
| Ldsfld
| Ldsflda
| Unbox_Any
| Stelem
| Ldelem
| Stobj
| Ldtoken
| Cpobj
| Ldobj
| Unbox
| Mkrefany
| Refanyval
| Jmp -> 1 + 4 // One-byte opcode + 4-byte token
type UnaryStringTokenIlOp =
| Ldstr
static member NumberOfBytes (op : UnaryStringTokenIlOp) : int =
match op with
| Ldstr -> 1 + 4
type IlOp =
| Nullary of NullaryIlOp
| UnaryConst of UnaryConstIlOp
| UnaryMetadataToken of UnaryMetadataTokenIlOp * MetadataToken
| UnaryStringToken of UnaryStringTokenIlOp * StringToken
| Switch of int32 ImmutableArray
override this.ToString () =
match this with
| IlOp.Nullary op -> $"Nullary %O{op}"
| IlOp.UnaryConst op -> $"UnaryConst.%O{op}"
| IlOp.UnaryMetadataToken (op, _) -> $"UnaryMetadataToken.%O{op}"
| IlOp.UnaryStringToken (op, _) -> $"UnaryStringToken.%O{op}"
| IlOp.Switch arr -> $"Switch[%i{arr.Length}]"
static member Format (opCode : IlOp) (offset : int) : string = $" IL_%04X{offset}: %-20O{opCode}"
static member NumberOfBytes (op : IlOp) =
match op with
| Nullary op -> NullaryIlOp.NumberOfBytes op
| UnaryConst op -> UnaryConstIlOp.NumberOfBytes op
| UnaryMetadataToken (op, _) -> UnaryMetadataTokenIlOp.NumberOfBytes op
| UnaryStringToken (op, _) -> UnaryStringTokenIlOp.NumberOfBytes op
| Switch arr -> 1 + 4 + arr.Length * 4