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 }
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 }
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 }
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 }
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); }); }
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); }); }
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 }
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 }
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 }
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 }
public static void EmitEncode(this IEmittingCodec codec, ILGenerator il, ILocalVariableCollection locals, LocalBuilder localVar) { codec.EmitEncode(il, locals, lil => lil.Emit(OpCodes.Ldloc, localVar)); }
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); } }
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 }
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)); }
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 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); }
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 }
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 }
/* 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 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 }
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)); }
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); }
public void EmitEncode(ILGenerator il, ILocalVariableCollection locals, Action<ILGenerator> emitLoad) { il.Emit(OpCodes.Ldloca, locals.DataPointer); emitLoad(il); il.Emit(OpCodes.Call, EncodeMethod); }
protected abstract void EmitDecodeAndStore(ILGenerator il, ILocalVariableCollection locals, LocalBuilder collectionVar, LocalBuilder iVar, bool doNotCheckBounds);
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); }
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); }