Пример #1
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, 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);
        }
Пример #2
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
        }
Пример #3
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, 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);
        }
Пример #4
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
        }
Пример #5
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
        }
Пример #6
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
        }
        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
        }
        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
        }