示例#1
0
        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);
        }
示例#2
0
        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);
        }
示例#3
0
        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);
        }
示例#4
0
        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);
        }
示例#5
0
        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);
        }
示例#6
0
 public void ReplayTo(IILGen target)
 {
     target.Mark(((ILLabel)_label).Label);
 }
示例#7
0
 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);
     }
 }
示例#8
0
        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);
            }
        }
示例#9
0
        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}");
        }
示例#10
0
 public void ReplayTo(IILGen target)
 {
     target.Mark(((ILLabel)_label).Label);
 }