/// <summary> /// <para>Initializes a new instance of the <see cref="SimpleLocal"/> class.</para> /// </summary> /// <param name="writer">The writer that the parameter belongs to.</param> /// <param name="index">The index of the parameter.</param> /// <param name="type">The type of the local variable.</param> /// <param name="name">The name of the local variable.</param> /// <param name="isPinned">A value indicating whether or not the local variable is pinned.</param> /// <exception cref="ArgumentNullException"> /// <para><paramref name="writer"/> is <see langword="null"/>.</para> /// <para>- or -</para> /// <para><paramref name="type"/> is <see langword="null"/>.</para> /// </exception> public SimpleLocal(ICILWriter writer, int index, Type type, string name, bool isPinned) : base(writer, index, type, name, isPinned) { if (type.IsByRef) { throw new NotSupportedException("ByRef types are not supported by this class."); } }
public static IVariable DefineLocal(this ICILWriter writer, Type type, bool isPinned, string name) { if (writer == null) { throw new ArgumentNullException("writer"); } return(writer.DefineLocal(type, isPinned, name)); }
/// <summary> /// <para>封装了加载 int 类型数据到计算堆栈的方法</para> /// <para>使用该方法,可以不考虑value范围而快捷方便的加载int类型数据到计算堆栈</para> /// </summary> /// <param name="writer">MSIL写入器</param> /// <param name="value">将类型为<see cref="Int32"/>的值加载到计算堆栈上.</param> /// <exception cref="ArgumentNullException"> /// <para><paramref name="writer"/> 是 <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 = OpCodes.Ldc_I4; //value <= byte.MaxValue 如果这样写会有BUG //? 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("意外的 OperandType. 这表示有一个BUG,请修复."); } }
protected SimpleVariable(ICILWriter writer, int index, Type type, string name, bool isPinned) { ArgumentAssert.IsNotNull(writer, "writer"); ArgumentAssert.IsNotNull(type, "type"); Writer = writer; Index = index; Type = type; Name = name; IsPinned = isPinned; }
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> /// <para>将位于特定索引处的局部变量的地址加载到计算堆栈上。注意:加载的是地址</para> /// <para>根据localIndex发送<see langword="OpCodes.Ldloca"/>或 <see langword="OpCodes.Ldloca_S"/>指令</para> /// <para><see langword="OpCodes.Ldloca_S"/>指令可以高效的加载索引0-255的局部变量的地址</para> /// </summary> /// <param name="writer"></param> /// <param name="localIndex">需要加载的局部变量的索引</param> public static void EmitLdloca(this ICILWriter writer, int localIndex) { if (writer == null) { throw new ArgumentNullException("writer"); } if (localIndex < 0) { throw new ArgumentOutOfRangeException("localIndex", "索引不是能负数"); } if (localIndex <= byte.MaxValue) { writer.Emit(OpCodes.Ldloca_S, (byte)localIndex); return; } writer.Emit(OpCodes.Ldloca, localIndex); }
/// <summary> /// Emits <see langword="OpCodes.Ldarga"/> 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 EmitLdarga(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.Ldarga_S, (byte)argumentIndex); return; } writer.Emit(OpCodes.Ldarga, argumentIndex); }
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> /// 用计算堆栈中的值替换给定索引处的数组元素,其类型在指令中指定。 /// </summary> /// <param name="writer"></param> /// <param name="elementType"></param> 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); } }
/// <summary> /// <para>将位于特定索引处的局部变量加载到计算堆栈上。注意:加载的是值</para> /// </summary> /// <param name="writer"></param> /// <param name="localIndex">需要加载的局部变量的索引</param> public static void EmitLdloc(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.Ldloc_0); return; case 1: writer.Emit(OpCodes.Ldloc_1); return; case 2: writer.Emit(OpCodes.Ldloc_2); return; case 3: writer.Emit(OpCodes.Ldloc_3); return; default: if (localIndex <= byte.MaxValue) { //高效加载0-255索引处的变量 writer.Emit(OpCodes.Ldloc_S, (byte)localIndex); return; } writer.Emit(OpCodes.Ldloc, localIndex); return; } }
/// <summary> /// 发送<see langword="OpCodes.Ldarg"/>指令,或者根据操作数,自动发射最佳的替代指令,例如OpCodes.Ldarg_3或pCodes.Ldarg_S /// </summary> 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; } }
/// <summary> /// 初始化一个 <see cref="MethodGenerator"/> 类的实例. /// </summary> /// <param name="writer">指令写入器</param> private MethodGenerator(ICILWriter writer) { if (writer == null) { throw new ArgumentNullException("writer"); } var header = writer.MethodHeader; //检查非静态方法是否传入了声明类型 if (header.DeclaringType == null && NotStaticMethod(header)) { throw new ArgumentException("必须为非静态方法定义一个声明类型(方法所在类的类型)"); } //检查参数是否有null for (int i = 0; i < header.ParameterTypes.Length; ++i) { if (header.ParameterTypes[i] == null) { throw new ArgumentException("writer.Header.Parameters 不能包含null值", "writer"); } } _writer = writer; _header = header; //收集参数 _parameters = LazyIndexer.Init <int, Parameter>(parameterIndex => { if (NotStaticMethod(_header)) { ++parameterIndex; //如果不是静态方法,那么将参数索引值+1,因为第0个参数是this(也就是对象本身) } return(new Parameter(this, _writer.GetParameter(parameterIndex))); }); _currentScope = new Scope(this); //创建代码范围 }
public SimpleParameter(ICILWriter writer, int index, Type type, string name) : base(writer, index, GetElementType(type), GetName(name, index), false) { _originalType = type; }
/// <summary> /// <para>写入条件转移指令</para> /// <para>结果为true时,将跳转到target</para> /// </summary> /// <param name="writer">写入器</param> /// <param name="target">需要跳转的语句标签</param> public void WriteBranch(ICILWriter writer, ILabel target) { _branchWriter(writer, target); }
/// <summary> /// 写入一个比较指令,该指令会将一个int32值推送到计算堆栈上 /// </summary> /// <param name="writer">MSIL写入器</param> public void WriteCompare(ICILWriter writer) { _compareWriter(writer); }
/// <summary> /// 对bool取反;注意:在计算堆栈中,bool是以int存放的true:1,false:0 /// </summary> /// <param name="w"></param> private static void NotBoolean(ICILWriter w) { w.Emit(OpCodes.Not); CastBooleanInt(w); }
/// <summary> /// <para>转成bool类型对应的int值</para> /// <para>false:0;true:1</para> /// <para>0取反得到的数值是-1;1取反得到的数值是-2;因此,我们需要将-1转成1,把-2转成0,才能得到正确的bool对应的整数值</para> /// </summary> private static void CastBooleanInt(ICILWriter w) { w.Emit(OpCodes.Ldc_I4_1); w.Emit(OpCodes.And); }