#ifndef IL_H #define IL_H enum ILCommandType { icUnknown, icByte, icWord, icDword, icQword, icComment, icData, icCase, icNop, icBreak, icLdarg_0, icLdarg_1, icLdarg_2, icLdarg_3, icLdloc_0, icLdloc_1, icLdloc_2, icLdloc_3, icStloc_0, icStloc_1, icStloc_2, icStloc_3, icLdarg_s, icLdarga_s, icStarg_s, icLdloc_s, icLdloca_s, icStloc_s, icLdnull, icLdc_i4_m1, icLdc_i4_0, icLdc_i4_1, icLdc_i4_2, icLdc_i4_3, icLdc_i4_4, icLdc_i4_5, icLdc_i4_6, icLdc_i4_7, icLdc_i4_8, icLdc_i4_s, icLdc_i4, icLdc_i8, icLdc_r4, icLdc_r8, icDup, icPop, icJmp, icCall, icCalli, icRet, icBr_s, icBrfalse_s, icBrtrue_s, icBeq_s, icBge_s, icBgt_s, icBle_s, icBlt_s, icBne_un_s, icBge_un_s, icBgt_un_s, icBle_un_s, icBlt_un_s, icBr, icBrfalse, icBrtrue, icBeq, icBge, icBgt, icBle, icBlt, icBne_un, icBge_un, icBgt_un, icBle_un, icBlt_un, icSwitch, icLdind_i1, icLdind_u1, icLdind_i2, icLdind_u2, icLdind_i4, icLdind_u4, icLdind_i8, icLdind_i, icLdind_r4, icLdind_r8, icLdind_ref, icStind_ref, icStind_i1, icStind_i2, icStind_i4, icStind_i8, icStind_r4, icStind_r8, icAdd, icSub, icMul, icDiv, icDiv_un, icRem, icRem_un, icAnd, icOr, icXor, icShl, icShr, icShr_un, icNeg, icNot, icConv_i1, icConv_i2, icConv_i4, icConv_i8, icConv_r4, icConv_r8, icConv_u4, icConv_u8, icCallvirt, icCpobj, icLdobj, icLdstr, icNewobj, icCastclass, icIsinst, icConv_r_un, icUnbox, icThrow, icLdfld, icLdflda, icStfld, icLdsfld, icLdsflda, icStsfld, icStobj, icConv_ovf_i1_un, icConv_ovf_i2_un, icConv_ovf_i4_un, icConv_ovf_i8_un, icConv_ovf_u1_un, icConv_ovf_u2_un, icConv_ovf_u4_un, icConv_ovf_u8_un, icConv_ovf_i_un, icConv_ovf_u_un, icBox, icNewarr, icLdlen, icLdelema, icLdelem_i1, icLdelem_u1, icLdelem_i2, icLdelem_u2, icLdelem_i4, icLdelem_u4, icLdelem_i8, icLdelem_i, icLdelem_r4, icLdelem_r8, icLdelem_ref, icStelem_i, icStelem_i1, icStelem_i2, icStelem_i4, icStelem_i8, icStelem_r4, icStelem_r8, icStelem_ref, icLdelem, icStelem, icUnbox_any, icConv_ovf_i1, icConv_ovf_u1, icConv_ovf_i2, icConv_ovf_u2, icConv_ovf_i4, icConv_ovf_u4, icConv_ovf_i8, icConv_ovf_u8, icRefanyval, icCkfinite, icMkrefany, icLdtoken, icConv_u2, icConv_u1, icConv_i, icConv_ovf_i, icConv_ovf_u, icAdd_ovf, icAdd_ovf_un, icMul_ovf, icMul_ovf_un, icSub_ovf, icSub_ovf_un, icEndfinally, icLeave, icLeave_s, icStind_i, icConv_u, icArglist, icCeq, icCgt, icCgt_un, icClt, icClt_un, icLdftn, icLdvirtftn, icLdarg, icLdarga, icStarg, icLdloc, icLdloca, icStloc, icLocalloc, icEndfilter, icUnaligned, icVolatile, icTail, icInitobj, icConstrained, icCpblk, icInitblk, icNo, icRethrow, icSizeof, icRefanytype, icReadonly, icConv, icConv_ovf, icConv_ovf_un, icLdmem_i4, icInitarg, icInitcatchblock, icEntertry, icCallvm, icCallvmvirt, icCmp, icCmp_un, icCNT }; enum ILFlowControl : uint8_t { Branch, Break, Call, Cond_Branch, Meta, // Provides information about a subsequent instruction. For example, the Unaligned instruction of Reflection.Emit.Opcodes has FlowControl.Meta and specifies that the subsequent pointer instruction might be unaligned. Next, // Normal flow of control Phi, // Obsolete. This enumerator value is reserved and should not be used. Return, Throw }; enum ILOpCodeType : uint8_t { Experimental, // Reserved (ECMA) instruction Macro, // synonym for other MSIL instructions (ldarg.0 - ldarg) Reserved, // Reserved (ECMA) instruction Objmodel, // Instruction that applies to objects Prefix, // Prefix instruction that modifies the behavior of the following instruction Primitive // Built-in instruction }; enum ILOperandType : uint8_t// The operand is a ... { InlineBrTarget, // 32-bit integer branch target InlineField, // 32-bit metadata token InlineI, // 32-bit integer InlineI8, // 64-bit integer InlineMethod, // 32-bit metadata token InlineNone, // No operand InlinePhi, // Obsolete. The operand is reserved and should not be used. InlineR, // 64-bit IEEE floating point number Inline8, // not used InlineSig, // 32-bit metadata signature token InlineString, // 32-bit metadata string token InlineSwitch, // 32-bit integer argument to a switch instruction InlineTok, // FieldRef, MethodRef, or TypeRef token InlineType, // 32-bit metadata token InlineVar, // 16-bit integer containing the ordinal of a local variable or an argument ShortInlineBrTarget, // 8-bit integer branch target ShortInlineI, // 8-bit integer ShortInlineR, // 32-bit IEEE floating point number ShortInlineVar, // 8-bit integer containing the ordinal of a local variable or an argument }; enum ILStackBehaviour : uint8_t { Pop0, // No values are popped off the stack. Pop1, // Pops one value off the stack. Pop1_pop1, // Pops 1 value off the stack for the first operand, and 1 value of the stack for the second operand. Popi, // Pops a 32-bit integer off the stack. Popi_pop1, // Pops a 32-bit integer off the stack for the first operand, and a value off the stack for the second operand. Popi_popi, // Pops a 32-bit integer off the stack for the first operand, and a 32-bit integer off the stack for the second operand. Popi_popi8, // Pops a 32-bit integer off the stack for the first operand, and a 64-bit integer off the stack for the second operand. Popi_popi_popi, // Pops a 32-bit integer off the stack for the first operand, a 32-bit integer off the stack for the second operand, and a 32-bit integer off the stack for the third operand. Popi_popr4, // Pops a 32-bit integer off the stack for the first operand, and a 32-bit floating point number off the stack for the second operand. Popi_popr8, // Pops a 32-bit integer off the stack for the first operand, and a 64-bit floating point number off the stack for the second operand. Popref, // Pops a reference off the stack. Popref_pop1, // Pops a reference off the stack for the first operand, and a value off the stack for the second operand. Popref_popi, // Pops a reference off the stack for the first operand, and a 32-bit integer off the stack for the second operand. Popref_popi_popi, // Pops a reference off the stack for the first operand, a value off the stack for the second operand, and a value off the stack for the third operand. Popref_popi_popi8, // Pops a reference off the stack for the first operand, a value off the stack for the second operand, and a 64-bit integer off the stack for the third operand. Popref_popi_popr4, // Pops a reference off the stack for the first operand, a value off the stack for the second operand, and a 32-bit integer off the stack for the third operand. Popref_popi_popr8, // Pops a reference off the stack for the first operand, a value off the stack for the second operand, and a 64-bit floating point number off the stack for the third operand. Popref_popi_popref, // Pops a reference off the stack for the first operand, a value off the stack for the second operand, and a reference off the stack for the third operand. Push0, // No values are pushed onto the stack. Push1, // Pushes one value onto the stack. Push1_push1, // Pushes 1 value onto the stack for the first operand, and 1 value onto the stack for the second operand. Pushi, // Pushes a 32-bit integer onto the stack. Pushi8, // Pushes a 64-bit integer onto the stack. Pushr4, // Pushes a 32-bit floating point number onto the stack. Pushr8, // Pushes a 64-bit floating point number onto the stack. Pushref, // Pushes a reference onto the stack. Varpop, // Pops a variable off the stack. Varpush, // Pushes a variable onto the stack. Popref_popi_pop1 // Pops a reference off the stack for the first operand, a value off the stack for the second operand, and a 32-bit integer off the stack for the third operand. }; struct ILOpCode { const char *name; ILStackBehaviour pop; ILStackBehaviour push; ILOperandType operand_type; ILOpCodeType opcode_type; ILFlowControl flow_type; bool is_ret; int stack_change; } const ILOpCodes[icCNT] = { {".byte ??", Pop0, Push0, InlineNone, Primitive, Next, false, 0}, {".byte", Pop0, Push0, ShortInlineI, Primitive, Next, false, 0}, {".word", Pop0, Push0, InlineVar, Primitive, Next, false, 0}, {".dword", Pop0, Push0, InlineI, Primitive, Next, false, 0}, {".qword", Pop0, Push0, InlineI8, Primitive, Next, false, 0}, {"", Pop0, Push0, InlineNone, Primitive, Next, false, 0}, {".byte", Pop0, Push0, InlineNone, Primitive, Next, false, 0}, {"", Pop0, Push0, InlineI, Primitive, Next, false, 0}, {"nop", Pop0, Push0, InlineNone, Primitive, Next, false, 0}, {"break", Pop0, Push0, InlineNone, Primitive, Break, false, 0}, {"ldarg.0", Pop0, Push1, InlineNone, Macro, Next, false, 1}, {"ldarg.1", Pop0, Push1, InlineNone, Macro, Next, false, 1}, {"ldarg.2", Pop0, Push1, InlineNone, Macro, Next, false, 1}, {"ldarg.3", Pop0, Push1, InlineNone, Macro, Next, false, 1}, {"ldloc.0", Pop0, Push1, InlineNone, Macro, Next, false, 1}, {"ldloc.1", Pop0, Push1, InlineNone, Macro, Next, false, 1}, {"ldloc.2", Pop0, Push1, InlineNone, Macro, Next, false, 1}, {"ldloc.3", Pop0, Push1, InlineNone, Macro, Next, false, 1}, {"stloc.0", Pop1, Push0, InlineNone, Macro, Next, false, -1}, {"stloc.1", Pop1, Push0, InlineNone, Macro, Next, false, -1}, {"stloc.2", Pop1, Push0, InlineNone, Macro, Next, false, -1}, {"stloc.3", Pop1, Push0, InlineNone, Macro, Next, false, -1}, {"ldarg.s", Pop0, Push1, ShortInlineVar, Macro, Next, false, 1}, {"ldarga.s", Pop0, Pushi, ShortInlineVar, Macro, Next, false, 1}, {"starg.s", Pop1, Push0, ShortInlineVar, Macro, Next, false, -1}, {"ldloc.s", Pop0, Push1, ShortInlineVar, Macro, Next, false, 1}, {"ldloca.s", Pop0, Pushi, ShortInlineVar, Macro, Next, false, 1}, {"stloc.s", Pop1, Push0, ShortInlineVar, Macro, Next, false, -1}, {"ldnull", Pop0, Pushref, InlineNone, Primitive, Next, false, 1}, {"ldc.i4.m1", Pop0, Pushi, InlineNone, Macro, Next, false, 1}, {"ldc.i4.0", Pop0, Pushi, InlineNone, Macro, Next, false, 1}, {"ldc.i4.1", Pop0, Pushi, InlineNone, Macro, Next, false, 1}, {"ldc.i4.2", Pop0, Pushi, InlineNone, Macro, Next, false, 1}, {"ldc.i4.3", Pop0, Pushi, InlineNone, Macro, Next, false, 1}, {"ldc.i4.4", Pop0, Pushi, InlineNone, Macro, Next, false, 1}, {"ldc.i4.5", Pop0, Pushi, InlineNone, Macro, Next, false, 1}, {"ldc.i4.6", Pop0, Pushi, InlineNone, Macro, Next, false, 1}, {"ldc.i4.7", Pop0, Pushi, InlineNone, Macro, Next, false, 1}, {"ldc.i4.8", Pop0, Pushi, InlineNone, Macro, Next, false, 1}, {"ldc.i4.s", Pop0, Pushi, ShortInlineI, Macro, Next, false, 1}, {"ldc.i4", Pop0, Pushi, InlineI, Primitive, Next, false, 1}, {"ldc.i8", Pop0, Pushi8, InlineI8, Primitive, Next, false, 1}, {"ldc.r4", Pop0, Pushr4, ShortInlineR, Primitive, Next, false, 1}, {"ldc.r8", Pop0, Pushr8, InlineR, Primitive, Next, false, 1}, {"dup", Pop1, Push1_push1, InlineNone, Primitive, Next, false, 1}, {"pop", Pop1, Push0, InlineNone, Primitive, Next, false, -1}, {"jmp", Pop0, Push0, InlineMethod, Primitive, Call, true, 0}, {"call", Varpop, Varpush, InlineMethod, Primitive, Call, false, 0}, {"calli", Varpop, Varpush, InlineSig, Primitive, Call, false, 0}, {"ret", Varpop, Push0, InlineNone, Primitive, Return, true, 0}, {"br.s", Pop0, Push0, ShortInlineBrTarget, Macro, Branch, true, 0}, {"brfalse.s", Popi, Push0, ShortInlineBrTarget, Macro, Cond_Branch, false, -1}, {"brtrue.s", Popi, Push0, ShortInlineBrTarget, Macro, Cond_Branch, false, -1}, {"beq.s", Pop1_pop1, Push0, ShortInlineBrTarget, Macro, Cond_Branch, false, -2}, {"bge.s", Pop1_pop1, Push0, ShortInlineBrTarget, Macro, Cond_Branch, false, -2}, {"bgt.s", Pop1_pop1, Push0, ShortInlineBrTarget, Macro, Cond_Branch, false, -2}, {"ble.s", Pop1_pop1, Push0, ShortInlineBrTarget, Macro, Cond_Branch, false, -2}, {"blt.s", Pop1_pop1, Push0, ShortInlineBrTarget, Macro, Cond_Branch, false, -2}, {"bne.un.s", Pop1_pop1, Push0, ShortInlineBrTarget, Macro, Cond_Branch, false, -2}, {"bge.un.s", Pop1_pop1, Push0, ShortInlineBrTarget, Macro, Cond_Branch, false, -2}, {"bgt.un.s", Pop1_pop1, Push0, ShortInlineBrTarget, Macro, Cond_Branch, false, -2}, {"ble.un.s", Pop1_pop1, Push0, ShortInlineBrTarget, Macro, Cond_Branch, false, -2}, {"blt.un.s", Pop1_pop1, Push0, ShortInlineBrTarget, Macro, Cond_Branch, false, -2}, {"br", Pop0, Push0, InlineBrTarget, Primitive, Branch, true, 0}, {"brfalse", Popi, Push0, InlineBrTarget, Primitive, Cond_Branch, false, -1}, {"brtrue", Popi, Push0, InlineBrTarget, Primitive, Cond_Branch, false, -1}, {"beq", Pop1_pop1, Push0, InlineBrTarget, Macro, Cond_Branch, false, -2}, {"bge", Pop1_pop1, Push0, InlineBrTarget, Macro, Cond_Branch, false, -2}, {"bgt", Pop1_pop1, Push0, InlineBrTarget, Macro, Cond_Branch, false, -2}, {"ble", Pop1_pop1, Push0, InlineBrTarget, Macro, Cond_Branch, false, -2}, {"blt", Pop1_pop1, Push0, InlineBrTarget, Macro, Cond_Branch, false, -2}, {"bne.un", Pop1_pop1, Push0, InlineBrTarget, Macro, Cond_Branch, false, -2}, {"bge.un", Pop1_pop1, Push0, InlineBrTarget, Macro, Cond_Branch, false, -2}, {"bgt.un", Pop1_pop1, Push0, InlineBrTarget, Macro, Cond_Branch, false, -2}, {"ble.un", Pop1_pop1, Push0, InlineBrTarget, Macro, Cond_Branch, false, -2}, {"blt.un", Pop1_pop1, Push0, InlineBrTarget, Macro, Cond_Branch, false, -2}, {"switch", Popi, Push0, InlineSwitch, Primitive, Cond_Branch, false, -1}, {"ldind.i1", Popi, Pushi, InlineNone, Primitive, Next, false, 0}, {"ldind.u1", Popi, Pushi, InlineNone, Primitive, Next, false, 0}, {"ldind.i2", Popi, Pushi, InlineNone, Primitive, Next, false, 0}, {"ldind.u2", Popi, Pushi, InlineNone, Primitive, Next, false, 0}, {"ldind.i4", Popi, Pushi, InlineNone, Primitive, Next, false, 0}, {"ldind.u4", Popi, Pushi, InlineNone, Primitive, Next, false, 0}, {"ldind.i8", Popi, Pushi8, InlineNone, Primitive, Next, false, 0}, {"ldind.i", Popi, Pushi, InlineNone, Primitive, Next, false, 0}, {"ldind.r4", Popi, Pushr4, InlineNone, Primitive, Next, false, 0}, {"ldind.r8", Popi, Pushr8, InlineNone, Primitive, Next, false, 0}, {"ldind.ref", Popi, Pushref, InlineNone, Primitive, Next, false, 0}, {"stind.ref", Popi_popi, Push0, InlineNone, Primitive, Next, false, -2}, {"stind.i1", Popi_popi, Push0, InlineNone, Primitive, Next, false, -2}, {"stind.i2", Popi_popi, Push0, InlineNone, Primitive, Next, false, -2}, {"stind.i4", Popi_popi, Push0, InlineNone, Primitive, Next, false, -2}, {"stind.i8", Popi_popi8, Push0, InlineNone, Primitive, Next, false, -2}, {"stind.r4", Popi_popr4, Push0, InlineNone, Primitive, Next, false, -2}, {"stind.r8", Popi_popr8, Push0, InlineNone, Primitive, Next, false, -2}, {"add", Pop1_pop1, Push1, InlineNone, Primitive, Next, false, -1}, {"sub", Pop1_pop1, Push1, InlineNone, Primitive, Next, false, -1}, {"mul", Pop1_pop1, Push1, InlineNone, Primitive, Next, false, -1}, {"div", Pop1_pop1, Push1, InlineNone, Primitive, Next, false, -1}, {"div.un", Pop1_pop1, Push1, InlineNone, Primitive, Next, false, -1}, {"rem", Pop1_pop1, Push1, InlineNone, Primitive, Next, false, -1}, {"rem.un", Pop1_pop1, Push1, InlineNone, Primitive, Next, false, -1}, {"and", Pop1_pop1, Push1, InlineNone, Primitive, Next, false, -1}, {"or", Pop1_pop1, Push1, InlineNone, Primitive, Next, false, -1}, {"xor", Pop1_pop1, Push1, InlineNone, Primitive, Next, false, -1}, {"shl", Pop1_pop1, Push1, InlineNone, Primitive, Next, false, -1}, {"shr", Pop1_pop1, Push1, InlineNone, Primitive, Next, false, -1}, {"shr.un", Pop1_pop1, Push1, InlineNone, Primitive, Next, false, -1}, {"neg", Pop1, Push1, InlineNone, Primitive, Next, false, 0}, {"not", Pop1, Push1, InlineNone, Primitive, Next, false, 0}, {"conv.i1", Pop1, Pushi, InlineNone, Primitive, Next, false, 0}, {"conv.i2", Pop1, Pushi, InlineNone, Primitive, Next, false, 0}, {"conv.i4", Pop1, Pushi, InlineNone, Primitive, Next, false, 0}, {"conv.i8", Pop1, Pushi8, InlineNone, Primitive, Next, false, 0}, {"conv.r4", Pop1, Pushr4, InlineNone, Primitive, Next, false, 0}, {"conv.r8", Pop1, Pushr8, InlineNone, Primitive, Next, false, 0}, {"conv.u4", Pop1, Pushi, InlineNone, Primitive, Next, false, 0}, {"conv.u8", Pop1, Pushi8, InlineNone, Primitive, Next, false, 0}, {"callvirt", Varpop, Varpush, InlineMethod, Objmodel, Call, false, 0}, {"cpobj", Popi_popi, Push0, InlineType, Objmodel, Next, false, -2}, {"ldobj", Popi, Push1, InlineType, Objmodel, Next, false, 0}, {"ldstr", Pop0, Pushref, InlineString, Objmodel, Next, false, 1}, {"newobj", Varpop, Pushref, InlineMethod, Objmodel, Call, false, 1}, {"castclass", Popref, Pushref, InlineType, Objmodel, Next, false, 0}, {"isinst", Popref, Pushi, InlineType, Objmodel, Next, false, 0}, {"conv.r.un", Pop1, Pushr8, InlineNone, Primitive, Next, false, 0}, {"unbox", Popref, Pushi, InlineType, Primitive, Next, false, 0}, {"throw", Popref, Push0, InlineNone, Objmodel, Throw, true, -1}, {"ldfld", Popref, Push1, InlineField, Objmodel, Next, false, 0}, {"ldflda", Popref, Pushi, InlineField, Objmodel, Next, false, 0}, {"stfld", Popref_pop1, Push0, InlineField, Objmodel, Next, false, -2}, {"ldsfld", Pop0, Push1, InlineField, Objmodel, Next, false, 1}, {"ldsflda", Pop0, Pushi, InlineField, Objmodel, Next, false, 1}, {"stsfld", Pop1, Push0, InlineField, Objmodel, Next, false, -1}, {"stobj", Popi_pop1, Push0, InlineType, Primitive, Next, false, -2}, {"conv.ovf.i1.un", Pop1, Pushi, InlineNone, Primitive, Next, false, 0}, {"conv.ovf.i2.un", Pop1, Pushi, InlineNone, Primitive, Next, false, 0}, {"conv.ovf.i4.un", Pop1, Pushi, InlineNone, Primitive, Next, false, 0}, {"conv.ovf.i8.un", Pop1, Pushi8, InlineNone, Primitive, Next, false, 0}, {"conv.ovf.u1.un", Pop1, Pushi, InlineNone, Primitive, Next, false, 0}, {"conv.ovf.u2.un", Pop1, Pushi, InlineNone, Primitive, Next, false, 0}, {"conv.ovf.u4.un", Pop1, Pushi, InlineNone, Primitive, Next, false, 0}, {"conv.ovf.u8.un", Pop1, Pushi8, InlineNone, Primitive, Next, false, 0}, {"conv.ovf.i.un", Pop1, Pushi, InlineNone, Primitive, Next, false, 0}, {"conv.ovf.u.un", Pop1, Pushi, InlineNone, Primitive, Next, false, 0}, {"box", Pop1, Pushref, InlineType, Primitive, Next, false, 0}, {"newarr", Popi, Pushref, InlineType, Objmodel, Next, false, 0}, {"ldlen", Popref, Pushi, InlineNone, Objmodel, Next, false, 0}, {"ldelema", Popref_popi, Pushi, InlineType, Objmodel, Next, false, -1}, {"ldelem.i1", Popref_popi, Pushi, InlineNone, Objmodel, Next, false, -1}, {"ldelem.u1", Popref_popi, Pushi, InlineNone, Objmodel, Next, false, -1}, {"ldelem.i2", Popref_popi, Pushi, InlineNone, Objmodel, Next, false, -1}, {"ldelem.u2", Popref_popi, Pushi, InlineNone, Objmodel, Next, false, -1}, {"ldelem.i4", Popref_popi, Pushi, InlineNone, Objmodel, Next, false, -1}, {"ldelem.u4", Popref_popi, Pushi, InlineNone, Objmodel, Next, false, -1}, {"ldelem.i8", Popref_popi, Pushi8, InlineNone, Objmodel, Next, false, -1}, {"ldelem.i", Popref_popi, Pushi, InlineNone, Objmodel, Next, false, -1}, {"ldelem.r4", Popref_popi, Pushr4, InlineNone, Objmodel, Next, false, -1}, {"ldelem.r8", Popref_popi, Pushr8, InlineNone, Objmodel, Next, false, -1}, {"ldelem.ref", Popref_popi, Pushref, InlineNone, Objmodel, Next, false, -1}, {"stelem.i", Popref_popi_popi, Push0, InlineNone, Objmodel, Next, false, -3}, {"stelem.i1", Popref_popi_popi, Push0, InlineNone, Objmodel, Next, false, -3}, {"stelem.i2", Popref_popi_popi, Push0, InlineNone, Objmodel, Next, false, -3}, {"stelem.i4", Popref_popi_popi, Push0, InlineNone, Objmodel, Next, false, -3}, {"stelem.i8", Popref_popi_popi8, Push0, InlineNone, Objmodel, Next, false, -3}, {"stelem.r4", Popref_popi_popr4, Push0, InlineNone, Objmodel, Next, false, -3}, {"stelem.r8", Popref_popi_popr8, Push0, InlineNone, Objmodel, Next, false, -3}, {"stelem.ref", Popref_popi_popref, Push0, InlineNone, Objmodel, Next, false, -3}, {"ldelem", Popref_popi, Push1, InlineType, Objmodel, Next, false, -1}, {"stelem", Popref_popi_pop1, Push0, InlineType, Objmodel, Next, false, 0}, {"unbox.any", Popref, Push1, InlineType, Objmodel, Next, false, 0}, {"conv.ovf.i1", Pop1, Pushi, InlineNone, Primitive, Next, false, 0}, {"conv.ovf.u1", Pop1, Pushi, InlineNone, Primitive, Next, false, 0}, {"conv.ovf.i2", Pop1, Pushi, InlineNone, Primitive, Next, false, 0}, {"conv.ovf.u2", Pop1, Pushi, InlineNone, Primitive, Next, false, 0}, {"conv.ovf.i4", Pop1, Pushi, InlineNone, Primitive, Next, false, 0}, {"conv.ovf.u4", Pop1, Pushi, InlineNone, Primitive, Next, false, 0}, {"conv.ovf.i8", Pop1, Pushi8, InlineNone, Primitive, Next, false, 0}, {"conv.ovf.u8", Pop1, Pushi8, InlineNone, Primitive, Next, false, 0}, {"refanyval", Pop1, Pushi, InlineType, Primitive, Next, false, 0}, {"ckfinite", Pop1, Pushr8, InlineNone, Primitive, Next, false, 0}, {"mkrefany", Popi, Push1, InlineType, Primitive, Next, false, 0}, {"ldtoken", Pop0, Pushi, InlineTok, Primitive, Next, false, 1}, {"conv.u2", Pop1, Pushi, InlineNone, Primitive, Next, false, 0}, {"conv.u1", Pop1, Pushi, InlineNone, Primitive, Next, false, 0}, {"conv.i", Pop1, Pushi, InlineNone, Primitive, Next, false, 0}, {"conv.ovf.i", Pop1, Pushi, InlineNone, Primitive, Next, false, 0}, {"conv.ovf.u", Pop1, Pushi, InlineNone, Primitive, Next, false, 0}, {"add.ovf", Pop1_pop1, Push1, InlineNone, Primitive, Next, false, -1}, {"add.ovf.un", Pop1_pop1, Push1, InlineNone, Primitive, Next, false, -1}, {"mul.ovf", Pop1_pop1, Push1, InlineNone, Primitive, Next, false, -1}, {"mul.ovf.un", Pop1_pop1, Push1, InlineNone, Primitive, Next, false, -1}, {"sub.ovf", Pop1_pop1, Push1, InlineNone, Primitive, Next, false, -1}, {"sub.ovf.un", Pop1_pop1, Push1, InlineNone, Primitive, Next, false, -1}, {"endfinally", Pop0, Push0, InlineNone, Primitive, Return, true, 0}, {"leave", Pop0, Push0, InlineBrTarget, Primitive, Branch, true, 0}, {"leave.s", Pop0, Push0, ShortInlineBrTarget, Primitive, Branch, true, 0}, {"stind.i", Popi_popi, Push0, InlineNone, Primitive, Next, false, -2}, {"conv.u", Pop1, Pushi, InlineNone, Primitive, Next, false, 0}, {"arglist", Pop0, Pushi, InlineNone, Primitive, Next, false, 1}, {"ceq", Pop1_pop1, Pushi, InlineNone, Primitive, Next, false, -1}, {"cgt", Pop1_pop1, Pushi, InlineNone, Primitive, Next, false, -1}, {"cgt.un", Pop1_pop1, Pushi, InlineNone, Primitive, Next, false, -1}, {"clt", Pop1_pop1, Pushi, InlineNone, Primitive, Next, false, -1}, {"clt.un", Pop1_pop1, Pushi, InlineNone, Primitive, Next, false, -1}, {"ldftn", Pop0, Pushi, InlineMethod, Primitive, Next, false, 1}, {"ldvirtftn", Popref, Pushi, InlineMethod, Primitive, Next, false, 0}, {"ldarg", Pop0, Push1, InlineVar, Primitive, Next, false, 1}, {"ldarga", Pop0, Pushi, InlineVar, Primitive, Next, false, 1}, {"starg", Pop1, Push0, InlineVar, Primitive, Next, false, -1}, {"ldloc", Pop0, Push1, InlineVar, Primitive, Next, false, 1}, {"ldloca", Pop0, Pushi, InlineVar, Primitive, Next, false, 1}, {"stloc", Pop1, Push0, InlineVar, Primitive, Next, false, -1}, {"localloc", Popi, Pushi, InlineNone, Primitive, Next, false, 0}, {"endfilter", Popi, Push0, InlineNone, Primitive, Return, true, -1}, {"unaligned.", Pop0, Push0, ShortInlineI, Prefix, Meta, false, 0}, {"volatile.", Pop0, Push0, InlineNone, Prefix, Meta, false, 0}, {"tail.", Pop0, Push0, InlineNone, Prefix, Meta, false, 0}, {"initobj", Popi, Push0, InlineType, Objmodel, Next, false, -1}, {"constrained.", Pop0, Push0, InlineType, Prefix, Meta, false, 0}, {"cpblk", Popi_popi_popi, Push0, InlineNone, Primitive, Next, false, -3}, {"initblk", Popi_popi_popi, Push0, InlineNone, Primitive, Next, false, -3}, {"no.", Pop0, Push0, InlineNone, Prefix, Meta, false, 0}, {"rethrow", Pop0, Push0, InlineNone, Objmodel, Throw, true, 0}, {"sizeof", Pop0, Pushi, InlineType, Primitive, Next, false, 1}, {"refanytype", Pop1, Pushi, InlineNone, Primitive, Next, false, 0}, {"readonly.", Pop0, Push0, InlineNone, Prefix, Meta, false, 0}, {"", Pop0, Push0, InlineNone, Primitive, Next, false, 0}, {"", Pop0, Push0, InlineNone, Primitive, Next, false, 0}, {"", Pop0, Push0, InlineNone, Primitive, Next, false, 0}, {"", Pop0, Push0, InlineNone, Primitive, Next, false, 0}, {"", Pop0, Push0, InlineNone, Primitive, Next, false, 0}, {"", Pop0, Push0, InlineNone, Primitive, Next, false, 0}, {"", Pop0, Push0, InlineNone, Primitive, Next, false, 0}, {"", Pop0, Push0, InlineNone, Primitive, Next, false, 0}, {"", Pop0, Push0, InlineNone, Primitive, Next, false, 0}, {"", Pop0, Push0, InlineNone, Primitive, Next, false, 0}, {"", Pop0, Push0, InlineNone, Primitive, Next, false, 0} }; class TokenReference; class ILCommand; class ILVMCommand : public BaseVMCommand { public: explicit ILVMCommand(ILCommand *owner, ILCommandType command_type, uint64_t value, TokenReference *token_reference); virtual uint64_t address() const { return address_; } virtual void set_address(uint64_t address) { address_ = address; } virtual void Compile(); ILCommandType command_type() const { return command_type_; } uint64_t value() const { return value_; } void set_value(uint64_t value) { value_ = value; } void set_dump(const Data &dump) { dump_ = dump; } bool is_data() const { return (command_type_ == icByte || command_type_ == icWord || command_type_ == icDword); } virtual bool is_end() const { return false; } virtual void WriteToFile(IArchitecture &file); virtual size_t dump_size() const { return dump_.size(); } TokenReference *token_reference() const { return token_reference_; } ILCommandType crypt_command() const { return crypt_command_; } OperandSize crypt_size() const { return crypt_size_; } uint64_t crypt_key() const { return crypt_key_; } ILVMCommand *link_command() const { return link_command_; } void set_token_reference(TokenReference *token_reference) { token_reference_ = token_reference; } void set_crypt_command(ILCommandType crypt_command, OperandSize crypt_size, uint64_t crypt_key) { crypt_command_ = crypt_command; crypt_size_ = crypt_size; crypt_key_ = crypt_key; } void set_link_command(ILVMCommand *command) { link_command_ = command; } private: uint64_t address_; ILCommandType command_type_; uint64_t value_; Data dump_; TokenReference *token_reference_; ILCommandType crypt_command_; OperandSize crypt_size_; uint64_t crypt_key_; ILVMCommand *link_command_; }; class ILCommand: public BaseCommand { public: explicit ILCommand(IFunction *owner, OperandSize size, ILCommandType type, uint64_t operand_value, IFixup *fixup = NULL); explicit ILCommand(IFunction *owner, OperandSize size, uint64_t address = 0); explicit ILCommand(IFunction *owner, OperandSize size, const std::string &value); explicit ILCommand(IFunction *owner, OperandSize size, const Data &value); explicit ILCommand(IFunction *owner, const ILCommand &source); void Init(ILCommandType type, uint64_t operand_value = 0, TokenReference *token_reference = NULL); virtual void clear(); ILVMCommand *item(size_t index) const { return reinterpret_cast(BaseCommand::item(index)); } virtual uint64_t ext_vm_address() const { return (ext_vm_entry_) ? ext_vm_entry_->address() : vm_address(); } virtual ISEHandler *seh_handler() const; virtual void set_seh_handler(ISEHandler *handler); virtual uint64_t address() const { return address_; } virtual CommandType type() const { return type_; } virtual std::string text() const; virtual uint32_t section_options() const { return section_options_; } virtual void include_section_option(SectionOption option) { section_options_ |= option; } virtual void exclude_section_option(SectionOption option) { section_options_ &= ~option; } virtual size_t original_dump_size() const { return (original_dump_size_) ? original_dump_size_ : dump_size(); } virtual void CompileToNative(); virtual void CompileLink(const CompileContext &ctx); virtual void PrepareLink(const CompileContext &ctx); virtual void set_operand_value(size_t operand_index, uint64_t value); virtual void set_link_value(size_t link_index, uint64_t value); virtual void set_jmp_value(size_t link_index, uint64_t value) {}; virtual void set_address(uint64_t address); void set_operand_fixup(IFixup *fixup); virtual void ReadFromBuffer(Buffer &buffer, IArchitecture &file); virtual void Rebase(uint64_t delta_base); virtual ILCommand *Clone(IFunction *owner) const; virtual bool Merge(ICommand *command); void InitUnknown(); void InitComment(const std::string &comment); virtual bool is_data() const; virtual bool is_end() const; bool is_prefix() const; virtual std::string display_address() const; virtual std::string dump_str() const; OperandSize size() const { return size_; } virtual CommentInfo comment(); size_t ReadFromFile(IArchitecture & file); void WriteToFile(IArchitecture &file); uint64_t operand_value() const { return operand_value_; } size_t operand_pos() const { return operand_pos_; } uint64_t ReadValueFromFile(IArchitecture &file, OperandSize value_size, bool is_token = false); void ReadString(IArchitecture &file, size_t len); void ReadCaseCommand(IArchitecture &file); TokenReference *token_reference() const { return token_reference_; } void set_token_reference(TokenReference *token_reference) { token_reference_ = token_reference; } void CompileToVM(const CompileContext &ctx); ILVMCommand *AddVMCommand(const CompileContext &ctx, ILCommandType command_type, uint64_t value, uint32_t options = 0, TokenReference *token_reference = NULL, ILCommand *to_command = NULL); void AddExtSection(const CompileContext &ctx); void set_param(uint32_t param) { param_ = param; } int GetStackLevel(size_t *pop_ref = NULL) const; private: void AddCmpSection(const CompileContext &ctx, ILCommandType jmp_command); void AddJmpWithFlagSection(const CompileContext &ctx, bool is_true); void AddCryptorSection(const CompileContext &ctx, ValueCryptor *cryptor, bool is_decrypt); uint64_t address_; OperandSize size_; ILCommandType type_; uint64_t operand_value_; size_t original_dump_size_; uint32_t section_options_; size_t operand_pos_; TokenReference *token_reference_; std::vector vm_links_; InternalLinkList internal_links_; ILVMCommand *ext_vm_entry_; uint32_t param_; IFixup *fixup_; }; class ILFunction : public BaseFunction { public: explicit ILFunction(IFunctionList *owner, const FunctionName &name, CompilationType compilation_type, uint32_t compilation_options, bool need_compile, Folder *folder); explicit ILFunction(IFunctionList *owner = NULL); explicit ILFunction(IFunctionList *owner, OperandSize cpu_address_size, IFunction *parent = NULL); explicit ILFunction(IFunctionList *owner, const ILFunction &src); virtual ILFunction *Clone(IFunctionList *owner) const; ILCommand *item(size_t index) const { return reinterpret_cast(IFunction::item(index)); } virtual bool Compile(const CompileContext &ctx); virtual void AfterCompile(const CompileContext &ctx); virtual void CompileLinks(const CompileContext &ctx); virtual bool Prepare(const CompileContext &ctx); virtual void CompileInfo(const CompileContext &ctx); ILCommand *AddCommand(OperandSize value_size, uint64_t value); ILCommand *AddCommand(const std::string &value); ILCommand *AddCommand(const Data &value); ILCommand *AddCommand(ILCommandType type, uint64_t operand_value, IFixup *fixup = NULL); ILCommand *Add(uint64_t address); ILCommand *GetCommandByAddress(uint64_t address) const; ILCommand *GetCommandByNearAddress(uint64_t address) const; virtual void ReadFromBuffer(Buffer &buffer, IArchitecture &file); virtual ILCommand *ParseCommand(IArchitecture &file, uint64_t address, bool dump_mode = false); void CreateBlocks(); protected: virtual ILCommand *CreateCommand(); virtual ILCommand *ParseString(IArchitecture &file, uint64_t address, size_t len); virtual void ParseBeginCommands(IArchitecture &file); virtual void ParseEndCommands(IArchitecture &file); virtual IFunction *CreateFunction(IFunction *parent) { return new ILFunction(NULL, cpu_address_size(), parent); } void CalcStack(std::map &stack_map); void Mutate(const CompileContext &ctx); void CompileToNative(const CompileContext &ctx); void CompileToVM(const CompileContext &ctx); }; class ILFileHelper : public IObject { public: explicit ILFileHelper(); ~ILFileHelper(); void Parse(NETArchitecture &file); private: void AddString(NETArchitecture &file, uint32_t token, uint64_t reference); std::vector string_list_; MapFunctionList *marker_name_list_; size_t marker_index_; // no copy ctr or assignment op ILFileHelper(const ILFileHelper &); ILFileHelper &operator =(const ILFileHelper &); }; class ILCommandBlock; class ILToken; class ILMethodDef; class ILCommandNode : public IObject { public: ILCommandNode(ILCommandBlock *owner, ILCommand *command); ~ILCommandNode(); ILCommand *command() const { return command_; } std::vector stack() const { return stack_; } void set_stack(std::vector &stack) { stack_ = stack; } std::string token_name() const; private: ILCommandBlock *owner_; ILCommand *command_; std::vector stack_; }; class ILCommandBlock : public ObjectList { public: ILCommandBlock(); bool Parse(ILFunction &func); ILCommandNode *GetNodeByCommand(ILCommand *command) const; ILToken *GetTypeOf(ILCommandNode *node) const; ILToken *GetTypeFromStack(ILCommandNode *node) const; protected: void AddObject(ILCommandNode *node); private: ILCommandNode *Add(ILCommand *command); std::map map_; ILMethodDef *method_; }; class NETLoader : public ILFunction { public: explicit NETLoader(IFunctionList *owner, OperandSize cpu_address_size); virtual bool Prepare(const CompileContext &ctx); virtual bool Compile(const CompileContext &ctx); virtual size_t WriteToFile(IArchitecture &file); ILCommand *file_crc_entry() const { return file_crc_entry_; } uint32_t file_crc_size() const { return file_crc_size_; } ILCommand *file_crc_size_entry() const { return file_crc_size_entry_; } ILCommand *loader_crc_entry() const { return loader_crc_entry_; } uint32_t loader_crc_size() const { return loader_crc_size_; } ILCommand *loader_crc_size_entry() const { return loader_crc_size_entry_; } ILCommand *loader_crc_hash_entry() const { return loader_crc_hash_entry_; } ILCommand *import_entry() const { return import_entry_; } uint32_t import_size() const { return import_size_; } ILCommand *iat_entry() const { return iat_entry_; } uint32_t iat_size() const { return iat_size_; } ILCommand *pe_entry() const { return pe_entry_; } ILCommand *strong_name_signature_entry() const { return strong_name_signature_entry_; } ILCommand *vtable_fixups_entry() const { return vtable_fixups_entry_; } ILCommand *tls_entry() const { return tls_entry_; } uint32_t tls_size() const { return tls_size_; } private: void AddAVBuffer(const CompileContext &ctx); struct ImportInfo { ILCommand *original_first_thunk; ILCommand *name; ILCommand *first_thunk; //IntelCommand *loader_name; }; struct ImportFunctionInfo { PEImportFunction *import_function; ILCommand *name; ILCommand *thunk; ILCommand *loader_name; ImportFunctionInfo(PEImportFunction *import_function_) : import_function(import_function_), name(NULL), thunk(NULL), loader_name(NULL) {} bool operator == (PEImportFunction *import_function_) const { return (import_function == import_function_); } }; struct LoaderInfo { ILCommand *data; size_t size; LoaderInfo(ILCommand *data_, size_t size_) : data(data_), size(size_) {} }; struct PackerInfo { PESegment *section; uint64_t address; size_t size; ILCommand *data; bool operator == (PESegment *section_) const { return (section == section_); } }; ILCommand *import_entry_; uint32_t import_size_; ILCommand *iat_entry_; uint32_t iat_size_; ILCommand *file_crc_entry_; ILCommand *file_crc_size_entry_; uint32_t file_crc_size_; ILCommand *loader_crc_entry_; ILCommand *loader_crc_size_entry_; ILCommand *loader_crc_hash_entry_; uint32_t loader_crc_size_; ILCommand *pe_entry_; ILCommand *strong_name_signature_entry_; ILCommand *vtable_fixups_entry_; ILCommand *tls_entry_; ILCommand *tls_call_back_entry_; uint32_t tls_size_; }; class ILSDK : public ILFunction { public: explicit ILSDK(IFunctionList *owner, OperandSize cpu_address_size); bool Init(const CompileContext &ctx); }; class ILCRCTable : public ILFunction { public: explicit ILCRCTable(IFunctionList *owner, OperandSize cpu_address_size); bool Init(const CompileContext &ctx); size_t table_size() const { return (count() - 2) * OperandSizeToValue(osDWord); } ILCommand *table_entry() const { return item(0); } ILCommand *size_entry() const { return size_entry_; } ILCommand *hash_entry() const { return hash_entry_; } private: ILCommand *size_entry_; ILCommand *hash_entry_; }; class ILRuntimeData : public ILFunction { public: explicit ILRuntimeData(IFunctionList *owner, OperandSize cpu_address_size); bool Init(const CompileContext &ctx); virtual size_t WriteToFile(IArchitecture &file); private: struct CommandCompareHelper { bool operator () (const ILCommand *left, ILCommand *right) const; }; RC5Key rc5_key_; ILCommand *resources_entry_; uint32_t resources_size_; ILCommand *strings_entry_; uint32_t strings_size_; ILCommand *trial_hwid_entry_; uint32_t trial_hwid_size_; #ifdef ULTIMATE ILCommand *license_data_entry_; uint32_t license_data_size_; #endif }; class ILRuntimeCRCTable : public ILFunction { public: explicit ILRuntimeCRCTable(IFunctionList *owner, OperandSize cpu_address_size); virtual void clear(); virtual bool Compile(const CompileContext &ctx); virtual size_t WriteToFile(IArchitecture &file); size_t region_count() const { return region_info_list_.size(); } private: struct RegionInfo { uint64_t address; uint32_t size; bool is_self_crc; RegionInfo(uint64_t address_, uint32_t size_, bool is_self_crc_) : address(address_), size(size_), is_self_crc(is_self_crc_) { } }; std::vector region_info_list_; ValueCryptor *cryptor_; }; class ILToken; struct ImportDelegateInfo { ILToken *method; ILToken *invoke; uint32_t call_type; ImportDelegateInfo(ILToken *method_, ILToken *invoke_, uint32_t call_type_) : method(method_), invoke(invoke_), call_type(call_type_) { } }; class ILImport : public ILFunction { public: explicit ILImport(IFunctionList *owner, OperandSize cpu_address_size); bool Init(const CompileContext &ctx); std::vector info_list() const { return info_list_; } private: std::vector info_list_; }; class ILVirtualMachineProcessor; class ILFunctionList : public BaseFunctionList { public: explicit ILFunctionList(IArchitecture *owner); explicit ILFunctionList(IArchitecture *owner, const ILFunctionList &src); ~ILFunctionList(); ILFunction *item(size_t index) const; ILFunction *GetFunctionByAddress(uint64_t address) const; virtual bool Prepare(const CompileContext &ctx); virtual bool Compile(const CompileContext &ctx); virtual void CompileLinks(const CompileContext &ctx); virtual void CompileInfo(const CompileContext &ctx); virtual void ReadFromBuffer(Buffer &buffer, IArchitecture &file); virtual ILFunction *Add(const std::string &name, CompilationType compilation_type, uint32_t compilation_options, bool need_compile, Folder *folder); virtual ILFunctionList *Clone(IArchitecture *owner) const; virtual ILCRCTable *crc_table() const { return crc_table_; } virtual ValueCryptor *crc_cryptor() const { return crc_cryptor_; } ILImport *import() const { return import_; } ILRuntimeCRCTable *runtime_crc_table() const { return runtime_crc_table_; } virtual IFunction *CreateFunction(OperandSize cpu_address_size = osDefault); virtual bool GetRuntimeOptions() const { return true; } ILVirtualMachineProcessor *AddProcessor(OperandSize cpu_address_size); protected: ILSDK *AddSDK(OperandSize cpu_address_size); ILRuntimeData *AddRuntimeData(OperandSize cpu_address_size); ILCRCTable *AddCRCTable(OperandSize cpu_address_size); ILFunction *AddWatermark(OperandSize cpu_address_size, Watermark *watermark, int copy_count); ILRuntimeCRCTable *AddRuntimeCRCTable(OperandSize cpu_address_size); ILImport *AddImport(OperandSize cpu_address_size); ValueCryptor *crc_cryptor_; ILCRCTable *crc_table_; ILRuntimeCRCTable *runtime_crc_table_; ILImport *import_; // no copy ctr or assignment op ILFunctionList(const ILFunctionList &); ILFunctionList &operator =(const ILFunctionList &); }; class ILVirtualMachineProcessor : public ILFunction { public: ILVirtualMachineProcessor(ILFunctionList *owner, OperandSize cpu_address_size); void InitCommands(const CompileContext &ctx); virtual void AfterCompile(const CompileContext &ctx); virtual void CompileLinks(const CompileContext &ctx); virtual void CompileInfo(const CompileContext &ctx); virtual size_t WriteToFile(IArchitecture &file); }; class ILVirtualMachineList : public IVirtualMachineList { public: virtual IVirtualMachineList * Clone() const; virtual void Prepare(const CompileContext &ctx); virtual IFunction *processor() const { return NULL; } }; class ILOpcodeList; class ILToken; class ILOpcodeInfo : public IObject { public: ILOpcodeInfo(ILOpcodeList *owner, ILCommandType command_type, ILToken *entry); ~ILOpcodeInfo(); ILCommandType command_type() const { return command_type_; } ILToken *entry() const { return entry_; } uint8_t opcode() const { return opcode_; } void set_opcode(uint8_t opcode) { opcode_ = opcode; } uint64_t Key() const { return command_type_; } class circular_queue : public std::vector { size_t position_; public: circular_queue() : std::vector(), position_(0) {} ILOpcodeInfo *Next(); }; private: ILOpcodeList *owner_; ILCommandType command_type_; ILToken *entry_; uint8_t opcode_; }; class ILOpcodeList : public ObjectList { public: ILOpcodeList(); ILOpcodeInfo *Add(ILCommandType command_type, ILToken *entry); ILOpcodeInfo *GetOpcodeInfo(ILCommandType command_type) const; }; class ILMethodDef; class ILVirtualMachine : public BaseVirtualMachine { public: ILVirtualMachine(ILVirtualMachineList *owner, uint8_t id, ILVirtualMachineProcessor *processor); void Init(const CompileContext &ctx); virtual ByteList *registr_order() { return NULL; } virtual bool backward_direction() const { return false; } virtual ILFunction *processor() const { return processor_; } ILMethodDef *ctor() const { return ctor_; } ILMethodDef *invoke() const { return invoke_; } void CompileCommand(ILVMCommand &vm_command); private: ILOpcodeInfo *GetOpcode(ILCommandType command_type); ILVirtualMachineProcessor *processor_; ILMethodDef *ctor_; ILMethodDef *invoke_; ILOpcodeList opcode_list_; std::unordered_map opcode_stack_; }; #endif