/// <summary>Loads the argument at index i onto the evaluation stack.</summary> public static ILSugar LoadArgument(this ILSugar il, int i) { switch (i) { case 0: il.Ldarg_0(); break; case 1: il.Ldarg_1(); break; case 2: il.Ldarg_2(); break; case 3: il.Ldarg_3(); break; default: if (i <= byte.MaxValue) { il.Ldarg_S((byte)i); } else { il.Ldarg(i); } break; } return(il); }
/// <summary>Loads the local variable at index i onto the evaluation stack.</summary> public static ILSugar LoadVariable(this ILSugar il, int i) { switch (i) { case 0: il.Ldloc_0(); break; case 1: il.Ldloc_1(); break; case 2: il.Ldloc_2(); break; case 3: il.Ldloc_3(); break; default: if (i <= byte.MaxValue) { il.Ldloc_S((byte)i); } else { il.Ldloc(i); } break; } return(il); }
/// <summary> Branches to the specified label if a string on the evaluation stacks equals the given literal value.</summary> public static ILSugar GotoIfStringEquals(this ILSugar il, string literal, Label @goto) { var ifStringEquals = il.Ldstr(literal).Call(KnownMethods.StringEquals); ifStringEquals .Brtrue(@goto); // TODO calculate offsets dynamically to call Brtrue_S vs. Brtrue, not worth it right now. return(il); }
/// <summary>If the given type is a value type, converts it into an object reference (type O)</summary> public static ILSugar MaybeBox(this ILSugar il, Type type) { if (type.IsValueType) { il.Box(type); } return(il); }
/// <summary>Pushes the value of i onto the evaluation stack as an int32.</summary> public static ILSugar LoadConstant(this ILSugar il, long i) { switch (i) { case 0: il.Ldc_I4_0(); break; case 1: il.Ldc_I4_1(); break; case 2: il.Ldc_I4_2(); break; case 3: il.Ldc_I4_3(); break; case 4: il.Ldc_I4_4(); break; case 5: il.Ldc_I4_5(); break; case 6: il.Ldc_I4_6(); break; case 7: il.Ldc_I4_7(); break; case 8: il.Ldc_I4_8(); break; default: if (i <= byte.MaxValue) { il.Ldc_I4_S((byte)i); } else if (i <= int.MaxValue) { il.Ldc_I4((int)i); } else { il.Ldc_I8(i); } break; } return(il); }
public static ILSugar CallOrCallvirt(this ILSugar il, Type type, MethodInfo method) { if (method.IsVirtual && !type.IsValueType) { il.Callvirt(method); } else { il.Call(method); } return(il); }
public static ILSugar CastOrUnboxAny(this ILSugar il, Type type) { if (type == typeof(object)) { return(il); } if (type.IsValueType) { il.Unbox_Any(type); } else { il.Castclass(type); } return(il); }
internal static void EmitCallMethod(this ILSugar il, MethodInfo method) { var type = method.DeclaringType ?? throw new NullReferenceException(); if (!method.IsStatic) { il.Ldarg_1(); // target il.Unbox_Any(type); var @this = il.DeclareLocal(type); il.Stloc(@this); if (type.IsValueType) { il.Ldloca(@this); } else { il.Ldloc(@this); } } var parameters = method.GetParameters(); if (parameters.Length > 0) { for (var i = 0; i < parameters.Length; i++) { il.Ldarg_2(); // args il.LoadConstant(i); // i il.Ldelem_Ref(); // args[i] var parameterType = parameters[i].ParameterType; var byRef = parameterType.IsByRef; if (byRef) { parameterType = parameterType.GetElementType(); } il.Unbox_Any(parameterType); var arg = il.DeclareLocal(parameterType); il.Stloc(arg); if (byRef) { il.Ldloca(arg); } else { il.Ldloc(arg); } } } il.CallOrCallvirt(type, method); for (var i = 0; i < parameters.Length; i++) { var parameterType = parameters[i].ParameterType; if (!parameterType.IsByRef) { continue; } il.Ldarg_2(); il.Ldc_I4(i); il.Ldloc(i + (method.IsStatic ? 0 : 1)); parameterType = parameterType.GetElementType() ?? parameterType; if (parameterType.IsValueType) { il.Box(parameterType); } il.Stelem_Ref(); } if (method.ReturnType == typeof(void)) { il.Ldnull(); } else { il.MaybeBox(method.ReturnType); } il.Ret(); }