Browse Source

Move decompiler code into ICSharpCode.Decompiler; add very simple integration with ILSpy.

pull/1/head^2
Daniel Grunwald 15 years ago
parent
commit
949e7c2378
  1. 632
      ICSharpCode.Decompiler/Ast/AstBuilder.cs
  2. 1496
      ICSharpCode.Decompiler/Ast/AstMetodBodyBuilder.cs
  3. 152
      ICSharpCode.Decompiler/Ast/Transforms/Idioms.cs
  4. 174
      ICSharpCode.Decompiler/Ast/Transforms/PushNegation.cs
  5. 100
      ICSharpCode.Decompiler/Ast/Transforms/RemoveDeadLabels.cs
  6. 72
      ICSharpCode.Decompiler/Ast/Transforms/RemoveEmptyElseBody.cs
  7. 372
      ICSharpCode.Decompiler/Ast/Transforms/RemoveGotos.cs
  8. 490
      ICSharpCode.Decompiler/Ast/Transforms/RemoveParenthesis.cs
  9. 150
      ICSharpCode.Decompiler/Ast/Transforms/RestoreLoop.cs
  10. 182
      ICSharpCode.Decompiler/Ast/Transforms/SimplifyTypeReferences.cs
  11. 30
      ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
  12. 384
      ICSharpCode.Decompiler/ILAst/ControlFlow/Node-Optimize.cs
  13. 466
      ICSharpCode.Decompiler/ILAst/ControlFlow/Node-Structure.cs
  14. 120
      ICSharpCode.Decompiler/ILAst/ControlFlow/Node-Transforms.cs
  15. 260
      ICSharpCode.Decompiler/ILAst/ControlFlow/NodeCollection.cs
  16. 510
      ICSharpCode.Decompiler/ILAst/ControlFlow/Nodes.cs
  17. 596
      ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs
  18. 174
      ICSharpCode.Decompiler/ILAst/ILAstTypes.cs
  19. 0
      ICSharpCode.Decompiler/Mono.Cecil.Rocks/Constants.cs
  20. 0
      ICSharpCode.Decompiler/Mono.Cecil.Rocks/MethodBodyRocks.cs
  21. 2
      ICSharpCode.Decompiler/Mono.Cecil.Rocks/MyRocks.cs
  22. 44
      ICSharpCode.Decompiler/Options.cs
  23. 10
      ILSpy.sln
  24. 10
      ILSpy/CSharpLanguage.cs

632
Decompiler/src/Ast/AstBuilder.cs → ICSharpCode.Decompiler/Ast/AstBuilder.cs

@ -1,316 +1,316 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using Ast = ICSharpCode.NRefactory.Ast; using Ast = ICSharpCode.NRefactory.Ast;
using ICSharpCode.NRefactory.Ast; using ICSharpCode.NRefactory.Ast;
using ICSharpCode.NRefactory.PrettyPrinter; using ICSharpCode.NRefactory.PrettyPrinter;
using Mono.Cecil; using Mono.Cecil;
using Mono.Cecil.Cil; using Mono.Cecil.Cil;
namespace Decompiler namespace Decompiler
{ {
public class AstBuilder public class AstBuilder
{ {
CompilationUnit astCompileUnit = new CompilationUnit(); CompilationUnit astCompileUnit = new CompilationUnit();
Dictionary<string, NamespaceDeclaration> astNamespaces = new Dictionary<string, NamespaceDeclaration>(); Dictionary<string, NamespaceDeclaration> astNamespaces = new Dictionary<string, NamespaceDeclaration>();
public string GenerateCode() public string GenerateCode()
{ {
CSharpOutputVisitor csOutVisitor = new CSharpOutputVisitor(); CSharpOutputVisitor csOutVisitor = new CSharpOutputVisitor();
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
if (Options.ReduceAstJumps) { if (Options.ReduceAstJumps) {
astCompileUnit.AcceptVisitor(new Transforms.Ast.RemoveGotos(), null); astCompileUnit.AcceptVisitor(new Transforms.Ast.RemoveGotos(), null);
astCompileUnit.AcceptVisitor(new Transforms.Ast.RemoveDeadLabels(), null); astCompileUnit.AcceptVisitor(new Transforms.Ast.RemoveDeadLabels(), null);
} }
if (Options.ReduceAstLoops) { if (Options.ReduceAstLoops) {
astCompileUnit.AcceptVisitor(new Transforms.Ast.RestoreLoop(), null); astCompileUnit.AcceptVisitor(new Transforms.Ast.RestoreLoop(), null);
} }
if (Options.ReduceAstOther) { if (Options.ReduceAstOther) {
astCompileUnit.AcceptVisitor(new Transforms.Ast.Idioms(), null); astCompileUnit.AcceptVisitor(new Transforms.Ast.Idioms(), null);
astCompileUnit.AcceptVisitor(new Transforms.Ast.RemoveEmptyElseBody(), null); astCompileUnit.AcceptVisitor(new Transforms.Ast.RemoveEmptyElseBody(), null);
astCompileUnit.AcceptVisitor(new Transforms.Ast.PushNegation(), null); astCompileUnit.AcceptVisitor(new Transforms.Ast.PushNegation(), null);
astCompileUnit.AcceptVisitor(new Transforms.Ast.PushNegation(), null); astCompileUnit.AcceptVisitor(new Transforms.Ast.PushNegation(), null);
astCompileUnit.AcceptVisitor(new Transforms.Ast.PushNegation(), null); astCompileUnit.AcceptVisitor(new Transforms.Ast.PushNegation(), null);
} }
} }
if (Options.ReduceAstOther) { if (Options.ReduceAstOther) {
astCompileUnit.AcceptVisitor(new Transforms.Ast.RemoveParenthesis(), null); astCompileUnit.AcceptVisitor(new Transforms.Ast.RemoveParenthesis(), null);
astCompileUnit.AcceptVisitor(new Transforms.Ast.RemoveParenthesis(), null); astCompileUnit.AcceptVisitor(new Transforms.Ast.RemoveParenthesis(), null);
astCompileUnit.AcceptVisitor(new Transforms.Ast.SimplifyTypeReferences(), null); astCompileUnit.AcceptVisitor(new Transforms.Ast.SimplifyTypeReferences(), null);
astCompileUnit.AcceptVisitor(new Transforms.Ast.Idioms(), null); astCompileUnit.AcceptVisitor(new Transforms.Ast.Idioms(), null);
} }
if (Options.ReduceAstLoops) { if (Options.ReduceAstLoops) {
astCompileUnit.AcceptVisitor(new Transforms.Ast.RestoreLoop(), null); astCompileUnit.AcceptVisitor(new Transforms.Ast.RestoreLoop(), null);
} }
astCompileUnit.AcceptVisitor(csOutVisitor, null); astCompileUnit.AcceptVisitor(csOutVisitor, null);
string code = csOutVisitor.Text; string code = csOutVisitor.Text;
for(int i = 10; i >= 0; i--) { for(int i = 10; i >= 0; i--) {
code = code.Replace("\r\n" + new string('\t', i) + "else {", " else {"); code = code.Replace("\r\n" + new string('\t', i) + "else {", " else {");
} }
code = code.Replace("\t", " "); code = code.Replace("\t", " ");
code = code.Replace("\"/***", ""); code = code.Replace("\"/***", "");
code = code.Replace("***/\";", ""); code = code.Replace("***/\";", "");
// Post processing commands // Post processing commands
while(true) { while(true) {
int endIndex = code.IndexOf("[JoinLine]") + "[JoinLine]".Length; int endIndex = code.IndexOf("[JoinLine]") + "[JoinLine]".Length;
if (endIndex != -1) { if (endIndex != -1) {
int startIndex = code.LastIndexOf("\r\n", endIndex, endIndex); int startIndex = code.LastIndexOf("\r\n", endIndex, endIndex);
if (startIndex != -1) { if (startIndex != -1) {
code = code.Remove(startIndex, endIndex - startIndex); code = code.Remove(startIndex, endIndex - startIndex);
continue; continue;
} }
} }
break; break;
} }
while(true) { while(true) {
int endIndex = code.IndexOf("[Tab]"); int endIndex = code.IndexOf("[Tab]");
if (endIndex != -1) { if (endIndex != -1) {
int startIndex = code.LastIndexOf("\r\n", endIndex, endIndex); int startIndex = code.LastIndexOf("\r\n", endIndex, endIndex);
if (startIndex != -1) { if (startIndex != -1) {
code = code.Remove(endIndex, "[Tab]".Length); code = code.Remove(endIndex, "[Tab]".Length);
code = code.Insert(endIndex, new string(' ', Math.Max(0, 40 - endIndex + startIndex))); code = code.Insert(endIndex, new string(' ', Math.Max(0, 40 - endIndex + startIndex)));
continue; continue;
} }
} }
break; break;
} }
return code; return code;
} }
public void AddAssembly(AssemblyDefinition assemblyDefinition) public void AddAssembly(AssemblyDefinition assemblyDefinition)
{ {
Ast.UsingDeclaration astUsing = new Ast.UsingDeclaration("System"); Ast.UsingDeclaration astUsing = new Ast.UsingDeclaration("System");
astCompileUnit.Children.Add(astUsing); astCompileUnit.Children.Add(astUsing);
foreach(TypeDefinition typeDef in assemblyDefinition.MainModule.Types) { foreach(TypeDefinition typeDef in assemblyDefinition.MainModule.Types) {
// Skip nested types - they will be added by the parent type // Skip nested types - they will be added by the parent type
if (typeDef.DeclaringType != null) continue; if (typeDef.DeclaringType != null) continue;
// Skip the <Module> class // Skip the <Module> class
if (typeDef.Name == "<Module>") continue; if (typeDef.Name == "<Module>") continue;
AddType(typeDef); AddType(typeDef);
} }
} }
NamespaceDeclaration GetCodeNamespace(string name) NamespaceDeclaration GetCodeNamespace(string name)
{ {
if (string.IsNullOrEmpty(name)) { if (string.IsNullOrEmpty(name)) {
return null; return null;
} }
if (astNamespaces.ContainsKey(name)) { if (astNamespaces.ContainsKey(name)) {
return astNamespaces[name]; return astNamespaces[name];
} else { } else {
// Create the namespace // Create the namespace
NamespaceDeclaration astNamespace = new NamespaceDeclaration(name); NamespaceDeclaration astNamespace = new NamespaceDeclaration(name);
astCompileUnit.Children.Add(astNamespace); astCompileUnit.Children.Add(astNamespace);
astNamespaces[name] = astNamespace; astNamespaces[name] = astNamespace;
return astNamespace; return astNamespace;
} }
} }
public void AddType(TypeDefinition typeDef) public void AddType(TypeDefinition typeDef)
{ {
if (!string.IsNullOrEmpty(Options.TypeFilter) && typeDef.Name != Options.TypeFilter) return; if (!string.IsNullOrEmpty(Options.TypeFilter) && typeDef.Name != Options.TypeFilter) return;
TypeDeclaration astType = CreateType(typeDef); TypeDeclaration astType = CreateType(typeDef);
NamespaceDeclaration astNS = GetCodeNamespace(typeDef.Namespace); NamespaceDeclaration astNS = GetCodeNamespace(typeDef.Namespace);
if (astNS != null) { if (astNS != null) {
astNS.Children.Add(astType); astNS.Children.Add(astType);
} else { } else {
astCompileUnit.Children.Add(astType); astCompileUnit.Children.Add(astType);
} }
} }
public TypeDeclaration CreateType(TypeDefinition typeDef) public TypeDeclaration CreateType(TypeDefinition typeDef)
{ {
TypeDeclaration astType = new TypeDeclaration(ConvertModifiers(typeDef), new List<AttributeSection>()); TypeDeclaration astType = new TypeDeclaration(ConvertModifiers(typeDef), new List<AttributeSection>());
astType.Name = typeDef.Name; astType.Name = typeDef.Name;
if (typeDef.IsEnum) { // NB: Enum is value type if (typeDef.IsEnum) { // NB: Enum is value type
astType.Type = ClassType.Enum; astType.Type = ClassType.Enum;
} else if (typeDef.IsValueType) { } else if (typeDef.IsValueType) {
astType.Type = ClassType.Struct; astType.Type = ClassType.Struct;
} else if (typeDef.IsInterface) { } else if (typeDef.IsInterface) {
astType.Type = ClassType.Interface; astType.Type = ClassType.Interface;
} else { } else {
astType.Type = ClassType.Class; astType.Type = ClassType.Class;
} }
// Nested types // Nested types
foreach(TypeDefinition nestedTypeDef in typeDef.NestedTypes) { foreach(TypeDefinition nestedTypeDef in typeDef.NestedTypes) {
astType.Children.Add(CreateType(nestedTypeDef)); astType.Children.Add(CreateType(nestedTypeDef));
} }
// Base type // Base type
if (typeDef.BaseType != null && !typeDef.IsValueType && typeDef.BaseType.FullName != Constants.Object) { if (typeDef.BaseType != null && !typeDef.IsValueType && typeDef.BaseType.FullName != Constants.Object) {
astType.BaseTypes.Add(new Ast.TypeReference(typeDef.BaseType.FullName)); astType.BaseTypes.Add(new Ast.TypeReference(typeDef.BaseType.FullName));
} }
AddTypeMembers(astType, typeDef); AddTypeMembers(astType, typeDef);
return astType; return astType;
} }
Modifiers ConvertModifiers(TypeDefinition typeDef) Modifiers ConvertModifiers(TypeDefinition typeDef)
{ {
return return
(typeDef.IsNestedPrivate ? Modifiers.Private : Modifiers.None) | (typeDef.IsNestedPrivate ? Modifiers.Private : Modifiers.None) |
(typeDef.IsNestedFamilyAndAssembly ? Modifiers.Protected : Modifiers.None) | // TODO: Extended access (typeDef.IsNestedFamilyAndAssembly ? Modifiers.Protected : Modifiers.None) | // TODO: Extended access
(typeDef.IsNestedAssembly ? Modifiers.Internal : Modifiers.None) | (typeDef.IsNestedAssembly ? Modifiers.Internal : Modifiers.None) |
(typeDef.IsNestedFamily ? Modifiers.Protected : Modifiers.None) | (typeDef.IsNestedFamily ? Modifiers.Protected : Modifiers.None) |
(typeDef.IsNestedFamilyOrAssembly ? Modifiers.Protected | Modifiers.Internal : Modifiers.None) | (typeDef.IsNestedFamilyOrAssembly ? Modifiers.Protected | Modifiers.Internal : Modifiers.None) |
(typeDef.IsPublic ? Modifiers.Public : Modifiers.None) | (typeDef.IsPublic ? Modifiers.Public : Modifiers.None) |
(typeDef.IsAbstract ? Modifiers.Abstract : Modifiers.None); (typeDef.IsAbstract ? Modifiers.Abstract : Modifiers.None);
} }
Modifiers ConvertModifiers(FieldDefinition fieldDef) Modifiers ConvertModifiers(FieldDefinition fieldDef)
{ {
return return
(fieldDef.IsPrivate ? Modifiers.Private : Modifiers.None) | (fieldDef.IsPrivate ? Modifiers.Private : Modifiers.None) |
(fieldDef.IsFamilyAndAssembly ? Modifiers.Protected : Modifiers.None) | // TODO: Extended access (fieldDef.IsFamilyAndAssembly ? Modifiers.Protected : Modifiers.None) | // TODO: Extended access
(fieldDef.IsAssembly ? Modifiers.Internal : Modifiers.None) | (fieldDef.IsAssembly ? Modifiers.Internal : Modifiers.None) |
(fieldDef.IsFamily ? Modifiers.Protected : Modifiers.None) | (fieldDef.IsFamily ? Modifiers.Protected : Modifiers.None) |
(fieldDef.IsFamilyOrAssembly ? Modifiers.Protected | Modifiers.Internal : Modifiers.None) | (fieldDef.IsFamilyOrAssembly ? Modifiers.Protected | Modifiers.Internal : Modifiers.None) |
(fieldDef.IsPublic ? Modifiers.Public : Modifiers.None) | (fieldDef.IsPublic ? Modifiers.Public : Modifiers.None) |
(fieldDef.IsLiteral ? Modifiers.Const : Modifiers.None) | (fieldDef.IsLiteral ? Modifiers.Const : Modifiers.None) |
(fieldDef.IsStatic ? Modifiers.Static : Modifiers.None); (fieldDef.IsStatic ? Modifiers.Static : Modifiers.None);
} }
Modifiers ConvertModifiers(MethodDefinition methodDef) Modifiers ConvertModifiers(MethodDefinition methodDef)
{ {
return return
(methodDef.IsCompilerControlled ? Modifiers.None : Modifiers.None) | (methodDef.IsCompilerControlled ? Modifiers.None : Modifiers.None) |
(methodDef.IsPrivate ? Modifiers.Private : Modifiers.None) | (methodDef.IsPrivate ? Modifiers.Private : Modifiers.None) |
(methodDef.IsFamilyAndAssembly ? Modifiers.Protected : Modifiers.None) | // TODO: Extended access (methodDef.IsFamilyAndAssembly ? Modifiers.Protected : Modifiers.None) | // TODO: Extended access
(methodDef.IsAssembly ? Modifiers.Internal : Modifiers.None) | (methodDef.IsAssembly ? Modifiers.Internal : Modifiers.None) |
(methodDef.IsFamily ? Modifiers.Protected : Modifiers.None) | (methodDef.IsFamily ? Modifiers.Protected : Modifiers.None) |
(methodDef.IsFamilyOrAssembly ? Modifiers.Protected | Modifiers.Internal : Modifiers.None) | (methodDef.IsFamilyOrAssembly ? Modifiers.Protected | Modifiers.Internal : Modifiers.None) |
(methodDef.IsPublic ? Modifiers.Public : Modifiers.None) | (methodDef.IsPublic ? Modifiers.Public : Modifiers.None) |
(methodDef.IsStatic ? Modifiers.Static : Modifiers.None) | (methodDef.IsStatic ? Modifiers.Static : Modifiers.None) |
(methodDef.IsVirtual ? Modifiers.Virtual : Modifiers.None) | (methodDef.IsVirtual ? Modifiers.Virtual : Modifiers.None) |
(methodDef.IsAbstract ? Modifiers.Abstract : Modifiers.None); (methodDef.IsAbstract ? Modifiers.Abstract : Modifiers.None);
} }
void AddTypeMembers(TypeDeclaration astType, TypeDefinition typeDef) void AddTypeMembers(TypeDeclaration astType, TypeDefinition typeDef)
{ {
// Add fields // Add fields
foreach(FieldDefinition fieldDef in typeDef.Fields) { foreach(FieldDefinition fieldDef in typeDef.Fields) {
Ast.FieldDeclaration astField = new Ast.FieldDeclaration(new List<AttributeSection>()); Ast.FieldDeclaration astField = new Ast.FieldDeclaration(new List<AttributeSection>());
astField.Fields.Add(new Ast.VariableDeclaration(fieldDef.Name)); astField.Fields.Add(new Ast.VariableDeclaration(fieldDef.Name));
astField.TypeReference = new Ast.TypeReference(fieldDef.FieldType.FullName); astField.TypeReference = new Ast.TypeReference(fieldDef.FieldType.FullName);
astField.Modifier = ConvertModifiers(fieldDef); astField.Modifier = ConvertModifiers(fieldDef);
astType.Children.Add(astField); astType.Children.Add(astField);
} }
if (typeDef.Fields.Count > 0) { if (typeDef.Fields.Count > 0) {
astType.Children.Add(new IdentifierExpression("\r\n")); astType.Children.Add(new IdentifierExpression("\r\n"));
} }
// Add events // Add events
foreach(EventDefinition eventDef in typeDef.Events) { foreach(EventDefinition eventDef in typeDef.Events) {
Ast.EventDeclaration astEvent = new Ast.EventDeclaration(); Ast.EventDeclaration astEvent = new Ast.EventDeclaration();
astEvent.Name = eventDef.Name; astEvent.Name = eventDef.Name;
astEvent.TypeReference = new Ast.TypeReference(eventDef.EventType.FullName); astEvent.TypeReference = new Ast.TypeReference(eventDef.EventType.FullName);
astEvent.Modifier = ConvertModifiers(eventDef.AddMethod); astEvent.Modifier = ConvertModifiers(eventDef.AddMethod);
astType.Children.Add(astEvent); astType.Children.Add(astEvent);
} }
if (typeDef.Events.Count > 0) { if (typeDef.Events.Count > 0) {
astType.Children.Add(new IdentifierExpression("\r\n")); astType.Children.Add(new IdentifierExpression("\r\n"));
} }
// Add properties // Add properties
foreach(PropertyDefinition propDef in typeDef.Properties) { foreach(PropertyDefinition propDef in typeDef.Properties) {
Ast.PropertyDeclaration astProp = new Ast.PropertyDeclaration( Ast.PropertyDeclaration astProp = new Ast.PropertyDeclaration(
ConvertModifiers(propDef.GetMethod), ConvertModifiers(propDef.GetMethod),
new List<AttributeSection>(), new List<AttributeSection>(),
propDef.Name, propDef.Name,
new List<ParameterDeclarationExpression>() new List<ParameterDeclarationExpression>()
); );
astProp.TypeReference = new Ast.TypeReference(propDef.PropertyType.FullName); astProp.TypeReference = new Ast.TypeReference(propDef.PropertyType.FullName);
if (propDef.GetMethod != null) { if (propDef.GetMethod != null) {
astProp.GetRegion = new PropertyGetRegion( astProp.GetRegion = new PropertyGetRegion(
AstMetodBodyBuilder.CreateMetodBody(propDef.GetMethod), AstMetodBodyBuilder.CreateMetodBody(propDef.GetMethod),
new List<AttributeSection>() new List<AttributeSection>()
); );
} }
if (propDef.SetMethod != null) { if (propDef.SetMethod != null) {
astProp.SetRegion = new PropertySetRegion( astProp.SetRegion = new PropertySetRegion(
AstMetodBodyBuilder.CreateMetodBody(propDef.SetMethod), AstMetodBodyBuilder.CreateMetodBody(propDef.SetMethod),
new List<AttributeSection>() new List<AttributeSection>()
); );
} }
astType.Children.Add(astProp); astType.Children.Add(astProp);
} }
if (typeDef.Properties.Count > 0) { if (typeDef.Properties.Count > 0) {
astType.Children.Add(new IdentifierExpression("\r\n")); astType.Children.Add(new IdentifierExpression("\r\n"));
} }
// Add constructors // Add constructors
foreach(MethodDefinition methodDef in typeDef.Methods) { foreach(MethodDefinition methodDef in typeDef.Methods) {
if (!methodDef.IsConstructor) continue; if (!methodDef.IsConstructor) continue;
Ast.ConstructorDeclaration astMethod = new Ast.ConstructorDeclaration( Ast.ConstructorDeclaration astMethod = new Ast.ConstructorDeclaration(
methodDef.Name, methodDef.Name,
ConvertModifiers(methodDef), ConvertModifiers(methodDef),
new List<ParameterDeclarationExpression>(MakeParameters(methodDef.Parameters)), new List<ParameterDeclarationExpression>(MakeParameters(methodDef.Parameters)),
new List<AttributeSection>() new List<AttributeSection>()
); );
astMethod.Body = AstMetodBodyBuilder.CreateMetodBody(methodDef); astMethod.Body = AstMetodBodyBuilder.CreateMetodBody(methodDef);
astType.Children.Add(astMethod); astType.Children.Add(astMethod);
astType.Children.Add(new IdentifierExpression("\r\n")); astType.Children.Add(new IdentifierExpression("\r\n"));
} }
// Add methods // Add methods
foreach(MethodDefinition methodDef in typeDef.Methods) { foreach(MethodDefinition methodDef in typeDef.Methods) {
if (methodDef.IsSpecialName) continue; if (methodDef.IsSpecialName) continue;
Ast.MethodDeclaration astMethod = new Ast.MethodDeclaration(); Ast.MethodDeclaration astMethod = new Ast.MethodDeclaration();
astMethod.Name = methodDef.Name; astMethod.Name = methodDef.Name;
astMethod.TypeReference = new Ast.TypeReference(methodDef.ReturnType.FullName); astMethod.TypeReference = new Ast.TypeReference(methodDef.ReturnType.FullName);
astMethod.Modifier = ConvertModifiers(methodDef); astMethod.Modifier = ConvertModifiers(methodDef);
astMethod.Parameters.AddRange(MakeParameters(methodDef.Parameters)); astMethod.Parameters.AddRange(MakeParameters(methodDef.Parameters));
astMethod.Body = AstMetodBodyBuilder.CreateMetodBody(methodDef); astMethod.Body = AstMetodBodyBuilder.CreateMetodBody(methodDef);
astType.Children.Add(astMethod); astType.Children.Add(astMethod);
astType.Children.Add(new IdentifierExpression("\r\n")); astType.Children.Add(new IdentifierExpression("\r\n"));
} }
if (astType.Children.LastOrDefault() is IdentifierExpression) { if (astType.Children.LastOrDefault() is IdentifierExpression) {
astType.Children.Last.Remove(); astType.Children.Last.Remove();
} }
} }
IEnumerable<Ast.ParameterDeclarationExpression> MakeParameters(IEnumerable<ParameterDefinition> paramCol) IEnumerable<Ast.ParameterDeclarationExpression> MakeParameters(IEnumerable<ParameterDefinition> paramCol)
{ {
foreach(ParameterDefinition paramDef in paramCol) { foreach(ParameterDefinition paramDef in paramCol) {
Ast.ParameterDeclarationExpression astParam = new Ast.ParameterDeclarationExpression( Ast.ParameterDeclarationExpression astParam = new Ast.ParameterDeclarationExpression(
new Ast.TypeReference(paramDef.ParameterType.FullName), new Ast.TypeReference(paramDef.ParameterType.FullName),
paramDef.Name paramDef.Name
); );
if (paramDef.IsIn && !paramDef.IsOut) astParam.ParamModifier = ParameterModifiers.In; if (paramDef.IsIn && !paramDef.IsOut) astParam.ParamModifier = ParameterModifiers.In;
if (!paramDef.IsIn && paramDef.IsOut) astParam.ParamModifier = ParameterModifiers.Out; if (!paramDef.IsIn && paramDef.IsOut) astParam.ParamModifier = ParameterModifiers.Out;
if (paramDef.IsIn && paramDef.IsOut) astParam.ParamModifier = ParameterModifiers.Ref; if (paramDef.IsIn && paramDef.IsOut) astParam.ParamModifier = ParameterModifiers.Ref;
yield return astParam; yield return astParam;
} }
} }
} }
} }

1496
Decompiler/src/Ast/AstMetodBodyBuilder.cs → ICSharpCode.Decompiler/Ast/AstMetodBodyBuilder.cs

File diff suppressed because it is too large Load Diff

152
Decompiler/src/Ast/Transforms/Idioms.cs → ICSharpCode.Decompiler/Ast/Transforms/Idioms.cs

@ -1,76 +1,76 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using Ast = ICSharpCode.NRefactory.Ast; using Ast = ICSharpCode.NRefactory.Ast;
using ICSharpCode.NRefactory.Ast; using ICSharpCode.NRefactory.Ast;
using ICSharpCode.NRefactory.Visitors; using ICSharpCode.NRefactory.Visitors;
namespace Decompiler.Transforms.Ast namespace Decompiler.Transforms.Ast
{ {
public class Idioms: AbstractAstTransformer public class Idioms: AbstractAstTransformer
{ {
public override object VisitInvocationExpression(InvocationExpression invocationExpression, object data) public override object VisitInvocationExpression(InvocationExpression invocationExpression, object data)
{ {
base.VisitInvocationExpression(invocationExpression, data); base.VisitInvocationExpression(invocationExpression, data);
// Reduce "String.Concat(a, b)" to "a + b" // Reduce "String.Concat(a, b)" to "a + b"
MemberReferenceExpression target = invocationExpression.TargetObject as MemberReferenceExpression; MemberReferenceExpression target = invocationExpression.TargetObject as MemberReferenceExpression;
if (target != null && if (target != null &&
target.MemberName == "Concat" && target.MemberName == "Concat" &&
invocationExpression.Arguments.Count == 2 && invocationExpression.Arguments.Count == 2 &&
target.TargetObject is IdentifierExpression && target.TargetObject is IdentifierExpression &&
(target.TargetObject as IdentifierExpression).Identifier == "String") (target.TargetObject as IdentifierExpression).Identifier == "String")
{ {
ReplaceCurrentNode( ReplaceCurrentNode(
new BinaryOperatorExpression( new BinaryOperatorExpression(
invocationExpression.Arguments[0], invocationExpression.Arguments[0],
BinaryOperatorType.Add, BinaryOperatorType.Add,
invocationExpression.Arguments[1] invocationExpression.Arguments[1]
) )
); );
} }
return null; return null;
} }
public override object VisitAssignmentExpression(AssignmentExpression assignment, object data) public override object VisitAssignmentExpression(AssignmentExpression assignment, object data)
{ {
IdentifierExpression ident = assignment.Left as IdentifierExpression; IdentifierExpression ident = assignment.Left as IdentifierExpression;
BinaryOperatorExpression binary = assignment.Right as BinaryOperatorExpression; BinaryOperatorExpression binary = assignment.Right as BinaryOperatorExpression;
if (ident != null && binary != null) { if (ident != null && binary != null) {
IdentifierExpression binaryLeft = binary.Left as IdentifierExpression; IdentifierExpression binaryLeft = binary.Left as IdentifierExpression;
if (binaryLeft != null && if (binaryLeft != null &&
binaryLeft.Identifier == ident.Identifier) { binaryLeft.Identifier == ident.Identifier) {
if (binary.Right is PrimitiveExpression && if (binary.Right is PrimitiveExpression &&
1.Equals((binary.Right as PrimitiveExpression).Value)) { 1.Equals((binary.Right as PrimitiveExpression).Value)) {
if (binary.Op == BinaryOperatorType.Add) { if (binary.Op == BinaryOperatorType.Add) {
ReplaceCurrentNode(new UnaryOperatorExpression(ident, UnaryOperatorType.PostIncrement)); ReplaceCurrentNode(new UnaryOperatorExpression(ident, UnaryOperatorType.PostIncrement));
} }
if (binary.Op == BinaryOperatorType.Subtract) { if (binary.Op == BinaryOperatorType.Subtract) {
ReplaceCurrentNode(new UnaryOperatorExpression(ident, UnaryOperatorType.PostDecrement)); ReplaceCurrentNode(new UnaryOperatorExpression(ident, UnaryOperatorType.PostDecrement));
} }
} else { } else {
if (binary.Op == BinaryOperatorType.Add) { if (binary.Op == BinaryOperatorType.Add) {
ReplaceCurrentNode(new AssignmentExpression(ident, AssignmentOperatorType.Add, binary.Right)); ReplaceCurrentNode(new AssignmentExpression(ident, AssignmentOperatorType.Add, binary.Right));
} }
if (binary.Op == BinaryOperatorType.Subtract) { if (binary.Op == BinaryOperatorType.Subtract) {
ReplaceCurrentNode(new AssignmentExpression(ident, AssignmentOperatorType.Subtract, binary.Right)); ReplaceCurrentNode(new AssignmentExpression(ident, AssignmentOperatorType.Subtract, binary.Right));
} }
} }
return null; return null;
} }
} }
return null; return null;
} }
public override object VisitCastExpression(CastExpression castExpression, object data) public override object VisitCastExpression(CastExpression castExpression, object data)
{ {
if (castExpression.CastTo.Type == "int" && if (castExpression.CastTo.Type == "int" &&
castExpression.Expression is MemberReferenceExpression && castExpression.Expression is MemberReferenceExpression &&
(castExpression.Expression as MemberReferenceExpression).MemberName == "Length") { (castExpression.Expression as MemberReferenceExpression).MemberName == "Length") {
ReplaceCurrentNode(castExpression.Expression); ReplaceCurrentNode(castExpression.Expression);
return null; return null;
} }
return base.VisitCastExpression(castExpression, data); return base.VisitCastExpression(castExpression, data);
} }
} }
} }

174
Decompiler/src/Ast/Transforms/PushNegation.cs → ICSharpCode.Decompiler/Ast/Transforms/PushNegation.cs

@ -1,87 +1,87 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using ICSharpCode.NRefactory.Ast; using ICSharpCode.NRefactory.Ast;
using ICSharpCode.NRefactory.Visitors; using ICSharpCode.NRefactory.Visitors;
namespace Decompiler.Transforms.Ast namespace Decompiler.Transforms.Ast
{ {
public class PushNegation: AbstractAstTransformer public class PushNegation: AbstractAstTransformer
{ {
public override object VisitUnaryOperatorExpression(UnaryOperatorExpression unary, object data) public override object VisitUnaryOperatorExpression(UnaryOperatorExpression unary, object data)
{ {
// Remove double negation // Remove double negation
// !!a // !!a
if (unary.Op == UnaryOperatorType.Not && if (unary.Op == UnaryOperatorType.Not &&
unary.Expression is UnaryOperatorExpression && unary.Expression is UnaryOperatorExpression &&
(unary.Expression as UnaryOperatorExpression).Op == UnaryOperatorType.Not) { (unary.Expression as UnaryOperatorExpression).Op == UnaryOperatorType.Not) {
Expression newParenth = new ParenthesizedExpression((unary.Expression as UnaryOperatorExpression).Expression); Expression newParenth = new ParenthesizedExpression((unary.Expression as UnaryOperatorExpression).Expression);
ReplaceCurrentNode(newParenth); ReplaceCurrentNode(newParenth);
return newParenth.AcceptVisitor(this, data); return newParenth.AcceptVisitor(this, data);
} }
// Basic assumtion is that we have something in form !(a) // Basic assumtion is that we have something in form !(a)
if (unary.Op == UnaryOperatorType.Not && if (unary.Op == UnaryOperatorType.Not &&
unary.Expression is ParenthesizedExpression) { unary.Expression is ParenthesizedExpression) {
ParenthesizedExpression parenth = ((ParenthesizedExpression)unary.Expression); ParenthesizedExpression parenth = ((ParenthesizedExpression)unary.Expression);
// Push through two parenthesis // Push through two parenthesis
// !((a)) // !((a))
if (parenth.Expression is ParenthesizedExpression) { if (parenth.Expression is ParenthesizedExpression) {
parenth.Expression = new UnaryOperatorExpression(parenth.Expression, UnaryOperatorType.Not); parenth.Expression = new UnaryOperatorExpression(parenth.Expression, UnaryOperatorType.Not);
ReplaceCurrentNode(parenth); ReplaceCurrentNode(parenth);
return parenth.AcceptVisitor(this, data); return parenth.AcceptVisitor(this, data);
} }
// Remove double negation // Remove double negation
// !(!a) // !(!a)
if (parenth.Expression is UnaryOperatorExpression && if (parenth.Expression is UnaryOperatorExpression &&
(parenth.Expression as UnaryOperatorExpression).Op == UnaryOperatorType.Not) { (parenth.Expression as UnaryOperatorExpression).Op == UnaryOperatorType.Not) {
parenth.Expression = (parenth.Expression as UnaryOperatorExpression).Expression; parenth.Expression = (parenth.Expression as UnaryOperatorExpression).Expression;
ReplaceCurrentNode(parenth); ReplaceCurrentNode(parenth);
return parenth.AcceptVisitor(this, data); return parenth.AcceptVisitor(this, data);
} }
// Push through binary operation // Push through binary operation
// !((a) op (b)) // !((a) op (b))
BinaryOperatorExpression binaryOp = parenth.Expression as BinaryOperatorExpression; BinaryOperatorExpression binaryOp = parenth.Expression as BinaryOperatorExpression;
if (binaryOp != null && if (binaryOp != null &&
binaryOp.Left is ParenthesizedExpression && binaryOp.Left is ParenthesizedExpression &&
binaryOp.Right is ParenthesizedExpression) { binaryOp.Right is ParenthesizedExpression) {
bool sucessful = true; bool sucessful = true;
switch(binaryOp.Op) { switch(binaryOp.Op) {
case BinaryOperatorType.Equality: binaryOp.Op = BinaryOperatorType.InEquality; break; case BinaryOperatorType.Equality: binaryOp.Op = BinaryOperatorType.InEquality; break;
case BinaryOperatorType.InEquality: binaryOp.Op = BinaryOperatorType.Equality; break; case BinaryOperatorType.InEquality: binaryOp.Op = BinaryOperatorType.Equality; break;
case BinaryOperatorType.GreaterThan: binaryOp.Op = BinaryOperatorType.LessThanOrEqual; break; case BinaryOperatorType.GreaterThan: binaryOp.Op = BinaryOperatorType.LessThanOrEqual; break;
case BinaryOperatorType.GreaterThanOrEqual: binaryOp.Op = BinaryOperatorType.LessThan; break; case BinaryOperatorType.GreaterThanOrEqual: binaryOp.Op = BinaryOperatorType.LessThan; break;
case BinaryOperatorType.LessThanOrEqual: binaryOp.Op = BinaryOperatorType.GreaterThan; break; case BinaryOperatorType.LessThanOrEqual: binaryOp.Op = BinaryOperatorType.GreaterThan; break;
case BinaryOperatorType.LessThan: binaryOp.Op = BinaryOperatorType.GreaterThanOrEqual; break; case BinaryOperatorType.LessThan: binaryOp.Op = BinaryOperatorType.GreaterThanOrEqual; break;
default: sucessful = false; break; default: sucessful = false; break;
} }
if (sucessful) { if (sucessful) {
ReplaceCurrentNode(parenth); ReplaceCurrentNode(parenth);
return parenth.AcceptVisitor(this, data); return parenth.AcceptVisitor(this, data);
} }
sucessful = true; sucessful = true;
switch(binaryOp.Op) { switch(binaryOp.Op) {
case BinaryOperatorType.BitwiseAnd: binaryOp.Op = BinaryOperatorType.BitwiseOr; break; case BinaryOperatorType.BitwiseAnd: binaryOp.Op = BinaryOperatorType.BitwiseOr; break;
case BinaryOperatorType.BitwiseOr: binaryOp.Op = BinaryOperatorType.BitwiseAnd; break; case BinaryOperatorType.BitwiseOr: binaryOp.Op = BinaryOperatorType.BitwiseAnd; break;
case BinaryOperatorType.LogicalAnd: binaryOp.Op = BinaryOperatorType.LogicalOr; break; case BinaryOperatorType.LogicalAnd: binaryOp.Op = BinaryOperatorType.LogicalOr; break;
case BinaryOperatorType.LogicalOr: binaryOp.Op = BinaryOperatorType.LogicalAnd; break; case BinaryOperatorType.LogicalOr: binaryOp.Op = BinaryOperatorType.LogicalAnd; break;
default: sucessful = false; break; default: sucessful = false; break;
} }
if (sucessful) { if (sucessful) {
binaryOp.Left = new UnaryOperatorExpression(binaryOp.Left, UnaryOperatorType.Not); binaryOp.Left = new UnaryOperatorExpression(binaryOp.Left, UnaryOperatorType.Not);
binaryOp.Right = new UnaryOperatorExpression(binaryOp.Right, UnaryOperatorType.Not); binaryOp.Right = new UnaryOperatorExpression(binaryOp.Right, UnaryOperatorType.Not);
ReplaceCurrentNode(parenth); ReplaceCurrentNode(parenth);
return parenth.AcceptVisitor(this, data); return parenth.AcceptVisitor(this, data);
} }
} }
} }
return base.VisitUnaryOperatorExpression(unary, data); return base.VisitUnaryOperatorExpression(unary, data);
} }
} }
} }

100
Decompiler/src/Ast/Transforms/RemoveDeadLabels.cs → ICSharpCode.Decompiler/Ast/Transforms/RemoveDeadLabels.cs

@ -1,50 +1,50 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using Ast = ICSharpCode.NRefactory.Ast; using Ast = ICSharpCode.NRefactory.Ast;
using ICSharpCode.NRefactory.Ast; using ICSharpCode.NRefactory.Ast;
using ICSharpCode.NRefactory.Visitors; using ICSharpCode.NRefactory.Visitors;
namespace Decompiler.Transforms.Ast namespace Decompiler.Transforms.Ast
{ {
public class RemoveDeadLabels: AbstractAstTransformer public class RemoveDeadLabels: AbstractAstTransformer
{ {
List<string> usedLabels = new List<string>(); List<string> usedLabels = new List<string>();
bool collectingUsedLabels; bool collectingUsedLabels;
public override object VisitConstructorDeclaration(ConstructorDeclaration constructorDeclaration, object data) public override object VisitConstructorDeclaration(ConstructorDeclaration constructorDeclaration, object data)
{ {
collectingUsedLabels = true; collectingUsedLabels = true;
base.VisitConstructorDeclaration(constructorDeclaration, data); base.VisitConstructorDeclaration(constructorDeclaration, data);
collectingUsedLabels = false; collectingUsedLabels = false;
base.VisitConstructorDeclaration(constructorDeclaration, data); base.VisitConstructorDeclaration(constructorDeclaration, data);
return null; return null;
} }
public override object VisitMethodDeclaration(MethodDeclaration methodDeclaration, object data) public override object VisitMethodDeclaration(MethodDeclaration methodDeclaration, object data)
{ {
collectingUsedLabels = true; collectingUsedLabels = true;
base.VisitMethodDeclaration(methodDeclaration, data); base.VisitMethodDeclaration(methodDeclaration, data);
collectingUsedLabels = false; collectingUsedLabels = false;
base.VisitMethodDeclaration(methodDeclaration, data); base.VisitMethodDeclaration(methodDeclaration, data);
return null; return null;
} }
public override object VisitGotoStatement(GotoStatement gotoStatement, object data) public override object VisitGotoStatement(GotoStatement gotoStatement, object data)
{ {
if (collectingUsedLabels) { if (collectingUsedLabels) {
usedLabels.Add(gotoStatement.Label); usedLabels.Add(gotoStatement.Label);
} }
return null; return null;
} }
public override object VisitLabelStatement(LabelStatement labelStatement, object data) public override object VisitLabelStatement(LabelStatement labelStatement, object data)
{ {
if (!collectingUsedLabels) { if (!collectingUsedLabels) {
if (!usedLabels.Contains(labelStatement.Label)) { if (!usedLabels.Contains(labelStatement.Label)) {
RemoveCurrentNode(); RemoveCurrentNode();
} }
} }
return null; return null;
} }
} }
} }

72
Decompiler/src/Ast/Transforms/RemoveEmptyElseBody.cs → ICSharpCode.Decompiler/Ast/Transforms/RemoveEmptyElseBody.cs

@ -1,36 +1,36 @@
using System; using System;
using Ast = ICSharpCode.NRefactory.Ast; using Ast = ICSharpCode.NRefactory.Ast;
using ICSharpCode.NRefactory.Ast; using ICSharpCode.NRefactory.Ast;
using ICSharpCode.NRefactory.Visitors; using ICSharpCode.NRefactory.Visitors;
namespace Decompiler.Transforms.Ast namespace Decompiler.Transforms.Ast
{ {
public class RemoveEmptyElseBody: AbstractAstTransformer public class RemoveEmptyElseBody: AbstractAstTransformer
{ {
public override object VisitBlockStatement(BlockStatement blockStatement, object data) public override object VisitBlockStatement(BlockStatement blockStatement, object data)
{ {
for(int i = 0; i < blockStatement.Children.Count; i++) { for(int i = 0; i < blockStatement.Children.Count; i++) {
if (blockStatement.Children[i] is Statement && if (blockStatement.Children[i] is Statement &&
((Statement)blockStatement.Children[i]).IsNull) ((Statement)blockStatement.Children[i]).IsNull)
{ {
blockStatement.Children.RemoveAt(i); blockStatement.Children.RemoveAt(i);
i--; i--;
} }
} }
return base.VisitBlockStatement(blockStatement, data); return base.VisitBlockStatement(blockStatement, data);
} }
public override object VisitIfElseStatement(IfElseStatement ifElseStatement, object data) public override object VisitIfElseStatement(IfElseStatement ifElseStatement, object data)
{ {
base.VisitIfElseStatement(ifElseStatement, data); base.VisitIfElseStatement(ifElseStatement, data);
if (ifElseStatement.FalseStatement.Count == 1 && if (ifElseStatement.FalseStatement.Count == 1 &&
ifElseStatement.FalseStatement[0] is BlockStatement && ifElseStatement.FalseStatement[0] is BlockStatement &&
ifElseStatement.FalseStatement[0].Children.Count == 0) ifElseStatement.FalseStatement[0].Children.Count == 0)
{ {
ifElseStatement.FalseStatement.Clear(); ifElseStatement.FalseStatement.Clear();
} }
return null; return null;
} }
} }
} }

372
Decompiler/src/Ast/Transforms/RemoveGotos.cs → ICSharpCode.Decompiler/Ast/Transforms/RemoveGotos.cs

@ -1,186 +1,186 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using ICSharpCode.NRefactory.Ast; using ICSharpCode.NRefactory.Ast;
using ICSharpCode.NRefactory.Visitors; using ICSharpCode.NRefactory.Visitors;
namespace Decompiler.Transforms.Ast namespace Decompiler.Transforms.Ast
{ {
public class RemoveGotos: AbstractAstTransformer public class RemoveGotos: AbstractAstTransformer
{ {
Stack<StatementWithEmbeddedStatement> enteredLoops = new Stack<StatementWithEmbeddedStatement>(); Stack<StatementWithEmbeddedStatement> enteredLoops = new Stack<StatementWithEmbeddedStatement>();
StatementWithEmbeddedStatement CurrentLoop { StatementWithEmbeddedStatement CurrentLoop {
get { get {
if (enteredLoops.Count > 0) { if (enteredLoops.Count > 0) {
return enteredLoops.Peek(); return enteredLoops.Peek();
} else { } else {
return null; return null;
} }
} }
} }
public override object VisitForStatement(ForStatement forStatement, object data) public override object VisitForStatement(ForStatement forStatement, object data)
{ {
enteredLoops.Push(forStatement); enteredLoops.Push(forStatement);
base.VisitForStatement(forStatement, data); base.VisitForStatement(forStatement, data);
enteredLoops.Pop(); enteredLoops.Pop();
return null; return null;
} }
public override object VisitDoLoopStatement(DoLoopStatement doLoopStatement, object data) public override object VisitDoLoopStatement(DoLoopStatement doLoopStatement, object data)
{ {
enteredLoops.Push(doLoopStatement); enteredLoops.Push(doLoopStatement);
base.VisitDoLoopStatement(doLoopStatement, data); base.VisitDoLoopStatement(doLoopStatement, data);
enteredLoops.Pop(); enteredLoops.Pop();
return null; return null;
} }
public override object VisitBlockStatement(BlockStatement blockStatement, object data) public override object VisitBlockStatement(BlockStatement blockStatement, object data)
{ {
base.VisitBlockStatement(blockStatement, data); base.VisitBlockStatement(blockStatement, data);
// Remove redundant jump at the end of block // Remove redundant jump at the end of block
INode lastStmt = blockStatement.Children.Last; INode lastStmt = blockStatement.Children.Last;
// End of while loop // End of while loop
if (lastStmt is ContinueStatement && if (lastStmt is ContinueStatement &&
blockStatement.Parent is DoLoopStatement) blockStatement.Parent is DoLoopStatement)
{ {
lastStmt.Remove(); lastStmt.Remove();
return null; return null;
} }
// End of for loop // End of for loop
if (lastStmt is ContinueStatement && if (lastStmt is ContinueStatement &&
blockStatement.Parent is ForStatement) blockStatement.Parent is ForStatement)
{ {
lastStmt.Remove(); lastStmt.Remove();
return null; return null;
} }
// End of method // End of method
if (lastStmt is ReturnStatement && if (lastStmt is ReturnStatement &&
(blockStatement.Parent is MethodDeclaration || blockStatement.Parent is ConstructorDeclaration) && (blockStatement.Parent is MethodDeclaration || blockStatement.Parent is ConstructorDeclaration) &&
((ReturnStatement)lastStmt).Expression.IsNull) ((ReturnStatement)lastStmt).Expression.IsNull)
{ {
lastStmt.Remove(); lastStmt.Remove();
return null; return null;
} }
return null; return null;
} }
// Get the next statement that will be executed after this one // Get the next statement that will be executed after this one
// May return null // May return null
public static INode GetNextStatement(Statement statement) public static INode GetNextStatement(Statement statement)
{ {
if (statement == null) throw new ArgumentNullException(); if (statement == null) throw new ArgumentNullException();
Statement next = (Statement)statement.Next(); Statement next = (Statement)statement.Next();
if (next != null) { if (next != null) {
return EnterBlockStatement(next); return EnterBlockStatement(next);
} else { } else {
if (statement.Parent is BlockStatement && if (statement.Parent is BlockStatement &&
statement.Parent.Parent is Statement) { statement.Parent.Parent is Statement) {
return ExitBlockStatement((Statement)statement.Parent.Parent); return ExitBlockStatement((Statement)statement.Parent.Parent);
} else { } else {
return null; return null;
} }
} }
} }
// Get the statement that will be executed once the given block exits by the end brace // Get the statement that will be executed once the given block exits by the end brace
// May return null // May return null
public static INode ExitBlockStatement(Statement statement) public static INode ExitBlockStatement(Statement statement)
{ {
if (statement == null) throw new ArgumentNullException(); if (statement == null) throw new ArgumentNullException();
// When an 'if' body is finished the execution continues with the // When an 'if' body is finished the execution continues with the
// next statement after the 'if' statement // next statement after the 'if' statement
if (statement is IfElseStatement) { if (statement is IfElseStatement) {
return GetNextStatement((IfElseStatement)statement); return GetNextStatement((IfElseStatement)statement);
} }
// When a 'for' body is finished the execution continues by: // When a 'for' body is finished the execution continues by:
// Iterator; Condition; Body // Iterator; Condition; Body
if (statement is ForStatement) { if (statement is ForStatement) {
ForStatement forLoop = statement as ForStatement; ForStatement forLoop = statement as ForStatement;
if (forLoop.Iterator.Count > 0) { if (forLoop.Iterator.Count > 0) {
return forLoop.Iterator[0]; return forLoop.Iterator[0];
} else if (!forLoop.Condition.IsNull) { } else if (!forLoop.Condition.IsNull) {
return forLoop.Condition; return forLoop.Condition;
} else { } else {
return EnterBlockStatement((Statement)forLoop.EmbeddedStatement.Children.First); return EnterBlockStatement((Statement)forLoop.EmbeddedStatement.Children.First);
} }
} }
return null; return null;
} }
// Get the first statement that will be executed in the given block // Get the first statement that will be executed in the given block
public static INode EnterBlockStatement(Statement statement) public static INode EnterBlockStatement(Statement statement)
{ {
if (statement == null) throw new ArgumentNullException(); if (statement == null) throw new ArgumentNullException();
// For loop starts as follows: Initializers; Condition; Body // For loop starts as follows: Initializers; Condition; Body
if (statement is ForStatement) { if (statement is ForStatement) {
ForStatement forLoop = statement as ForStatement; ForStatement forLoop = statement as ForStatement;
if (forLoop.Initializers.Count > 0) { if (forLoop.Initializers.Count > 0) {
return forLoop.Initializers[0]; return forLoop.Initializers[0];
} else if (!forLoop.Condition.IsNull) { } else if (!forLoop.Condition.IsNull) {
return forLoop.Condition; return forLoop.Condition;
} else if (forLoop.EmbeddedStatement is BlockStatement && } else if (forLoop.EmbeddedStatement is BlockStatement &&
forLoop.EmbeddedStatement.Children.Count > 0) { forLoop.EmbeddedStatement.Children.Count > 0) {
statement = (Statement)forLoop.EmbeddedStatement.Children.First; statement = (Statement)forLoop.EmbeddedStatement.Children.First;
return EnterBlockStatement(statement); // Simplify again return EnterBlockStatement(statement); // Simplify again
} }
} }
return statement; // Can not simplify return statement; // Can not simplify
} }
public override object VisitGotoStatement(GotoStatement gotoStatement, object data) public override object VisitGotoStatement(GotoStatement gotoStatement, object data)
{ {
// Remove redundant goto which goes to a label that imideately follows // Remove redundant goto which goes to a label that imideately follows
INode fallthoughTarget = GetNextStatement(gotoStatement); INode fallthoughTarget = GetNextStatement(gotoStatement);
if ((fallthoughTarget is LabelStatement) && if ((fallthoughTarget is LabelStatement) &&
(fallthoughTarget as LabelStatement).Label == gotoStatement.Label) { (fallthoughTarget as LabelStatement).Label == gotoStatement.Label) {
RemoveCurrentNode(); RemoveCurrentNode();
return null; return null;
} }
// Replace goto with 'break' // Replace goto with 'break'
// Break statement moves right outside the looop // Break statement moves right outside the looop
if (CurrentLoop != null) { if (CurrentLoop != null) {
INode breakTarget = GetNextStatement(CurrentLoop); INode breakTarget = GetNextStatement(CurrentLoop);
if ((breakTarget is LabelStatement) && if ((breakTarget is LabelStatement) &&
(breakTarget as LabelStatement).Label == gotoStatement.Label) { (breakTarget as LabelStatement).Label == gotoStatement.Label) {
ReplaceCurrentNode(new BreakStatement()); ReplaceCurrentNode(new BreakStatement());
return null; return null;
} }
} }
// Replace goto with 'continue' // Replace goto with 'continue'
// Continue statement which moves at the very end of loop // Continue statement which moves at the very end of loop
if (CurrentLoop != null && if (CurrentLoop != null &&
(CurrentLoop.EmbeddedStatement is BlockStatement) && (CurrentLoop.EmbeddedStatement is BlockStatement) &&
((CurrentLoop.EmbeddedStatement as BlockStatement).Children.Last as LabelStatement) != null && ((CurrentLoop.EmbeddedStatement as BlockStatement).Children.Last as LabelStatement) != null &&
((CurrentLoop.EmbeddedStatement as BlockStatement).Children.Last as LabelStatement).Label == gotoStatement.Label) { ((CurrentLoop.EmbeddedStatement as BlockStatement).Children.Last as LabelStatement).Label == gotoStatement.Label) {
ReplaceCurrentNode(new ContinueStatement()); ReplaceCurrentNode(new ContinueStatement());
return null; return null;
} }
// Replace goto with 'continue' // Replace goto with 'continue'
// Continue statement which moves at the very start of for loop // Continue statement which moves at the very start of for loop
if (CurrentLoop != null) { if (CurrentLoop != null) {
INode continueTarget = ExitBlockStatement(CurrentLoop); // The start of the loop INode continueTarget = ExitBlockStatement(CurrentLoop); // The start of the loop
if ((continueTarget is LabelStatement) && if ((continueTarget is LabelStatement) &&
(continueTarget as LabelStatement).Label == gotoStatement.Label) { (continueTarget as LabelStatement).Label == gotoStatement.Label) {
ReplaceCurrentNode(new ContinueStatement()); ReplaceCurrentNode(new ContinueStatement());
return null; return null;
} }
} }
return null; return null;
} }
} }
} }

490
Decompiler/src/Ast/Transforms/RemoveParenthesis.cs → ICSharpCode.Decompiler/Ast/Transforms/RemoveParenthesis.cs

@ -1,245 +1,245 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using ICSharpCode.NRefactory.Ast; using ICSharpCode.NRefactory.Ast;
using ICSharpCode.NRefactory.Visitors; using ICSharpCode.NRefactory.Visitors;
namespace Decompiler.Transforms.Ast namespace Decompiler.Transforms.Ast
{ {
public class RemoveParenthesis: AbstractAstTransformer public class RemoveParenthesis: AbstractAstTransformer
{ {
public override object VisitParenthesizedExpression(ParenthesizedExpression parenthesizedExpression, object data) public override object VisitParenthesizedExpression(ParenthesizedExpression parenthesizedExpression, object data)
{ {
// The following do not need to be parenthesized // The following do not need to be parenthesized
if (parenthesizedExpression.Expression is IdentifierExpression || if (parenthesizedExpression.Expression is IdentifierExpression ||
parenthesizedExpression.Expression is PrimitiveExpression || parenthesizedExpression.Expression is PrimitiveExpression ||
parenthesizedExpression.Expression is ThisReferenceExpression || parenthesizedExpression.Expression is ThisReferenceExpression ||
parenthesizedExpression.Expression is ParenthesizedExpression) { parenthesizedExpression.Expression is ParenthesizedExpression) {
ReplaceCurrentNode(parenthesizedExpression.Expression); ReplaceCurrentNode(parenthesizedExpression.Expression);
return null; return null;
} }
return base.VisitParenthesizedExpression(parenthesizedExpression, data); return base.VisitParenthesizedExpression(parenthesizedExpression, data);
} }
public override object VisitAssignmentExpression(AssignmentExpression assignmentExpression, object data) public override object VisitAssignmentExpression(AssignmentExpression assignmentExpression, object data)
{ {
assignmentExpression.Left = Deparenthesize(assignmentExpression.Left); assignmentExpression.Left = Deparenthesize(assignmentExpression.Left);
assignmentExpression.Right = Deparenthesize(assignmentExpression.Right); assignmentExpression.Right = Deparenthesize(assignmentExpression.Right);
return base.VisitAssignmentExpression(assignmentExpression, data); return base.VisitAssignmentExpression(assignmentExpression, data);
} }
public override object VisitArrayCreateExpression(ArrayCreateExpression array, object data) public override object VisitArrayCreateExpression(ArrayCreateExpression array, object data)
{ {
for(int i = 0; i < array.Arguments.Count; i++) { for(int i = 0; i < array.Arguments.Count; i++) {
array.Arguments[i] = Deparenthesize(array.Arguments[i]); array.Arguments[i] = Deparenthesize(array.Arguments[i]);
} }
return base.VisitArrayCreateExpression(array, data); return base.VisitArrayCreateExpression(array, data);
} }
public override object VisitReturnStatement(ReturnStatement returnStatement, object data) public override object VisitReturnStatement(ReturnStatement returnStatement, object data)
{ {
returnStatement.Expression = Deparenthesize(returnStatement.Expression); returnStatement.Expression = Deparenthesize(returnStatement.Expression);
return base.VisitReturnStatement(returnStatement, data); return base.VisitReturnStatement(returnStatement, data);
} }
public override object VisitCastExpression(CastExpression castExpression, object data) public override object VisitCastExpression(CastExpression castExpression, object data)
{ {
if (GetPrecedence(castExpression.Expression) > GetPrecedence(castExpression)) { if (GetPrecedence(castExpression.Expression) > GetPrecedence(castExpression)) {
castExpression.Expression = Deparenthesize(castExpression.Expression); castExpression.Expression = Deparenthesize(castExpression.Expression);
} }
return base.VisitCastExpression(castExpression, data); return base.VisitCastExpression(castExpression, data);
} }
public override object VisitIndexerExpression(IndexerExpression indexer, object data) public override object VisitIndexerExpression(IndexerExpression indexer, object data)
{ {
if (GetPrecedence(indexer.TargetObject) >= GetPrecedence(indexer)) { if (GetPrecedence(indexer.TargetObject) >= GetPrecedence(indexer)) {
indexer.TargetObject = Deparenthesize(indexer.TargetObject); indexer.TargetObject = Deparenthesize(indexer.TargetObject);
} }
return base.VisitIndexerExpression(indexer, data); return base.VisitIndexerExpression(indexer, data);
} }
public override object VisitIfElseStatement(IfElseStatement ifElseStatement, object data) public override object VisitIfElseStatement(IfElseStatement ifElseStatement, object data)
{ {
ifElseStatement.Condition = Deparenthesize(ifElseStatement.Condition); ifElseStatement.Condition = Deparenthesize(ifElseStatement.Condition);
return base.VisitIfElseStatement(ifElseStatement, data); return base.VisitIfElseStatement(ifElseStatement, data);
} }
public override object VisitVariableDeclaration(VariableDeclaration variableDeclaration, object data) public override object VisitVariableDeclaration(VariableDeclaration variableDeclaration, object data)
{ {
variableDeclaration.Initializer = Deparenthesize(variableDeclaration.Initializer); variableDeclaration.Initializer = Deparenthesize(variableDeclaration.Initializer);
return base.VisitVariableDeclaration(variableDeclaration, data); return base.VisitVariableDeclaration(variableDeclaration, data);
} }
public override object VisitUnaryOperatorExpression(UnaryOperatorExpression unary, object data) public override object VisitUnaryOperatorExpression(UnaryOperatorExpression unary, object data)
{ {
if (GetPrecedence(unary.Expression) > GetPrecedence(unary)) { if (GetPrecedence(unary.Expression) > GetPrecedence(unary)) {
unary.Expression = Deparenthesize(unary.Expression); unary.Expression = Deparenthesize(unary.Expression);
} }
return base.VisitUnaryOperatorExpression(unary, data); return base.VisitUnaryOperatorExpression(unary, data);
} }
public override object VisitMemberReferenceExpression(MemberReferenceExpression memberRef, object data) public override object VisitMemberReferenceExpression(MemberReferenceExpression memberRef, object data)
{ {
if (GetPrecedence(memberRef.TargetObject) >= GetPrecedence(memberRef)) { if (GetPrecedence(memberRef.TargetObject) >= GetPrecedence(memberRef)) {
memberRef.TargetObject = Deparenthesize(memberRef.TargetObject); memberRef.TargetObject = Deparenthesize(memberRef.TargetObject);
} }
return base.VisitMemberReferenceExpression(memberRef, data); return base.VisitMemberReferenceExpression(memberRef, data);
} }
public override object VisitInvocationExpression(InvocationExpression invocation, object data) public override object VisitInvocationExpression(InvocationExpression invocation, object data)
{ {
if (GetPrecedence(invocation.TargetObject) >= GetPrecedence(invocation)) { if (GetPrecedence(invocation.TargetObject) >= GetPrecedence(invocation)) {
invocation.TargetObject = Deparenthesize(invocation.TargetObject); invocation.TargetObject = Deparenthesize(invocation.TargetObject);
} }
for(int i = 0; i < invocation.Arguments.Count; i++) { for(int i = 0; i < invocation.Arguments.Count; i++) {
invocation.Arguments[i] = Deparenthesize(invocation.Arguments[i]); invocation.Arguments[i] = Deparenthesize(invocation.Arguments[i]);
} }
return base.VisitInvocationExpression(invocation, data); return base.VisitInvocationExpression(invocation, data);
} }
public override object VisitBinaryOperatorExpression(BinaryOperatorExpression binary, object data) public override object VisitBinaryOperatorExpression(BinaryOperatorExpression binary, object data)
{ {
int? myPrecedence = GetPrecedence(binary); int? myPrecedence = GetPrecedence(binary);
if (GetPrecedence(binary.Left) > myPrecedence) { if (GetPrecedence(binary.Left) > myPrecedence) {
binary.Left = Deparenthesize(binary.Left); binary.Left = Deparenthesize(binary.Left);
} }
if (GetPrecedence(binary.Right) > myPrecedence) { if (GetPrecedence(binary.Right) > myPrecedence) {
binary.Right = Deparenthesize(binary.Right); binary.Right = Deparenthesize(binary.Right);
} }
// Associativity // Associativity
if (GetPrecedence(binary.Left) == myPrecedence && myPrecedence.HasValue) { if (GetPrecedence(binary.Left) == myPrecedence && myPrecedence.HasValue) {
binary.Left = Deparenthesize(binary.Left); binary.Left = Deparenthesize(binary.Left);
} }
return base.VisitBinaryOperatorExpression(binary, data); return base.VisitBinaryOperatorExpression(binary, data);
} }
public override object VisitExpressionStatement(ExpressionStatement expressionStatement, object data) public override object VisitExpressionStatement(ExpressionStatement expressionStatement, object data)
{ {
expressionStatement.Expression = Deparenthesize(expressionStatement.Expression); expressionStatement.Expression = Deparenthesize(expressionStatement.Expression);
return base.VisitExpressionStatement(expressionStatement, data); return base.VisitExpressionStatement(expressionStatement, data);
} }
public override object VisitForStatement(ForStatement forStatement, object data) public override object VisitForStatement(ForStatement forStatement, object data)
{ {
forStatement.Condition = Deparenthesize(forStatement.Condition); forStatement.Condition = Deparenthesize(forStatement.Condition);
return base.VisitForStatement(forStatement, data); return base.VisitForStatement(forStatement, data);
} }
Expression Deparenthesize(Expression expr) Expression Deparenthesize(Expression expr)
{ {
if (expr is ParenthesizedExpression) { if (expr is ParenthesizedExpression) {
return Deparenthesize(((ParenthesizedExpression)expr).Expression); return Deparenthesize(((ParenthesizedExpression)expr).Expression);
} else { } else {
return expr; return expr;
} }
} }
int? GetPrecedence(Expression expr) int? GetPrecedence(Expression expr)
{ {
if (expr is ParenthesizedExpression) { if (expr is ParenthesizedExpression) {
return GetPrecedence(((ParenthesizedExpression)expr).Expression); return GetPrecedence(((ParenthesizedExpression)expr).Expression);
} }
UnaryOperatorExpression unary = expr as UnaryOperatorExpression; UnaryOperatorExpression unary = expr as UnaryOperatorExpression;
BinaryOperatorExpression binary = expr as BinaryOperatorExpression; BinaryOperatorExpression binary = expr as BinaryOperatorExpression;
// see http://msdn2.microsoft.com/en-us/library/ms173145.aspx // see http://msdn2.microsoft.com/en-us/library/ms173145.aspx
// Primary // Primary
// x.y // x.y
if (expr is MemberReferenceExpression) return 15; if (expr is MemberReferenceExpression) return 15;
// f(x) // f(x)
if (expr is InvocationExpression) return 15; if (expr is InvocationExpression) return 15;
// a[x] // a[x]
if (expr is IndexerExpression) return 15; if (expr is IndexerExpression) return 15;
// x++ // x++
if (unary != null && unary.Op == UnaryOperatorType.PostIncrement) return 15; if (unary != null && unary.Op == UnaryOperatorType.PostIncrement) return 15;
// x-- // x--
if (unary != null && unary.Op == UnaryOperatorType.PostDecrement) return 15; if (unary != null && unary.Op == UnaryOperatorType.PostDecrement) return 15;
// new T(...) // new T(...)
if (expr is ObjectCreateExpression) return 15; if (expr is ObjectCreateExpression) return 15;
// new T(...){...} // new T(...){...}
// new {...} // new {...}
// new T[...] // new T[...]
if (expr is ArrayCreateExpression) return 15; if (expr is ArrayCreateExpression) return 15;
// typeof(T) // typeof(T)
if (expr is TypeOfExpression) return 15; if (expr is TypeOfExpression) return 15;
// checked(x) // checked(x)
// unchecked(x) // unchecked(x)
// default (T) // default (T)
// delegate {} // delegate {}
// Unary // Unary
// +x // +x
if (unary != null && unary.Op == UnaryOperatorType.Plus) return 14; if (unary != null && unary.Op == UnaryOperatorType.Plus) return 14;
// -x // -x
if (unary != null && unary.Op == UnaryOperatorType.Minus) return 14; if (unary != null && unary.Op == UnaryOperatorType.Minus) return 14;
// !x // !x
if (unary != null && unary.Op == UnaryOperatorType.Not) return 14; if (unary != null && unary.Op == UnaryOperatorType.Not) return 14;
// ~x // ~x
if (unary != null && unary.Op == UnaryOperatorType.BitNot) return 14; if (unary != null && unary.Op == UnaryOperatorType.BitNot) return 14;
// ++x // ++x
if (unary != null && unary.Op == UnaryOperatorType.Increment) return 14; if (unary != null && unary.Op == UnaryOperatorType.Increment) return 14;
// --x // --x
if (unary != null && unary.Op == UnaryOperatorType.Decrement) return 14; if (unary != null && unary.Op == UnaryOperatorType.Decrement) return 14;
// (T)x // (T)x
if (expr is CastExpression) return 14; if (expr is CastExpression) return 14;
// Multiplicative // Multiplicative
// *, , // *, ,
if (binary != null && binary.Op == BinaryOperatorType.Multiply) return 13; if (binary != null && binary.Op == BinaryOperatorType.Multiply) return 13;
// / // /
if (binary != null && binary.Op == BinaryOperatorType.Divide) return 13; if (binary != null && binary.Op == BinaryOperatorType.Divide) return 13;
// % // %
if (binary != null && binary.Op == BinaryOperatorType.Modulus) return 13; if (binary != null && binary.Op == BinaryOperatorType.Modulus) return 13;
// Additive // Additive
// x + y // x + y
if (binary != null && binary.Op == BinaryOperatorType.Add) return 12; if (binary != null && binary.Op == BinaryOperatorType.Add) return 12;
// x - y // x - y
if (binary != null && binary.Op == BinaryOperatorType.Subtract) return 12; if (binary != null && binary.Op == BinaryOperatorType.Subtract) return 12;
// Shift // Shift
// x << y // x << y
// x >> y // x >> y
// Relational and Type Testing // Relational and Type Testing
// x < y // x < y
if (binary != null && binary.Op == BinaryOperatorType.LessThan) return 10; if (binary != null && binary.Op == BinaryOperatorType.LessThan) return 10;
// x > y // x > y
if (binary != null && binary.Op == BinaryOperatorType.GreaterThan) return 10; if (binary != null && binary.Op == BinaryOperatorType.GreaterThan) return 10;
// x <= y // x <= y
if (binary != null && binary.Op == BinaryOperatorType.LessThanOrEqual) return 10; if (binary != null && binary.Op == BinaryOperatorType.LessThanOrEqual) return 10;
// x >= y // x >= y
if (binary != null && binary.Op == BinaryOperatorType.GreaterThanOrEqual) return 10; if (binary != null && binary.Op == BinaryOperatorType.GreaterThanOrEqual) return 10;
// x is T // x is T
// x as T // x as T
// Equality // Equality
// x == y // x == y
if (binary != null && binary.Op == BinaryOperatorType.Equality) return 9; if (binary != null && binary.Op == BinaryOperatorType.Equality) return 9;
// x != y // x != y
if (binary != null && binary.Op == BinaryOperatorType.InEquality) return 9; if (binary != null && binary.Op == BinaryOperatorType.InEquality) return 9;
// Logical AND // Logical AND
// x & y // x & y
if (binary != null && binary.Op == BinaryOperatorType.BitwiseAnd) return 8; if (binary != null && binary.Op == BinaryOperatorType.BitwiseAnd) return 8;
// Logical XOR // Logical XOR
// x ^ y // x ^ y
if (binary != null && binary.Op == BinaryOperatorType.ExclusiveOr) return 7; if (binary != null && binary.Op == BinaryOperatorType.ExclusiveOr) return 7;
// Logical OR // Logical OR
// x | y // x | y
if (binary != null && binary.Op == BinaryOperatorType.BitwiseOr) return 6; if (binary != null && binary.Op == BinaryOperatorType.BitwiseOr) return 6;
// Conditional AND // Conditional AND
// x && y // x && y
if (binary != null && binary.Op == BinaryOperatorType.LogicalAnd) return 5; if (binary != null && binary.Op == BinaryOperatorType.LogicalAnd) return 5;
// Conditional OR // Conditional OR
// x || y // x || y
if (binary != null && binary.Op == BinaryOperatorType.LogicalOr) return 4; if (binary != null && binary.Op == BinaryOperatorType.LogicalOr) return 4;
// Null coalescing // Null coalescing
// X ?? y // X ?? y
// Conditional // Conditional
// x ?: y : z // x ?: y : z
// Assignment or anonymous function // Assignment or anonymous function
// =, , => // =, , =>
if (expr is AssignmentExpression) return 1; if (expr is AssignmentExpression) return 1;
// x op= y // x op= y
// (T x) => y // (T x) => y
return null; return null;
} }
} }
} }

150
Decompiler/src/Ast/Transforms/RestoreLoop.cs → ICSharpCode.Decompiler/Ast/Transforms/RestoreLoop.cs

@ -1,75 +1,75 @@
using System; using System;
using Ast = ICSharpCode.NRefactory.Ast; using Ast = ICSharpCode.NRefactory.Ast;
using ICSharpCode.NRefactory.Ast; using ICSharpCode.NRefactory.Ast;
using ICSharpCode.NRefactory.Visitors; using ICSharpCode.NRefactory.Visitors;
namespace Decompiler.Transforms.Ast namespace Decompiler.Transforms.Ast
{ {
public class RestoreLoop: AbstractAstTransformer public class RestoreLoop: AbstractAstTransformer
{ {
public override object VisitForStatement(ForStatement forStatement, object data) public override object VisitForStatement(ForStatement forStatement, object data)
{ {
base.VisitForStatement(forStatement, data); base.VisitForStatement(forStatement, data);
// Restore loop initializer // Restore loop initializer
if (forStatement.Initializers.Count == 0) { if (forStatement.Initializers.Count == 0) {
LocalVariableDeclaration varDeclr = forStatement.Previous() as LocalVariableDeclaration; LocalVariableDeclaration varDeclr = forStatement.Previous() as LocalVariableDeclaration;
if (varDeclr != null) { if (varDeclr != null) {
varDeclr.ReplaceWith(Statement.Null); varDeclr.ReplaceWith(Statement.Null);
forStatement.Initializers.Add(varDeclr); forStatement.Initializers.Add(varDeclr);
} }
} }
// Restore loop condition // Restore loop condition
if (forStatement.Condition.IsNull && if (forStatement.Condition.IsNull &&
forStatement.EmbeddedStatement.Children.Count >= 3) forStatement.EmbeddedStatement.Children.Count >= 3)
{ {
IfElseStatement condition = forStatement.EmbeddedStatement.Children[0] as IfElseStatement; IfElseStatement condition = forStatement.EmbeddedStatement.Children[0] as IfElseStatement;
BreakStatement breakStmt = forStatement.EmbeddedStatement.Children[1] as BreakStatement; BreakStatement breakStmt = forStatement.EmbeddedStatement.Children[1] as BreakStatement;
LabelStatement label = forStatement.EmbeddedStatement.Children[2] as LabelStatement; LabelStatement label = forStatement.EmbeddedStatement.Children[2] as LabelStatement;
if (condition != null && breakStmt != null && label != null && if (condition != null && breakStmt != null && label != null &&
condition.TrueStatement.Count == 1) condition.TrueStatement.Count == 1)
{ {
GotoStatement gotoStmt = condition.TrueStatement[0] as GotoStatement; GotoStatement gotoStmt = condition.TrueStatement[0] as GotoStatement;
if (gotoStmt != null && gotoStmt.Label == label.Label) { if (gotoStmt != null && gotoStmt.Label == label.Label) {
condition.Remove(); condition.Remove();
breakStmt.Remove(); breakStmt.Remove();
forStatement.Condition = condition.Condition; forStatement.Condition = condition.Condition;
} }
} }
} }
// Restore loop condition (version 2) // Restore loop condition (version 2)
if (forStatement.Condition.IsNull) { if (forStatement.Condition.IsNull) {
IfElseStatement condition = forStatement.EmbeddedStatement.Children.First as IfElseStatement; IfElseStatement condition = forStatement.EmbeddedStatement.Children.First as IfElseStatement;
if (condition != null && if (condition != null &&
condition.TrueStatement.Count == 1 && condition.TrueStatement.Count == 1 &&
condition.TrueStatement[0] is BlockStatement && condition.TrueStatement[0] is BlockStatement &&
condition.TrueStatement[0].Children.Count == 1 && condition.TrueStatement[0].Children.Count == 1 &&
condition.TrueStatement[0].Children.First is BreakStatement && condition.TrueStatement[0].Children.First is BreakStatement &&
condition.FalseStatement.Count == 1 && condition.FalseStatement.Count == 1 &&
condition.FalseStatement[0] is BlockStatement && condition.FalseStatement[0] is BlockStatement &&
condition.FalseStatement[0].Children.Count == 0) condition.FalseStatement[0].Children.Count == 0)
{ {
condition.Remove(); condition.Remove();
forStatement.Condition = new UnaryOperatorExpression(condition.Condition, UnaryOperatorType.Not); forStatement.Condition = new UnaryOperatorExpression(condition.Condition, UnaryOperatorType.Not);
} }
} }
// Restore loop iterator // Restore loop iterator
if (forStatement.EmbeddedStatement.Children.Count > 0 && if (forStatement.EmbeddedStatement.Children.Count > 0 &&
forStatement.Iterator.Count == 0) forStatement.Iterator.Count == 0)
{ {
ExpressionStatement lastStmt = forStatement.EmbeddedStatement.Children.Last as ExpressionStatement; ExpressionStatement lastStmt = forStatement.EmbeddedStatement.Children.Last as ExpressionStatement;
if (lastStmt != null && if (lastStmt != null &&
(lastStmt.Expression is AssignmentExpression || lastStmt.Expression is UnaryOperatorExpression)) { (lastStmt.Expression is AssignmentExpression || lastStmt.Expression is UnaryOperatorExpression)) {
lastStmt.Remove(); lastStmt.Remove();
forStatement.Iterator.Add(lastStmt); forStatement.Iterator.Add(lastStmt);
} }
} }
return null; return null;
} }
} }
} }

182
Decompiler/src/Ast/Transforms/SimplifyTypeReferences.cs → ICSharpCode.Decompiler/Ast/Transforms/SimplifyTypeReferences.cs

@ -1,91 +1,91 @@
using System; using System;
using Ast = ICSharpCode.NRefactory.Ast; using Ast = ICSharpCode.NRefactory.Ast;
using ICSharpCode.NRefactory.Ast; using ICSharpCode.NRefactory.Ast;
using ICSharpCode.NRefactory.Visitors; using ICSharpCode.NRefactory.Visitors;
namespace Decompiler.Transforms.Ast namespace Decompiler.Transforms.Ast
{ {
public class SimplifyTypeReferences: AbstractAstTransformer public class SimplifyTypeReferences: AbstractAstTransformer
{ {
string currentNamepace = string.Empty; string currentNamepace = string.Empty;
string currentClass = null; string currentClass = null;
public override object VisitNamespaceDeclaration(NamespaceDeclaration namespaceDeclaration, object data) public override object VisitNamespaceDeclaration(NamespaceDeclaration namespaceDeclaration, object data)
{ {
currentNamepace = namespaceDeclaration.Name; currentNamepace = namespaceDeclaration.Name;
base.VisitNamespaceDeclaration(namespaceDeclaration, data); base.VisitNamespaceDeclaration(namespaceDeclaration, data);
currentNamepace = string.Empty; currentNamepace = string.Empty;
return null; return null;
} }
public override object VisitTypeDeclaration(TypeDeclaration typeDeclaration, object data) public override object VisitTypeDeclaration(TypeDeclaration typeDeclaration, object data)
{ {
currentClass = currentNamepace + "." + typeDeclaration.Name; currentClass = currentNamepace + "." + typeDeclaration.Name;
base.VisitTypeDeclaration(typeDeclaration, data); base.VisitTypeDeclaration(typeDeclaration, data);
currentClass = null; currentClass = null;
return null; return null;
} }
public override object VisitMemberReferenceExpression(MemberReferenceExpression memberReferenceExpression, object data) public override object VisitMemberReferenceExpression(MemberReferenceExpression memberReferenceExpression, object data)
{ {
IdentifierExpression id = memberReferenceExpression.TargetObject as IdentifierExpression; IdentifierExpression id = memberReferenceExpression.TargetObject as IdentifierExpression;
if (id != null) { if (id != null) {
if (id.Identifier == "System" || id.Identifier == currentClass) { if (id.Identifier == "System" || id.Identifier == currentClass) {
ReplaceCurrentNode(new IdentifierExpression(memberReferenceExpression.MemberName)); ReplaceCurrentNode(new IdentifierExpression(memberReferenceExpression.MemberName));
return null; return null;
} }
if (id.Identifier.StartsWith("System.")) { if (id.Identifier.StartsWith("System.")) {
id.Identifier = id.Identifier.Replace("System.", ""); id.Identifier = id.Identifier.Replace("System.", "");
return null; return null;
} }
} }
if (memberReferenceExpression.TargetObject is ThisReferenceExpression) { if (memberReferenceExpression.TargetObject is ThisReferenceExpression) {
ReplaceCurrentNode(new IdentifierExpression(memberReferenceExpression.MemberName)); ReplaceCurrentNode(new IdentifierExpression(memberReferenceExpression.MemberName));
return null; return null;
} }
return base.VisitMemberReferenceExpression(memberReferenceExpression, data); return base.VisitMemberReferenceExpression(memberReferenceExpression, data);
} }
public override object VisitTypeReference(TypeReference typeReference, object data) public override object VisitTypeReference(TypeReference typeReference, object data)
{ {
string fullName = typeReference.Type; string fullName = typeReference.Type;
string shortName = GetShortName(fullName); string shortName = GetShortName(fullName);
if (shortName != null) { if (shortName != null) {
typeReference.Type = shortName; typeReference.Type = shortName;
return null; return null;
} }
if (fullName.EndsWith("[]")) { if (fullName.EndsWith("[]")) {
shortName = GetShortName(fullName.Replace("[]","")); shortName = GetShortName(fullName.Replace("[]",""));
if (shortName != null) { if (shortName != null) {
typeReference.Type = shortName + "[]"; typeReference.Type = shortName + "[]";
return null; return null;
} }
} }
return null; return null;
} }
public string GetShortName(string fullName) public string GetShortName(string fullName)
{ {
switch(fullName) { switch(fullName) {
case "System.Boolean": return "bool"; case "System.Boolean": return "bool";
case "System.Byte": return "byte"; case "System.Byte": return "byte";
case "System.Char": return "char"; case "System.Char": return "char";
case "System.Decimal": return "decimal"; case "System.Decimal": return "decimal";
case "System.Double": return "double"; case "System.Double": return "double";
case "System.Single": return "float"; case "System.Single": return "float";
case "System.Int32": return "int"; case "System.Int32": return "int";
case "System.Int64": return "long"; case "System.Int64": return "long";
case "System.Object": return "object"; case "System.Object": return "object";
case "System.SByte": return "sbyte"; case "System.SByte": return "sbyte";
case "System.Int16": return "short"; case "System.Int16": return "short";
case "System.String": return "string"; case "System.String": return "string";
case "System.UInt32": return "uint"; case "System.UInt32": return "uint";
case "System.UInt64": return "ulong"; case "System.UInt64": return "ulong";
case "System.UInt16": return "ushort"; case "System.UInt16": return "ushort";
case "System.Void": return "void"; case "System.Void": return "void";
} }
return null; return null;
} }
} }
} }

30
ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj

@ -49,6 +49,16 @@
</Reference> </Reference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="Ast\AstBuilder.cs" />
<Compile Include="Ast\AstMetodBodyBuilder.cs" />
<Compile Include="Ast\Transforms\Idioms.cs" />
<Compile Include="Ast\Transforms\PushNegation.cs" />
<Compile Include="Ast\Transforms\RemoveDeadLabels.cs" />
<Compile Include="Ast\Transforms\RemoveEmptyElseBody.cs" />
<Compile Include="Ast\Transforms\RemoveGotos.cs" />
<Compile Include="Ast\Transforms\RemoveParenthesis.cs" />
<Compile Include="Ast\Transforms\RestoreLoop.cs" />
<Compile Include="Ast\Transforms\SimplifyTypeReferences.cs" />
<Compile Include="CecilExtensions.cs" /> <Compile Include="CecilExtensions.cs" />
<Compile Include="Disassembler\DisassemblerHelpers.cs" /> <Compile Include="Disassembler\DisassemblerHelpers.cs" />
<Compile Include="Disassembler\ILStructure.cs" /> <Compile Include="Disassembler\ILStructure.cs" />
@ -69,19 +79,39 @@
<Compile Include="FlowAnalysis\SsaVariable.cs" /> <Compile Include="FlowAnalysis\SsaVariable.cs" />
<Compile Include="FlowAnalysis\TransformToSsa.cs" /> <Compile Include="FlowAnalysis\TransformToSsa.cs" />
<Compile Include="GraphVizGraph.cs" /> <Compile Include="GraphVizGraph.cs" />
<Compile Include="ILAst\ControlFlow\Node-Optimize.cs" />
<Compile Include="ILAst\ControlFlow\Node-Structure.cs" />
<Compile Include="ILAst\ControlFlow\Node-Transforms.cs" />
<Compile Include="ILAst\ControlFlow\NodeCollection.cs" />
<Compile Include="ILAst\ControlFlow\Nodes.cs" />
<Compile Include="ILAst\ILAstBuilder.cs" />
<Compile Include="ILAst\ILAstTypes.cs" />
<Compile Include="ITextOutput.cs" /> <Compile Include="ITextOutput.cs" />
<Compile Include="Mono.Cecil.Rocks\Constants.cs" />
<Compile Include="Mono.Cecil.Rocks\MethodBodyRocks.cs" />
<Compile Include="Mono.Cecil.Rocks\MyRocks.cs" />
<Compile Include="Options.cs" />
<Compile Include="PlainTextOutput.cs" /> <Compile Include="PlainTextOutput.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<None Include="Properties\AssemblyInfo.template.cs" /> <None Include="Properties\AssemblyInfo.template.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Decompiler\lib\NRefactory\Project\NRefactory.csproj">
<Project>{3A9AE6AA-BC07-4A2F-972C-581E3AE2F195}</Project>
<Name>NRefactory</Name>
</ProjectReference>
<ProjectReference Include="..\Mono.Cecil\Mono.Cecil.csproj"> <ProjectReference Include="..\Mono.Cecil\Mono.Cecil.csproj">
<Project>{D68133BD-1E63-496E-9EDE-4FBDBF77B486}</Project> <Project>{D68133BD-1E63-496E-9EDE-4FBDBF77B486}</Project>
<Name>Mono.Cecil</Name> <Name>Mono.Cecil</Name>
</ProjectReference> </ProjectReference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Folder Include="Ast" />
<Folder Include="Ast\Transforms" />
<Folder Include="Disassembler" /> <Folder Include="Disassembler" />
<Folder Include="ILAst" />
<Folder Include="ILAst\ControlFlow" />
<Folder Include="Mono.Cecil.Rocks" />
</ItemGroup> </ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.Targets" /> <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.Targets" />
<Target Name="BeforeBuild"> <Target Name="BeforeBuild">

384
Decompiler/src/ILAst/ControlFlow/Node-Optimize.cs → ICSharpCode.Decompiler/ILAst/ControlFlow/Node-Optimize.cs

@ -1,192 +1,192 @@
using System; using System;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
namespace Decompiler.ControlFlow namespace Decompiler.ControlFlow
{ {
public abstract partial class Node public abstract partial class Node
{ {
public void Optimize() public void Optimize()
{ {
if (Options.ReduceLoops) { if (Options.ReduceLoops) {
OptimizeLoops(); OptimizeLoops();
} }
if (Options.ReduceConditonals) { if (Options.ReduceConditonals) {
OptimizeShortCircuits(); OptimizeShortCircuits();
OptimizeConditions(); OptimizeConditions();
} }
} }
public void OptimizeLoops() public void OptimizeLoops()
{ {
Reset: Reset:
foreach(Node child in this.Childs) { foreach(Node child in this.Childs) {
if (child.Predecessors.Count == 1) { if (child.Predecessors.Count == 1) {
Node predecessor = child.Predecessors[0]; Node predecessor = child.Predecessors[0];
Node mergedNode; Node mergedNode;
if (child.Successors.Contains(predecessor)) { if (child.Successors.Contains(predecessor)) {
mergedNode = MergeChilds<Loop>(predecessor, child); mergedNode = MergeChilds<Loop>(predecessor, child);
} else { } else {
mergedNode = MergeChilds<AcyclicGraph>(predecessor, child); mergedNode = MergeChilds<AcyclicGraph>(predecessor, child);
} }
mergedNode.FalttenAcyclicChilds(); mergedNode.FalttenAcyclicChilds();
goto Reset; goto Reset;
} }
} }
// If the result is single acyclic node, eliminate it // If the result is single acyclic node, eliminate it
if (this.Childs.Count == 1 && this.HeadChild is AcyclicGraph) { if (this.Childs.Count == 1 && this.HeadChild is AcyclicGraph) {
Node headChild = this.HeadChild; Node headChild = this.HeadChild;
this.Childs.Remove(this.HeadChild); this.Childs.Remove(this.HeadChild);
headChild.Childs.MoveTo(this); headChild.Childs.MoveTo(this);
} }
} }
NodeCollection GetReachableNodes() NodeCollection GetReachableNodes()
{ {
NodeCollection reachableNodes = new NodeCollection(); NodeCollection reachableNodes = new NodeCollection();
reachableNodes.Add(this); reachableNodes.Add(this);
for(int i = 0; i < reachableNodes.Count; i++) { for(int i = 0; i < reachableNodes.Count; i++) {
foreach(Node alsoReachable in reachableNodes[i].Successors) { foreach(Node alsoReachable in reachableNodes[i].Successors) {
// Do not go though the head child // Do not go though the head child
if (alsoReachable != this.Parent.HeadChild) { if (alsoReachable != this.Parent.HeadChild) {
reachableNodes.Add(alsoReachable); reachableNodes.Add(alsoReachable);
} }
} }
} }
return reachableNodes; return reachableNodes;
} }
public void OptimizeShortCircuits() public void OptimizeShortCircuits()
{ {
foreach(Node child in this.Childs) { foreach(Node child in this.Childs) {
if (child is Loop) { if (child is Loop) {
child.OptimizeShortCircuits(); child.OptimizeShortCircuits();
} }
} }
Reset: Reset:
foreach(Node child in this.Childs) { foreach(Node child in this.Childs) {
if (TryOptimizeShortCircuit(child)) { if (TryOptimizeShortCircuit(child)) {
goto Reset; goto Reset;
} }
} }
} }
public static bool TryOptimizeShortCircuit(Node head) public static bool TryOptimizeShortCircuit(Node head)
{ {
if ((head is BasicBlock) && if ((head is BasicBlock) &&
(head as BasicBlock).BranchBasicBlock != null && (head as BasicBlock).BranchBasicBlock != null &&
(head as BasicBlock).FallThroughBasicBlock != null) { (head as BasicBlock).FallThroughBasicBlock != null) {
head.Parent.MergeChilds<SimpleBranch>(head); head.Parent.MergeChilds<SimpleBranch>(head);
return true; return true;
} }
Branch top = head as Branch; Branch top = head as Branch;
if (top == null) return false; if (top == null) return false;
Branch left = head.FloatUpToNeighbours(top.TrueSuccessor) as Branch; Branch left = head.FloatUpToNeighbours(top.TrueSuccessor) as Branch;
Branch right = head.FloatUpToNeighbours(top.FalseSuccessor) as Branch; Branch right = head.FloatUpToNeighbours(top.FalseSuccessor) as Branch;
// A & B // A & B
if (left != null && if (left != null &&
left.Predecessors.Count == 1 && left.Predecessors.Count == 1 &&
left.FalseSuccessor == top.FalseSuccessor) { left.FalseSuccessor == top.FalseSuccessor) {
ShortCircuitBranch scBranch = top.Parent.MergeChilds<ShortCircuitBranch>(top, left); ShortCircuitBranch scBranch = top.Parent.MergeChilds<ShortCircuitBranch>(top, left);
scBranch.Operator = ShortCircuitOperator.LeftAndRight; scBranch.Operator = ShortCircuitOperator.LeftAndRight;
return true; return true;
} }
// ~A | B // ~A | B
if (left != null && if (left != null &&
left.Predecessors.Count == 1 && left.Predecessors.Count == 1 &&
left.TrueSuccessor == top.FalseSuccessor) { left.TrueSuccessor == top.FalseSuccessor) {
ShortCircuitBranch scBranch = top.Parent.MergeChilds<ShortCircuitBranch>(top, left); ShortCircuitBranch scBranch = top.Parent.MergeChilds<ShortCircuitBranch>(top, left);
scBranch.Operator = ShortCircuitOperator.NotLeftOrRight; scBranch.Operator = ShortCircuitOperator.NotLeftOrRight;
return true; return true;
} }
// A | B // A | B
if (right != null && if (right != null &&
right.Predecessors.Count == 1 && right.Predecessors.Count == 1 &&
right.TrueSuccessor == top.TrueSuccessor) { right.TrueSuccessor == top.TrueSuccessor) {
ShortCircuitBranch scBranch = top.Parent.MergeChilds<ShortCircuitBranch>(top, right); ShortCircuitBranch scBranch = top.Parent.MergeChilds<ShortCircuitBranch>(top, right);
scBranch.Operator = ShortCircuitOperator.LeftOrRight; scBranch.Operator = ShortCircuitOperator.LeftOrRight;
return true; return true;
} }
// ~A & B // ~A & B
if (right != null && if (right != null &&
right.Predecessors.Count == 1 && right.Predecessors.Count == 1 &&
right.FalseSuccessor == top.TrueSuccessor) { right.FalseSuccessor == top.TrueSuccessor) {
ShortCircuitBranch scBranch = top.Parent.MergeChilds<ShortCircuitBranch>(top, right); ShortCircuitBranch scBranch = top.Parent.MergeChilds<ShortCircuitBranch>(top, right);
scBranch.Operator = ShortCircuitOperator.NotLeftAndRight; scBranch.Operator = ShortCircuitOperator.NotLeftAndRight;
return true; return true;
} }
return false; return false;
} }
public void OptimizeConditions() public void OptimizeConditions()
{ {
foreach(Node child in this.Childs) { foreach(Node child in this.Childs) {
if (child is Loop) { if (child is Loop) {
child.OptimizeConditions(); child.OptimizeConditions();
} }
} }
Node conditionNode = this.HeadChild; Node conditionNode = this.HeadChild;
while(conditionNode != null) { while(conditionNode != null) {
// Keep looking for some conditional block // Keep looking for some conditional block
if (conditionNode is Branch) { if (conditionNode is Branch) {
// Found start of conditional // Found start of conditional
OptimizeIf((Branch)conditionNode); OptimizeIf((Branch)conditionNode);
// Restart // Restart
conditionNode = this.HeadChild; conditionNode = this.HeadChild;
continue; continue;
} else if (conditionNode.Successors.Count > 0) { } else if (conditionNode.Successors.Count > 0) {
// Keep looking down // Keep looking down
conditionNode = conditionNode.Successors[0]; conditionNode = conditionNode.Successors[0];
if (conditionNode == this.HeadChild) { if (conditionNode == this.HeadChild) {
return; return;
} }
continue; // Next continue; // Next
} else { } else {
return; // End of block return; // End of block
} }
} }
} }
public static void OptimizeIf(Branch condition) public static void OptimizeIf(Branch condition)
{ {
Node trueStart = condition.FloatUpToNeighbours(condition.TrueSuccessor); Node trueStart = condition.FloatUpToNeighbours(condition.TrueSuccessor);
Node falseStart = condition.FloatUpToNeighbours(condition.FalseSuccessor); Node falseStart = condition.FloatUpToNeighbours(condition.FalseSuccessor);
NodeCollection trueReachable = trueStart != null ? trueStart.GetReachableNodes() : NodeCollection.Empty; NodeCollection trueReachable = trueStart != null ? trueStart.GetReachableNodes() : NodeCollection.Empty;
NodeCollection falseReachable = falseStart != null ? falseStart.GetReachableNodes() : NodeCollection.Empty; NodeCollection falseReachable = falseStart != null ? falseStart.GetReachableNodes() : NodeCollection.Empty;
NodeCollection commonReachable = NodeCollection.Intersect(trueReachable, falseReachable); NodeCollection commonReachable = NodeCollection.Intersect(trueReachable, falseReachable);
NodeCollection trueNodes = trueReachable.Clone(); NodeCollection trueNodes = trueReachable.Clone();
trueNodes.RemoveRange(commonReachable); trueNodes.RemoveRange(commonReachable);
NodeCollection falseNodes = falseReachable.Clone(); NodeCollection falseNodes = falseReachable.Clone();
falseNodes.RemoveRange(commonReachable); falseNodes.RemoveRange(commonReachable);
// Replace the basic block with condition node // Replace the basic block with condition node
Node conditionParent = condition.Parent; Node conditionParent = condition.Parent;
int conditionIndex = condition.Index; int conditionIndex = condition.Index;
ConditionalNode conditionalNode = new ConditionalNode(condition); ConditionalNode conditionalNode = new ConditionalNode(condition);
conditionalNode.MoveTo(conditionParent, conditionIndex); conditionalNode.MoveTo(conditionParent, conditionIndex);
// If there are no common nodes, let the 'true' block be the default // If there are no common nodes, let the 'true' block be the default
if (commonReachable.Count > 0) { if (commonReachable.Count > 0) {
trueNodes.MoveTo(conditionalNode.TrueBody); trueNodes.MoveTo(conditionalNode.TrueBody);
} }
falseNodes.MoveTo(conditionalNode.FalseBody); falseNodes.MoveTo(conditionalNode.FalseBody);
// Optimize the created subtrees // Optimize the created subtrees
conditionalNode.TrueBody.OptimizeConditions(); conditionalNode.TrueBody.OptimizeConditions();
conditionalNode.FalseBody.OptimizeConditions(); conditionalNode.FalseBody.OptimizeConditions();
} }
} }
} }

466
Decompiler/src/ILAst/ControlFlow/Node-Structure.cs → ICSharpCode.Decompiler/ILAst/ControlFlow/Node-Structure.cs

@ -1,233 +1,233 @@
using System; using System;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
namespace Decompiler.ControlFlow namespace Decompiler.ControlFlow
{ {
public abstract partial class Node public abstract partial class Node
{ {
public static int NextNodeID = 1; public static int NextNodeID = 1;
int id; int id;
string label; string label;
Node parent; Node parent;
NodeCollection childs = new NodeCollection(); NodeCollection childs = new NodeCollection();
// Structural and linking cache // Structural and linking cache
NodeCollection basicBlocks_cache = null; NodeCollection basicBlocks_cache = null;
NodeCollection predecessors_cache = null; NodeCollection predecessors_cache = null;
NodeCollection successors_cache = null; NodeCollection successors_cache = null;
public int ID { public int ID {
get { return id; } get { return id; }
} }
public string Label { public string Label {
get { return label; } get { return label; }
} }
public Node Parent { public Node Parent {
get { return parent; } get { return parent; }
} }
public Node HeadChild { public Node HeadChild {
get { get {
if (this.Childs.Count > 0) { if (this.Childs.Count > 0) {
return this.Childs[0]; return this.Childs[0];
} else { } else {
return null; return null;
} }
} }
} }
public NodeCollection Childs { public NodeCollection Childs {
get { get {
return childs; return childs;
} }
} }
/// <summary> All basic blocks within the scope of this node (inclusive) </summary> /// <summary> All basic blocks within the scope of this node (inclusive) </summary>
public NodeCollection BasicBlocks { public NodeCollection BasicBlocks {
get { get {
if (basicBlocks_cache == null) { if (basicBlocks_cache == null) {
NodeCollection basicBlocks = new NodeCollection(); NodeCollection basicBlocks = new NodeCollection();
if (this is BasicBlock) { if (this is BasicBlock) {
basicBlocks.Add(this); basicBlocks.Add(this);
} }
foreach(Node child in this.Childs) { foreach(Node child in this.Childs) {
basicBlocks.AddRange(child.BasicBlocks); basicBlocks.AddRange(child.BasicBlocks);
} }
basicBlocks_cache = basicBlocks; basicBlocks_cache = basicBlocks;
} }
return basicBlocks_cache; return basicBlocks_cache;
} }
} }
NodeCollection FloatUpToNeighbours(IEnumerable<BasicBlock> basicBlocks) NodeCollection FloatUpToNeighbours(IEnumerable<BasicBlock> basicBlocks)
{ {
NodeCollection neighbours = new NodeCollection(); NodeCollection neighbours = new NodeCollection();
if (this.Parent != null) { if (this.Parent != null) {
foreach(BasicBlock basicBlock in basicBlocks) { foreach(BasicBlock basicBlock in basicBlocks) {
Node targetNode = FloatUpToNeighbours(basicBlock); Node targetNode = FloatUpToNeighbours(basicBlock);
// The target is outside the scope of the parent node // The target is outside the scope of the parent node
if (targetNode == null) continue; if (targetNode == null) continue;
// This child is a loop // This child is a loop
if (targetNode == this) continue; if (targetNode == this) continue;
// We found a target in our scope // We found a target in our scope
neighbours.Add(targetNode); neighbours.Add(targetNode);
} }
} }
return neighbours; return neighbours;
} }
Node FloatUpToNeighbours(BasicBlock basicBlock) Node FloatUpToNeighbours(BasicBlock basicBlock)
{ {
// Find neighbour coresponding to the basickBlock // Find neighbour coresponding to the basickBlock
Node targetNode = basicBlock; Node targetNode = basicBlock;
while(targetNode != null && targetNode.Parent != this.Parent) { while(targetNode != null && targetNode.Parent != this.Parent) {
targetNode = targetNode.Parent; targetNode = targetNode.Parent;
} }
return targetNode; return targetNode;
} }
public NodeCollection Predecessors { public NodeCollection Predecessors {
get { get {
if (predecessors_cache == null) { if (predecessors_cache == null) {
List<BasicBlock> basicBlockPredecessors = new List<BasicBlock>(); List<BasicBlock> basicBlockPredecessors = new List<BasicBlock>();
foreach(BasicBlock basicBlock in this.BasicBlocks) { foreach(BasicBlock basicBlock in this.BasicBlocks) {
foreach(BasicBlock basicBlockPredecessor in basicBlock.BasicBlockPredecessors) { foreach(BasicBlock basicBlockPredecessor in basicBlock.BasicBlockPredecessors) {
basicBlockPredecessors.Add(basicBlockPredecessor); basicBlockPredecessors.Add(basicBlockPredecessor);
} }
} }
predecessors_cache = FloatUpToNeighbours(basicBlockPredecessors); predecessors_cache = FloatUpToNeighbours(basicBlockPredecessors);
} }
return predecessors_cache; return predecessors_cache;
} }
} }
public NodeCollection Successors { public NodeCollection Successors {
get { get {
if (successors_cache == null) { if (successors_cache == null) {
List<BasicBlock> basicBlockSuccessors = new List<BasicBlock>(); List<BasicBlock> basicBlockSuccessors = new List<BasicBlock>();
foreach(BasicBlock basicBlock in this.BasicBlocks) { foreach(BasicBlock basicBlock in this.BasicBlocks) {
foreach(BasicBlock basicBlockSuccessor in basicBlock.BasicBlockSuccessors) { foreach(BasicBlock basicBlockSuccessor in basicBlock.BasicBlockSuccessors) {
basicBlockSuccessors.Add(basicBlockSuccessor); basicBlockSuccessors.Add(basicBlockSuccessor);
} }
} }
successors_cache = FloatUpToNeighbours(basicBlockSuccessors); successors_cache = FloatUpToNeighbours(basicBlockSuccessors);
} }
return successors_cache; return successors_cache;
} }
} }
int Index { int Index {
get { get {
if (this.Parent == null) throw new Exception("Does not have a parent"); if (this.Parent == null) throw new Exception("Does not have a parent");
return this.Parent.Childs.IndexOf(this); return this.Parent.Childs.IndexOf(this);
} }
} }
public Node NextNode { public Node NextNode {
get { get {
int index = this.Index + 1; int index = this.Index + 1;
if (0 <= index && index < this.Parent.Childs.Count) { if (0 <= index && index < this.Parent.Childs.Count) {
return this.Parent.Childs[index]; return this.Parent.Childs[index];
} else { } else {
return null; return null;
} }
} }
} }
public string Description { public string Description {
get { get {
return ToString(); return ToString();
} }
} }
protected Node() protected Node()
{ {
this.id = NextNodeID++; this.id = NextNodeID++;
this.label = this.GetType().Name + "_" + ID; this.label = this.GetType().Name + "_" + ID;
this.Childs.Added += delegate(object sender, NodeEventArgs e) { this.Childs.Added += delegate(object sender, NodeEventArgs e) {
if (e.Node.Parent != null) { if (e.Node.Parent != null) {
throw new Exception("Node is already assigned to other parent"); throw new Exception("Node is already assigned to other parent");
} }
e.Node.parent = this; e.Node.parent = this;
NotifyChildsChanged(); NotifyChildsChanged();
}; };
this.Childs.Removed += delegate(object sender, NodeEventArgs e) { this.Childs.Removed += delegate(object sender, NodeEventArgs e) {
e.Node.parent = null; e.Node.parent = null;
NotifyChildsChanged(); NotifyChildsChanged();
}; };
} }
void NotifyChildsChanged() void NotifyChildsChanged()
{ {
this.basicBlocks_cache = null; this.basicBlocks_cache = null;
foreach(Node child in this.Childs) { foreach(Node child in this.Childs) {
child.predecessors_cache = null; child.predecessors_cache = null;
child.successors_cache = null; child.successors_cache = null;
} }
if (this.Parent != null) { if (this.Parent != null) {
this.Parent.NotifyChildsChanged(); this.Parent.NotifyChildsChanged();
} }
} }
public override string ToString() public override string ToString()
{ {
System.Text.StringBuilder sb = new System.Text.StringBuilder(); System.Text.StringBuilder sb = new System.Text.StringBuilder();
sb.Append(this.GetType().Name); sb.Append(this.GetType().Name);
sb.Append(" "); sb.Append(" ");
sb.Append(ID); sb.Append(ID);
sb.Append(" "); sb.Append(" ");
sb.Append("("); sb.Append("(");
if (this.Predecessors.Count > 0) { if (this.Predecessors.Count > 0) {
sb.Append("Predecessors:"); sb.Append("Predecessors:");
bool isFirst = true; bool isFirst = true;
foreach(Node predecessor in this.Predecessors) { foreach(Node predecessor in this.Predecessors) {
if (isFirst) { if (isFirst) {
isFirst = false; isFirst = false;
} else { } else {
sb.Append(","); sb.Append(",");
} }
sb.Append(predecessor.ID); sb.Append(predecessor.ID);
} }
sb.Append(" "); sb.Append(" ");
} }
if (this.Successors.Count > 0) { if (this.Successors.Count > 0) {
sb.Append("Successors:"); sb.Append("Successors:");
bool isFirst = true; bool isFirst = true;
foreach(Node successor in this.Successors) { foreach(Node successor in this.Successors) {
if (isFirst) { if (isFirst) {
isFirst = false; isFirst = false;
} else { } else {
sb.Append(","); sb.Append(",");
} }
sb.Append(successor.ID); sb.Append(successor.ID);
} }
sb.Append(" "); sb.Append(" ");
} }
if (this.Parent != null) { if (this.Parent != null) {
sb.Append("Parent:"); sb.Append("Parent:");
sb.Append(this.Parent.ID); sb.Append(this.Parent.ID);
sb.Append(" "); sb.Append(" ");
} }
if (sb[sb.Length - 1] == '(') { if (sb[sb.Length - 1] == '(') {
sb.Length -= 1; sb.Length -= 1;
} else if (sb[sb.Length - 1] == ' ') { } else if (sb[sb.Length - 1] == ' ') {
sb.Length -= 1; sb.Length -= 1;
sb.Append(")"); sb.Append(")");
} }
return sb.ToString(); return sb.ToString();
} }
} }
} }

120
Decompiler/src/ILAst/ControlFlow/Node-Transforms.cs → ICSharpCode.Decompiler/ILAst/ControlFlow/Node-Transforms.cs

@ -1,60 +1,60 @@
using System; using System;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
namespace Decompiler.ControlFlow namespace Decompiler.ControlFlow
{ {
public abstract partial class Node public abstract partial class Node
{ {
public void Remove() public void Remove()
{ {
if (this.Parent != null) { if (this.Parent != null) {
this.Parent.Childs.Remove(this); this.Parent.Childs.Remove(this);
} }
} }
public void MoveTo(Node newNode) public void MoveTo(Node newNode)
{ {
MoveTo(newNode, newNode.Childs.Count); MoveTo(newNode, newNode.Childs.Count);
} }
public void MoveTo(Node newNode, int index) public void MoveTo(Node newNode, int index)
{ {
this.Remove(); this.Remove();
newNode.Childs.Insert(index, this); newNode.Childs.Insert(index, this);
} }
T MergeChilds<T>(params Node[] nodes) where T: Node, new() T MergeChilds<T>(params Node[] nodes) where T: Node, new()
{ {
foreach(Node node in nodes) { foreach(Node node in nodes) {
if (node == null) throw new ArgumentNullException("nodes"); if (node == null) throw new ArgumentNullException("nodes");
if (node.Parent != this) throw new ArgumentException("The node is not my child"); if (node.Parent != this) throw new ArgumentException("The node is not my child");
} }
if (nodes.Length == 0) throw new ArgumentException("At least one node must be specified"); if (nodes.Length == 0) throw new ArgumentException("At least one node must be specified");
T mergedNode = new T(); T mergedNode = new T();
// Add the merged node // Add the merged node
int headIndex = this.Childs.IndexOf(nodes[0]); int headIndex = this.Childs.IndexOf(nodes[0]);
this.Childs.Insert(headIndex, mergedNode); this.Childs.Insert(headIndex, mergedNode);
foreach(Node node in nodes) { foreach(Node node in nodes) {
node.MoveTo(mergedNode); node.MoveTo(mergedNode);
} }
return mergedNode; return mergedNode;
} }
public void FalttenAcyclicChilds() public void FalttenAcyclicChilds()
{ {
Reset: Reset:
foreach(Node child in this.Childs) { foreach(Node child in this.Childs) {
if (child is AcyclicGraph) { if (child is AcyclicGraph) {
child.Childs.MoveTo(this, child.Index); child.Childs.MoveTo(this, child.Index);
child.Remove(); child.Remove();
goto Reset; goto Reset;
} }
} }
} }
} }
} }

260
Decompiler/src/ILAst/ControlFlow/NodeCollection.cs → ICSharpCode.Decompiler/ILAst/ControlFlow/NodeCollection.cs

@ -1,130 +1,130 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
namespace Decompiler.ControlFlow namespace Decompiler.ControlFlow
{ {
public class NodeEventArgs: EventArgs public class NodeEventArgs: EventArgs
{ {
Node node; Node node;
public Node Node { public Node Node {
get { return node; } get { return node; }
} }
public NodeEventArgs(Node node) public NodeEventArgs(Node node)
{ {
this.node = node; this.node = node;
} }
} }
public class NodeCollection: System.Collections.ObjectModel.Collection<Node> public class NodeCollection: System.Collections.ObjectModel.Collection<Node>
{ {
public static NodeCollection Empty = new NodeCollection(); public static NodeCollection Empty = new NodeCollection();
public event EventHandler<NodeEventArgs> Added; public event EventHandler<NodeEventArgs> Added;
public event EventHandler<NodeEventArgs> Removed; public event EventHandler<NodeEventArgs> Removed;
protected virtual void OnAdded(Node node) protected virtual void OnAdded(Node node)
{ {
if (Added != null) { if (Added != null) {
Added(this, new NodeEventArgs(node)); Added(this, new NodeEventArgs(node));
} }
} }
protected virtual void OnRemoved(Node node) protected virtual void OnRemoved(Node node)
{ {
if (Removed != null) { if (Removed != null) {
Removed(this, new NodeEventArgs(node)); Removed(this, new NodeEventArgs(node));
} }
} }
protected override void ClearItems() protected override void ClearItems()
{ {
while(this.Count > 0) { while(this.Count > 0) {
this.RemoveAt(this.Count - 1); this.RemoveAt(this.Count - 1);
} }
} }
protected override void InsertItem(int index, Node item) protected override void InsertItem(int index, Node item)
{ {
if (!this.Contains(item)) { if (!this.Contains(item)) {
base.InsertItem(index, item); base.InsertItem(index, item);
} }
OnAdded(item); OnAdded(item);
} }
protected override void RemoveItem(int index) protected override void RemoveItem(int index)
{ {
Node node = this[index]; Node node = this[index];
base.RemoveItem(index); base.RemoveItem(index);
OnRemoved(node); OnRemoved(node);
} }
protected override void SetItem(int index, Node item) protected override void SetItem(int index, Node item)
{ {
this.RemoveAt(index); this.RemoveAt(index);
this.Insert(index, item); this.Insert(index, item);
} }
public void AddRange(IEnumerable<Node> items) public void AddRange(IEnumerable<Node> items)
{ {
foreach(Node item in items) { foreach(Node item in items) {
this.Add(item); this.Add(item);
} }
} }
public void RemoveRange(IEnumerable<Node> items) public void RemoveRange(IEnumerable<Node> items)
{ {
foreach(Node item in items) { foreach(Node item in items) {
this.Remove(item); this.Remove(item);
} }
} }
public void MoveTo(Node newNode) public void MoveTo(Node newNode)
{ {
foreach(Node child in this.Clone()) { foreach(Node child in this.Clone()) {
child.MoveTo(newNode); child.MoveTo(newNode);
} }
} }
public void MoveTo(Node newNode, int index) public void MoveTo(Node newNode, int index)
{ {
foreach(Node child in this.Clone()) { foreach(Node child in this.Clone()) {
child.MoveTo(newNode, index); child.MoveTo(newNode, index);
index++; index++;
} }
} }
public NodeCollection() public NodeCollection()
{ {
} }
public NodeCollection(IEnumerable<Node> items) public NodeCollection(IEnumerable<Node> items)
{ {
this.AddRange(items); this.AddRange(items);
} }
public NodeCollection Clone() public NodeCollection Clone()
{ {
return new NodeCollection(this); return new NodeCollection(this);
} }
public static NodeCollection Intersect(NodeCollection collectionA, NodeCollection collectionB) public static NodeCollection Intersect(NodeCollection collectionA, NodeCollection collectionB)
{ {
NodeCollection result = new NodeCollection(); NodeCollection result = new NodeCollection();
foreach(Node a in collectionA) { foreach(Node a in collectionA) {
if (collectionB.Contains(a)) { if (collectionB.Contains(a)) {
result.Add(a); result.Add(a);
} }
} }
return result; return result;
} }
public override string ToString() public override string ToString()
{ {
return string.Format("{0} Count = {1}", typeof(NodeCollection).Name, this.Count); return string.Format("{0} Count = {1}", typeof(NodeCollection).Name, this.Count);
} }
} }
} }

510
Decompiler/src/ILAst/ControlFlow/Nodes.cs → ICSharpCode.Decompiler/ILAst/ControlFlow/Nodes.cs

@ -1,255 +1,255 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using Decompiler.Mono.Cecil.Rocks; using Decompiler.Mono.Cecil.Rocks;
using Mono.Cecil; using Mono.Cecil;
using Mono.Cecil.Cil; using Mono.Cecil.Cil;
namespace Decompiler.ControlFlow namespace Decompiler.ControlFlow
{ {
public class BasicBlock: Node public class BasicBlock: Node
{ {
List<ILNode> body = new List<ILNode>(); List<ILNode> body = new List<ILNode>();
List<BasicBlock> basicBlockPredecessors = new List<BasicBlock>(); List<BasicBlock> basicBlockPredecessors = new List<BasicBlock>();
BasicBlock fallThroughBasicBlock; BasicBlock fallThroughBasicBlock;
BasicBlock branchBasicBlock; BasicBlock branchBasicBlock;
public List<ILNode> Body { public List<ILNode> Body {
get { return body; } get { return body; }
} }
public List<BasicBlock> BasicBlockPredecessors { public List<BasicBlock> BasicBlockPredecessors {
get { return basicBlockPredecessors; } get { return basicBlockPredecessors; }
} }
public BasicBlock FallThroughBasicBlock { public BasicBlock FallThroughBasicBlock {
get { return fallThroughBasicBlock; } get { return fallThroughBasicBlock; }
set { fallThroughBasicBlock = value; } set { fallThroughBasicBlock = value; }
} }
public BasicBlock BranchBasicBlock { public BasicBlock BranchBasicBlock {
get { return branchBasicBlock; } get { return branchBasicBlock; }
set { branchBasicBlock = value; } set { branchBasicBlock = value; }
} }
public IEnumerable<BasicBlock> BasicBlockSuccessors { public IEnumerable<BasicBlock> BasicBlockSuccessors {
get { get {
if (this.FallThroughBasicBlock != null) { if (this.FallThroughBasicBlock != null) {
yield return this.FallThroughBasicBlock; yield return this.FallThroughBasicBlock;
} }
if (this.BranchBasicBlock != null) { if (this.BranchBasicBlock != null) {
yield return this.BranchBasicBlock; yield return this.BranchBasicBlock;
} }
} }
} }
} }
public enum ShortCircuitOperator { public enum ShortCircuitOperator {
LeftAndRight, LeftAndRight,
LeftOrRight, LeftOrRight,
NotLeftAndRight, NotLeftAndRight,
NotLeftOrRight, NotLeftOrRight,
} }
public abstract class Branch: Node public abstract class Branch: Node
{ {
public abstract BasicBlock FirstBasicBlock { get; } public abstract BasicBlock FirstBasicBlock { get; }
public abstract BasicBlock TrueSuccessor { get; } public abstract BasicBlock TrueSuccessor { get; }
public abstract BasicBlock FalseSuccessor { get; } public abstract BasicBlock FalseSuccessor { get; }
} }
public class SimpleBranch: Branch public class SimpleBranch: Branch
{ {
public override BasicBlock FirstBasicBlock { public override BasicBlock FirstBasicBlock {
get { get {
return this.BasicBlock; return this.BasicBlock;
} }
} }
public BasicBlock BasicBlock { public BasicBlock BasicBlock {
get { return (BasicBlock)this.Childs[0]; } get { return (BasicBlock)this.Childs[0]; }
} }
public override BasicBlock TrueSuccessor { public override BasicBlock TrueSuccessor {
get { return this.BasicBlock.BranchBasicBlock; } get { return this.BasicBlock.BranchBasicBlock; }
} }
public override BasicBlock FalseSuccessor { public override BasicBlock FalseSuccessor {
get { return this.BasicBlock.FallThroughBasicBlock; } get { return this.BasicBlock.FallThroughBasicBlock; }
} }
} }
public class ShortCircuitBranch: Branch public class ShortCircuitBranch: Branch
{ {
ShortCircuitOperator @operator; ShortCircuitOperator @operator;
public override BasicBlock FirstBasicBlock { public override BasicBlock FirstBasicBlock {
get { get {
return this.Left.FirstBasicBlock; return this.Left.FirstBasicBlock;
} }
} }
public Branch Left { public Branch Left {
get { return (Branch)this.Childs[0];; } get { return (Branch)this.Childs[0];; }
} }
public Branch Right { public Branch Right {
get { return (Branch)this.Childs[1]; } get { return (Branch)this.Childs[1]; }
} }
public ShortCircuitOperator Operator { public ShortCircuitOperator Operator {
get { return @operator; } get { return @operator; }
set { @operator = value; } set { @operator = value; }
} }
public override BasicBlock TrueSuccessor { public override BasicBlock TrueSuccessor {
get { return this.Right.TrueSuccessor; } get { return this.Right.TrueSuccessor; }
} }
public override BasicBlock FalseSuccessor { public override BasicBlock FalseSuccessor {
get { return this.Right.FalseSuccessor; } get { return this.Right.FalseSuccessor; }
} }
} }
public class MethodBodyGraph: Node public class MethodBodyGraph: Node
{ {
BasicBlock methodEntry; BasicBlock methodEntry;
public BasicBlock MethodEntry { public BasicBlock MethodEntry {
get { return methodEntry; } get { return methodEntry; }
} }
Dictionary<ILLabel, BasicBlock> labelToBasicBlock = new Dictionary<ILLabel, BasicBlock>(); Dictionary<ILLabel, BasicBlock> labelToBasicBlock = new Dictionary<ILLabel, BasicBlock>();
public MethodBodyGraph(List<ILNode> ast) public MethodBodyGraph(List<ILNode> ast)
{ {
if (ast.Count == 0) throw new ArgumentException("Count == 0", "ast"); if (ast.Count == 0) throw new ArgumentException("Count == 0", "ast");
this.methodEntry = new BasicBlock(); this.methodEntry = new BasicBlock();
this.Childs.Add(this.methodEntry); this.Childs.Add(this.methodEntry);
this.Childs.AddRange(SplitToBasicBlocks(ast)); this.Childs.AddRange(SplitToBasicBlocks(ast));
// Add branch links to BasicBlocks // Add branch links to BasicBlocks
foreach(BasicBlock basicBlock in this.BasicBlocks) { foreach(BasicBlock basicBlock in this.BasicBlocks) {
foreach(ILNode node in basicBlock.Body) { foreach(ILNode node in basicBlock.Body) {
if (node is ILExpression) { if (node is ILExpression) {
ILExpression expr = (ILExpression)node; ILExpression expr = (ILExpression)node;
if (expr.Operand is ILLabel) { if (expr.Operand is ILLabel) {
BasicBlock target = labelToBasicBlock[(ILLabel)expr.Operand]; BasicBlock target = labelToBasicBlock[(ILLabel)expr.Operand];
basicBlock.BranchBasicBlock = target; basicBlock.BranchBasicBlock = target;
target.BasicBlockPredecessors.Add(basicBlock); target.BasicBlockPredecessors.Add(basicBlock);
} }
// TODO: Switch // TODO: Switch
} }
} }
} }
} }
public List<Node> SplitToBasicBlocks(List<ILNode> ast) public List<Node> SplitToBasicBlocks(List<ILNode> ast)
{ {
if (ast.Count == 0) return new List<Node>(); if (ast.Count == 0) return new List<Node>();
List<Node> nodes = new List<Node>(); List<Node> nodes = new List<Node>();
BasicBlock basicBlock = null; BasicBlock basicBlock = null;
for(int i = 0; i < ast.Count; i++) { for(int i = 0; i < ast.Count; i++) {
if (i == 0 || if (i == 0 ||
ast[i] is ILLabel || ast[i] is ILLabel ||
ast[i - 1] is ILTryCatchBlock || ast[i - 1] is ILTryCatchBlock ||
ast[i] is ILTryCatchBlock || ast[i] is ILTryCatchBlock ||
(ast[i - 1] is ILExpression) && ((ILExpression)ast[i - 1]).OpCode.IsBranch() || (ast[i - 1] is ILExpression) && ((ILExpression)ast[i - 1]).OpCode.IsBranch() ||
(ast[i] is ILExpression) && ((ILExpression)ast[i]).OpCode.IsBranch()) (ast[i] is ILExpression) && ((ILExpression)ast[i]).OpCode.IsBranch())
{ {
BasicBlock oldBB = basicBlock; BasicBlock oldBB = basicBlock;
basicBlock = new BasicBlock(); basicBlock = new BasicBlock();
nodes.Add(basicBlock); nodes.Add(basicBlock);
// Links // Links
if (oldBB != null && ast[i - 1] is ILExpression && ((ILExpression)ast[i - 1]).OpCode.CanFallThough()) { if (oldBB != null && ast[i - 1] is ILExpression && ((ILExpression)ast[i - 1]).OpCode.CanFallThough()) {
oldBB.FallThroughBasicBlock = basicBlock; oldBB.FallThroughBasicBlock = basicBlock;
basicBlock.BasicBlockPredecessors.Add(oldBB); basicBlock.BasicBlockPredecessors.Add(oldBB);
} }
} }
if (ast[i] is ILTryCatchBlock) { if (ast[i] is ILTryCatchBlock) {
nodes.Add(ConvertTryCatch((ILTryCatchBlock)ast[i])); nodes.Add(ConvertTryCatch((ILTryCatchBlock)ast[i]));
} else { } else {
basicBlock.Body.Add(ast[i]); basicBlock.Body.Add(ast[i]);
} }
if (ast[i] is ILLabel) { if (ast[i] is ILLabel) {
labelToBasicBlock[(ILLabel)ast[i]] = basicBlock; labelToBasicBlock[(ILLabel)ast[i]] = basicBlock;
} }
} }
return nodes; return nodes;
} }
public TryCatchNode ConvertTryCatch(ILTryCatchBlock ilTryCatch) public TryCatchNode ConvertTryCatch(ILTryCatchBlock ilTryCatch)
{ {
TryCatchNode tryCatch = new TryCatchNode(); TryCatchNode tryCatch = new TryCatchNode();
Block tryBlock = new Block(); Block tryBlock = new Block();
tryBlock.Childs.AddRange(SplitToBasicBlocks(ilTryCatch.TryBlock)); tryBlock.Childs.AddRange(SplitToBasicBlocks(ilTryCatch.TryBlock));
tryBlock.MoveTo(tryCatch); tryBlock.MoveTo(tryCatch);
Block finallyBlock = new Block(); Block finallyBlock = new Block();
if (ilTryCatch.FinallyBlock != null) { if (ilTryCatch.FinallyBlock != null) {
finallyBlock.Childs.AddRange(SplitToBasicBlocks(ilTryCatch.FinallyBlock)); finallyBlock.Childs.AddRange(SplitToBasicBlocks(ilTryCatch.FinallyBlock));
} }
finallyBlock.MoveTo(tryCatch); finallyBlock.MoveTo(tryCatch);
foreach(ILTryCatchBlock.CatchBlock cb in ilTryCatch.CatchBlocks) { foreach(ILTryCatchBlock.CatchBlock cb in ilTryCatch.CatchBlocks) {
tryCatch.Types.Add(cb.ExceptionType); tryCatch.Types.Add(cb.ExceptionType);
Block catchBlock = new Block(); Block catchBlock = new Block();
catchBlock.Childs.AddRange(SplitToBasicBlocks(cb.Body)); catchBlock.Childs.AddRange(SplitToBasicBlocks(cb.Body));
catchBlock.MoveTo(tryCatch); catchBlock.MoveTo(tryCatch);
} }
return tryCatch; return tryCatch;
} }
} }
public class TryCatchNode: Node public class TryCatchNode: Node
{ {
public List<TypeReference> Types = new List<TypeReference>(); public List<TypeReference> Types = new List<TypeReference>();
} }
public class AcyclicGraph: Node public class AcyclicGraph: Node
{ {
} }
public class Loop: Node public class Loop: Node
{ {
} }
public class Block: Node public class Block: Node
{ {
} }
public class ConditionalNode: Node public class ConditionalNode: Node
{ {
Branch condition; Branch condition;
Block trueBody = new Block(); Block trueBody = new Block();
Block falseBody = new Block(); Block falseBody = new Block();
public Branch Condition { public Branch Condition {
get { return condition; } get { return condition; }
} }
public Block TrueBody { public Block TrueBody {
get { return trueBody; } get { return trueBody; }
} }
public Block FalseBody { public Block FalseBody {
get { return falseBody; } get { return falseBody; }
} }
public ConditionalNode(Branch condition) public ConditionalNode(Branch condition)
{ {
this.condition = condition; this.condition = condition;
condition.MoveTo(this); condition.MoveTo(this);
trueBody.MoveTo(this); trueBody.MoveTo(this);
falseBody.MoveTo(this); falseBody.MoveTo(this);
} }
} }
} }

596
Decompiler/src/ILAst/ILAstBuilder.cs → ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs

@ -1,298 +1,298 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using Decompiler.Mono.Cecil.Rocks; using Decompiler.Mono.Cecil.Rocks;
using Mono.Cecil; using Mono.Cecil;
using Mono.Cecil.Cil; using Mono.Cecil.Cil;
using Cecil = Mono.Cecil; using Cecil = Mono.Cecil;
namespace Decompiler namespace Decompiler
{ {
public class ILAstBuilder public class ILAstBuilder
{ {
class ILStack class ILStack
{ {
public class Slot public class Slot
{ {
public Instruction PushedBy; public Instruction PushedBy;
public TypeReference Type; public TypeReference Type;
public Slot(Instruction inst, TypeReference type) public Slot(Instruction inst, TypeReference type)
{ {
this.PushedBy = inst; this.PushedBy = inst;
this.Type = type; this.Type = type;
} }
} }
public List<Slot> Items = new List<Slot>(); public List<Slot> Items = new List<Slot>();
public ILStack Clone() public ILStack Clone()
{ {
ILStack clone = new ILStack(); ILStack clone = new ILStack();
foreach(Slot s in this.Items) { foreach(Slot s in this.Items) {
clone.Items.Add(new Slot(s.PushedBy, s.Type)); clone.Items.Add(new Slot(s.PushedBy, s.Type));
} }
return clone; return clone;
} }
public override string ToString() public override string ToString()
{ {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
bool first = true; bool first = true;
foreach (Slot s in this.Items) { foreach (Slot s in this.Items) {
if (!first) sb.Append(", "); if (!first) sb.Append(", ");
sb.Append(s.PushedBy.Offset.ToString("X")); sb.Append(s.PushedBy.Offset.ToString("X"));
first = false; first = false;
} }
return sb.ToString(); return sb.ToString();
} }
} }
Dictionary<Instruction, ILStack> stackBefore = new Dictionary<Instruction, ILAstBuilder.ILStack>(); Dictionary<Instruction, ILStack> stackBefore = new Dictionary<Instruction, ILAstBuilder.ILStack>();
Dictionary<Instruction, ILLabel> labels = new Dictionary<Instruction, ILLabel>(); Dictionary<Instruction, ILLabel> labels = new Dictionary<Instruction, ILLabel>();
public List<ILNode> Build(MethodDefinition methodDef) public List<ILNode> Build(MethodDefinition methodDef)
{ {
List<Instruction> body = new List<Instruction>(methodDef.Body.Instructions); List<Instruction> body = new List<Instruction>(methodDef.Body.Instructions);
if (body.Count == 0) return new List<ILNode>(); if (body.Count == 0) return new List<ILNode>();
StackAnalysis(body, methodDef); StackAnalysis(body, methodDef);
// Create branch labels for instructins; use the labels as branch operands // Create branch labels for instructins; use the labels as branch operands
foreach (Instruction inst in body) { foreach (Instruction inst in body) {
if (inst.Operand is Instruction[]) { if (inst.Operand is Instruction[]) {
List<ILLabel> newOperand = new List<ILLabel>(); List<ILLabel> newOperand = new List<ILLabel>();
foreach(Instruction target in (Instruction[])inst.Operand) { foreach(Instruction target in (Instruction[])inst.Operand) {
if (!labels.ContainsKey(target)) { if (!labels.ContainsKey(target)) {
labels[target] = new ILLabel() { Name = "IL_" + target.Offset.ToString("X2") }; labels[target] = new ILLabel() { Name = "IL_" + target.Offset.ToString("X2") };
} }
newOperand.Add(labels[target]); newOperand.Add(labels[target]);
} }
inst.Operand = newOperand.ToArray(); inst.Operand = newOperand.ToArray();
} else if (inst.Operand is Instruction) { } else if (inst.Operand is Instruction) {
Instruction target = (Instruction)inst.Operand; Instruction target = (Instruction)inst.Operand;
if (!labels.ContainsKey(target)) { if (!labels.ContainsKey(target)) {
labels[target] = new ILLabel() { Name = "IL_" + target.Offset.ToString("X2") }; labels[target] = new ILLabel() { Name = "IL_" + target.Offset.ToString("X2") };
} }
inst.Operand = labels[target]; inst.Operand = labels[target];
} }
} }
List<ILNode> ast = ConvertToAst(body, methodDef.Body.ExceptionHandlers); List<ILNode> ast = ConvertToAst(body, methodDef.Body.ExceptionHandlers);
return ast; return ast;
} }
public void StackAnalysis(List<Instruction> body, MethodDefinition methodDef) public void StackAnalysis(List<Instruction> body, MethodDefinition methodDef)
{ {
Queue<Instruction> agenda = new Queue<Instruction>(); Queue<Instruction> agenda = new Queue<Instruction>();
// Add known states // Add known states
stackBefore[body[0]] = new ILStack(); stackBefore[body[0]] = new ILStack();
agenda.Enqueue(body[0]); agenda.Enqueue(body[0]);
if(methodDef.Body.HasExceptionHandlers) { if(methodDef.Body.HasExceptionHandlers) {
foreach(ExceptionHandler ex in methodDef.Body.ExceptionHandlers) { foreach(ExceptionHandler ex in methodDef.Body.ExceptionHandlers) {
stackBefore[ex.TryStart] = new ILStack(); stackBefore[ex.TryStart] = new ILStack();
agenda.Enqueue(ex.TryStart); agenda.Enqueue(ex.TryStart);
ILStack stack = new ILStack(); ILStack stack = new ILStack();
stack.Items.Add(new ILStack.Slot(null, MyRocks.TypeException)); stack.Items.Add(new ILStack.Slot(null, MyRocks.TypeException));
stackBefore[ex.HandlerStart] = stack; stackBefore[ex.HandlerStart] = stack;
agenda.Enqueue(ex.HandlerStart); agenda.Enqueue(ex.HandlerStart);
} }
} }
// Process agenda // Process agenda
while(agenda.Count > 0) { while(agenda.Count > 0) {
Instruction inst = agenda.Dequeue(); Instruction inst = agenda.Dequeue();
// What is the effect of the instruction on the stack? // What is the effect of the instruction on the stack?
ILStack newStack = stackBefore[inst].Clone(); ILStack newStack = stackBefore[inst].Clone();
int popCount = inst.GetPopCount(); int popCount = inst.GetPopCount();
if (popCount == int.MaxValue) popCount = stackBefore[inst].Items.Count; // Pop all if (popCount == int.MaxValue) popCount = stackBefore[inst].Items.Count; // Pop all
List<TypeReference> typeArgs = new List<TypeReference>(); List<TypeReference> typeArgs = new List<TypeReference>();
for (int i = newStack.Items.Count - popCount; i < newStack.Items.Count; i++) { for (int i = newStack.Items.Count - popCount; i < newStack.Items.Count; i++) {
typeArgs.Add(newStack.Items[i].Type); typeArgs.Add(newStack.Items[i].Type);
} }
TypeReference type; TypeReference type;
try { try {
type = inst.GetTypeInternal(methodDef, typeArgs); type = inst.GetTypeInternal(methodDef, typeArgs);
} catch { } catch {
type = MyRocks.TypeObject; type = MyRocks.TypeObject;
} }
if (popCount > 0) { if (popCount > 0) {
newStack.Items.RemoveRange(newStack.Items.Count - popCount, popCount); newStack.Items.RemoveRange(newStack.Items.Count - popCount, popCount);
} }
int pushCount = inst.GetPushCount(); int pushCount = inst.GetPushCount();
for (int i = 0; i < pushCount; i++) { for (int i = 0; i < pushCount; i++) {
newStack.Items.Add(new ILStack.Slot(inst, type)); newStack.Items.Add(new ILStack.Slot(inst, type));
} }
// Apply the state to any successors // Apply the state to any successors
List<Instruction> branchTargets = new List<Instruction>(); List<Instruction> branchTargets = new List<Instruction>();
if (inst.OpCode.CanFallThough()) { if (inst.OpCode.CanFallThough()) {
branchTargets.Add(inst.Next); branchTargets.Add(inst.Next);
} }
if (inst.OpCode.IsBranch()) { if (inst.OpCode.IsBranch()) {
if (inst.Operand is Instruction[]) { if (inst.Operand is Instruction[]) {
branchTargets.AddRange((Instruction[])inst.Operand); branchTargets.AddRange((Instruction[])inst.Operand);
} else { } else {
branchTargets.Add((Instruction)inst.Operand); branchTargets.Add((Instruction)inst.Operand);
} }
} }
foreach (Instruction branchTarget in branchTargets) { foreach (Instruction branchTarget in branchTargets) {
ILStack nextStack; ILStack nextStack;
if (stackBefore.TryGetValue(branchTarget, out nextStack)) { if (stackBefore.TryGetValue(branchTarget, out nextStack)) {
// TODO: Compare stacks // TODO: Compare stacks
} else { } else {
stackBefore[branchTarget] = newStack; stackBefore[branchTarget] = newStack;
agenda.Enqueue(branchTarget); agenda.Enqueue(branchTarget);
} }
} }
} }
} }
public List<ILNode> ConvertToAst(List<Instruction> body, IEnumerable<ExceptionHandler> ehs) public List<ILNode> ConvertToAst(List<Instruction> body, IEnumerable<ExceptionHandler> ehs)
{ {
List<ILNode> ast = new List<ILNode>(); List<ILNode> ast = new List<ILNode>();
while (ehs.Any()) { while (ehs.Any()) {
ILTryCatchBlock tryCatchBlock = new ILTryCatchBlock(); ILTryCatchBlock tryCatchBlock = new ILTryCatchBlock();
// Find the first and widest scope // Find the first and widest scope
int tryStart = ehs.Min(eh => eh.TryStart.Offset); int tryStart = ehs.Min(eh => eh.TryStart.Offset);
int tryEnd = ehs.Where(eh => eh.TryStart.Offset == tryStart).Max(eh => eh.TryEnd.Offset); int tryEnd = ehs.Where(eh => eh.TryStart.Offset == tryStart).Max(eh => eh.TryEnd.Offset);
var handlers = ehs.Where(eh => eh.TryStart.Offset == tryStart && eh.TryEnd.Offset == tryEnd).ToList(); var handlers = ehs.Where(eh => eh.TryStart.Offset == tryStart && eh.TryEnd.Offset == tryEnd).ToList();
// Cut all instructions up to the try block // Cut all instructions up to the try block
{ {
int tryStartIdx; int tryStartIdx;
for (tryStartIdx = 0; body[tryStartIdx].Offset != tryStart; tryStartIdx++); for (tryStartIdx = 0; body[tryStartIdx].Offset != tryStart; tryStartIdx++);
ast.AddRange(ConvertToAst(body.CutRange(0, tryStartIdx))); ast.AddRange(ConvertToAst(body.CutRange(0, tryStartIdx)));
} }
// Cut the try block // Cut the try block
{ {
List<ExceptionHandler> nestedEHs = ehs.Where(eh => (tryStart <= eh.TryStart.Offset && eh.TryEnd.Offset < tryEnd) || (tryStart < eh.TryStart.Offset && eh.TryEnd.Offset <= tryEnd)).ToList(); List<ExceptionHandler> nestedEHs = ehs.Where(eh => (tryStart <= eh.TryStart.Offset && eh.TryEnd.Offset < tryEnd) || (tryStart < eh.TryStart.Offset && eh.TryEnd.Offset <= tryEnd)).ToList();
int tryEndIdx; int tryEndIdx;
for (tryEndIdx = 0; tryEndIdx < body.Count && body[tryEndIdx].Offset != tryEnd; tryEndIdx++); for (tryEndIdx = 0; tryEndIdx < body.Count && body[tryEndIdx].Offset != tryEnd; tryEndIdx++);
tryCatchBlock.TryBlock = ConvertToAst(body.CutRange(0, tryEndIdx), nestedEHs); tryCatchBlock.TryBlock = ConvertToAst(body.CutRange(0, tryEndIdx), nestedEHs);
} }
// Cut all handlers // Cut all handlers
tryCatchBlock.CatchBlocks = new List<ILTryCatchBlock.CatchBlock>(); tryCatchBlock.CatchBlocks = new List<ILTryCatchBlock.CatchBlock>();
foreach(ExceptionHandler eh in handlers) { foreach(ExceptionHandler eh in handlers) {
int start; int start;
for (start = 0; body[start] != eh.HandlerStart; start++); for (start = 0; body[start] != eh.HandlerStart; start++);
int end; int end;
for (end = 0; body[end] != eh.HandlerEnd; end++); for (end = 0; body[end] != eh.HandlerEnd; end++);
int count = end - start; int count = end - start;
List<ExceptionHandler> nestedEHs = ehs.Where(e => (start <= e.TryStart.Offset && e.TryEnd.Offset < end) || (start < e.TryStart.Offset && e.TryEnd.Offset <= end)).ToList(); List<ExceptionHandler> nestedEHs = ehs.Where(e => (start <= e.TryStart.Offset && e.TryEnd.Offset < end) || (start < e.TryStart.Offset && e.TryEnd.Offset <= end)).ToList();
List<ILNode> handlerAst = ConvertToAst(body.CutRange(start, count), nestedEHs); List<ILNode> handlerAst = ConvertToAst(body.CutRange(start, count), nestedEHs);
if (eh.HandlerType == ExceptionHandlerType.Catch) { if (eh.HandlerType == ExceptionHandlerType.Catch) {
tryCatchBlock.CatchBlocks.Add(new ILTryCatchBlock.CatchBlock() { tryCatchBlock.CatchBlocks.Add(new ILTryCatchBlock.CatchBlock() {
ExceptionType = eh.CatchType, ExceptionType = eh.CatchType,
Body = handlerAst Body = handlerAst
}); });
} else if (eh.HandlerType == ExceptionHandlerType.Finally) { } else if (eh.HandlerType == ExceptionHandlerType.Finally) {
tryCatchBlock.FinallyBlock = handlerAst; tryCatchBlock.FinallyBlock = handlerAst;
} else { } else {
// TODO // TODO
} }
} }
ehs = ehs.Where(eh => eh.TryStart.Offset > tryEnd).ToList(); ehs = ehs.Where(eh => eh.TryStart.Offset > tryEnd).ToList();
ast.Add(tryCatchBlock); ast.Add(tryCatchBlock);
} }
// Add whatever is left // Add whatever is left
ast.AddRange(ConvertToAst(body)); ast.AddRange(ConvertToAst(body));
return ast; return ast;
} }
public List<ILNode> ConvertToAst(List<Instruction> body) public List<ILNode> ConvertToAst(List<Instruction> body)
{ {
List<ILNode> ast = new List<ILNode>(); List<ILNode> ast = new List<ILNode>();
// Convert stack-based IL code to ILAst tree // Convert stack-based IL code to ILAst tree
foreach(Instruction inst in body) { foreach(Instruction inst in body) {
ILExpression expr = new ILExpression(inst.OpCode, inst.Operand); ILExpression expr = new ILExpression(inst.OpCode, inst.Operand);
// Label for this instruction // Label for this instruction
ILLabel label; ILLabel label;
if (labels.TryGetValue(inst, out label)) { if (labels.TryGetValue(inst, out label)) {
ast.Add(label); ast.Add(label);
} }
// Reference arguments using temporary variables // Reference arguments using temporary variables
ILStack stack = stackBefore[inst]; ILStack stack = stackBefore[inst];
int popCount = inst.GetPopCount(); int popCount = inst.GetPopCount();
if (popCount == int.MaxValue) popCount = stackBefore[inst].Items.Count; // Pop all if (popCount == int.MaxValue) popCount = stackBefore[inst].Items.Count; // Pop all
for (int i = stack.Items.Count - popCount; i < stack.Items.Count; i++) { for (int i = stack.Items.Count - popCount; i < stack.Items.Count; i++) {
Instruction pushedBy = stack.Items[i].PushedBy; Instruction pushedBy = stack.Items[i].PushedBy;
if (pushedBy != null) { if (pushedBy != null) {
ILExpression ldExpr = new ILExpression(OpCodes.Ldloc, new ILStackVariable() { Name = "expr" + pushedBy.Offset.ToString("X2") }); ILExpression ldExpr = new ILExpression(OpCodes.Ldloc, new ILStackVariable() { Name = "expr" + pushedBy.Offset.ToString("X2") });
expr.Arguments.Add(ldExpr); expr.Arguments.Add(ldExpr);
} else { } else {
ILExpression ldExpr = new ILExpression(OpCodes.Ldloc, new ILStackVariable() { Name = "exception" }); ILExpression ldExpr = new ILExpression(OpCodes.Ldloc, new ILStackVariable() { Name = "exception" });
expr.Arguments.Add(ldExpr); expr.Arguments.Add(ldExpr);
} }
} }
// If the bytecode pushes anything store the result in temporary variable // If the bytecode pushes anything store the result in temporary variable
int pushCount = inst.GetPushCount(); int pushCount = inst.GetPushCount();
if (pushCount > 0) { if (pushCount > 0) {
ILExpression stExpr = new ILExpression(OpCodes.Stloc, new ILStackVariable() { Name = "expr" + inst.Offset.ToString("X2"), RefCount = pushCount }); ILExpression stExpr = new ILExpression(OpCodes.Stloc, new ILStackVariable() { Name = "expr" + inst.Offset.ToString("X2"), RefCount = pushCount });
stExpr.Arguments.Add(expr); stExpr.Arguments.Add(expr);
expr = stExpr; expr = stExpr;
} }
ast.Add(expr); ast.Add(expr);
} }
// Try to in-line stloc / ldloc pairs // Try to in-line stloc / ldloc pairs
for(int i = 0; i < ast.Count - 1; i++) { for(int i = 0; i < ast.Count - 1; i++) {
ILExpression expr = ast[i] as ILExpression; ILExpression expr = ast[i] as ILExpression;
ILExpression nextExpr = ast[i + 1] as ILExpression; ILExpression nextExpr = ast[i + 1] as ILExpression;
if (expr != null && nextExpr != null && expr.OpCode.Code == Code.Stloc && expr.Operand is ILStackVariable) { if (expr != null && nextExpr != null && expr.OpCode.Code == Code.Stloc && expr.Operand is ILStackVariable) {
// If the next expression is stloc, look inside // If the next expression is stloc, look inside
if (nextExpr.OpCode.Code == Code.Stloc && nextExpr.Operand is ILStackVariable) { if (nextExpr.OpCode.Code == Code.Stloc && nextExpr.Operand is ILStackVariable) {
nextExpr = nextExpr.Arguments[0]; nextExpr = nextExpr.Arguments[0];
} }
// Find the use of the 'expr' // Find the use of the 'expr'
for(int j = 0; j < nextExpr.Arguments.Count; j++) { for(int j = 0; j < nextExpr.Arguments.Count; j++) {
ILExpression arg = nextExpr.Arguments[j]; ILExpression arg = nextExpr.Arguments[j];
// TODO: Check if duplicating the dup opcode has side-effects // TODO: Check if duplicating the dup opcode has side-effects
if (arg.OpCode.Code == Code.Ldloc && arg.Operand is ILStackVariable) { if (arg.OpCode.Code == Code.Ldloc && arg.Operand is ILStackVariable) {
ILStackVariable stVar = (ILStackVariable)expr.Operand; ILStackVariable stVar = (ILStackVariable)expr.Operand;
ILStackVariable ldVar = (ILStackVariable)arg.Operand; ILStackVariable ldVar = (ILStackVariable)arg.Operand;
if (stVar.Name == ldVar.Name) { if (stVar.Name == ldVar.Name) {
stVar.RefCount--; stVar.RefCount--;
if (stVar.RefCount <= 0) { if (stVar.RefCount <= 0) {
ast.RemoveAt(i); ast.RemoveAt(i);
} }
nextExpr.Arguments[j] = expr.Arguments[0]; // Inline the stloc body nextExpr.Arguments[j] = expr.Arguments[0]; // Inline the stloc body
i = Math.Max(0, i - 2); // Try the same index again i = Math.Max(0, i - 2); // Try the same index again
break; // Found break; // Found
} }
} else { } else {
break; // This argument might have side effects so we can not move the 'expr' after it. break; // This argument might have side effects so we can not move the 'expr' after it.
} }
} }
} }
} }
return ast; return ast;
} }
} }
} }

174
Decompiler/src/ILAst/ILAstTypes.cs → ICSharpCode.Decompiler/ILAst/ILAstTypes.cs

@ -1,87 +1,87 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text; using System.Text;
using Decompiler.ControlFlow; using Decompiler.ControlFlow;
using Mono.Cecil; using Mono.Cecil;
using Mono.Cecil.Cil; using Mono.Cecil.Cil;
using Cecil = Mono.Cecil; using Cecil = Mono.Cecil;
namespace Decompiler namespace Decompiler
{ {
public class ILNode public class ILNode
{ {
} }
public class ILLabel: ILNode public class ILLabel: ILNode
{ {
public string Name; public string Name;
public override string ToString() public override string ToString()
{ {
return Name + ":"; return Name + ":";
} }
} }
public class ILTryCatchBlock: ILNode public class ILTryCatchBlock: ILNode
{ {
public class CatchBlock public class CatchBlock
{ {
public TypeReference ExceptionType; public TypeReference ExceptionType;
public List<ILNode> Body; public List<ILNode> Body;
} }
public List<ILNode> TryBlock; public List<ILNode> TryBlock;
public List<CatchBlock> CatchBlocks; public List<CatchBlock> CatchBlocks;
public List<ILNode> FinallyBlock; public List<ILNode> FinallyBlock;
public override string ToString() public override string ToString()
{ {
return "Try-Catch{}"; return "Try-Catch{}";
} }
} }
public class ILStackVariable public class ILStackVariable
{ {
public string Name; public string Name;
public int RefCount; public int RefCount;
public override string ToString() public override string ToString()
{ {
return Name; return Name;
} }
} }
public class ILExpression: ILNode public class ILExpression: ILNode
{ {
public OpCode OpCode { get; set; } public OpCode OpCode { get; set; }
public object Operand { get; set; } public object Operand { get; set; }
public List<ILExpression> Arguments { get; set; } public List<ILExpression> Arguments { get; set; }
public ILExpression(OpCode opCode, object operand, params ILExpression[] args) public ILExpression(OpCode opCode, object operand, params ILExpression[] args)
{ {
this.OpCode = opCode; this.OpCode = opCode;
this.Operand = operand; this.Operand = operand;
this.Arguments = new List<ILExpression>(args); this.Arguments = new List<ILExpression>(args);
} }
public override string ToString() public override string ToString()
{ {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.Append(OpCode.Name); sb.Append(OpCode.Name);
sb.Append('('); sb.Append('(');
bool first = true; bool first = true;
if (Operand != null) { if (Operand != null) {
sb.Append(Operand.ToString()); sb.Append(Operand.ToString());
first = false; first = false;
} }
foreach (ILExpression arg in this.Arguments) { foreach (ILExpression arg in this.Arguments) {
if (!first) sb.Append(","); if (!first) sb.Append(",");
sb.Append(arg.ToString()); sb.Append(arg.ToString());
first = false; first = false;
} }
sb.Append(')'); sb.Append(')');
return sb.ToString(); return sb.ToString();
} }
} }
} }

0
Decompiler/src/Mono.Cecil.Rocks/Constants.cs → ICSharpCode.Decompiler/Mono.Cecil.Rocks/Constants.cs

0
Decompiler/src/Mono.Cecil.Rocks/MethodBodyRocks.cs → ICSharpCode.Decompiler/Mono.Cecil.Rocks/MethodBodyRocks.cs

2
Decompiler/src/Mono.Cecil.Rocks/MyRocks.cs → ICSharpCode.Decompiler/Mono.Cecil.Rocks/MyRocks.cs

@ -126,7 +126,7 @@ namespace Decompiler.Mono.Cecil.Rocks
static public TypeReference GetCecilType(Type type) static public TypeReference GetCecilType(Type type)
{ {
return new TypeReference(type.Name, type.Namespace, null, type.IsValueType); return new TypeReference(type.Name, type.Namespace, null, null, type.IsValueType);
} }
static public TypeReference GetTypeInternal(this Instruction inst, MethodDefinition methodDef, List<TypeReference> args) static public TypeReference GetTypeInternal(this Instruction inst, MethodDefinition methodDef, List<TypeReference> args)

44
Decompiler/src/Options.cs → ICSharpCode.Decompiler/Options.cs

@ -1,22 +1,22 @@
using System; using System;
namespace Decompiler namespace Decompiler
{ {
public static class Options public static class Options
{ {
public static string TypeFilter = null; public static string TypeFilter = null;
public static int CollapseExpression = 1000; public static int CollapseExpression = 1000;
public static int ReduceGraph = 1000; public static int ReduceGraph = 1000;
public static bool NodeComments = false; public static bool NodeComments = false;
public static bool ReduceLoops = true; public static bool ReduceLoops = true;
public static bool ReduceConditonals = true; public static bool ReduceConditonals = true;
public static bool ReduceAstJumps = true; public static bool ReduceAstJumps = true;
public static bool ReduceAstLoops = true; public static bool ReduceAstLoops = true;
public static bool ReduceAstOther = true; public static bool ReduceAstOther = true;
} }
class StopOptimizations: Exception class StopOptimizations: Exception
{ {
} }
} }

10
ILSpy.sln

@ -12,6 +12,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICSharpCode.AvalonEdit", "A
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICSharpCode.Decompiler", "ICSharpCode.Decompiler\ICSharpCode.Decompiler.csproj", "{984CC812-9470-4A13-AFF9-CC44068D666C}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICSharpCode.Decompiler", "ICSharpCode.Decompiler\ICSharpCode.Decompiler.csproj", "{984CC812-9470-4A13-AFF9-CC44068D666C}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NRefactory", "Decompiler\lib\NRefactory\Project\NRefactory.csproj", "{3A9AE6AA-BC07-4A2F-972C-581E3AE2F195}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x86 = Debug|x86 Debug|x86 = Debug|x86
@ -60,5 +62,13 @@ Global
{984CC812-9470-4A13-AFF9-CC44068D666C}.Release|x86.ActiveCfg = Release|Any CPU {984CC812-9470-4A13-AFF9-CC44068D666C}.Release|x86.ActiveCfg = Release|Any CPU
{984CC812-9470-4A13-AFF9-CC44068D666C}.Release|Any CPU.Build.0 = Release|Any CPU {984CC812-9470-4A13-AFF9-CC44068D666C}.Release|Any CPU.Build.0 = Release|Any CPU
{984CC812-9470-4A13-AFF9-CC44068D666C}.Release|Any CPU.ActiveCfg = Release|Any CPU {984CC812-9470-4A13-AFF9-CC44068D666C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3A9AE6AA-BC07-4A2F-972C-581E3AE2F195}.Debug|x86.Build.0 = Debug|Any CPU
{3A9AE6AA-BC07-4A2F-972C-581E3AE2F195}.Debug|x86.ActiveCfg = Debug|Any CPU
{3A9AE6AA-BC07-4A2F-972C-581E3AE2F195}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3A9AE6AA-BC07-4A2F-972C-581E3AE2F195}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3A9AE6AA-BC07-4A2F-972C-581E3AE2F195}.Release|x86.Build.0 = Release|Any CPU
{3A9AE6AA-BC07-4A2F-972C-581E3AE2F195}.Release|x86.ActiveCfg = Release|Any CPU
{3A9AE6AA-BC07-4A2F-972C-581E3AE2F195}.Release|Any CPU.Build.0 = Release|Any CPU
{3A9AE6AA-BC07-4A2F-972C-581E3AE2F195}.Release|Any CPU.ActiveCfg = Release|Any CPU
EndGlobalSection EndGlobalSection
EndGlobal EndGlobal

10
ILSpy/CSharpLanguage.cs

@ -17,6 +17,7 @@
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using System; using System;
using Decompiler;
using ICSharpCode.Decompiler; using ICSharpCode.Decompiler;
using Mono.Cecil; using Mono.Cecil;
@ -37,7 +38,14 @@ namespace ICSharpCode.ILSpy
public override void DecompileMethod(MethodDefinition method, ITextOutput output, DecompilationOptions options) public override void DecompileMethod(MethodDefinition method, ITextOutput output, DecompilationOptions options)
{ {
throw new NotImplementedException(); throw new NotImplementedException("Currently we can decompile only whole types.");
}
public override void DecompileType(TypeDefinition type, ITextOutput output, DecompilationOptions options)
{
AstBuilder codeDomBuilder = new AstBuilder();
codeDomBuilder.AddType(type);
output.Write(codeDomBuilder.GenerateCode());
} }
} }
} }

Loading…
Cancel
Save