diff --git a/source/Cosmos.IL2CPU/ILOpCode.cs b/source/Cosmos.IL2CPU/ILOpCode.cs index fe933ac59..65a987e3e 100644 --- a/source/Cosmos.IL2CPU/ILOpCode.cs +++ b/source/Cosmos.IL2CPU/ILOpCode.cs @@ -5,489 +5,516 @@ using System.Linq; using System.Text; using SR = System.Reflection; -namespace Cosmos.IL2CPU { - // ILOpcode represents the opcode during for scanning. - // Do not: - // Include reference to ILOp, the scanner should do that - // Include referense to System.Reflection.Emit, this is metadata - // only needed by reader and not ILOpCode - public abstract class ILOpCode { - - public enum Code : ushort { - #region Values - Nop = 0x0000, - Break = 0x0001, - Ldarg_0 = 0x0002, - Ldarg_1 = 0x0003, - Ldarg_2 = 0x0004, - Ldarg_3 = 0x0005, - Ldloc_0 = 0x0006, - Ldloc_1 = 0x0007, - Ldloc_2 = 0x0008, - Ldloc_3 = 0x0009, - Stloc_0 = 0x000A, - Stloc_1 = 0x000B, - Stloc_2 = 0x000C, - Stloc_3 = 0x000D, - Ldarg_S = 0x000E, - Ldarga_S = 0x000F, - Starg_S = 0x0010, - Ldloc_S = 0x0011, - Ldloca_S = 0x0012, - Stloc_S = 0x0013, - Ldnull = 0x0014, - Ldc_I4_M1 = 0x0015, - Ldc_I4_0 = 0x0016, - Ldc_I4_1 = 0x0017, - Ldc_I4_2 = 0x0018, - Ldc_I4_3 = 0x0019, - Ldc_I4_4 = 0x001A, - Ldc_I4_5 = 0x001B, - Ldc_I4_6 = 0x001C, - Ldc_I4_7 = 0x001D, - Ldc_I4_8 = 0x001E, - Ldc_I4_S = 0x001F, - Ldc_I4 = 0x0020, - Ldc_I8 = 0x0021, - Ldc_R4 = 0x0022, - Ldc_R8 = 0x0023, - Dup = 0x0025, - Pop = 0x0026, - Jmp = 0x0027, - Call = 0x0028, - Calli = 0x0029, - Ret = 0x002A, - Br_S = 0x002B, - Brfalse_S = 0x002C, - Brtrue_S = 0x002D, - Beq_S = 0x002E, - Bge_S = 0x002F, - Bgt_S = 0x0030, - Ble_S = 0x0031, - Blt_S = 0x0032, - Bne_Un_S = 0x0033, - Bge_Un_S = 0x0034, - Bgt_Un_S = 0x0035, - Ble_Un_S = 0x0036, - Blt_Un_S = 0x0037, - Br = 0x0038, - Brfalse = 0x0039, - Brtrue = 0x003A, - Beq = 0x003B, - Bge = 0x003C, - Bgt = 0x003D, - Ble = 0x003E, - Blt = 0x003F, - Bne_Un = 0x0040, - Bge_Un = 0x0041, - Bgt_Un = 0x0042, - Ble_Un = 0x0043, - Blt_Un = 0x0044, - Switch = 0x0045, - Ldind_I1 = 0x0046, - Ldind_U1 = 0x0047, - Ldind_I2 = 0x0048, - Ldind_U2 = 0x0049, - Ldind_I4 = 0x004A, - Ldind_U4 = 0x004B, - Ldind_I8 = 0x004C, - Ldind_I = 0x004D, - Ldind_R4 = 0x004E, - Ldind_R8 = 0x004F, - Ldind_Ref = 0x0050, - Stind_Ref = 0x0051, - Stind_I1 = 0x0052, - Stind_I2 = 0x0053, - Stind_I4 = 0x0054, - Stind_I8 = 0x0055, - Stind_R4 = 0x0056, - Stind_R8 = 0x0057, - Add = 0x0058, - Sub = 0x0059, - Mul = 0x005A, - Div = 0x005B, - Div_Un = 0x005C, - Rem = 0x005D, - Rem_Un = 0x005E, - And = 0x005F, - Or = 0x0060, - Xor = 0x0061, - Shl = 0x0062, - Shr = 0x0063, - Shr_Un = 0x0064, - Neg = 0x0065, - Not = 0x0066, - Conv_I1 = 0x0067, - Conv_I2 = 0x0068, - Conv_I4 = 0x0069, - Conv_I8 = 0x006A, - Conv_R4 = 0x006B, - Conv_R8 = 0x006C, - Conv_U4 = 0x006D, - Conv_U8 = 0x006E, - Callvirt = 0x006F, - Cpobj = 0x0070, - Ldobj = 0x0071, - Ldstr = 0x0072, - Newobj = 0x0073, - Castclass = 0x0074, - Isinst = 0x0075, - Conv_R_Un = 0x0076, - Unbox = 0x0079, - Throw = 0x007A, - Ldfld = 0x007B, - Ldflda = 0x007C, - Stfld = 0x007D, - Ldsfld = 0x007E, - Ldsflda = 0x007F, - Stsfld = 0x0080, - Stobj = 0x0081, - Conv_Ovf_I1_Un = 0x0082, - Conv_Ovf_I2_Un = 0x0083, - Conv_Ovf_I4_Un = 0x0084, - Conv_Ovf_I8_Un = 0x0085, - Conv_Ovf_U1_Un = 0x0086, - Conv_Ovf_U2_Un = 0x0087, - Conv_Ovf_U4_Un = 0x0088, - Conv_Ovf_U8_Un = 0x0089, - Conv_Ovf_I_Un = 0x008A, - Conv_Ovf_U_Un = 0x008B, - Box = 0x008C, - Newarr = 0x008D, - Ldlen = 0x008E, - Ldelema = 0x008F, - Ldelem_I1 = 0x0090, - Ldelem_U1 = 0x0091, - Ldelem_I2 = 0x0092, - Ldelem_U2 = 0x0093, - Ldelem_I4 = 0x0094, - Ldelem_U4 = 0x0095, - Ldelem_I8 = 0x0096, - Ldelem_I = 0x0097, - Ldelem_R4 = 0x0098, - Ldelem_R8 = 0x0099, - Ldelem_Ref = 0x009A, - Stelem_I = 0x009B, - Stelem_I1 = 0x009C, - Stelem_I2 = 0x009D, - Stelem_I4 = 0x009E, - Stelem_I8 = 0x009F, - Stelem_R4 = 0x00A0, - Stelem_R8 = 0x00A1, - Stelem_Ref = 0x00A2, - Ldelem = 0x00A3, - Stelem = 0x00A4, - Unbox_Any = 0x00A5, - Conv_Ovf_I1 = 0x00B3, - Conv_Ovf_U1 = 0x00B4, - Conv_Ovf_I2 = 0x00B5, - Conv_Ovf_U2 = 0x00B6, - Conv_Ovf_I4 = 0x00B7, - Conv_Ovf_U4 = 0x00B8, - Conv_Ovf_I8 = 0x00B9, - Conv_Ovf_U8 = 0x00BA, - Refanyval = 0x00C2, - Ckfinite = 0x00C3, - Mkrefany = 0x00C6, - Ldtoken = 0x00D0, - Conv_U2 = 0x00D1, - Conv_U1 = 0x00D2, - Conv_I = 0x00D3, - Conv_Ovf_I = 0x00D4, - Conv_Ovf_U = 0x00D5, - Add_Ovf = 0x00D6, - Add_Ovf_Un = 0x00D7, - Mul_Ovf = 0x00D8, - Mul_Ovf_Un = 0x00D9, - Sub_Ovf = 0x00DA, - Sub_Ovf_Un = 0x00DB, - Endfinally = 0x00DC, - Leave = 0x00DD, - Leave_S = 0x00DE, - Stind_I = 0x00DF, - Conv_U = 0x00E0, - Prefix7 = 0x00F8, - Prefix6 = 0x00F9, - Prefix5 = 0x00FA, - Prefix4 = 0x00FB, - Prefix3 = 0x00FC, - Prefix2 = 0x00FD, - Prefix1 = 0x00FE, - Prefixref = 0x00FF, - Arglist = 0xFE00, - Ceq = 0xFE01, - Cgt = 0xFE02, - Cgt_Un = 0xFE03, - Clt = 0xFE04, - Clt_Un = 0xFE05, - Ldftn = 0xFE06, - Ldvirtftn = 0xFE07, - Ldarg = 0xFE09, - Ldarga = 0xFE0A, - Starg = 0xFE0B, - Ldloc = 0xFE0C, - Ldloca = 0xFE0D, - Stloc = 0xFE0E, - Localloc = 0xFE0F, - Endfilter = 0xFE11, - Unaligned = 0xFE12, - Volatile = 0xFE13, - Tailcall = 0xFE14, - Initobj = 0xFE15, - Constrained = 0xFE16, - Cpblk = 0xFE17, - Initblk = 0xFE18, - Rethrow = 0xFE1A, - Sizeof = 0xFE1C, - Refanytype = 0xFE1D, - Readonly = 0xFE1E - #endregion - } - - public readonly Code OpCode; - // Op offset within method. Used for labels etc in assembly. - public readonly int Position; - // position of the next instruction - public readonly int NextPosition; - - public readonly SR.ExceptionHandlingClause CurrentExceptionHandler; - - protected ILOpCode(Code aOpCode, int aPos, int aNextPos, SR.ExceptionHandlingClause aCurrentExceptionHandler) { - OpCode = aOpCode; - Position = aPos; - NextPosition = aNextPos; - CurrentExceptionHandler = aCurrentExceptionHandler; - } - - public override string ToString() +namespace Cosmos.IL2CPU +{ + // ILOpcode represents the opcode during for scanning. + // Do not: + // Include reference to ILOp, the scanner should do that + // Include referense to System.Reflection.Emit, this is metadata + // only needed by reader and not ILOpCode + public abstract class ILOpCode { - // leave here, makes easier debugging the compiler. Compiler will - // show for example "IL_0001: ldstr" instead of just ILOpCode - return String.Format("IL_{0}: {1}", Position.ToString("X4"), OpCode); - } - - /// - /// Returns the number of items popped from the stack. This is the logical stack, not physical items. - /// So a 100byte struct is 1 pop, even though it might be multiple 32-bit or 64-bit words on the stack. - /// - /// - public abstract int GetNumberOfStackPops(SR.MethodBase aMethod); - - /// - /// Returns the number of items pushed to the stack. This is the logical stack, not physical items. - /// So a 100byte struct is 1 pop, even though it might be multiple 32-bit or 64-bit words on the stack. - /// - /// - public abstract int GetNumberOfStackPushes(SR.MethodBase aMethod); - - public Type[] StackPopTypes { - get; - private set; - } - - public Type[] StackPushTypes - { - get; - private set; - } - - internal void InitStackAnalysis(SR.MethodBase aMethod) - { - StackPopTypes = new Type[GetNumberOfStackPops(aMethod)]; - StackPushTypes = new Type[GetNumberOfStackPushes(aMethod)]; - DoInitStackAnalysis(aMethod); - } - - protected virtual void DoInitStackAnalysis(SR.MethodBase aMethod) - { - } - - - /// - /// Gets set to true on first interpreter processing. Is used for loop detection - /// - internal bool Processed = false; - - public uint? StackOffsetBeforeExecution = null; - - public void InterpretStackTypes(IDictionary aOpCodes, Stack aStack, ref bool aSituationChanged, int aMaxRecursionDepth) - { - if (Processed) - { - ILInterpretationDebugLine(() => String.Format("{0} skipped for reinterpretation", this)); - return; - } - Processed = true; - ILInterpretationDebugLine(() => - { - var sb = new StringBuilder(); - sb.AppendFormat("Interpreting {0}. StackCount = {1}. Contents: ", this, aStack.Count); - foreach (var item in aStack) - { - if (item == null) - { - sb.Append("**NULL**, "); - } - else - { - sb.AppendFormat("{0}, ", item.FullName); - } - } - return sb.ToString().Trim(',', ' '); - }); - if (aMaxRecursionDepth == 0) - { - throw new Exception("Safety Error: MaxRecursionDepth reached!"); - } - - if (StackOffsetBeforeExecution == null) - { - StackOffsetBeforeExecution = 0; - foreach (var item in aStack) + public enum Code : ushort { - if (item == null) - { - StackOffsetBeforeExecution = null; - break; - } - StackOffsetBeforeExecution += ILOp.Align(ILOp.SizeOfType(item), 4); - } - } + #region Values - // if current instruction is the first instruction of a catch statement, "push" the exception type now - if (CurrentExceptionHandler != null && - CurrentExceptionHandler.HandlerOffset == Position) - { - if (CurrentExceptionHandler.Flags != SR.ExceptionHandlingClauseOptions.Finally) + Nop = 0x0000, + Break = 0x0001, + Ldarg_0 = 0x0002, + Ldarg_1 = 0x0003, + Ldarg_2 = 0x0004, + Ldarg_3 = 0x0005, + Ldloc_0 = 0x0006, + Ldloc_1 = 0x0007, + Ldloc_2 = 0x0008, + Ldloc_3 = 0x0009, + Stloc_0 = 0x000A, + Stloc_1 = 0x000B, + Stloc_2 = 0x000C, + Stloc_3 = 0x000D, + Ldarg_S = 0x000E, + Ldarga_S = 0x000F, + Starg_S = 0x0010, + Ldloc_S = 0x0011, + Ldloca_S = 0x0012, + Stloc_S = 0x0013, + Ldnull = 0x0014, + Ldc_I4_M1 = 0x0015, + Ldc_I4_0 = 0x0016, + Ldc_I4_1 = 0x0017, + Ldc_I4_2 = 0x0018, + Ldc_I4_3 = 0x0019, + Ldc_I4_4 = 0x001A, + Ldc_I4_5 = 0x001B, + Ldc_I4_6 = 0x001C, + Ldc_I4_7 = 0x001D, + Ldc_I4_8 = 0x001E, + Ldc_I4_S = 0x001F, + Ldc_I4 = 0x0020, + Ldc_I8 = 0x0021, + Ldc_R4 = 0x0022, + Ldc_R8 = 0x0023, + Dup = 0x0025, + Pop = 0x0026, + Jmp = 0x0027, + Call = 0x0028, + Calli = 0x0029, + Ret = 0x002A, + Br_S = 0x002B, + Brfalse_S = 0x002C, + Brtrue_S = 0x002D, + Beq_S = 0x002E, + Bge_S = 0x002F, + Bgt_S = 0x0030, + Ble_S = 0x0031, + Blt_S = 0x0032, + Bne_Un_S = 0x0033, + Bge_Un_S = 0x0034, + Bgt_Un_S = 0x0035, + Ble_Un_S = 0x0036, + Blt_Un_S = 0x0037, + Br = 0x0038, + Brfalse = 0x0039, + Brtrue = 0x003A, + Beq = 0x003B, + Bge = 0x003C, + Bgt = 0x003D, + Ble = 0x003E, + Blt = 0x003F, + Bne_Un = 0x0040, + Bge_Un = 0x0041, + Bgt_Un = 0x0042, + Ble_Un = 0x0043, + Blt_Un = 0x0044, + Switch = 0x0045, + Ldind_I1 = 0x0046, + Ldind_U1 = 0x0047, + Ldind_I2 = 0x0048, + Ldind_U2 = 0x0049, + Ldind_I4 = 0x004A, + Ldind_U4 = 0x004B, + Ldind_I8 = 0x004C, + Ldind_I = 0x004D, + Ldind_R4 = 0x004E, + Ldind_R8 = 0x004F, + Ldind_Ref = 0x0050, + Stind_Ref = 0x0051, + Stind_I1 = 0x0052, + Stind_I2 = 0x0053, + Stind_I4 = 0x0054, + Stind_I8 = 0x0055, + Stind_R4 = 0x0056, + Stind_R8 = 0x0057, + Add = 0x0058, + Sub = 0x0059, + Mul = 0x005A, + Div = 0x005B, + Div_Un = 0x005C, + Rem = 0x005D, + Rem_Un = 0x005E, + And = 0x005F, + Or = 0x0060, + Xor = 0x0061, + Shl = 0x0062, + Shr = 0x0063, + Shr_Un = 0x0064, + Neg = 0x0065, + Not = 0x0066, + Conv_I1 = 0x0067, + Conv_I2 = 0x0068, + Conv_I4 = 0x0069, + Conv_I8 = 0x006A, + Conv_R4 = 0x006B, + Conv_R8 = 0x006C, + Conv_U4 = 0x006D, + Conv_U8 = 0x006E, + Callvirt = 0x006F, + Cpobj = 0x0070, + Ldobj = 0x0071, + Ldstr = 0x0072, + Newobj = 0x0073, + Castclass = 0x0074, + Isinst = 0x0075, + Conv_R_Un = 0x0076, + Unbox = 0x0079, + Throw = 0x007A, + Ldfld = 0x007B, + Ldflda = 0x007C, + Stfld = 0x007D, + Ldsfld = 0x007E, + Ldsflda = 0x007F, + Stsfld = 0x0080, + Stobj = 0x0081, + Conv_Ovf_I1_Un = 0x0082, + Conv_Ovf_I2_Un = 0x0083, + Conv_Ovf_I4_Un = 0x0084, + Conv_Ovf_I8_Un = 0x0085, + Conv_Ovf_U1_Un = 0x0086, + Conv_Ovf_U2_Un = 0x0087, + Conv_Ovf_U4_Un = 0x0088, + Conv_Ovf_U8_Un = 0x0089, + Conv_Ovf_I_Un = 0x008A, + Conv_Ovf_U_Un = 0x008B, + Box = 0x008C, + Newarr = 0x008D, + Ldlen = 0x008E, + Ldelema = 0x008F, + Ldelem_I1 = 0x0090, + Ldelem_U1 = 0x0091, + Ldelem_I2 = 0x0092, + Ldelem_U2 = 0x0093, + Ldelem_I4 = 0x0094, + Ldelem_U4 = 0x0095, + Ldelem_I8 = 0x0096, + Ldelem_I = 0x0097, + Ldelem_R4 = 0x0098, + Ldelem_R8 = 0x0099, + Ldelem_Ref = 0x009A, + Stelem_I = 0x009B, + Stelem_I1 = 0x009C, + Stelem_I2 = 0x009D, + Stelem_I4 = 0x009E, + Stelem_I8 = 0x009F, + Stelem_R4 = 0x00A0, + Stelem_R8 = 0x00A1, + Stelem_Ref = 0x00A2, + Ldelem = 0x00A3, + Stelem = 0x00A4, + Unbox_Any = 0x00A5, + Conv_Ovf_I1 = 0x00B3, + Conv_Ovf_U1 = 0x00B4, + Conv_Ovf_I2 = 0x00B5, + Conv_Ovf_U2 = 0x00B6, + Conv_Ovf_I4 = 0x00B7, + Conv_Ovf_U4 = 0x00B8, + Conv_Ovf_I8 = 0x00B9, + Conv_Ovf_U8 = 0x00BA, + Refanyval = 0x00C2, + Ckfinite = 0x00C3, + Mkrefany = 0x00C6, + Ldtoken = 0x00D0, + Conv_U2 = 0x00D1, + Conv_U1 = 0x00D2, + Conv_I = 0x00D3, + Conv_Ovf_I = 0x00D4, + Conv_Ovf_U = 0x00D5, + Add_Ovf = 0x00D6, + Add_Ovf_Un = 0x00D7, + Mul_Ovf = 0x00D8, + Mul_Ovf_Un = 0x00D9, + Sub_Ovf = 0x00DA, + Sub_Ovf_Un = 0x00DB, + Endfinally = 0x00DC, + Leave = 0x00DD, + Leave_S = 0x00DE, + Stind_I = 0x00DF, + Conv_U = 0x00E0, + Prefix7 = 0x00F8, + Prefix6 = 0x00F9, + Prefix5 = 0x00FA, + Prefix4 = 0x00FB, + Prefix3 = 0x00FC, + Prefix2 = 0x00FD, + Prefix1 = 0x00FE, + Prefixref = 0x00FF, + Arglist = 0xFE00, + Ceq = 0xFE01, + Cgt = 0xFE02, + Cgt_Un = 0xFE03, + Clt = 0xFE04, + Clt_Un = 0xFE05, + Ldftn = 0xFE06, + Ldvirtftn = 0xFE07, + Ldarg = 0xFE09, + Ldarga = 0xFE0A, + Starg = 0xFE0B, + Ldloc = 0xFE0C, + Ldloca = 0xFE0D, + Stloc = 0xFE0E, + Localloc = 0xFE0F, + Endfilter = 0xFE11, + Unaligned = 0xFE12, + Volatile = 0xFE13, + Tailcall = 0xFE14, + Initobj = 0xFE15, + Constrained = 0xFE16, + Cpblk = 0xFE17, + Initblk = 0xFE18, + Rethrow = 0xFE1A, + Sizeof = 0xFE1C, + Refanytype = 0xFE1D, + Readonly = 0xFE1E + + #endregion + } + + public readonly Code OpCode; + + // Op offset within method. Used for labels etc in assembly. + public readonly int Position; + + // position of the next instruction + public readonly int NextPosition; + + public readonly SR.ExceptionHandlingClause CurrentExceptionHandler; + + protected ILOpCode(Code aOpCode, int aPos, int aNextPos, SR.ExceptionHandlingClause aCurrentExceptionHandler) { - aStack.Push(CurrentExceptionHandler.CatchType); + OpCode = aOpCode; + Position = aPos; + NextPosition = aNextPos; + CurrentExceptionHandler = aCurrentExceptionHandler; } - } - if (StackPopTypes.Length > aStack.Count) - { - throw new Exception(String.Format("OpCode {0} tries to pop more stuff from analytical stack than there is!", this)); - } - - for (int i = 0; i < StackPopTypes.Length; i++) - { - var xActualStackItem = aStack.ElementAt(i); - if (xActualStackItem == null) + public override string ToString() { - continue; + // leave here, makes easier debugging the compiler. Compiler will + // show for example "IL_0001: ldstr" instead of just ILOpCode + return String.Format("IL_{0}: {1}", Position.ToString("X4"), OpCode); } - if (StackPopTypes[i] == null) + + /// + /// Returns the number of items popped from the stack. This is the logical stack, not physical items. + /// So a 100byte struct is 1 pop, even though it might be multiple 32-bit or 64-bit words on the stack. + /// + /// + public abstract int GetNumberOfStackPops(SR.MethodBase aMethod); + + /// + /// Returns the number of items pushed to the stack. This is the logical stack, not physical items. + /// So a 100byte struct is 1 pop, even though it might be multiple 32-bit or 64-bit words on the stack. + /// + /// + public abstract int GetNumberOfStackPushes(SR.MethodBase aMethod); + + public Type[] StackPopTypes { get; private set; } + + public Type[] StackPushTypes { get; private set; } + + internal void InitStackAnalysis(SR.MethodBase aMethod) { - StackPopTypes[i] = xActualStackItem; - aSituationChanged = true; + StackPopTypes = new Type[GetNumberOfStackPops(aMethod)]; + StackPushTypes = new Type[GetNumberOfStackPushes(aMethod)]; + DoInitStackAnalysis(aMethod); } - if (StackPopTypes[i] != xActualStackItem - && !StackPopTypes[i].IsAssignableFrom(xActualStackItem) - && !((StackPopTypes[i].IsPointer || StackPopTypes[i].IsByRef) && (xActualStackItem.IsPointer || xActualStackItem.IsByRef))) + + protected virtual void DoInitStackAnalysis(SR.MethodBase aMethod) { - throw new Exception(String.Format("OpCode {0} tries to pop item at stack position {1} with type {2}, but actual type is {3}", - this, i, StackPopTypes[i], xActualStackItem)); } - } - foreach (var xPopItem in StackPopTypes) - { - aStack.Pop(); - } - try - { - DoInterpretStackTypes(ref aSituationChanged); - } - catch (Exception E) - { - throw new Exception("Error interpreting stacktypes for " + this, E); - } - foreach (var xPushItem in StackPushTypes) - { - aStack.Push(xPushItem); - } - DoInterpretNextInstructionStackTypes(aOpCodes, aStack, ref aSituationChanged, aMaxRecursionDepth); + + /// + /// Gets set to true on first interpreter processing. Is used for loop detection + /// + internal bool Processed = false; + + public uint? StackOffsetBeforeExecution = null; + + public void InterpretStackTypes( + IDictionary aOpCodes, + Stack aStack, + ref bool aSituationChanged, + int aMaxRecursionDepth) + { + if (Processed) + { + ILInterpretationDebugLine(() => String.Format("{0} skipped for reinterpretation", this)); + return; + } + Processed = true; + ILInterpretationDebugLine( + () => + { + var sb = new StringBuilder(); + sb.AppendFormat("Interpreting {0}. StackCount = {1}. Contents: ", this, aStack.Count); + foreach (var item in aStack) + { + if (item == null) + { + sb.Append("**NULL**, "); + } + else + { + sb.AppendFormat("{0}, ", item.FullName); + } + } + return sb.ToString().Trim(',', ' '); + }); + if (aMaxRecursionDepth == 0) + { + throw new Exception("Safety Error: MaxRecursionDepth reached!"); + } + + if (StackOffsetBeforeExecution == null) + { + StackOffsetBeforeExecution = 0; + foreach (var item in aStack) + { + if (item == null) + { + StackOffsetBeforeExecution = null; + break; + } + StackOffsetBeforeExecution += ILOp.Align(ILOp.SizeOfType(item), 4); + } + } + + // if current instruction is the first instruction of a catch statement, "push" the exception type now + if (CurrentExceptionHandler != null && CurrentExceptionHandler.HandlerOffset == Position) + { + if (CurrentExceptionHandler.Flags != SR.ExceptionHandlingClauseOptions.Finally) + { + aStack.Push(CurrentExceptionHandler.CatchType); + } + } + + if (StackPopTypes.Length > aStack.Count) + { + throw new Exception( + String.Format("OpCode {0} tries to pop more stuff from analytical stack than there is!", this)); + } + + for (int i = 0; i < StackPopTypes.Length; i++) + { + var xActualStackItem = aStack.ElementAt(i); + if (xActualStackItem == null) + { + continue; + } + if (StackPopTypes[i] == null) + { + StackPopTypes[i] = xActualStackItem; + aSituationChanged = true; + } + if ((StackPopTypes[i] != xActualStackItem) + && (((StackPopTypes[i] == typeof(Byte)) || (StackPopTypes[i] == typeof(SByte))) + || ((StackPopTypes[i] == typeof(UInt16)) || (StackPopTypes[i] == typeof(Int16))) + || ((StackPopTypes[i] == typeof(UInt32)) || (StackPopTypes[i] == typeof(Int32))) + || ((StackPopTypes[i] == typeof(UInt64)) || (StackPopTypes[i] == typeof(Int64))) + || ((StackPopTypes[i] == typeof(UIntPtr)) || (StackPopTypes[i] == typeof(IntPtr))))) + { + StackPopTypes[i] = xActualStackItem; + aSituationChanged = true; + } + if (StackPopTypes[i] != xActualStackItem && !StackPopTypes[i].IsAssignableFrom(xActualStackItem) + && !((StackPopTypes[i].IsPointer || StackPopTypes[i].IsByRef) + && (xActualStackItem.IsPointer || xActualStackItem.IsByRef))) + { + throw new Exception($"OpCode {this} tries to pop item at stack position {i} with type {StackPopTypes[i]}, but actual type is {xActualStackItem}"); + } + } + + foreach (var xPopItem in StackPopTypes) + { + aStack.Pop(); + } + try + { + DoInterpretStackTypes(ref aSituationChanged); + } + catch (Exception E) + { + throw new Exception("Error interpreting stacktypes for " + this, E); + } + foreach (var xPushItem in StackPushTypes) + { + aStack.Push(xPushItem); + } + DoInterpretNextInstructionStackTypes(aOpCodes, aStack, ref aSituationChanged, aMaxRecursionDepth); + } + + /// + /// Based on updated StackPopTypes, try to update + /// + protected virtual void DoInterpretStackTypes(ref bool aSituationChanged) + { + // + } + + protected virtual void DoInterpretNextInstructionStackTypesIfNotYetProcessed( + IDictionary aOpCodes, + Stack aStack, + ref bool aSituationChanged, + int aMaxRecursionDepth) + { + ILOpCode xNextOpCode; + if (aOpCodes.TryGetValue(NextPosition, out xNextOpCode)) + { + ILInterpretationDebugLine(() => String.Format("- Branching from {0} to {1}", this, xNextOpCode)); + InterpretInstruction(xNextOpCode, aOpCodes, aStack, ref aSituationChanged, aMaxRecursionDepth); + } + } + + protected virtual void DoInterpretNextInstructionStackTypes( + IDictionary aOpCodes, + Stack aStack, + ref bool aSituationChanged, + int aMaxRecursionDepth) + { + InterpretInstruction(NextPosition, aOpCodes, aStack, ref aSituationChanged, aMaxRecursionDepth); + } + + protected void InterpretInstructionIfNotYetProcessed( + int aPosition, + IDictionary aOpCodes, + Stack aStack, + ref bool aSituationChanged, + int aMaxRecursionDepth) + { + ILOpCode xNextOpCode; + if (aOpCodes.TryGetValue(aPosition, out xNextOpCode)) + { + ILInterpretationDebugLine(() => String.Format("- Branching from {0} to {1}", this, xNextOpCode)); + InterpretInstruction(xNextOpCode, aOpCodes, aStack, ref aSituationChanged, aMaxRecursionDepth); + } + } + + protected void InterpretInstruction( + int aPosition, + IDictionary aOpCodes, + Stack aStack, + ref bool aSituationChanged, + int aMaxRecursionDepth) + { + ILOpCode xNextOpCode; + if (aOpCodes.TryGetValue(aPosition, out xNextOpCode)) + { + InterpretInstruction(xNextOpCode, aOpCodes, aStack, ref aSituationChanged, aMaxRecursionDepth); + } + } + + protected void InterpretInstruction( + ILOpCode xNextOpCode, + IDictionary aOpCodes, + Stack aStack, + ref bool aSituationChanged, + int aMaxRecursionDepth) + { + xNextOpCode.InterpretStackTypes(aOpCodes, aStack, ref aSituationChanged, aMaxRecursionDepth - 1); + } + + protected static 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) || type == typeof(IntPtr) || type == typeof(UIntPtr); + } + + protected static bool IsIntegralTypeOrPointer(Type type) + { + return IsIntegralType(type) || type.IsPointer || type.IsByRef; + } + + + protected static bool IsPointer(Type aPointer) + { + return aPointer.IsPointer || aPointer.IsByRef || aPointer == typeof(IntPtr) || aPointer == typeof(UIntPtr); + } + + [Conditional("DISABLED")] + public static void ILInterpretationDebugLine(Func message) + { + //Console.WriteLine(message()); + } } - - /// - /// Based on updated StackPopTypes, try to update - /// - protected virtual void DoInterpretStackTypes(ref bool aSituationChanged) - { - // - } - - protected virtual void DoInterpretNextInstructionStackTypesIfNotYetProcessed(IDictionary aOpCodes, Stack aStack, ref bool aSituationChanged, int aMaxRecursionDepth) - { - ILOpCode xNextOpCode; - if (aOpCodes.TryGetValue(NextPosition, out xNextOpCode)) - { - ILInterpretationDebugLine(() => String.Format("- Branching from {0} to {1}", this, xNextOpCode)); - InterpretInstruction(xNextOpCode, aOpCodes, aStack, ref aSituationChanged, aMaxRecursionDepth); - } - } - - protected virtual void DoInterpretNextInstructionStackTypes(IDictionary aOpCodes, Stack aStack, ref bool aSituationChanged, int aMaxRecursionDepth) - { - InterpretInstruction(NextPosition, aOpCodes, aStack, ref aSituationChanged, aMaxRecursionDepth); - } - - protected void InterpretInstructionIfNotYetProcessed(int aPosition, IDictionary aOpCodes, Stack aStack, ref bool aSituationChanged, int aMaxRecursionDepth) - { - ILOpCode xNextOpCode; - if (aOpCodes.TryGetValue(aPosition, out xNextOpCode)) - { - ILInterpretationDebugLine(() => String.Format("- Branching from {0} to {1}", this, xNextOpCode)); - InterpretInstruction(xNextOpCode, aOpCodes, aStack, ref aSituationChanged, aMaxRecursionDepth); - } - } - - protected void InterpretInstruction(int aPosition, IDictionary aOpCodes, Stack aStack, ref bool aSituationChanged, int aMaxRecursionDepth) - { - ILOpCode xNextOpCode; - if (aOpCodes.TryGetValue(aPosition, out xNextOpCode)) - { - InterpretInstruction(xNextOpCode, aOpCodes, aStack, ref aSituationChanged, aMaxRecursionDepth); - } - } - - protected void InterpretInstruction(ILOpCode xNextOpCode, IDictionary aOpCodes, Stack aStack, ref bool aSituationChanged, int aMaxRecursionDepth) - { - xNextOpCode.InterpretStackTypes(aOpCodes, aStack, ref aSituationChanged, aMaxRecursionDepth - 1); - } - - protected static 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) - || type == typeof(IntPtr) - || type == typeof(UIntPtr); - } - - protected static bool IsIntegralTypeOrPointer(Type type) - { - return IsIntegralType(type) - || type.IsPointer - || type.IsByRef; - } - - - protected static bool IsPointer(Type aPointer) - { - return aPointer.IsPointer || aPointer.IsByRef || aPointer == typeof(IntPtr) || aPointer == typeof(UIntPtr); - } - - [Conditional("DISABLED")] - public static void ILInterpretationDebugLine(Func message) - { - //Console.WriteLine(message()); - } - } -} +} \ No newline at end of file