Browse Source

Fixed local variable names, types and definitions

pull/10/head
David Srbecký 15 years ago
parent
commit
d469b6a513
  1. 106
      ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs
  2. 16
      ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs
  3. 11
      ICSharpCode.Decompiler/ILAst/ILAstTypes.cs

106
ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs

@ -15,8 +15,7 @@ namespace Decompiler
public class AstMethodBodyBuilder public class AstMethodBodyBuilder
{ {
MethodDefinition methodDef; MethodDefinition methodDef;
static Dictionary<string, Cecil.TypeReference> localVarTypes = new Dictionary<string, Cecil.TypeReference>(); HashSet<ILVariable> definedLocalVars = new HashSet<ILVariable>();
static Dictionary<string, bool> localVarDefined = new Dictionary<string, bool>();
public static BlockStatement CreateMethodBody(MethodDefinition methodDef) public static BlockStatement CreateMethodBody(MethodDefinition methodDef)
{ {
@ -47,48 +46,45 @@ namespace Decompiler
if (methodDef.Body == null) return null; if (methodDef.Body == null) return null;
ILBlock ilMethod = new ILBlock(); 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(); ILAstOptimizer bodyGraph = new ILAstOptimizer();
bodyGraph.Optimize(ilMethod); bodyGraph.Optimize(ilMethod);
List<string> intNames = new List<string>(new string[] {"i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t"}); List<string> intNames = new List<string>(new string[] {"i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t"});
Dictionary<string, int> typeNames = new Dictionary<string, int>(); Dictionary<string, int> typeNames = new Dictionary<string, int>();
foreach(VariableDefinition varDef in methodDef.Body.Variables) { foreach(ILVariable varDef in astBuilder.Variables) {
if (string.IsNullOrEmpty(varDef.Name)) { if (varDef.Type.FullName == Constants.Int32 && intNames.Count > 0) {
if (varDef.VariableType.FullName == Constants.Int32 && intNames.Count > 0) { varDef.Name = intNames[0];
varDef.Name = intNames[0]; intNames.RemoveAt(0);
intNames.RemoveAt(0); } else {
} else { string name;
string name; if (varDef.Type.IsArray) {
if (varDef.VariableType.IsArray) { name = "array";
name = "array"; } else if (!typeNameToVariableNameDict.TryGetValue(varDef.Type.FullName, out name)) {
} else if (!typeNameToVariableNameDict.TryGetValue(varDef.VariableType.FullName, out name)) { name = varDef.Type.Name;
name = varDef.VariableType.Name; // remove the 'I' for interfaces
// remove the 'I' for interfaces if (name.Length >= 3 && name[0] == 'I' && char.IsUpper(name[1]) && char.IsLower(name[2]))
if (name.Length >= 3 && name[0] == 'I' && char.IsUpper(name[1]) && char.IsLower(name[2])) name = name.Substring(1);
name = name.Substring(1); // remove the backtick (generics)
// remove the backtick (generics) int pos = name.IndexOf('`');
int pos = name.IndexOf('`'); if (pos >= 0)
if (pos >= 0) name = name.Substring(0, pos);
name = name.Substring(0, pos); if (name.Length == 0)
if (name.Length == 0) name = "obj";
name = "obj"; else
else name = char.ToLower(name[0]) + name.Substring(1);
name = char.ToLower(name[0]) + name.Substring(1); }
} if (!typeNames.ContainsKey(name)) {
if (!typeNames.ContainsKey(name)) { typeNames.Add(name, 0);
typeNames.Add(name, 0);
}
int count = typeNames[name];
if (count > 0) {
name += count.ToString();
}
varDef.Name = name;
} }
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.VariableDeclaration astVar = new Ast.VariableDeclaration(varDef.Name);
// Ast.LocalVariableDeclaration astLocalVar = new Ast.LocalVariableDeclaration(astVar); // Ast.LocalVariableDeclaration astLocalVar = new Ast.LocalVariableDeclaration(astVar);
@ -172,8 +168,8 @@ namespace Decompiler
SwitchStatement switchStmt = new SwitchStatement() { Expression = (Expression)TransformExpression(ilSwitch.Condition.Arguments[0]) }; SwitchStatement switchStmt = new SwitchStatement() { Expression = (Expression)TransformExpression(ilSwitch.Condition.Arguments[0]) };
for (int i = 0; i < ilSwitch.CaseBlocks.Count; i++) { for (int i = 0; i < ilSwitch.CaseBlocks.Count; i++) {
switchStmt.AddChild(new SwitchSection() { switchStmt.AddChild(new SwitchSection() {
CaseLabels = new CaseLabel[] { new CaseLabel() { Expression = new PrimitiveExpression(i) } }, CaseLabels = new[] { new CaseLabel() { Expression = new PrimitiveExpression(i) } },
Statements = new Statement[] { TransformBlock(ilSwitch.CaseBlocks[i]) } Statements = new[] { TransformBlock(ilSwitch.CaseBlocks[i]) }
}, SwitchStatement.SwitchSectionRole); }, SwitchStatement.SwitchSectionRole);
} }
yield return switchStmt; yield return switchStmt;
@ -272,7 +268,7 @@ namespace Decompiler
*/ */
} }
static AstNode TransformByteCode(MethodDefinition methodDef, ILExpression byteCode, List<Ast.Expression> args) AstNode TransformByteCode(MethodDefinition methodDef, ILExpression byteCode, List<Ast.Expression> args)
{ {
try { try {
AstNode ret = TransformByteCode_Internal(methodDef, byteCode, args); 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) { if (operand == null) {
return string.Empty; return string.Empty;
@ -312,7 +308,7 @@ namespace Decompiler
} }
} }
static AstNode TransformByteCode_Internal(MethodDefinition methodDef, ILExpression byteCode, List<Ast.Expression> args) AstNode TransformByteCode_Internal(MethodDefinition methodDef, ILExpression byteCode, List<Ast.Expression> args)
{ {
// throw new NotImplementedException(); // throw new NotImplementedException();
@ -605,29 +601,15 @@ namespace Decompiler
case Code.Sizeof: return new Ast.SizeOfExpression { Type = AstBuilder.ConvertType(operand as TypeReference) }; case Code.Sizeof: return new Ast.SizeOfExpression { Type = AstBuilder.ConvertType(operand as TypeReference) };
case Code.Starg: throw new NotImplementedException(); case Code.Starg: throw new NotImplementedException();
case Code.Stloc: { case Code.Stloc: {
if (operand is ILVariable) { ILVariable locVar = (ILVariable)operand;
var astLocalVar = new Ast.VariableDeclarationStatement(); if (!definedLocalVars.Contains(locVar)) {
astLocalVar.Type = new Ast.PrimitiveType("var"); definedLocalVars.Add(locVar);
astLocalVar.Variables = new [] { return new Ast.VariableDeclarationStatement() {
new Ast.VariableInitializer(((ILVariable)operand).Name, arg1) 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 { } 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(); case Code.Stobj: throw new NotImplementedException();

16
ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs

@ -95,6 +95,8 @@ namespace Decompiler
Dictionary<Instruction, ByteCode> instrToByteCode = new Dictionary<Instruction, ByteCode>(); Dictionary<Instruction, ByteCode> instrToByteCode = new Dictionary<Instruction, ByteCode>();
Dictionary<ILVariable, bool> allowInline = new Dictionary<ILVariable, bool>(); Dictionary<ILVariable, bool> allowInline = new Dictionary<ILVariable, bool>();
public List<ILVariable> Variables;
public List<ILNode> Build(MethodDefinition methodDef, bool optimize) public List<ILNode> Build(MethodDefinition methodDef, bool optimize)
{ {
this.methodDef = methodDef; this.methodDef = methodDef;
@ -249,27 +251,27 @@ namespace Decompiler
} }
// Convert local varibles // Convert local varibles
List<ILVariable> vars = methodDef.Body.Variables.Select(v => new ILVariable() { Name = string.IsNullOrEmpty(v.Name) ? "var_" + v.Index : v.Name }).ToList(); 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[vars.Count]; int[] numReads = new int[Variables.Count];
int[] numWrites = new int[vars.Count]; int[] numWrites = new int[Variables.Count];
foreach(ByteCode byteCode in body) { foreach(ByteCode byteCode in body) {
if (byteCode.OpCode == OpCodes.Ldloc) { if (byteCode.OpCode == OpCodes.Ldloc) {
int index = ((VariableDefinition)byteCode.Operand).Index; int index = ((VariableDefinition)byteCode.Operand).Index;
byteCode.Operand = vars[index]; byteCode.Operand = Variables[index];
numReads[index]++; numReads[index]++;
} }
if (byteCode.OpCode == OpCodes.Stloc) { if (byteCode.OpCode == OpCodes.Stloc) {
int index = ((VariableDefinition)byteCode.Operand).Index; int index = ((VariableDefinition)byteCode.Operand).Index;
byteCode.Operand = vars[index]; byteCode.Operand = Variables[index];
numWrites[index]++; numWrites[index]++;
} }
} }
// Find which variables we can inline // Find which variables we can inline
if (this.optimize) { 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) { if (numReads[i] == 1 && numWrites[i] == 1) {
allowInline[vars[i]] = true; allowInline[Variables[i]] = true;
} }
} }
} }

11
ICSharpCode.Decompiler/ILAst/ILAstTypes.cs

@ -44,6 +44,11 @@ namespace Decompiler
{ {
yield break; yield break;
} }
public override string ToString()
{
return this.GetType().Name;
}
} }
public class ILBlock: ILNode public class ILBlock: ILNode
@ -102,17 +107,13 @@ namespace Decompiler
if (this.FinallyBlock != null) if (this.FinallyBlock != null)
yield return this.FinallyBlock; yield return this.FinallyBlock;
} }
public override string ToString()
{
return "Try-Catch{}";
}
} }
public class ILVariable public class ILVariable
{ {
public string Name; public string Name;
public bool IsGenerated; public bool IsGenerated;
public TypeReference Type;
public override string ToString() public override string ToString()
{ {

Loading…
Cancel
Save