Browse Source

Reactivate PatternStatementTransform

pull/728/head
Daniel Grunwald 9 years ago
parent
commit
bb1beedbd4
  1. 9
      ICSharpCode.Decompiler/CSharp/Annotations.cs
  2. 4
      ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
  3. 78
      ICSharpCode.Decompiler/CSharp/Transforms/ContextTrackingVisitor.cs
  4. 69
      ICSharpCode.Decompiler/CSharp/Transforms/PatternStatementTransform.cs
  5. 5
      ICSharpCode.Decompiler/CSharp/Transforms/TransformContext.cs
  6. 2
      ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
  7. 12
      ICSharpCode.Decompiler/IL/Instructions/ILInstruction.cs
  8. 3
      ICSharpCode.Decompiler/IL/Transforms/InlineCompilerGeneratedVariables.cs
  9. 3
      ICSharpCode.Decompiler/IL/Transforms/LoopingTransform.cs
  10. 1
      ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj

9
ICSharpCode.Decompiler/CSharp/Annotations.cs

@ -110,6 +110,15 @@ namespace ICSharpCode.Decompiler.CSharp
{ {
return node.Annotation<ResolveResult>() ?? ErrorResolveResult.UnknownError; return node.Annotation<ResolveResult>() ?? ErrorResolveResult.UnknownError;
} }
public static ILVariable GetILVariable(this IdentifierExpression expr)
{
var rr = expr.Annotation<ResolveResult>() as ILVariableResolveResult;
if (rr != null)
return rr.Variable;
else
return null;
}
} }
public class ILVariableResolveResult : ResolveResult public class ILVariableResolveResult : ResolveResult

4
ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs

@ -66,7 +66,7 @@ namespace ICSharpCode.Decompiler.CSharp
List<IAstTransform> astTransforms = new List<IAstTransform> { List<IAstTransform> astTransforms = new List<IAstTransform> {
//new PushNegation(), //new PushNegation(),
//new DelegateConstruction(context), //new DelegateConstruction(context),
//new PatternStatementTransform(context), new PatternStatementTransform(),
new ReplaceMethodCallsWithOperators(), new ReplaceMethodCallsWithOperators(),
new IntroduceUnsafeModifier(), new IntroduceUnsafeModifier(),
new AddCheckedBlocks(), new AddCheckedBlocks(),
@ -196,7 +196,7 @@ namespace ICSharpCode.Decompiler.CSharp
void RunTransforms(AstNode rootNode, ITypeResolveContext decompilationContext) void RunTransforms(AstNode rootNode, ITypeResolveContext decompilationContext)
{ {
var typeSystemAstBuilder = CreateAstBuilder(decompilationContext); var typeSystemAstBuilder = CreateAstBuilder(decompilationContext);
var context = new TransformContext(typeSystem, decompilationContext, typeSystemAstBuilder, CancellationToken); var context = new TransformContext(typeSystem, decompilationContext, typeSystemAstBuilder, settings, CancellationToken);
foreach (var transform in astTransforms) { foreach (var transform in astTransforms) {
CancellationToken.ThrowIfCancellationRequested(); CancellationToken.ThrowIfCancellationRequested();
transform.Run(rootNode, context); transform.Run(rootNode, context);

78
ICSharpCode.Decompiler/CSharp/Transforms/ContextTrackingVisitor.cs

@ -19,6 +19,7 @@
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using ICSharpCode.NRefactory.CSharp; using ICSharpCode.NRefactory.CSharp;
using ICSharpCode.NRefactory.TypeSystem;
using Mono.Cecil; using Mono.Cecil;
namespace ICSharpCode.Decompiler.CSharp.Transforms namespace ICSharpCode.Decompiler.CSharp.Transforms
@ -26,86 +27,81 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
/// <summary> /// <summary>
/// Base class for AST visitors that need the current type/method context info. /// Base class for AST visitors that need the current type/method context info.
/// </summary> /// </summary>
public abstract class ContextTrackingVisitor<TResult> : DepthFirstAstVisitor<object, TResult>, IAstTransform public abstract class ContextTrackingVisitor<TResult> : DepthFirstAstVisitor<TResult>
{ {
protected readonly DecompilerContext context; protected ITypeDefinition currentTypeDefinition;
protected IMethod currentMethod;
protected ContextTrackingVisitor(DecompilerContext context) protected void Initialize(TransformContext context)
{ {
if (context == null) currentTypeDefinition = context.DecompiledTypeDefinition;
throw new ArgumentNullException("context"); currentMethod = context.DecompiledMember as IMethod;
this.context = context;
} }
public override TResult VisitTypeDeclaration(TypeDeclaration typeDeclaration, object data) public override TResult VisitTypeDeclaration(TypeDeclaration typeDeclaration)
{ {
TypeDefinition oldType = context.CurrentType; ITypeDefinition oldType = currentTypeDefinition;
try { try {
context.CurrentType = typeDeclaration.Annotation<TypeDefinition>(); currentTypeDefinition = typeDeclaration.GetSymbol() as ITypeDefinition;
return base.VisitTypeDeclaration(typeDeclaration, data); return base.VisitTypeDeclaration(typeDeclaration);
} finally { } finally {
context.CurrentType = oldType; currentTypeDefinition = oldType;
} }
} }
public override TResult VisitMethodDeclaration(MethodDeclaration methodDeclaration, object data) public override TResult VisitMethodDeclaration(MethodDeclaration methodDeclaration)
{ {
Debug.Assert(context.CurrentMethod == null); Debug.Assert(currentMethod == null);
try { try {
context.CurrentMethod = methodDeclaration.Annotation<MethodDefinition>(); currentMethod = methodDeclaration.GetSymbol() as IMethod;
return base.VisitMethodDeclaration(methodDeclaration, data); return base.VisitMethodDeclaration(methodDeclaration);
} finally { } finally {
context.CurrentMethod = null; currentMethod = null;
} }
} }
public override TResult VisitConstructorDeclaration(ConstructorDeclaration constructorDeclaration, object data) public override TResult VisitConstructorDeclaration(ConstructorDeclaration constructorDeclaration)
{ {
Debug.Assert(context.CurrentMethod == null); Debug.Assert(currentMethod == null);
try { try {
context.CurrentMethod = constructorDeclaration.Annotation<MethodDefinition>(); currentMethod = constructorDeclaration.GetSymbol() as IMethod;
return base.VisitConstructorDeclaration(constructorDeclaration, data); return base.VisitConstructorDeclaration(constructorDeclaration);
} finally { } finally {
context.CurrentMethod = null; currentMethod = null;
} }
} }
public override TResult VisitDestructorDeclaration(DestructorDeclaration destructorDeclaration, object data) public override TResult VisitDestructorDeclaration(DestructorDeclaration destructorDeclaration)
{ {
Debug.Assert(context.CurrentMethod == null); Debug.Assert(currentMethod == null);
try { try {
context.CurrentMethod = destructorDeclaration.Annotation<MethodDefinition>(); currentMethod = destructorDeclaration.GetSymbol() as IMethod;
return base.VisitDestructorDeclaration(destructorDeclaration, data); return base.VisitDestructorDeclaration(destructorDeclaration);
} finally { } finally {
context.CurrentMethod = null; currentMethod = null;
} }
} }
public override TResult VisitOperatorDeclaration(OperatorDeclaration operatorDeclaration, object data) public override TResult VisitOperatorDeclaration(OperatorDeclaration operatorDeclaration)
{ {
Debug.Assert(context.CurrentMethod == null); Debug.Assert(currentMethod == null);
try { try {
context.CurrentMethod = operatorDeclaration.Annotation<MethodDefinition>(); currentMethod = operatorDeclaration.GetSymbol() as IMethod;
return base.VisitOperatorDeclaration(operatorDeclaration, data); return base.VisitOperatorDeclaration(operatorDeclaration);
} finally { } finally {
context.CurrentMethod = null; currentMethod = null;
} }
} }
public override TResult VisitAccessor(Accessor accessor, object data) public override TResult VisitAccessor(Accessor accessor)
{ {
Debug.Assert(context.CurrentMethod == null); Debug.Assert(currentMethod == null);
try { try {
context.CurrentMethod = accessor.Annotation<MethodDefinition>(); currentMethod = accessor.GetSymbol() as IMethod;
return base.VisitAccessor(accessor, data); return base.VisitAccessor(accessor);
} finally { } finally {
context.CurrentMethod = null; currentMethod = null;
} }
} }
void IAstTransform.Run(AstNode node)
{
node.AcceptVisitor(this, null);
}
} }
} }

69
ICSharpCode.Decompiler/CSharp/Transforms/PatternStatementTransform.cs

@ -21,7 +21,6 @@ using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Linq; using System.Linq;
using ICSharpCode.Decompiler.ILAst;
using ICSharpCode.NRefactory.CSharp; using ICSharpCode.NRefactory.CSharp;
using ICSharpCode.NRefactory.CSharp.Analysis; using ICSharpCode.NRefactory.CSharp.Analysis;
using ICSharpCode.NRefactory.PatternMatching; using ICSharpCode.NRefactory.PatternMatching;
@ -34,12 +33,17 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
/// </summary> /// </summary>
public sealed class PatternStatementTransform : ContextTrackingVisitor<AstNode>, IAstTransform public sealed class PatternStatementTransform : ContextTrackingVisitor<AstNode>, IAstTransform
{ {
public PatternStatementTransform(DecompilerContext context) : base(context) TransformContext context;
public void Run(AstNode rootNode, TransformContext context)
{ {
this.context = context;
base.Initialize(context);
rootNode.AcceptVisitor(this);
} }
#region Visitor Overrides #region Visitor Overrides
protected override AstNode VisitChildren(AstNode node, object data) protected override AstNode VisitChildren(AstNode node)
{ {
// Go through the children, and keep visiting a node as long as it changes. // Go through the children, and keep visiting a node as long as it changes.
// Because some transforms delete/replace nodes before and after the node being transformed, we rely // Because some transforms delete/replace nodes before and after the node being transformed, we rely
@ -48,14 +52,14 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
AstNode oldChild; AstNode oldChild;
do { do {
oldChild = child; oldChild = child;
child = child.AcceptVisitor(this, data); child = child.AcceptVisitor(this);
Debug.Assert(child != null && child.Parent == node); Debug.Assert(child != null && child.Parent == node);
} while (child != oldChild); } while (child != oldChild);
} }
return node; return node;
} }
public override AstNode VisitExpressionStatement(ExpressionStatement expressionStatement, object data) public override AstNode VisitExpressionStatement(ExpressionStatement expressionStatement)
{ {
AstNode result; AstNode result;
if (context.Settings.UsingStatement) if (context.Settings.UsingStatement)
@ -75,25 +79,25 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
if (result != null) if (result != null)
return result; return result;
} }
return base.VisitExpressionStatement(expressionStatement, data); return base.VisitExpressionStatement(expressionStatement);
} }
public override AstNode VisitUsingStatement(UsingStatement usingStatement, object data) public override AstNode VisitUsingStatement(UsingStatement usingStatement)
{ {
if (context.Settings.ForEachStatement) { if (context.Settings.ForEachStatement) {
AstNode result = TransformForeach(usingStatement); AstNode result = TransformForeach(usingStatement);
if (result != null) if (result != null)
return result; return result;
} }
return base.VisitUsingStatement(usingStatement, data); return base.VisitUsingStatement(usingStatement);
} }
public override AstNode VisitWhileStatement(WhileStatement whileStatement, object data) public override AstNode VisitWhileStatement(WhileStatement whileStatement)
{ {
return TransformDoWhile(whileStatement) ?? base.VisitWhileStatement(whileStatement, data); return TransformDoWhile(whileStatement) ?? base.VisitWhileStatement(whileStatement);
} }
public override AstNode VisitIfElseStatement(IfElseStatement ifElseStatement, object data) public override AstNode VisitIfElseStatement(IfElseStatement ifElseStatement)
{ {
if (context.Settings.SwitchStatementOnString) { if (context.Settings.SwitchStatementOnString) {
AstNode result = TransformSwitchOnString(ifElseStatement); AstNode result = TransformSwitchOnString(ifElseStatement);
@ -103,23 +107,23 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
AstNode simplifiedIfElse = SimplifyCascadingIfElseStatements(ifElseStatement); AstNode simplifiedIfElse = SimplifyCascadingIfElseStatements(ifElseStatement);
if (simplifiedIfElse != null) if (simplifiedIfElse != null)
return simplifiedIfElse; return simplifiedIfElse;
return base.VisitIfElseStatement(ifElseStatement, data); return base.VisitIfElseStatement(ifElseStatement);
} }
public override AstNode VisitPropertyDeclaration(PropertyDeclaration propertyDeclaration, object data) public override AstNode VisitPropertyDeclaration(PropertyDeclaration propertyDeclaration)
{ {
if (context.Settings.AutomaticProperties) { if (context.Settings.AutomaticProperties) {
AstNode result = TransformAutomaticProperties(propertyDeclaration); AstNode result = TransformAutomaticProperties(propertyDeclaration);
if (result != null) if (result != null)
return result; return result;
} }
return base.VisitPropertyDeclaration(propertyDeclaration, data); return base.VisitPropertyDeclaration(propertyDeclaration);
} }
public override AstNode VisitCustomEventDeclaration(CustomEventDeclaration eventDeclaration, object data) public override AstNode VisitCustomEventDeclaration(CustomEventDeclaration eventDeclaration)
{ {
// first apply transforms to the accessor bodies // first apply transforms to the accessor bodies
base.VisitCustomEventDeclaration(eventDeclaration, data); base.VisitCustomEventDeclaration(eventDeclaration);
if (context.Settings.AutomaticEvents) { if (context.Settings.AutomaticEvents) {
AstNode result = TransformAutomaticEvents(eventDeclaration); AstNode result = TransformAutomaticEvents(eventDeclaration);
if (result != null) if (result != null)
@ -128,14 +132,14 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
return eventDeclaration; return eventDeclaration;
} }
public override AstNode VisitMethodDeclaration(MethodDeclaration methodDeclaration, object data) public override AstNode VisitMethodDeclaration(MethodDeclaration methodDeclaration)
{ {
return TransformDestructor(methodDeclaration) ?? base.VisitMethodDeclaration(methodDeclaration, data); return TransformDestructor(methodDeclaration) ?? base.VisitMethodDeclaration(methodDeclaration);
} }
public override AstNode VisitTryCatchStatement(TryCatchStatement tryCatchStatement, object data) public override AstNode VisitTryCatchStatement(TryCatchStatement tryCatchStatement)
{ {
return TransformTryCatchFinally(tryCatchStatement) ?? base.VisitTryCatchStatement(tryCatchStatement, data); return TransformTryCatchFinally(tryCatchStatement) ?? base.VisitTryCatchStatement(tryCatchStatement);
} }
#endregion #endregion
@ -216,13 +220,13 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
TryCatchStatement tryCatch = node.NextSibling as TryCatchStatement; TryCatchStatement tryCatch = node.NextSibling as TryCatchStatement;
Match m2 = usingTryCatchPattern.Match(tryCatch); Match m2 = usingTryCatchPattern.Match(tryCatch);
if (!m2.Success) return null; if (!m2.Success) return null;
IL.ILVariable variable = m1.Get<IdentifierExpression>("variable").Single().GetILVariable();
string variableName = m1.Get<IdentifierExpression>("variable").Single().Identifier; string variableName = m1.Get<IdentifierExpression>("variable").Single().Identifier;
if (variableName != m2.Get<IdentifierExpression>("ident").Single().Identifier) if (variable == null || variableName != m2.Get<IdentifierExpression>("ident").Single().Identifier)
return null; return null;
if (m2.Has("valueType")) { if (m2.Has("valueType")) {
// if there's no if(x!=null), then it must be a value type // if there's no if(x!=null), then it must be a value type
ILVariable v = m1.Get<AstNode>("variable").Single().Annotation<ILVariable>(); if (variable.Type.IsReferenceType != false)
if (v == null || v.Type == null || !v.Type.IsValueType)
return null; return null;
} }
@ -271,7 +275,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
Name = variableName, Name = variableName,
Initializer = m1.Get<Expression>("initializer").Single().Detach() Initializer = m1.Get<Expression>("initializer").Single().Detach()
}.CopyAnnotationsFrom(node.Expression) }.CopyAnnotationsFrom(node.Expression)
.WithAnnotation(m1.Get<AstNode>("variable").Single().Annotation<ILVariable>()) .WithAnnotation(variable)
} }
}.CopyAnnotationsFrom(node); }.CopyAnnotationsFrom(node);
} else { } else {
@ -328,12 +332,13 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
blocks.Reverse(); // go from parent blocks to child blocks blocks.Reverse(); // go from parent blocks to child blocks
DefiniteAssignmentAnalysis daa = new DefiniteAssignmentAnalysis(blocks[0], context.CancellationToken); DefiniteAssignmentAnalysis daa = new DefiniteAssignmentAnalysis(blocks[0], context.CancellationToken);
declarationPoint = null; declarationPoint = null;
foreach (BlockStatement block in blocks) { return false;
/*foreach (BlockStatement block in blocks) {
if (!DeclareVariables.FindDeclarationPoint(daa, varDecl, block, out declarationPoint)) { if (!DeclareVariables.FindDeclarationPoint(daa, varDecl, block, out declarationPoint)) {
return false; return false;
} }
} }
return true; return true;*/
} }
/// <summary> /// <summary>
@ -438,7 +443,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
VariableName = itemVar.Identifier, VariableName = itemVar.Identifier,
InExpression = m.Get<Expression>("collection").Single().Detach(), InExpression = m.Get<Expression>("collection").Single().Detach(),
EmbeddedStatement = newBody EmbeddedStatement = newBody
}.WithAnnotation(itemVarDecl.Variables.Single().Annotation<ILVariable>()); }.WithAnnotation(itemVarDecl.Variables.Single().Annotation<IL.ILVariable>());
if (foreachStatement.InExpression is BaseReferenceExpression) { if (foreachStatement.InExpression is BaseReferenceExpression) {
foreachStatement.InExpression = new ThisReferenceExpression().CopyAnnotationsFrom(foreachStatement.InExpression); foreachStatement.InExpression = new ThisReferenceExpression().CopyAnnotationsFrom(foreachStatement.InExpression);
} }
@ -532,7 +537,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
{ {
VariableType = itemVarDecl.Type.Clone(), VariableType = itemVarDecl.Type.Clone(),
VariableName = itemVar.Identifier, VariableName = itemVar.Identifier,
}.WithAnnotation(itemVarDecl.Variables.Single().Annotation<ILVariable>()); }.WithAnnotation(itemVarDecl.Variables.Single().Annotation<IL.ILVariable>());
BlockStatement body = new BlockStatement(); BlockStatement body = new BlockStatement();
foreachStatement.EmbeddedStatement = body; foreachStatement.EmbeddedStatement = body;
((BlockStatement)node.Parent).Statements.InsertBefore(node, foreachStatement); ((BlockStatement)node.Parent).Statements.InsertBefore(node, foreachStatement);
@ -628,7 +633,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
if (m.Success) { if (m.Success) {
DoWhileStatement doLoop = new DoWhileStatement(); DoWhileStatement doLoop = new DoWhileStatement();
doLoop.Condition = new UnaryOperatorExpression(UnaryOperatorType.Not, m.Get<Expression>("condition").Single().Detach()); doLoop.Condition = new UnaryOperatorExpression(UnaryOperatorType.Not, m.Get<Expression>("condition").Single().Detach());
doLoop.Condition.AcceptVisitor(new PushNegation(), null); //doLoop.Condition.AcceptVisitor(new PushNegation(), null);
BlockStatement block = (BlockStatement)whileLoop.EmbeddedStatement; BlockStatement block = (BlockStatement)whileLoop.EmbeddedStatement;
block.Statements.Last().Remove(); // remove if statement block.Statements.Last().Remove(); // remove if statement
doLoop.EmbeddedStatement = block.Detach(); doLoop.EmbeddedStatement = block.Detach();
@ -1069,7 +1074,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
FieldDefinition field = eventDef.DeclaringType.Fields.FirstOrDefault(f => f.Name == ev.Name); FieldDefinition field = eventDef.DeclaringType.Fields.FirstOrDefault(f => f.Name == ev.Name);
if (field != null) { if (field != null) {
ed.AddAnnotation(field); ed.AddAnnotation(field);
AstBuilder.ConvertAttributes(ed, field, "field"); // TODO AstBuilder.ConvertAttributes(ed, field, "field");
} }
} }
@ -1102,7 +1107,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
methodDef.Attributes.MoveTo(dd.Attributes); methodDef.Attributes.MoveTo(dd.Attributes);
dd.Modifiers = methodDef.Modifiers & ~(Modifiers.Protected | Modifiers.Override); dd.Modifiers = methodDef.Modifiers & ~(Modifiers.Protected | Modifiers.Override);
dd.Body = m.Get<BlockStatement>("body").Single().Detach(); dd.Body = m.Get<BlockStatement>("body").Single().Detach();
dd.Name = AstBuilder.CleanName(context.CurrentType.Name); dd.Name = currentTypeDefinition.Name;
methodDef.ReplaceWith(dd); methodDef.ReplaceWith(dd);
return dd; return dd;
} }

5
ICSharpCode.Decompiler/CSharp/Transforms/TransformContext.cs

@ -32,6 +32,8 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
public readonly DecompilerTypeSystem TypeSystem; public readonly DecompilerTypeSystem TypeSystem;
public readonly CancellationToken CancellationToken; public readonly CancellationToken CancellationToken;
public readonly TypeSystemAstBuilder TypeSystemAstBuilder; public readonly TypeSystemAstBuilder TypeSystemAstBuilder;
public readonly DecompilerSettings Settings;
readonly ITypeResolveContext decompilationContext; readonly ITypeResolveContext decompilationContext;
/// <summary> /// <summary>
@ -48,11 +50,12 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
get { return decompilationContext.CurrentTypeDefinition; } get { return decompilationContext.CurrentTypeDefinition; }
} }
internal TransformContext(DecompilerTypeSystem typeSystem, ITypeResolveContext decompilationContext, TypeSystemAstBuilder typeSystemAstBuilder, CancellationToken cancellationToken) internal TransformContext(DecompilerTypeSystem typeSystem, ITypeResolveContext decompilationContext, TypeSystemAstBuilder typeSystemAstBuilder, DecompilerSettings settings, CancellationToken cancellationToken)
{ {
this.TypeSystem = typeSystem; this.TypeSystem = typeSystem;
this.decompilationContext = decompilationContext; this.decompilationContext = decompilationContext;
this.TypeSystemAstBuilder = typeSystemAstBuilder; this.TypeSystemAstBuilder = typeSystemAstBuilder;
this.Settings = settings;
this.CancellationToken = cancellationToken; this.CancellationToken = cancellationToken;
} }
} }

2
ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj

@ -65,11 +65,13 @@
<ItemGroup> <ItemGroup>
<Compile Include="CSharp\Annotations.cs" /> <Compile Include="CSharp\Annotations.cs" />
<Compile Include="CSharp\DecompilerSettings.cs" /> <Compile Include="CSharp\DecompilerSettings.cs" />
<Compile Include="CSharp\Transforms\ContextTrackingVisitor.cs" />
<Compile Include="CSharp\Transforms\DecimalConstantTransform.cs" /> <Compile Include="CSharp\Transforms\DecimalConstantTransform.cs" />
<Compile Include="CSharp\Transforms\DeclareVariables.cs" /> <Compile Include="CSharp\Transforms\DeclareVariables.cs" />
<Compile Include="CSharp\Transforms\EscapeInvalidIdentifiers.cs" /> <Compile Include="CSharp\Transforms\EscapeInvalidIdentifiers.cs" />
<Compile Include="CSharp\Transforms\FixNameCollisions.cs" /> <Compile Include="CSharp\Transforms\FixNameCollisions.cs" />
<Compile Include="CSharp\Transforms\IntroduceUsingDeclarations.cs" /> <Compile Include="CSharp\Transforms\IntroduceUsingDeclarations.cs" />
<Compile Include="CSharp\Transforms\PatternStatementTransform.cs" />
<Compile Include="CSharp\Transforms\TransformContext.cs" /> <Compile Include="CSharp\Transforms\TransformContext.cs" />
<Compile Include="CSharp\TranslatedExpression.cs" /> <Compile Include="CSharp\TranslatedExpression.cs" />
<Compile Include="CSharp\CSharpDecompiler.cs" /> <Compile Include="CSharp\CSharpDecompiler.cs" />

12
ICSharpCode.Decompiler/IL/Instructions/ILInstruction.cs

@ -105,6 +105,12 @@ namespace ICSharpCode.Decompiler.IL
return a; return a;
} }
/// <summary>
/// Gets whether this node (or any subnode) was modified since the last <c>ResetDirty()</c> call.
/// </summary>
/// <remarks>
/// IsDirty is used by the LoopingTransform, and must not be used by individual transforms within the loop.
/// </remarks>
public bool IsDirty { get; private set; } public bool IsDirty { get; private set; }
protected void MakeDirty() protected void MakeDirty()
@ -113,6 +119,12 @@ namespace ICSharpCode.Decompiler.IL
inst.IsDirty = true; inst.IsDirty = true;
} }
/// <summary>
/// Marks this node (and all subnodes) as <c>IsDirty=false</c>.
/// </summary>
/// <remarks>
/// IsDirty is used by the LoopingTransform, and must not be used by individual transforms within the loop.
/// </remarks>
public void ResetDirty() public void ResetDirty()
{ {
foreach (ILInstruction inst in Descendants) foreach (ILInstruction inst in Descendants)

3
ICSharpCode.Decompiler/IL/Transforms/InlineCompilerGeneratedVariables.cs

@ -74,8 +74,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
if (block == null) if (block == null)
return false; return false;
ILInstruction next = block.Instructions.ElementAtOrDefault(stloc.ChildIndex + 1); ILInstruction next = block.Instructions.ElementAtOrDefault(stloc.ChildIndex + 1);
if (next == null) // NB: next==null is considerd as a dead store
continue; // store at end of block might still be a dead store
if (ILInlining.CanInlineInto(next, v, stloc.Value)) { if (ILInlining.CanInlineInto(next, v, stloc.Value)) {
loadsAccountedFor++; loadsAccountedFor++;
storesToInline.Add(stloc); storesToInline.Add(stloc);

3
ICSharpCode.Decompiler/IL/Transforms/LoopingTransform.cs

@ -22,6 +22,9 @@ using System.Collections.Generic;
namespace ICSharpCode.Decompiler.IL namespace ICSharpCode.Decompiler.IL
{ {
/// <summary>
/// Repeats the child transforms until the ILAst no longer changes.
/// </summary>
public class LoopingTransform : IILTransform public class LoopingTransform : IILTransform
{ {
readonly IReadOnlyCollection<IILTransform> children; readonly IReadOnlyCollection<IILTransform> children;

1
ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj

@ -128,6 +128,7 @@
<Compile Include="TestCases\PropertiesAndEvents.cs" /> <Compile Include="TestCases\PropertiesAndEvents.cs" />
<Compile Include="TestCases\Switch.cs" /> <Compile Include="TestCases\Switch.cs" />
<Compile Include="TestCases\UndocumentedExpressions.cs" /> <Compile Include="TestCases\UndocumentedExpressions.cs" />
<Compile Include="TestCases\UnsafeCode.cs" />
<Compile Include="TestCases\ValueTypeCall.cs" /> <Compile Include="TestCases\ValueTypeCall.cs" />
<Compile Include="TestRunner.cs" /> <Compile Include="TestRunner.cs" />
<Compile Include="Util\IntervalTests.cs" /> <Compile Include="Util\IntervalTests.cs" />

Loading…
Cancel
Save