コード例 #1
0
 /// <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.");
     }
 }
コード例 #2
0
        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));
        }
コード例 #3
0
        /// <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,请修复.");
            }
        }
コード例 #4
0
        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;
        }
コード例 #5
0
        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);
        }
コード例 #6
0
        /// <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);
        }
コード例 #7
0
        /// <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);
        }
コード例 #8
0
        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);
            }
        }
コード例 #9
0
        /// <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);
            }
        }
コード例 #10
0
        /// <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;
            }
        }
コード例 #11
0
        /// <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;
            }
        }
コード例 #12
0
        /// <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); //创建代码范围
        }
コード例 #13
0
 public SimpleParameter(ICILWriter writer, int index, Type type, string name)
     : base(writer, index, GetElementType(type), GetName(name, index), false)
 {
     _originalType = type;
 }
コード例 #14
0
 /// <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);
 }
コード例 #15
0
 /// <summary>
 /// 写入一个比较指令,该指令会将一个int32值推送到计算堆栈上
 /// </summary>
 /// <param name="writer">MSIL写入器</param>
 public void WriteCompare(ICILWriter writer)
 {
     _compareWriter(writer);
 }
コード例 #16
0
 /// <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);
 }
コード例 #17
0
 /// <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);
 }