From 475eab39cfd0fe7b422e4e0d65df6bbb29afa97d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Srbeck=C3=BD?= Date: Sun, 11 Nov 2007 20:46:08 +0000 Subject: [PATCH] Move code from Util class to - ByteCode.PopCount - ByteCode.PushCount --- src/AstMetodBodyBuilder.cs | 6 +- src/ByteCode.cs | 109 ++++++++++++++++++++++++++++++++++--- src/ByteCodeCollection.cs | 38 ++++++++++--- src/StackAnalysis.cs | 6 +- src/Util.cs | 74 +------------------------ 5 files changed, 137 insertions(+), 96 deletions(-) diff --git a/src/AstMetodBodyBuilder.cs b/src/AstMetodBodyBuilder.cs index ac13c9f77..d24050354 100644 --- a/src/AstMetodBodyBuilder.cs +++ b/src/AstMetodBodyBuilder.cs @@ -18,7 +18,7 @@ namespace Decompiler methodDef.Body.Simplify(); - ByteCodeCollection body = new ByteCodeCollection(methodDef.Body.Instructions); + ByteCodeCollection body = new ByteCodeCollection(methodDef); StackAnalysis stackAnalysis = new StackAnalysis(methodDef, body); foreach(VariableDefinition varDef in methodDef.Body.Variables) { @@ -41,7 +41,7 @@ namespace Decompiler Ast.Statement astStatement = null; try { - int argCount = Util.GetNumberOfInputs(methodDef, byteCode); + int argCount = byteCode.PopCount; Ast.Expression[] args = new Ast.Expression[argCount]; for(int i = 0; i < argCount; i++) { ByteCode allocBy = stackAnalysis.StackBefore[byteCode].Peek(argCount - i).AllocadedBy; @@ -53,7 +53,7 @@ namespace Decompiler byteCode, args); if (codeExpr is Ast.Expression) { - if (Util.GetNumberOfOutputs(methodDef, byteCode) == 1) { + if (byteCode.PushCount == 1) { string type = stackAnalysis.GetTypeOf(byteCode).FullName; string name = string.Format("expr{0:X2}", byteCode.Offset); Ast.LocalVariableDeclaration astLocal = new Ast.LocalVariableDeclaration(new Ast.TypeReference(type.ToString())); diff --git a/src/ByteCode.cs b/src/ByteCode.cs index 6b0d181b2..e01912217 100644 --- a/src/ByteCode.cs +++ b/src/ByteCode.cs @@ -9,17 +9,42 @@ namespace Decompiler { public class ByteCode { + ByteCode previous; ByteCode next; + List nestedByteCodes = new List(); + + MethodDefinition methodDef; int offset; OpCode opCode; object operand; + public ByteCode Previous { + get { return previous; } + set { previous = value; } + } + public ByteCode Next { get { return next; } set { next = value; } } + public int PopCount { + get { + return GetNumberOfInputs(methodDef, this); + } + } + + public int PushCount { + get { + return GetNumberOfOutputs(methodDef, this); + } + } + + public List NestedByteCodes { + get { return nestedByteCodes; } + } + public int Offset { get { return offset; } set { offset = value; } @@ -48,18 +73,86 @@ namespace Decompiler } } - public ByteCode(int offset, OpCode opCode, object operand) - { - this.offset = offset; - this.opCode = opCode; - this.operand = operand; - } - - public ByteCode(Instruction inst) + public ByteCode(MethodDefinition methodDef, Instruction inst) { + this.methodDef = methodDef; this.offset = inst.Offset; this.opCode = inst.OpCode; this.operand = inst.Operand; } + + static int GetNumberOfInputs(MethodDefinition methodDef, ByteCode byteCode) + { + switch(byteCode.OpCode.StackBehaviourPop) { + case StackBehaviour.Pop0: return 0; + case StackBehaviour.Pop1: return 1; + case StackBehaviour.Popi: return 1; + case StackBehaviour.Popref: return 1; + case StackBehaviour.Pop1_pop1: return 2; + case StackBehaviour.Popi_pop1: return 2; + case StackBehaviour.Popi_popi: return 2; + case StackBehaviour.Popi_popi8: return 2; + case StackBehaviour.Popi_popr4: return 2; + case StackBehaviour.Popi_popr8: return 2; + case StackBehaviour.Popref_pop1: return 2; + case StackBehaviour.Popref_popi: return 2; + case StackBehaviour.Popi_popi_popi: return 3; + case StackBehaviour.Popref_popi_popi: return 3; + case StackBehaviour.Popref_popi_popi8: return 3; + case StackBehaviour.Popref_popi_popr4: return 3; + case StackBehaviour.Popref_popi_popr8: return 3; + case StackBehaviour.Popref_popi_popref: return 3; + case StackBehaviour.PopAll: throw new Exception("PopAll"); + case StackBehaviour.Varpop: + switch(byteCode.OpCode.Code) { + case Code.Call: + Cecil.MethodReference cecilMethod = ((MethodReference)byteCode.Operand); + if (cecilMethod.HasThis) { + return cecilMethod.Parameters.Count + 1 /* this */; + } else { + return cecilMethod.Parameters.Count; + } + case Code.Calli: throw new NotImplementedException(); + case Code.Callvirt: throw new NotImplementedException(); + case Code.Ret: + if (methodDef.ReturnType.ReturnType.FullName == Constants.Void) { + return 0; + } else { + return 1; + } + case Code.Newobj: throw new NotImplementedException(); + default: throw new Exception("Unknown Varpop opcode"); + } + default: throw new Exception("Unknown pop behaviour: " + byteCode.OpCode.StackBehaviourPop); + } + } + + static int GetNumberOfOutputs(MethodDefinition methodDef, ByteCode byteCode) + { + switch(byteCode.OpCode.StackBehaviourPush) { + case StackBehaviour.Push0: return 0; + case StackBehaviour.Push1: return 1; + case StackBehaviour.Push1_push1: return 2; + case StackBehaviour.Pushi: return 1; + case StackBehaviour.Pushi8: return 1; + case StackBehaviour.Pushr4: return 1; + case StackBehaviour.Pushr8: return 1; + case StackBehaviour.Pushref: return 1; + case StackBehaviour.Varpush: // Happens only for calls + switch(byteCode.OpCode.Code) { + case Code.Call: + Cecil.MethodReference cecilMethod = ((MethodReference)byteCode.Operand); + if (cecilMethod.ReturnType.ReturnType.FullName == Constants.Void) { + return 0; + } else { + return 1; + } + case Code.Calli: throw new NotImplementedException(); + case Code.Callvirt: throw new NotImplementedException(); + default: throw new Exception("Unknown Varpush opcode"); + } + default: throw new Exception("Unknown push behaviour: " + byteCode.OpCode.StackBehaviourPush); + } + } } } diff --git a/src/ByteCodeCollection.cs b/src/ByteCodeCollection.cs index 37289eec9..4b9e94f12 100644 --- a/src/ByteCodeCollection.cs +++ b/src/ByteCodeCollection.cs @@ -10,27 +10,27 @@ namespace Decompiler { public class ByteCodeCollection: IEnumerable { - List byteCodes = new List(); + List list = new List(); public IEnumerator GetEnumerator() { - return byteCodes.GetEnumerator(); + return list.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { - return byteCodes.GetEnumerator(); + return list.GetEnumerator(); } public int Count { get { - return byteCodes.Count; + return list.Count; } } public ByteCode this[int index] { get { - return byteCodes[index]; + return list[index]; } } @@ -44,18 +44,38 @@ namespace Decompiler throw new Exception("Not found"); } - public ByteCodeCollection(InstructionCollection instCol) + public int IndexOf(ByteCode byteCode) { - foreach(Instruction inst in instCol) { - byteCodes.Add(new ByteCode(inst)); + return list.IndexOf(byteCode); + } + + public void Remove(ByteCode byteCode) + { + int index = IndexOf(byteCode); + list.RemoveAt(index); + byteCode.Next = null; + byteCode.Previous = null; + UpdateNextPrevious(); + } + + public ByteCodeCollection(MethodDefinition methodDef) + { + foreach(Instruction inst in methodDef.Body.Instructions) { + list.Add(new ByteCode(methodDef, inst)); } foreach(ByteCode byteCode in this) { if (byteCode.CanBranch) { byteCode.Operand = GetByOffset(((Instruction)byteCode.Operand).Offset); } } - for(int i = 0; i < byteCodes.Count - 1; i++) { + UpdateNextPrevious(); + } + + void UpdateNextPrevious() + { + for(int i = 0; i < list.Count - 1; i++) { this[i].Next = this[i + 1]; + this[i + 1].Previous = this[i]; } } } diff --git a/src/StackAnalysis.cs b/src/StackAnalysis.cs index 7539702e3..985a65503 100644 --- a/src/StackAnalysis.cs +++ b/src/StackAnalysis.cs @@ -124,7 +124,7 @@ namespace Decompiler public Cecil.TypeReference GetTypeOf(ByteCode byteCode) { - if (Util.GetNumberOfOutputs(methodDef, byteCode) == 0) { + if (byteCode.PushCount == 0) { return TypeVoid; } else { return StackAfter[byteCode].Peek(1).Type; @@ -179,12 +179,12 @@ namespace Decompiler CilStack ChangeStack(CilStack oldStack, ByteCode byteCode) { CilStack newStack = oldStack.Clone(); - CilStackSlot[] popedSlots = newStack.PopCount(Util.GetNumberOfInputs(methodDef, byteCode)); + CilStackSlot[] popedSlots = newStack.PopCount(byteCode.PopCount); List typeArgs = new List(); foreach(CilStackSlot slot in popedSlots) { typeArgs.Add(slot.Type); } - for (int i = 0; i < Util.GetNumberOfOutputs(methodDef, byteCode); i++) { + for (int i = 0; i < byteCode.PushCount; i++) { newStack.Push(new CilStackSlot(byteCode, GetType(methodDef, byteCode, typeArgs.ToArray()))); } return newStack; diff --git a/src/Util.cs b/src/Util.cs index a8e11d557..065dd2a1c 100644 --- a/src/Util.cs +++ b/src/Util.cs @@ -11,78 +11,6 @@ namespace Decompiler { public static class Util { - public static int GetNumberOfInputs(MethodDefinition methodDef, ByteCode byteCode) - { - switch(byteCode.OpCode.StackBehaviourPop) { - case StackBehaviour.Pop0: return 0; - case StackBehaviour.Pop1: return 1; - case StackBehaviour.Popi: return 1; - case StackBehaviour.Popref: return 1; - case StackBehaviour.Pop1_pop1: return 2; - case StackBehaviour.Popi_pop1: return 2; - case StackBehaviour.Popi_popi: return 2; - case StackBehaviour.Popi_popi8: return 2; - case StackBehaviour.Popi_popr4: return 2; - case StackBehaviour.Popi_popr8: return 2; - case StackBehaviour.Popref_pop1: return 2; - case StackBehaviour.Popref_popi: return 2; - case StackBehaviour.Popi_popi_popi: return 3; - case StackBehaviour.Popref_popi_popi: return 3; - case StackBehaviour.Popref_popi_popi8: return 3; - case StackBehaviour.Popref_popi_popr4: return 3; - case StackBehaviour.Popref_popi_popr8: return 3; - case StackBehaviour.Popref_popi_popref: return 3; - case StackBehaviour.PopAll: throw new Exception("PopAll"); - case StackBehaviour.Varpop: - switch(byteCode.OpCode.Code) { - case Code.Call: - Cecil.MethodReference cecilMethod = ((MethodReference)byteCode.Operand); - if (cecilMethod.HasThis) { - return cecilMethod.Parameters.Count + 1 /* this */; - } else { - return cecilMethod.Parameters.Count; - } - case Code.Calli: throw new NotImplementedException(); - case Code.Callvirt: throw new NotImplementedException(); - case Code.Ret: - if (methodDef.ReturnType.ReturnType.FullName == Constants.Void) { - return 0; - } else { - return 1; - } - case Code.Newobj: throw new NotImplementedException(); - default: throw new Exception("Unknown Varpop opcode"); - } - default: throw new Exception("Unknown pop behaviour: " + byteCode.OpCode.StackBehaviourPop); - } - } - - public static int GetNumberOfOutputs(MethodDefinition methodDef, ByteCode byteCode) - { - switch(byteCode.OpCode.StackBehaviourPush) { - case StackBehaviour.Push0: return 0; - case StackBehaviour.Push1: return 1; - case StackBehaviour.Push1_push1: return 2; - case StackBehaviour.Pushi: return 1; - case StackBehaviour.Pushi8: return 1; - case StackBehaviour.Pushr4: return 1; - case StackBehaviour.Pushr8: return 1; - case StackBehaviour.Pushref: return 1; - case StackBehaviour.Varpush: // Happens only for calls - switch(byteCode.OpCode.Code) { - case Code.Call: - Cecil.MethodReference cecilMethod = ((MethodReference)byteCode.Operand); - if (cecilMethod.ReturnType.ReturnType.FullName == Constants.Void) { - return 0; - } else { - return 1; - } - case Code.Calli: throw new NotImplementedException(); - case Code.Callvirt: throw new NotImplementedException(); - default: throw new Exception("Unknown Varpush opcode"); - } - default: throw new Exception("Unknown push behaviour: " + byteCode.OpCode.StackBehaviourPush); - } - } + } }