public void GenerateSkip(IILGen ilGenerator, Action <IILGen> pushReader, Action <IILGen> pushCtx) { var finish = ilGenerator.DefineLabel(); ilGenerator .Do(pushReader) .Callvirt(() => default(AbstractBufferedReader).ReadBool()) .Brfalse(finish); _itemDescriptor.GenerateSkipEx(ilGenerator, pushReader, pushCtx); ilGenerator .Mark(finish); }
public void Skip(IILGen ilGenerator, Action <IILGen> pushReaderOrCtx) { var finish = ilGenerator.DefineLabel(); ilGenerator .Do(pushReaderOrCtx) .Callvirt(() => default(AbstractBufferedReader).ReadBool()) .Brfalse(finish); _itemHandler.Skip(ilGenerator, pushReaderOrCtx); ilGenerator .Mark(finish); }
public void Save(IILGen ilGenerator, Action <IILGen> pushWriter, Action <IILGen>?pushCtx, Action <IILGen> pushValue) { var nullableType = typeof(Nullable <>).MakeGenericType(_type !.GetGenericArguments()[0]); var localValue = ilGenerator.DeclareLocal(nullableType); var localHasValue = ilGenerator.DeclareLocal(typeof(bool)); var finish = ilGenerator.DefineLabel(); ilGenerator .Do(pushValue) .Stloc(localValue) .Do(pushWriter) .Ldloca(localValue) //ref for struct! .Call(nullableType.GetMethod("get_HasValue") !) .Dup() .Stloc(localHasValue) .Call(typeof(SpanWriter).GetMethod(nameof(SpanWriter.WriteBool)) !) .Ldloc(localHasValue) .Brfalse(finish); _itemHandler.Save(ilGenerator, pushWriter, pushCtx, il => il .Ldloca(localValue).Call(_type.GetMethod("get_Value") !) .Do(_typeConvertorGenerator.GenerateConversion(_type.GetGenericArguments()[0], _itemHandler.HandledType()) !)); ilGenerator.Mark(finish); }
public void GenerateSave(IILGen ilGenerator, Action <IILGen> pushWriter, Action <IILGen> pushCtx, Action <IILGen> pushValue, Type valueType) { var itemType = GetItemType(valueType); var localValue = ilGenerator.DeclareLocal(valueType); var localHasValue = ilGenerator.DeclareLocal(typeof(bool)); var finish = ilGenerator.DefineLabel(); ilGenerator .Do(pushValue) .Stloc(localValue) .Do(pushWriter) .Ldloca(localValue) .Call(valueType.GetMethod("get_HasValue")) .Dup() .Stloc(localHasValue) .Callvirt(() => default(AbstractBufferedWriter).WriteBool(false)) .Ldloc(localHasValue) .Brfalse(finish); _itemDescriptor.GenerateSaveEx(ilGenerator, pushWriter, pushCtx, il => il.Ldloca(localValue).Call(valueType.GetMethod("get_Value")), itemType); ilGenerator .Mark(finish); }
public void Save(IILGen ilGenerator, Action <IILGen> pushWriterOrCtx, Action <IILGen> pushValue) { var nullableType = typeof(Nullable <>).MakeGenericType(_type.GetGenericArguments()[0]); var localValue = ilGenerator.DeclareLocal(nullableType); var localHasValue = ilGenerator.DeclareLocal(typeof(bool)); var finish = ilGenerator.DefineLabel(); ilGenerator .Do(pushValue) .Stloc(localValue) .Do(pushWriterOrCtx) .Ldloca(localValue) //Ldloca for struct! .Call(nullableType.GetMethod("get_HasValue")) .Dup() .Stloc(localHasValue) .Callvirt(() => default(AbstractBufferedWriter).WriteBool(false)) .Ldloc(localHasValue) .Brfalse(finish); _itemHandler.Save(ilGenerator, pushWriterOrCtx, il => il .Ldloca(localValue).Call(_type.GetMethod("get_Value")) .Do(_typeConvertorGenerator.GenerateConversion(_type.GetGenericArguments()[0], _itemHandler.HandledType()))); ilGenerator.Mark(finish); }
public void ReplayTo(IILGen target) { target.Mark(((ILLabel)_label).Label); }
public void GenerateSave(IILGen ilGenerator, Action<IILGen> pushWriter, Action<IILGen> pushCtx, Action<IILGen> pushValue, Type saveType) { var notnull = ilGenerator.DefineLabel(); var completeFinish = ilGenerator.DefineLabel(); var notDictionary = ilGenerator.DefineLabel(); var keyType = saveType.GetGenericArguments()[0]; var valueType = saveType.GetGenericArguments()[1]; var typeAsIDictionary = typeof(IDictionary<,>).MakeGenericType(keyType, valueType); var typeAsICollection = typeAsIDictionary.GetInterface("ICollection`1"); var localDict = ilGenerator.DeclareLocal(typeAsIDictionary); ilGenerator .Do(pushValue) .Castclass(typeAsIDictionary) .Stloc(localDict) .Ldloc(localDict) .Brtrue(notnull) .Do(pushWriter) .Callvirt(() => default(AbstractBufferedWriter).WriteByteZero()) .Br(completeFinish) .Mark(notnull) .Do(pushWriter) .Ldloc(localDict) .Callvirt(typeAsICollection.GetProperty("Count").GetGetMethod()) .LdcI4(1) .Add() .Callvirt(() => default(AbstractBufferedWriter).WriteVUInt32(0)); { var typeAsDictionary = typeof(Dictionary<,>).MakeGenericType(keyType, valueType); var getEnumeratorMethod = typeAsDictionary.GetMethods() .Single(m => m.Name == "GetEnumerator" && m.ReturnType.IsValueType && m.GetParameters().Length == 0); var typeAsIEnumerator = getEnumeratorMethod.ReturnType; var currentGetter = typeAsIEnumerator.GetProperty("Current").GetGetMethod(); var typeKeyValuePair = currentGetter.ReturnType; var localEnumerator = ilGenerator.DeclareLocal(typeAsIEnumerator); var localPair = ilGenerator.DeclareLocal(typeKeyValuePair); var finish = ilGenerator.DefineLabel(); var next = ilGenerator.DefineLabel(); ilGenerator .Ldloc(localDict) .Castclass(typeAsDictionary) .Brfalse(notDictionary) .Ldloc(localDict) .Castclass(typeAsDictionary) .Callvirt(getEnumeratorMethod) .Stloc(localEnumerator) .Try() .Mark(next) .Ldloca(localEnumerator) .Call(typeAsIEnumerator.GetMethod("MoveNext")) .Brfalse(finish) .Ldloca(localEnumerator) .Call(currentGetter) .Stloc(localPair); _keyDescriptor.GenerateSaveEx(ilGenerator, pushWriter, pushCtx, il => il.Ldloca(localPair).Call(typeKeyValuePair.GetProperty("Key").GetGetMethod()), keyType); _valueDescriptor.GenerateSaveEx(ilGenerator, pushWriter, pushCtx, il => il.Ldloca(localPair).Call(typeKeyValuePair.GetProperty("Value").GetGetMethod()), valueType); ilGenerator .Br(next) .Mark(finish) .Finally() .Ldloca(localEnumerator) .Constrained(typeAsIEnumerator) .Callvirt(() => default(IDisposable).Dispose()) .EndTry() .Br(completeFinish); } { var getEnumeratorMethod = typeAsIDictionary.GetInterface("IEnumerable`1").GetMethod("GetEnumerator"); var typeAsIEnumerator = getEnumeratorMethod.ReturnType; var currentGetter = typeAsIEnumerator.GetProperty("Current").GetGetMethod(); var typeKeyValuePair = currentGetter.ReturnType; var localEnumerator = ilGenerator.DeclareLocal(typeAsIEnumerator); var localPair = ilGenerator.DeclareLocal(typeKeyValuePair); var finish = ilGenerator.DefineLabel(); var next = ilGenerator.DefineLabel(); ilGenerator .Mark(notDictionary) .Ldloc(localDict) .Callvirt(getEnumeratorMethod) .Stloc(localEnumerator) .Try() .Mark(next) .Ldloc(localEnumerator) .Callvirt(() => default(IEnumerator).MoveNext()) .Brfalse(finish) .Ldloc(localEnumerator) .Callvirt(currentGetter) .Stloc(localPair); _keyDescriptor.GenerateSaveEx(ilGenerator, pushWriter, pushCtx, il => il.Ldloca(localPair).Call(typeKeyValuePair.GetProperty("Key").GetGetMethod()), keyType); _valueDescriptor.GenerateSaveEx(ilGenerator, pushWriter, pushCtx, il => il.Ldloca(localPair).Call(typeKeyValuePair.GetProperty("Value").GetGetMethod()), valueType); ilGenerator .Br(next) .Mark(finish) .Finally() .Ldloc(localEnumerator) .Callvirt(() => default(IDisposable).Dispose()) .EndTry() .Mark(completeFinish); } }
public void GenerateSave(IILGen ilGenerator, Action <IILGen> pushWriter, Action <IILGen> pushCtx, Action <IILGen> pushValue, Type saveType) { var notnull = ilGenerator.DefineLabel(); var completeFinish = ilGenerator.DefineLabel(); var notDictionary = ilGenerator.DefineLabel(); var keyType = saveType.GetGenericArguments()[0]; var valueType = saveType.GetGenericArguments()[1]; var typeAsIDictionary = typeof(IDictionary <,>).MakeGenericType(keyType, valueType); var typeAsICollection = typeAsIDictionary.GetInterface("ICollection`1"); var localDict = ilGenerator.DeclareLocal(typeAsIDictionary); ilGenerator .Do(pushValue) .Castclass(typeAsIDictionary) .Stloc(localDict) .Ldloc(localDict) .Brtrue(notnull) .Do(pushWriter) .Callvirt(() => default(AbstractBufferedWriter).WriteByteZero()) .Br(completeFinish) .Mark(notnull) .Do(pushWriter) .Ldloc(localDict) .Callvirt(typeAsICollection.GetProperty(nameof(ICollection.Count)).GetGetMethod()) .LdcI4(1) .Add() .Callvirt(() => default(AbstractBufferedWriter).WriteVUInt32(0)); { var typeAsDictionary = typeof(Dictionary <,>).MakeGenericType(keyType, valueType); var getEnumeratorMethod = typeAsDictionary.GetMethods() .Single(m => m.Name == nameof(IEnumerable.GetEnumerator) && m.ReturnType.IsValueType && m.GetParameters().Length == 0); var typeAsIEnumerator = getEnumeratorMethod.ReturnType; var currentGetter = typeAsIEnumerator.GetProperty(nameof(IEnumerator.Current)).GetGetMethod(); var typeKeyValuePair = currentGetter.ReturnType; var localEnumerator = ilGenerator.DeclareLocal(typeAsIEnumerator); var localPair = ilGenerator.DeclareLocal(typeKeyValuePair); var finish = ilGenerator.DefineLabel(); var next = ilGenerator.DefineLabel(); ilGenerator .Ldloc(localDict) .Isinst(typeAsDictionary) .Brfalse(notDictionary) .Ldloc(localDict) .Castclass(typeAsDictionary) .Callvirt(getEnumeratorMethod) .Stloc(localEnumerator) .Try() .Mark(next) .Ldloca(localEnumerator) .Call(typeAsIEnumerator.GetMethod(nameof(IEnumerator.MoveNext))) .Brfalse(finish) .Ldloca(localEnumerator) .Call(currentGetter) .Stloc(localPair); _keyDescriptor.GenerateSaveEx(ilGenerator, pushWriter, pushCtx, il => il.Ldloca(localPair).Call(typeKeyValuePair.GetProperty("Key").GetGetMethod()), keyType); _valueDescriptor.GenerateSaveEx(ilGenerator, pushWriter, pushCtx, il => il.Ldloca(localPair).Call(typeKeyValuePair.GetProperty("Value").GetGetMethod()), valueType); ilGenerator .Br(next) .Mark(finish) .Finally() .Ldloca(localEnumerator) .Constrained(typeAsIEnumerator) .Callvirt(() => default(IDisposable).Dispose()) .EndTry() .Br(completeFinish); } { var getEnumeratorMethod = typeAsIDictionary.GetInterface("IEnumerable`1").GetMethod(nameof(IEnumerable.GetEnumerator)); var typeAsIEnumerator = getEnumeratorMethod.ReturnType; var currentGetter = typeAsIEnumerator.GetProperty(nameof(IEnumerator.Current)).GetGetMethod(); var typeKeyValuePair = currentGetter.ReturnType; var localEnumerator = ilGenerator.DeclareLocal(typeAsIEnumerator); var localPair = ilGenerator.DeclareLocal(typeKeyValuePair); var finish = ilGenerator.DefineLabel(); var next = ilGenerator.DefineLabel(); ilGenerator .Mark(notDictionary) .Ldloc(localDict) .Callvirt(getEnumeratorMethod) .Stloc(localEnumerator) .Try() .Mark(next) .Ldloc(localEnumerator) .Callvirt(() => default(IEnumerator).MoveNext()) .Brfalse(finish) .Ldloc(localEnumerator) .Callvirt(currentGetter) .Stloc(localPair); _keyDescriptor.GenerateSaveEx(ilGenerator, pushWriter, pushCtx, il => il.Ldloca(localPair).Call(typeKeyValuePair.GetProperty("Key").GetGetMethod()), keyType); _valueDescriptor.GenerateSaveEx(ilGenerator, pushWriter, pushCtx, il => il.Ldloca(localPair).Call(typeKeyValuePair.GetProperty("Value").GetGetMethod()), valueType); ilGenerator .Br(next) .Mark(finish) .Finally() .Ldloc(localEnumerator) .Callvirt(() => default(IDisposable).Dispose()) .EndTry() .Mark(completeFinish); } }
public static void GenerateJumpIfEqual(IILGen ilGenerator, Type type, IILLabel jumpTo, Action <IILGen> loadLeft, Action <IILGen> loadRight) { if (type == typeof(sbyte) || type == typeof(byte) || type == typeof(short) || type == typeof(ushort) || type == typeof(int) || type == typeof(uint) || type == typeof(long) || type == typeof(ulong) || type == typeof(float) || type == typeof(double) || type == typeof(bool) || type.IsEnum) { ilGenerator .Do(loadLeft) .Do(loadRight) .BeqS(jumpTo); return; } if (type.IsGenericType) { var genType = type.GetGenericTypeDefinition(); if (genType == typeof(Nullable <>)) { var localLeft = ilGenerator.DeclareLocal(type, "left"); var localRight = ilGenerator.DeclareLocal(type, "right"); var hasValueMethod = type.GetMethod("get_HasValue"); var getValueMethod = type.GetMethod("GetValueOrDefault", Type.EmptyTypes); var labelLeftHasValue = ilGenerator.DefineLabel("leftHasValue"); var labelDifferent = ilGenerator.DefineLabel("different"); ilGenerator .Do(loadLeft) .Stloc(localLeft) .Do(loadRight) .Stloc(localRight) .Ldloca(localLeft) .Call(hasValueMethod) .BrtrueS(labelLeftHasValue) .Ldloca(localRight) .Call(hasValueMethod) .BrtrueS(labelDifferent) .BrS(jumpTo) .Mark(labelLeftHasValue) .Ldloca(localRight) .Call(hasValueMethod) .BrfalseS(labelDifferent); GenerateJumpIfEqual( ilGenerator, type.GetGenericArguments()[0], jumpTo, g => g.Ldloca(localLeft).Call(getValueMethod), g => g.Ldloca(localRight).Call(getValueMethod)); ilGenerator.Mark(labelDifferent); return; } } var equalsMethod = type.GetMethod("Equals", new[] { type, type }) ?? type.GetMethod("op_Equality", new[] { type, type }); if (equalsMethod != null) { loadLeft(ilGenerator); loadRight(ilGenerator); ilGenerator .Call(equalsMethod) .BrtrueS(jumpTo); return; } throw new ArgumentOutOfRangeException(nameof(type), $"Don't know how to compare type {type}"); }