/// <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."); } }
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(); }
/// <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); }
/// <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); }
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); } }
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> /// 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; } }
/// <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; } }
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(); }
/// <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(); }
/// <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); }
/// <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); }
/// <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; }