Browse Source

Move code from Util class to

- ByteCode.PopCount
 - ByteCode.PushCount
pull/1/head^2
David Srbecký 18 years ago
parent
commit
475eab39cf
  1. 6
      src/AstMetodBodyBuilder.cs
  2. 109
      src/ByteCode.cs
  3. 38
      src/ByteCodeCollection.cs
  4. 6
      src/StackAnalysis.cs
  5. 74
      src/Util.cs

6
src/AstMetodBodyBuilder.cs

@ -18,7 +18,7 @@ namespace Decompiler @@ -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 @@ -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 @@ -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()));

109
src/ByteCode.cs

@ -9,17 +9,42 @@ namespace Decompiler @@ -9,17 +9,42 @@ namespace Decompiler
{
public class ByteCode
{
ByteCode previous;
ByteCode next;
List<ByteCode> nestedByteCodes = new List<ByteCode>();
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<ByteCode> NestedByteCodes {
get { return nestedByteCodes; }
}
public int Offset {
get { return offset; }
set { offset = value; }
@ -48,18 +73,86 @@ namespace Decompiler @@ -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);
}
}
}
}

38
src/ByteCodeCollection.cs

@ -10,27 +10,27 @@ namespace Decompiler @@ -10,27 +10,27 @@ namespace Decompiler
{
public class ByteCodeCollection: IEnumerable<ByteCode>
{
List<ByteCode> byteCodes = new List<ByteCode>();
List<ByteCode> list = new List<ByteCode>();
public IEnumerator<ByteCode> 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 @@ -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];
}
}
}

6
src/StackAnalysis.cs

@ -124,7 +124,7 @@ namespace Decompiler @@ -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 @@ -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<Cecil.TypeReference> typeArgs = new List<Cecil.TypeReference>();
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;

74
src/Util.cs

@ -11,78 +11,6 @@ namespace Decompiler @@ -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);
}
}
}
}

Loading…
Cancel
Save