Example #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.");
     }
 }
        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>
        /// 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.");
            }
        }
Example #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;
        }
        public void GenerateFill(ICilWriter msilWriter)
        {
            var g = new MethodGenerator(msilWriter);

            var instance = g.GetParameter(0);

            g.If(() =>
            {
                g.Load(instance);
                return(BinaryOperator.IsNull);
            });
            {
                if (_def.Type.IsAbstract)
                {
                    g.BeginCall(typeof(BarfErrors).ResolveMethod("RaiseAbstractConstructionError", typeof(Type)));
                    g.Load(_def.Type);
                    g.EndCall();
                }
                else
                {
                    g.BeginAssign(instance);
                    {
                        g.NewObject(_def.Type);
                    }
                    g.EndAssign();
                }
            }
            g.EndIf();

            foreach (var part in _def.Parts)
            {
                g.BeginScope();
                {
                    var member = g.CreateExpression(instance);
                    if (part.Member == null)
                    {
                        member.MakeReadOnly();
                    }
                    else
                    {
                        member.AddMember(part.Member);
                    }
                    var context = new GenFillContext(g, member, part);

                    var builder = PartResolver.Current.GetPartBuilder(part.Type, part, true);

                    builder.GenerateFillPart(context);
                }
                g.EndScope();
            }

            g.Return();
        }
Example #6
0
        /// <summary>
        /// Generates the body of the <see cref="BarfSerializer{T}.CreateEmpty()"/>.
        /// </summary>
        /// <param name="msilWriter">The MSIL writer to write to.</param>
        public void GenerateCreateEmptyMethod(ICilWriter msilWriter)
        {
            var g = new MethodGenerator(msilWriter);

            if (_def.Type.IsValueType)
            {
                g.LoadDefaultOf(_def.Type);
            }
            else
            {
                g.NewObject(_def.Type, Type.EmptyTypes);
            }
            g.Return();
        }
        /// <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);
        }
        public void GenerateAssertAreEqual(ICilWriter msilWriter)
        {
            var g = new MethodGenerator(msilWriter);

            var expected = g.GetParameter(0);
            var actual   = g.GetParameter(1);

            var assertAreEqual    = typeof(Assert).ResolveMethod("AreEqual", typeof(object), typeof(object));
            var assertAreNotEqual = typeof(Assert).ResolveMethod("AreNotEqual", typeof(object), typeof(object));

            if (_def.Type.IsValueType)
            {
                GenerateAssertPartsAreEqual(g);
            }
            else
            {
                g.If(() =>
                {
                    g.Load(expected);
                    return(BinaryOperator.IsNull);
                });
                {
                    g.BeginCall(assertAreEqual);
                    {
                        g.LoadNull();
                        g.Load(actual);
                    }
                    g.EndCall();
                }
                g.Else();
                {
                    g.BeginCall(assertAreNotEqual);
                    {
                        g.LoadNull();
                        g.Load(actual);
                    }
                    g.EndCall();

                    GenerateAssertPartsAreEqual(g);
                }
                g.EndIf();
            }

            g.Return();
        }
        /// <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);
        }
Example #10
0
        /// <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);
        }
Example #11
0
        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);
            }
        }
Example #12
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);
            }
        }
Example #13
0
        /// <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;
            }
        }
Example #14
0
        /// <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;
            }
        }
Example #15
0
        public void GenerateInnerDeserializeMethod(ICilWriter msilWriter)
        {
            var g = new MethodGenerator(msilWriter);

            var instance = g.CreateExpression(g.GetParameter(0));
            var args     = g.CreateExpression(g.GetParameter(1));
            var header   = g.DeclareLocal(typeof(BarfObjectHeader));

            g.BeginAssign(header);
            {
                g.Load(args);
                g.Call(typeof(BarfDeserializationArgs)
                       .ResolveMethod("BeginObject")
                       .MakeGenericMethod(_def.Type));
            }
            g.EndAssign();

            var version = g.CreateExpression(header).AddMember("Version");

            g.If(() =>
            {
                g.Load(header);
                g.LoadMember("IsNull");
                return(BinaryOperator.IsTrue);
            });
            {
                g.BeginAssign(instance);
                g.LoadNull();
                g.EndAssign();
            }
            g.Else();
            {
                g.If(() =>
                {
                    g.Load(instance);
                    return(BinaryOperator.IsNull);
                });
                {
                    if (_def.Type.IsAbstract)
                    {
                        g.BeginCall(typeof(BarfErrors).ResolveMethod("RaiseAbstractConstructionError", typeof(Type)));
                        g.Load(_def.Type);
                        g.EndCall();
                    }
                    else
                    {
                        g.BeginAssign(instance);
                        g.NewObject(instance.Type);
                        g.EndAssign();
                    }
                }
                g.EndIf();

                var partsByVersion = _def.Parts
                                     .GroupBy <PartDefinition, int>(part => part.Version)
                                     .OrderBy <IGrouping <int, PartDefinition>, int>(group => group.Key);

                int count = 0;
                foreach (var versionGroup in partsByVersion)
                {
                    g.If(() =>
                    {
                        g.Load(version);
                        g.Load(versionGroup.Key);
                        return(BinaryOperator.GreaterThanOrEqualTo);
                    });
                    {
                        foreach (var part in versionGroup)
                        {
                            Trace.WriteLine("\tBuilding Deserialize Part - " + part.FullName);

                            g.BeginScope();
                            var context = new GenDeserializeContext(g, part, instance, args, header);
                            part.GetCurrentBuilder()
                            .GenerateDeserializePart(context);
                            g.EndScope();
                        }
                    }
                    count++;
                }
                for (; count > 0; --count)
                {
                    g.EndIf();
                }

                if (_def.IsForwardCompatible)
                {
                    g.If(() =>
                    {
                        g.Load(header).LoadMember("Version");
                        g.Load(_def.CurrentVersion);
                        return(BinaryOperator.GreaterThan);
                    });
                    {
                        g.Load(args);
                        g.BeginCall(typeof(BarfDeserializationArgs)
                                    .ResolveMethod(
                                        "CaptureFutureData",
                                        new[] { _def.Type },
                                        typeof(BarfObjectHeader), new GenericParameter(0).MakeByRefType()));
                        {
                            g.Load(header);
                            g.Load(instance, LoadOptions.AnyAsAddress);
                        }
                        g.EndCall();
                    }
                    g.EndIf();
                }
            }
            g.EndIf();

            g.Load(args).BeginCall(typeof(BarfDeserializationArgs)
                                   .ResolveMethod("EndObject", new[] { _def.Type }, typeof(BarfObjectHeader)));
            {
                g.Load(header);
            }
            g.EndCall();

            g.Return();
        }
Example #16
0
        /// <summary>
        /// Generates the body of the serialize method.
        /// </summary>
        /// <param name="msilWriter">The MSIL writer to write to.</param>
        public void GenerateSerializeMethod(ICilWriter msilWriter)
        {
            var g        = new MethodGenerator(msilWriter);
            var instance = g.GetParameter(0);
            var args     = g.GetParameter(1);

            if (!_def.Type.IsValueType)
            {
                g.If(() =>
                {
                    g.Load(instance);
                    return(BinaryOperator.IsNull);
                });
                {
                    g.Load(args);
                    // todo - call through MemberResolver
                    g.Call(typeof(BarfSerializationArgs).GetMethod("WriteNullObject"));
                    g.Return();
                }
                g.EndIf();
            }

            IVariable  typeContext;
            MethodInfo beginMethod;
            MethodInfo endMethod;

            if (_def.IsForwardCompatible)
            {
                typeContext = g.DeclareLocal(typeof(BarfSerializationArgs.TypeContext));
                beginMethod = typeof(BarfSerializationArgs).GetMethods(BindingFlags.Instance | BindingFlags.Public)
                              .Where <MethodInfo>(m => m.Name == "BeginObject")
                              .Where <MethodInfo>(m =>
                {
                    var ps = m.GetParameters();
                    return(ps.Length == 1 && ps[0].ParameterType.IsGenericParameter);
                })
                              .FirstOrDefault <MethodInfo>()
                              .MakeGenericMethod(_def.Type);
                endMethod = typeof(BarfSerializationArgs).ResolveMethod("EndObject", typeof(BarfSerializationArgs.TypeContext));
            }
            else
            {
                typeContext = g.DeclareLocal(typeof(long));
                beginMethod = typeof(BarfSerializationArgs)
                              .ResolveMethod("BeginObject", Type.EmptyTypes)
                              .MakeGenericMethod(_def.Type);
                endMethod = typeof(BarfSerializationArgs).ResolveMethod("EndObject", typeof(long));
            }
            g.Load(args);
            g.BeginCall(beginMethod);
            if (_def.IsForwardCompatible)
            {
                g.Load(instance);
            }
            g.EndCall();
            g.Store(typeContext);

            foreach (var part in _def.Parts)
            {
                Trace.WriteLine("\tBuilding Serialize Part - " + part.FullName);
                g.BeginScope();
                {
                    var context = new GenSerializeContext(g, part, g.CreateExpression(instance));
                    part.GetCurrentBuilder()
                    .GenerateSerializePart(context);
                }
                g.EndScope();
            }

            g.Load(args);
            g.BeginCall(endMethod);
            {
                g.Load(typeContext);
            }
            g.EndCall();

            g.Return();
        }
Example #17
0
 /// <summary>
 /// Writes a compare instruction that leaves an int32 on the eval stack.
 /// </summary>
 /// <param name="writer">The writer.</param>
 public void WriteCompare(ICilWriter writer)
 {
     _compareWriter(writer);
 }
Example #18
0
 /// <summary>
 /// Writes a conditional branch instruction to <paramref name="target"/>.
 /// The instruction will branch if the operator evaluates to <see langword="true"/>.
 /// </summary>
 /// <param name="writer">The writer to write to.</param>
 /// <param name="target">The label to branch to.</param>
 public void WriteBranch(ICilWriter writer, ILabel target)
 {
     _branchWriter(writer, target);
 }
Example #19
0
 /// <summary>
 ///     <para>Initializes a new instance of the <see cref="SimpleParameter"/> 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 parameter's type.</param>
 /// <param name="name">The parameter's name, or <see langword="null"/> if unavailable.</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 SimpleParameter(ICilWriter writer, int index, Type type, string name)
     : base(writer, index, GetElementType(type), GetName(name, index), false)
 {
     _originalType = type;
 }