public override void DoInterpretStackTypes() { switch (OpCode) { case Code.Add: case Code.Add_Ovf: case Code.Add_Ovf_Un: case Code.Mul: case Code.Mul_Ovf: case Code.Mul_Ovf_Un: case Code.Div: case Code.Div_Un: case Code.Sub: case Code.Sub_Ovf: case Code.Sub_Ovf_Un: case Code.Rem: case Code.Rem_Un: case Code.Xor: case Code.And: case Code.Or: if (StackPushTypes[0] != null) { return; } if (!StackPopTypes.Contains(null)) { // PopTypes set, but PushType not yet, so fill it. if (StackPopTypes[0] == StackPopTypes[1]) { StackPushTypes[0] = StackPopTypes[0]; return; } if (ILOp.IsIntegerBasedType(StackPopTypes[0]) && ILOp.IsIntegerBasedType(StackPopTypes[1])) { StackPushTypes[0] = typeof(int); return; } if (ILOp.IsLongBasedType(StackPopTypes[0]) && ILOp.IsLongBasedType(StackPopTypes[1])) { StackPushTypes[0] = typeof(long); return; } if (ILOp.IsPointer(StackPopTypes[0]) && ILOp.IsPointer(StackPopTypes[1])) { StackPushTypes[0] = typeof(uint *); return; } if ((ILOp.IsPointer(StackPopTypes[0]) && ILOp.IsIntegerBasedType(StackPopTypes[1])) || (ILOp.IsIntegerBasedType(StackPopTypes[0]) && ILOp.IsPointer(StackPopTypes[1]))) { StackPushTypes[0] = typeof(uint *); return; } throw new NotImplementedException(string.Format("{0} on types '{1}' and '{2}' {3} not yet implemented!", OpCode, StackPopTypes[0], StackPopTypes[1], StackPopTypes[1].IsByRef)); } break; case Code.Localloc: StackPushTypes[0] = typeof(void *); return; case Code.Stelem_I2: var xTypeValue = StackPopTypes[0]; if (xTypeValue == null) { return; } if (xTypeValue == typeof(byte) || xTypeValue == typeof(char) || xTypeValue == typeof(short) || xTypeValue == typeof(ushort) || xTypeValue == typeof(int)) { return; } throw new NotImplementedException(String.Format("Stelem_I2 storing type '{0}' is not implemented!", xTypeValue)); case Code.Shl: case Code.Shr: case Code.Shr_Un: xTypeValue = StackPopTypes[1]; var xTypeShift = StackPopTypes[0]; if (xTypeValue == null || xTypeShift == null) { return; } if (xTypeValue == typeof(int) && xTypeShift == typeof(int)) { StackPushTypes[0] = typeof(int); return; } if (xTypeValue == typeof(byte) && xTypeShift == typeof(int)) { StackPushTypes[0] = typeof(int); return; } if (xTypeValue == typeof(long) && xTypeShift == typeof(int)) { StackPushTypes[0] = typeof(long); return; } if (xTypeValue == typeof(IntPtr) && xTypeShift == typeof(int)) { StackPushTypes[0] = typeof(int); return; } if (xTypeValue == typeof(int) && xTypeShift == typeof(IntPtr)) { StackPushTypes[0] = typeof(int); return; } if (xTypeValue == typeof(ushort) && xTypeShift == typeof(int)) { StackPushTypes[0] = typeof(int); return; } if (xTypeValue == typeof(char) && xTypeShift == typeof(int)) { StackPushTypes[0] = typeof(int); return; } if (xTypeValue == typeof(uint) && xTypeShift == typeof(int)) { StackPushTypes[0] = typeof(int); return; } if (xTypeValue == typeof(long) && xTypeShift == typeof(IntPtr)) { StackPushTypes[0] = typeof(long); return; } if (xTypeValue == typeof(IntPtr) && xTypeShift == typeof(IntPtr)) { StackPushTypes[0] = typeof(IntPtr); return; } if (xTypeValue == typeof(IntPtr) && xTypeShift == typeof(IntPtr)) { StackPushTypes[0] = typeof(IntPtr); return; } if (xTypeValue == typeof(ulong) && xTypeShift == typeof(int)) { StackPushTypes[0] = typeof(ulong); return; } if (xTypeValue == typeof(sbyte) && xTypeShift == typeof(int)) { StackPushTypes[0] = typeof(int); return; } if (xTypeValue == typeof(short) && xTypeShift == typeof(int)) { StackPushTypes[0] = typeof(int); return; } if (xTypeValue == typeof(UIntPtr) && xTypeShift == typeof(int)) { StackPushTypes[0] = typeof(UIntPtr); return; } if (xTypeValue == typeof(char *) && xTypeShift == typeof(int)) { StackPushTypes[0] = typeof(char *); return; } throw new NotImplementedException(String.Format("{0} with types {1} and {2} is not implemented!", OpCode, xTypeValue.FullName, xTypeShift.FullName)); case Code.Ldelem_Ref: if (StackPushTypes[0] != null) { return; } var xTypeArray = StackPopTypes[1]; if (xTypeArray == null) { return; } if (!xTypeArray.IsArray) { throw new Exception("Ldelem Array type is not an array (Actual = " + xTypeArray.FullName + ")"); } StackPushTypes[0] = xTypeArray.GetElementType(); break; case Code.Not: case Code.Neg: if (StackPushTypes[0] != null) { return; } if (StackPopTypes[0] != null) { StackPushTypes[0] = StackPopTypes[0]; return; } break; case Code.Dup: if (StackPopTypes[0] != null) { StackPushTypes[0] = StackPopTypes[0]; StackPushTypes[1] = StackPopTypes[0]; return; } return; case Code.Stind_I1: if (!ILOp.IsIntegerBasedType(StackPopTypes[0])) { throw new Exception("Wrong value type: " + StackPopTypes[0].FullName); } if (!ILOp.IsPointer(StackPopTypes[1]) && StackPopTypes[1] != typeof(int)) // can either be pointer or native int { throw new Exception("Wrong Pointer type: " + StackPopTypes[1].FullName); } break; case Code.Stind_I2: if (!ILOp.IsIntegerBasedType(StackPopTypes[0])) { throw new Exception("Wrong value type: " + StackPopTypes[0].FullName); } if (!ILOp.IsPointer(StackPopTypes[1]) && StackPopTypes[1] != typeof(int)) { throw new Exception("Wrong Pointer type: " + StackPopTypes[1].FullName); } break; case Code.Stind_I4: if (!ILOp.IsIntegerBasedType(StackPopTypes[0])) { throw new Exception("Wrong value type: " + StackPopTypes[0].FullName); } if (!ILOp.IsPointer(StackPopTypes[1]) && StackPopTypes[1] != typeof(int)) { throw new Exception("Wrong Pointer type: " + StackPopTypes[1].FullName); } break; case Code.Stind_I8: if (!ILOp.IsLongBasedType(StackPopTypes[0])) { throw new Exception("Wrong value type: " + StackPopTypes[0].FullName); } if (!ILOp.IsPointer(StackPopTypes[1]) && StackPopTypes[1] != typeof(int)) { throw new Exception("Wrong Pointer type: " + StackPopTypes[1].FullName); } break; case Code.Stind_I: if (!ILOp.IsIntegralTypeOrPointer(StackPopTypes[0])) { throw new Exception("Wrong value type: " + StackPopTypes[0].FullName); } if (!ILOp.IsPointer(StackPopTypes[1]) && StackPopTypes[1] != typeof(int)) { throw new Exception("Wrong Pointer type: " + StackPopTypes[1].FullName); } break; case Code.Ldind_Ref: if (StackPushTypes[0] != null) { return; } if (StackPopTypes[0] == null) { return; } if (!StackPopTypes[0].IsByRef && !StackPopTypes[0].IsPointer) { throw new Exception("Invalid ref type: " + StackPopTypes[0].FullName); } if (StackPopTypes[0].IsPointer) { StackPushTypes[0] = typeof(object); } else { StackPushTypes[0] = StackPopTypes[0].GetElementType(); } break; } }
public override void DoInterpretStackTypes() { switch (OpCode) { case Code.Stfld: // pop type 0 is value and pop type 1 is object var expectedType = Value.FieldType; if (expectedType.IsEnum) { expectedType = expectedType.GetEnumUnderlyingType(); } if (StackPopTypes[1] == typeof(void *)) { return; } if (StackPopTypes[1] == expectedType || StackPopTypes[1] == Value.FieldType) { return; } if ((ILOp.IsPointer(Value.FieldType) || ILOp.IsIntegerBasedType(Value.FieldType)) && (ILOp.IsIntegerBasedType(StackPopTypes[1]) || ILOp.IsPointer(StackPopTypes[1]))) { return; } if (expectedType == typeof(bool)) { if (StackPopTypes[1] == typeof(int)) { return; } } if (StackPopTypes[1] == typeof(NullRef)) { return; } if (expectedType.IsAssignableFrom(StackPopTypes[1])) { return; } if (StackPopTypes[0] == null) { return; } if (expectedType.IsAssignableFrom(StackPopTypes[0])) { return; } if (ILOp.IsObject(expectedType) && ILOp.IsObject(StackPopTypes[0])) { return; } if (ILOp.IsPointer(expectedType) && ILOp.IsPointer(StackPopTypes[0])) { return; } if (ILOp.IsIntegerBasedType(expectedType) && ILOp.IsIntegerBasedType(StackPopTypes[0])) { return; } throw new Exception($"Wrong Poptype encountered! (Field Type = {StackPopTypes[0].FullName} expected = {expectedType.FullName})"); case Code.Stsfld: if (StackPopTypes[0] == null) { return; } if (StackPopTypes[0] == typeof(void *)) { return; } expectedType = Value.FieldType; if (expectedType.IsEnum) { expectedType = expectedType.GetEnumUnderlyingType(); } if (StackPopTypes[0] == expectedType || StackPopTypes[0] == Value.FieldType) { return; } if (ILOp.IsIntegerBasedType(expectedType) && ILOp.IsIntegerBasedType(StackPopTypes[0])) { return; } if (ILOp.IsLongBasedType(expectedType) && ILOp.IsLongBasedType(StackPopTypes[0])) { return; } if (expectedType == typeof(bool)) { if (StackPopTypes[0] == typeof(int)) { return; } } if (expectedType.IsAssignableFrom(StackPopTypes[0])) { return; } if (StackPopTypes[0] == typeof(NullRef)) { return; } if ((StackPopTypes[0] == typeof(IntPtr) || StackPopTypes[0] == typeof(UIntPtr)) & expectedType.IsPointer) { return; } throw new Exception("Wrong Poptype encountered! (Type = " + StackPopTypes[0].FullName + ", expected = " + expectedType.FullName + ")"); case Code.Ldfld: if (StackPopTypes[0] == null) { return; } if (!Value.DeclaringType.IsValueType) { return; } if (StackPopTypes[0] == Value.DeclaringType.MakePointerType() || StackPopTypes[0] == Value.DeclaringType.MakeByRefType() || StackPopTypes[0] == typeof(void *) || StackPopTypes[0] == typeof(IntPtr)) { return; } if (StackPopTypes[0] == Value.DeclaringType) { return; } throw new Exception("Wrong Poptype encountered! (Type = " + StackPopTypes[0].FullName + ", expected = " + Value.DeclaringType.FullName + ")"); } }
public override void DoInterpretStackTypes() { // this method is supposed to deduct push types from pop types. Branch ops don't push, but we want to do checks here, // to help verify other code is right switch (OpCode) { case Code.Brtrue: case Code.Brfalse: // check pop types according to ECMA 335 var xPopType = StackPopTypes[0]; if (xPopType == null) { return; } if (ILOp.IsIntegerBasedType(xPopType) || ILOp.IsLongBasedType(xPopType)) { return; } if (xPopType.IsClass) { return; } if (xPopType.IsInterface) { return; } // ECMA apparently sees a boolean on the stack as a native int. We push as boolean, so acccept that as well if (xPopType == typeof(bool)) { return; } throw new Exception("Invalid type in PopTypes! (Type = '" + xPopType.AssemblyQualifiedName + "')"); case Code.Br: case Code.Leave: return; case Code.Blt: case Code.Ble: case Code.Beq: case Code.Bge: case Code.Bgt: case Code.Bge_Un: case Code.Blt_Un: case Code.Ble_Un: case Code.Bne_Un: case Code.Bgt_Un: var xValue1 = StackPopTypes[0]; var xValue2 = StackPopTypes[1]; if (ILOp.IsSameValueType(xValue1, xValue2)) { return; } if ((xValue1.IsClass || xValue1.IsInterface) && (xValue2.IsClass || xValue2.IsInterface)) { return; } throw new Exception(String.Format("Comparing types '{0}' and '{1}' not supported!", xValue1.AssemblyQualifiedName, xValue2.AssemblyQualifiedName)); default: throw new NotImplementedException("Checks for opcode " + OpCode + " not implemented!"); } }