diff --git a/Decompiler.csproj b/Decompiler.csproj index d07b24d12..7e3bfbdb2 100644 --- a/Decompiler.csproj +++ b/Decompiler.csproj @@ -40,12 +40,12 @@ + - MainForm.cs diff --git a/src/StackAnalysis.Types.cs b/src/ByteCode.Type.cs similarity index 93% rename from src/StackAnalysis.Types.cs rename to src/ByteCode.Type.cs index b91aba662..94c83f2bf 100644 --- a/src/StackAnalysis.Types.cs +++ b/src/ByteCode.Type.cs @@ -10,7 +10,7 @@ using Mono.Cecil.Cil; namespace Decompiler { - public partial class StackAnalysis + public partial class ByteCode { static public Cecil.TypeReference TypeVoid = GetCecilType(typeof(void)); static public Cecil.TypeReference TypeObject = GetCecilType(typeof(Object)); @@ -23,19 +23,19 @@ namespace Decompiler return new Cecil.TypeReference(type.Name, type.Namespace, null, type.IsValueType); } - static Cecil.TypeReference GetType(MethodDefinition methodDef, ByteCode byteCode, params Cecil.TypeReference[] args) + public Cecil.TypeReference GetType(params Cecil.TypeReference[] args) { try { - return(GetTypeInternal(methodDef, byteCode, args)); + return(GetTypeInternal(args)); } catch (NotImplementedException) { return TypeObject; } } - static Cecil.TypeReference GetTypeInternal(MethodDefinition methodDef, ByteCode byteCode, params Cecil.TypeReference[] args) + public Cecil.TypeReference GetTypeInternal(params Cecil.TypeReference[] args) { - OpCode opCode = byteCode.OpCode; - object operand = byteCode.Operand; + OpCode opCode = this.OpCode; + object operand = this.Operand; Cecil.TypeReference operandAsTypeRef = operand as Cecil.TypeReference; ByteCode operandAsByteCode = operand as ByteCode; string operandAsByteCodeLabel = operand is ByteCode ? String.Format("IL_{0:X2}", ((ByteCode)operand).Offset) : null; diff --git a/src/ByteCode.cs b/src/ByteCode.cs index e01912217..713a3077d 100644 --- a/src/ByteCode.cs +++ b/src/ByteCode.cs @@ -7,7 +7,7 @@ using Mono.Cecil.Cil; namespace Decompiler { - public class ByteCode + public partial class ByteCode { ByteCode previous; ByteCode next; @@ -31,16 +31,40 @@ namespace Decompiler public int PopCount { get { - return GetNumberOfInputs(methodDef, this); + int popCount; + int pushCount; + SimulateStackSize(out popCount, out pushCount); + return popCount; } } public int PushCount { get { - return GetNumberOfOutputs(methodDef, this); + int popCount; + int pushCount; + SimulateStackSize(out popCount, out pushCount); + return pushCount; } } + void SimulateStackSize(out int popCount, out int pushCount) + { + int stackSize = 0; + int minStackSize = 0; + foreach(ByteCode bc in nestedByteCodes) { + stackSize -= bc.PopCount; + minStackSize = Math.Min(minStackSize, stackSize); + stackSize += bc.PushCount; + } + { + stackSize -= GetPopCount(methodDef, this); + minStackSize = Math.Min(minStackSize, stackSize); + stackSize += GetPushCount(methodDef, this); + } + popCount = -minStackSize; + pushCount = stackSize - minStackSize; + } + public List NestedByteCodes { get { return nestedByteCodes; } } @@ -81,7 +105,7 @@ namespace Decompiler this.operand = inst.Operand; } - static int GetNumberOfInputs(MethodDefinition methodDef, ByteCode byteCode) + static int GetPopCount(MethodDefinition methodDef, ByteCode byteCode) { switch(byteCode.OpCode.StackBehaviourPop) { case StackBehaviour.Pop0: return 0; @@ -127,7 +151,7 @@ namespace Decompiler } } - static int GetNumberOfOutputs(MethodDefinition methodDef, ByteCode byteCode) + static int GetPushCount(MethodDefinition methodDef, ByteCode byteCode) { switch(byteCode.OpCode.StackBehaviourPush) { case StackBehaviour.Push0: return 0; diff --git a/src/StackAnalysis.cs b/src/StackAnalysis.cs index 985a65503..bc87bd6af 100644 --- a/src/StackAnalysis.cs +++ b/src/StackAnalysis.cs @@ -125,7 +125,7 @@ namespace Decompiler public Cecil.TypeReference GetTypeOf(ByteCode byteCode) { if (byteCode.PushCount == 0) { - return TypeVoid; + return ByteCode.TypeVoid; } else { return StackAfter[byteCode].Peek(1).Type; } @@ -185,7 +185,7 @@ namespace Decompiler typeArgs.Add(slot.Type); } for (int i = 0; i < byteCode.PushCount; i++) { - newStack.Push(new CilStackSlot(byteCode, GetType(methodDef, byteCode, typeArgs.ToArray()))); + newStack.Push(new CilStackSlot(byteCode, byteCode.GetType(typeArgs.ToArray()))); } return newStack; }