diff --git a/Users/Matthijs/DebugCompiler/Program.TestCompiler.cs b/Users/Matthijs/DebugCompiler/Program.TestCompiler.cs index 89bf0308d..bb3fc3d46 100644 --- a/Users/Matthijs/DebugCompiler/Program.TestCompiler.cs +++ b/Users/Matthijs/DebugCompiler/Program.TestCompiler.cs @@ -17,7 +17,7 @@ namespace DebugCompiler internal class Program { //public const string CosmosRoot = @"e:\Cosmos"; - public const string CosmosRoot = @"c:\data\sources\cosmos"; + public const string CosmosRoot = @"e:\OpenSOurce\Cosmos"; //public const string CosmosRoot = @"C:\Users\Huge\Documents\Visual Studio 2010\Projects\IL2CPU"; private const string KernelFile = CosmosRoot + @"\Users\Kudzu\Breakpoints\bin\Debug\Playground.Kudzu.BreakpointsKernel.dll"; @@ -50,7 +50,7 @@ namespace DebugCompiler xTask.OnLogException = (m) => { Console.WriteLine("Exception: {0}", m.ToString()); - Console.ReadLine(); + //Console.ReadLine(); }; if (xTask.Execute()) { @@ -66,7 +66,7 @@ namespace DebugCompiler catch (Exception E) { Console.WriteLine(E.ToString()); - Console.ReadLine(); + //Console.ReadLine(); return; } Console.WriteLine("Run took {0}", xSW.Elapsed); diff --git a/source2/IL2CPU/Cosmos.IL2CPU/ILOpCode.cs b/source2/IL2CPU/Cosmos.IL2CPU/ILOpCode.cs index 1913756c3..2e02bf15f 100644 --- a/source2/IL2CPU/Cosmos.IL2CPU/ILOpCode.cs +++ b/source2/IL2CPU/Cosmos.IL2CPU/ILOpCode.cs @@ -375,5 +375,19 @@ namespace Cosmos.IL2CPU { xNextOpCode.InterpretStackTypes(aOpCodes, aStack, ref aSituationChanged, aMaxRecursionDepth - 1); } } + + protected bool IsIntegralType(Type type) + { + return type == typeof(byte) + || type == typeof(sbyte) + || type == typeof(ushort) + || type == typeof(short) + || type == typeof(int) + || type == typeof(uint) + || type == typeof(long) + || type == typeof(ulong) + || type == typeof(char); + + } } } diff --git a/source2/IL2CPU/Cosmos.IL2CPU/ILOpCodes/OpBranch.cs b/source2/IL2CPU/Cosmos.IL2CPU/ILOpCodes/OpBranch.cs index 1cce3af89..58b351411 100644 --- a/source2/IL2CPU/Cosmos.IL2CPU/ILOpCodes/OpBranch.cs +++ b/source2/IL2CPU/Cosmos.IL2CPU/ILOpCodes/OpBranch.cs @@ -141,11 +141,7 @@ namespace Cosmos.IL2CPU.ILOpCodes { { return; } - if (xValue1 == typeof (int) && xValue2 == typeof (int)) - { - return; - } - if (xValue1 == typeof(long) && xValue2 == typeof(long)) + if (IsIntegralType(xValue1) && IsIntegralType(xValue2)) { return; } @@ -172,6 +168,12 @@ namespace Cosmos.IL2CPU.ILOpCodes { { return; } + if (xValue1.IsClass && + xValue2.IsClass) + { + 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!"); @@ -194,13 +196,13 @@ namespace Cosmos.IL2CPU.ILOpCodes { case Code.Bge_Un: case Code.Beq: case Code.Bne_Un: + case Code.Br: base.DoInterpretNextInstructionStackTypes(aOpCodes, new Stack(aStack), ref aSituationChanged, aMaxRecursionDepth); if (Value > Position) { InterpretInstruction(Value, aOpCodes, aStack, ref aSituationChanged, aMaxRecursionDepth); } break; - case Code.Br: case Code.Leave: if (Value > Position) { diff --git a/source2/IL2CPU/Cosmos.IL2CPU/ILOpCodes/OpField.cs b/source2/IL2CPU/Cosmos.IL2CPU/ILOpCodes/OpField.cs index 3ec11b6a4..974626fe6 100644 --- a/source2/IL2CPU/Cosmos.IL2CPU/ILOpCodes/OpField.cs +++ b/source2/IL2CPU/Cosmos.IL2CPU/ILOpCodes/OpField.cs @@ -3,6 +3,8 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Text; +using Cosmos.IL2CPU.X86.IL; +using FieldInfo = System.Reflection.FieldInfo; namespace Cosmos.IL2CPU.ILOpCodes { public class OpField : ILOpCode { @@ -55,34 +57,13 @@ namespace Cosmos.IL2CPU.ILOpCodes { base.DoInitStackAnalysis(aMethod); switch (OpCode) - { - case Code.Stsfld: - StackPopTypes[0] = Value.FieldType; - if (StackPopTypes[0].IsEnum) - { - StackPopTypes[0] = StackPopTypes[0].GetEnumUnderlyingType(); - } - - return; - case Code.Ldsfld: + { case Code.Ldsfld: StackPushTypes[0] = Value.FieldType; if (StackPushTypes[0].IsEnum) { StackPushTypes[0] = StackPushTypes[0].GetEnumUnderlyingType(); } - return; - case Code.Stfld: - //StackPopTypes[0] = Value.FieldType; - //if (StackPopTypes[0].IsEnum) - //{ - // StackPopTypes[0] = StackPopTypes[0].GetEnumUnderlyingType(); - //} - //else if (Value.DeclaringType.IsValueType) - //{ - // StackPopTypes[0] = typeof(void*); - //} - //StackPopTypes[1] = Value.DeclaringType; return; case Code.Ldfld: StackPushTypes[0] = Value.FieldType; @@ -135,6 +116,10 @@ namespace Cosmos.IL2CPU.ILOpCodes { { return; } + if (IsIntegralType(expectedType) && IsIntegralType(StackPopTypes[0])) + { + return; + } if (expectedType == typeof (bool)) { if (StackPopTypes[0] == typeof (int)) @@ -142,7 +127,53 @@ namespace Cosmos.IL2CPU.ILOpCodes { return; } } - throw new Exception("Wrong Poptype encountered! (Type = " + StackPopTypes[0].FullName + ")"); + if (StackPopTypes[0] == typeof(NullRef)) + { + return; + } + if (expectedType.IsAssignableFrom(StackPopTypes[0])) + { + return; + } + throw new Exception("Wrong Poptype encountered! (Type = " + StackPopTypes[0].FullName + ", expected = " + expectedType.FullName + ")"); + case Code.Stsfld: + if (StackPopTypes[0] == null) + { + return; + } + expectedType = Value.FieldType; + if (expectedType.IsEnum) + { + expectedType = expectedType.GetEnumUnderlyingType(); + } + else if (Value.DeclaringType.IsValueType) + { + expectedType = typeof(void*); + } + if (StackPopTypes[0] == expectedType || StackPopTypes[0] == Value.FieldType) + { + return; + } + if (IsIntegralType(expectedType) && IsIntegralType(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; + } + throw new Exception("Wrong Poptype encountered! (Type = " + StackPopTypes[0].FullName + ", expected = " + expectedType.FullName + ")"); } } } diff --git a/source2/IL2CPU/Cosmos.IL2CPU/ILOpCodes/OpNone.cs b/source2/IL2CPU/Cosmos.IL2CPU/ILOpCodes/OpNone.cs index 5c231392a..a7d62dce1 100644 --- a/source2/IL2CPU/Cosmos.IL2CPU/ILOpCodes/OpNone.cs +++ b/source2/IL2CPU/Cosmos.IL2CPU/ILOpCodes/OpNone.cs @@ -138,7 +138,7 @@ namespace Cosmos.IL2CPU.ILOpCodes { case Code.Dup: return 1; case Code.Volatile: - return 1; + return 0; case Code.Endfinally: return 0; default: @@ -264,7 +264,7 @@ namespace Cosmos.IL2CPU.ILOpCodes { case Code.Dup: return 2; case Code.Volatile: - return 1; + return 0; case Code.Endfinally: return 0; default: @@ -283,26 +283,6 @@ namespace Cosmos.IL2CPU.ILOpCodes { StackPopTypes[1] = typeof(void*); return; - case Code.Stind_I1: - StackPopTypes[0] = typeof (sbyte); - StackPopTypes[1] = typeof(void*); - return; - - case Code.Stind_I2: - StackPopTypes[0] = typeof (short); - StackPopTypes[1] = typeof(void*); - return; - - case Code.Stind_I4: - StackPopTypes[0] = typeof (int); - StackPopTypes[1] = typeof(void*); - return; - - case Code.Stind_I8: - StackPopTypes[0] = typeof (long); - StackPopTypes[1] = typeof(void*); - return; - case Code.Ldind_U1: StackPushTypes[0] = typeof (byte); return; @@ -557,6 +537,13 @@ namespace Cosmos.IL2CPU.ILOpCodes { 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))) { @@ -585,6 +572,13 @@ namespace Cosmos.IL2CPU.ILOpCodes { 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(IntPtr)) { StackPushTypes[0] = typeof(uint); @@ -609,6 +603,12 @@ namespace Cosmos.IL2CPU.ILOpCodes { 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); @@ -621,8 +621,23 @@ namespace Cosmos.IL2CPU.ILOpCodes { aSituationChanged = true; return; } - - throw new NotImplementedException(string.Format("Add on types '{0}' and '{1}' not yet implemented!", StackPopTypes[0], StackPopTypes[1])); + 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.Stelem_I2: @@ -680,6 +695,18 @@ namespace Cosmos.IL2CPU.ILOpCodes { 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); @@ -741,7 +768,91 @@ namespace Cosmos.IL2CPU.ILOpCodes { return; } return; + case Code.Stind_I1: + if (StackPopTypes[1] == null || StackPopTypes[0] == null) + { + return; + } + if (StackPopTypes[0] != typeof(sbyte) && + StackPopTypes[0] != typeof(byte)) + { + throw new Exception("Wrong value type: " + StackPopTypes[0].FullName); + } + if (!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 (StackPopTypes[0] != typeof(short) && + StackPopTypes[0] != typeof(ushort) && + StackPopTypes[0] != typeof(int) && + StackPopTypes[0] != typeof(uint) && + StackPopTypes[0] != typeof(char)) + { + throw new Exception("Wrong value type: " + StackPopTypes[0].FullName); + } + if (!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 (StackPopTypes[0] != typeof(int) && + StackPopTypes[0] != typeof(uint)) + { + throw new Exception("Wrong value type: " + StackPopTypes[0].FullName); + } + if (!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 (StackPopTypes[0] != typeof(long) && + StackPopTypes[0] != typeof(ulong)) + { + throw new Exception("Wrong value type: " + StackPopTypes[0].FullName); + } + if (!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) + { + throw new Exception("Invalid ref type: " + StackPopTypes[0].FullName); + } + StackPushTypes[0] = StackPopTypes[0].GetElementType(); + aSituationChanged = true; + break; } } + + private bool IsPointer(Type aPointer) + { + return aPointer.IsPointer || aPointer.IsByRef || aPointer == typeof(IntPtr) || aPointer == typeof(UIntPtr); + } } } diff --git a/source2/IL2CPU/Cosmos.IL2CPU/ILOpCodes/OpSwitch.cs b/source2/IL2CPU/Cosmos.IL2CPU/ILOpCodes/OpSwitch.cs index 53639e8cd..beb15e569 100644 --- a/source2/IL2CPU/Cosmos.IL2CPU/ILOpCodes/OpSwitch.cs +++ b/source2/IL2CPU/Cosmos.IL2CPU/ILOpCodes/OpSwitch.cs @@ -42,11 +42,41 @@ namespace Cosmos.IL2CPU.ILOpCodes { switch (OpCode) { case Code.Switch: - StackPopTypes[0] = typeof(uint); + //StackPopTypes[0] = typeof(uint); break; default: break; } } + + /// + /// Based on updated StackPopTypes, try to update + /// + protected override void DoInterpretStackTypes(ref bool aSituationChanged) + { + base.DoInterpretStackTypes(ref aSituationChanged); + // no switch necessary, there's only 1 instruction using this type. + + if (StackPopTypes[0] == null) + { + return; + } + + if (StackPopTypes[0] == typeof(int) || + StackPopTypes[0] == typeof(byte)) + { + return; + } + throw new Exception("Wrong type: " + StackPopTypes[0].FullName); + } + + protected override void DoInterpretNextInstructionStackTypes(IDictionary aOpCodes, Stack aStack, ref bool aSituationChanged, int aMaxRecursionDepth) + { + base.DoInterpretNextInstructionStackTypes(aOpCodes, new Stack(aStack), ref aSituationChanged, aMaxRecursionDepth); + foreach (var xTarget in BranchLocations) + { + base.InterpretInstruction(xTarget, aOpCodes, new Stack(aStack), ref aSituationChanged, aMaxRecursionDepth); + } + } } } \ No newline at end of file diff --git a/source2/IL2CPU/Cosmos.IL2CPU/ILOpCodes/OpType.cs b/source2/IL2CPU/Cosmos.IL2CPU/ILOpCodes/OpType.cs index 3676cba1a..5be8dbeb6 100644 --- a/source2/IL2CPU/Cosmos.IL2CPU/ILOpCodes/OpType.cs +++ b/source2/IL2CPU/Cosmos.IL2CPU/ILOpCodes/OpType.cs @@ -5,11 +5,13 @@ using System.Reflection; using System.Text; namespace Cosmos.IL2CPU.ILOpCodes { - public class OpType : ILOpCode { + public class OpType: ILOpCode + { public readonly Type Value; public OpType(Code aOpCode, int aPos, int aNextPos, Type aValue, System.Reflection.ExceptionHandlingClause aCurrentExceptionHandler) - : base(aOpCode, aPos, aNextPos, aCurrentExceptionHandler) { + : base(aOpCode, aPos, aNextPos, aCurrentExceptionHandler) + { Value = aValue; } @@ -81,10 +83,9 @@ namespace Cosmos.IL2CPU.ILOpCodes { StackPushTypes[0] = typeof(void*); return; case Code.Box: - StackPopTypes[0] = Value; if (Value.IsPrimitive) { - StackPushTypes[0] = typeof (Box<>).MakeGenericType(Value); + StackPushTypes[0] = typeof(Box<>).MakeGenericType(Value); } else { @@ -103,21 +104,12 @@ namespace Cosmos.IL2CPU.ILOpCodes { StackPushTypes[0] = Value; return; case Code.Isinst: - if (Value.IsGenericType && Value.GetGenericTypeDefinition() == typeof(Nullable<>)) - { - StackPopTypes[0] = typeof(Box<>).MakeGenericType(Value.GetGenericArguments()[0]); - } - else if (Value.IsValueType) - { - StackPopTypes[0] = typeof(Box<>).MakeGenericType(Value); - } - else - { - StackPopTypes[0] = Value; - } + StackPopTypes[0] = typeof(object); + StackPushTypes[0] = typeof(bool); return; case Code.Castclass: - if (Value.IsGenericType && Value.GetGenericTypeDefinition() == typeof(Nullable<>)) + if (Value.IsGenericType && + Value.GetGenericTypeDefinition() == typeof(Nullable<>)) { StackPushTypes[0] = typeof(Box<>).MakeGenericType(Value.GetGenericArguments()[0]); } @@ -134,5 +126,36 @@ namespace Cosmos.IL2CPU.ILOpCodes { break; } } + + /// + /// Based on updated StackPopTypes, try to update + /// + protected override void DoInterpretStackTypes(ref bool aSituationChanged) + { + base.DoInterpretStackTypes(ref aSituationChanged); + + switch (OpCode) + { + case Code.Box: + if (StackPushTypes[0] != null) + { + return; + } + + if (StackPopTypes[0] == null) + { + return; + } + + if (IsIntegralType(StackPopTypes[0]) && + IsIntegralType(Value)) + { + StackPushTypes[0] = typeof(Box<>).MakeGenericType(Value); + aSituationChanged = true; + return; + } + throw new Exception("Wrong poptype: " + StackPopTypes[0].FullName); + } + } } }