Browse Source

Resurrect Ast based "goto removal" - we will use that until it is converted to ILAst based one.

pull/10/head
David Srbecký 15 years ago
parent
commit
1ba93ac216
  1. 6
      ICSharpCode.Decompiler/Ast/AstBuilder.cs
  2. 56
      ICSharpCode.Decompiler/Ast/Transforms/RemoveDeadLabels.cs
  3. 68
      ICSharpCode.Decompiler/Ast/Transforms/RemoveGotos.cs
  4. 53
      ICSharpCode.Decompiler/Ast/Transforms/RestoreLoop.cs
  5. 1
      ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj

6
ICSharpCode.Decompiler/Ast/AstBuilder.cs

@ -19,11 +19,11 @@ namespace Decompiler @@ -19,11 +19,11 @@ namespace Decompiler
{
for (int i = 0; i < 4; i++) {
if (Options.ReduceAstJumps) {
//astCompileUnit.AcceptVisitor(new Transforms.Ast.RemoveGotos(), null);
//astCompileUnit.AcceptVisitor(new Transforms.Ast.RemoveDeadLabels(), null);
astCompileUnit.AcceptVisitor(new Transforms.Ast.RemoveGotos(), null);
astCompileUnit.AcceptVisitor(new Transforms.Ast.RemoveDeadLabels(), null);
}
if (Options.ReduceAstLoops) {
//astCompileUnit.AcceptVisitor(new Transforms.Ast.RestoreLoop(), null);
astCompileUnit.AcceptVisitor(new Transforms.Ast.RestoreLoop(), null);
}
if (Options.ReduceAstOther) {
astCompileUnit.AcceptVisitor(new Transforms.Ast.RemoveEmptyElseBody(), null);

56
ICSharpCode.Decompiler/Ast/Transforms/RemoveDeadLabels.cs

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

68
ICSharpCode.Decompiler/Ast/Transforms/RemoveGotos.cs

@ -1,16 +1,15 @@ @@ -1,16 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using ICSharpCode.NRefactory.CSharp;
namespace Decompiler.Transforms.Ast
{
/*
public class RemoveGotos: DepthFirstAstVisitor<object, object>
{
Stack<Statement> enteredLoops = new Stack<Statement>();
Stack<ForStatement> enteredLoops = new Stack<ForStatement>();
Statement CurrentLoop {
ForStatement CurrentLoop {
get {
if (enteredLoops.Count > 0) {
return enteredLoops.Peek();
@ -28,27 +27,20 @@ namespace Decompiler.Transforms.Ast @@ -28,27 +27,20 @@ namespace Decompiler.Transforms.Ast
return null;
}
public override object VisitWhileStatement(WhileStatement whileStatement, object data)
{
enteredLoops.Push(whileStatement);
base.VisitWhileStatement(whileStatement, data);
enteredLoops.Pop();
return null;
}
// public override object VisitWhileStatement(WhileStatement whileStatement, object data)
// {
// enteredLoops.Push(whileStatement);
// base.VisitWhileStatement(whileStatement, data);
// enteredLoops.Pop();
// return null;
// }
public override object VisitBlockStatement(BlockStatement blockStatement, object data)
{
base.VisitBlockStatement(blockStatement, data);
// Remove redundant jump at the end of block
INode lastStmt = blockStatement.Children.Last;
// End of while loop
if (lastStmt is ContinueStatement &&
blockStatement.Parent is DoLoopStatement)
{
lastStmt.Remove();
return null;
}
AstNode lastStmt = blockStatement.Children.LastOrDefault();
// End of for loop
if (lastStmt is ContinueStatement &&
blockStatement.Parent is ForStatement)
@ -74,7 +66,7 @@ namespace Decompiler.Transforms.Ast @@ -74,7 +66,7 @@ namespace Decompiler.Transforms.Ast
{
if (statement == null) throw new ArgumentNullException();
Statement next = (Statement)statement.Next();
Statement next = (Statement)statement.NextSibling;
if (next != null) {
return EnterBlockStatement(next);
@ -104,12 +96,12 @@ namespace Decompiler.Transforms.Ast @@ -104,12 +96,12 @@ namespace Decompiler.Transforms.Ast
// Iterator; Condition; Body
if (statement is ForStatement) {
ForStatement forLoop = statement as ForStatement;
if (forLoop.Iterator.Count > 0) {
return forLoop.Iterator[0];
if (forLoop.Iterators.Any()) {
return forLoop.Iterators.First();
} else if (!forLoop.Condition.IsNull) {
return forLoop.Condition;
} else {
return EnterBlockStatement((Statement)forLoop.EmbeddedStatement.Children.First);
return EnterBlockStatement((Statement)forLoop.EmbeddedStatement.FirstChild);
}
}
@ -124,14 +116,12 @@ namespace Decompiler.Transforms.Ast @@ -124,14 +116,12 @@ namespace Decompiler.Transforms.Ast
// For loop starts as follows: Initializers; Condition; Body
if (statement is ForStatement) {
ForStatement forLoop = statement as ForStatement;
if (forLoop.Initializers.Count > 0) {
return forLoop.Initializers[0];
if (forLoop.Initializers.Any()) {
return forLoop.Initializers.First();
} else if (!forLoop.Condition.IsNull) {
return forLoop.Condition;
} else if (forLoop.EmbeddedStatement is BlockStatement &&
forLoop.EmbeddedStatement.Children.Count > 0) {
statement = (Statement)forLoop.EmbeddedStatement.Children.First;
return EnterBlockStatement(statement); // Simplify again
} else if (forLoop.EmbeddedStatement.Children.FirstOrDefault() is Statement) {
return EnterBlockStatement((Statement)forLoop.EmbeddedStatement.FirstChild); // Simplify again
}
}
@ -141,11 +131,11 @@ namespace Decompiler.Transforms.Ast @@ -141,11 +131,11 @@ namespace Decompiler.Transforms.Ast
public override object VisitGotoStatement(GotoStatement gotoStatement, object data)
{
// Remove redundant goto which goes to a label that imideately follows
INode fallthoughTarget = GetNextStatement(gotoStatement);
AstNode fallthoughTarget = GetNextStatement(gotoStatement);
while(true) {
if (fallthoughTarget is LabelStatement) {
if ((fallthoughTarget as LabelStatement).Label == gotoStatement.Label) {
RemoveCurrentNode();
gotoStatement.Remove();
return null;
} else {
fallthoughTarget = GetNextStatement((LabelStatement)fallthoughTarget);
@ -158,10 +148,10 @@ namespace Decompiler.Transforms.Ast @@ -158,10 +148,10 @@ namespace Decompiler.Transforms.Ast
// Replace goto with 'break'
// Break statement moves right outside the looop
if (CurrentLoop != null) {
INode breakTarget = GetNextStatement(CurrentLoop);
AstNode breakTarget = GetNextStatement(CurrentLoop);
if ((breakTarget is LabelStatement) &&
(breakTarget as LabelStatement).Label == gotoStatement.Label) {
ReplaceCurrentNode(new BreakStatement());
gotoStatement.ReplaceWith(new BreakStatement());
return null;
}
}
@ -170,24 +160,24 @@ namespace Decompiler.Transforms.Ast @@ -170,24 +160,24 @@ namespace Decompiler.Transforms.Ast
// Continue statement which moves at the very end of loop
if (CurrentLoop != null &&
(CurrentLoop.EmbeddedStatement is BlockStatement) &&
((CurrentLoop.EmbeddedStatement as BlockStatement).Children.Last as LabelStatement) != null &&
((CurrentLoop.EmbeddedStatement as BlockStatement).Children.Last as LabelStatement).Label == gotoStatement.Label) {
ReplaceCurrentNode(new ContinueStatement());
((CurrentLoop.EmbeddedStatement as BlockStatement).LastChild as LabelStatement) != null &&
((CurrentLoop.EmbeddedStatement as BlockStatement).LastChild as LabelStatement).Label == gotoStatement.Label) {
gotoStatement.ReplaceWith(new ContinueStatement());
return null;
}
// Replace goto with 'continue'
// Continue statement which moves at the very start of for loop
if (CurrentLoop != null) {
INode continueTarget = ExitBlockStatement(CurrentLoop); // The start of the loop
AstNode continueTarget = ExitBlockStatement(CurrentLoop); // The start of the loop
if ((continueTarget is LabelStatement) &&
(continueTarget as LabelStatement).Label == gotoStatement.Label) {
ReplaceCurrentNode(new ContinueStatement());
gotoStatement.ReplaceWith(new ContinueStatement());
return null;
}
}
return null;
}
}*/
}
}

53
ICSharpCode.Decompiler/Ast/Transforms/RestoreLoop.cs

@ -1,10 +1,9 @@ @@ -1,10 +1,9 @@
using System;
using ICSharpCode.NRefactory.CSharp;
using System;
using System.Linq;
using ICSharpCode.NRefactory.CSharp;
namespace Decompiler.Transforms.Ast
{
/*
public class RestoreLoop: DepthFirstAstVisitor<object, object>
{
public override object VisitForStatement(ForStatement forStatement, object data)
@ -12,25 +11,25 @@ namespace Decompiler.Transforms.Ast @@ -12,25 +11,25 @@ namespace Decompiler.Transforms.Ast
base.VisitForStatement(forStatement, data);
// Restore loop initializer
if (forStatement.Initializers.Count == 0) {
LocalVariableDeclaration varDeclr = forStatement.Previous() as LocalVariableDeclaration;
if (!forStatement.Initializers.Any()) {
VariableDeclarationStatement varDeclr = forStatement.PrevSibling as VariableDeclarationStatement;
if (varDeclr != null) {
varDeclr.ReplaceWith(Statement.Null);
forStatement.Initializers.Add(varDeclr);
forStatement.Initializers = new Statement[] { varDeclr };
}
}
// Restore loop condition
if (forStatement.Condition.IsNull &&
forStatement.EmbeddedStatement.Children.Count >= 3)
forStatement.EmbeddedStatement.Children.Count() >= 3)
{
IfElseStatement condition = forStatement.EmbeddedStatement.Children[0] as IfElseStatement;
BreakStatement breakStmt = forStatement.EmbeddedStatement.Children[1] as BreakStatement;
LabelStatement label = forStatement.EmbeddedStatement.Children[2] as LabelStatement;
IfElseStatement condition = forStatement.EmbeddedStatement.Children.First() as IfElseStatement;
BreakStatement breakStmt = forStatement.EmbeddedStatement.Children.Skip(1).First() as BreakStatement;
LabelStatement label = forStatement.EmbeddedStatement.Children.Skip(2).First() as LabelStatement;
if (condition != null && breakStmt != null && label != null &&
condition.TrueStatement.Count == 1)
condition.TrueStatement.Children.Count() == 1)
{
GotoStatement gotoStmt = condition.TrueStatement[0] as GotoStatement;
GotoStatement gotoStmt = condition.TrueStatement.FirstChild as GotoStatement;
if (gotoStmt != null && gotoStmt.Label == label.Label) {
condition.Remove();
breakStmt.Remove();
@ -41,34 +40,34 @@ namespace Decompiler.Transforms.Ast @@ -41,34 +40,34 @@ namespace Decompiler.Transforms.Ast
// Restore loop condition (version 2)
if (forStatement.Condition.IsNull) {
IfElseStatement condition = forStatement.EmbeddedStatement.Children.First as IfElseStatement;
IfElseStatement condition = forStatement.EmbeddedStatement.FirstChild as IfElseStatement;
if (condition != null &&
condition.TrueStatement.Count == 1 &&
condition.TrueStatement[0] is BlockStatement &&
condition.TrueStatement[0].Children.Count == 1 &&
condition.TrueStatement[0].Children.First is BreakStatement &&
condition.FalseStatement.Count == 1 &&
condition.FalseStatement[0] is BlockStatement &&
condition.FalseStatement[0].Children.Count == 0)
condition.TrueStatement.Children.Any() &&
condition.TrueStatement.FirstChild is BlockStatement &&
condition.TrueStatement.Children.Count() == 1 &&
condition.TrueStatement.FirstChild.FirstChild is BreakStatement &&
condition.FalseStatement.Children.Any() &&
condition.FalseStatement.FirstChild is BlockStatement &&
condition.FalseStatement.Children.Count() == 0)
{
condition.Remove();
forStatement.Condition = new UnaryOperatorExpression(condition.Condition, UnaryOperatorType.Not);
forStatement.Condition = new UnaryOperatorExpression() { Expression = condition.Condition, Operator = UnaryOperatorType.Not };
}
}
// Restore loop iterator
if (forStatement.EmbeddedStatement.Children.Count > 0 &&
forStatement.Iterator.Count == 0)
if (forStatement.EmbeddedStatement.Children.Any() &&
!forStatement.Iterators.Any())
{
ExpressionStatement lastStmt = forStatement.EmbeddedStatement.Children.Last as ExpressionStatement;
ExpressionStatement lastStmt = forStatement.EmbeddedStatement.LastChild as ExpressionStatement;
if (lastStmt != null &&
(lastStmt.Expression is AssignmentExpression || lastStmt.Expression is UnaryOperatorExpression)) {
lastStmt.Remove();
forStatement.Iterator.Add(lastStmt);
forStatement.Iterators = new Statement[] { lastStmt };
}
}
return null;
}
}*/
}
}

1
ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj

@ -57,6 +57,7 @@ @@ -57,6 +57,7 @@
<Compile Include="Ast\Transforms\ConvertConstructorCallIntoInitializer.cs" />
<Compile Include="Ast\Transforms\ReplaceMethodCallsWithOperators.cs" />
<Compile Include="Ast\Transforms\PushNegation.cs" />
<Compile Include="Ast\Transforms\RemoveDeadLabels.cs" />
<Compile Include="Ast\Transforms\RemoveEmptyElseBody.cs" />
<Compile Include="Ast\Transforms\RemoveGotos.cs" />
<Compile Include="Ast\Transforms\RestoreLoop.cs" />

Loading…
Cancel
Save