Esempio n. 1
0
        public void EmitEncode(ILGenerator il, ILocalVariableCollection locals, Action <ILGenerator> emitLoad)
        {
            var valueIsNotNullLabel = il.DefineLabel();
            var endOfMethodLabel    = il.DefineLabel();

            var elemVar = il.DeclareLocal(elementType);                 // TElement elem

            emitLoad(il);                                               // if (value)
            il.Emit(OpCodes.Brtrue, valueIsNotNullLabel);               //     goto valueIsNotNullLabel

            // value is null branch
            il.Emit(OpCodes.Ldloc, locals.DataPointer);                 // *(int*) data = -1
            il.Emit_Ldc_I4(-1);
            il.Emit(OpCodes.Stind_I4);
            il.Emit_IncreasePointer(locals.DataPointer, sizeof(int));   // data += sizeof(int)
            il.Emit(OpCodes.Br, endOfMethodLabel);                      // goto endOfMethodLabel

            // value is not null branch
            il.MarkLabel(valueIsNotNullLabel);                          // label valueIsNotNullLabel
            il.Emit(OpCodes.Ldloc, locals.DataPointer);                 // *(int*) data = (int)value.Count
            EmitLoadCount(il, emitLoad);
            il.Emit(OpCodes.Stind_I4);
            il.Emit_IncreasePointer(locals.DataPointer, sizeof(int));   // data += sizeof(int)
            EmitEnumerateCollection(il, emitLoad, emitLoadCurrent =>    // foreach (current in value)
            {
                emitLoadCurrent();                                      //     elem = current
                il.Emit(OpCodes.Stloc, elemVar);
                elementCodec.EmitEncode(il, locals, elemVar);           //     encode(data, elem)
            });
            il.MarkLabel(endOfMethodLabel);                             // label endOfMethodLabel
        }
Esempio n. 2
0
        public void EmitEncode(ILGenerator il, ILocalVariableCollection locals, Action <ILGenerator> emitLoad)
        {
            var valueIsNotNullLabel = il.DefineLabel();
            var endOfSubmethodLabel = il.DefineLabel();

            if (CanBeNull)
            {
                emitLoad(il);                                               // if (value)
                il.Emit(OpCodes.Brtrue, valueIsNotNullLabel);               //     goto valueIsNotNullLabel

                il.Emit(OpCodes.Ldloc, locals.DataPointer);                 // *(int*) data = 0
                il.Emit_Ldc_I4(0);
                il.Emit(OpCodes.Stind_I4);
                il.Emit_IncreasePointer(locals.DataPointer, sizeof(int));   // data += sizeof(int)
                il.Emit(OpCodes.Br, endOfSubmethodLabel);                   // goto endOfSubmethodLabel

                il.MarkLabel(valueIsNotNullLabel);                          // goto valueIsNotNullLabel
                il.Emit(OpCodes.Ldloc, locals.DataPointer);                 // *(int*) data = 1
                il.Emit_Ldc_I4(1);
                il.Emit(OpCodes.Stind_I4);
                il.Emit_IncreasePointer(locals.DataPointer, sizeof(int));   // data += sizeof(int)
            }

            foreach (var memberInfo in memberInfos)                         // foreach (member)
            {
                var memberVar = il.DeclareLocal(                            //     encode(value.member)
                    GetMemberType(memberInfo.Member));
                EmitLoadMember(il, emitLoad, memberInfo.Member);
                il.Emit(OpCodes.Stloc, memberVar);
                memberInfo.Codec.EmitEncode(il, locals, memberVar);
            }
            il.MarkLabel(endOfSubmethodLabel);                              // label endOfSubmethodLabel
        }
Esempio n. 3
0
        public void EmitDecode(ILGenerator il, ILocalVariableCollection locals, bool doNotCheckBounds)
        {
            var resultIsNotNullLabel = il.DefineLabel();
            var endOfSubmethodLabel  = il.DefineLabel();

            if (CanBeNull)
            {
                if (!doNotCheckBounds)
                {
                    var canReadFlagLabel = il.DefineLabel();
                    il.Emit(OpCodes.Ldloc, locals.RemainingBytes);              // if (remainingBytes >= sizeof(int))
                    il.Emit_Ldc_I4(sizeof(int));                                //     goto canReadFlagLabel
                    il.Emit(OpCodes.Bge, canReadFlagLabel);
                    il.Emit_ThrowUnexpectedEndException();                      // throw new InvalidDataException("...")
                    il.MarkLabel(canReadFlagLabel);                             // label canReadFlagLabel
                }

                var flagVar = il.DeclareLocal(typeof(int));

                il.Emit(OpCodes.Ldloc, locals.DataPointer);                     // flag = *(int*) data
                il.Emit(OpCodes.Ldind_I4);
                il.Emit(OpCodes.Stloc, flagVar);
                il.Emit_IncreasePointer(locals.DataPointer, sizeof(int));       // data += sizeof(int)
                il.Emit_DecreaseInteger(locals.RemainingBytes, sizeof(int));    // remainingBytes -= sizeof(int)

                il.Emit(OpCodes.Ldloc, flagVar);                                // if (flag)
                il.Emit(OpCodes.Brtrue, resultIsNotNullLabel);                  //     goto resultIsNotNullLabel

                il.Emit(OpCodes.Ldnull);                                        // stack_0 = null
                il.Emit(OpCodes.Br, endOfSubmethodLabel);                       // goto endOfSubmethodLabel

                il.MarkLabel(resultIsNotNullLabel);                             // label resultIsNotNullLabel
            }

            var thisVar = il.DeclareLocal(type);

            if (CanBeNull)
            {
                il.Emit(OpCodes.Ldtoken, type);                                 // stack_0 = (T)FormatterServices.GetUninitializedObject(typeof(T))
                il.Emit(OpCodes.Call, GetTypeFromHandleMethod);
                il.Emit(OpCodes.Call, GetUninitializedObject);
                il.Emit(OpCodes.Castclass, type);
                il.Emit(OpCodes.Stloc, thisVar);
            }
            else
            {
                il.Emit(OpCodes.Ldloca, thisVar);
                il.Emit(OpCodes.Initobj, type);
            }

            foreach (var memberInfo in memberInfos)                             // foreach (member)
            {
                il.Emit(CanBeNull ? OpCodes.Ldloc : OpCodes.Ldloca, thisVar);   //     stack_0.member = decode()
                memberInfo.Codec.EmitDecode(il, locals, doNotCheckBounds);
                EmitSetMember(il, memberInfo.Member);
            }

            il.Emit(OpCodes.Ldloc, thisVar);
            il.MarkLabel(endOfSubmethodLabel);                                  // label endOfSubmethodLabel
        }
Esempio n. 4
0
 public void EmitEncode(ILGenerator il, ILocalVariableCollection locals, Action <ILGenerator> emitLoad)
 {
     il.Emit(OpCodes.Ldloc, locals.DataPointer);              // *(T*) data = val
     emitLoad(il);
     il.Emit(OpCodes.Stobj, type);
     il.Emit_IncreasePointer(locals.DataPointer, sizeInBytes);// data += sizeInBytes
 }
Esempio n. 5
0
 protected override void EmitDecodeAndStore(ILGenerator il, ILocalVariableCollection locals, LocalBuilder collectionVar, LocalBuilder iVar, bool doNotCheckBounds)
 {
     il.Emit(OpCodes.Ldloc, collectionVar);
     il.Emit(OpCodes.Ldloc, iVar);
     ElementCodec.EmitDecode(il, locals, doNotCheckBounds);
     il.Emit(OpCodes.Stelem_Ref);
 }
 public static void EmitEncode(this IEmittingCodec codec, ILGenerator il, ILocalVariableCollection locals, Action<ILGenerator> emitLoadParent, MethodInfo propertyGetter)
 {
     codec.EmitEncode(il, locals, lil =>
         {
             emitLoadParent(lil);
             lil.Emit(OpCodes.Call, propertyGetter);
         });
 }
Esempio n. 7
0
 public static void EmitEncode(this IEmittingCodec codec, ILGenerator il, ILocalVariableCollection locals, Action <ILGenerator> emitLoadParent, MethodInfo propertyGetter)
 {
     codec.EmitEncode(il, locals, lil =>
     {
         emitLoadParent(lil);
         lil.Emit(OpCodes.Call, propertyGetter);
     });
 }
Esempio n. 8
0
        public void EmitDecode(ILGenerator il, ILocalVariableCollection locals, bool doNotCheckBounds)
        {
            var endOfSubmethodLabel = il.DefineLabel();

            if (!doNotCheckBounds)
            {
                var canReadSizeLabel = il.DefineLabel();
                il.Emit(OpCodes.Ldloc, locals.RemainingBytes);          // if (remainingBytes >= sizeof(int))
                il.Emit_Ldc_I4(sizeof(int));                            //     goto canReadSizeLabel
                il.Emit(OpCodes.Bge, canReadSizeLabel);
                il.Emit_ThrowUnexpectedEndException();                  // throw new InvalidDataException("...")
                il.MarkLabel(canReadSizeLabel);                         // label canReadSizeLabel
            }
            il.Emit(OpCodes.Ldloc, locals.DataPointer);                 // stack_0 = *(int*) data
            il.Emit(OpCodes.Ldind_I4);
            var tempInteger = locals.GetOrAdd("tempInteger",            // var tempInteger = stack_0
                                              g => g.DeclareLocal(typeof(int)));

            il.Emit(OpCodes.Stloc, tempInteger);
            il.Emit_IncreasePointer(locals.DataPointer, sizeof(int));    // data += sizeof(int)
            il.Emit_DecreaseInteger(locals.RemainingBytes, sizeof(int)); // remainingBytes -= sizeof(int)

            if (canBeNull)
            {
                var strIsNotNullLabel = il.DefineLabel();

                il.Emit(OpCodes.Ldloc, tempInteger);                    // if (tempInteger != -1)
                il.Emit_Ldc_I4(-1);                                     //     goto strIsNotNullLabel
                il.Emit(OpCodes.Bne_Un, strIsNotNullLabel);

                // String is null branch
                il.Emit(OpCodes.Ldnull);                                // stack_0 = null
                il.Emit(OpCodes.Br, endOfSubmethodLabel);               // goto endOfSubmethodLabel

                // String is not null branch
                il.MarkLabel(strIsNotNullLabel);                        // label strIsNotNullLabel
            }

            if (!doNotCheckBounds)
            {
                var canReadDataLabel = il.DefineLabel();
                il.Emit(OpCodes.Ldloc, locals.RemainingBytes);          // if (remainingBytes >= tempInteger)
                il.Emit(OpCodes.Ldloc, tempInteger);                    //     goto canReadDataLabel
                il.Emit(OpCodes.Bge, canReadDataLabel);
                il.Emit_ThrowUnexpectedEndException();                  // throw new InvalidDataException("...")
                il.MarkLabel(canReadDataLabel);                         // label canReadDataLabel
            }
            il.Emit(OpCodes.Ldloc, locals.DataPointer);                 // stack_0 = data
            il.Emit_Ldc_I4(0);                                          // stack_1 = 0
            il.Emit(OpCodes.Ldloc, tempInteger);                        // stack_2 = tempInteger >> 1
            il.Emit_Ldc_I4(1);
            il.Emit(OpCodes.Shr);
            il.Emit(OpCodes.Newobj, NewString);                          // stack_0 = new string(stack_0, stack_1, stack_2)
            EmitParseFromString(il);                                     // stack_0 = Parse(stack_0)
            il.Emit_IncreasePointer(locals.DataPointer, tempInteger);    // data += tempInteger
            il.Emit_DecreaseInteger(locals.RemainingBytes, tempInteger); // remainingBytes -= tempInteger
            il.MarkLabel(endOfSubmethodLabel);                           // label endOfSubmethodLabel
        }
Esempio n. 9
0
 public void EmitDecode(ILGenerator il, ILocalVariableCollection locals, bool doNotCheckBounds)
 {
     if (!doNotCheckBounds)
     {
         var everythingsAllrightLabel = il.DefineLabel();
         il.Emit(OpCodes.Ldloc, locals.RemainingBytes);           // if (remainingBytes >= sizeInBytes)
         il.Emit_Ldc_I4(sizeInBytes);                             //     goto everythingsAllrightLabel
         il.Emit(OpCodes.Bge, everythingsAllrightLabel);
         il.Emit_ThrowUnexpectedEndException();                   // throw new InvalidDataException("...")
         il.MarkLabel(everythingsAllrightLabel);                  // label everythingsAllrightLabel
     }
     il.Emit(OpCodes.Ldloc, locals.DataPointer);                  // stack_0 = *(T*) data
     il.Emit(OpCodes.Ldobj, type);
     il.Emit_IncreasePointer(locals.DataPointer, sizeInBytes);    // data += sizeInBytes
     il.Emit_DecreaseInteger(locals.RemainingBytes, sizeInBytes); // remainingBytes -= sizeInBytes
 }
Esempio n. 10
0
        public void EmitDecode(ILGenerator il, ILocalVariableCollection locals, bool doNotCheckBounds)
        {
            var valueIsNotNullLabel = il.DefineLabel();
            var endOfMethodLabel    = il.DefineLabel();

            var resultVar = il.DeclareLocal(type);                      // TCollection result

            if (!doNotCheckBounds)
            {
                var canReadLengthLabel = il.DefineLabel();
                il.Emit(OpCodes.Ldloc, locals.RemainingBytes);          // if (remainingBytes >= sizeof(int))
                il.Emit_Ldc_I4(sizeof(int));                            //     goto canReadLengthLabel
                il.Emit(OpCodes.Bge, canReadLengthLabel);
                il.Emit_ThrowUnexpectedEndException();                  // throw new InvalidDataException("...")
                il.MarkLabel(canReadLengthLabel);                       // label canReadLengthLabel
            }

            var lengthVar = il.DeclareLocal(typeof(int));               // var length = *(int*) data

            il.Emit(OpCodes.Ldloc, locals.DataPointer);
            il.Emit(OpCodes.Ldind_I4);
            il.Emit(OpCodes.Stloc, lengthVar);
            il.Emit_IncreasePointer(locals.DataPointer, sizeof(int));    // data += sizeof(int)
            il.Emit_DecreaseInteger(locals.RemainingBytes, sizeof(int)); // remainingBytes -= sizeof(int)
            il.Emit(OpCodes.Ldloc, lengthVar);                           // if (length != -1)
            il.Emit_Ldc_I4(-1);                                          //     goto valueIsNotNullLabel
            il.Emit(OpCodes.Bne_Un, valueIsNotNullLabel);

            il.Emit(OpCodes.Ldnull);                                    // stack_0 = null
            il.Emit(OpCodes.Br, endOfMethodLabel);                      // goto endOfMethodLabel

            il.MarkLabel(valueIsNotNullLabel);                          // label valueIsNotNullLabel
            EmitCreateCollection(il, lengthVar);                        // result = new TCollection()
            il.Emit(OpCodes.Stloc, resultVar);
            il.EmitForLoop(lengthVar, (lil, iVar) =>                    // for (int i = 0; i < length; i++)
                           EmitDecodeAndStore(                          //     result.Add(decode(data, remainingBytes))
                               lil, locals, resultVar, iVar, doNotCheckBounds));
            il.Emit(OpCodes.Ldloc, resultVar);                          // stack_0 = result
            il.MarkLabel(endOfMethodLabel);                             // label endOfMethodLabel
        }
Esempio n. 11
0
        public void EmitEncode(ILGenerator il, ILocalVariableCollection locals, Action <ILGenerator> emitLoad)
        {
            var strIsNotNullLabel   = il.DefineLabel();
            var endOfSubmethodLabel = il.DefineLabel();

            if (canBeNull)
            {
                emitLoad(il);                                            // if (val) goto strIsNotNullLabel
                il.Emit(OpCodes.Brtrue, strIsNotNullLabel);

                // String is null branch
                il.Emit(OpCodes.Ldloc, locals.DataPointer);              // *(int*) data = -1
                il.Emit_Ldc_I4(-1);
                il.Emit(OpCodes.Stind_I4);
                il.Emit_IncreasePointer(locals.DataPointer, sizeof(int)); // data += sizeof(int)
                il.Emit(OpCodes.Br, endOfSubmethodLabel);                 // goto endOfEncodeLabel

                // String is not null branch
                il.MarkLabel(strIsNotNullLabel);                         // label strIsNotNullLabel
            }

            var stringValueVar = locals.GetOrAdd("stringValue",         // var stringValue = FormatToString(value)
                                                 g => g.DeclareLocal(typeof(string)));

            EmitLoadAsString(il, emitLoad);
            il.Emit(OpCodes.Stloc, stringValueVar);

            var tempIntegerVar = locals.GetOrAdd("tempInteger",         // var tempInteger = stringValue.Length << 1
                                                 g => g.DeclareLocal(typeof(int)));

            il.Emit(OpCodes.Ldloc, stringValueVar);
            il.Emit(OpCodes.Call, GetLength);
            il.Emit_Ldc_I4(1);
            il.Emit(OpCodes.Shl);
            il.Emit(OpCodes.Stloc, tempIntegerVar);
            il.Emit(OpCodes.Ldloc, locals.DataPointer);                 // *(int*)data = tempInteger
            il.Emit(OpCodes.Ldloc, tempIntegerVar);
            il.Emit(OpCodes.Stind_I4);
            il.Emit_IncreasePointer(locals.DataPointer, sizeof(int));   // data += sizeof(int)
            var pinnedString = locals.GetOrAdd("pinnedString",          // var pinned pinnedString = stringValue
                                               g => g.DeclareLocal(typeof(string), true));

            il.Emit(OpCodes.Ldloc, stringValueVar);
            il.Emit(OpCodes.Stloc, pinnedString);
            il.Emit(OpCodes.Ldloc, pinnedString);                       // stack_0 = (byte*)pinnedString
            il.Emit(OpCodes.Conv_I);
            il.Emit(OpCodes.Call, GetOffsetToStringData);               // stack_0 = stack_0 +
            il.Emit(OpCodes.Add);                                       //     RuntimeHelpers.OffsetToStringData
            var charPointer = locals.GetOrAdd("charPointer",            // charPointer = stack_0
                                              g => g.DeclareLocal(typeof(char *)));

            il.Emit(OpCodes.Stloc, charPointer);
            il.Emit(OpCodes.Ldloc, locals.DataPointer);                 // cpblk(data, charPointer, tempInteger)
            il.Emit(OpCodes.Ldloc, charPointer);
            il.Emit(OpCodes.Ldloc, tempIntegerVar);
            il.Emit(OpCodes.Cpblk);
            il.Emit(OpCodes.Ldnull);                                     // pinnedString = null
            il.Emit(OpCodes.Stloc, pinnedString);
            il.Emit_IncreasePointer(locals.DataPointer, tempIntegerVar); // data += tempInteger
            il.MarkLabel(endOfSubmethodLabel);                           // label endOfSubmethodLabel
        }
Esempio n. 12
0
 public static void EmitEncode(this IEmittingCodec codec, ILGenerator il, ILocalVariableCollection locals, LocalBuilder localVar)
 {
     codec.EmitEncode(il, locals, lil => lil.Emit(OpCodes.Ldloc, localVar));
 }
Esempio n. 13
0
 private void EmitDecodeAndStore(ILGenerator il, ILocalVariableCollection locals, bool doNotCheckBounds)
 {
     if (isStruct)
     {
         il.Emit(OpCodes.Ldelema, type);
         elementCodec.EmitDecode(il, locals, doNotCheckBounds);
         il.Emit(OpCodes.Stobj, type);
     }
     else
     {
         elementCodec.EmitDecode(il, locals, doNotCheckBounds);
         il.Emit(OpCodes.Stelem_Ref);
     }
 }
Esempio n. 14
0
        public void EmitEncode(ILGenerator il, ILocalVariableCollection locals, Action<ILGenerator> emitLoad)
        {
            var valueIsNotNullLabel = il.DefineLabel();
            var loopStartLabel = il.DefineLabel();
            var loopConditionLabel = il.DefineLabel();
            var endOfMethodLabel = il.DefineLabel();

            var iVar = il.DeclareLocal(typeof(int));                 // int i
            var elemVar = il.DeclareLocal(type);                     // T elem

            emitLoad(il);                                            // if (value)
            il.Emit(OpCodes.Brtrue, valueIsNotNullLabel);            //     goto valueIsNotNullLabel

            // value is null branch
            il.Emit(OpCodes.Ldloc, locals.DataPointer);              // *(int*) data = -1
            il.Emit_Ldc_I4(-1);
            il.Emit(OpCodes.Stind_I4);
            il.Emit_IncreasePointer(locals.DataPointer, sizeof(int));// data += sizeof(int)
            il.Emit(OpCodes.Br, endOfMethodLabel);                   // goto endOfMethodLabel

            // value is not null branch
            il.MarkLabel(valueIsNotNullLabel);                       // label valueIsNotNullLabel
            il.Emit(OpCodes.Ldloc, locals.DataPointer);              // *(int*) data = (int)value.Length
            emitLoad(il);
            il.Emit(OpCodes.Ldlen);
            il.Emit(OpCodes.Conv_I4);
            il.Emit(OpCodes.Stind_I4);
            il.Emit_IncreasePointer(locals.DataPointer, sizeof(int));// data += sizeof(int)
            il.Emit_Ldc_I4(0);                                       // i = 0
            il.Emit(OpCodes.Stloc, iVar);
            il.Emit(OpCodes.Br, loopConditionLabel);                 // goto loopConditionLabel

            // loop start
            il.MarkLabel(loopStartLabel);                            // loopStartLabel
            emitLoad(il);                                            // elem = value[i]
            il.Emit(OpCodes.Ldloc, iVar);
            EmitLdelem(il);
            il.Emit(OpCodes.Stloc, elemVar);
            elementCodec.EmitEncode(il, locals, elemVar);            // encode(data, elem)
            il.Emit(OpCodes.Ldloc, iVar);                            // i++
            il.Emit_Ldc_I4(1);
            il.Emit(OpCodes.Add);
            il.Emit(OpCodes.Stloc, iVar);

            // loop condition
            il.MarkLabel(loopConditionLabel);                        // label loopConditionLabel
            il.Emit(OpCodes.Ldloc, iVar);                            // if (i < (int)value.Length)
            emitLoad(il);                                            //     goto loopStartLabel
            il.Emit(OpCodes.Ldlen);
            il.Emit(OpCodes.Conv_I4);
            il.Emit(OpCodes.Blt, loopStartLabel);

            il.MarkLabel(endOfMethodLabel);                          // endOfMethodLabel
        }
Esempio n. 15
0
        public void EmitDecode(ILGenerator il, ILocalVariableCollection locals, bool doNotCheckBounds)
        {
            var valueIsNotNullLabel = il.DefineLabel();
            var loopStartLabel = il.DefineLabel();
            var loopConditionLabel = il.DefineLabel();
            var endOfMethodLabel = il.DefineLabel();

            var resultVar = il.DeclareLocal(type.MakeArrayType());      // T[] result
            var iVar = il.DeclareLocal(typeof(int));                    // int i

            if (!doNotCheckBounds)
            {
                var canReadLengthLabel = il.DefineLabel();
                il.Emit(OpCodes.Ldloc, locals.RemainingBytes);          // if (remainingBytes >= sizeof(int))
                il.Emit_Ldc_I4(sizeof(int));                            //     goto canReadLengthLabel
                il.Emit(OpCodes.Bge, canReadLengthLabel);
                il.Emit_ThrowUnexpectedEndException();                  // throw new InvalidDataException("...")
                il.MarkLabel(canReadLengthLabel);                       // label canReadLengthLabel
            }

            var lengthVar = locals.GetOrAdd("refArrayLength",
                lil => lil.DeclareLocal(typeof(int)));
            il.Emit(OpCodes.Ldloc, locals.DataPointer);                 // var length = *(int*) data
            il.Emit(OpCodes.Ldind_I4);
            il.Emit(OpCodes.Stloc, lengthVar);
            il.Emit_IncreasePointer(locals.DataPointer, sizeof(int));   // data += sizeof(int)
            il.Emit_DecreaseInteger(locals.RemainingBytes, sizeof(int));// remainingBytes -= sizeof(int)
            il.Emit(OpCodes.Ldloc, lengthVar);                          // if (length == -1)
            il.Emit_Ldc_I4(-1);                                         //     goto valueIsNotNullLabel
            il.Emit(OpCodes.Bne_Un, valueIsNotNullLabel);

            // value is null branch
            il.Emit(OpCodes.Ldnull);                                    // stack_0 = null
            il.Emit(OpCodes.Br, endOfMethodLabel);                      // goto endOfMethodLabel

            // value is not null branch
            il.MarkLabel(valueIsNotNullLabel);                          // label valueIsNotNullLabel
            il.Emit(OpCodes.Ldloc, lengthVar);                          // result = new T[length]
            il.Emit(OpCodes.Newarr, type);
            il.Emit(OpCodes.Stloc, resultVar);
            il.Emit_Ldc_I4(0);                                          // i = 0
            il.Emit(OpCodes.Stloc, iVar);
            il.Emit(OpCodes.Br, loopConditionLabel);                    // goto loopConditionLabel

            // loop start
            il.MarkLabel(loopStartLabel);                               // label loopStartLabel
            il.Emit(OpCodes.Ldloc, resultVar);                          // result[i] = decode(data, remainingBytes)
            il.Emit(OpCodes.Ldloc, iVar);
            EmitDecodeAndStore(il, locals, doNotCheckBounds);
            il.Emit(OpCodes.Ldloc, iVar);                               // i++
            il.Emit_Ldc_I4(1);
            il.Emit(OpCodes.Add);
            il.Emit(OpCodes.Stloc, iVar);

            // loop condition
            il.MarkLabel(loopConditionLabel);                           // label loopConditionLabel
            il.Emit(OpCodes.Ldloc, iVar);                               // if (i < (int)result.Length)
            il.Emit(OpCodes.Ldloc, resultVar);                          //     goto loopStartLabel
            il.Emit(OpCodes.Ldlen);
            il.Emit(OpCodes.Conv_I4);
            il.Emit(OpCodes.Blt, loopStartLabel);

            il.Emit(OpCodes.Ldloc, resultVar);                          // stack_0 = result
            il.MarkLabel(endOfMethodLabel);                             // label endOfMethodLabel
        }
 public static void EmitEncode(this IEmittingCodec codec, ILGenerator il, ILocalVariableCollection locals, int argIndex)
 {
     codec.EmitEncode(il, locals, lil => lil.Emit_Ldarg(argIndex));
 }
Esempio n. 17
0
        public void EmitEncode(ILGenerator il, ILocalVariableCollection locals, Action<ILGenerator> emitLoad)
        {
            var strIsNotNullLabel = il.DefineLabel();
            var endOfSubmethodLabel = il.DefineLabel();

            emitLoad(il);                                                // if (val) goto strIsNotNullLabel
            il.Emit(OpCodes.Brtrue, strIsNotNullLabel);

            // String is null branch
            il.Emit(OpCodes.Ldloc, locals.DataPointer);              // *(int*) data = -1
            il.Emit_Ldc_I4(-1);
            il.Emit(OpCodes.Stind_I4);
            il.Emit_IncreasePointer(locals.DataPointer, sizeof(int));// data += sizeof(int)
            il.Emit(OpCodes.Br, endOfSubmethodLabel);                // goto endOfEncodeLabel

            // String is not null branch
            il.MarkLabel(strIsNotNullLabel);                         // label strIsNotNullLabel
            var tempInteger = locals.GetOrAdd("tempInteger",         // var tempInteger = val.Length << 1
                g => g.DeclareLocal(typeof(int)));
            emitLoad(il);
            il.Emit(OpCodes.Call, GetLength);
            il.Emit_Ldc_I4(1);
            il.Emit(OpCodes.Shl);
            il.Emit(OpCodes.Stloc, tempInteger);
            il.Emit(OpCodes.Ldloc, locals.DataPointer);              // *(int*)data = tempInteger
            il.Emit(OpCodes.Ldloc, tempInteger);
            il.Emit(OpCodes.Stind_I4);
            il.Emit_IncreasePointer(locals.DataPointer, sizeof(int));// data += sizeof(int)
            var pinnedString = locals.GetOrAdd("pinnedString",       // var pinned pinnedString = val
                g => g.DeclareLocal(typeof(string), true));
            emitLoad(il);
            il.Emit(OpCodes.Stloc, pinnedString);
            il.Emit(OpCodes.Ldloc, pinnedString);                    // stack_0 = (byte*)pinnedString
            il.Emit(OpCodes.Conv_I);
            il.Emit(OpCodes.Call, GetOffsetToStringData);            // stack_0 = stack_0 +
            il.Emit(OpCodes.Add);                                    //     RuntimeHelpers.OffsetToStringData
            var charPointer = locals.GetOrAdd("charPointer",         // charPointer = stack_0
                g => g.DeclareLocal(typeof(char*)));
            il.Emit(OpCodes.Stloc, charPointer);
            il.Emit(OpCodes.Ldloc, locals.DataPointer);              // cpblk(data, charPointer, tempInteger)
            il.Emit(OpCodes.Ldloc, charPointer);
            il.Emit(OpCodes.Ldloc, tempInteger);
            il.Emit(OpCodes.Cpblk);
            il.Emit(OpCodes.Ldnull);                                 // pinnedString = null
            il.Emit(OpCodes.Stloc, pinnedString);
            il.Emit_IncreasePointer(locals.DataPointer, tempInteger);// data += tempInteger
            il.MarkLabel(endOfSubmethodLabel);                       // label endOfSubmethodLabel
        }
Esempio n. 18
0
 public static void EmitEncodeIndirect(this IEmittingCodec codec, ILGenerator il, ILocalVariableCollection locals, int argIndex, Type type)
 {
     codec.EmitEncode(il, locals, lil => { lil.Emit_Ldarg(argIndex); lil.Emit(OpCodes.Ldobj, type); });
 }
 public static void EmitEncodeIndirect(this IEmittingCodec codec, ILGenerator il, ILocalVariableCollection locals, int argIndex, Type type)
 {
     codec.EmitEncode(il, locals, lil => { lil.Emit_Ldarg(argIndex); lil.Emit(OpCodes.Ldobj, type); });
 }
        public void EmitEncode(ILGenerator il, ILocalVariableCollection locals, Action<ILGenerator> emitLoad)
        {
            var arrayIsNotNullLabel = il.DefineLabel();
            var arrayIsNotEmptylabel = il.DefineLabel();
            var endOfSubmethodLabel = il.DefineLabel();

            emitLoad(il);                                            // if (value)
            il.Emit(OpCodes.Brtrue, arrayIsNotNullLabel);            //     goto arrayIsNotNullLabel

            // Array is null branch
            il.Emit(OpCodes.Ldloc, locals.DataPointer);              // *(int*) data = -1
            il.Emit_Ldc_I4(-1);
            il.Emit(OpCodes.Stind_I4);
            il.Emit_IncreasePointer(locals.DataPointer, sizeof(int));// data += sizeof(int)
            il.Emit(OpCodes.Br, endOfSubmethodLabel);                // goto endOfSubmethodLabel

            il.MarkLabel(arrayIsNotNullLabel);
            emitLoad(il);                                            // if (value.Length)
            il.Emit(OpCodes.Ldlen);                                  //     goto arrayIsNotEmptylabel
            il.Emit(OpCodes.Conv_I4);
            il.Emit(OpCodes.Brtrue, arrayIsNotEmptylabel);

            // Array is empty branch
            il.Emit(OpCodes.Ldloc, locals.DataPointer);              // *(int*) data = 0
            il.Emit_Ldc_I4(0);
            il.Emit(OpCodes.Stind_I4);
            il.Emit_IncreasePointer(locals.DataPointer, sizeof(int));// data += sizeof(int)
            il.Emit(OpCodes.Br, endOfSubmethodLabel);                // goto endOfSubmethodLabel

            // Array is not empty branch
            il.MarkLabel(arrayIsNotEmptylabel);
            var lengthVar = locals.GetOrAdd("length",                // var length = value.Length
                lil => lil.DeclareLocal(typeof(int)));
            emitLoad(il);
            il.Emit(OpCodes.Ldlen);
            il.Emit(OpCodes.Conv_I4);
            il.Emit(OpCodes.Stloc, lengthVar);
            var sizeVar = locals.GetOrAdd("sizeInBytes",             // var sizeInBytes = length * sizeOfStruct
                lil => lil.DeclareLocal(typeof(int)));
            il.Emit(OpCodes.Ldloc, lengthVar);
            il.Emit_Ldc_I4(sizeOfStruct);
            il.Emit(OpCodes.Mul);
            il.Emit(OpCodes.Stloc, sizeVar);
            il.Emit(OpCodes.Ldloc, locals.DataPointer);              // *(int*) data = length
            il.Emit(OpCodes.Ldloc, lengthVar);
            il.Emit(OpCodes.Stind_I4);
            il.Emit_IncreasePointer(locals.DataPointer, sizeof(int));// data += sizeof(int)
            var arrayPointerVar = il.Emit_PinArray(                  // var pinned arrayPointer = pin(value)
                typeOfStruct, locals, emitLoad);
            il.Emit(OpCodes.Ldloc, locals.DataPointer);              // cpblk(data, (byte*)arrayPointer, sizeInBytes)
            il.Emit(OpCodes.Ldloc, arrayPointerVar);
            il.Emit(OpCodes.Conv_I);
            il.Emit(OpCodes.Ldloc, sizeVar);
            il.Emit(OpCodes.Cpblk);
            il.Emit_UnpinArray(arrayPointerVar);                     // unpin(arrayPointer)
            il.Emit_IncreasePointer(locals.DataPointer, sizeVar);    // data += sizeInBytes
            il.MarkLabel(endOfSubmethodLabel);
        }
Esempio n. 21
0
 public static LocalBuilder Emit_PinArray(this ILGenerator il, Type elementType, ILocalVariableCollection locals, LocalBuilder localVar)
 {
     return Emit_PinArray(il, elementType, locals, lil => lil.Emit(OpCodes.Ldloc, localVar));
 }
        public void EmitDecode(ILGenerator il, ILocalVariableCollection locals, bool doNotCheckBounds)
        {
            var resultIsNotNullLabel = il.DefineLabel();
            var endOfSubmethodLabel = il.DefineLabel();

            if (!doNotCheckBounds)
            {
                var canReadFlagLabel = il.DefineLabel();
                il.Emit(OpCodes.Ldloc, locals.RemainingBytes);                  // if (remainingBytes >= sizeof(int))
                il.Emit_Ldc_I4(sizeof(int));                                    //     goto canReadFlagLabel
                il.Emit(OpCodes.Bge, canReadFlagLabel);
                il.Emit_ThrowUnexpectedEndException();                          // throw new InvalidDataException("...")
                il.MarkLabel(canReadFlagLabel);                                 // label canReadFlagLabel
            }

            var flagVar = locals.GetOrAdd("existanceFlag",
                lil => lil.DeclareLocal(typeof(int)));

            il.Emit(OpCodes.Ldloc, locals.DataPointer);                         // flag = *(int*) data
            il.Emit(OpCodes.Ldind_I4);
            il.Emit(OpCodes.Stloc, flagVar);
            il.Emit_IncreasePointer(locals.DataPointer, sizeof(int));           // data += sizeof(int)
            il.Emit_DecreaseInteger(locals.RemainingBytes, sizeof(int));        // remainingBytes -= sizeof(int)
            il.Emit(OpCodes.Ldloc, flagVar);                                    // if (flag)
            il.Emit(OpCodes.Brtrue, resultIsNotNullLabel);                      //     goto resultIsNotNullLabel

            // Result is null branch
            il.Emit(OpCodes.Ldnull);                                            // stack_0 = null
            il.Emit(OpCodes.Br, endOfSubmethodLabel);                           // goto endOfSubmethodLabel

            // Result is not null branch
            il.MarkLabel(resultIsNotNullLabel);                                 // label resultIsNotNullLabel
            il.Emit(OpCodes.Ldtoken, type);                                     // stack_0 = (T)FormatterServices.GetUninitializedObject(typeof(T))
            il.Emit(OpCodes.Call, GetTypeFromHandleMethod);
            il.Emit(OpCodes.Call, GetUninitializedObject);
            il.Emit(OpCodes.Castclass, type);

            foreach (var memberInfo in memberInfos)                             // foreach (Prop)
            {                                                                   // {
                il.Emit(OpCodes.Dup);                                           //     stack_0.Prop = decode()
                memberInfo.Codec.EmitDecode(il, locals, doNotCheckBounds);
                il.Emit(OpCodes.Call, memberInfo.Property.GetSetMethod(true));
            }                                                                   // }

            il.MarkLabel(endOfSubmethodLabel);                                  // label endOfSubmethodLabel
        }
Esempio n. 23
0
        public void EmitDecode(ILGenerator il, ILocalVariableCollection locals, bool doNotCheckBounds)
        {
            var strIsNotNullLabel = il.DefineLabel();
            var endOfSubmethodLabel = il.DefineLabel();

            if (!doNotCheckBounds)
            {
                var canReadSizeLabel = il.DefineLabel();
                il.Emit(OpCodes.Ldloc, locals.RemainingBytes);          // if (remainingBytes >= sizeof(int))
                il.Emit_Ldc_I4(sizeof(int));                            //     goto canReadSizeLabel
                il.Emit(OpCodes.Bge, canReadSizeLabel);
                il.Emit_ThrowUnexpectedEndException();                  // throw new InvalidDataException("...")
                il.MarkLabel(canReadSizeLabel);                         // label canReadSizeLabel
            }
            il.Emit(OpCodes.Ldloc, locals.DataPointer);                 // stack_0 = *(int*) data
            il.Emit(OpCodes.Ldind_I4);
            var tempInteger = locals.GetOrAdd("tempInteger",            // var tempInteger = stack_0
                g => g.DeclareLocal(typeof(int)));
            il.Emit(OpCodes.Stloc, tempInteger);
            il.Emit_IncreasePointer(locals.DataPointer, sizeof(int));   // data += sizeof(int)
            il.Emit_DecreaseInteger(locals.RemainingBytes, sizeof(int));// remainingBytes -= sizeof(int)
            il.Emit(OpCodes.Ldloc, tempInteger);
            il.Emit_Ldc_I4(-1);
            il.Emit(OpCodes.Bne_Un, strIsNotNullLabel);

            // String is null branch
            il.Emit(OpCodes.Ldnull);                                    // stack_0 = null
            il.Emit(OpCodes.Br, endOfSubmethodLabel);                   // goto endOfSubmethodLabel

            // String is not null branch
            il.MarkLabel(strIsNotNullLabel);                            // label strIsNotNullLabel
            if (!doNotCheckBounds)
            {
                var canReadDataLabel = il.DefineLabel();
                il.Emit(OpCodes.Ldloc, locals.RemainingBytes);          // if (remainingBytes >= tempInteger)
                il.Emit(OpCodes.Ldloc, tempInteger);                    //     goto canReadDataLabel
                il.Emit(OpCodes.Bge, canReadDataLabel);
                il.Emit_ThrowUnexpectedEndException();                  // throw new InvalidDataException("...")
                il.MarkLabel(canReadDataLabel);                         // label canReadDataLabel
            }
            il.Emit(OpCodes.Ldloc, locals.DataPointer);                 // stack_0 = data
            il.Emit_Ldc_I4(0);                                          // stack_1 = 0
            il.Emit(OpCodes.Ldloc, tempInteger);                        // stack_2 = tempInteger >> 1
            il.Emit_Ldc_I4(1);
            il.Emit(OpCodes.Shr);
            il.Emit(OpCodes.Newobj, NewString);                         // stack_0 = new string(stack_0, stack_1, stack_2)
            il.Emit_IncreasePointer(locals.DataPointer, tempInteger);   // data += tempInteger
            il.Emit_DecreaseInteger(locals.RemainingBytes, tempInteger);// remainingBytes -= tempInteger
            il.MarkLabel(endOfSubmethodLabel);                          // label endOfSubmethodLabel
        }
Esempio n. 24
0
        /*
        public static void Emit_LoadSize(this ILGenerator il, IEmittingCodec codec)
        {
            if (codec.HasFixedSize)
            {
                il.Emit(OpCodes.Pop);
                il.Emit_Ldc_I4(codec.FixedSize);
            }
            else
            {
                codec.EmitCalculateSize(il);
            }
        }

        public static void Emit_LoadSize(this ILGenerator il, IEmittingCodec codec, LocalBuilder localVar)
        {
            Emit_LoadSize(il, codec, lil => lil.Emit(OpCodes.Ldloc, localVar));
        }*/
        public static LocalBuilder Emit_PinArray(this ILGenerator il, Type elementType, ILocalVariableCollection locals, Action<ILGenerator> load)
        {
            var argsDataPointerVar = locals.GetOrAdd("pinnedArray" + elementType.FullName,
                lil => lil.DeclareLocal(elementType.MakePointerType(), true));
            load(il);
            il.Emit_Ldc_I4(0);
            il.Emit(OpCodes.Ldelema, elementType);
            il.Emit(OpCodes.Stloc, argsDataPointerVar);
            return argsDataPointerVar;
        }
 public static void EmitEncode(this IEmittingCodec codec, ILGenerator il, ILocalVariableCollection locals, LocalBuilder localVar)
 {
     codec.EmitEncode(il, locals, lil => lil.Emit(OpCodes.Ldloc, localVar));
 }
Esempio n. 26
0
 public static LocalBuilder Emit_PinArray(this ILGenerator il, Type elementType, ILocalVariableCollection locals)
 {
     return Emit_PinArray(il, elementType, locals, lil => { });
 }
        public void EmitEncode(ILGenerator il, ILocalVariableCollection locals, Action<ILGenerator> emitLoad)
        {
            var valueIsNotNullLabel = il.DefineLabel();
            var endOfSubmethodLabel = il.DefineLabel();

            emitLoad(il);                                                   // if (value)
            il.Emit(OpCodes.Brtrue, valueIsNotNullLabel);                   //     goto valueIsNotNullLabel

            // Value is null branch
            il.Emit(OpCodes.Ldloc, locals.DataPointer);                     // *(int*) data = 0
            il.Emit_Ldc_I4(0);
            il.Emit(OpCodes.Stind_I4);
            il.Emit_IncreasePointer(locals.DataPointer, sizeof(int));       // data += sizeof(int)
            il.Emit(OpCodes.Br, endOfSubmethodLabel);                       // goto endOfSubmethodLabel

            // Value is not null branch
            il.MarkLabel(valueIsNotNullLabel);                              // goto valueIsNotNullLabel
            il.Emit(OpCodes.Ldloc, locals.DataPointer);                     // *(int*) data = 1
            il.Emit_Ldc_I4(1);
            il.Emit(OpCodes.Stind_I4);
            il.Emit_IncreasePointer(locals.DataPointer, sizeof(int));       // data += sizeof(int)
            foreach (var memberInfo in memberInfos)                         // foreach (Prop)
            {                                                               // {
                var propertyGetter = memberInfo.Property.GetGetMethod(true);//     encode(value.Prop)
                memberInfo.Codec.EmitEncode(
                    il, locals, emitLoad, propertyGetter);
            }                                                               // }
            il.MarkLabel(endOfSubmethodLabel);                              // label endOfSubmethodLabel
        }
Esempio n. 28
0
 public static LocalBuilder Emit_PinArray(this ILGenerator il, Type elementType, ILocalVariableCollection locals, int argIndex)
 {
     return Emit_PinArray(il, elementType, locals, lil => lil.Emit_Ldarg(argIndex));
 }
Esempio n. 29
0
 public void EmitDecode(ILGenerator il, ILocalVariableCollection locals, bool doNotCheckBounds)
 {
     il.Emit(OpCodes.Ldloca, locals.DataPointer);
     il.Emit(OpCodes.Ldloca, locals.RemainingBytes);
     il.Emit(OpCodes.Call, doNotCheckBounds ? DecodeFastMethod : DecodeMethod);
 }
        public void EmitDecode(ILGenerator il, ILocalVariableCollection locals, bool doNotCheckBounds)
        {
            var enoughBytesForLengthLabel = il.DefineLabel();
            var enoughBytesForDataLabel = il.DefineLabel();
            var lengthIsMinusOneLabel = il.DefineLabel();
            var lengthIsZeroLabel = il.DefineLabel();
            var labelGroup = new[] {lengthIsMinusOneLabel, lengthIsZeroLabel};
            var lengthIsPositiveLabel = il.DefineLabel();
            var endOfMethodLabel = il.DefineLabel();

            if (!doNotCheckBounds)
            {
                il.Emit(OpCodes.Ldloc, locals.RemainingBytes);          // if (remainingBytes >= sizeof(int))
                il.Emit_Ldc_I4(sizeof(int));                            //     goto enoughBytesForLengthLabel
                il.Emit(OpCodes.Bge, enoughBytesForLengthLabel);

                // not enough bytes for length
                il.Emit_ThrowUnexpectedEndException();                  // throw new InvalidDataException(...)
            }

            // enough bytes for length
            il.MarkLabel(enoughBytesForLengthLabel);
            var lengthVar = locals.GetOrAdd("length",                   // var length = *(int*)data
                lil => lil.DeclareLocal(typeof(int)));
            il.Emit(OpCodes.Ldloc, locals.DataPointer);
            il.Emit(OpCodes.Ldind_I4);
            il.Emit(OpCodes.Stloc, lengthVar);
            il.Emit_IncreasePointer(locals.DataPointer, sizeof(int));   // data += sizeof(int)
            il.Emit_DecreaseInteger(locals.RemainingBytes, sizeof(int));// remainingBytes -= sizeof(int)
            il.Emit(OpCodes.Ldloc, lengthVar);                          // switch(length + 1)
            il.Emit_Ldc_I4(1);                                          //     case 0:  goto lengthIsMinusOneLabel
            il.Emit(OpCodes.Add);                                       //     case 1:  goto lengthIsZeroLabel
            il.Emit(OpCodes.Switch, labelGroup);                        //     default: goto lengthIsPositiveLabel
            il.Emit(OpCodes.Br, lengthIsPositiveLabel);

            // length is -1
            il.MarkLabel(lengthIsMinusOneLabel);
            il.Emit(OpCodes.Ldnull);                                    // stack_0 = null
            il.Emit(OpCodes.Br, endOfMethodLabel);                      // goto endOfMethodLabel

            // length is 0
            il.MarkLabel(lengthIsZeroLabel);
            il.Emit_Ldc_I4(0);                                          // stack_0 = new T[0]
            il.Emit(OpCodes.Newarr, typeOfStruct);
            il.Emit(OpCodes.Br, endOfMethodLabel);                      // goto endOfMethodLabel

            // length is positive
            il.MarkLabel(lengthIsPositiveLabel);
            var sizeVar = locals.GetOrAdd("sizeInBytes",                // var sizeInBytes = length * sizeOfStruct
                lil => lil.DeclareLocal(typeof(int)));
            il.Emit(OpCodes.Ldloc, lengthVar);
            il.Emit_Ldc_I4(sizeOfStruct);
            il.Emit(OpCodes.Mul);
            il.Emit(OpCodes.Stloc, sizeVar);

            if (!doNotCheckBounds)
            {
                il.Emit(OpCodes.Ldloc, locals.RemainingBytes);          // if (remainingBytes >= sizeInBytes)
                il.Emit(OpCodes.Ldloc, sizeVar);                        //     goto enoughBytesForDataLabel
                il.Emit(OpCodes.Bge, enoughBytesForDataLabel);

                // not enough bytes for data
                il.Emit_ThrowUnexpectedEndException();                  // throw new InvalidDataException(...)
            }

            // enough bytes for data
            il.MarkLabel(enoughBytesForDataLabel);
            var resultVar = locals.GetOrAdd(                            // var result = new T[length]
                "arrayOf" + typeOfStruct.FullName,
                lil => lil.DeclareLocal(typeOfStruct.MakeArrayType()));
            il.Emit(OpCodes.Ldloc, lengthVar);
            il.Emit(OpCodes.Newarr, typeOfStruct);
            il.Emit(OpCodes.Stloc, resultVar);
            var arrayPointerVar = il.Emit_PinArray(                     // var pinned arrayPointer = pin(value)
                typeOfStruct, locals, resultVar);
            il.Emit(OpCodes.Ldloc, arrayPointerVar);                    // cpblk((byte*)arrayPointer, data, sizeInBytes)
            il.Emit(OpCodes.Conv_I);
            il.Emit(OpCodes.Ldloc, locals.DataPointer);
            il.Emit(OpCodes.Ldloc, sizeVar);
            il.Emit(OpCodes.Cpblk);
            il.Emit_UnpinArray(arrayPointerVar);                        // unpin(arrayPointer)
            il.Emit_IncreasePointer(locals.DataPointer, sizeVar);       // data += size
            il.Emit_DecreaseInteger(locals.RemainingBytes, sizeVar);    // remainingBytes -= size
            il.Emit(OpCodes.Ldloc, resultVar);                          // stack_0 = result
            il.MarkLabel(endOfMethodLabel);
        }
Esempio n. 31
0
 public void EmitEncode(ILGenerator il, ILocalVariableCollection locals, Action<ILGenerator> emitLoad)
 {
     il.Emit(OpCodes.Ldloca, locals.DataPointer);
     emitLoad(il);
     il.Emit(OpCodes.Call, EncodeMethod);
 }
Esempio n. 32
0
 protected abstract void EmitDecodeAndStore(ILGenerator il, ILocalVariableCollection locals, LocalBuilder collectionVar, LocalBuilder iVar, bool doNotCheckBounds);
Esempio n. 33
0
        public void EmitDecode(ILGenerator il, ILocalVariableCollection locals, bool doNotCheckBounds)
        {
            var enoughBytesForLengthLabel = il.DefineLabel();
            var enoughBytesForDataLabel   = il.DefineLabel();
            var lengthIsMinusOneLabel     = il.DefineLabel();
            var lengthIsZeroLabel         = il.DefineLabel();
            var labelGroup            = new[] { lengthIsMinusOneLabel, lengthIsZeroLabel };
            var lengthIsPositiveLabel = il.DefineLabel();
            var endOfMethodLabel      = il.DefineLabel();

            if (!doNotCheckBounds)
            {
                il.Emit(OpCodes.Ldloc, locals.RemainingBytes);          // if (remainingBytes >= sizeof(int))
                il.Emit_Ldc_I4(sizeof(int));                            //     goto enoughBytesForLengthLabel
                il.Emit(OpCodes.Bge, enoughBytesForLengthLabel);

                // not enough bytes for length
                il.Emit_ThrowUnexpectedEndException();                  // throw new InvalidDataException(...)
            }

            // enough bytes for length
            il.MarkLabel(enoughBytesForLengthLabel);
            var lengthVar = locals.GetOrAdd("length",                   // var length = *(int*)data
                                            lil => lil.DeclareLocal(typeof(int)));

            il.Emit(OpCodes.Ldloc, locals.DataPointer);
            il.Emit(OpCodes.Ldind_I4);
            il.Emit(OpCodes.Stloc, lengthVar);
            il.Emit_IncreasePointer(locals.DataPointer, sizeof(int));    // data += sizeof(int)
            il.Emit_DecreaseInteger(locals.RemainingBytes, sizeof(int)); // remainingBytes -= sizeof(int)
            il.Emit(OpCodes.Ldloc, lengthVar);                           // switch(length + 1)
            il.Emit_Ldc_I4(1);                                           //     case 0:  goto lengthIsMinusOneLabel
            il.Emit(OpCodes.Add);                                        //     case 1:  goto lengthIsZeroLabel
            il.Emit(OpCodes.Switch, labelGroup);                         //     default: goto lengthIsPositiveLabel
            il.Emit(OpCodes.Br, lengthIsPositiveLabel);

            // length is -1
            il.MarkLabel(lengthIsMinusOneLabel);
            il.Emit(OpCodes.Ldnull);                                    // stack_0 = null
            il.Emit(OpCodes.Br, endOfMethodLabel);                      // goto endOfMethodLabel

            // length is 0
            il.MarkLabel(lengthIsZeroLabel);
            il.Emit_Ldc_I4(0);                                          // stack_0 = new T[0]
            il.Emit(OpCodes.Newarr, typeOfStruct);
            il.Emit(OpCodes.Br, endOfMethodLabel);                      // goto endOfMethodLabel

            // length is positive
            il.MarkLabel(lengthIsPositiveLabel);
            var sizeVar = locals.GetOrAdd("sizeInBytes",                // var sizeInBytes = length * sizeOfStruct
                                          lil => lil.DeclareLocal(typeof(int)));

            il.Emit(OpCodes.Ldloc, lengthVar);
            il.Emit_Ldc_I4(sizeOfStruct);
            il.Emit(OpCodes.Mul);
            il.Emit(OpCodes.Stloc, sizeVar);

            if (!doNotCheckBounds)
            {
                il.Emit(OpCodes.Ldloc, locals.RemainingBytes);          // if (remainingBytes >= sizeInBytes)
                il.Emit(OpCodes.Ldloc, sizeVar);                        //     goto enoughBytesForDataLabel
                il.Emit(OpCodes.Bge, enoughBytesForDataLabel);

                // not enough bytes for data
                il.Emit_ThrowUnexpectedEndException();                  // throw new InvalidDataException(...)
            }

            // enough bytes for data
            il.MarkLabel(enoughBytesForDataLabel);
            var resultVar = locals.GetOrAdd(                            // var result = new T[length]
                "arrayOf" + typeOfStruct.FullName,
                lil => lil.DeclareLocal(typeOfStruct.MakeArrayType()));

            il.Emit(OpCodes.Ldloc, lengthVar);
            il.Emit(OpCodes.Newarr, typeOfStruct);
            il.Emit(OpCodes.Stloc, resultVar);
            var arrayPointerVar = il.Emit_PinArray(                     // var pinned arrayPointer = pin(value)
                typeOfStruct, resultVar);

            il.Emit(OpCodes.Ldloc, arrayPointerVar);                    // cpblk((byte*)arrayPointer, data, sizeInBytes)
            il.Emit(OpCodes.Conv_I);
            il.Emit(OpCodes.Ldloc, locals.DataPointer);
            il.Emit(OpCodes.Ldloc, sizeVar);
            il.Emit(OpCodes.Cpblk);
            il.Emit_UnpinArray(arrayPointerVar);                        // unpin(arrayPointer)
            il.Emit_IncreasePointer(locals.DataPointer, sizeVar);       // data += size
            il.Emit_DecreaseInteger(locals.RemainingBytes, sizeVar);    // remainingBytes -= size
            il.Emit(OpCodes.Ldloc, resultVar);                          // stack_0 = result
            il.MarkLabel(endOfMethodLabel);
        }
Esempio n. 34
0
        public void EmitEncode(ILGenerator il, ILocalVariableCollection locals, Action <ILGenerator> emitLoad)
        {
            var arrayIsNotNullLabel  = il.DefineLabel();
            var arrayIsNotEmptylabel = il.DefineLabel();
            var endOfSubmethodLabel  = il.DefineLabel();

            emitLoad(il);                                            // if (value)
            il.Emit(OpCodes.Brtrue, arrayIsNotNullLabel);            //     goto arrayIsNotNullLabel

            // Array is null branch
            il.Emit(OpCodes.Ldloc, locals.DataPointer);              // *(int*) data = -1
            il.Emit_Ldc_I4(-1);
            il.Emit(OpCodes.Stind_I4);
            il.Emit_IncreasePointer(locals.DataPointer, sizeof(int)); // data += sizeof(int)
            il.Emit(OpCodes.Br, endOfSubmethodLabel);                 // goto endOfSubmethodLabel

            il.MarkLabel(arrayIsNotNullLabel);
            emitLoad(il);                                            // if (value.Length)
            il.Emit(OpCodes.Ldlen);                                  //     goto arrayIsNotEmptylabel
            il.Emit(OpCodes.Conv_I4);
            il.Emit(OpCodes.Brtrue, arrayIsNotEmptylabel);

            // Array is empty branch
            il.Emit(OpCodes.Ldloc, locals.DataPointer);              // *(int*) data = 0
            il.Emit_Ldc_I4(0);
            il.Emit(OpCodes.Stind_I4);
            il.Emit_IncreasePointer(locals.DataPointer, sizeof(int)); // data += sizeof(int)
            il.Emit(OpCodes.Br, endOfSubmethodLabel);                 // goto endOfSubmethodLabel

            // Array is not empty branch
            il.MarkLabel(arrayIsNotEmptylabel);
            var lengthVar = locals.GetOrAdd("length",                // var length = value.Length
                                            lil => lil.DeclareLocal(typeof(int)));

            emitLoad(il);
            il.Emit(OpCodes.Ldlen);
            il.Emit(OpCodes.Conv_I4);
            il.Emit(OpCodes.Stloc, lengthVar);
            var sizeVar = locals.GetOrAdd("sizeInBytes",             // var sizeInBytes = length * sizeOfStruct
                                          lil => lil.DeclareLocal(typeof(int)));

            il.Emit(OpCodes.Ldloc, lengthVar);
            il.Emit_Ldc_I4(sizeOfStruct);
            il.Emit(OpCodes.Mul);
            il.Emit(OpCodes.Stloc, sizeVar);
            il.Emit(OpCodes.Ldloc, locals.DataPointer);              // *(int*) data = length
            il.Emit(OpCodes.Ldloc, lengthVar);
            il.Emit(OpCodes.Stind_I4);
            il.Emit_IncreasePointer(locals.DataPointer, sizeof(int)); // data += sizeof(int)
            var arrayPointerVar = il.Emit_PinArray(                   // var pinned arrayPointer = pin(value)
                typeOfStruct, emitLoad);

            il.Emit(OpCodes.Ldloc, locals.DataPointer);              // cpblk(data, (byte*)arrayPointer, sizeInBytes)
            il.Emit(OpCodes.Ldloc, arrayPointerVar);
            il.Emit(OpCodes.Conv_I);
            il.Emit(OpCodes.Ldloc, sizeVar);
            il.Emit(OpCodes.Cpblk);
            il.Emit_UnpinArray(arrayPointerVar);                     // unpin(arrayPointer)
            il.Emit_IncreasePointer(locals.DataPointer, sizeVar);    // data += sizeInBytes
            il.MarkLabel(endOfSubmethodLabel);
        }
Esempio n. 35
0
 public static void EmitEncode(this IEmittingCodec codec, ILGenerator il, ILocalVariableCollection locals, int argIndex)
 {
     codec.EmitEncode(il, locals, lil => lil.Emit_Ldarg(argIndex));
 }