/// <summary> /// Puts TypeCode.Empty in <c>result</c> if <c>writeEmpty</c> = true and returns /// </summary> public void WriteNull() { var retLabel = Il.DefineLabel("return"); LoadWriteEmpty(); // stack: [writeEmpty] Il.Brfalse(retLabel); // if(!writeEmpty) goto ret; WriteTypeCode(GroBufTypeCode.Empty); Il.MarkLabel(retLabel); Il.Ret(); }
public void AssertTypeCode(GroBufTypeCode expectedTypeCode) { Il.Ldloc(TypeCode); // stack: [typeCode] Il.Ldc_I4((int)expectedTypeCode); // stack: [typeCode, expectedTypeCode] var okLabel = Il.DefineLabel("ok"); Il.Beq(okLabel); SkipValue(); Il.Ret(); Il.MarkLabel(okLabel); }
public void SkipValue() { LoadIndexByRef(); // stack: [ref index] LoadIndex(); // stack: [ref index, index] // todo: сделать switch Il.Ldloc(TypeCode); // stack: [ref index, index, TypeCode] Il.Ldc_I4((int)GroBufTypeCode.DateTimeOld); // stack: [ref index, index, TypeCode, GroBufTypeCode.DateTimeOld] var notDateTimeLabel = Il.DefineLabel("notDateTime"); Il.Bne_Un(notDateTimeLabel); // if(TypeCode != GroBufTypeCode.DateTimeOld) goto notDateTime; stack: [ref index, index] Il.Ldc_I4(8); // stack: [ref index, index, 8] AssertLength(); GoToCurrentLocation(); // stack: [ref index, index, &data[index]] Il.Ldc_I4(4); Il.Add(); Il.Ldind(typeof(int)); // stack: [ref index, index, (int)(&data[index])] Il.Ldc_I4(31); // stack: [ref index, index, (int)&data[index], 31] Il.Shr(true); // stack: [ref index, index, (int)&data[index] >> 31] Il.Ldc_I4(8); // stack: [ref index, index, (int)&data[index] >> 31, 8] Il.Add(); // stack: [ref index, index, (int)&data[index] >> 31 + 8] var increaseLabel = Il.DefineLabel("increase"); Il.Br(increaseLabel); Il.MarkLabel(notDateTimeLabel); LoadField(Context.Lengths); Il.Ldloc(TypeCode); // stack: [ref index, index, lengths, typeCode] Il.Ldelem(typeof(int)); // stack: [ref index, index, lengths[typeCode]] Il.Dup(); // stack: [ref index, index, lengths[typeCode], lengths[typeCode]] Il.Ldc_I4(-1); // stack: [ref index, index, lengths[typeCode], lengths[typeCode], -1] Il.Bne_Un(increaseLabel); // if(lengths[typeCode] != -1) goto increase; Il.Ldc_I4(4); AssertLength(); Il.Pop(); // stack: [ref index, index] Il.Dup(); // stack: [ref index, index, index] LoadData(); // stack: [ref index, index, index, pinnedData] Il.Add(); // stack: [ref index, index, index + pinnedData] Il.Ldind(typeof(uint)); // stack: [ref index, index, *(uint*)(pinnedData + index)] Il.Ldc_I4(4); // stack: [ref index, index, *(uint*)(pinnedData + index), 4] Il.Add(); // stack: [ref index, *(uint*)(pinnedData + index) + 4] Il.MarkLabel(increaseLabel); Il.Dup(); // stack: [ref index, length, length] AssertLength(); // stack: [ref index, length] Il.Add(); // stack: [ref index, index + length] Il.Stind(typeof(int)); // index = index + length }
/// <summary> /// Asserts that the specified number of bytes can be read from <c>data</c> starting at <c>index</c> /// <para></para> /// The number of bytes must be pushed onto the evaluation stack /// </summary> public void AssertLength() { LoadIndex(); // stack: [length, index] Il.Add(); // stack: [length + index] LoadDataLength(); // stack: [length + index, dataLength] var bigEnoughLabel = Il.DefineLabel("bigEnough"); Il.Ble(bigEnoughLabel, true); Il.Ldstr("Unexpected end of data"); var constructor = typeof(DataCorruptedException).GetConstructor(new[] { typeof(string) }); if (constructor == null) { throw new MissingConstructorException(typeof(DataCorruptedException), typeof(string)); } Il.Newobj(constructor); Il.Throw(); Il.MarkLabel(bigEnoughLabel); }
/// <summary> /// Asserts that the specified number of bytes can be written to <c>result</c> starting at <c>index</c> /// <para></para> /// The number of bytes must be pushed onto the evaluation stack /// </summary> public void AssertLength() { LoadIndex(); // stack: [length, index] Il.Add(); // stack: [length + index] LoadResultLength(); // stack: [length + index, resultLength] var bigEnoughLabel = Il.DefineLabel("bigEnough"); Il.Ble(bigEnoughLabel, true); Il.Ldstr("Seems like the object being serialized has been changed during serialization"); var constructor = typeof(InvalidOperationException).GetConstructor(new[] { typeof(string) }); if (constructor == null) { throw new MissingConstructorException(typeof(InvalidOperationException), typeof(string)); } Il.Newobj(constructor); Il.Throw(); Il.MarkLabel(bigEnoughLabel); }
/// <summary> /// Checks TypeCode and throws Exception if it is invalid /// </summary> public void CheckTypeCode() { LoadField(Context.Lengths); Il.Ldloc(TypeCode); // stack: [lengths, typeCode] Il.Ldelem(typeof(int)); // stack: [lengths[typeCode]] var okLabel = Il.DefineLabel("ok"); Il.Brtrue(okLabel); // if(lengths[typeCode] != 0) goto ok; Il.Ldstr("Unknown type code: "); Il.Ldloca(TypeCode); Il.Call(HackHelpers.GetMethodDefinition <int>(x => x.ToString()), typeof(int)); Il.Call(HackHelpers.GetMethodDefinition <string>(s => s + "zzz")); var constructor = typeof(DataCorruptedException).GetConstructor(new[] { typeof(string) }); if (constructor == null) { throw new MissingConstructorException(typeof(DataCorruptedException), typeof(string)); } Il.Newobj(constructor); Il.Throw(); Il.MarkLabel(okLabel); }
public void StoreObject(Type type) { if (Index == null) { return; } if (type.IsValueType) { throw new InvalidOperationException("A reference type expected"); } // Store in array of all references LoadContext(); // stack: [context] Il.Ldfld(ReaderContext.ObjectsField); // stack: [context.objects] var doneLabel = Il.DefineLabel("done"); Il.Brfalse(doneLabel); // if(context.objects == null) goto done; stack: [] LoadContext(); // stack: [context] Il.Ldfld(ReaderContext.ObjectsField); // stack: [context.objects] Il.Ldloc(Index); // stack: [context.objects, index] LoadResult(type); // stack: [context.objects, index, result] Il.Call(HackHelpers.GetMethodDefinition <Dictionary <int, object> >(dict => dict.Add(0, null))); // context.objects.Add(index, result) Il.MarkLabel(doneLabel); }
public void MarkLabelAndSurroundWithSP(GroboIL.Label label) { MarkHiddenSP(); Il.MarkLabel(label); MarkHiddenSP(); }