Skip to content
Browse files

Move decompiler code into ICSharpCode.Decompiler; add very simple int…

…egration with ILSpy.
  • Loading branch information...
1 parent 6cadb0d commit 949e7c2378c349f36293aeacf272ea02e7bffa3d @dgrunwald dgrunwald committed
Showing with 3,237 additions and 3,189 deletions.
  1. +316 −316 {Decompiler/src → ICSharpCode.Decompiler}/Ast/AstBuilder.cs
  2. +748 −748 {Decompiler/src → ICSharpCode.Decompiler}/Ast/AstMetodBodyBuilder.cs
  3. +76 −76 {Decompiler/src → ICSharpCode.Decompiler}/Ast/Transforms/Idioms.cs
  4. +87 −87 {Decompiler/src → ICSharpCode.Decompiler}/Ast/Transforms/PushNegation.cs
  5. +50 −50 {Decompiler/src → ICSharpCode.Decompiler}/Ast/Transforms/RemoveDeadLabels.cs
  6. +36 −36 {Decompiler/src → ICSharpCode.Decompiler}/Ast/Transforms/RemoveEmptyElseBody.cs
  7. +186 −186 {Decompiler/src → ICSharpCode.Decompiler}/Ast/Transforms/RemoveGotos.cs
  8. +245 −245 {Decompiler/src → ICSharpCode.Decompiler}/Ast/Transforms/RemoveParenthesis.cs
  9. +75 −75 {Decompiler/src → ICSharpCode.Decompiler}/Ast/Transforms/RestoreLoop.cs
  10. +91 −91 {Decompiler/src → ICSharpCode.Decompiler}/Ast/Transforms/SimplifyTypeReferences.cs
  11. +30 −0 ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
  12. +192 −192 {Decompiler/src → ICSharpCode.Decompiler}/ILAst/ControlFlow/Node-Optimize.cs
  13. +233 −233 {Decompiler/src → ICSharpCode.Decompiler}/ILAst/ControlFlow/Node-Structure.cs
  14. +60 −60 {Decompiler/src → ICSharpCode.Decompiler}/ILAst/ControlFlow/Node-Transforms.cs
  15. +130 −130 {Decompiler/src → ICSharpCode.Decompiler}/ILAst/ControlFlow/NodeCollection.cs
  16. +255 −255 {Decompiler/src → ICSharpCode.Decompiler}/ILAst/ControlFlow/Nodes.cs
  17. +298 −298 {Decompiler/src → ICSharpCode.Decompiler}/ILAst/ILAstBuilder.cs
  18. +87 −87 {Decompiler/src → ICSharpCode.Decompiler}/ILAst/ILAstTypes.cs
  19. 0 {Decompiler/src → ICSharpCode.Decompiler}/Mono.Cecil.Rocks/Constants.cs
  20. 0 {Decompiler/src → ICSharpCode.Decompiler}/Mono.Cecil.Rocks/MethodBodyRocks.cs
  21. +1 −1 {Decompiler/src → ICSharpCode.Decompiler}/Mono.Cecil.Rocks/MyRocks.cs
  22. +22 −22 {Decompiler/src → ICSharpCode.Decompiler}/Options.cs
  23. +10 −0 ILSpy.sln
  24. +9 −1 ILSpy/CSharpLanguage.cs
View
632 Decompiler/src/Ast/AstBuilder.cs → ICSharpCode.Decompiler/Ast/AstBuilder.cs
@@ -1,316 +1,316 @@
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using Ast = ICSharpCode.NRefactory.Ast;
-using ICSharpCode.NRefactory.Ast;
-using ICSharpCode.NRefactory.PrettyPrinter;
-using Mono.Cecil;
-using Mono.Cecil.Cil;
-
-namespace Decompiler
-{
- public class AstBuilder
- {
- CompilationUnit astCompileUnit = new CompilationUnit();
- Dictionary<string, NamespaceDeclaration> astNamespaces = new Dictionary<string, NamespaceDeclaration>();
-
- public string GenerateCode()
- {
- CSharpOutputVisitor csOutVisitor = new CSharpOutputVisitor();
-
- for (int i = 0; i < 4; i++) {
- if (Options.ReduceAstJumps) {
- astCompileUnit.AcceptVisitor(new Transforms.Ast.RemoveGotos(), null);
- astCompileUnit.AcceptVisitor(new Transforms.Ast.RemoveDeadLabels(), null);
- }
- if (Options.ReduceAstLoops) {
- astCompileUnit.AcceptVisitor(new Transforms.Ast.RestoreLoop(), null);
- }
- if (Options.ReduceAstOther) {
- astCompileUnit.AcceptVisitor(new Transforms.Ast.Idioms(), 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);
- }
- }
- if (Options.ReduceAstOther) {
- 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.Idioms(), null);
- }
- if (Options.ReduceAstLoops) {
- astCompileUnit.AcceptVisitor(new Transforms.Ast.RestoreLoop(), null);
- }
-
- astCompileUnit.AcceptVisitor(csOutVisitor, null);
-
- string code = csOutVisitor.Text;
- for(int i = 10; i >= 0; i--) {
- code = code.Replace("\r\n" + new string('\t', i) + "else {", " else {");
- }
- code = code.Replace("\t", " ");
- code = code.Replace("\"/***", "");
- code = code.Replace("***/\";", "");
-
- // Post processing commands
- while(true) {
- int endIndex = code.IndexOf("[JoinLine]") + "[JoinLine]".Length;
- if (endIndex != -1) {
- int startIndex = code.LastIndexOf("\r\n", endIndex, endIndex);
- if (startIndex != -1) {
- code = code.Remove(startIndex, endIndex - startIndex);
- continue;
- }
- }
- break;
- }
- while(true) {
- int endIndex = code.IndexOf("[Tab]");
- if (endIndex != -1) {
- int startIndex = code.LastIndexOf("\r\n", endIndex, endIndex);
- if (startIndex != -1) {
- code = code.Remove(endIndex, "[Tab]".Length);
- code = code.Insert(endIndex, new string(' ', Math.Max(0, 40 - endIndex + startIndex)));
- continue;
- }
- }
- break;
- }
-
- return code;
- }
-
- public void AddAssembly(AssemblyDefinition assemblyDefinition)
- {
- Ast.UsingDeclaration astUsing = new Ast.UsingDeclaration("System");
- astCompileUnit.Children.Add(astUsing);
-
- foreach(TypeDefinition typeDef in assemblyDefinition.MainModule.Types) {
- // Skip nested types - they will be added by the parent type
- if (typeDef.DeclaringType != null) continue;
- // Skip the <Module> class
- if (typeDef.Name == "<Module>") continue;
-
- AddType(typeDef);
- }
- }
-
- NamespaceDeclaration GetCodeNamespace(string name)
- {
- if (string.IsNullOrEmpty(name)) {
- return null;
- }
- if (astNamespaces.ContainsKey(name)) {
- return astNamespaces[name];
- } else {
- // Create the namespace
- NamespaceDeclaration astNamespace = new NamespaceDeclaration(name);
- astCompileUnit.Children.Add(astNamespace);
- astNamespaces[name] = astNamespace;
- return astNamespace;
- }
- }
-
- public void AddType(TypeDefinition typeDef)
- {
- if (!string.IsNullOrEmpty(Options.TypeFilter) && typeDef.Name != Options.TypeFilter) return;
-
- TypeDeclaration astType = CreateType(typeDef);
- NamespaceDeclaration astNS = GetCodeNamespace(typeDef.Namespace);
- if (astNS != null) {
- astNS.Children.Add(astType);
- } else {
- astCompileUnit.Children.Add(astType);
- }
- }
-
- public TypeDeclaration CreateType(TypeDefinition typeDef)
- {
- TypeDeclaration astType = new TypeDeclaration(ConvertModifiers(typeDef), new List<AttributeSection>());
- astType.Name = typeDef.Name;
-
- if (typeDef.IsEnum) { // NB: Enum is value type
- astType.Type = ClassType.Enum;
- } else if (typeDef.IsValueType) {
- astType.Type = ClassType.Struct;
- } else if (typeDef.IsInterface) {
- astType.Type = ClassType.Interface;
- } else {
- astType.Type = ClassType.Class;
- }
-
- // Nested types
- foreach(TypeDefinition nestedTypeDef in typeDef.NestedTypes) {
- astType.Children.Add(CreateType(nestedTypeDef));
- }
-
- // Base type
- if (typeDef.BaseType != null && !typeDef.IsValueType && typeDef.BaseType.FullName != Constants.Object) {
- astType.BaseTypes.Add(new Ast.TypeReference(typeDef.BaseType.FullName));
- }
-
- AddTypeMembers(astType, typeDef);
-
- return astType;
- }
-
- Modifiers ConvertModifiers(TypeDefinition typeDef)
- {
- return
- (typeDef.IsNestedPrivate ? Modifiers.Private : Modifiers.None) |
- (typeDef.IsNestedFamilyAndAssembly ? Modifiers.Protected : Modifiers.None) | // TODO: Extended access
- (typeDef.IsNestedAssembly ? Modifiers.Internal : Modifiers.None) |
- (typeDef.IsNestedFamily ? Modifiers.Protected : Modifiers.None) |
- (typeDef.IsNestedFamilyOrAssembly ? Modifiers.Protected | Modifiers.Internal : Modifiers.None) |
- (typeDef.IsPublic ? Modifiers.Public : Modifiers.None) |
- (typeDef.IsAbstract ? Modifiers.Abstract : Modifiers.None);
- }
-
- Modifiers ConvertModifiers(FieldDefinition fieldDef)
- {
- return
- (fieldDef.IsPrivate ? Modifiers.Private : Modifiers.None) |
- (fieldDef.IsFamilyAndAssembly ? Modifiers.Protected : Modifiers.None) | // TODO: Extended access
- (fieldDef.IsAssembly ? Modifiers.Internal : Modifiers.None) |
- (fieldDef.IsFamily ? Modifiers.Protected : Modifiers.None) |
- (fieldDef.IsFamilyOrAssembly ? Modifiers.Protected | Modifiers.Internal : Modifiers.None) |
- (fieldDef.IsPublic ? Modifiers.Public : Modifiers.None) |
- (fieldDef.IsLiteral ? Modifiers.Const : Modifiers.None) |
- (fieldDef.IsStatic ? Modifiers.Static : Modifiers.None);
- }
-
- Modifiers ConvertModifiers(MethodDefinition methodDef)
- {
- return
- (methodDef.IsCompilerControlled ? Modifiers.None : Modifiers.None) |
- (methodDef.IsPrivate ? Modifiers.Private : Modifiers.None) |
- (methodDef.IsFamilyAndAssembly ? Modifiers.Protected : Modifiers.None) | // TODO: Extended access
- (methodDef.IsAssembly ? Modifiers.Internal : Modifiers.None) |
- (methodDef.IsFamily ? Modifiers.Protected : Modifiers.None) |
- (methodDef.IsFamilyOrAssembly ? Modifiers.Protected | Modifiers.Internal : Modifiers.None) |
- (methodDef.IsPublic ? Modifiers.Public : Modifiers.None) |
- (methodDef.IsStatic ? Modifiers.Static : Modifiers.None) |
- (methodDef.IsVirtual ? Modifiers.Virtual : Modifiers.None) |
- (methodDef.IsAbstract ? Modifiers.Abstract : Modifiers.None);
- }
-
- void AddTypeMembers(TypeDeclaration astType, TypeDefinition typeDef)
- {
- // Add fields
- foreach(FieldDefinition fieldDef in typeDef.Fields) {
- Ast.FieldDeclaration astField = new Ast.FieldDeclaration(new List<AttributeSection>());
- astField.Fields.Add(new Ast.VariableDeclaration(fieldDef.Name));
- astField.TypeReference = new Ast.TypeReference(fieldDef.FieldType.FullName);
- astField.Modifier = ConvertModifiers(fieldDef);
-
- astType.Children.Add(astField);
- }
-
- if (typeDef.Fields.Count > 0) {
- astType.Children.Add(new IdentifierExpression("\r\n"));
- }
-
- // Add events
- foreach(EventDefinition eventDef in typeDef.Events) {
- Ast.EventDeclaration astEvent = new Ast.EventDeclaration();
- astEvent.Name = eventDef.Name;
- astEvent.TypeReference = new Ast.TypeReference(eventDef.EventType.FullName);
- astEvent.Modifier = ConvertModifiers(eventDef.AddMethod);
-
- astType.Children.Add(astEvent);
- }
-
- if (typeDef.Events.Count > 0) {
- astType.Children.Add(new IdentifierExpression("\r\n"));
- }
-
- // Add properties
- foreach(PropertyDefinition propDef in typeDef.Properties) {
- Ast.PropertyDeclaration astProp = new Ast.PropertyDeclaration(
- ConvertModifiers(propDef.GetMethod),
- new List<AttributeSection>(),
- propDef.Name,
- new List<ParameterDeclarationExpression>()
- );
- astProp.TypeReference = new Ast.TypeReference(propDef.PropertyType.FullName);
-
- if (propDef.GetMethod != null) {
- astProp.GetRegion = new PropertyGetRegion(
- AstMetodBodyBuilder.CreateMetodBody(propDef.GetMethod),
- new List<AttributeSection>()
- );
- }
- if (propDef.SetMethod != null) {
- astProp.SetRegion = new PropertySetRegion(
- AstMetodBodyBuilder.CreateMetodBody(propDef.SetMethod),
- new List<AttributeSection>()
- );
- }
-
- astType.Children.Add(astProp);
- }
-
- if (typeDef.Properties.Count > 0) {
- astType.Children.Add(new IdentifierExpression("\r\n"));
- }
-
- // Add constructors
- foreach(MethodDefinition methodDef in typeDef.Methods) {
- if (!methodDef.IsConstructor) continue;
-
- Ast.ConstructorDeclaration astMethod = new Ast.ConstructorDeclaration(
- methodDef.Name,
- ConvertModifiers(methodDef),
- new List<ParameterDeclarationExpression>(MakeParameters(methodDef.Parameters)),
- new List<AttributeSection>()
- );
-
- astMethod.Body = AstMetodBodyBuilder.CreateMetodBody(methodDef);
-
- astType.Children.Add(astMethod);
- astType.Children.Add(new IdentifierExpression("\r\n"));
- }
-
- // Add methods
- foreach(MethodDefinition methodDef in typeDef.Methods) {
- if (methodDef.IsSpecialName) continue;
-
- Ast.MethodDeclaration astMethod = new Ast.MethodDeclaration();
- astMethod.Name = methodDef.Name;
- astMethod.TypeReference = new Ast.TypeReference(methodDef.ReturnType.FullName);
- astMethod.Modifier = ConvertModifiers(methodDef);
-
- astMethod.Parameters.AddRange(MakeParameters(methodDef.Parameters));
-
- astMethod.Body = AstMetodBodyBuilder.CreateMetodBody(methodDef);
-
- astType.Children.Add(astMethod);
-
- astType.Children.Add(new IdentifierExpression("\r\n"));
- }
-
- if (astType.Children.LastOrDefault() is IdentifierExpression) {
- astType.Children.Last.Remove();
- }
- }
-
- IEnumerable<Ast.ParameterDeclarationExpression> MakeParameters(IEnumerable<ParameterDefinition> paramCol)
- {
- foreach(ParameterDefinition paramDef in paramCol) {
- Ast.ParameterDeclarationExpression astParam = new Ast.ParameterDeclarationExpression(
- new Ast.TypeReference(paramDef.ParameterType.FullName),
- paramDef.Name
- );
-
- 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.Ref;
-
- yield return astParam;
- }
- }
- }
-}
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using Ast = ICSharpCode.NRefactory.Ast;
+using ICSharpCode.NRefactory.Ast;
+using ICSharpCode.NRefactory.PrettyPrinter;
+using Mono.Cecil;
+using Mono.Cecil.Cil;
+
+namespace Decompiler
+{
+ public class AstBuilder
+ {
+ CompilationUnit astCompileUnit = new CompilationUnit();
+ Dictionary<string, NamespaceDeclaration> astNamespaces = new Dictionary<string, NamespaceDeclaration>();
+
+ public string GenerateCode()
+ {
+ CSharpOutputVisitor csOutVisitor = new CSharpOutputVisitor();
+
+ for (int i = 0; i < 4; i++) {
+ if (Options.ReduceAstJumps) {
+ astCompileUnit.AcceptVisitor(new Transforms.Ast.RemoveGotos(), null);
+ astCompileUnit.AcceptVisitor(new Transforms.Ast.RemoveDeadLabels(), null);
+ }
+ if (Options.ReduceAstLoops) {
+ astCompileUnit.AcceptVisitor(new Transforms.Ast.RestoreLoop(), null);
+ }
+ if (Options.ReduceAstOther) {
+ astCompileUnit.AcceptVisitor(new Transforms.Ast.Idioms(), 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);
+ }
+ }
+ if (Options.ReduceAstOther) {
+ 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.Idioms(), null);
+ }
+ if (Options.ReduceAstLoops) {
+ astCompileUnit.AcceptVisitor(new Transforms.Ast.RestoreLoop(), null);
+ }
+
+ astCompileUnit.AcceptVisitor(csOutVisitor, null);
+
+ string code = csOutVisitor.Text;
+ for(int i = 10; i >= 0; i--) {
+ code = code.Replace("\r\n" + new string('\t', i) + "else {", " else {");
+ }
+ code = code.Replace("\t", " ");
+ code = code.Replace("\"/***", "");
+ code = code.Replace("***/\";", "");
+
+ // Post processing commands
+ while(true) {
+ int endIndex = code.IndexOf("[JoinLine]") + "[JoinLine]".Length;
+ if (endIndex != -1) {
+ int startIndex = code.LastIndexOf("\r\n", endIndex, endIndex);
+ if (startIndex != -1) {
+ code = code.Remove(startIndex, endIndex - startIndex);
+ continue;
+ }
+ }
+ break;
+ }
+ while(true) {
+ int endIndex = code.IndexOf("[Tab]");
+ if (endIndex != -1) {
+ int startIndex = code.LastIndexOf("\r\n", endIndex, endIndex);
+ if (startIndex != -1) {
+ code = code.Remove(endIndex, "[Tab]".Length);
+ code = code.Insert(endIndex, new string(' ', Math.Max(0, 40 - endIndex + startIndex)));
+ continue;
+ }
+ }
+ break;
+ }
+
+ return code;
+ }
+
+ public void AddAssembly(AssemblyDefinition assemblyDefinition)
+ {
+ Ast.UsingDeclaration astUsing = new Ast.UsingDeclaration("System");
+ astCompileUnit.Children.Add(astUsing);
+
+ foreach(TypeDefinition typeDef in assemblyDefinition.MainModule.Types) {
+ // Skip nested types - they will be added by the parent type
+ if (typeDef.DeclaringType != null) continue;
+ // Skip the <Module> class
+ if (typeDef.Name == "<Module>") continue;
+
+ AddType(typeDef);
+ }
+ }
+
+ NamespaceDeclaration GetCodeNamespace(string name)
+ {
+ if (string.IsNullOrEmpty(name)) {
+ return null;
+ }
+ if (astNamespaces.ContainsKey(name)) {
+ return astNamespaces[name];
+ } else {
+ // Create the namespace
+ NamespaceDeclaration astNamespace = new NamespaceDeclaration(name);
+ astCompileUnit.Children.Add(astNamespace);
+ astNamespaces[name] = astNamespace;
+ return astNamespace;
+ }
+ }
+
+ public void AddType(TypeDefinition typeDef)
+ {
+ if (!string.IsNullOrEmpty(Options.TypeFilter) && typeDef.Name != Options.TypeFilter) return;
+
+ TypeDeclaration astType = CreateType(typeDef);
+ NamespaceDeclaration astNS = GetCodeNamespace(typeDef.Namespace);
+ if (astNS != null) {
+ astNS.Children.Add(astType);
+ } else {
+ astCompileUnit.Children.Add(astType);
+ }
+ }
+
+ public TypeDeclaration CreateType(TypeDefinition typeDef)
+ {
+ TypeDeclaration astType = new TypeDeclaration(ConvertModifiers(typeDef), new List<AttributeSection>());
+ astType.Name = typeDef.Name;
+
+ if (typeDef.IsEnum) { // NB: Enum is value type
+ astType.Type = ClassType.Enum;
+ } else if (typeDef.IsValueType) {
+ astType.Type = ClassType.Struct;
+ } else if (typeDef.IsInterface) {
+ astType.Type = ClassType.Interface;
+ } else {
+ astType.Type = ClassType.Class;
+ }
+
+ // Nested types
+ foreach(TypeDefinition nestedTypeDef in typeDef.NestedTypes) {
+ astType.Children.Add(CreateType(nestedTypeDef));
+ }
+
+ // Base type
+ if (typeDef.BaseType != null && !typeDef.IsValueType && typeDef.BaseType.FullName != Constants.Object) {
+ astType.BaseTypes.Add(new Ast.TypeReference(typeDef.BaseType.FullName));
+ }
+
+ AddTypeMembers(astType, typeDef);
+
+ return astType;
+ }
+
+ Modifiers ConvertModifiers(TypeDefinition typeDef)
+ {
+ return
+ (typeDef.IsNestedPrivate ? Modifiers.Private : Modifiers.None) |
+ (typeDef.IsNestedFamilyAndAssembly ? Modifiers.Protected : Modifiers.None) | // TODO: Extended access
+ (typeDef.IsNestedAssembly ? Modifiers.Internal : Modifiers.None) |
+ (typeDef.IsNestedFamily ? Modifiers.Protected : Modifiers.None) |
+ (typeDef.IsNestedFamilyOrAssembly ? Modifiers.Protected | Modifiers.Internal : Modifiers.None) |
+ (typeDef.IsPublic ? Modifiers.Public : Modifiers.None) |
+ (typeDef.IsAbstract ? Modifiers.Abstract : Modifiers.None);
+ }
+
+ Modifiers ConvertModifiers(FieldDefinition fieldDef)
+ {
+ return
+ (fieldDef.IsPrivate ? Modifiers.Private : Modifiers.None) |
+ (fieldDef.IsFamilyAndAssembly ? Modifiers.Protected : Modifiers.None) | // TODO: Extended access
+ (fieldDef.IsAssembly ? Modifiers.Internal : Modifiers.None) |
+ (fieldDef.IsFamily ? Modifiers.Protected : Modifiers.None) |
+ (fieldDef.IsFamilyOrAssembly ? Modifiers.Protected | Modifiers.Internal : Modifiers.None) |
+ (fieldDef.IsPublic ? Modifiers.Public : Modifiers.None) |
+ (fieldDef.IsLiteral ? Modifiers.Const : Modifiers.None) |
+ (fieldDef.IsStatic ? Modifiers.Static : Modifiers.None);
+ }
+
+ Modifiers ConvertModifiers(MethodDefinition methodDef)
+ {
+ return
+ (methodDef.IsCompilerControlled ? Modifiers.None : Modifiers.None) |
+ (methodDef.IsPrivate ? Modifiers.Private : Modifiers.None) |
+ (methodDef.IsFamilyAndAssembly ? Modifiers.Protected : Modifiers.None) | // TODO: Extended access
+ (methodDef.IsAssembly ? Modifiers.Internal : Modifiers.None) |
+ (methodDef.IsFamily ? Modifiers.Protected : Modifiers.None) |
+ (methodDef.IsFamilyOrAssembly ? Modifiers.Protected | Modifiers.Internal : Modifiers.None) |
+ (methodDef.IsPublic ? Modifiers.Public : Modifiers.None) |
+ (methodDef.IsStatic ? Modifiers.Static : Modifiers.None) |
+ (methodDef.IsVirtual ? Modifiers.Virtual : Modifiers.None) |
+ (methodDef.IsAbstract ? Modifiers.Abstract : Modifiers.None);
+ }
+
+ void AddTypeMembers(TypeDeclaration astType, TypeDefinition typeDef)
+ {
+ // Add fields
+ foreach(FieldDefinition fieldDef in typeDef.Fields) {
+ Ast.FieldDeclaration astField = new Ast.FieldDeclaration(new List<AttributeSection>());
+ astField.Fields.Add(new Ast.VariableDeclaration(fieldDef.Name));
+ astField.TypeReference = new Ast.TypeReference(fieldDef.FieldType.FullName);
+ astField.Modifier = ConvertModifiers(fieldDef);
+
+ astType.Children.Add(astField);
+ }
+
+ if (typeDef.Fields.Count > 0) {
+ astType.Children.Add(new IdentifierExpression("\r\n"));
+ }
+
+ // Add events
+ foreach(EventDefinition eventDef in typeDef.Events) {
+ Ast.EventDeclaration astEvent = new Ast.EventDeclaration();
+ astEvent.Name = eventDef.Name;
+ astEvent.TypeReference = new Ast.TypeReference(eventDef.EventType.FullName);
+ astEvent.Modifier = ConvertModifiers(eventDef.AddMethod);
+
+ astType.Children.Add(astEvent);
+ }
+
+ if (typeDef.Events.Count > 0) {
+ astType.Children.Add(new IdentifierExpression("\r\n"));
+ }
+
+ // Add properties
+ foreach(PropertyDefinition propDef in typeDef.Properties) {
+ Ast.PropertyDeclaration astProp = new Ast.PropertyDeclaration(
+ ConvertModifiers(propDef.GetMethod),
+ new List<AttributeSection>(),
+ propDef.Name,
+ new List<ParameterDeclarationExpression>()
+ );
+ astProp.TypeReference = new Ast.TypeReference(propDef.PropertyType.FullName);
+
+ if (propDef.GetMethod != null) {
+ astProp.GetRegion = new PropertyGetRegion(
+ AstMetodBodyBuilder.CreateMetodBody(propDef.GetMethod),
+ new List<AttributeSection>()
+ );
+ }
+ if (propDef.SetMethod != null) {
+ astProp.SetRegion = new PropertySetRegion(
+ AstMetodBodyBuilder.CreateMetodBody(propDef.SetMethod),
+ new List<AttributeSection>()
+ );
+ }
+
+ astType.Children.Add(astProp);
+ }
+
+ if (typeDef.Properties.Count > 0) {
+ astType.Children.Add(new IdentifierExpression("\r\n"));
+ }
+
+ // Add constructors
+ foreach(MethodDefinition methodDef in typeDef.Methods) {
+ if (!methodDef.IsConstructor) continue;
+
+ Ast.ConstructorDeclaration astMethod = new Ast.ConstructorDeclaration(
+ methodDef.Name,
+ ConvertModifiers(methodDef),
+ new List<ParameterDeclarationExpression>(MakeParameters(methodDef.Parameters)),
+ new List<AttributeSection>()
+ );
+
+ astMethod.Body = AstMetodBodyBuilder.CreateMetodBody(methodDef);
+
+ astType.Children.Add(astMethod);
+ astType.Children.Add(new IdentifierExpression("\r\n"));
+ }
+
+ // Add methods
+ foreach(MethodDefinition methodDef in typeDef.Methods) {
+ if (methodDef.IsSpecialName) continue;
+
+ Ast.MethodDeclaration astMethod = new Ast.MethodDeclaration();
+ astMethod.Name = methodDef.Name;
+ astMethod.TypeReference = new Ast.TypeReference(methodDef.ReturnType.FullName);
+ astMethod.Modifier = ConvertModifiers(methodDef);
+
+ astMethod.Parameters.AddRange(MakeParameters(methodDef.Parameters));
+
+ astMethod.Body = AstMetodBodyBuilder.CreateMetodBody(methodDef);
+
+ astType.Children.Add(astMethod);
+
+ astType.Children.Add(new IdentifierExpression("\r\n"));
+ }
+
+ if (astType.Children.LastOrDefault() is IdentifierExpression) {
+ astType.Children.Last.Remove();
+ }
+ }
+
+ IEnumerable<Ast.ParameterDeclarationExpression> MakeParameters(IEnumerable<ParameterDefinition> paramCol)
+ {
+ foreach(ParameterDefinition paramDef in paramCol) {
+ Ast.ParameterDeclarationExpression astParam = new Ast.ParameterDeclarationExpression(
+ new Ast.TypeReference(paramDef.ParameterType.FullName),
+ paramDef.Name
+ );
+
+ 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.Ref;
+
+ yield return astParam;
+ }
+ }
+ }
+}
View
1,496 Decompiler/src/Ast/AstMetodBodyBuilder.cs → ...ode.Decompiler/Ast/AstMetodBodyBuilder.cs
@@ -1,748 +1,748 @@
-using System;
-using System.Collections.Generic;
-
-using Ast = ICSharpCode.NRefactory.Ast;
-using ICSharpCode.NRefactory.Ast;
-using Cecil = Mono.Cecil;
-using Mono.Cecil;
-using Mono.Cecil.Cil;
-using Mono.Cecil.Rocks;
-using Decompiler.ControlFlow;
-
-namespace Decompiler
-{
- public class AstMetodBodyBuilder
- {
- MethodDefinition methodDef;
- static Dictionary<string, Cecil.TypeReference> localVarTypes = new Dictionary<string, Cecil.TypeReference>();
- static Dictionary<string, bool> localVarDefined = new Dictionary<string, bool>();
-
- public static BlockStatement CreateMetodBody(MethodDefinition methodDef)
- {
- AstMetodBodyBuilder builder = new AstMetodBodyBuilder();
- builder.methodDef = methodDef;
- try {
- return builder.CreateMetodBody();
- } catch {
- BlockStatement block = new BlockStatement();
- block.Children.Add(MakeComment("Exception during decompilation"));
- return block;
- }
- }
-
- public BlockStatement CreateMetodBody()
- {
- Ast.BlockStatement astBlock = new Ast.BlockStatement();
-
- if (methodDef.Body == null) return astBlock;
-
- methodDef.Body.SimplifyMacros();
-
- List<ILNode> body = new ILAstBuilder().Build(methodDef);
-
- MethodBodyGraph bodyGraph = new MethodBodyGraph(body);
- bodyGraph.Optimize();
-
- List<string> intNames = new List<string>(new string[] {"i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t"});
- Dictionary<string, int> typeNames = new Dictionary<string, int>();
- int boolFlagId = 1;
- foreach(VariableDefinition varDef in methodDef.Body.Variables) {
- if (string.IsNullOrEmpty(varDef.Name)) {
- if (varDef.VariableType.FullName == Constants.Int32 && intNames.Count > 0) {
- varDef.Name = intNames[0];
- intNames.RemoveAt(0);
- } else if (varDef.VariableType.FullName == Constants.Boolean) {
- if (boolFlagId == 1) {
- varDef.Name = "flag";
- } else {
- varDef.Name = "flag" + boolFlagId;
- }
- boolFlagId++;
- } else {
- string name;
- if (varDef.VariableType.IsArray) {
- name = "array";
- } else {
- name = varDef.VariableType.Name;
- name = char.ToLower(name[0]) + name.Substring(1);
- }
- if (!typeNames.ContainsKey(name)) {
- typeNames.Add(name, 0);
- }
- int count = typeNames[name];
- if (count > 0) {
- name += count.ToString();
- }
- varDef.Name = name;
- }
- }
- localVarTypes[varDef.Name] = varDef.VariableType;
- localVarDefined[varDef.Name] = false;
-
-// Ast.VariableDeclaration astVar = new Ast.VariableDeclaration(varDef.Name);
-// Ast.LocalVariableDeclaration astLocalVar = new Ast.LocalVariableDeclaration(astVar);
-// astLocalVar.TypeReference = new Ast.TypeReference(varDef.VariableType.FullName);
-// astBlock.Children.Add(astLocalVar);
- }
-
- astBlock.Children.AddRange(TransformNodes(bodyGraph.Childs));
-
- return astBlock;
- }
-
- IEnumerable<Ast.INode> TransformNodes(IEnumerable<Node> nodes)
- {
- foreach(Node node in nodes) {
- foreach(Ast.Statement stmt in TransformNode(node)) {
- yield return stmt;
- }
- }
- }
-
- IEnumerable<Ast.INode> TransformNode(Node node)
- {
- if (Options.NodeComments) {
- yield return MakeComment("// " + node.Description);
- }
-
- yield return new Ast.LabelStatement(node.Label);
-
- if (node is BasicBlock) {
- foreach(ILNode expr in ((BasicBlock)node).Body) {
- if (expr is ILLabel) {
- yield return new Ast.LabelStatement(((ILLabel)expr).Name);
- } else {
- Statement stmt = TransformExpressionToStatement((ILExpression)expr);
- if (stmt != null) {
- yield return stmt;
- }
- }
- }
- Node fallThroughNode = ((BasicBlock)node).FallThroughBasicBlock;
- // If there is default branch and it is not the following node
- if (fallThroughNode != null) {
- yield return new Ast.GotoStatement(fallThroughNode.Label);
- }
- } else if (node is AcyclicGraph) {
- Ast.BlockStatement blockStatement = new Ast.BlockStatement();
- blockStatement.Children.AddRange(TransformNodes(node.Childs));
- yield return blockStatement;
- } else if (node is Loop) {
- Ast.BlockStatement blockStatement = new Ast.BlockStatement();
- blockStatement.Children.AddRange(TransformNodes(node.Childs));
- yield return new Ast.ForStatement(
- null,
- null,
- null,
- blockStatement
- );
- } else if (node is Block) {
- foreach(Ast.INode inode in TransformNodes(node.Childs)) {
- yield return inode;
- }
- } else if (node is Branch) {
- yield return new Ast.LabelStatement(((Branch)node).FirstBasicBlock.Label);
-
- Ast.BlockStatement trueBlock = new Ast.BlockStatement();
- trueBlock.Children.Add(new Ast.GotoStatement(((Branch)node).TrueSuccessor.Label));
-
- Ast.BlockStatement falseBlock = new Ast.BlockStatement();
- falseBlock.Children.Add(new Ast.GotoStatement(((Branch)node).FalseSuccessor.Label));
-
- Ast.IfElseStatement ifElseStmt = new Ast.IfElseStatement(
- MakeBranchCondition((Branch)node),
- trueBlock,
- falseBlock
- );
- trueBlock.Parent = ifElseStmt;
- falseBlock.Parent = ifElseStmt;
-
- yield return ifElseStmt;
- } else if (node is ConditionalNode) {
- ConditionalNode conditionalNode = (ConditionalNode)node;
- yield return new Ast.LabelStatement(conditionalNode.Condition.FirstBasicBlock.Label);
-
- Ast.BlockStatement trueBlock = new Ast.BlockStatement();
- // The block entry code
- trueBlock.Children.Add(new Ast.GotoStatement(conditionalNode.Condition.TrueSuccessor.Label));
- // Sugested content
- trueBlock.Children.AddRange(TransformNode(conditionalNode.TrueBody));
-
- Ast.BlockStatement falseBlock = new Ast.BlockStatement();
- // The block entry code
- falseBlock.Children.Add(new Ast.GotoStatement(conditionalNode.Condition.FalseSuccessor.Label));
- // Sugested content
- falseBlock.Children.AddRange(TransformNode(conditionalNode.FalseBody));
-
- Ast.IfElseStatement ifElseStmt = new Ast.IfElseStatement(
- // Method bodies are swapped
- new Ast.UnaryOperatorExpression(
- new Ast.ParenthesizedExpression(
- MakeBranchCondition(conditionalNode.Condition)
- ),
- UnaryOperatorType.Not
- ),
- falseBlock,
- trueBlock
- );
- trueBlock.Parent = ifElseStmt;
- falseBlock.Parent = ifElseStmt;
-
- yield return ifElseStmt;
- } else if (node is TryCatchNode) {
- TryCatchNode tryCachNode = ((TryCatchNode)node);
- Ast.BlockStatement tryBlock = new Ast.BlockStatement();
- tryBlock.Children.AddRange(TransformNode(tryCachNode.Childs[0]));
- Ast.BlockStatement finallyBlock = null;
- if (tryCachNode.Childs[1].Childs.Count > 0) {
- finallyBlock = new Ast.BlockStatement();
- finallyBlock.Children.AddRange(TransformNode(tryCachNode.Childs[1]));
- }
- List<Ast.CatchClause> ccs = new List<CatchClause>();
- for (int i = 0; i < tryCachNode.Types.Count; i++) {
- Ast.BlockStatement catchBlock = new Ast.BlockStatement();
- catchBlock.Children.AddRange(TransformNode(tryCachNode.Childs[i + 2]));
- Ast.CatchClause cc = new Ast.CatchClause(
- new Ast.TypeReference(tryCachNode.Types[i].FullName),
- "exception",
- catchBlock
- );
- ccs.Add(cc);
- }
- Ast.TryCatchStatement tryCachStmt = new Ast.TryCatchStatement(tryBlock, ccs, finallyBlock);
- yield return tryCachStmt;
- } else {
- throw new Exception("Bad node type");
- }
-
- if (Options.NodeComments) {
- yield return MakeComment("");
- }
- }
-
- List<Ast.Expression> TransformExpressionArguments(ILExpression expr)
- {
- List<Ast.Expression> args = new List<Ast.Expression>();
- // Args generated by nested expressions (which must be closed)
- foreach(ILExpression arg in expr.Arguments) {
- args.Add((Ast.Expression)TransformExpression(arg));
- }
- return args;
- }
-
- object TransformExpression(ILExpression expr)
- {
- List<Ast.Expression> args = TransformExpressionArguments(expr);
- return TransformByteCode(methodDef, expr, args);
- }
-
- Ast.Statement TransformExpressionToStatement(ILExpression expr)
- {
- object codeExpr = TransformExpression(expr);
- if (codeExpr == null) {
- return null;
- } else if (codeExpr is Ast.Expression) {
- return new Ast.ExpressionStatement((Ast.Expression)codeExpr);
- } else if (codeExpr is Ast.Statement) {
- return (Ast.Statement)codeExpr;
- } else {
- throw new Exception();
- }
- }
-
- static Ast.ExpressionStatement MakeComment(string text)
- {
- text = "/***" + text + "***/";
- return new Ast.ExpressionStatement(new PrimitiveExpression(text, text));
- }
-
- Ast.Expression MakeBranchCondition(Branch branch)
- {
- return new ParenthesizedExpression(MakeBranchCondition_Internal(branch));
- }
-
- Ast.Expression MakeBranchCondition_Internal(Branch branch)
- {
- if (branch is SimpleBranch) {
- List<Ast.Expression> args = TransformExpressionArguments((ILExpression)((SimpleBranch)branch).BasicBlock.Body[0]);
- Ast.Expression arg1 = args.Count >= 1 ? args[0] : null;
- Ast.Expression arg2 = args.Count >= 2 ? args[1] : null;
- switch(((ILExpression)((SimpleBranch)branch).BasicBlock.Body[0]).OpCode.Code) {
- case Code.Brfalse: return new Ast.UnaryOperatorExpression(arg1, UnaryOperatorType.Not);
- case Code.Brtrue: return arg1;
- case Code.Beq: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Equality, arg2);
- case Code.Bge: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.GreaterThanOrEqual, arg2);
- case Code.Bge_Un: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.GreaterThanOrEqual, arg2);
- case Code.Bgt: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.GreaterThan, arg2);
- case Code.Bgt_Un: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.GreaterThan, arg2);
- case Code.Ble: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.LessThanOrEqual, arg2);
- case Code.Ble_Un: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.LessThanOrEqual, arg2);
- case Code.Blt: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.LessThan, arg2);
- case Code.Blt_Un: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.LessThan, arg2);
- case Code.Bne_Un: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.InEquality, arg2);
- case Code.Leave: return new Ast.PrimitiveExpression(true, true.ToString());
- default: throw new Exception("Bad opcode");
- }
- } else if (branch is ShortCircuitBranch) {
- ShortCircuitBranch scBranch = (ShortCircuitBranch)branch;
- switch(scBranch.Operator) {
- case ShortCircuitOperator.LeftAndRight:
- return new BinaryOperatorExpression(
- MakeBranchCondition(scBranch.Left),
- BinaryOperatorType.LogicalAnd,
- MakeBranchCondition(scBranch.Right)
- );
- case ShortCircuitOperator.LeftOrRight:
- return new BinaryOperatorExpression(
- MakeBranchCondition(scBranch.Left),
- BinaryOperatorType.LogicalOr,
- MakeBranchCondition(scBranch.Right)
- );
- case ShortCircuitOperator.NotLeftAndRight:
- return new BinaryOperatorExpression(
- new UnaryOperatorExpression(MakeBranchCondition(scBranch.Left), UnaryOperatorType.Not),
- BinaryOperatorType.LogicalAnd,
- MakeBranchCondition(scBranch.Right)
- );
- case ShortCircuitOperator.NotLeftOrRight:
- return new BinaryOperatorExpression(
- new UnaryOperatorExpression(MakeBranchCondition(scBranch.Left), UnaryOperatorType.Not),
- BinaryOperatorType.LogicalOr,
- MakeBranchCondition(scBranch.Right)
- );
- default:
- throw new Exception("Bad operator");
- }
- } else {
- throw new Exception("Bad type");
- }
- }
-
- static object TransformByteCode(MethodDefinition methodDef, ILExpression byteCode, List<Ast.Expression> args)
- {
- try {
- Ast.INode ret = TransformByteCode_Internal(methodDef, byteCode, args);
- if (ret is Ast.Expression) {
- ret = new ParenthesizedExpression((Ast.Expression)ret);
- }
- // ret.UserData["Type"] = byteCode.Type;
- return ret;
- } catch (NotImplementedException) {
- // Output the operand of the unknown IL code as well
- if (byteCode.Operand != null) {
- args.Insert(0, new IdentifierExpression(FormatByteCodeOperand(byteCode.Operand)));
- }
- return new Ast.InvocationExpression(new IdentifierExpression("__" + byteCode.OpCode.Name), args);
- }
- }
-
- static string FormatByteCodeOperand(object operand)
- {
- if (operand == null) {
- return string.Empty;
- //} else if (operand is ILExpression) {
- // return string.Format("IL_{0:X2}", ((ILExpression)operand).Offset);
- } else if (operand is MethodReference) {
- return ((MethodReference)operand).Name + "()";
- } else if (operand is Cecil.TypeReference) {
- return ((Cecil.TypeReference)operand).FullName;
- } else if (operand is VariableDefinition) {
- return ((VariableDefinition)operand).Name;
- } else if (operand is ParameterDefinition) {
- return ((ParameterDefinition)operand).Name;
- } else if (operand is FieldReference) {
- return ((FieldReference)operand).Name;
- } else if (operand is string) {
- return "\"" + operand + "\"";
- } else if (operand is int) {
- return operand.ToString();
- } else {
- return operand.ToString();
- }
- }
-
- static Ast.INode TransformByteCode_Internal(MethodDefinition methodDef, ILExpression byteCode, List<Ast.Expression> args)
- {
- // throw new NotImplementedException();
-
- OpCode opCode = byteCode.OpCode;
- object operand = byteCode.Operand;
- Ast.TypeReference operandAsTypeRef = operand is Cecil.TypeReference ? new Ast.TypeReference(((Cecil.TypeReference)operand).FullName) : null;
- ILExpression operandAsByteCode = operand as ILExpression;
- Ast.Expression arg1 = args.Count >= 1 ? args[0] : null;
- Ast.Expression arg2 = args.Count >= 2 ? args[1] : null;
- Ast.Expression arg3 = args.Count >= 3 ? args[2] : null;
-
- Ast.Statement branchCommand = null;
- if (byteCode.Operand is ILExpression) {
- branchCommand = new Ast.GotoStatement(((ILLabel)byteCode.Operand).Name);
- }
-
- switch(opCode.Code) {
- #region Arithmetic
- case Code.Add: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Add, arg2);
- case Code.Add_Ovf: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Add, arg2);
- case Code.Add_Ovf_Un: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Add, arg2);
- case Code.Div: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Divide, arg2);
- case Code.Div_Un: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Divide, arg2);
- case Code.Mul: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Multiply, arg2);
- case Code.Mul_Ovf: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Multiply, arg2);
- case Code.Mul_Ovf_Un: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Multiply, arg2);
- case Code.Rem: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Modulus, arg2);
- case Code.Rem_Un: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Modulus, arg2);
- case Code.Sub: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Subtract, arg2);
- case Code.Sub_Ovf: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Subtract, arg2);
- case Code.Sub_Ovf_Un: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Subtract, arg2);
- case Code.And: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.BitwiseAnd, arg2);
- case Code.Xor: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.ExclusiveOr, arg2);
- case Code.Shl: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.ShiftLeft, arg2);
- case Code.Shr: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.ShiftRight, arg2);
- case Code.Shr_Un: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.ShiftRight, arg2);
-
- case Code.Neg: return new Ast.UnaryOperatorExpression(arg1, UnaryOperatorType.Minus);
- case Code.Not: return new Ast.UnaryOperatorExpression(arg1, UnaryOperatorType.BitNot);
- #endregion
- #region Arrays
- case Code.Newarr:
- operandAsTypeRef.RankSpecifier = new int[] {0};
- return new Ast.ArrayCreateExpression(operandAsTypeRef, new List<Expression>(new Expression[] {arg1}));
-
- case Code.Ldlen: return new Ast.MemberReferenceExpression(arg1, "Length");
-
- case Code.Ldelem_I:
- case Code.Ldelem_I1:
- case Code.Ldelem_I2:
- case Code.Ldelem_I4:
- case Code.Ldelem_I8:
- case Code.Ldelem_U1:
- case Code.Ldelem_U2:
- case Code.Ldelem_U4:
- case Code.Ldelem_R4:
- case Code.Ldelem_R8:
- case Code.Ldelem_Ref: return new Ast.IndexerExpression(arg1, new List<Expression>(new Expression[] {arg2}));
- case Code.Ldelem_Any: throw new NotImplementedException();
- case Code.Ldelema: return new Ast.IndexerExpression(arg1, new List<Expression>(new Expression[] {arg2}));
-
- case Code.Stelem_I:
- case Code.Stelem_I1:
- case Code.Stelem_I2:
- case Code.Stelem_I4:
- case Code.Stelem_I8:
- case Code.Stelem_R4:
- case Code.Stelem_R8:
- case Code.Stelem_Ref: return new Ast.AssignmentExpression(new Ast.IndexerExpression(arg1, new List<Expression>(new Expression[] {arg2})), AssignmentOperatorType.Assign, arg3);
- case Code.Stelem_Any: throw new NotImplementedException();
- #endregion
- #region Branching
- case Code.Br: return branchCommand;
- case Code.Brfalse: return new Ast.IfElseStatement(new Ast.UnaryOperatorExpression(arg1, UnaryOperatorType.Not), branchCommand);
- case Code.Brtrue: return new Ast.IfElseStatement(arg1, branchCommand);
- case Code.Beq: return new Ast.IfElseStatement(new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Equality, arg2), branchCommand);
- case Code.Bge: return new Ast.IfElseStatement(new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.GreaterThanOrEqual, arg2), branchCommand);
- case Code.Bge_Un: return new Ast.IfElseStatement(new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.GreaterThanOrEqual, arg2), branchCommand);
- case Code.Bgt: return new Ast.IfElseStatement(new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.GreaterThan, arg2), branchCommand);
- case Code.Bgt_Un: return new Ast.IfElseStatement(new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.GreaterThan, arg2), branchCommand);
- case Code.Ble: return new Ast.IfElseStatement(new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.LessThanOrEqual, arg2), branchCommand);
- case Code.Ble_Un: return new Ast.IfElseStatement(new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.LessThanOrEqual, arg2), branchCommand);
- case Code.Blt: return new Ast.IfElseStatement(new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.LessThan, arg2), branchCommand);
- case Code.Blt_Un: return new Ast.IfElseStatement(new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.LessThan, arg2), branchCommand);
- case Code.Bne_Un: return new Ast.IfElseStatement(new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.InEquality, arg2), branchCommand);
- #endregion
- #region Comparison
- case Code.Ceq: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Equality, ConvertIntToBool(arg2));
- case Code.Cgt: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.GreaterThan, arg2);
- case Code.Cgt_Un: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.GreaterThan, arg2);
- case Code.Clt: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.LessThan, arg2);
- case Code.Clt_Un: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.LessThan, arg2);
- #endregion
- #region Conversions
- case Code.Conv_I: return new Ast.CastExpression(new Ast.TypeReference(typeof(int).FullName), arg1, CastType.Cast); // TODO
- case Code.Conv_I1: return new Ast.CastExpression(new Ast.TypeReference(typeof(SByte).FullName), arg1, CastType.Cast);
- case Code.Conv_I2: return new Ast.CastExpression(new Ast.TypeReference(typeof(Int16).FullName), arg1, CastType.Cast);
- case Code.Conv_I4: return new Ast.CastExpression(new Ast.TypeReference(typeof(Int32).FullName), arg1, CastType.Cast);
- case Code.Conv_I8: return new Ast.CastExpression(new Ast.TypeReference(typeof(Int64).FullName), arg1, CastType.Cast);
- case Code.Conv_U: return new Ast.CastExpression(new Ast.TypeReference(typeof(uint).FullName), arg1, CastType.Cast); // TODO
- case Code.Conv_U1: return new Ast.CastExpression(new Ast.TypeReference(typeof(Byte).FullName), arg1, CastType.Cast);
- case Code.Conv_U2: return new Ast.CastExpression(new Ast.TypeReference(typeof(UInt16).FullName), arg1, CastType.Cast);
- case Code.Conv_U4: return new Ast.CastExpression(new Ast.TypeReference(typeof(UInt32).FullName), arg1, CastType.Cast);
- case Code.Conv_U8: return new Ast.CastExpression(new Ast.TypeReference(typeof(UInt64).FullName), arg1, CastType.Cast);
- case Code.Conv_R4: return new Ast.CastExpression(new Ast.TypeReference(typeof(float).FullName), arg1, CastType.Cast);
- case Code.Conv_R8: return new Ast.CastExpression(new Ast.TypeReference(typeof(double).FullName), arg1, CastType.Cast);
- case Code.Conv_R_Un: return new Ast.CastExpression(new Ast.TypeReference(typeof(double).FullName), arg1, CastType.Cast); // TODO
-
- case Code.Conv_Ovf_I: return new Ast.CastExpression(new Ast.TypeReference(typeof(int).FullName), arg1, CastType.Cast); // TODO
- case Code.Conv_Ovf_I1: return new Ast.CastExpression(new Ast.TypeReference(typeof(SByte).FullName), arg1, CastType.Cast);
- case Code.Conv_Ovf_I2: return new Ast.CastExpression(new Ast.TypeReference(typeof(Int16).FullName), arg1, CastType.Cast);
- case Code.Conv_Ovf_I4: return new Ast.CastExpression(new Ast.TypeReference(typeof(Int32).FullName), arg1, CastType.Cast);
- case Code.Conv_Ovf_I8: return new Ast.CastExpression(new Ast.TypeReference(typeof(Int64).FullName), arg1, CastType.Cast);
- case Code.Conv_Ovf_U: return new Ast.CastExpression(new Ast.TypeReference(typeof(uint).FullName), arg1, CastType.Cast); // TODO
- case Code.Conv_Ovf_U1: return new Ast.CastExpression(new Ast.TypeReference(typeof(Byte).FullName), arg1, CastType.Cast);
- case Code.Conv_Ovf_U2: return new Ast.CastExpression(new Ast.TypeReference(typeof(UInt16).FullName), arg1, CastType.Cast);
- case Code.Conv_Ovf_U4: return new Ast.CastExpression(new Ast.TypeReference(typeof(UInt32).FullName), arg1, CastType.Cast);
- case Code.Conv_Ovf_U8: return new Ast.CastExpression(new Ast.TypeReference(typeof(UInt64).FullName), arg1, CastType.Cast);
-
- case Code.Conv_Ovf_I_Un: return new Ast.CastExpression(new Ast.TypeReference(typeof(int).FullName), arg1, CastType.Cast); // TODO
- case Code.Conv_Ovf_I1_Un: return new Ast.CastExpression(new Ast.TypeReference(typeof(SByte).FullName), arg1, CastType.Cast);
- case Code.Conv_Ovf_I2_Un: return new Ast.CastExpression(new Ast.TypeReference(typeof(Int16).FullName), arg1, CastType.Cast);
- case Code.Conv_Ovf_I4_Un: return new Ast.CastExpression(new Ast.TypeReference(typeof(Int32).FullName), arg1, CastType.Cast);
- case Code.Conv_Ovf_I8_Un: return new Ast.CastExpression(new Ast.TypeReference(typeof(Int64).FullName), arg1, CastType.Cast);
- case Code.Conv_Ovf_U_Un: return new Ast.CastExpression(new Ast.TypeReference(typeof(uint).FullName), arg1, CastType.Cast); // TODO
- case Code.Conv_Ovf_U1_Un: return new Ast.CastExpression(new Ast.TypeReference(typeof(Byte).FullName), arg1, CastType.Cast);
- case Code.Conv_Ovf_U2_Un: return new Ast.CastExpression(new Ast.TypeReference(typeof(UInt16).FullName), arg1, CastType.Cast);
- case Code.Conv_Ovf_U4_Un: return new Ast.CastExpression(new Ast.TypeReference(typeof(UInt32).FullName), arg1, CastType.Cast);
- case Code.Conv_Ovf_U8_Un: return new Ast.CastExpression(new Ast.TypeReference(typeof(UInt64).FullName), arg1, CastType.Cast);
- #endregion
- #region Indirect
- case Code.Ldind_I: throw new NotImplementedException();
- case Code.Ldind_I1: throw new NotImplementedException();
- case Code.Ldind_I2: throw new NotImplementedException();
- case Code.Ldind_I4: throw new NotImplementedException();
- case Code.Ldind_I8: throw new NotImplementedException();
- case Code.Ldind_U1: throw new NotImplementedException();
- case Code.Ldind_U2: throw new NotImplementedException();
- case Code.Ldind_U4: throw new NotImplementedException();
- case Code.Ldind_R4: throw new NotImplementedException();
- case Code.Ldind_R8: throw new NotImplementedException();
- case Code.Ldind_Ref: throw new NotImplementedException();
-
- case Code.Stind_I: throw new NotImplementedException();
- case Code.Stind_I1: throw new NotImplementedException();
- case Code.Stind_I2: throw new NotImplementedException();
- case Code.Stind_I4: throw new NotImplementedException();
- case Code.Stind_I8: throw new NotImplementedException();
- case Code.Stind_R4: throw new NotImplementedException();
- case Code.Stind_R8: throw new NotImplementedException();
- case Code.Stind_Ref: throw new NotImplementedException();
- #endregion
- case Code.Arglist: throw new NotImplementedException();
- case Code.Box: throw new NotImplementedException();
- case Code.Break: throw new NotImplementedException();
- case Code.Call:
- case Code.Callvirt:
- // TODO: Diferentiate vitual and non-vitual dispach
- Cecil.MethodReference cecilMethod = ((MethodReference)operand);
- Ast.Expression target;
- List<Ast.Expression> methodArgs = new List<Ast.Expression>(args);
- if (cecilMethod.HasThis) {
- target = methodArgs[0];
- methodArgs.RemoveAt(0);
- } else {
- target = new Ast.IdentifierExpression(cecilMethod.DeclaringType.FullName);
- }
-
- // TODO: Constructors are ignored
- if (cecilMethod.Name == ".ctor") {
- return MakeComment("// Constructor");
- }
-
- // TODO: Hack, detect properties properly
- if (cecilMethod.Name.StartsWith("get_")) {
- return new Ast.MemberReferenceExpression(target, cecilMethod.Name.Remove(0, 4));
- } else if (cecilMethod.Name.StartsWith("set_")) {
- return new Ast.AssignmentExpression(
- new Ast.MemberReferenceExpression(target, cecilMethod.Name.Remove(0, 4)),
- AssignmentOperatorType.Assign,
- methodArgs[0]
- );
- }
-
- // Multi-dimensional array acces // TODO: do properly
- if (cecilMethod.Name == "Get") {
- return new Ast.IndexerExpression(target, methodArgs);
- } else if (cecilMethod.Name == "Set") {
- Expression val = methodArgs[methodArgs.Count - 1];
- methodArgs.RemoveAt(methodArgs.Count - 1);
- return new Ast.AssignmentExpression(
- new Ast.IndexerExpression(target, methodArgs),
- AssignmentOperatorType.Assign,
- Convert(val, ((Cecil.ArrayType)target.UserData["Type"]).ElementType)
- );
- }
-
- // Default invocation
- return new Ast.InvocationExpression(
- new Ast.MemberReferenceExpression(target, cecilMethod.Name),
- methodArgs
- );
- case Code.Calli: throw new NotImplementedException();
- case Code.Castclass: return new Ast.CastExpression(operandAsTypeRef, arg1, CastType.Cast);
- case Code.Ckfinite: throw new NotImplementedException();
- case Code.Constrained: throw new NotImplementedException();
- case Code.Cpblk: throw new NotImplementedException();
- case Code.Cpobj: throw new NotImplementedException();
- case Code.Dup: return arg1;
- case Code.Endfilter: throw new NotImplementedException();
- case Code.Endfinally: return null;
- case Code.Initblk: throw new NotImplementedException();
- case Code.Initobj: throw new NotImplementedException();
- case Code.Isinst: return new Ast.TypeOfIsExpression(arg1, new Ast.TypeReference(((Cecil.TypeReference)operand).FullName));
- case Code.Jmp: throw new NotImplementedException();
- case Code.Ldarg:
- if (methodDef.HasThis && ((ParameterDefinition)operand).Index == 0) {
- return new Ast.ThisReferenceExpression();
- } else {
- return new Ast.IdentifierExpression(((ParameterDefinition)operand).Name);
- }
- case Code.Ldarga: throw new NotImplementedException();
- case Code.Ldc_I4:
- case Code.Ldc_I8:
- case Code.Ldc_R4:
- case Code.Ldc_R8: return new Ast.PrimitiveExpression(operand, null);
- case Code.Ldfld:
- case Code.Ldsfld: {
- if (operand is FieldDefinition) {
- FieldDefinition field = (FieldDefinition) operand;
- if (field.IsStatic) {
- return new Ast.MemberReferenceExpression(
- new Ast.IdentifierExpression(field.DeclaringType.FullName),
- field.Name
- );
- } else {
- return new Ast.MemberReferenceExpression(arg1, field.Name);
- }
- } else {
- // TODO: Static accesses
- return new Ast.MemberReferenceExpression(arg1, ((FieldReference)operand).Name);
- }
- }
- case Code.Stfld:
- case Code.Stsfld: {
- FieldDefinition field = (FieldDefinition) operand;
- if (field.IsStatic) {
- return new AssignmentExpression(
- new Ast.MemberReferenceExpression(
- new Ast.IdentifierExpression(field.DeclaringType.FullName),
- field.Name
- ),
- AssignmentOperatorType.Assign,
- arg1
- );
- } else {
- return new AssignmentExpression(
- new Ast.MemberReferenceExpression(arg1, field.Name),
- AssignmentOperatorType.Assign,
- arg2
- );
- }
- }
- case Code.Ldflda:
- case Code.Ldsflda: throw new NotImplementedException();
- case Code.Ldftn: throw new NotImplementedException();
- case Code.Ldloc:
- if (operand is ILStackVariable) {
- return new Ast.IdentifierExpression(((ILStackVariable)operand).Name);
- } else {
- return new Ast.IdentifierExpression(((VariableDefinition)operand).Name);
- }
- case Code.Ldloca: throw new NotImplementedException();
- case Code.Ldnull: return new Ast.PrimitiveExpression(null, null);
- case Code.Ldobj: throw new NotImplementedException();
- case Code.Ldstr: return new Ast.PrimitiveExpression(operand, null);
- case Code.Ldtoken:
- if (operand is Cecil.TypeReference) {
- return new Ast.MemberReferenceExpression(
- new Ast.TypeOfExpression(operandAsTypeRef),
- "TypeHandle"
- );
- } else {
- throw new NotImplementedException();
- }
- case Code.Ldvirtftn: throw new NotImplementedException();
- case Code.Leave: return null;
- case Code.Localloc: throw new NotImplementedException();
- case Code.Mkrefany: throw new NotImplementedException();
- case Code.Newobj:
- Cecil.TypeReference declaringType = ((MethodReference)operand).DeclaringType;
- // TODO: Ensure that the corrent overloaded constructor is called
- if (declaringType is ArrayType) {
- return new Ast.ArrayCreateExpression(
- new Ast.TypeReference(((ArrayType)declaringType).ElementType.FullName, new int[] {}),
- new List<Expression>(args)
- );
- }
- return new Ast.ObjectCreateExpression(
- new Ast.TypeReference(declaringType.FullName),
- new List<Expression>(args)
- );
- case Code.No: throw new NotImplementedException();
- case Code.Nop: return null;
- case Code.Or: throw new NotImplementedException();
- case Code.Pop: return arg1;
- case Code.Readonly: throw new NotImplementedException();
- case Code.Refanytype: throw new NotImplementedException();
- case Code.Refanyval: throw new NotImplementedException();
- case Code.Ret: {
- if (methodDef.ReturnType.FullName != Constants.Void) {
- arg1 = Convert(arg1, methodDef.ReturnType);
- return new Ast.ReturnStatement(arg1);
- } else {
- return new Ast.ReturnStatement(null);
- }
- }
- case Code.Rethrow: return new Ast.ThrowStatement(new IdentifierExpression("exception"));
- case Code.Sizeof: throw new NotImplementedException();
- case Code.Starg: throw new NotImplementedException();
- case Code.Stloc: {
- if (operand is ILStackVariable) {
- return new Ast.AssignmentExpression(new Ast.IdentifierExpression(((ILStackVariable)operand).Name), AssignmentOperatorType.Assign, arg1);
- }
- VariableDefinition locVar = (VariableDefinition)operand;
- string name = locVar.Name;
- arg1 = Convert(arg1, locVar.VariableType);
- if (localVarDefined.ContainsKey(name)) {
- if (localVarDefined[name]) {
- return new Ast.AssignmentExpression(new Ast.IdentifierExpression(name), AssignmentOperatorType.Assign, arg1);
- } else {
- Ast.LocalVariableDeclaration astLocalVar = new Ast.LocalVariableDeclaration(new Ast.VariableDeclaration(name, arg1));
- astLocalVar.TypeReference = new Ast.TypeReference(localVarTypes[name].FullName);
- localVarDefined[name] = true;
- return astLocalVar;
- }
- } else {
- return new Ast.AssignmentExpression(new Ast.IdentifierExpression(name), AssignmentOperatorType.Assign, arg1);
- }
- }
- case Code.Stobj: throw new NotImplementedException();
- case Code.Switch: throw new NotImplementedException();
- case Code.Tail: throw new NotImplementedException();
- case Code.Throw: return new Ast.ThrowStatement(arg1);
- case Code.Unaligned: throw new NotImplementedException();
- case Code.Unbox: throw new NotImplementedException();
- case Code.Unbox_Any: throw new NotImplementedException();
- case Code.Volatile: throw new NotImplementedException();
- default: throw new Exception("Unknown OpCode: " + opCode);
- }
- }
-
- static Ast.Expression Convert(Ast.Expression expr, Cecil.TypeReference reqType)
- {
- if (reqType == null) {
- return expr;
- } else {
- return Convert(expr, reqType.FullName);
- }
- }
-
- static Ast.Expression Convert(Ast.Expression expr, string reqType)
- {
-// if (expr.UserData.ContainsKey("Type")) {
-// Cecil.TypeReference exprType = (Cecil.TypeReference)expr.UserData["Type"];
-// if (exprType == ByteCode.TypeZero &&
-// reqType == ByteCode.TypeBool.FullName) {
-// return new PrimitiveExpression(false, "false");
-// }
-// if (exprType == ByteCode.TypeOne &&
-// reqType == ByteCode.TypeBool.FullName) {
-// return new PrimitiveExpression(true, "true");
-// }
-// }
- return expr;
- }
-
- static Ast.Expression ConvertIntToBool(Ast.Expression astInt)
- {
- return astInt;
- // return new Ast.ParenthesizedExpression(new Ast.BinaryOperatorExpression(astInt, BinaryOperatorType.InEquality, new Ast.PrimitiveExpression(0, "0")));
- }
- }
-}
+using System;
+using System.Collections.Generic;
+
+using Ast = ICSharpCode.NRefactory.Ast;
+using ICSharpCode.NRefactory.Ast;
+using Cecil = Mono.Cecil;
+using Mono.Cecil;
+using Mono.Cecil.Cil;
+using Mono.Cecil.Rocks;
+using Decompiler.ControlFlow;
+
+namespace Decompiler
+{
+ public class AstMetodBodyBuilder
+ {
+ MethodDefinition methodDef;
+ static Dictionary<string, Cecil.TypeReference> localVarTypes = new Dictionary<string, Cecil.TypeReference>();
+ static Dictionary<string, bool> localVarDefined = new Dictionary<string, bool>();
+
+ public static BlockStatement CreateMetodBody(MethodDefinition methodDef)
+ {
+ AstMetodBodyBuilder builder = new AstMetodBodyBuilder();
+ builder.methodDef = methodDef;
+ try {
+ return builder.CreateMetodBody();
+ } catch {
+ BlockStatement block = new BlockStatement();
+ block.Children.Add(MakeComment("Exception during decompilation"));
+ return block;
+ }
+ }
+
+ public BlockStatement CreateMetodBody()
+ {
+ Ast.BlockStatement astBlock = new Ast.BlockStatement();
+
+ if (methodDef.Body == null) return astBlock;
+
+ methodDef.Body.SimplifyMacros();
+
+ List<ILNode> body = new ILAstBuilder().Build(methodDef);
+
+ MethodBodyGraph bodyGraph = new MethodBodyGraph(body);
+ bodyGraph.Optimize();
+
+ List<string> intNames = new List<string>(new string[] {"i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t"});
+ Dictionary<string, int> typeNames = new Dictionary<string, int>();
+ int boolFlagId = 1;
+ foreach(VariableDefinition varDef in methodDef.Body.Variables) {
+ if (string.IsNullOrEmpty(varDef.Name)) {
+ if (varDef.VariableType.FullName == Constants.Int32 && intNames.Count > 0) {
+ varDef.Name = intNames[0];
+ intNames.RemoveAt(0);
+ } else if (varDef.VariableType.FullName == Constants.Boolean) {
+ if (boolFlagId == 1) {
+ varDef.Name = "flag";
+ } else {
+ varDef.Name = "flag" + boolFlagId;
+ }
+ boolFlagId++;
+ } else {
+ string name;
+ if (varDef.VariableType.IsArray) {
+ name = "array";
+ } else {
+ name = varDef.VariableType.Name;
+ name = char.ToLower(name[0]) + name.Substring(1);
+ }
+ if (!typeNames.ContainsKey(name)) {
+ typeNames.Add(name, 0);
+ }
+ int count = typeNames[name];
+ if (count > 0) {
+ name += count.ToString();
+ }
+ varDef.Name = name;
+ }
+ }
+ localVarTypes[varDef.Name] = varDef.VariableType;
+ localVarDefined[varDef.Name] = false;
+
+// Ast.VariableDeclaration astVar = new Ast.VariableDeclaration(varDef.Name);
+// Ast.LocalVariableDeclaration astLocalVar = new Ast.LocalVariableDeclaration(astVar);
+// astLocalVar.TypeReference = new Ast.TypeReference(varDef.VariableType.FullName);
+// astBlock.Children.Add(astLocalVar);
+ }
+
+ astBlock.Children.AddRange(TransformNodes(bodyGraph.Childs));
+
+ return astBlock;
+ }
+
+ IEnumerable<Ast.INode> TransformNodes(IEnumerable<Node> nodes)
+ {
+ foreach(Node node in nodes) {
+ foreach(Ast.Statement stmt in TransformNode(node)) {
+ yield return stmt;
+ }
+ }
+ }
+
+ IEnumerable<Ast.INode> TransformNode(Node node)
+ {
+ if (Options.NodeComments) {
+ yield return MakeComment("// " + node.Description);
+ }
+
+ yield return new Ast.LabelStatement(node.Label);
+
+ if (node is BasicBlock) {
+ foreach(ILNode expr in ((BasicBlock)node).Body) {
+ if (expr is ILLabel) {
+ yield return new Ast.LabelStatement(((ILLabel)expr).Name);
+ } else {
+ Statement stmt = TransformExpressionToStatement((ILExpression)expr);
+ if (stmt != null) {
+ yield return stmt;
+ }
+ }
+ }
+ Node fallThroughNode = ((BasicBlock)node).FallThroughBasicBlock;
+ // If there is default branch and it is not the following node
+ if (fallThroughNode != null) {
+ yield return new Ast.GotoStatement(fallThroughNode.Label);
+ }
+ } else if (node is AcyclicGraph) {
+ Ast.BlockStatement blockStatement = new Ast.BlockStatement();
+ blockStatement.Children.AddRange(TransformNodes(node.Childs));
+ yield return blockStatement;
+ } else if (node is Loop) {
+ Ast.BlockStatement blockStatement = new Ast.BlockStatement();
+ blockStatement.Children.AddRange(TransformNodes(node.Childs));
+ yield return new Ast.ForStatement(
+ null,
+ null,
+ null,
+ blockStatement
+ );
+ } else if (node is Block) {
+ foreach(Ast.INode inode in TransformNodes(node.Childs)) {
+ yield return inode;
+ }
+ } else if (node is Branch) {
+ yield return new Ast.LabelStatement(((Branch)node).FirstBasicBlock.Label);
+
+ Ast.BlockStatement trueBlock = new Ast.BlockStatement();
+ trueBlock.Children.Add(new Ast.GotoStatement(((Branch)node).TrueSuccessor.Label));
+
+ Ast.BlockStatement falseBlock = new Ast.BlockStatement();
+ falseBlock.Children.Add(new Ast.GotoStatement(((Branch)node).FalseSuccessor.Label));
+
+ Ast.IfElseStatement ifElseStmt = new Ast.IfElseStatement(
+ MakeBranchCondition((Branch)node),
+ trueBlock,
+ falseBlock
+ );
+ trueBlock.Parent = ifElseStmt;
+ falseBlock.Parent = ifElseStmt;
+
+ yield return ifElseStmt;
+ } else if (node is ConditionalNode) {
+ ConditionalNode conditionalNode = (ConditionalNode)node;
+ yield return new Ast.LabelStatement(conditionalNode.Condition.FirstBasicBlock.Label);
+
+ Ast.BlockStatement trueBlock = new Ast.BlockStatement();
+ // The block entry code
+ trueBlock.Children.Add(new Ast.GotoStatement(conditionalNode.Condition.TrueSuccessor.Label));
+ // Sugested content
+ trueBlock.Children.AddRange(TransformNode(conditionalNode.TrueBody));
+
+ Ast.BlockStatement falseBlock = new Ast.BlockStatement();
+ // The block entry code
+ falseBlock.Children.Add(new Ast.GotoStatement(conditionalNode.Condition.FalseSuccessor.Label));
+ // Sugested content
+ falseBlock.Children.AddRange(TransformNode(conditionalNode.FalseBody));
+
+ Ast.IfElseStatement ifElseStmt = new Ast.IfElseStatement(
+ // Method bodies are swapped
+ new Ast.UnaryOperatorExpression(
+ new Ast.ParenthesizedExpression(
+ MakeBranchCondition(conditionalNode.Condition)
+ ),
+ UnaryOperatorType.Not
+ ),
+ falseBlock,
+ trueBlock
+ );
+ trueBlock.Parent = ifElseStmt;
+ falseBlock.Parent = ifElseStmt;
+
+ yield return ifElseStmt;
+ } else if (node is TryCatchNode) {
+ TryCatchNode tryCachNode = ((TryCatchNode)node);
+ Ast.BlockStatement tryBlock = new Ast.BlockStatement();
+ tryBlock.Children.AddRange(TransformNode(tryCachNode.Childs[0]));
+ Ast.BlockStatement finallyBlock = null;
+ if (tryCachNode.Childs[1].Childs.Count > 0) {
+ finallyBlock = new Ast.BlockStatement();
+ finallyBlock.Children.AddRange(TransformNode(tryCachNode.Childs[1]));
+ }
+ List<Ast.CatchClause> ccs = new List<CatchClause>();
+ for (int i = 0; i < tryCachNode.Types.Count; i++) {
+ Ast.BlockStatement catchBlock = new Ast.BlockStatement();
+ catchBlock.Children.AddRange(TransformNode(tryCachNode.Childs[i + 2]));
+ Ast.CatchClause cc = new Ast.CatchClause(
+ new Ast.TypeReference(tryCachNode.Types[i].FullName),
+ "exception",
+ catchBlock
+ );
+ ccs.Add(cc);
+ }
+ Ast.TryCatchStatement tryCachStmt = new Ast.TryCatchStatement(tryBlock, ccs, finallyBlock);
+ yield return tryCachStmt;
+ } else {
+ throw new Exception("Bad node type");
+ }
+
+ if (Options.NodeComments) {
+ yield return MakeComment("");
+ }
+ }
+
+ List<Ast.Expression> TransformExpressionArguments(ILExpression expr)
+ {
+ List<Ast.Expression> args = new List<Ast.Expression>();
+ // Args generated by nested expressions (which must be closed)
+ foreach(ILExpression arg in expr.Arguments) {
+ args.Add((Ast.Expression)TransformExpression(arg));
+ }
+ return args;
+ }
+
+ object TransformExpression(ILExpression expr)
+ {
+ List<Ast.Expression> args = TransformExpressionArguments(expr);
+ return TransformByteCode(methodDef, expr, args);
+ }
+
+ Ast.Statement TransformExpressionToStatement(ILExpression expr)
+ {
+ object codeExpr = TransformExpression(expr);
+ if (codeExpr == null) {
+ return null;
+ } else if (codeExpr is Ast.Expression) {
+ return new Ast.ExpressionStatement((Ast.Expression)codeExpr);
+ } else if (codeExpr is Ast.Statement) {
+ return (Ast.Statement)codeExpr;
+ } else {
+ throw new Exception();
+ }
+ }
+
+ static Ast.ExpressionStatement MakeComment(string text)
+ {
+ text = "/***" + text + "***/";
+ return new Ast.ExpressionStatement(new PrimitiveExpression(text, text));
+ }
+
+ Ast.Expression MakeBranchCondition(Branch branch)
+ {
+ return new ParenthesizedExpression(MakeBranchCondition_Internal(branch));
+ }
+
+ Ast.Expression MakeBranchCondition_Internal(Branch branch)
+ {
+ if (branch is SimpleBranch) {
+ List<Ast.Expression> args = TransformExpressionArguments((ILExpression)((SimpleBranch)branch).BasicBlock.Body[0]);
+ Ast.Expression arg1 = args.Count >= 1 ? args[0] : null;
+ Ast.Expression arg2 = args.Count >= 2 ? args[1] : null;
+ switch(((ILExpression)((SimpleBranch)branch).BasicBlock.Body[0]).OpCode.Code) {
+ case Code.Brfalse: return new Ast.UnaryOperatorExpression(arg1, UnaryOperatorType.Not);
+ case Code.Brtrue: return arg1;
+ case Code.Beq: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Equality, arg2);
+ case Code.Bge: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.GreaterThanOrEqual, arg2);
+ case Code.Bge_Un: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.GreaterThanOrEqual, arg2);
+ case Code.Bgt: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.GreaterThan, arg2);
+ case Code.Bgt_Un: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.GreaterThan, arg2);
+ case Code.Ble: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.LessThanOrEqual, arg2);
+ case Code.Ble_Un: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.LessThanOrEqual, arg2);
+ case Code.Blt: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.LessThan, arg2);
+ case Code.Blt_Un: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.LessThan, arg2);
+ case Code.Bne_Un: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.InEquality, arg2);
+ case Code.Leave: return new Ast.PrimitiveExpression(true, true.ToString());
+ default: throw new Exception("Bad opcode");
+ }
+ } else if (branch is ShortCircuitBranch) {
+ ShortCircuitBranch scBranch = (ShortCircuitBranch)branch;
+ switch(scBranch.Operator) {
+ case ShortCircuitOperator.LeftAndRight:
+ return new BinaryOperatorExpression(
+ MakeBranchCondition(scBranch.Left),
+ BinaryOperatorType.LogicalAnd,
+ MakeBranchCondition(scBranch.Right)
+ );
+ case ShortCircuitOperator.LeftOrRight:
+ return new BinaryOperatorExpression(
+ MakeBranchCondition(scBranch.Left),
+ BinaryOperatorType.LogicalOr,
+ MakeBranchCondition(scBranch.Right)
+ );
+ case ShortCircuitOperator.NotLeftAndRight:
+ return new BinaryOperatorExpression(
+ new UnaryOperatorExpression(MakeBranchCondition(scBranch.Left), UnaryOperatorType.Not),
+ BinaryOperatorType.LogicalAnd,
+ MakeBranchCondition(scBranch.Right)
+ );
+ case ShortCircuitOperator.NotLeftOrRight:
+ return new BinaryOperatorExpression(
+ new UnaryOperatorExpression(MakeBranchCondition(scBranch.Left), UnaryOperatorType.Not),
+ BinaryOperatorType.LogicalOr,
+ MakeBranchCondition(scBranch.Right)
+ );
+ default:
+ throw new Exception("Bad operator");
+ }
+ } else {
+ throw new Exception("Bad type");
+ }
+ }
+
+ static object TransformByteCode(MethodDefinition methodDef, ILExpression byteCode, List<Ast.Expression> args)
+ {
+ try {
+ Ast.INode ret = TransformByteCode_Internal(methodDef, byteCode, args);
+ if (ret is Ast.Expression) {
+ ret = new ParenthesizedExpression((Ast.Expression)ret);
+ }
+ // ret.UserData["Type"] = byteCode.Type;
+ return ret;
+ } catch (NotImplementedException) {
+ // Output the operand of the unknown IL code as well
+ if (byteCode.Operand != null) {
+ args.Insert(0, new IdentifierExpression(FormatByteCodeOperand(byteCode.Operand)));
+ }
+ return new Ast.InvocationExpression(new IdentifierExpression("__" + byteCode.OpCode.Name), args);
+ }
+ }
+
+ static string FormatByteCodeOperand(object operand)
+ {
+ if (operand == null) {
+ return string.Empty;
+ //} else if (operand is ILExpression) {
+ // return string.Format("IL_{0:X2}", ((ILExpression)operand).Offset);
+ } else if (operand is MethodReference) {
+ return ((MethodReference)operand).Name + "()";
+ } else if (operand is Cecil.TypeReference) {
+ return ((Cecil.TypeReference)operand).FullName;
+ } else if (operand is VariableDefinition) {
+ return ((VariableDefinition)operand).Name;
+ } else if (operand is ParameterDefinition) {
+ return ((ParameterDefinition)operand).Name;
+ } else if (operand is FieldReference) {
+ return ((FieldReference)operand).Name;
+ } else if (operand is string) {
+ return "\"" + operand + "\"";
+ } else if (operand is int) {
+ return operand.ToString();
+ } else {
+ return operand.ToString();
+ }
+ }
+
+ static Ast.INode TransformByteCode_Internal(MethodDefinition methodDef, ILExpression byteCode, List<Ast.Expression> args)
+ {
+ // throw new NotImplementedException();
+
+ OpCode opCode = byteCode.OpCode;
+ object operand = byteCode.Operand;
+ Ast.TypeReference operandAsTypeRef = operand is Cecil.TypeReference ? new Ast.TypeReference(((Cecil.TypeReference)operand).FullName) : null;
+ ILExpression operandAsByteCode = operand as ILExpression;
+ Ast.Expression arg1 = args.Count >= 1 ? args[0] : null;
+ Ast.Expression arg2 = args.Count >= 2 ? args[1] : null;
+ Ast.Expression arg3 = args.Count >= 3 ? args[2] : null;
+
+ Ast.Statement branchCommand = null;
+ if (byteCode.Operand is ILExpression) {
+ branchCommand = new Ast.GotoStatement(((ILLabel)byteCode.Operand).Name);
+ }
+
+ switch(opCode.Code) {
+ #region Arithmetic
+ case Code.Add: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Add, arg2);
+ case Code.Add_Ovf: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Add, arg2);
+ case Code.Add_Ovf_Un: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Add, arg2);
+ case Code.Div: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Divide, arg2);
+ case Code.Div_Un: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Divide, arg2);
+ case Code.Mul: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Multiply, arg2);
+ case Code.Mul_Ovf: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Multiply, arg2);
+ case Code.Mul_Ovf_Un: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Multiply, arg2);
+ case Code.Rem: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Modulus, arg2);
+ case Code.Rem_Un: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Modulus, arg2);
+ case Code.Sub: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Subtract, arg2);
+ case Code.Sub_Ovf: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Subtract, arg2);
+ case Code.Sub_Ovf_Un: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Subtract, arg2);
+ case Code.And: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.BitwiseAnd, arg2);
+ case Code.Xor: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.ExclusiveOr, arg2);
+ case Code.Shl: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.ShiftLeft, arg2);
+ case Code.Shr: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.ShiftRight, arg2);
+ case Code.Shr_Un: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.ShiftRight, arg2);
+
+ case Code.Neg: return new Ast.UnaryOperatorExpression(arg1, UnaryOperatorType.Minus);
+ case Code.Not: return new Ast.UnaryOperatorExpression(arg1, UnaryOperatorType.BitNot);
+ #endregion
+ #region Arrays
+ case Code.Newarr:
+ operandAsTypeRef.RankSpecifier = new int[] {0};
+ return new Ast.ArrayCreateExpression(operandAsTypeRef, new List<Expression>(new Expression[] {arg1}));
+
+ case Code.Ldlen: return new Ast.MemberReferenceExpression(arg1, "Length");
+
+ case Code.Ldelem_I:
+ case Code.Ldelem_I1:
+ case Code.Ldelem_I2:
+ case Code.Ldelem_I4:
+ case Code.Ldelem_I8:
+ case Code.Ldelem_U1:
+ case Code.Ldelem_U2:
+ case Code.Ldelem_U4:
+ case Code.Ldelem_R4:
+ case Code.Ldelem_R8:
+ case Code.Ldelem_Ref: return new Ast.IndexerExpression(arg1, new List<Expression>(new Expression[] {arg2}));
+ case Code.Ldelem_Any: throw new NotImplementedException();
+ case Code.Ldelema: return new Ast.IndexerExpression(arg1, new List<Expression>(new Expression[] {arg2}));
+
+ case Code.Stelem_I:
+ case Code.Stelem_I1:
+ case Code.Stelem_I2:
+ case Code.Stelem_I4:
+ case Code.Stelem_I8:
+ case Code.Stelem_R4:
+ case Code.Stelem_R8:
+ case Code.Stelem_Ref: return new Ast.AssignmentExpression(new Ast.IndexerExpression(arg1, new List<Expression>(new Expression[] {arg2})), AssignmentOperatorType.Assign, arg3);
+ case Code.Stelem_Any: throw new NotImplementedException();
+ #endregion
+ #region Branching
+ case Code.Br: return branchCommand;
+ case Code.Brfalse: return new Ast.IfElseStatement(new Ast.UnaryOperatorExpression(arg1, UnaryOperatorType.Not), branchCommand);
+ case Code.Brtrue: return new Ast.IfElseStatement(arg1, branchCommand);
+ case Code.Beq: return new Ast.IfElseStatement(new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Equality, arg2), branchCommand);
+ case Code.Bge: return new Ast.IfElseStatement(new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.GreaterThanOrEqual, arg2), branchCommand);
+ case Code.Bge_Un: return new Ast.IfElseStatement(new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.GreaterThanOrEqual, arg2), branchCommand);
+ case Code.Bgt: return new Ast.IfElseStatement(new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.GreaterThan, arg2), branchCommand);
+ case Code.Bgt_Un: return new Ast.IfElseStatement(new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.GreaterThan, arg2), branchCommand);
+ case Code.Ble: return new Ast.IfElseStatement(new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.LessThanOrEqual, arg2), branchCommand);
+ case Code.Ble_Un: return new Ast.IfElseStatement(new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.LessThanOrEqual, arg2), branchCommand);
+ case Code.Blt: return new Ast.IfElseStatement(new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.LessThan, arg2), branchCommand);
+ case Code.Blt_Un: return new Ast.IfElseStatement(new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.LessThan, arg2), branchCommand);
+ case Code.Bne_Un: return new Ast.IfElseStatement(new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.InEquality, arg2), branchCommand);
+ #endregion
+ #region Comparison
+ case Code.Ceq: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Equality, ConvertIntToBool(arg2));
+ case Code.Cgt: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.GreaterThan, arg2);
+ case Code.Cgt_Un: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.GreaterThan, arg2);
+ case Code.Clt: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.LessThan, arg2);
+ case Code.Clt_Un: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.LessThan, arg2);
+ #endregion
+ #region Conversions
+ case Code.Conv_I: return new Ast.CastExpression(new Ast.TypeReference(typeof(int).FullName), arg1, CastType.Cast); // TODO
+ case Code.Conv_I1: return new Ast.CastExpression(new Ast.TypeReference(typeof(SByte).FullName), arg1, CastType.Cast);
+ case Code.Conv_I2: return new Ast.CastExpression(new Ast.TypeReference(typeof(Int16).FullName), arg1, CastType.Cast);
+ case Code.Conv_I4: return new Ast.CastExpression(new Ast.TypeReference(typeof(Int32).FullName), arg1, CastType.Cast);
+ case Code.Conv_I8: return new Ast.CastExpression(new Ast.TypeReference(typeof(Int64).FullName), arg1, CastType.Cast);
+ case Code.Conv_U: return new Ast.CastExpression(new Ast.TypeReference(typeof(uint).FullName), arg1, CastType.Cast); // TODO
+ case Code.Conv_U1: return new Ast.CastExpression(new Ast.TypeReference(typeof(Byte).FullName), arg1, CastType.Cast);
+ case Code.Conv_U2: return new Ast.CastExpression(new Ast.TypeReference(typeof(UInt16).FullName), arg1, CastType.Cast);
+ case Code.Conv_U4: return new Ast.CastExpression(new Ast.TypeReference(typeof(UInt32).FullName), arg1, CastType.Cast);
+ case Code.Conv_U8: return new Ast.CastExpression(new Ast.TypeReference(typeof(UInt64).FullName), arg1, CastType.Cast);
+ case Code.Conv_R4: return new Ast.CastExpression(new Ast.TypeReference(typeof(float).FullName), arg1, CastType.Cast);
+ case Code.Conv_R8: return new Ast.CastExpression(new Ast.TypeReference(typeof(double).FullName), arg1, CastType.Cast);
+ case Code.Conv_R_Un: return new Ast.CastExpression(new Ast.TypeReference(typeof(double).FullName), arg1, CastType.Cast); // TODO
+
+ case Code.Conv_Ovf_I: return new Ast.CastExpression(new Ast.TypeReference(typeof(int).FullName), arg1, CastType.Cast); // TODO
+ case Code.Conv_Ovf_I1: return new Ast.CastExpression(new Ast.TypeReference(typeof(SByte).FullName), arg1, CastType.Cast);
+ case Code.Conv_Ovf_I2: return new Ast.CastExpression(new Ast.TypeReference(typeof(Int16).FullName), arg1, CastType.Cast);
+ case Code.Conv_Ovf_I4: return new Ast.CastExpression(new Ast.TypeReference(typeof(Int32).FullName), arg1, CastType.Cast);
+ case Code.Conv_Ovf_I8: return new Ast.CastExpression(new Ast.TypeReference(typeof(Int64).FullName), arg1, CastType.Cast);
+ case Code.Conv_Ovf_U: return new Ast.CastExpression(new Ast.TypeReference(typeof(uint).FullName), arg1, CastType.Cast); // TODO
+ case Code.Conv_Ovf_U1: return new Ast.CastExpression(new Ast.TypeReference(typeof(Byte).FullName), arg1, CastType.Cast);
+ case Code.Conv_Ovf_U2: return new Ast.CastExpression(new Ast.TypeReference(typeof(UInt16).FullName), arg1, CastType.Cast);
+ case Code.Conv_Ovf_U4: return new Ast.CastExpression(new Ast.TypeReference(typeof(UInt32).FullName), arg1, CastType.Cast);
+ case Code.Conv_Ovf_U8: return new Ast.CastExpression(new Ast.TypeReference(typeof(UInt64).FullName), arg1, CastType.Cast);
+
+ case Code.Conv_Ovf_I_Un: return new Ast.CastExpression(new Ast.TypeReference(typeof(int).FullName), arg1, CastType.Cast); // TODO
+ case Code.Conv_Ovf_I1_Un: return new Ast.CastExpression(new Ast.TypeReference(typeof(SByte).FullName), arg1, CastType.Cast);
+ case Code.Conv_Ovf_I2_Un: return new Ast.CastExpression(new Ast.TypeReference(typeof(Int16).FullName), arg1, CastType.Cast);
+ case Code.Conv_Ovf_I4_Un: return new Ast.CastExpression(new Ast.TypeReference(typeof(Int32).FullName), arg1, CastType.Cast);
+ case Code.Conv_Ovf_I8_Un: return new Ast.CastExpression(new Ast.TypeReference(typeof(Int64).FullName), arg1, CastType.Cast);
+ case Code.Conv_Ovf_U_Un: return new Ast.CastExpression(new Ast.TypeReference(typeof(uint).FullName), arg1, CastType.Cast); // TODO
+ case Code.Conv_Ovf_U1_Un: return new Ast.CastExpression(new Ast.TypeReference(typeof(Byte).FullName), arg1, CastType.Cast);
+ case Code.Conv_Ovf_U2_Un: return new Ast.CastExpression(new Ast.TypeReference(typeof(UInt16).FullName), arg1, CastType.Cast);
+ case Code.Conv_Ovf_U4_Un: return new Ast.CastExpression(new Ast.TypeReference(typeof(UInt32).FullName), arg1, CastType.Cast);
+ case Code.Conv_Ovf_U8_Un: return new Ast.CastExpression(new Ast.TypeReference(typeof(UInt64).FullName), arg1, CastType.Cast);
+ #endregion
+ #region Indirect
+ case Code.Ldind_I: throw new NotImplementedException();
+ case Code.Ldind_I1: throw new NotImplementedException();
+ case Code.Ldind_I2: throw new NotImplementedException();
+ case Code.Ldind_I4: throw new NotImplementedException();
+ case Code.Ldind_I8: throw new NotImplementedException();
+ case Code.Ldind_U1: throw new NotImplementedException();
+ case Code.Ldind_U2: throw new NotImplementedException();
+ case Code.Ldind_U4: throw new NotImplementedException();
+ case Code.Ldind_R4: throw new NotImplementedException();
+ case Code.Ldind_R8: throw new NotImplementedException();
+ case Code.Ldind_Ref: throw new NotImplementedException();
+
+ case Code.Stind_I: throw new NotImplementedException();
+ case Code.Stind_I1: throw new NotImplementedException();
+ case Code.Stind_I2: throw new NotImplementedException();
+ case Code.Stind_I4: throw new NotImplementedException();
+ case Code.Stind_I8: throw new NotImplementedException();
+ case Code.Stind_R4: throw new NotImplementedException();
+ case Code.Stind_R8: throw new NotImplementedException();
+ case Code.Stind_Ref: throw new NotImplementedException();
+ #endregion
+ case Code.Arglist: throw new NotImplementedException();
+ case Code.Box: throw new NotImplementedException();
+ case Code.Break: throw new NotImplementedException();
+ case Code.Call:
+ case Code.Callvirt:
+ // TODO: Diferentiate vitual and non-vitual dispach
+ Cecil.MethodReference cecilMethod = ((MethodReference)operand);
+ Ast.Expression target;
+ List<Ast.Expression> methodArgs = new List<Ast.Expression>(args);
+ if (cecilMethod.HasThis) {
+ target = methodArgs[0];
+ methodArgs.RemoveAt(0);
+ } else {
+ target = new Ast.IdentifierExpression(cecilMethod.DeclaringType.FullName);
+ }
+
+ // TODO: Constructors are ignored
+ if (cecilMethod.Name == ".ctor") {
+ return MakeComment("// Constructor");
+ }
+
+ // TODO: Hack, detect properties properly
+ if (cecilMethod.Name.StartsWith("get_")) {
+ return new Ast.MemberReferenceExpression(target, cecilMethod.Name.Remove(0, 4));
+ } else if (cecilMethod.Name.StartsWith("set_")) {
+ return new Ast.AssignmentExpression(
+ new Ast.MemberReferenceExpression(target, cecilMethod.Name.Remove(0, 4)),
+ AssignmentOperatorType.Assign,
+ methodArgs[0]
+ );
+ }
+
+ // Multi-dimensional array acces // TODO: do properly
+ if (cecilMethod.Name == "Get") {
+ return new Ast.IndexerExpression(target, methodArgs);
+ } else if (cecilMethod.Name == "Set") {
+ Expression val = methodArgs[methodArgs.Count - 1];
+ methodArgs.RemoveAt(methodArgs.Count - 1);
+ return new Ast.AssignmentExpression(
+ new Ast.IndexerExpression(target, methodArgs),
+ AssignmentOperatorType.Assign,
+ Convert(val, ((Cecil.ArrayType)target.UserData["Type"]).ElementType)
+ );
+ }
+
+ // Default invocation
+ return new Ast.InvocationExpression(
+ new Ast.MemberReferenceExpression(target, cecilMethod.Name),
+ methodArgs
+ );
+ case Code.Calli: throw new NotImplementedException();
+ case Code.Castclass: return new Ast.CastExpression(operandAsTypeRef, arg1, CastType.Cast);
+ case Code.Ckfinite: throw new NotImplementedException();
+ case Code.Constrained: throw new NotImplementedException();
+ case Code.Cpblk: throw new NotImplementedException();
+ case Code.Cpobj: throw new NotImplementedException();
+ case Code.Dup: return arg1;
+ case Code.Endfilter: throw new NotImplementedException();
+ case Code.Endfinally: return null;
+ case Code.Initblk: throw new NotImplementedException();
+ case Code.Initobj: throw new NotImplementedException();
+ case Code.Isinst: return new Ast.TypeOfIsExpression(arg1, new Ast.TypeReference(((Cecil.TypeReference)operand).FullName));
+ case Code.Jmp: throw new NotImplementedException();
+ case Code.Ldarg:
+ if (methodDef.HasThis && ((ParameterDefinition)operand).Index == 0) {
+ return new Ast.ThisReferenceExpression();
+ } else {
+ return new Ast.IdentifierExpression(((ParameterDefinition)operand).Name);
+ }
+ case Code.Ldarga: throw new NotImplementedException();
+ case Code.Ldc_I4:
+ case Code.Ldc_I8:
+ case Code.Ldc_R4:
+ case Code.Ldc_R8: return new Ast.PrimitiveExpression(operand, null);
+ case Code.Ldfld:
+ case Code.Ldsfld: {
+ if (operand is FieldDefinition) {
+ FieldDefinition field = (FieldDefinition) operand;
+ if (field.IsStatic) {
+ return new Ast.MemberReferenceExpression(
+ new Ast.IdentifierExpression(field.DeclaringType.FullName),
+ field.Name
+ );
+ } else {
+ return new Ast.MemberReferenceExpression(arg1, field.Name);
+ }
+ } else {
+ // TODO: Static accesses
+ return new Ast.MemberReferenceExpression(arg1, ((FieldReference)operand).Name);
+ }
+ }
+ case Code.Stfld:
+ case Code.Stsfld: {
+ FieldDefinition field = (FieldDefinition) operand;
+ if (field.IsStatic) {
+ return new AssignmentExpression(
+ new Ast.MemberReferenceExpression(
+ new Ast.IdentifierExpression(field.DeclaringType.FullName),
+ field.Name
+ ),
+ AssignmentOperatorType.Assign,
+ arg1
+ );
+ } else {
+ return new AssignmentExpression(
+ new Ast.MemberReferenceExpression(arg1, field.Name),
+ AssignmentOperatorType.Assign,
+ arg2
+ );
+ }
+ }
+ case Code.Ldflda:
+ case Code.Ldsflda: throw new NotImplementedException();
+ case Code.Ldftn: throw new NotImplementedException();
+ case Code.Ldloc:
+ if (operand is ILStackVariable) {
+ return new Ast.IdentifierExpression(((ILStackVariable)operand).Name);
+ } else {
+ return new Ast.IdentifierExpression(((VariableDefinition)operand).Name);
+ }
+ case Code.Ldloca: throw new NotImplementedException();
+ case Code.Ldnull: return new Ast.PrimitiveExpression(null, null);
+ case Code.Ldobj: throw new NotImplementedException();
+ case Code.Ldstr: return new Ast.PrimitiveExpression(operand, null);
+ case Code.Ldtoken:
+ if (operand is Cecil.TypeReference) {
+ return new Ast.MemberReferenceExpression(
+ new Ast.TypeOfExpression(operandAsTypeRef),
+ "TypeHandle"
+ );
+ } else {
+ throw new NotImplementedException();
+ }
+ case Code.Ldvirtftn: throw new NotImplementedException();
+ case Code.Leave: return null;
+ case Code.Localloc: throw new NotImplementedException();
+ case Code.Mkrefany: throw new NotImplementedException();
+ case Code.Newobj:
+ Cecil.TypeReference declaringType = ((MethodReference)operand).DeclaringType;
+ // TODO: Ensure that the corrent overloaded constructor is called
+ if (declaringType is ArrayType) {
+ return new Ast.ArrayCreateExpression(
+ new Ast.TypeReference(((ArrayType)declaringType).ElementType.FullName, new int[] {}),
+ new List<Expression>(args)
+ );
+ }
+ return new Ast.ObjectCreateExpression(
+ new Ast.TypeReference(declaringType.FullName),
+ new List<Expression>(args)
+ );
+ case Code.No: throw new NotImplementedException();
+ case Code.Nop: return null;
+ case Code.Or: throw new NotImplementedException();
+ case Code.Pop: return arg1;
+ case Code.Readonly: throw new NotImplementedException();
+ case Code.Refanytype: throw new NotImplementedException();
+ case Code.Refanyval: throw new NotImplementedException();
+ case Code.Ret: {
+ if (methodDef.ReturnType.FullName != Constants.Void) {
+ arg1 = Convert(arg1, methodDef.ReturnType);
+ return new Ast.ReturnStatement(arg1);
+ } else {
+ return new Ast.ReturnStatement(null);
+ }
+ }
+ case Code.Rethrow: return new Ast.ThrowStatement(new IdentifierExpression("exception"));
+ case Code.Sizeof: throw new NotImplementedException();
+ case Code.Starg: throw new NotImplementedException();
+ case Code.Stloc: {
+ if (operand is ILStackVariable) {
+ return new Ast.AssignmentExpression(new Ast.IdentifierExpression(((ILStackVariable)operand).Name), AssignmentOperatorType.Assign, arg1);
+ }
+ VariableDefinition locVar = (VariableDefinition)operand;
+ string name = locVar.Name;
+ arg1 = Convert(arg1, locVar.VariableType);
+ if (localVarDefined.ContainsKey(name)) {
+ if (localVarDefined[name]) {
+ return new Ast.AssignmentExpression(new Ast.IdentifierExpression(name), AssignmentOperatorType.Assign, arg1);
+ } else {
+ Ast.LocalVariableDeclaration astLocalVar = new Ast.LocalVariableDeclaration(new Ast.VariableDeclaration(name, arg1));
+ astLocalVar.TypeReference = new Ast.TypeReference(localVarTypes[name].FullName);
+ localVarDefined[name] = true;
+ return astLocalVar;
+ }
+ } else {
+ return new Ast.AssignmentExpression(new Ast.IdentifierExpression(name), AssignmentOperatorType.Assign, arg1);
+ }
+ }
+ case Code.Stobj: throw new NotImplementedException();
+ case Code.Switch: throw new NotImplementedException();
+ case Code.Tail: throw new NotImplementedException();
+ case Code.Throw: return new Ast.ThrowStatement(arg1);
+ case Code.Unaligned: throw new NotImplementedException();
+ case Code.Unbox: throw new NotImplementedException();
+ case Code.Unbox_Any: throw new NotImplementedException();
+ case Code.Volatile: throw new NotImplementedException();
+ default: throw new Exception("Unknown OpCode: " + opCode);
+ }
+ }
+
+ static Ast.Expression Convert(Ast.Expression expr, Cecil.TypeReference reqType)
+ {
+ if (reqType == null) {
+ return expr;
+ } else {
+ return Convert(expr, reqType.FullName);
+ }
+ }
+
+ static Ast.Expression Convert(Ast.Expression expr, string reqType)
+ {
+// if (expr.UserData.ContainsKey("Type")) {
+// Cecil.TypeReference exprType = (Cecil.TypeReference)expr.UserData["Type"];
+// if (exprType == ByteCode.TypeZero &&
+// reqType == ByteCode.TypeBool.FullName) {
+// return new PrimitiveExpression(false, "false");
+// }
+// if (exprType == ByteCode.TypeOne &&
+// reqType == ByteCode.TypeBool.FullName) {
+// return new PrimitiveExpression(true, "true");
+// }
+// }
+ return expr;
+ }
+
+ static Ast.Expression ConvertIntToBool(Ast.Expression astInt)
+ {
+ return astInt;
+ // return new Ast.ParenthesizedExpression(new Ast.BinaryOperatorExpression(astInt, BinaryOperatorType.InEquality, new Ast.PrimitiveExpression(0, "0")));
+ }
+ }
+}
View
152 Decompiler/src/Ast/Transforms/Idioms.cs → ...pCode.Decompiler/Ast/Transforms/Idioms.cs
@@ -1,76 +1,76 @@
-using System;
-using System.Collections.Generic;
-using Ast = ICSharpCode.NRefactory.Ast;
-using ICSharpCode.NRefactory.Ast;
-using ICSharpCode.NRefactory.Visitors;
-
-namespace Decompiler.Transforms.Ast
-{
- public class Idioms: AbstractAstTransformer
- {
- public override object VisitInvocationExpression(InvocationExpression invocationExpression, object data)
- {
- base.VisitInvocationExpression(invocationExpression, data);
-
- // Reduce "String.Concat(a, b)" to "a + b"
- MemberReferenceExpression target = invocationExpression.TargetObject as MemberReferenceExpression;
- if (target != null &&
- target.MemberName == "Concat" &&
- invocationExpression.Arguments.Count == 2 &&
- target.TargetObject is IdentifierExpression &&
- (target.TargetObject as IdentifierExpression).Identifier == "String")
- {
- ReplaceCurrentNode(
- new BinaryOperatorExpression(
- invocationExpression.Arguments[0],
- BinaryOperatorType.Add,
- invocationExpression.Arguments[1]
- )
- );
- }
-
- return null;
- }
-
- public override object VisitAssignmentExpression(AssignmentExpression assignment, object data)
- {
- IdentifierExpression ident = assignment.Left as IdentifierExpression;
- BinaryOperatorExpression binary = assignment.Right as BinaryOperatorExpression;
- if (ident != null && binary != null) {
- IdentifierExpression binaryLeft = binary.Left as IdentifierExpression;
- if (binaryLeft != null &&
- binaryLeft.Identifier == ident.Identifier) {
- if (binary.Right is PrimitiveExpression &&
- 1.Equals((binary.Right as PrimitiveExpression).Value)) {
- if (binary.Op == BinaryOperatorType.Add) {
- ReplaceCurrentNode(new UnaryOperatorExpression(ident, UnaryOperatorType.PostIncrement));
- }
- if (binary.Op == BinaryOperatorType.Subtract) {
- ReplaceCurrentNode(new UnaryOperatorExpression(ident, UnaryOperatorType.PostDecrement));
- }
- } else {
- if (binary.Op == BinaryOperatorType.Add) {
- ReplaceCurrentNode(new AssignmentExpression(ident, AssignmentOperatorType.Add, binary.Right));
- }
- if (binary.Op == BinaryOperatorType.Subtract) {
- ReplaceCurrentNode(new AssignmentExpression(ident, AssignmentOperatorType.Subtract, binary.Right));
- }
- }
- return null;
- }
- }
- return null;
- }
-
- public override object VisitCastExpression(CastExpression castExpression, object data)
- {
- if (castExpression.CastTo.Type == "int" &&
- castExpression.Expression is MemberReferenceExpression &&
- (castExpression.Expression as MemberReferenceExpression).MemberName == "Length") {
- ReplaceCurrentNode(castExpression.Expression);
- return null;
- }
- return base.VisitCastExpression(castExpression, data);
- }
- }
-}
+using System;
+using System.Collections.Generic;
+using Ast = ICSharpCode.NRefactory.Ast;
+using ICSharpCode.NRefactory.Ast;
+using ICSharpCode.NRefactory.Visitors;
+
+namespace Decompiler.Transforms.Ast
+{
+ public class Idioms: AbstractAstTransformer
+ {
+ public override object VisitInvocationExpression(InvocationExpression invocationExpression, object data)
+ {
+ base.VisitInvocationExpression(invocationExpression, data);
+
+ // Reduce "String.Concat(a, b)" to "a + b"
+ MemberReferenceExpression target = invocationExpression.TargetObject as MemberReferenceExpression;
+ if (target != null &&
+ target.MemberName == "Concat" &&
+ invocationExpression.Arguments.Count == 2 &&
+ target.TargetObject is IdentifierExpression &&
+ (target.TargetObject as IdentifierExpression).Identifier == "String")
+ {
+ ReplaceCurrentNode(
+ new BinaryOperatorExpression(
+ invocationExpression.Arguments[0],
+ BinaryOperatorType.Add,
+ invocationExpression.Arguments[1]
+ )
+ );
+ }
+
+ return null;
+ }
+
+ public override object VisitAssignmentExpression(AssignmentExpression assignment, object data)
+ {
+ IdentifierExpression ident = assignment.Left as IdentifierExpression;
+ BinaryOperatorExpression binary = assignment.Right as BinaryOperatorExpression;
+ if (ident != null && binary != null) {
+ IdentifierExpression binaryLeft = binary.Left as IdentifierExpression;
+ if (binaryLeft != null &&
+ binaryLeft.Identifier == ident.Identifier) {
+ if (binary.Right is PrimitiveExpression &&
+ 1.Equals((binary.Right as PrimitiveExpression).Value)) {
+ if (binary.Op == BinaryOperatorType.Add) {
+ ReplaceCurrentNode(new UnaryOperatorExpression(ident, UnaryOperatorType.PostIncrement));
+ }
+ if (binary.Op == BinaryOperatorType.Subtract) {
+ ReplaceCurrentNode(new UnaryOperatorExpression(ident, UnaryOperatorType.PostDecrement));
+ }
+ } else {
+ if (binary.Op == BinaryOperatorType.Add) {
+ ReplaceCurrentNode(new AssignmentExpression(ident, AssignmentOperatorType.Add, binary.Right));
+ }
+ if (binary.Op == BinaryOperatorType.Subtract) {
+ ReplaceCurrentNode(new AssignmentExpression(ident, AssignmentOperatorType.Subtract, binary.Right));
+ }
+ }
+ return null;
+ }
+ }
+ return null;
+ }
+
+ public override object VisitCastExpression(CastExpression castExpression, object data)
+ {
+ if (castExpression.CastTo.Type == "int" &&
+ castExpression.Expression is MemberReferenceExpression &&
+ (castExpression.Expression as MemberReferenceExpression).MemberName == "Length") {
+ ReplaceCurrentNode(castExpression.Expression);
+ return null;
+ }
+ return base.VisitCastExpression(castExpression, data);
+ }
+ }
+}
View
174 ...mpiler/src/Ast/Transforms/PushNegation.cs → ...Decompiler/Ast/Transforms/PushNegation.cs
@@ -1,87 +1,87 @@
-using System;
-using System.Collections.Generic;
-
-using ICSharpCode.NRefactory.Ast;
-using ICSharpCode.NRefactory.Visitors;
-
-namespace Decompiler.Transforms.Ast
-{
- public class PushNegation: AbstractAstTransformer
- {
- public override object VisitUnaryOperatorExpression(UnaryOperatorExpression unary, object data)
- {
- // Remove double negation
- // !!a
- if (unary.Op == UnaryOperatorType.Not &&
- unary.Expression is UnaryOperatorExpression &&
- (unary.Expression as UnaryOperatorExpression).Op == UnaryOperatorType.Not) {
- Expression newParenth = new ParenthesizedExpression((unary.Expression as UnaryOperatorExpression).Expression);
- ReplaceCurrentNode(newParenth);
- return newParenth.AcceptVisitor(this, data);
- }
-
- // Basic assumtion is that we have something in form !(a)
- if (unary.Op == UnaryOperatorType.Not &&
- unary.Expression is ParenthesizedExpression) {
- ParenthesizedExpression parenth = ((ParenthesizedExpression)unary.Expression);
-
- // Push through two parenthesis
- // !((a))
- if (parenth.Expression is ParenthesizedExpression) {
- parenth.Expression = new UnaryOperatorExpression(parenth.Expression, UnaryOperatorType.Not);
- ReplaceCurrentNode(parenth);
- return parenth.AcceptVisitor(this, data);
- }
-
- // Remove double negation
- // !(!a)
- if (parenth.Expression is UnaryOperatorExpression &&
- (parenth.Expression as UnaryOperatorExpression).Op == UnaryOperatorType.Not) {
- parenth.Expression = (parenth.Expression as UnaryOperatorExpression).Expression;
- ReplaceCurrentNode(parenth);
- return parenth.AcceptVisitor(this, data);
- }
-
- // Push through binary operation
- // !((a) op (b))
- BinaryOperatorExpression binaryOp = parenth.Expression as BinaryOperatorExpression;
- if (binaryOp != null &&
- binaryOp.Left is ParenthesizedExpression &&
- binaryOp.Right is ParenthesizedExpression) {
-
- bool sucessful = true;
- switch(binaryOp.Op) {
- case BinaryOperatorType.Equality: binaryOp.Op = BinaryOperatorType.InEquality; break;
- case BinaryOperatorType.InEquality: binaryOp.Op = BinaryOperatorType.Equality; break;
- case BinaryOperatorType.GreaterThan: binaryOp.Op = BinaryOperatorType.LessThanOrEqual; break;
- case BinaryOperatorType.GreaterThanOrEqual: binaryOp.Op = BinaryOperatorType.LessThan; break;
- case BinaryOperatorType.LessThanOrEqual: binaryOp.Op = BinaryOperatorType.GreaterThan; break;
- case BinaryOperatorType.LessThan: binaryOp.Op = BinaryOperatorType.GreaterThanOrEqual; break;
- default: sucessful = false; break;
- }
- if (sucessful) {
- ReplaceCurrentNode(parenth);
- return parenth.AcceptVisitor(this, data);
- }
-
- sucessful = true;
- switch(binaryOp.Op) {
- case BinaryOperatorType.BitwiseAnd: binaryOp.Op = BinaryOperatorType.BitwiseOr; break;
- case BinaryOperatorType.BitwiseOr: binaryOp.Op = BinaryOperatorType.BitwiseAnd; break;
- case BinaryOperatorType.LogicalAnd: binaryOp.Op = BinaryOperatorType.LogicalOr; break;
- case BinaryOperatorType.LogicalOr: binaryOp.Op = BinaryOperatorType.LogicalAnd; break;
- default: sucessful = false; break;
- }
- if (sucessful) {
- binaryOp.Left = new UnaryOperatorExpression(binaryOp.Left, UnaryOperatorType.Not);
- binaryOp.Right = new UnaryOperatorExpression(binaryOp.Right, UnaryOperatorType.Not);
- ReplaceCurrentNode(parenth);
- return parenth.AcceptVisitor(this, data);
- }
- }
- }
-
- return base.VisitUnaryOperatorExpression(unary, data);
- }
- }
-}
+using System;
+using System.Collections.Generic;
+
+using ICSharpCode.NRefactory.Ast;
+using ICSharpCode.NRefactory.Visitors;
+
+namespace Decompiler.Transforms.Ast
+{
+ public class PushNegation: AbstractAstTransformer
+ {
+ public override object VisitUnaryOperatorExpression(UnaryOperatorExpression unary, object data)
+ {
+ // Remove double negation
+ // !!a
+ if (unary.Op == UnaryOperatorType.Not &&
+ unary.Expression is UnaryOperatorExpression &&
+ (unary.Expression as UnaryOperatorExpression).Op == UnaryOperatorType.Not) {
+ Expression newParenth = new ParenthesizedExpression((unary.Expression as UnaryOperatorExpression).Expression);
+ ReplaceCurrentNode(newParenth);
+ return newParenth.AcceptVisitor(this, data);
+ }
+
+ // Basic assumtion is that we have something in form !(a)
+ if (unary.Op == UnaryOperatorType.Not &&
+ unary.Expression is ParenthesizedExpression) {
+ ParenthesizedExpression parenth = ((ParenthesizedExpression)unary.Expression);
+
+ // Push through two parenthesis
+ // !((a))
+ if (parenth.Expression is ParenthesizedExpression) {
+ parenth.Expression = new UnaryOperatorExpression(parenth.Expression, UnaryOperatorType.Not);
+ ReplaceCurrentNode(parenth);
+ return parenth.AcceptVisitor(this, data);
+ }
+
+ // Remove double negation
+ // !(!a)
+ if (parenth.Expression is UnaryOperatorExpression &&
+ (parenth.Expression as UnaryOperatorExpression).Op == UnaryOperatorType.Not) {
+ parenth.Expression = (parenth.Expression as UnaryOperatorExpression).Expression;
+ ReplaceCurrentNode(parenth);
+ return parenth.AcceptVisitor(this, data);
+ }
+
+ // Push through binary operation
+ // !((a) op (b))
+ BinaryOperatorExpression binaryOp = parenth.Expression as BinaryOperatorExpression;
+ if (binaryOp != null &&
+ binaryOp.Left is ParenthesizedExpression &&
+ binaryOp.Right is ParenthesizedExpression) {
+
+ bool sucessful = true;
+ switch(binaryOp.Op) {
+ case BinaryOperatorType.Equality: binaryOp.Op = BinaryOperatorType.InEquality; break;
+ case BinaryOperatorType.InEquality: binaryOp.Op = BinaryOperatorType.Equality; break;
+ case BinaryOperatorType.GreaterThan: binaryOp.Op = BinaryOperatorType.LessThanOrEqual; break;
+ case BinaryOperatorType.GreaterThanOrEqual: binaryOp.Op = BinaryOperatorType.LessThan; break;
+ case BinaryOperatorType.LessThanOrEqual: binaryOp.Op = BinaryOperatorType.GreaterThan; break;
+ case BinaryOperatorType.LessThan: binaryOp.Op = BinaryOperatorType.GreaterThanOrEqual; break;
+ default: sucessful = false; break;
+ }
+ if (sucessful) {
+ ReplaceCurrentNode(parenth);
+ return parenth.AcceptVisitor(this, data);