Ejemplo n.º 1
0
        /// <summary>
        /// Loads the address of the given field onto the stack.
        ///
        /// If the field is an instance field, a `this` reference is expected on the stack and will be popped.
        /// </summary>
        public Emit <DelegateType> LoadFieldAddress(FieldInfo field)
        {
            if (field == null)
            {
                throw new ArgumentNullException("field");
            }

            if (!AllowsUnverifiableCIL && field.IsInitOnly)
            {
                throw new InvalidOperationException("LoadFieldAddress on InitOnly fields is not verifiable");
            }

            if (!field.IsStatic)
            {
                var transitions =
                    new[] {
                    new StackTransition(new [] { field.DeclaringType }, new [] { field.FieldType.MakeByRefType() })
                };

                UpdateState(OpCodes.Ldflda, field, Wrap(transitions, "LoadFieldAddress"));
            }
            else
            {
                UpdateState(OpCodes.Ldsflda, field, Wrap(StackTransition.Push(field.FieldType.MakeByRefType()), "LoadFieldAddress"));
            }

            return(this);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Begins a catch block for the given exception type in the given exception block.
        ///
        /// The given exception block must still be open.
        /// </summary>
        public CatchBlock BeginCatchBlock(ExceptionBlock forTry, Type exceptionType)
        {
            if (exceptionType == null)
            {
                throw new ArgumentNullException("exceptionType");
            }

            if (forTry == null)
            {
                throw new ArgumentNullException("forTry");
            }

            if (((IOwned)forTry).Owner != this)
            {
                FailOwnership(forTry);
            }

            if (CurrentExceptionBlock.Count > 0 && forTry != CurrentExceptionBlock.Peek())
            {
                throw new InvalidOperationException("Cannot start CatchBlock on " + forTry + " while inner ExceptionBlock is still open");
            }

            if (!typeof(Exception).IsAssignableFrom(exceptionType))
            {
                throw new ArgumentException("BeginCatchBlock expects a type descending from Exception, found " + exceptionType, "exceptionType");
            }

            var currentlyOpen = CatchBlocks.Where(c => c.Key.ExceptionBlock == forTry && c.Value.Item2 == -1).Select(s => s.Key).SingleOrDefault();

            if (currentlyOpen != null)
            {
                throw new InvalidOperationException("Cannot start a new catch block, " + currentlyOpen + " has not been ended");
            }

            if (MustMark)
            {
                MarkLabel(DefineLabel(AutoNamer.Next(this, "__autolabel")));
            }

            UpdateState(Wrap(new[] { new StackTransition(0) }, "BeginCatchBlock"));

            var tryBlock = TryBlocks[forTry];

            if (tryBlock.Item2 != -1)
            {
                throw new SigilVerificationException("BeginCatchBlock expects an unclosed exception block, but " + forTry + " is already closed", IL.Instructions(AllLocals));
            }

            IL.BeginCatchBlock(exceptionType);

            UpdateState(Wrap(StackTransition.Push(exceptionType), "BeginCatchBlock"));

            var ret = new CatchBlock(exceptionType, forTry);

            CatchBlocks[ret] = SigilTuple.Create(IL.Index, -1);

            return(ret);
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Push a constant RuntimeMethodHandle onto the stack.
        /// </summary>
        public Emit <DelegateType> LoadConstant(MethodInfo method)
        {
            if (method == null)
            {
                throw new ArgumentNullException("method");
            }

            UpdateState(OpCodes.Ldtoken, method, Type.EmptyTypes, Wrap(StackTransition.Push <RuntimeMethodHandle>(), "LoadConstant"));

            return(this);
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Push a constant RuntimeTypeHandle onto the stack.
        /// </summary>
        public Emit <DelegateType> LoadConstant(Type type)
        {
            if (type == null)
            {
                throw new ArgumentNullException("type");
            }

            UpdateState(OpCodes.Ldtoken, type, Wrap(StackTransition.Push <RuntimeTypeHandle>(), "LoadConstant"));

            return(this);
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Push a constant RuntimeMethodHandle onto the stack.
        /// </summary>
        public Emit <DelegateType> LoadConstant(ConstructorInfo constructor)
        {
            if (constructor == null)
            {
                throw new ArgumentNullException("constructor");
            }

            UpdateState(OpCodes.Ldtoken, constructor, TypeHelpers.EmptyTypes, Wrap(StackTransition.Push <RuntimeMethodHandle>(), "LoadConstant"));

            return(this);
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Push a constant RuntimeFieldHandle onto the stack.
        /// </summary>
        public Emit <DelegateType> LoadConstant(FieldInfo field)
        {
            if (field == null)
            {
                throw new ArgumentNullException("field");
            }

            UpdateState(OpCodes.Ldtoken, field, Wrap(StackTransition.Push <RuntimeFieldHandle>(), "LoadConstant"));

            return(this);
        }
Ejemplo n.º 7
0
        /// <summary>
        /// Pushes a pointer to the current argument list onto the stack.
        ///
        /// This instruction can only be used in VarArgs methods.
        /// </summary>
        public Emit <DelegateType> ArgumentList()
        {
            if (!AllowsUnverifiableCIL)
            {
                FailUnverifiable("ArgumentList");
            }

            if (CallingConventions != System.Reflection.CallingConventions.VarArgs)
            {
                throw new InvalidOperationException("ArgumentList can only be called in VarArgs methods");
            }

            UpdateState(OpCodes.Arglist, Wrap(StackTransition.Push <NativeIntType>(), "ArgumentList"));

            return(this);
        }
Ejemplo n.º 8
0
        /// <summary>
        /// Pushes the size of the given value type onto the stack.
        /// </summary>
        public Emit <DelegateType> SizeOf(Type valueType)
        {
            if (valueType == null)
            {
                throw new ArgumentNullException("valueType");
            }

            if (!valueType.IsValueType)
            {
                throw new ArgumentException("valueType must be a ValueType");
            }

            UpdateState(OpCodes.Sizeof, valueType, Wrap(StackTransition.Push <int>(), "SizeOf"));

            return(this);
        }
Ejemplo n.º 9
0
        /// <summary>
        /// Pushes a pointer to the given local onto the stack.
        ///
        /// To create a local, use DeclareLocal.
        /// </summary>
        public Emit <DelegateType> LoadLocalAddress(Local local)
        {
            if (local == null)
            {
                throw new ArgumentNullException("local");
            }

            if (((IOwned)local).Owner != this)
            {
                if (((IOwned)local).Owner is DisassembledOperations <DelegateType> )
                {
                    return(LoadLocalAddress(local.Name));
                }

                FailOwnership(local);
            }

            UnusedLocals.Remove(local);

            var type = local.StackType.Type;

            var ptrType = type.MakePointerType();

            if (local.Index >= byte.MinValue && local.Index <= byte.MaxValue)
            {
                byte asByte;
                unchecked
                {
                    asByte = (byte)local.Index;
                }

                UpdateState(OpCodes.Ldloca_S, asByte, Wrap(StackTransition.Push(ptrType), "LoadLocalAddress"));
                return(this);
            }

            short asShort;

            unchecked
            {
                asShort = (short)local.Index;
            }

            UpdateState(OpCodes.Ldloca, asShort, Wrap(StackTransition.Push(ptrType), "LoadLocalAddress"));

            return(this);
        }
Ejemplo n.º 10
0
        /// <summary>
        /// Loads the argument at the given index (starting at 0) for the current method onto the stack.
        /// </summary>
        public Emit <DelegateType> LoadArgument(ushort index)
        {
            if (ParameterTypes.Length == 0)
            {
                throw new ArgumentException("Delegate of type " + typeof(DelegateType) + " takes no parameters");
            }

            if (index >= ParameterTypes.Length)
            {
                throw new ArgumentException("index must be between 0 and " + (ParameterTypes.Length - 1) + ", inclusive");
            }

            var transitions = Wrap(StackTransition.Push(ParameterTypes[index]), "LoadArgument");

            switch (index)
            {
            case 0: UpdateState(OpCodes.Ldarg_0, transitions); return(this);

            case 1: UpdateState(OpCodes.Ldarg_1, transitions); return(this);

            case 2: UpdateState(OpCodes.Ldarg_2, transitions); return(this);

            case 3: UpdateState(OpCodes.Ldarg_3, transitions); return(this);
            }

            if (index >= byte.MinValue && index <= byte.MaxValue)
            {
                UpdateState(OpCodes.Ldarg_S, (byte)index, transitions);
                return(this);
            }

            short asShort;

            unchecked
            {
                asShort = (short)index;
            }

            UpdateState(OpCodes.Ldarg, asShort, transitions);

            return(this);
        }
Ejemplo n.º 11
0
        /// <summary>
        /// Push a constant int32 onto the stack.
        /// </summary>
        public Emit <DelegateType> LoadConstant(uint i)
        {
            switch (i)
            {
            case uint.MaxValue: UpdateState(OpCodes.Ldc_I4_M1, Wrap(StackTransition.Push <int>(), "LoadConstant")); return(this);

            case 0: UpdateState(OpCodes.Ldc_I4_0, Wrap(StackTransition.Push <int>(), "LoadConstant")); return(this);

            case 1: UpdateState(OpCodes.Ldc_I4_1, Wrap(StackTransition.Push <int>(), "LoadConstant")); return(this);

            case 2: UpdateState(OpCodes.Ldc_I4_2, Wrap(StackTransition.Push <int>(), "LoadConstant")); return(this);

            case 3: UpdateState(OpCodes.Ldc_I4_3, Wrap(StackTransition.Push <int>(), "LoadConstant")); return(this);

            case 4: UpdateState(OpCodes.Ldc_I4_4, Wrap(StackTransition.Push <int>(), "LoadConstant")); return(this);

            case 5: UpdateState(OpCodes.Ldc_I4_5, Wrap(StackTransition.Push <int>(), "LoadConstant")); return(this);

            case 6: UpdateState(OpCodes.Ldc_I4_6, Wrap(StackTransition.Push <int>(), "LoadConstant")); return(this);

            case 7: UpdateState(OpCodes.Ldc_I4_7, Wrap(StackTransition.Push <int>(), "LoadConstant")); return(this);

            case 8: UpdateState(OpCodes.Ldc_I4_8, Wrap(StackTransition.Push <int>(), "LoadConstant")); return(this);
            }

            if (i <= sbyte.MaxValue)
            {
                byte asByte;
                unchecked
                {
                    asByte = (byte)i;
                }

                UpdateState(OpCodes.Ldc_I4_S, asByte, Wrap(StackTransition.Push <int>(), "LoadConstant"));
                return(this);
            }

            UpdateState(OpCodes.Ldc_I4, i, Wrap(StackTransition.Push <int>(), "LoadConstant"));

            return(this);
        }
Ejemplo n.º 12
0
        /// <summary>
        /// Loads the value in the given local onto the stack.
        ///
        /// To create a local, use DeclareLocal().
        /// </summary>
        public Emit <DelegateType> LoadLocal(Local local)
        {
            if (local == null)
            {
                throw new ArgumentNullException("local");
            }

            if (((IOwned)local).Owner != this)
            {
                if (((IOwned)local).Owner is DisassembledOperations <DelegateType> )
                {
                    return(LoadLocal(local.Name));
                }

                FailOwnership(local);
            }

            UnusedLocals.Remove(local);

            switch (local.Index)
            {
            case 0: UpdateState(OpCodes.Ldloc_0, Wrap(StackTransition.Push(local.StackType), "LoadLocal")); return(this);

            case 1: UpdateState(OpCodes.Ldloc_1, Wrap(StackTransition.Push(local.StackType), "LoadLocal")); return(this);

            case 2: UpdateState(OpCodes.Ldloc_2, Wrap(StackTransition.Push(local.StackType), "LoadLocal")); return(this);

            case 3: UpdateState(OpCodes.Ldloc_3, Wrap(StackTransition.Push(local.StackType), "LoadLocal")); return(this);
            }

            if (local.Index >= byte.MinValue && local.Index <= byte.MaxValue)
            {
                UpdateState(OpCodes.Ldloc_S, (byte)local.Index, Wrap(StackTransition.Push(local.StackType), "LoadLocal"));
                return(this);
            }

            UpdateState(OpCodes.Ldloc, local, Wrap(StackTransition.Push(local.StackType), "LoadLocal"));

            return(this);
        }
Ejemplo n.º 13
0
        /// <summary>
        /// Loads a pointer to the argument at index (starting at zero) onto the stack.
        /// </summary>
        public Emit <DelegateType> LoadArgumentAddress(ushort index)
        {
            if (ParameterTypes.Length == 0)
            {
                throw new ArgumentException("Delegate of type " + typeof(DelegateType) + " takes no parameters");
            }

            if (index >= ParameterTypes.Length)
            {
                throw new ArgumentException("index must be between 0 and " + (ParameterTypes.Length - 1) + ", inclusive");
            }

            if (index >= byte.MinValue && index <= byte.MaxValue)
            {
                byte asByte;
                unchecked
                {
                    asByte = (byte)index;
                }

                UpdateState(OpCodes.Ldarga_S, asByte, Wrap(StackTransition.Push(ParameterTypes[index].MakePointerType()), "LoadArgumentAddress"));

                return(this);
            }

            short asShort;

            unchecked
            {
                asShort = (short)index;
            }

            UpdateState(OpCodes.Ldarga, asShort, Wrap(StackTransition.Push(ParameterTypes[index].MakePointerType()), "LoadArgumentAddress"));

            return(this);
        }
Ejemplo n.º 14
0
        /// <summary>
        /// Push a constant double onto the stack.
        /// </summary>
        public Emit <DelegateType> LoadConstant(double d)
        {
            UpdateState(OpCodes.Ldc_R8, d, Wrap(StackTransition.Push <double>(), "LoadConstant"));

            return(this);
        }
Ejemplo n.º 15
0
        /// <summary>
        /// <para>Loads a field onto the stack.</para>
        /// <para>Instance fields expect a reference on the stack, which is popped.</para>
        /// </summary>
        public Emit <DelegateType> LoadField(FieldInfo field, bool?isVolatile = null, int?unaligned = null)
        {
            if (field == null)
            {
                throw new ArgumentNullException("field");
            }

            if (unaligned.HasValue && (unaligned != 1 && unaligned != 2 && unaligned != 4))
            {
                throw new ArgumentException("unaligned must be null, 1, 2, or 4");
            }

            if (unaligned.HasValue && field.IsStatic)
            {
                throw new ArgumentException("unaligned cannot be used with static fields");
            }

            var useVolatile = isVolatile ?? ExtensionMethods.IsVolatile(field);

            if (!field.IsStatic)
            {
                if (useVolatile)
                {
                    UpdateState(OpCodes.Volatile, Wrap(StackTransition.None(), "LoadField"));
                }

                if (unaligned.HasValue)
                {
                    UpdateState(OpCodes.Unaligned, (byte)unaligned.Value, Wrap(StackTransition.None(), "LoadField"));
                }

                StackTransition[] transitions;
                if (TypeHelpers.IsValueType(field.DeclaringType))
                {
                    transitions =
                        new[]
                    {
                        // This transition isn't really to spec... but it seems to work consistently in .NET soooo.... yeah
                        new StackTransition(new [] { field.DeclaringType }, new [] { field.FieldType }),
                        new StackTransition(new [] { field.DeclaringType.MakePointerType() }, new [] { field.FieldType })
                    };
                }
                else
                {
                    transitions =
                        new[]
                    {
                        new StackTransition(new [] { field.DeclaringType }, new [] { field.FieldType })
                    };
                }

                UpdateState(OpCodes.Ldfld, field, Wrap(transitions, "LoadField"));
            }
            else
            {
                if (useVolatile)
                {
                    UpdateState(OpCodes.Volatile, Wrap(StackTransition.None(), "LoadField"));
                }

                UpdateState(OpCodes.Ldsfld, field, Wrap(StackTransition.Push(field.FieldType), "LoadField"));
            }

            return(this);
        }
Ejemplo n.º 16
0
        /// <summary>
        /// Push a constant int64 onto the stack.
        /// </summary>
        public Emit <DelegateType> LoadConstant(ulong l)
        {
            UpdateState(OpCodes.Ldc_I8, l, Wrap(StackTransition.Push <long>(), "LoadConstant"));

            return(this);
        }
Ejemplo n.º 17
0
        /// <summary>
        /// Loads a null reference onto the stack.
        /// </summary>
        public Emit <DelegateType> LoadNull()
        {
            UpdateState(OpCodes.Ldnull, Wrap(StackTransition.Push <NullType>(), "LoadNull"));

            return(this);
        }
Ejemplo n.º 18
0
        /// <summary>
        /// Push a constant float onto the stack.
        /// </summary>
        public Emit <DelegateType> LoadConstant(float f)
        {
            UpdateState(OpCodes.Ldc_R4, f, Wrap(StackTransition.Push <float>(), "LoadConstant"));

            return(this);
        }
Ejemplo n.º 19
0
        /// <summary>
        /// Push a constant string onto the stack.
        /// </summary>
        public Emit <DelegateType> LoadConstant(string str)
        {
            UpdateState(OpCodes.Ldstr, str, Wrap(StackTransition.Push <string>(), "LoadConstant"));

            return(this);
        }