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; } }
protected override void DoInterpretStackTypes(ref bool aSituationChanged) { base.DoInterpretStackTypes(ref aSituationChanged); 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] == typeof(bool) && StackPopTypes[1] == typeof(bool)) { StackPushTypes[0] = typeof(bool); aSituationChanged = true; return; } if ((StackPopTypes[0] == typeof(bool) && StackPopTypes[1] == typeof(Int32)) || (StackPopTypes[0] == typeof(Int32) && StackPopTypes[1] == typeof(bool))) { StackPushTypes[0] = typeof(Int32); aSituationChanged = true; return; } if ((StackPopTypes[0] == typeof(IntPtr) && StackPopTypes[1] == typeof(uint *)) || (StackPopTypes[0] == typeof(uint *) && StackPopTypes[1] == typeof(IntPtr))) { StackPushTypes[0] = typeof(uint *); aSituationChanged = true; return; } if ((StackPopTypes[0] == typeof(UIntPtr) && StackPopTypes[1] == typeof(uint *)) || (StackPopTypes[0] == typeof(uint *) && StackPopTypes[1] == typeof(UIntPtr))) { StackPushTypes[0] = typeof(uint *); aSituationChanged = true; return; } if ((StackPopTypes[0] == typeof(uint) && StackPopTypes[1] == typeof(byte *)) || (StackPopTypes[0] == typeof(byte *) && StackPopTypes[1] == typeof(uint))) { StackPushTypes[0] = typeof(byte *); aSituationChanged = true; return; } if ((StackPopTypes[0] == typeof(int) && StackPopTypes[1] == typeof(byte *)) || (StackPopTypes[0] == typeof(byte *) && StackPopTypes[1] == typeof(int))) { StackPushTypes[0] = typeof(byte *); aSituationChanged = true; return; } if ((StackPopTypes[0] == typeof(IntPtr) && StackPopTypes[1] == typeof(byte *)) || (StackPopTypes[0] == typeof(byte *) && StackPopTypes[1] == typeof(IntPtr))) { StackPushTypes[0] = typeof(byte *); aSituationChanged = true; return; } if ((StackPopTypes[0] == typeof(IntPtr) && StackPopTypes[1] == typeof(char *)) || (StackPopTypes[0] == typeof(char *) && StackPopTypes[1] == typeof(IntPtr))) { StackPushTypes[0] = typeof(char *); aSituationChanged = true; return; } if ((StackPopTypes[0] == typeof(UIntPtr) && StackPopTypes[1] == typeof(char *)) || (StackPopTypes[0] == typeof(char *) && StackPopTypes[1] == typeof(UIntPtr))) { StackPushTypes[0] = typeof(char *); aSituationChanged = true; return; } if ((StackPopTypes[0] == typeof(IntPtr) && StackPopTypes[1] == typeof(uint)) || (StackPopTypes[0] == typeof(uint) && StackPopTypes[1] == typeof(IntPtr))) { StackPushTypes[0] = typeof(UIntPtr); aSituationChanged = true; return; } if ((StackPopTypes[0] == typeof(int) && StackPopTypes[1] == typeof(UIntPtr)) || (StackPopTypes[0] == typeof(UIntPtr) && StackPopTypes[1] == typeof(int))) { StackPushTypes[0] = typeof(UIntPtr); aSituationChanged = true; return; } if ((StackPopTypes[0] == typeof(int) && StackPopTypes[1] == typeof(IntPtr)) || (StackPopTypes[0] == typeof(IntPtr) && StackPopTypes[1] == typeof(int))) { StackPushTypes[0] = typeof(IntPtr); aSituationChanged = true; return; } if ((StackPopTypes[0] == typeof(int) && StackPopTypes[1] == typeof(uint)) || (StackPopTypes[0] == typeof(uint) && StackPopTypes[1] == typeof(int))) { StackPushTypes[0] = typeof(int); aSituationChanged = true; return; } if ((StackPopTypes[0] == typeof(short) && StackPopTypes[1] == typeof(ushort)) || (StackPopTypes[0] == typeof(ushort) && StackPopTypes[1] == typeof(short))) { StackPushTypes[0] = typeof(short); aSituationChanged = true; return; } if ((StackPopTypes[0] == typeof(int) && StackPopTypes[1] == typeof(byte)) || (StackPopTypes[0] == typeof(byte) && StackPopTypes[1] == typeof(int))) { StackPushTypes[0] = typeof(int); aSituationChanged = true; return; } if ((StackPopTypes[0] == typeof(int) && StackPopTypes[1] == typeof(short)) || (StackPopTypes[0] == typeof(short) && StackPopTypes[1] == typeof(int))) { StackPushTypes[0] = typeof(int); aSituationChanged = true; return; } if ((StackPopTypes[0] == typeof(long) && StackPopTypes[1] == typeof(ulong)) || (StackPopTypes[0] == typeof(ulong) && StackPopTypes[1] == typeof(long))) { StackPushTypes[0] = typeof(long); aSituationChanged = true; return; } if ((StackPopTypes[0] == typeof(int) && StackPopTypes[1] == typeof(ushort)) || (StackPopTypes[0] == typeof(ushort) && StackPopTypes[1] == typeof(int))) { StackPushTypes[0] = typeof(int); aSituationChanged = true; return; } if ((StackPopTypes[0] == typeof(byte) && StackPopTypes[1] == typeof(uint)) || (StackPopTypes[0] == typeof(uint) && StackPopTypes[1] == typeof(byte))) { StackPushTypes[0] = typeof(int); aSituationChanged = true; return; } if ((StackPopTypes[0] == typeof(ushort) && StackPopTypes[1] == typeof(uint)) || (StackPopTypes[0] == typeof(uint) && StackPopTypes[1] == typeof(ushort))) { StackPushTypes[0] = typeof(uint); aSituationChanged = true; return; } if ((StackPopTypes[0] == typeof(int) && StackPopTypes[1] == typeof(char)) || (StackPopTypes[0] == typeof(char) && StackPopTypes[1] == typeof(int))) { StackPushTypes[0] = typeof(int); aSituationChanged = true; return; } if ((StackPopTypes[0] == typeof(IntPtr) && StackPopTypes[1] == typeof(UIntPtr)) || (StackPopTypes[0] == typeof(UIntPtr) && StackPopTypes[1] == typeof(IntPtr))) { StackPushTypes[0] = typeof(UIntPtr); aSituationChanged = true; return; } if (StackPopTypes[0] == typeof(IntPtr) && StackPopTypes[1] == typeof(IntPtr)) { StackPushTypes[0] = typeof(IntPtr); aSituationChanged = true; return; } if (StackPopTypes[0] == typeof(uint) && StackPopTypes[1] == typeof(uint)) { StackPushTypes[0] = typeof(uint); aSituationChanged = true; return; } if (StackPopTypes[0] == typeof(uint) && StackPopTypes[1] == typeof(char)) { StackPushTypes[0] = typeof(uint); aSituationChanged = true; return; } if (StackPopTypes[0] == typeof(byte) && StackPopTypes[1] == typeof(byte)) { StackPushTypes[0] = typeof(byte); aSituationChanged = true; return; } if (StackPopTypes[0] == typeof(byte) && StackPopTypes[1] == typeof(ushort) || StackPopTypes[0] == typeof(ushort) && StackPopTypes[1] == typeof(byte)) { StackPushTypes[0] = typeof(ushort); aSituationChanged = true; return; } if (StackPopTypes[0] == typeof(int) && StackPopTypes[1] == typeof(int)) { StackPushTypes[0] = typeof(int); aSituationChanged = true; return; } if ((StackPopTypes[0] == typeof(int) && StackPopTypes[1] == typeof(bool)) || (StackPopTypes[0] == typeof(bool) && StackPopTypes[1] == typeof(int))) { StackPushTypes[0] = typeof(int); aSituationChanged = true; return; } if (StackPopTypes[0] == typeof(ushort) && StackPopTypes[1] == typeof(ushort)) { StackPushTypes[0] = typeof(ushort); aSituationChanged = true; return; } //Changed if (StackPopTypes[0] == typeof(short) && StackPopTypes[1] == typeof(short)) { StackPushTypes[0] = typeof(short); aSituationChanged = true; return; } if (StackPopTypes[0] == typeof(long) && StackPopTypes[1] == typeof(long)) { StackPushTypes[0] = typeof(long); aSituationChanged = true; return; } if (StackPopTypes[0] == typeof(ulong) && StackPopTypes[1] == typeof(ulong)) { StackPushTypes[0] = typeof(ulong); aSituationChanged = true; return; } if (StackPopTypes[0] == typeof(Double) && StackPopTypes[1] == typeof(Double)) { StackPushTypes[0] = typeof(Double); aSituationChanged = true; return; } if (StackPopTypes[0] == typeof(Single) && StackPopTypes[1] == typeof(Single)) { StackPushTypes[0] = typeof(Single); aSituationChanged = true; return; } if (StackPopTypes[0] == typeof(Char) && StackPopTypes[1] == typeof(Char)) { StackPushTypes[0] = typeof(Char); aSituationChanged = true; return; } if ((StackPopTypes[0] == typeof(int) && StackPopTypes[1] == typeof(sbyte)) || (StackPopTypes[0] == typeof(sbyte) && StackPopTypes[1] == typeof(int))) { StackPushTypes[0] = typeof(int); aSituationChanged = true; return; } if (StackPopTypes[0] == StackPopTypes[1] && StackPopTypes[0].IsPointer) { StackPushTypes[0] = StackPopTypes[0]; aSituationChanged = true; return; } if (StackPopTypes[0] == typeof(int) && StackPopTypes[1].IsPointer) { StackPushTypes[0] = StackPopTypes[1]; aSituationChanged = true; return; } if ((StackPopTypes[0] == typeof(IntPtr) || StackPopTypes[0] == typeof(UIntPtr)) && StackPopTypes[1].IsPointer) { StackPushTypes[0] = StackPopTypes[1]; aSituationChanged = true; return; } if (OpCode == Code.Add && ((StackPopTypes[0] == typeof(IntPtr) && (StackPopTypes[1].IsPointer || StackPopTypes[1].IsByRef)) || ((StackPopTypes[0].IsPointer || StackPopTypes[0].IsByRef) && StackPopTypes[1] == typeof(IntPtr)))) { if (StackPopTypes[0] == typeof(IntPtr)) { StackPushTypes[0] = StackPopTypes[1]; } else { StackPushTypes[0] = StackPopTypes[0]; } aSituationChanged = true; return; } throw new NotImplementedException(string.Format("{0} on types '{1}' and '{2}' not yet implemented!", OpCode, StackPopTypes[0], StackPopTypes[1])); } break; case Code.Localloc: StackPushTypes[0] = typeof(void *); aSituationChanged = true; 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); aSituationChanged = true; return; } if (xTypeValue == typeof(byte) && xTypeShift == typeof(int)) { StackPushTypes[0] = typeof(int); aSituationChanged = true; return; } if (xTypeValue == typeof(long) && xTypeShift == typeof(int)) { StackPushTypes[0] = typeof(long); aSituationChanged = true; return; } if (xTypeValue == typeof(IntPtr) && xTypeShift == typeof(int)) { StackPushTypes[0] = typeof(int); aSituationChanged = true; return; } if (xTypeValue == typeof(int) && xTypeShift == typeof(IntPtr)) { StackPushTypes[0] = typeof(int); aSituationChanged = true; return; } if (xTypeValue == typeof(ushort) && xTypeShift == typeof(int)) { StackPushTypes[0] = typeof(int); aSituationChanged = true; return; } if (xTypeValue == typeof(char) && xTypeShift == typeof(int)) { StackPushTypes[0] = typeof(int); aSituationChanged = true; return; } if (xTypeValue == typeof(uint) && xTypeShift == typeof(int)) { StackPushTypes[0] = typeof(int); aSituationChanged = true; return; } if (xTypeValue == typeof(long) && xTypeShift == typeof(IntPtr)) { StackPushTypes[0] = typeof(long); aSituationChanged = true; return; } if (xTypeValue == typeof(IntPtr) && xTypeShift == typeof(IntPtr)) { StackPushTypes[0] = typeof(IntPtr); aSituationChanged = true; return; } if (xTypeValue == typeof(IntPtr) && xTypeShift == typeof(IntPtr)) { StackPushTypes[0] = typeof(IntPtr); aSituationChanged = true; return; } if (xTypeValue == typeof(ulong) && xTypeShift == typeof(int)) { StackPushTypes[0] = typeof(ulong); aSituationChanged = true; return; } if (xTypeValue == typeof(sbyte) && xTypeShift == typeof(int)) { StackPushTypes[0] = typeof(int); aSituationChanged = true; return; } if (xTypeValue == typeof(short) && xTypeShift == typeof(int)) { StackPushTypes[0] = typeof(int); aSituationChanged = true; 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(); aSituationChanged = true; break; case Code.Not: case Code.Neg: if (StackPushTypes[0] != null) { return; } if (StackPopTypes[0] != null) { StackPushTypes[0] = StackPopTypes[0]; aSituationChanged = true; return; } break; case Code.Dup: if (StackPushTypes[0] != null && StackPushTypes[1] != null) { return; } if (StackPopTypes[0] != null) { StackPushTypes[0] = StackPopTypes[0]; StackPushTypes[1] = StackPopTypes[0]; aSituationChanged = true; return; } return; case Code.Stind_I1: if (StackPopTypes[1] == null || StackPopTypes[0] == null) { return; } if (!ILOp.IsIntegralType(StackPopTypes[0])) { throw new Exception("Wrong value type: " + StackPopTypes[0].FullName); } if (!ILOp.IsPointer(StackPopTypes[1])) { throw new Exception("Wrong Pointer type: " + StackPopTypes[1].FullName); } break; case Code.Stind_I2: if (StackPopTypes[1] == null || StackPopTypes[0] == null) { return; } if (!ILOp.IsIntegralType(StackPopTypes[0])) { throw new Exception("Wrong value type: " + StackPopTypes[0].FullName); } if (!ILOp.IsPointer(StackPopTypes[1])) { throw new Exception("Wrong Pointer type: " + StackPopTypes[1].FullName); } break; case Code.Stind_I4: if (StackPopTypes[1] == null || StackPopTypes[0] == null) { return; } if (!ILOp.IsIntegralType(StackPopTypes[0])) { throw new Exception("Wrong value type: " + StackPopTypes[0].FullName); } if (!ILOp.IsPointer(StackPopTypes[1])) { throw new Exception("Wrong Pointer type: " + StackPopTypes[1].FullName); } break; case Code.Stind_I8: if (StackPopTypes[1] == null || StackPopTypes[0] == null) { return; } if (!ILOp.IsIntegralType(StackPopTypes[0])) { throw new Exception("Wrong value type: " + StackPopTypes[0].FullName); } if (!ILOp.IsPointer(StackPopTypes[1])) { throw new Exception("Wrong Pointer type: " + StackPopTypes[1].FullName); } break; case Code.Stind_I: if (StackPopTypes[1] == null || StackPopTypes[0] == null) { return; } if (!ILOp.IsIntegralTypeOrPointer(StackPopTypes[0])) { throw new Exception("Wrong value type: " + StackPopTypes[0].FullName); } if (!ILOp.IsPointer(StackPopTypes[1])) { 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(); } aSituationChanged = true; break; } }
protected override void DoInterpretStackTypes(ref bool aSituationChanged) { base.DoInterpretStackTypes(ref aSituationChanged); // 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.IsIntegralType(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 (xValue1 == null || xValue2 == null) { return; } if (ILOp.IsIntegralTypeOrPointer(xValue1) && ILOp.IsIntegralTypeOrPointer(xValue2)) { return; } if (xValue1 == typeof(float) && xValue2 == typeof(float)) { return; } if (xValue1 == typeof(double) && xValue2 == typeof(double)) { return; } if (xValue1 == typeof(IntPtr) && xValue2 == typeof(IntPtr)) { return; } if (xValue1 == typeof(bool) && xValue2 == typeof(bool)) { return; } if ((xValue1 == typeof(int) && xValue2 == typeof(IntPtr)) || (xValue1 == typeof(IntPtr) && xValue2 == typeof(int))) { return; } if ((xValue1 == typeof(UIntPtr) && xValue2 == typeof(byte *)) || (xValue1 == typeof(byte *) && xValue2 == typeof(UIntPtr))) { return; } if ((xValue1 == typeof(long) && xValue2 == typeof(ulong)) || (xValue1 == typeof(ulong) && xValue2 == typeof(long))) { return; } if ((xValue1 == typeof(int) && xValue2 == typeof(bool)) || (xValue1 == typeof(bool) && xValue2 == typeof(int))) { 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!"); } }