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 }
public void EmitLoadDefaultValue(Type type) { if (type == typeof(void)) { return; } if (!type.IsValueType) { Il.Ldnull(); } else { using (var temp = DeclareLocal(type)) { Il.Ldloca(temp); Il.Initobj(type); Il.Ldloc(temp); } } }
/// <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 bool EmitNullChecking(Type type, GroboIL.Label objIsNullLabel) { if (!type.IsValueType) { Il.Dup(); // stack: [obj, obj] Il.Brfalse(objIsNullLabel); // if(obj == null) goto returnDefaultValue; stack: [obj] return(true); } if (type.IsNullable()) { using (var temp = DeclareLocal(type.MakeByRefType())) { Il.Stloc(temp); Il.Ldnull(); Il.Ldloc(temp); EmitHasValueAccess(type); Il.Brfalse(objIsNullLabel); Il.Pop(); Il.Ldloc(temp); } return(true); } return(false); }
public void EmitArithmeticOperation(ExpressionType nodeType, Type resultType, Type leftType, Type rightType, MethodInfo method) { if (!leftType.IsNullable() && !rightType.IsNullable()) { if (method != null) { Il.Call(method); } else { if (leftType.IsStruct()) { throw new InvalidOperationException("Unable to perfrom operation '" + nodeType + "' to a struct of type '" + leftType + "'"); } if (rightType.IsStruct()) { throw new InvalidOperationException("Unable to perfrom operation '" + nodeType + "' to a struct of type '" + rightType + "'"); } EmitOp(Il, nodeType, resultType); } } else { using (var localLeft = DeclareLocal(leftType)) using (var localRight = DeclareLocal(rightType)) { Il.Stloc(localRight); Il.Stloc(localLeft); var returnNullLabel = Il.DefineLabel("returnNull"); if (leftType.IsNullable()) { Il.Ldloca(localLeft); EmitHasValueAccess(leftType); Il.Brfalse(returnNullLabel); } if (rightType.IsNullable()) { Il.Ldloca(localRight); EmitHasValueAccess(rightType); Il.Brfalse(returnNullLabel); } if (!leftType.IsNullable()) { Il.Ldloc(localLeft); } else { Il.Ldloca(localLeft); EmitValueAccess(leftType); } if (!rightType.IsNullable()) { Il.Ldloc(localRight); } else { Il.Ldloca(localRight); EmitValueAccess(rightType); } Type argumentType = resultType.GetGenericArguments()[0]; if (method != null) { Il.Call(method); } else { EmitOp(Il, nodeType, argumentType); } Il.Newobj(resultType.GetConstructor(new[] { argumentType })); var doneLabel = Il.DefineLabel("done"); Il.Br(doneLabel); MarkLabelAndSurroundWithSP(returnNullLabel); EmitLoadDefaultValue(resultType); MarkLabelAndSurroundWithSP(doneLabel); } } }