170 lines
No EOL
5 KiB
C#
170 lines
No EOL
5 KiB
C#
#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
|
|
|
|
/// <summary>
|
|
/// Provides optimized generation code and helpers.
|
|
/// </summary>
|
|
internal static class ILGeneratorExtensions
|
|
{
|
|
/// <summary>
|
|
/// Loads the local variable at a specific index onto the evaluation stack.
|
|
/// </summary>
|
|
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;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Pops the current value from the top of the evaluation stack and stores it in a the local variable list at a specified index.
|
|
/// </summary>
|
|
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;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Loads the address of the local variable at a specific index onto the evaluation statck.
|
|
/// </summary>
|
|
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);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Pushes a supplied value of type int32 onto the evaluation stack as an int32.
|
|
/// </summary>
|
|
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;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Helper for Pop op.
|
|
/// </summary>
|
|
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 |