/// <summary> /// Emits a macro /// </summary> /// <param name="writer">The MSIL writer to write to.</param> /// <param name="value">The constant <see cref="Int32"/> value to load onto the evaluation stack.</param> /// <exception cref="ArgumentNullException"> /// <para><paramref name="writer"/> is <see langword="null"/>.</para> /// </exception> public static void EmitLdcI4(this ICilWriter writer, int value) { if (writer == null) { throw new ArgumentNullException("writer"); } OpCode opCode; switch (value) { case -1: opCode = OpCodes.Ldc_I4_M1; break; case 0: opCode = OpCodes.Ldc_I4_0; break; case 1: opCode = OpCodes.Ldc_I4_1; break; case 2: opCode = OpCodes.Ldc_I4_2; break; case 3: opCode = OpCodes.Ldc_I4_3; break; case 4: opCode = OpCodes.Ldc_I4_4; break; case 5: opCode = OpCodes.Ldc_I4_5; break; case 6: opCode = OpCodes.Ldc_I4_6; break; case 7: opCode = OpCodes.Ldc_I4_7; break; case 8: opCode = OpCodes.Ldc_I4_8; break; default: opCode = value <= byte.MaxValue ? OpCodes.Ldc_I4_S : OpCodes.Ldc_I4; break; } switch (opCode.OperandType) { case OperandType.InlineNone: writer.Emit(opCode); break; case OperandType.ShortInlineI: writer.Emit(opCode, (byte)value); break; case OperandType.InlineI: writer.Emit(opCode, value); break; default: throw new InvalidOperationException("Unexpected OperandType. This is an indication of a bug."); } }
/// <summary> /// Emits <see langword="OpCodes.Ldloca"/> or the best alternative macro depending on the operand. /// </summary> /// <param name="writer">The writer to write to.</param> /// <param name="localIndex">The index of the local variable operand.</param> public static void EmitLdloca(this ICilWriter writer, int localIndex) { if (writer == null) { throw new ArgumentNullException("writer"); } if (localIndex < 0) { throw new ArgumentOutOfRangeException("localIndex", "localIndex may not be negative"); } if (localIndex <= byte.MaxValue) { writer.Emit(OpCodes.Ldloca_S, (byte)localIndex); return; } writer.Emit(OpCodes.Ldloca, localIndex); }
/// <summary> /// Emits <see langword="OpCodes.Starg"/> or the best alternative macro depending on the operand. /// </summary> /// <param name="writer">The writer to write to.</param> /// <param name="argumentIndex">The index of the parameter operand.</param> public static void EmitStarg(this ICilWriter writer, int argumentIndex) { if (writer == null) { throw new ArgumentNullException("writer"); } if (argumentIndex < 0) { throw new ArgumentOutOfRangeException("argumentIndex", "argumentIndex may not be negative"); } if (argumentIndex <= byte.MaxValue) { writer.Emit(OpCodes.Starg_S, (byte)argumentIndex); return; } writer.Emit(OpCodes.Starg, argumentIndex); }
internal static void EmitStelem(this ICilWriter writer, Type elementType) { OpCode opCode; if (elementType.IsPrimitive && _primitiveStelemOpCodes.TryGetValue(elementType, out opCode)) { writer.Emit(opCode); return; } if (elementType.IsValueType || elementType.IsGenericParameter) { writer.Emit(OpCodes.Stelem, elementType); } else { writer.Emit(OpCodes.Stelem_Ref); } }
internal static void EmitStobj(this ICilWriter writer, Type type) { OpCode opCode; if (type.IsPrimitive && _primitiveStobjOpCodes.TryGetValue(type, out opCode)) { writer.Emit(opCode); return; } if (type.IsValueType || type.IsGenericParameter) { writer.Emit(OpCodes.Stobj, type); } else { writer.Emit(OpCodes.Stind_Ref); } }
/// <summary> /// Emits <see cref="OpCodes.Callvirt"/> or <see cref="OpCodes.Call"/> depending on /// which is appropriate for <paramref name="method"/>. /// </summary> /// <param name="writer">The MSIL writer to write to.</param> /// <param name="method">The method to call in the output MSIL.</param> /// <exception cref="ArgumentNullException"> /// <para><paramref name="writer"/> is <see langword="null"/>.</para> /// <para>- or -</para> /// <para><paramref name="method"/> is <see langword="null"/>.</para> /// </exception> public static void EmitCall(this ICilWriter writer, MethodInfo method) { if (writer == null) { throw new ArgumentNullException("writer"); } if (method == null) { throw new ArgumentNullException("method"); } OpCode opCode = !method.IsStatic && method.IsVirtual ? OpCodes.Callvirt : OpCodes.Call; writer.Emit(opCode, method); }
/// <summary> /// Emits <see langword="OpCodes.Stloc"/> or the best alternative macro depending on the operand. /// </summary> /// <param name="writer">The writer to write to.</param> /// <param name="localIndex">The index of the local variable operand.</param> public static void EmitStloc(this ICilWriter writer, int localIndex) { if (writer == null) { throw new ArgumentNullException("writer"); } if (localIndex < 0) { throw new ArgumentOutOfRangeException("localIndex", "localIndex may not be negative"); } switch (localIndex) { case 0: writer.Emit(OpCodes.Stloc_0); return; case 1: writer.Emit(OpCodes.Stloc_1); return; case 2: writer.Emit(OpCodes.Stloc_2); return; case 3: writer.Emit(OpCodes.Stloc_3); return; default: if (localIndex <= byte.MaxValue) { writer.Emit(OpCodes.Stloc_S, (byte)localIndex); return; } writer.Emit(OpCodes.Stloc, localIndex); return; } }
/// <summary> /// Emits <see langword="OpCodes.Ldarg"/> or the best alternative macro depending on the operand. /// </summary> /// <param name="writer">The writer to write to.</param> /// <param name="argumentIndex">The index of the parameter operand.</param> public static void EmitLdarg(this ICilWriter writer, int argumentIndex) { if (writer == null) { throw new ArgumentNullException("writer"); } if (argumentIndex < 0) { throw new ArgumentOutOfRangeException("argumentIndex", "argumentIndex may not be negative"); } switch (argumentIndex) { case 0: writer.Emit(OpCodes.Ldarg_0); return; case 1: writer.Emit(OpCodes.Ldarg_1); return; case 2: writer.Emit(OpCodes.Ldarg_2); return; case 3: writer.Emit(OpCodes.Ldarg_3); return; default: if (argumentIndex <= byte.MaxValue) { writer.Emit(OpCodes.Ldarg_S, (byte)argumentIndex); return; } writer.Emit(OpCodes.Ldarg, argumentIndex); return; } }