#if NON_UNITY || !NET_STANDARD_2_0 using System; using System.Reflection; using System.Reflection.Emit; namespace MagicOnion.Utils { // full list of can create optimize helper -> https://github.com/kevin-montrose/Sigil#automated-opcode-choice /// /// Provides optimized generation code and helpers. /// internal static class ILGeneratorExtensions { /// /// Loads the local variable at a specific index onto the evaluation stack. /// public static void EmitLdloc(this ILGenerator il, int index) { switch (index) { case 0: il.Emit(OpCodes.Ldloc_0); break; case 1: il.Emit(OpCodes.Ldloc_1); break; case 2: il.Emit(OpCodes.Ldloc_2); break; case 3: il.Emit(OpCodes.Ldloc_3); break; default: if (index <= 255) { il.Emit(OpCodes.Ldloc_S, (byte)index); } else { il.Emit(OpCodes.Ldloc, (short)index); } break; } } /// /// Pops the current value from the top of the evaluation stack and stores it in a the local variable list at a specified index. /// public static void EmitStloc(this ILGenerator il, int index) { switch (index) { case 0: il.Emit(OpCodes.Stloc_0); break; case 1: il.Emit(OpCodes.Stloc_1); break; case 2: il.Emit(OpCodes.Stloc_2); break; case 3: il.Emit(OpCodes.Stloc_3); break; default: if (index <= 255) { il.Emit(OpCodes.Stloc_S, (byte)index); } else { il.Emit(OpCodes.Stloc, (short)index); } break; } } /// /// Loads the address of the local variable at a specific index onto the evaluation statck. /// public static void EmitLdloca(this ILGenerator il, int index) { if (index <= 255) { il.Emit(OpCodes.Ldloca_S, (byte)index); } else { il.Emit(OpCodes.Ldloca, (short)index); } } /// /// Pushes a supplied value of type int32 onto the evaluation stack as an int32. /// public static void EmitLdc_I4(this ILGenerator il, int value) { switch (value) { case -1: il.Emit(OpCodes.Ldc_I4_M1); break; case 0: il.Emit(OpCodes.Ldc_I4_0); break; case 1: il.Emit(OpCodes.Ldc_I4_1); break; case 2: il.Emit(OpCodes.Ldc_I4_2); break; case 3: il.Emit(OpCodes.Ldc_I4_3); break; case 4: il.Emit(OpCodes.Ldc_I4_4); break; case 5: il.Emit(OpCodes.Ldc_I4_5); break; case 6: il.Emit(OpCodes.Ldc_I4_6); break; case 7: il.Emit(OpCodes.Ldc_I4_7); break; case 8: il.Emit(OpCodes.Ldc_I4_8); break; default: if (value >= -128 && value <= 127) { il.Emit(OpCodes.Ldc_I4_S, (sbyte)value); } else { il.Emit(OpCodes.Ldc_I4, value); } break; } } /// /// Helper for Pop op. /// public static void EmitPop(this ILGenerator il, int count) { for (int i = 0; i < count; i++) { il.Emit(OpCodes.Pop); } } public static void EmitNullReturn(this ILGenerator il) { il.Emit(OpCodes.Ldnull); il.Emit(OpCodes.Ret); } public static void EmitThrowNotimplemented(this ILGenerator il) { il.Emit(OpCodes.Newobj, typeof(System.NotImplementedException).GetConstructor(Type.EmptyTypes)); il.Emit(OpCodes.Throw); } } } #endif