Browse Source

Use custom data structure to store bytecode sequence

pull/1/head^2
David Srbecký 18 years ago
parent
commit
0fe95f6b0b
  1. 2
      Decompiler.csproj
  2. 69
      src/AstMetodBodyBuilder.cs
  3. 65
      src/ByteCode.cs
  4. 62
      src/ByteCodeCollection.cs
  5. 14
      src/StackAnalysis.Types.cs
  6. 80
      src/StackAnalysis.cs
  7. 20
      src/Util.cs

2
Decompiler.csproj

@ -39,6 +39,8 @@ @@ -39,6 +39,8 @@
<Compile Include="src\AssemblyInfo.cs" />
<Compile Include="src\AstBuilder.cs" />
<Compile Include="src\AstMetodBodyBuilder.cs" />
<Compile Include="src\ByteCode.cs" />
<Compile Include="src\ByteCodeCollection.cs" />
<Compile Include="src\MainForm.cs" />
<Compile Include="src\MainForm.Designer.cs" />
<Compile Include="src\Program.cs" />

69
src/AstMetodBodyBuilder.cs

@ -18,7 +18,8 @@ namespace Decompiler @@ -18,7 +18,8 @@ namespace Decompiler
methodDef.Body.Simplify();
StackAnalysis stackAnalysis = new StackAnalysis(methodDef);
ByteCodeCollection body = new ByteCodeCollection(methodDef.Body.Instructions);
StackAnalysis stackAnalysis = new StackAnalysis(methodDef, body);
foreach(VariableDefinition varDef in methodDef.Body.Variables) {
Ast.VariableDeclaration astVar = new Ast.VariableDeclaration(varDef.Name);
@ -27,12 +28,12 @@ namespace Decompiler @@ -27,12 +28,12 @@ namespace Decompiler
astBlock.Children.Add(astLocalVar);
}
foreach(Instruction instr in methodDef.Body.Instructions) {
OpCode opCode = instr.OpCode;
foreach(ByteCode byteCode in body) {
OpCode opCode = byteCode.OpCode;
string description =
string.Format(" {1, -22} # {2}->{3} {4} {5}",
instr.Offset,
opCode + " " + FormatInstructionOperand(instr.Operand),
byteCode.Offset,
opCode + " " + FormatByteCodeOperand(byteCode.Operand),
opCode.StackBehaviourPop,
opCode.StackBehaviourPush,
opCode.FlowControl == FlowControl.Next ? string.Empty : "Flow=" + opCode.FlowControl,
@ -40,21 +41,21 @@ namespace Decompiler @@ -40,21 +41,21 @@ namespace Decompiler
Ast.Statement astStatement = null;
try {
int argCount = Util.GetNumberOfInputs(methodDef, instr);
int argCount = Util.GetNumberOfInputs(methodDef, byteCode);
Ast.Expression[] args = new Ast.Expression[argCount];
for(int i = 0; i < argCount; i++) {
Instruction allocBy = stackAnalysis.StackBefore[instr].Peek(argCount - i).AllocadedBy;
ByteCode allocBy = stackAnalysis.StackBefore[byteCode].Peek(argCount - i).AllocadedBy;
string name = string.Format("expr{0:X2}", allocBy.Offset);
args[i] = new Ast.IdentifierExpression(name);
}
object codeExpr = MakeCodeDomExpression(
methodDef,
instr,
byteCode,
args);
if (codeExpr is Ast.Expression) {
if (Util.GetNumberOfOutputs(methodDef, instr) == 1) {
string type = stackAnalysis.GetTypeOf(instr).FullName;
string name = string.Format("expr{0:X2}", instr.Offset);
if (Util.GetNumberOfOutputs(methodDef, byteCode) == 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()));
astLocal.Variables.Add(new Ast.VariableDeclaration(name, (Ast.Expression)codeExpr));
astStatement = astLocal;
@ -68,8 +69,8 @@ namespace Decompiler @@ -68,8 +69,8 @@ namespace Decompiler
astStatement = MakeComment(description);
}
//astBlock.Children.Add(MakeComment(description));
if (stackAnalysis.BranchTargetOf[instr].Count > 0) {
astBlock.Children.Add(new Ast.LabelStatement(string.Format("IL_{0:X2}", instr.Offset)));
if (stackAnalysis.BranchTargetOf[byteCode].Count > 0) {
astBlock.Children.Add(new Ast.LabelStatement(string.Format("IL_{0:X2}", byteCode.Offset)));
}
astBlock.Children.Add(astStatement);
//astBlock.Children.Add(MakeComment(" " + stackAnalysis.StackAfter[instr].ToString()));
@ -84,12 +85,12 @@ namespace Decompiler @@ -84,12 +85,12 @@ namespace Decompiler
return new Ast.ExpressionStatement(new PrimitiveExpression(text, text));
}
static object FormatInstructionOperand(object operand)
static object FormatByteCodeOperand(object operand)
{
if (operand == null) {
return string.Empty;
} else if (operand is Instruction) {
return string.Format("IL_{0:X2}", ((Instruction)operand).Offset);
} else if (operand is ByteCode) {
return string.Format("IL_{0:X2}", ((ByteCode)operand).Offset);
} else if (operand is MethodReference) {
return ((MethodReference)operand).Name + "()";
} else if (operand is Cecil.TypeReference) {
@ -107,13 +108,13 @@ namespace Decompiler @@ -107,13 +108,13 @@ namespace Decompiler
}
}
static object MakeCodeDomExpression(MethodDefinition methodDef, Instruction inst, params Ast.Expression[] args)
static object MakeCodeDomExpression(MethodDefinition methodDef, ByteCode byteCode, params Ast.Expression[] args)
{
OpCode opCode = inst.OpCode;
object operand = inst.Operand;
OpCode opCode = byteCode.OpCode;
object operand = byteCode.Operand;
Ast.TypeReference operandAsTypeRef = operand is Cecil.TypeReference ? new Ast.TypeReference(((Cecil.TypeReference)operand).FullName) : null;
Instruction operandAsInstruction = operand is Instruction ? (Instruction)operand : null;
string operandAsInstructionLabel = operand is Instruction ? String.Format("IL_{0:X2}", ((Instruction)operand).Offset) : null;
ByteCode operandAsByteCode = operand as ByteCode;
string operandAsByteCodeLabel = operand is ByteCode ? String.Format("IL_{0:X2}", ((ByteCode)operand).Offset) : null;
Ast.Expression arg1 = args.Length >= 1 ? args[0] : null;
Ast.Expression arg2 = args.Length >= 2 ? args[1] : null;
Ast.Expression arg3 = args.Length >= 3 ? args[2] : null;
@ -174,19 +175,19 @@ namespace Decompiler @@ -174,19 +175,19 @@ namespace Decompiler
case Code.Stelem_Any: throw new NotImplementedException();
#endregion
#region Branching
case Code.Br: return new Ast.GotoStatement(operandAsInstructionLabel);
case Code.Brfalse: return new Ast.IfElseStatement(new Ast.UnaryOperatorExpression(arg1, UnaryOperatorType.Not), new Ast.GotoStatement(operandAsInstructionLabel));
case Code.Brtrue: return new Ast.IfElseStatement(arg1, new Ast.GotoStatement(operandAsInstructionLabel));
case Code.Beq: return new Ast.IfElseStatement(new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Equality, arg2), new Ast.GotoStatement(operandAsInstructionLabel));
case Code.Bge: return new Ast.IfElseStatement(new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.GreaterThanOrEqual, arg2), new Ast.GotoStatement(operandAsInstructionLabel));
case Code.Bge_Un: return new Ast.IfElseStatement(new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.GreaterThanOrEqual, arg2), new Ast.GotoStatement(operandAsInstructionLabel));
case Code.Bgt: return new Ast.IfElseStatement(new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.GreaterThan, arg2), new Ast.GotoStatement(operandAsInstructionLabel));
case Code.Bgt_Un: return new Ast.IfElseStatement(new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.GreaterThan, arg2), new Ast.GotoStatement(operandAsInstructionLabel));
case Code.Ble: return new Ast.IfElseStatement(new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.LessThanOrEqual, arg2), new Ast.GotoStatement(operandAsInstructionLabel));
case Code.Ble_Un: return new Ast.IfElseStatement(new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.LessThanOrEqual, arg2), new Ast.GotoStatement(operandAsInstructionLabel));
case Code.Blt: return new Ast.IfElseStatement(new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.LessThan, arg2), new Ast.GotoStatement(operandAsInstructionLabel));
case Code.Blt_Un: return new Ast.IfElseStatement(new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.LessThan, arg2), new Ast.GotoStatement(operandAsInstructionLabel));
case Code.Bne_Un: return new Ast.IfElseStatement(new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.InEquality, arg2), new Ast.GotoStatement(operandAsInstructionLabel));
case Code.Br: return new Ast.GotoStatement(operandAsByteCodeLabel);
case Code.Brfalse: return new Ast.IfElseStatement(new Ast.UnaryOperatorExpression(arg1, UnaryOperatorType.Not), new Ast.GotoStatement(operandAsByteCodeLabel));
case Code.Brtrue: return new Ast.IfElseStatement(arg1, new Ast.GotoStatement(operandAsByteCodeLabel));
case Code.Beq: return new Ast.IfElseStatement(new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Equality, arg2), new Ast.GotoStatement(operandAsByteCodeLabel));
case Code.Bge: return new Ast.IfElseStatement(new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.GreaterThanOrEqual, arg2), new Ast.GotoStatement(operandAsByteCodeLabel));
case Code.Bge_Un: return new Ast.IfElseStatement(new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.GreaterThanOrEqual, arg2), new Ast.GotoStatement(operandAsByteCodeLabel));
case Code.Bgt: return new Ast.IfElseStatement(new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.GreaterThan, arg2), new Ast.GotoStatement(operandAsByteCodeLabel));
case Code.Bgt_Un: return new Ast.IfElseStatement(new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.GreaterThan, arg2), new Ast.GotoStatement(operandAsByteCodeLabel));
case Code.Ble: return new Ast.IfElseStatement(new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.LessThanOrEqual, arg2), new Ast.GotoStatement(operandAsByteCodeLabel));
case Code.Ble_Un: return new Ast.IfElseStatement(new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.LessThanOrEqual, arg2), new Ast.GotoStatement(operandAsByteCodeLabel));
case Code.Blt: return new Ast.IfElseStatement(new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.LessThan, arg2), new Ast.GotoStatement(operandAsByteCodeLabel));
case Code.Blt_Un: return new Ast.IfElseStatement(new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.LessThan, arg2), new Ast.GotoStatement(operandAsByteCodeLabel));
case Code.Bne_Un: return new Ast.IfElseStatement(new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.InEquality, arg2), new Ast.GotoStatement(operandAsByteCodeLabel));
#endregion
#region Comparison
case Code.Ceq: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Equality, ConvertIntToBool(arg2));

65
src/ByteCode.cs

@ -0,0 +1,65 @@ @@ -0,0 +1,65 @@
using System;
using System.Collections.Generic;
using Cecil = Mono.Cecil;
using Mono.Cecil;
using Mono.Cecil.Cil;
namespace Decompiler
{
public class ByteCode
{
ByteCode next;
int offset;
OpCode opCode;
object operand;
public ByteCode Next {
get { return next; }
set { next = value; }
}
public int Offset {
get { return offset; }
set { offset = value; }
}
public OpCode OpCode {
get { return opCode; }
set { opCode = value; }
}
public object Operand {
get { return operand; }
set { operand = value; }
}
public ByteCode BranchTarget {
get {
return (ByteCode)operand;
}
}
public bool CanBranch {
get {
return OpCode.FlowControl == FlowControl.Branch ||
OpCode.FlowControl == FlowControl.Cond_Branch;
}
}
public ByteCode(int offset, OpCode opCode, object operand)
{
this.offset = offset;
this.opCode = opCode;
this.operand = operand;
}
public ByteCode(Instruction inst)
{
this.offset = inst.Offset;
this.opCode = inst.OpCode;
this.operand = inst.Operand;
}
}
}

62
src/ByteCodeCollection.cs

@ -0,0 +1,62 @@ @@ -0,0 +1,62 @@
using System;
using System.Collections;
using System.Collections.Generic;
using Cecil = Mono.Cecil;
using Mono.Cecil;
using Mono.Cecil.Cil;
namespace Decompiler
{
public class ByteCodeCollection: IEnumerable<ByteCode>
{
List<ByteCode> byteCodes = new List<ByteCode>();
public IEnumerator<ByteCode> GetEnumerator()
{
return byteCodes.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return byteCodes.GetEnumerator();
}
public int Count {
get {
return byteCodes.Count;
}
}
public ByteCode this[int index] {
get {
return byteCodes[index];
}
}
public ByteCode GetByOffset(int offset)
{
foreach(ByteCode byteCode in this) {
if (byteCode.Offset == offset) {
return byteCode;
}
}
throw new Exception("Not found");
}
public ByteCodeCollection(InstructionCollection instCol)
{
foreach(Instruction inst in instCol) {
byteCodes.Add(new ByteCode(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++) {
this[i].Next = this[i + 1];
}
}
}
}

14
src/StackAnalysis.Types.cs

@ -23,22 +23,22 @@ namespace Decompiler @@ -23,22 +23,22 @@ namespace Decompiler
return new Cecil.TypeReference(type.Name, type.Namespace, null, type.IsValueType);
}
static Cecil.TypeReference GetType(MethodDefinition methodDef, Instruction inst, params Cecil.TypeReference[] args)
static Cecil.TypeReference GetType(MethodDefinition methodDef, ByteCode byteCode, params Cecil.TypeReference[] args)
{
try {
return(GetTypeInternal(methodDef, inst, args));
return(GetTypeInternal(methodDef, byteCode, args));
} catch (NotImplementedException) {
return TypeObject;
}
}
static Cecil.TypeReference GetTypeInternal(MethodDefinition methodDef, Instruction inst, params Cecil.TypeReference[] args)
static Cecil.TypeReference GetTypeInternal(MethodDefinition methodDef, ByteCode byteCode, params Cecil.TypeReference[] args)
{
OpCode opCode = inst.OpCode;
object operand = inst.Operand;
OpCode opCode = byteCode.OpCode;
object operand = byteCode.Operand;
Cecil.TypeReference operandAsTypeRef = operand as Cecil.TypeReference;
Instruction operandAsInstruction = operand is Instruction ? (Instruction)operand : null;
string operandAsInstructionLabel = operand is Instruction ? String.Format("IL_{0:X2}", ((Instruction)operand).Offset) : null;
ByteCode operandAsByteCode = operand as ByteCode;
string operandAsByteCodeLabel = operand is ByteCode ? String.Format("IL_{0:X2}", ((ByteCode)operand).Offset) : null;
Cecil.TypeReference arg1 = args.Length >= 1 ? args[0] : null;
Cecil.TypeReference arg2 = args.Length >= 2 ? args[1] : null;
Cecil.TypeReference arg3 = args.Length >= 3 ? args[2] : null;

80
src/StackAnalysis.cs

@ -12,10 +12,10 @@ namespace Decompiler @@ -12,10 +12,10 @@ namespace Decompiler
{
// Imutable
public struct CilStackSlot {
Instruction allocadedBy;
ByteCode allocadedBy;
Cecil.TypeReference type;
public Instruction AllocadedBy {
public ByteCode AllocadedBy {
get { return allocadedBy; }
}
@ -23,7 +23,7 @@ namespace Decompiler @@ -23,7 +23,7 @@ namespace Decompiler
get { return type; }
}
public CilStackSlot(Instruction allocadedBy, Cecil.TypeReference type)
public CilStackSlot(ByteCode allocadedBy, Cecil.TypeReference type)
{
this.allocadedBy = allocadedBy;
this.type = type;
@ -106,98 +106,96 @@ namespace Decompiler @@ -106,98 +106,96 @@ namespace Decompiler
public partial class StackAnalysis {
MethodDefinition methodDef;
Dictionary<Instruction, CilStack> stackBefore = new Dictionary<Instruction, CilStack>();
Dictionary<Instruction, CilStack> stackAfter = new Dictionary<Instruction, CilStack>();
Dictionary<Instruction, List<Instruction>> branchTargetOf = new Dictionary<Instruction, List<Instruction>>();
Dictionary<ByteCode, CilStack> stackBefore = new Dictionary<ByteCode, CilStack>();
Dictionary<ByteCode, CilStack> stackAfter = new Dictionary<ByteCode, CilStack>();
Dictionary<ByteCode, List<ByteCode>> branchTargetOf = new Dictionary<ByteCode, List<ByteCode>>();
public Dictionary<Instruction, CilStack> StackBefore {
public Dictionary<ByteCode, CilStack> StackBefore {
get { return stackBefore; }
}
public Dictionary<Instruction, CilStack> StackAfter {
public Dictionary<ByteCode, CilStack> StackAfter {
get { return stackAfter; }
}
public Dictionary<Instruction, List<Instruction>> BranchTargetOf {
public Dictionary<ByteCode, List<ByteCode>> BranchTargetOf {
get { return branchTargetOf; }
}
public Cecil.TypeReference GetTypeOf(Instruction inst)
public Cecil.TypeReference GetTypeOf(ByteCode byteCode)
{
if (Util.GetNumberOfOutputs(methodDef, inst) == 0) {
if (Util.GetNumberOfOutputs(methodDef, byteCode) == 0) {
return TypeVoid;
} else {
return StackAfter[inst].Peek(1).Type;
return StackAfter[byteCode].Peek(1).Type;
}
}
public StackAnalysis(MethodDefinition methodDef) {
public StackAnalysis(MethodDefinition methodDef, ByteCodeCollection byteCodeCol) {
this.methodDef = methodDef;
foreach(Instruction inst in methodDef.Body.Instructions) {
stackBefore[inst] = null;
stackAfter[inst] = null;
branchTargetOf[inst] = new List<Instruction>();
foreach(ByteCode byteCode in byteCodeCol) {
stackBefore[byteCode] = null;
stackAfter[byteCode] = null;
branchTargetOf[byteCode] = new List<ByteCode>();
}
foreach(Instruction inst in methodDef.Body.Instructions) {
if (inst.OpCode.FlowControl == FlowControl.Branch ||
inst.OpCode.FlowControl == FlowControl.Cond_Branch)
{
branchTargetOf[(Instruction)inst.Operand].Add(inst);
foreach(ByteCode byteCode in byteCodeCol) {
if (byteCode.CanBranch) {
branchTargetOf[byteCode.BranchTarget].Add(byteCode);
}
}
if (methodDef.Body.Instructions.Count > 0) {
Instruction firstInst = methodDef.Body.Instructions[0];
if (byteCodeCol.Count > 0) {
ByteCode firstInst = byteCodeCol[0];
stackBefore[firstInst] = CilStack.Empty;
ProcessInstructionRec(firstInst);
ProcessByteCodeRec(firstInst);
}
}
void ProcessInstructionRec(Instruction inst)
void ProcessByteCodeRec(ByteCode byteCode)
{
stackAfter[inst] = ChangeStack(stackBefore[inst], inst);
stackAfter[byteCode] = ChangeStack(stackBefore[byteCode], byteCode);
switch(inst.OpCode.FlowControl) {
switch(byteCode.OpCode.FlowControl) {
case FlowControl.Branch:
CopyStack(inst, ((Instruction)inst.Operand));
CopyStack(byteCode, byteCode.BranchTarget);
break;
case FlowControl.Cond_Branch:
CopyStack(inst, inst.Next);
CopyStack(inst, ((Instruction)inst.Operand));
CopyStack(byteCode, byteCode.Next);
CopyStack(byteCode, byteCode.BranchTarget);
break;
case FlowControl.Next:
case FlowControl.Call:
CopyStack(inst, inst.Next);
CopyStack(byteCode, byteCode.Next);
break;
case FlowControl.Return:
if (stackAfter[inst].Count > 0) throw new Exception("Non-empty stack at the end");
if (stackAfter[byteCode].Count > 0) throw new Exception("Non-empty stack at the end");
break;
default: throw new NotImplementedException();
}
}
CilStack ChangeStack(CilStack oldStack, Instruction inst)
CilStack ChangeStack(CilStack oldStack, ByteCode byteCode)
{
CilStack newStack = oldStack.Clone();
CilStackSlot[] popedSlots = newStack.PopCount(Util.GetNumberOfInputs(methodDef, inst));
CilStackSlot[] popedSlots = newStack.PopCount(Util.GetNumberOfInputs(methodDef, byteCode));
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, inst); i++) {
newStack.Push(new CilStackSlot(inst, GetType(methodDef, inst, typeArgs.ToArray())));
for (int i = 0; i < Util.GetNumberOfOutputs(methodDef, byteCode); i++) {
newStack.Push(new CilStackSlot(byteCode, GetType(methodDef, byteCode, typeArgs.ToArray())));
}
return newStack;
}
void CopyStack(Instruction instFrom, Instruction instTo)
void CopyStack(ByteCode byteCodeFrom, ByteCode byteCodeTo)
{
CilStack mergedStack;
if (!Merge(stackAfter[instFrom], stackBefore[instTo], out mergedStack)) {
stackBefore[instTo] = mergedStack;
ProcessInstructionRec(instTo);
if (!Merge(stackAfter[byteCodeFrom], stackBefore[byteCodeTo], out mergedStack)) {
stackBefore[byteCodeTo] = mergedStack;
ProcessByteCodeRec(byteCodeTo);
}
}

20
src/Util.cs

@ -11,9 +11,9 @@ namespace Decompiler @@ -11,9 +11,9 @@ namespace Decompiler
{
public static class Util
{
public static int GetNumberOfInputs(MethodDefinition methodDef, Instruction inst)
public static int GetNumberOfInputs(MethodDefinition methodDef, ByteCode byteCode)
{
switch(inst.OpCode.StackBehaviourPop) {
switch(byteCode.OpCode.StackBehaviourPop) {
case StackBehaviour.Pop0: return 0;
case StackBehaviour.Pop1: return 1;
case StackBehaviour.Popi: return 1;
@ -34,9 +34,9 @@ namespace Decompiler @@ -34,9 +34,9 @@ namespace Decompiler
case StackBehaviour.Popref_popi_popref: return 3;
case StackBehaviour.PopAll: throw new Exception("PopAll");
case StackBehaviour.Varpop:
switch(inst.OpCode.Code) {
switch(byteCode.OpCode.Code) {
case Code.Call:
Cecil.MethodReference cecilMethod = ((MethodReference)inst.Operand);
Cecil.MethodReference cecilMethod = ((MethodReference)byteCode.Operand);
if (cecilMethod.HasThis) {
return cecilMethod.Parameters.Count + 1 /* this */;
} else {
@ -53,13 +53,13 @@ namespace Decompiler @@ -53,13 +53,13 @@ namespace Decompiler
case Code.Newobj: throw new NotImplementedException();
default: throw new Exception("Unknown Varpop opcode");
}
default: throw new Exception("Unknown pop behaviour: " + inst.OpCode.StackBehaviourPop);
default: throw new Exception("Unknown pop behaviour: " + byteCode.OpCode.StackBehaviourPop);
}
}
public static int GetNumberOfOutputs(MethodDefinition methodDef, Instruction inst)
public static int GetNumberOfOutputs(MethodDefinition methodDef, ByteCode byteCode)
{
switch(inst.OpCode.StackBehaviourPush) {
switch(byteCode.OpCode.StackBehaviourPush) {
case StackBehaviour.Push0: return 0;
case StackBehaviour.Push1: return 1;
case StackBehaviour.Push1_push1: return 2;
@ -69,9 +69,9 @@ namespace Decompiler @@ -69,9 +69,9 @@ namespace Decompiler
case StackBehaviour.Pushr8: return 1;
case StackBehaviour.Pushref: return 1;
case StackBehaviour.Varpush: // Happens only for calls
switch(inst.OpCode.Code) {
switch(byteCode.OpCode.Code) {
case Code.Call:
Cecil.MethodReference cecilMethod = ((MethodReference)inst.Operand);
Cecil.MethodReference cecilMethod = ((MethodReference)byteCode.Operand);
if (cecilMethod.ReturnType.ReturnType.FullName == Constants.Void) {
return 0;
} else {
@ -81,7 +81,7 @@ namespace Decompiler @@ -81,7 +81,7 @@ namespace Decompiler
case Code.Callvirt: throw new NotImplementedException();
default: throw new Exception("Unknown Varpush opcode");
}
default: throw new Exception("Unknown push behaviour: " + inst.OpCode.StackBehaviourPush);
default: throw new Exception("Unknown push behaviour: " + byteCode.OpCode.StackBehaviourPush);
}
}
}

Loading…
Cancel
Save