Beispiel #1
0
        /// <summary>
        /// Pops an array reference (containing elements of the given type), and index and a value of the given type, and stores the value in the array at that index
        /// </summary>
        /// <param name="generator">The <see cref="T:System.Reflection.Emit.XsILGenerator" /> to emit instructions from</param>
        /// <param name="type">The type of elements in the array</param>

        public static XsILGenerator StoreElement(this XsILGenerator generator, Type type)
        {
            if (!type.IsValueType)
            {
                return(generator.FluentEmit(OpCodes.Stelem_Ref));
            }
            else if (type == typeof(sbyte) || type == typeof(byte) || type == typeof(bool))
            {
                return(generator.FluentEmit(OpCodes.Stelem_I1));
            }
            else if (type == typeof(short) || type == typeof(ushort))
            {
                return(generator.FluentEmit(OpCodes.Stelem_I2));
            }
            else if (type == typeof(int) || type == typeof(uint))
            {
                return(generator.FluentEmit(OpCodes.Stelem_I4));
            }
            else if (type == typeof(long) || type == typeof(ulong))
            {
                return(generator.FluentEmit(OpCodes.Ldelem_I8));
            }
            else if (type == typeof(float))
            {
                return(generator.FluentEmit(OpCodes.Stelem_R4));
            }
            else if (type == typeof(double))
            {
                return(generator.FluentEmit(OpCodes.Stelem_R8));
            }
            else
            {
                return(generator.FluentEmit(OpCodes.Stelem, type));
            }
        }
        /// <summary>
        /// Pops the address of the storage location of a value type and initializes each field of the type at that location
        /// </summary>
        /// <param name="type">The type to initialize</param>
        /// <param name="generator">The <see cref="T:System.Reflection.Emit.XsILGenerator" /> to emit instructions from</param>

        public static XsILGenerator InitializeValueType(this XsILGenerator generator, Type type)
        {
            if (!type.IsValueType)
            {
                throw new InvalidOperationException("Cannot initialize a non-value type");
            }

            return(generator.FluentEmit(OpCodes.Initobj, type));
        }
        /// <summary>
        /// Pops a reference from the evaluation stack, and pushes a reference of the given type if the object is an instance of that type, otherwise an <see cref="InvalidCastException" /> is thrown
        /// </summary>
        /// <param name="generator">The <see cref="T:System.Reflection.Emit.XsILGenerator" /> to emit instructions from</param>
        /// <param name="type">The type to attempt to cast to</param>

        public static XsILGenerator CastClass(this XsILGenerator generator, Type type)
        {
            if (type.IsValueType)
            {
                throw new InvalidOperationException("Cannot cast to a value type");
            }

            return(generator.FluentEmit(OpCodes.Castclass, type));
        }
        /// <summary>
        /// Pops two addresses from the evaluation stack and copies the value type object (of the given type) in the first into the second
        /// </summary>
        /// <param name="generator">The <see cref="T:System.Reflection.Emit.XsILGenerator" /> to emit instructions from</param>
        /// <param name="type">The type of the value type object</param>

        public static XsILGenerator CopyObject(this XsILGenerator generator, Type type)
        {
            if (!type.IsValueType)
            {
                throw new InvalidOperationException("Copying a non-value-type results in unspecified runtime behaviour");
            }

            return(generator.FluentEmit(OpCodes.Cpobj, type));
        }
Beispiel #5
0
        /// <summary>
        /// Duplicates the value on the top of the evaluation stack <paramref name="n"/> times
        /// </summary>
        /// <param name="generator">The <see cref="T:System.Reflection.Emit.XsILGenerator" /> to emit instructions from</param>
        /// <param name="n">The number of times to duplicate the value</param>

        public static XsILGenerator Duplicate(this XsILGenerator generator, uint n)
        {
            for (int i = 0; i < n; i++)
            {
                generator.FluentEmit(OpCodes.Dup);
            }

            return(generator);
        }
        /// <summary>
        /// Pops a value type object from the evaluation stack, and pushes a reference to a new boxed instance of the object onto the evaluation stack
        /// </summary>
        /// <param name="generator">The <see cref="T:System.Reflection.Emit.XsILGenerator" /> to emit instructions from</param>
        /// <param name="type">The type of the value type object</param>

        public static XsILGenerator Box(this XsILGenerator generator, Type type)
        {
            if (!type.IsValueType)
            {
                throw new InvalidOperationException("Can only box value types");
            }

            return(generator.FluentEmit(OpCodes.Box, type));
        }
        /// <summary>
        /// Stores the given value in the given local
        /// </summary>
        /// <param name="generator">The <see cref="T:System.Reflection.Emit.XsILGenerator" /> to emit instructions from</param>
        /// <param name="local">The local to store value in</param>
        /// <param name="value">The value to store in the local</param>
        /// <exception cref="ArgumentException">Thrown if the local is not of type <see cref="SByte" /></exception>

        public static XsILGenerator OverwriteLocalWith(this XsILGenerator generator, LocalBuilder local, SByte value)
        {
            if (local.LocalType != typeof(SByte))
            {
                throw new ArgumentException("Cannot store a SByte value in a local of type " + local.LocalType.Name);
            }

            return(generator.LoadConstant(value)
                   .StoreInLocal(local));
        }
        /// <summary>
        /// Pops an address from the evaluation stack and pushes the value type object (of the given type) at that location onto the evaluation stack, with volatile semantics
        /// </summary>
        /// <param name="generator">The <see cref="T:System.Reflection.Emit.XsILGenerator" /> to emit instructions from</param>
        /// <param name="type">The type of the value type object</param>

        public static XsILGenerator LoadValueTypeOntoStackVolatile(this XsILGenerator generator, Type type)
        {
            if (!type.IsValueType)
            {
                throw new InvalidOperationException("This operation is not valid on reference types");
            }

            return(generator.FluentEmit(OpCodes.Volatile)
                   .LoadValueTypeOntoStack(type));
        }
        /// <summary>
        /// Pops a reference off the evaluation stack and calls the setter of the given property on the object with the given value
        /// </summary>
        /// <param name="generator"></param>
        /// <param name="property">The property to set</param>
        /// <param name="value">The value to set the property to</param>

        public static XsILGenerator SetProperty(this XsILGenerator generator, PropertyInfo property, UInt64 value)
        {
            if (property.PropertyType != typeof(UInt64))
            {
                throw new InvalidOperationException("Property is not of type UInt64");
            }

            return(generator.LoadConstant(value)
                   .SetProperty(property));
        }
        /// <summary>
        /// Pops an address and a value type object (of the given type) from the evaluation stack, and copies the object into the address, with volatile semantics
        /// </summary>
        /// <param name="generator">The <see cref="T:System.Reflection.Emit.XsILGenerator" /> to emit instructions from</param>
        /// <param name="type">The type of the value type object</param>

        public static XsILGenerator StoreValueTypeFromStackVolatile(this XsILGenerator generator, Type type)
        {
            if (!type.IsValueType)
            {
                throw new InvalidOperationException("This operation is not valid on a reference type");
            }

            return(generator.FluentEmit(OpCodes.Volatile)
                   .FluentEmit(OpCodes.Stobj, type));
        }
        internal static LocalBuilder GetLocal(this XsILGenerator generator, string localName)
        {
            LocalBuilder local;

            if (!GeneratorExtraData.GetOrCreateValue(generator).Locals.TryGetValue(localName, out local))
            {
                throw new InvalidOperationException("No local with the name `" + localName + "` declared");
            }

            return(local);
        }
Beispiel #12
0
        /// <summary>
        /// Pops a reference and a value off the evaluation stack and calls the setter of the given property on the object with the value
        /// </summary>
        /// <param name="generator"></param>
        /// <param name="property">The property to set</param>

        public static XsILGenerator SetProperty(this XsILGenerator generator, PropertyInfo property)
        {
            if (!property.CanWrite)
            {
                throw new InvalidOperationException("Cannot write to this property");
            }

            var setMethod = property.GetSetMethod();

            return(generator.Call(setMethod));
        }
Beispiel #13
0
        /// <summary>
        /// Pops a reference off the evaluation stack and calls the getter of the given property on the object
        /// </summary>
        /// <param name="generator"></param>
        /// <param name="property">The property to get the value of</param>

        public static XsILGenerator GetProperty(this XsILGenerator generator, PropertyInfo property)
        {
            if (!property.CanRead)
            {
                throw new InvalidOperationException("Cannot read from this property");
            }

            var getMethod = property.GetGetMethod();

            return(generator.Call(getMethod));
        }
Beispiel #14
0
        /// <summary>
        /// Pushes the given value onto the evaluation stack
        /// </summary>
        /// <param name="generator">The <see cref="T:System.Reflection.Emit.XsILGenerator" /> to emit instructions from</param>
        /// <param name="value">The value to push onto the evaluation stack</param>

        public static XsILGenerator LoadConstant(this XsILGenerator generator, ulong value)
        {
            if (value <= uint.MaxValue)
            {
                return(generator.LoadConstant((uint)value)
                       .ConvertToUInt64());
            }
            else
            {
                return(generator.FluentEmit(OpCodes.Ldc_I8, value));
            }
        }
Beispiel #15
0
        /// <summary>
        /// Pops an array reference (containing elements of the given type) and an index off the evaluation stack and pushes the element at that array index
        /// </summary>
        /// <param name="generator">The <see cref="T:System.Reflection.Emit.XsILGenerator" /> to emit instructions from</param>
        /// <param name="type">The type of elements in the array</param>

        public static XsILGenerator LoadElement(this XsILGenerator generator, Type type)
        {
            if (!type.IsValueType)
            {
                return(generator.FluentEmit(OpCodes.Ldelem_Ref));
            }
            else if (type == typeof(sbyte) || type == typeof(bool))
            {
                return(generator.FluentEmit(OpCodes.Ldelem_I1));
            }
            else if (type == typeof(byte))
            {
                return(generator.FluentEmit(OpCodes.Ldelem_U1));
            }
            else if (type == typeof(short))
            {
                return(generator.FluentEmit(OpCodes.Ldelem_I2));
            }
            else if (type == typeof(ushort))
            {
                return(generator.FluentEmit(OpCodes.Ldelem_U2));
            }
            else if (type == typeof(int))
            {
                return(generator.FluentEmit(OpCodes.Ldelem_I4));
            }
            else if (type == typeof(uint))
            {
                return(generator.FluentEmit(OpCodes.Ldelem_U4));
            }
            else if (type == typeof(long))
            {
                return(generator.FluentEmit(OpCodes.Ldelem_I8));
            }
            else if (type == typeof(ulong))
            {
                // Not a mistake! ldelem.U8 is an alias for ldelem.I8
                return(generator.FluentEmit(OpCodes.Ldelem_I8));
            }
            else if (type == typeof(float))
            {
                return(generator.FluentEmit(OpCodes.Ldelem_R4));
            }
            else if (type == typeof(double))
            {
                return(generator.FluentEmit(OpCodes.Ldelem_R8));
            }
            else
            {
                return(generator.FluentEmit(OpCodes.Ldelem, type));
            }
        }
Beispiel #16
0
        /// <summary>
        /// Throws an exception of the given type with the given message
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="generator">The <see cref="T:System.Reflection.Emit.XsILGenerator" /> to emit instructions from</param>
        /// <param name="message">The message to give the exception</param>
        /// <exception cref="InvalidOperationException">Exception type <typeparamref name="T"/> does not have a public constructor taking only a string</exception>

        public static XsILGenerator Throw <T>(this XsILGenerator generator, string message) where T : Exception
        {
            var constructor = typeof(T).GetConstructor(BindingFlags.Public | BindingFlags.Instance, null, StringTypeArray, null);

            if (constructor == null)
            {
                throw new InvalidOperationException("Exception type " + typeof(T).Name + " does not have a public constructor taking only a string");
            }

            return(generator.LoadString(message)
                   .NewObject(constructor)
                   .Throw());
        }
        private static XsILGenerator CreateLocal(this XsILGenerator generator, string localName, Type localType, bool pinned)
        {
            var data = GeneratorExtraData.GetOrCreateValue(generator);

            if (data.Locals.ContainsKey(localName))
            {
                throw new InvalidOperationException("Local with the name `" + localName + "` already declared");
            }

            var local = generator.DeclareLocal(localType, pinned);

            data.Locals.Add(localName, local);

            return(generator);
        }
        /// <summary>
        /// Mark the fluently-specified label
        /// </summary>
        /// <param name="generator"></param>
        /// <param name="labelName">The name of the fluently-specified label</param>

        public static XsILGenerator MarkLabel(this XsILGenerator generator, string labelName)
        {
            var   data = GeneratorExtraData.GetOrCreateValue(generator);
            Label label;

            if (!data.Labels.TryGetValue(labelName, out label))
            {
                throw new InvalidOperationException("No label with the name `" + labelName + "` declared");
            }

            generator.MarkLabel(label);
            data.Labels.Remove(labelName);

            return(generator);
        }
        /// <summary>
        /// Pops an address from the evaluation stack and pushes the value type object (of the given type) at that location onto the evaluation stack
        /// </summary>
        /// <param name="generator">The <see cref="T:System.Reflection.Emit.XsILGenerator" /> to emit instructions from</param>
        /// <param name="type">The type of the value type object</param>

        public static XsILGenerator LoadValueTypeOntoStack(this XsILGenerator generator, Type type)
        {
            if (!type.IsValueType)
            {
                throw new InvalidOperationException("This operation is not valid on reference types");
            }

            if (type == typeof(sbyte))
            {
                return(generator.FluentEmit(OpCodes.Ldind_I1));
            }
            else if (type == typeof(byte))
            {
                return(generator.FluentEmit(OpCodes.Ldind_U1));
            }
            else if (type == typeof(short))
            {
                return(generator.FluentEmit(OpCodes.Ldind_I2));
            }
            else if (type == typeof(ushort))
            {
                return(generator.FluentEmit(OpCodes.Ldind_U2));
            }
            else if (type == typeof(int))
            {
                return(generator.FluentEmit(OpCodes.Ldind_I4));
            }
            else if (type == typeof(uint))
            {
                return(generator.FluentEmit(OpCodes.Ldind_U4));
            }
            else if (type == typeof(long) || type == typeof(ulong))
            {
                return(generator.FluentEmit(OpCodes.Ldind_I8));
            }
            else if (type == typeof(float))
            {
                return(generator.FluentEmit(OpCodes.Ldind_R4));
            }
            else if (type == typeof(double))
            {
                return(generator.FluentEmit(OpCodes.Ldind_R8));
            }
            else
            {
                return(generator.FluentEmit(OpCodes.Ldobj, type));
            }
        }
Beispiel #20
0
        public static XsILGenerator LoadConstantNumber(this XsILGenerator generator, string type, decimal number)
        {
            var itl = type.ToLower();

            if (itl == "f64")
            {
                return(generator.LoadConstant((double)number));
            }
            if (itl == "f32")
            {
                return(generator.LoadConstant((float)number));
            }
            if (itl == "i64")
            {
                return(generator.LoadConstant((long)number));
            }
            if (itl == "i32")
            {
                return(generator.LoadConstant((int)number));
            }
            if (itl == "i16")
            {
                return(generator.LoadConstant((short)number));
            }
            if (itl == "i8")
            {
                return(generator.LoadConstant((sbyte)number));
            }
            if (itl == "u64")
            {
                return(generator.LoadConstant((ulong)number));
            }
            if (itl == "u32")
            {
                return(generator.LoadConstant((uint)number));
            }
            if (itl == "u16")
            {
                return(generator.LoadConstant((ushort)number));
            }
            if (itl == "u8")
            {
                return(generator.LoadConstant((byte)number));
            }
            return(generator.LoadConstant((double)number));
        }
        internal static Label GetOrCreateLabel(this XsILGenerator generator, string labelName)
        {
            var data = GeneratorExtraData.GetOrCreateValue(generator);

            Label label;

            if (data.Labels.TryGetValue(labelName, out label))
            {
                return(label);
            }
            else
            {
                label = generator.DefineLabel();
                data.Labels.Add(labelName, label);
                return(label);
            }
        }
Beispiel #22
0
        /// <summary>
        /// Pops a value from the evaluation stack and stores it in the given local
        /// </summary>
        /// <param name="generator">The <see cref="T:System.Reflection.Emit.XsILGenerator" /> to emit instructions from</param>
        /// <param name="local">The local to store the evaluation stack value in</param>

        public static XsILGenerator StoreInLocal(this XsILGenerator generator, LocalBuilder local)
        {
            switch (local.LocalIndex)
            {
            case 0:
                return(generator.FluentEmit(OpCodes.Stloc_0));

            case 1:
                return(generator.FluentEmit(OpCodes.Stloc_1));

            case 2:
                return(generator.FluentEmit(OpCodes.Stloc_2));

            default:
                return((local.LocalIndex <= 255)
                        ? generator.FluentEmit(OpCodes.Stloc_S, local)
                        : generator.FluentEmit(OpCodes.Stloc, local));
            }
        }
 private void TryStoreReference(object varRef, XsILGenerator il = null)
 {
     if (il == null)
     {
         il = ctx.GetILGenerator();
     }
     if (varRef is XsField field)
     {
         il.StoreInField(field);
         ctx.LastStoredReference = varRef;
     }
     else if (varRef is XsVariable local)
     {
         il.StoreInLocal(local);
     }
     else if (varRef is XsParameter param)
     {
         il.StoreInArgument(param);
     }
 }
Beispiel #24
0
        /// <summary>
        /// Pushes the given value onto the evaluation stack
        /// </summary>
        /// <param name="generator">The <see cref="T:System.Reflection.Emit.XsILGenerator" /> to emit instructions from</param>
        /// <param name="value">The value to push onto the evaluation stack</param>

        public static XsILGenerator LoadConstant(this XsILGenerator generator, Int32 value)
        {
            switch (value)
            {
            case -1:
                return(generator.FluentEmit(OpCodes.Ldc_I4_M1));

            case 0:
                return(generator.FluentEmit(OpCodes.Ldc_I4_0));

            case 1:
                return(generator.FluentEmit(OpCodes.Ldc_I4_1));

            case 2:
                return(generator.FluentEmit(OpCodes.Ldc_I4_2));

            case 3:
                return(generator.FluentEmit(OpCodes.Ldc_I4_3));

            case 4:
                return(generator.FluentEmit(OpCodes.Ldc_I4_4));

            case 5:
                return(generator.FluentEmit(OpCodes.Ldc_I4_5));

            case 6:
                return(generator.FluentEmit(OpCodes.Ldc_I4_6));

            case 7:
                return(generator.FluentEmit(OpCodes.Ldc_I4_7));

            case 8:
                return(generator.FluentEmit(OpCodes.Ldc_I4_8));

            default:
                return(value <= 127 && value >= -128
                        ? generator.FluentEmit(OpCodes.Ldc_I4_S, value)
                        : generator.FluentEmit(OpCodes.Ldc_I4, value));
            }
        }
Beispiel #25
0
        /// <summary>
        /// Loads the specified argument onto the evaluation stack
        /// </summary>
        /// <param name="generator">The <see cref="T:System.Reflection.Emit.XsILGenerator" /> to emit instructions from</param>
        /// <param name="argNum">The index of the argument to load</param>
        public static XsILGenerator LoadArgument(this XsILGenerator generator, ushort argNum)
        {
            switch (argNum)
            {
            case 0:
                return(generator.FluentEmit(OpCodes.Ldarg_0));

            case 1:
                return(generator.FluentEmit(OpCodes.Ldarg_1));

            case 2:
                return(generator.FluentEmit(OpCodes.Ldarg_2));

            case 3:
                return(generator.FluentEmit(OpCodes.Ldarg_3));

            default:
                return(argNum <= 255
                        ? generator.FluentEmit(OpCodes.Ldarg_S, (byte)argNum)
                        : generator.FluentEmit(OpCodes.Ldarg, argNum));
            }
        }
 private void TryLoadReference(object value, XsILGenerator il = null)
 {
     if (il == null)
     {
         il = ctx.GetILGenerator();
     }
     if (value is XsVariable variable)
     {
         il.LoadLocal(variable);
     }
     else if (value is XsField field)
     {
         if (!field.FIeldInfo.IsStatic)
         {
             il.LoadThis();
         }
         il.LoadField(field);
         ctx.LastLoadedReference = value;
     }
     else if (value is XsParameter param)
     {
         il.LoadArgument(param);
     }
 }
Beispiel #27
0
 /// <summary>
 /// Stores the given value in the given local
 /// </summary>
 /// <param name="generator">The <see cref="T:System.Reflection.Emit.XsILGenerator" /> to emit instructions from</param>
 /// <param name="localName">The name of the fluently-specified local</param>
 /// <param name="value">The value to store in the local</param>
 /// <exception cref="ArgumentException">Thrown if the local is not of type <see cref="Char" /></exception>
 public static XsILGenerator OverwriteLocalWith(this XsILGenerator generator, string localName, Char value)
 => generator.OverwriteLocalWith(generator.GetLocal(localName), value);
Beispiel #28
0
        /// <summary>
        /// Branch to the given label, clearing the evaluation stack; can be used to leave a protected region
        /// </summary>
        /// <param name="generator">The <see cref="T:System.Reflection.Emit.XsILGenerator" /> to emit instructions from</param>
        /// <param name="label">The label to branch to</param>

        public static XsILGenerator Leave(this XsILGenerator generator, Label label) => generator.FluentEmit(OpCodes.Leave, label);
Beispiel #29
0
        /// <summary>
        /// Pops an integer value from the evaluation stack and branches to the corresponding zero-indexed label in the provided list, continuing to the next instruction if the value is outside the valid range
        /// </summary>
        /// <param name="generator">The <see cref="T:System.Reflection.Emit.XsILGenerator" /> to emit instructions from</param>
        /// <param name="labelNames">The names of the fluently-specified labels to form a jump table from</param>

        public static XsILGenerator Switch(this XsILGenerator generator, params string[] labelNames)
        => generator.Switch(labelNames.Select(generator.GetOrCreateLabel).ToArray());
Beispiel #30
0
        /// <summary>
        /// Pops an integer value from the evaluation stack and branches to the corresponding zero-indexed label in the provided list, continuing to the next instruction if the value is outside the valid range
        /// </summary>
        /// <param name="generator">The <see cref="T:System.Reflection.Emit.XsILGenerator" /> to emit instructions from</param>
        /// <param name="labels">The labels to form a jump table from</param>

        public static XsILGenerator Switch(this XsILGenerator generator, params Label[] labels) => generator.FluentEmit(OpCodes.Switch, labels);