From c3885ad7a15cda909fb461222113a4ab4b1025be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Srbeck=C3=BD?= Date: Sat, 12 Feb 2011 14:40:00 +0000 Subject: [PATCH] Implemented control flow merge points (aka Phi) --- Decompiler/tests/Stack/StackTests.exe | Bin 0 -> 2048 bytes Decompiler/tests/Stack/StackTests.il | 135 ++++++ .../Ast/AstMetodBodyBuilder.cs | 26 +- .../Ast/Transforms/RemoveGotos.cs | 15 +- ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs | 398 ++++++++++++------ ICSharpCode.Decompiler/ILAst/ILAstTypes.cs | 4 +- .../Mono.Cecil.Rocks/MyRocks.cs | 8 +- 7 files changed, 425 insertions(+), 161 deletions(-) create mode 100644 Decompiler/tests/Stack/StackTests.exe create mode 100644 Decompiler/tests/Stack/StackTests.il diff --git a/Decompiler/tests/Stack/StackTests.exe b/Decompiler/tests/Stack/StackTests.exe new file mode 100644 index 0000000000000000000000000000000000000000..db6194ad6836b1f6367770a08757a45309c92121 GIT binary patch literal 2048 zcmeHH&ubGw6#jP8rZKg#f+P{NPKkvQG_=-3717vQf3_M)t5OAOqRA z=&cv^APAm32%=E2c+s1u{smt8M+kzK`n}z48>kedC&5SNz4yI0^X7Xqvl$wlMFcBO$j3CwL;XrDI*7utt!R9!Xc*w>xXgsPM*%l1@RD`(15RZAT^ zS5y=BxX!h-#CM0K3j@HQVdCSLk)h??7GWCAMl2v@2GMsJTE&s)5T$6C6W$`r7GnhA znh5fbfL8yvYC|ZCC}XU9CUF0(^T6gmXV#A@fE}zzjQHdV0&=SEo042GIM>2bj4QAGug>P z(N30$r&ir$GTF)MQHjKpsXCBKrB*ZP`b>7zJQ(N34r@*JHj39mFH4@>?^sC591zwl z>z{mrHknQJ%I&3l<;b@8auFg2o2ZqPyOeF%+oZPno@(<=n<*6H*}mfGK0{7`A{B1$ z&voT`x_Y_~NTd-pF-&Lf12x(wgqfn}RITf-q<%1#me@!Un@NeU5SbGrr-bVc;yr@< zYId1cgdyVu8`~t{S4R($etEwe=KSX&eTVlFGV2O$6k8GJvq)2m1iSg_}=WB>2k>M__?K1OmI*VrixfvKEHgL<=x2a9Ab body = new ILAstBuilder().Build(methodDef); + List body = new ILAstBuilder().Build(methodDef, true); MethodBodyGraph bodyGraph = new MethodBodyGraph(body); bodyGraph.Optimize(); @@ -649,8 +653,8 @@ namespace Decompiler case Code.Ldsflda: throw new NotImplementedException(); case Code.Ldftn: throw new NotImplementedException(); case Code.Ldloc: - if (operand is ILStackVariable) { - return new Ast.IdentifierExpression(((ILStackVariable)operand).Name); + if (operand is ILVariable) { + return new Ast.IdentifierExpression(((ILVariable)operand).Name); } else { return new Ast.IdentifierExpression(((VariableDefinition)operand).Name); } @@ -703,8 +707,8 @@ namespace Decompiler case Code.Sizeof: throw new NotImplementedException(); case Code.Starg: throw new NotImplementedException(); case Code.Stloc: { - if (operand is ILStackVariable) { - Ast.LocalVariableDeclaration astLocalVar = new Ast.LocalVariableDeclaration(new Ast.VariableDeclaration(((ILStackVariable)operand).Name, arg1)); + if (operand is ILVariable) { + Ast.LocalVariableDeclaration astLocalVar = new Ast.LocalVariableDeclaration(new Ast.VariableDeclaration(((ILVariable)operand).Name, arg1)); astLocalVar.TypeReference = new Ast.TypeReference("var"); return astLocalVar; } diff --git a/ICSharpCode.Decompiler/Ast/Transforms/RemoveGotos.cs b/ICSharpCode.Decompiler/Ast/Transforms/RemoveGotos.cs index a737b9c8b..7b4c2d245 100644 --- a/ICSharpCode.Decompiler/Ast/Transforms/RemoveGotos.cs +++ b/ICSharpCode.Decompiler/Ast/Transforms/RemoveGotos.cs @@ -142,10 +142,17 @@ namespace Decompiler.Transforms.Ast { // Remove redundant goto which goes to a label that imideately follows INode fallthoughTarget = GetNextStatement(gotoStatement); - if ((fallthoughTarget is LabelStatement) && - (fallthoughTarget as LabelStatement).Label == gotoStatement.Label) { - RemoveCurrentNode(); - return null; + while(true) { + if (fallthoughTarget is LabelStatement) { + if ((fallthoughTarget as LabelStatement).Label == gotoStatement.Label) { + RemoveCurrentNode(); + return null; + } else { + fallthoughTarget = GetNextStatement((LabelStatement)fallthoughTarget); + continue; + } + } + break; } // Replace goto with 'break' diff --git a/ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs b/ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs index 0e5b99013..fef8687e6 100644 --- a/ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs +++ b/ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs @@ -12,27 +12,45 @@ namespace Decompiler { public class ILAstBuilder { - class ILStack + class StackSlot { - public class Slot + public List PushedBy; // Pushed by one of these; null element means exception pushed by CLR + public ILVariable LoadFrom; + + public StackSlot() { - public Instruction PushedBy; - public TypeReference Type; - - public Slot(Instruction inst, TypeReference type) - { - this.PushedBy = inst; - this.Type = type; - } } - public List Items = new List(); + public StackSlot(ByteCode pushedBy) + { + this.PushedBy = new List(1); + this.PushedBy.Add(pushedBy); + } + } + + class ByteCode + { + public ILLabel Label; // Non-null only if needed + public int Offset; + public OpCode OpCode; + public object Operand; + public int? PopCount; // Null means pop all + public int PushCount; + public string Name { get { return "IL_" + this.Offset.ToString("X2"); } } + public ByteCode Next; + public List StackBefore; + public List StoreTo; - public ILStack Clone() + public List CloneStack(int? popCount) { - ILStack clone = new ILStack(); - foreach(Slot s in this.Items) { - clone.Items.Add(new Slot(s.PushedBy, s.Type)); + List clone = new List(); + if (popCount.HasValue) { + if (popCount.Value > this.StackBefore.Count) { + throw new Exception("Can not pop - the stack is empty"); + } + for(int i = 0; i < this.StackBefore.Count - popCount.Value; i++) { + clone.Add(new StackSlot() { PushedBy = new List(this.StackBefore[i].PushedBy) }); + } } return clone; } @@ -40,123 +58,237 @@ namespace Decompiler public override string ToString() { StringBuilder sb = new StringBuilder(); - bool first = true; - foreach (Slot s in this.Items) { - if (!first) sb.Append(", "); - sb.Append(s.PushedBy.Offset.ToString("X")); - first = false; + sb.AppendFormat("{0}:{1} {2} {3}", this.Name, this.Label != null ? " *" : "", this.OpCode, this.Operand); + if (this.StackBefore != null) { + sb.Append(" StackBefore = {"); + bool first = true; + foreach (StackSlot slot in this.StackBefore) { + if (!first) sb.Append(","); + bool first2 = true; + foreach(ByteCode pushedBy in slot.PushedBy) { + if (!first2) sb.Append("|"); + sb.AppendFormat("IL_{0:X2}", pushedBy.Offset); + first2 = false; + } + first = false; + } + sb.Append("}"); + } + if (this.StoreTo != null && this.StoreTo.Count > 0) { + sb.Append(" StoreTo = {"); + bool first = true; + foreach (ILVariable stackVar in this.StoreTo) { + if (!first) sb.Append(","); + sb.Append(stackVar.Name); + first = false; + } + sb.Append("}"); } return sb.ToString(); } } MethodDefinition methodDef; - Dictionary stackBefore = new Dictionary(); - Dictionary labels = new Dictionary(); + bool optimize; - public List Build(MethodDefinition methodDef) + Dictionary instrToByteCode = new Dictionary(); + Dictionary allowInline = new Dictionary(); + + public List Build(MethodDefinition methodDef, bool optimize) { this.methodDef = methodDef; + this.optimize = optimize; - // Make editable copy - List body = new List(methodDef.Body.Instructions); - - if (body.Count == 0) return new List(); + if (methodDef.Body.Instructions.Count == 0) return new List(); - StackAnalysis(body, methodDef); - - // Create branch labels for instructins; use the labels as branch operands - foreach (Instruction inst in body) { - if (inst.Operand is Instruction[]) { - foreach(Instruction target in (Instruction[])inst.Operand) { - if (!labels.ContainsKey(target)) { - labels[target] = new ILLabel() { Name = "IL_" + target.Offset.ToString("X2") }; - } - } - } else if (inst.Operand is Instruction) { - Instruction target = (Instruction)inst.Operand; - if (!labels.ContainsKey(target)) { - labels[target] = new ILLabel() { Name = "IL_" + target.Offset.ToString("X2") }; - } - } - } + List body = StackAnalysis(methodDef); List ast = ConvertToAst(body, methodDef.Body.ExceptionHandlers); return ast; } - public void StackAnalysis(List body, MethodDefinition methodDef) + List StackAnalysis(MethodDefinition methodDef) { - Queue agenda = new Queue(); + // Create temporary structure for the stack analysis + List body = new List(methodDef.Body.Instructions.Count); + foreach(Instruction inst in methodDef.Body.Instructions) { + OpCode opCode = inst.OpCode; + object operand = inst.Operand; + MethodBodyRocks.ExpandMacro(ref opCode, ref operand, methodDef.Body); + ByteCode byteCode = new ByteCode() { + Offset = inst.Offset, + OpCode = opCode, + Operand = operand, + PopCount = inst.GetPopCount(), + PushCount = inst.GetPushCount() + }; + instrToByteCode[inst] = byteCode; + body.Add(byteCode); + } + for (int i = 0; i < body.Count - 1; i++) { + body[i].Next = body[i + 1]; + } + + Queue agenda = new Queue(); // Add known states - stackBefore[body[0]] = new ILStack(); + body[0].StackBefore = new List(); agenda.Enqueue(body[0]); if(methodDef.Body.HasExceptionHandlers) { foreach(ExceptionHandler ex in methodDef.Body.ExceptionHandlers) { - stackBefore[ex.TryStart] = new ILStack(); - agenda.Enqueue(ex.TryStart); + ByteCode tryStart = instrToByteCode[ex.TryStart]; + tryStart.StackBefore = new List(); + agenda.Enqueue(tryStart); - ILStack stack = new ILStack(); - stack.Items.Add(new ILStack.Slot(null, MyRocks.TypeException)); - stackBefore[ex.HandlerStart] = stack; - agenda.Enqueue(ex.HandlerStart); + ByteCode handlerStart = instrToByteCode[ex.HandlerType == ExceptionHandlerType.Filter ? ex.FilterStart : ex.HandlerStart]; + handlerStart.StackBefore = new List(); + if (ex.HandlerType == ExceptionHandlerType.Catch || ex.HandlerType == ExceptionHandlerType.Filter) { + handlerStart.StackBefore.Add(new StackSlot(null)); + } + agenda.Enqueue(handlerStart); + + // Control flow is not required to reach endfilter + if (ex.HandlerType == ExceptionHandlerType.Filter) { + ByteCode endFilter = instrToByteCode[ex.FilterEnd.Previous]; + endFilter.StackBefore = new List(); + } } } // Process agenda while(agenda.Count > 0) { - Instruction inst = agenda.Dequeue(); + ByteCode byteCode = agenda.Dequeue(); - // What is the effect of the instruction on the stack? - ILStack newStack = stackBefore[inst].Clone(); - int popCount = inst.GetPopCount(); - if (popCount == int.MaxValue) popCount = stackBefore[inst].Items.Count; // Pop all - List typeArgs = new List(); - for (int i = newStack.Items.Count - popCount; i < newStack.Items.Count; i++) { - typeArgs.Add(newStack.Items[i].Type); - } - TypeReference type; - try { - type = inst.GetTypeInternal(methodDef, typeArgs); - } catch { - type = MyRocks.TypeObject; - } - if (popCount > 0) { - newStack.Items.RemoveRange(newStack.Items.Count - popCount, popCount); - } - int pushCount = inst.GetPushCount(); - for (int i = 0; i < pushCount; i++) { - newStack.Items.Add(new ILStack.Slot(inst, type)); + // Calculate new stack + List newStack = byteCode.CloneStack(byteCode.PopCount); + for (int i = 0; i < byteCode.PushCount; i++) { + newStack.Add(new StackSlot(byteCode)); } // Apply the state to any successors - List branchTargets = new List(); - if (inst.OpCode.CanFallThough()) { - branchTargets.Add(inst.Next); + List branchTargets = new List(); + if (byteCode.OpCode.CanFallThough()) { + branchTargets.Add(byteCode.Next); } - if (inst.OpCode.IsBranch()) { - if (inst.Operand is Instruction[]) { - branchTargets.AddRange((Instruction[])inst.Operand); + if (byteCode.OpCode.IsBranch()) { + if (byteCode.Operand is Instruction[]) { + foreach(Instruction inst in (Instruction[])byteCode.Operand) { + ByteCode target = instrToByteCode[inst]; + branchTargets.Add(target); + // The target of a branch must have label + if (target.Label == null) { + target.Label = new ILLabel() { Name = target.Name }; + } + } } else { - branchTargets.Add((Instruction)inst.Operand); + ByteCode target = instrToByteCode[(Instruction)byteCode.Operand]; + branchTargets.Add(target); + // The target of a branch must have label + if (target.Label == null) { + target.Label = new ILLabel() { Name = target.Name }; + } } } - foreach (Instruction branchTarget in branchTargets) { - ILStack nextStack; - if (stackBefore.TryGetValue(branchTarget, out nextStack)) { - // TODO: Compare stacks - } else { - stackBefore[branchTarget] = newStack; + foreach (ByteCode branchTarget in branchTargets) { + if (branchTarget.StackBefore == null) { + branchTarget.StackBefore = newStack; + // Do not share one stack for several bytecodes + if (branchTargets.Count > 1) { + branchTarget.StackBefore = branchTarget.CloneStack(0); + } agenda.Enqueue(branchTarget); + } else { + if (branchTarget.StackBefore.Count != newStack.Count) { + throw new Exception("Inconsistent stack size at " + byteCode.Name); + } + + // Merge stacks + bool modified = false; + for (int i = 0; i < newStack.Count; i++) { + List oldPushedBy = branchTarget.StackBefore[i].PushedBy; + List newPushedBy = oldPushedBy.Union(newStack[i].PushedBy).ToList(); + if (newPushedBy.Count > oldPushedBy.Count) { + branchTarget.StackBefore[i].PushedBy = newPushedBy; + modified = true; + } + } + + if (modified) { + agenda.Enqueue(branchTarget); + } + } + } + } + + // Genertate temporary variables to replace stack + foreach(ByteCode byteCode in body) { + int argIdx = 0; + int popCount = byteCode.PopCount ?? byteCode.StackBefore.Count; + for (int i = byteCode.StackBefore.Count - popCount; i < byteCode.StackBefore.Count; i++) { + StackSlot arg = byteCode.StackBefore[i]; + ILVariable tmpVar = new ILVariable() { Name = string.Format("arg_{0:X2}_{1}", byteCode.Offset, argIdx), IsGenerated = true }; + arg.LoadFrom = tmpVar; + foreach(ByteCode pushedBy in arg.PushedBy) { + // TODO: Handle exception variables + if (pushedBy != null) { + if (pushedBy.StoreTo == null) { + pushedBy.StoreTo = new List(1); + } + pushedBy.StoreTo.Add(tmpVar); + } + } + if (arg.PushedBy.Count == 1) { + allowInline[tmpVar] = true; + } + argIdx++; + } + } + + // Convert local varibles + List vars = methodDef.Body.Variables.Select(v => new ILVariable() { Name = string.IsNullOrEmpty(v.Name) ? "var_" + v.Index : v.Name }).ToList(); + int[] numReads = new int[vars.Count]; + int[] numWrites = new int[vars.Count]; + foreach(ByteCode byteCode in body) { + if (byteCode.OpCode == OpCodes.Ldloc) { + int index = ((VariableDefinition)byteCode.Operand).Index; + byteCode.Operand = vars[index]; + numReads[index]++; + } + if (byteCode.OpCode == OpCodes.Stloc) { + int index = ((VariableDefinition)byteCode.Operand).Index; + byteCode.Operand = vars[index]; + numWrites[index]++; + } + } + + // Find which variables we can inline + if (this.optimize) { + for (int i = 0; i < vars.Count; i++) { + if (numReads[i] == 1 && numWrites[i] == 1) { + allowInline[vars[i]] = true; + } + } + } + + // Convert branch targets to labels + foreach(ByteCode byteCode in body) { + if (byteCode.Operand is Instruction[]) { + List newOperand = new List(); + foreach(Instruction target in (Instruction[])byteCode.Operand) { + newOperand.Add(instrToByteCode[target].Label); } + byteCode.Operand = newOperand.ToArray(); + } else if (byteCode.Operand is Instruction) { + byteCode.Operand = instrToByteCode[(Instruction)byteCode.Operand].Label; } } + + return body; } - public List ConvertToAst(List body, IEnumerable ehs) + List ConvertToAst(List body, IEnumerable ehs) { List ast = new List(); @@ -187,9 +319,9 @@ namespace Decompiler tryCatchBlock.CatchBlocks = new List(); foreach(ExceptionHandler eh in handlers) { int start; - for (start = 0; body[start] != eh.HandlerStart; start++); + for (start = 0; body[start].Offset != eh.HandlerStart.Offset; start++); int end; - for (end = 0; body[end] != eh.HandlerEnd; end++); + for (end = 0; body[end].Offset != eh.HandlerEnd.Offset; end++); int count = end - start; List nestedEHs = ehs.Where(e => (start <= e.TryStart.Offset && e.TryEnd.Offset < end) || (start < e.TryStart.Offset && e.TryEnd.Offset <= end)).ToList(); List handlerAst = ConvertToAst(body.CutRange(start, count), nestedEHs); @@ -216,73 +348,62 @@ namespace Decompiler return ast; } - public List ConvertToAst(List body) + List ConvertToAst(List body) { List ast = new List(); // Convert stack-based IL code to ILAst tree - foreach(Instruction inst in body) { - OpCode opCode = inst.OpCode; - object operand = inst.Operand; + foreach(ByteCode byteCode in body) { + OpCode opCode = byteCode.OpCode; + object operand = byteCode.Operand; MethodBodyRocks.ExpandMacro(ref opCode, ref operand, methodDef.Body); ILExpression expr = new ILExpression(opCode, operand); // Label for this instruction - ILLabel label; - if (labels.TryGetValue(inst, out label)) { - ast.Add(label); - } - - // Branch using labels - if (inst.Operand is Instruction[]) { - List newOperand = new List(); - foreach(Instruction target in (Instruction[])inst.Operand) { - newOperand.Add(labels[target]); - } - expr.Operand = newOperand.ToArray(); - } else if (inst.Operand is Instruction) { - expr.Operand = labels[(Instruction)inst.Operand]; + if (byteCode.Label != null) { + ast.Add(byteCode.Label); } // Reference arguments using temporary variables - ILStack stack = stackBefore[inst]; - int popCount = inst.GetPopCount(); - if (popCount == int.MaxValue) popCount = stackBefore[inst].Items.Count; // Pop all - for (int i = stack.Items.Count - popCount; i < stack.Items.Count; i++) { - Instruction pushedBy = stack.Items[i].PushedBy; - if (pushedBy != null) { - ILExpression ldExpr = new ILExpression(OpCodes.Ldloc, new ILStackVariable() { Name = "expr" + pushedBy.Offset.ToString("X2") }); + int popCount = byteCode.PopCount ?? byteCode.StackBefore.Count; + for (int i = byteCode.StackBefore.Count - popCount; i < byteCode.StackBefore.Count; i++) { + StackSlot slot = byteCode.StackBefore[i]; + if (slot.PushedBy != null) { + ILExpression ldExpr = new ILExpression(OpCodes.Ldloc, slot.LoadFrom); expr.Arguments.Add(ldExpr); } else { - ILExpression ldExpr = new ILExpression(OpCodes.Ldloc, new ILStackVariable() { Name = "exception" }); + ILExpression ldExpr = new ILExpression(OpCodes.Ldloc, new ILVariable() { Name = "ex", IsGenerated = true }); expr.Arguments.Add(ldExpr); } } - // If the bytecode pushes anything store the result in temporary variable - int pushCount = inst.GetPushCount(); - if (pushCount > 0) { - ILExpression stExpr = new ILExpression(OpCodes.Stloc, new ILStackVariable() { Name = "expr" + inst.Offset.ToString("X2"), RefCount = pushCount }); - stExpr.Arguments.Add(expr); - expr = stExpr; + // Store the result to temporary variable(s) if needed + if (byteCode.StoreTo == null || byteCode.StoreTo.Count == 0) { + ast.Add(expr); + } else if (byteCode.StoreTo.Count == 1) { + ast.Add(new ILExpression(OpCodes.Stloc, byteCode.StoreTo[0], expr)); + } else { + ILVariable tmpVar = new ILVariable() { Name = "expr_" + byteCode.Offset.ToString("X2"), IsGenerated = true }; + ast.Add(new ILExpression(OpCodes.Stloc, tmpVar, expr)); + foreach(ILVariable storeTo in byteCode.StoreTo) { + ast.Add(new ILExpression(OpCodes.Stloc, storeTo, new ILExpression(OpCodes.Ldloc, tmpVar))); + } } - - ast.Add(expr); } // Try to in-line stloc / ldloc pairs for(int i = 0; i < ast.Count - 1; i++) { if (i < 0) continue; - ILExpression expr = ast[i] as ILExpression; + ILExpression currExpr = ast[i] as ILExpression; ILExpression nextExpr = ast[i + 1] as ILExpression; - if (expr != null && nextExpr != null && expr.OpCode.Code == Code.Stloc && expr.Operand is ILStackVariable) { + if (currExpr != null && nextExpr != null && currExpr.OpCode.Code == Code.Stloc) { - // If the next expression is stloc, look inside - if (nextExpr.OpCode.Code == Code.Stloc && nextExpr.Operand is ILStackVariable) { + // If the next expression is generated stloc, look inside + if (nextExpr.OpCode.Code == Code.Stloc && ((ILVariable)nextExpr.Operand).IsGenerated) { nextExpr = nextExpr.Arguments[0]; } @@ -290,22 +411,19 @@ namespace Decompiler for(int j = 0; j < nextExpr.Arguments.Count; j++) { ILExpression arg = nextExpr.Arguments[j]; - // TODO: Check if duplicating the dup opcode has side-effects - - if (arg.OpCode.Code == Code.Ldloc && arg.Operand is ILStackVariable) { - ILStackVariable stVar = (ILStackVariable)expr.Operand; - ILStackVariable ldVar = (ILStackVariable)arg.Operand; - if (stVar.Name == ldVar.Name) { - stVar.RefCount--; - if (stVar.RefCount <= 0) { - ast.RemoveAt(i); - } - nextExpr.Arguments[j] = expr.Arguments[0]; // Inline the stloc body + // We are moving the expression evaluation past the other aguments. + // It is ok to pass ldloc because the expression can not contain stloc and thus the ldcoc will still return the same value + if (arg.OpCode.Code == Code.Ldloc) { + bool canInline; + allowInline.TryGetValue((ILVariable)arg.Operand, out canInline); + if (arg.Operand == currExpr.Operand && canInline) { + ast.RemoveAt(i); + nextExpr.Arguments[j] = currExpr.Arguments[0]; // Inline the stloc body i -= 2; // Try the same index again break; // Found } } else { - break; // This argument might have side effects so we can not move the 'expr' after it. + break; // Side-effects } } } diff --git a/ICSharpCode.Decompiler/ILAst/ILAstTypes.cs b/ICSharpCode.Decompiler/ILAst/ILAstTypes.cs index 77eb40bda..c30c53499 100644 --- a/ICSharpCode.Decompiler/ILAst/ILAstTypes.cs +++ b/ICSharpCode.Decompiler/ILAst/ILAstTypes.cs @@ -41,10 +41,10 @@ namespace Decompiler } } - public class ILStackVariable + public class ILVariable { public string Name; - public int RefCount; + public bool IsGenerated; public override string ToString() { diff --git a/ICSharpCode.Decompiler/Mono.Cecil.Rocks/MyRocks.cs b/ICSharpCode.Decompiler/Mono.Cecil.Rocks/MyRocks.cs index 1f976df93..dbf99f5e7 100644 --- a/ICSharpCode.Decompiler/Mono.Cecil.Rocks/MyRocks.cs +++ b/ICSharpCode.Decompiler/Mono.Cecil.Rocks/MyRocks.cs @@ -43,7 +43,7 @@ namespace Decompiler.Mono.Cecil.Rocks case FlowControl.Call: return true; case FlowControl.Return: return false; case FlowControl.Throw: return false; - case FlowControl.Meta: return false; + case FlowControl.Meta: return true; default: throw new NotImplementedException(); } } @@ -53,7 +53,7 @@ namespace Decompiler.Mono.Cecil.Rocks return opCode.FlowControl == FlowControl.Branch || opCode.FlowControl == FlowControl.Cond_Branch; } - public static int GetPopCount(this Instruction inst) + public static int? GetPopCount(this Instruction inst) { switch(inst.OpCode.StackBehaviourPop) { case StackBehaviour.Pop0: return 0; @@ -74,7 +74,7 @@ namespace Decompiler.Mono.Cecil.Rocks case StackBehaviour.Popref_popi_popr4: return 3; case StackBehaviour.Popref_popi_popr8: return 3; case StackBehaviour.Popref_popi_popref: return 3; - case StackBehaviour.PopAll: return int.MaxValue; + case StackBehaviour.PopAll: return null; case StackBehaviour.Varpop: switch(inst.OpCode.Code) { case Code.Call: @@ -86,7 +86,7 @@ namespace Decompiler.Mono.Cecil.Rocks return cecilMethod.Parameters.Count; } case Code.Calli: throw new NotImplementedException(); - case Code.Ret: return int.MaxValue; + case Code.Ret: return null; case Code.Newobj: MethodReference ctorMethod = ((MethodReference)inst.Operand); return ctorMethod.Parameters.Count;