diff --git a/ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs b/ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs index c7a1fd760..869ed77b9 100644 --- a/ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs +++ b/ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs @@ -15,8 +15,7 @@ namespace Decompiler public class AstMethodBodyBuilder { MethodDefinition methodDef; - static Dictionary localVarTypes = new Dictionary(); - static Dictionary localVarDefined = new Dictionary(); + HashSet definedLocalVars = new HashSet(); public static BlockStatement CreateMethodBody(MethodDefinition methodDef) { @@ -47,48 +46,45 @@ namespace Decompiler if (methodDef.Body == null) return null; ILBlock ilMethod = new ILBlock(); - ilMethod.Body = new ILAstBuilder().Build(methodDef, true); + ILAstBuilder astBuilder = new ILAstBuilder(); + ilMethod.Body = astBuilder.Build(methodDef, true); ILAstOptimizer bodyGraph = new ILAstOptimizer(); bodyGraph.Optimize(ilMethod); List intNames = new List(new string[] {"i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t"}); Dictionary typeNames = new Dictionary(); - foreach(VariableDefinition varDef in methodDef.Body.Variables) { - if (string.IsNullOrEmpty(varDef.Name)) { - if (varDef.VariableType.FullName == Constants.Int32 && intNames.Count > 0) { - varDef.Name = intNames[0]; - intNames.RemoveAt(0); - } else { - string name; - if (varDef.VariableType.IsArray) { - name = "array"; - } else if (!typeNameToVariableNameDict.TryGetValue(varDef.VariableType.FullName, out name)) { - name = varDef.VariableType.Name; - // remove the 'I' for interfaces - if (name.Length >= 3 && name[0] == 'I' && char.IsUpper(name[1]) && char.IsLower(name[2])) - name = name.Substring(1); - // remove the backtick (generics) - int pos = name.IndexOf('`'); - if (pos >= 0) - name = name.Substring(0, pos); - if (name.Length == 0) - name = "obj"; - else - name = char.ToLower(name[0]) + name.Substring(1); - } - if (!typeNames.ContainsKey(name)) { - typeNames.Add(name, 0); - } - int count = typeNames[name]; - if (count > 0) { - name += count.ToString(); - } - varDef.Name = name; + foreach(ILVariable varDef in astBuilder.Variables) { + if (varDef.Type.FullName == Constants.Int32 && intNames.Count > 0) { + varDef.Name = intNames[0]; + intNames.RemoveAt(0); + } else { + string name; + if (varDef.Type.IsArray) { + name = "array"; + } else if (!typeNameToVariableNameDict.TryGetValue(varDef.Type.FullName, out name)) { + name = varDef.Type.Name; + // remove the 'I' for interfaces + if (name.Length >= 3 && name[0] == 'I' && char.IsUpper(name[1]) && char.IsLower(name[2])) + name = name.Substring(1); + // remove the backtick (generics) + int pos = name.IndexOf('`'); + if (pos >= 0) + name = name.Substring(0, pos); + if (name.Length == 0) + name = "obj"; + else + name = char.ToLower(name[0]) + name.Substring(1); + } + if (!typeNames.ContainsKey(name)) { + typeNames.Add(name, 0); } + int count = typeNames[name]; + if (count > 0) { + name += count.ToString(); + } + varDef.Name = name; } - localVarTypes[varDef.Name] = varDef.VariableType; - localVarDefined[varDef.Name] = false; // Ast.VariableDeclaration astVar = new Ast.VariableDeclaration(varDef.Name); // Ast.LocalVariableDeclaration astLocalVar = new Ast.LocalVariableDeclaration(astVar); @@ -172,8 +168,8 @@ namespace Decompiler SwitchStatement switchStmt = new SwitchStatement() { Expression = (Expression)TransformExpression(ilSwitch.Condition.Arguments[0]) }; for (int i = 0; i < ilSwitch.CaseBlocks.Count; i++) { switchStmt.AddChild(new SwitchSection() { - CaseLabels = new CaseLabel[] { new CaseLabel() { Expression = new PrimitiveExpression(i) } }, - Statements = new Statement[] { TransformBlock(ilSwitch.CaseBlocks[i]) } + CaseLabels = new[] { new CaseLabel() { Expression = new PrimitiveExpression(i) } }, + Statements = new[] { TransformBlock(ilSwitch.CaseBlocks[i]) } }, SwitchStatement.SwitchSectionRole); } yield return switchStmt; @@ -272,7 +268,7 @@ namespace Decompiler */ } - static AstNode TransformByteCode(MethodDefinition methodDef, ILExpression byteCode, List args) + AstNode TransformByteCode(MethodDefinition methodDef, ILExpression byteCode, List args) { try { AstNode ret = TransformByteCode_Internal(methodDef, byteCode, args); @@ -287,7 +283,7 @@ namespace Decompiler } } - static string FormatByteCodeOperand(object operand) + string FormatByteCodeOperand(object operand) { if (operand == null) { return string.Empty; @@ -312,7 +308,7 @@ namespace Decompiler } } - static AstNode TransformByteCode_Internal(MethodDefinition methodDef, ILExpression byteCode, List args) + AstNode TransformByteCode_Internal(MethodDefinition methodDef, ILExpression byteCode, List args) { // throw new NotImplementedException(); @@ -605,29 +601,15 @@ namespace Decompiler case Code.Sizeof: return new Ast.SizeOfExpression { Type = AstBuilder.ConvertType(operand as TypeReference) }; case Code.Starg: throw new NotImplementedException(); case Code.Stloc: { - if (operand is ILVariable) { - var astLocalVar = new Ast.VariableDeclarationStatement(); - astLocalVar.Type = new Ast.PrimitiveType("var"); - astLocalVar.Variables = new [] { - new Ast.VariableInitializer(((ILVariable)operand).Name, arg1) + ILVariable locVar = (ILVariable)operand; + if (!definedLocalVars.Contains(locVar)) { + definedLocalVars.Add(locVar); + return new Ast.VariableDeclarationStatement() { + Type = locVar.Type != null ? AstBuilder.ConvertType(locVar.Type) : new Ast.PrimitiveType("var"), + Variables = new[] { new Ast.VariableInitializer(locVar.Name, arg1) } }; - return astLocalVar; - } - VariableDefinition locVar = (VariableDefinition)operand; - string name = locVar.Name; - arg1 = Convert(arg1, locVar.VariableType); - if (localVarDefined.ContainsKey(name)) { - if (localVarDefined[name]) { - return new Ast.AssignmentExpression(new Ast.IdentifierExpression(name), arg1); - } else { - var astLocalVar = new Ast.VariableDeclarationStatement(); - astLocalVar.Type = AstBuilder.ConvertType(localVarTypes[name]); - astLocalVar.Variables = new[] { new Ast.VariableInitializer(name, arg1) }; - localVarDefined[name] = true; - return astLocalVar; - } } else { - return new Ast.AssignmentExpression(new Ast.IdentifierExpression(name), arg1); + return new Ast.AssignmentExpression(new Ast.IdentifierExpression(locVar.Name), arg1); } } case Code.Stobj: throw new NotImplementedException(); diff --git a/ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs b/ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs index 50a67b48f..e520437f0 100644 --- a/ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs +++ b/ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs @@ -95,6 +95,8 @@ namespace Decompiler Dictionary instrToByteCode = new Dictionary(); Dictionary allowInline = new Dictionary(); + public List Variables; + public List Build(MethodDefinition methodDef, bool optimize) { this.methodDef = methodDef; @@ -249,27 +251,27 @@ namespace Decompiler } // 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]; + Variables = methodDef.Body.Variables.Select(v => new ILVariable() { Name = string.IsNullOrEmpty(v.Name) ? "var_" + v.Index : v.Name, Type = v.VariableType }).ToList(); + int[] numReads = new int[Variables.Count]; + int[] numWrites = new int[Variables.Count]; foreach(ByteCode byteCode in body) { if (byteCode.OpCode == OpCodes.Ldloc) { int index = ((VariableDefinition)byteCode.Operand).Index; - byteCode.Operand = vars[index]; + byteCode.Operand = Variables[index]; numReads[index]++; } if (byteCode.OpCode == OpCodes.Stloc) { int index = ((VariableDefinition)byteCode.Operand).Index; - byteCode.Operand = vars[index]; + byteCode.Operand = Variables[index]; numWrites[index]++; } } // Find which variables we can inline if (this.optimize) { - for (int i = 0; i < vars.Count; i++) { + for (int i = 0; i < Variables.Count; i++) { if (numReads[i] == 1 && numWrites[i] == 1) { - allowInline[vars[i]] = true; + allowInline[Variables[i]] = true; } } } diff --git a/ICSharpCode.Decompiler/ILAst/ILAstTypes.cs b/ICSharpCode.Decompiler/ILAst/ILAstTypes.cs index bfd300b21..61756612f 100644 --- a/ICSharpCode.Decompiler/ILAst/ILAstTypes.cs +++ b/ICSharpCode.Decompiler/ILAst/ILAstTypes.cs @@ -44,6 +44,11 @@ namespace Decompiler { yield break; } + + public override string ToString() + { + return this.GetType().Name; + } } public class ILBlock: ILNode @@ -102,17 +107,13 @@ namespace Decompiler if (this.FinallyBlock != null) yield return this.FinallyBlock; } - - public override string ToString() - { - return "Try-Catch{}"; - } } public class ILVariable { public string Name; public bool IsGenerated; + public TypeReference Type; public override string ToString() {