Browse Source

Fixed some bugs in DeclareVariables.

pull/100/head
Daniel Grunwald 15 years ago
parent
commit
cca7547789
  1. 4
      ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs
  2. 41
      ICSharpCode.Decompiler/Ast/Transforms/DeclareVariables.cs
  3. 4
      ICSharpCode.Decompiler/Ast/Transforms/DelegateConstruction.cs
  4. 20
      ICSharpCode.Decompiler/Ast/Transforms/PatternStatementTransform.cs

4
ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs

@ -88,9 +88,11 @@ namespace ICSharpCode.Decompiler.Ast
context.CancellationToken.ThrowIfCancellationRequested(); context.CancellationToken.ThrowIfCancellationRequested();
Ast.BlockStatement astBlock = TransformBlock(ilMethod); Ast.BlockStatement astBlock = TransformBlock(ilMethod);
CommentStatement.ReplaceAll(astBlock); // convert CommentStatements to Comments CommentStatement.ReplaceAll(astBlock); // convert CommentStatements to Comments
Statement insertionPoint = astBlock.Statements.FirstOrDefault();
foreach (ILVariable v in localVariablesToDefine) { foreach (ILVariable v in localVariablesToDefine) {
var newVarDecl = new VariableDeclarationStatement(AstBuilder.ConvertType(v.Type), v.Name); var newVarDecl = new VariableDeclarationStatement(AstBuilder.ConvertType(v.Type), v.Name);
astBlock.Statements.InsertAfter(null, newVarDecl); astBlock.Statements.InsertBefore(insertionPoint, newVarDecl);
} }
return astBlock; return astBlock;

41
ICSharpCode.Decompiler/Ast/Transforms/DeclareVariables.cs

@ -92,14 +92,22 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
if (TryConvertAssignmentExpressionIntoVariableDeclaration((Expression)usingStmt.ResourceAcquisition, type, variableName)) if (TryConvertAssignmentExpressionIntoVariableDeclaration((Expression)usingStmt.ResourceAcquisition, type, variableName))
continue; continue;
} }
foreach (BlockStatement subBlock in stmt.Children.OfType<BlockStatement>()) { foreach (AstNode child in stmt.Children) {
BlockStatement subBlock = child as BlockStatement;
if (subBlock != null) {
DeclareVariableInBlock(daa, subBlock, type, variableName, allowPassIntoLoops); DeclareVariableInBlock(daa, subBlock, type, variableName, allowPassIntoLoops);
} else if (HasNestedBlocks(child)) {
foreach (BlockStatement nestedSubBlock in child.Children.OfType<BlockStatement>()) {
DeclareVariableInBlock(daa, nestedSubBlock, type, variableName, allowPassIntoLoops);
}
}
} }
} }
} else { } else {
// Try converting an assignment expression into a VariableDeclarationStatement // Try converting an assignment expression into a VariableDeclarationStatement
if (!TryConvertAssignmentExpressionIntoVariableDeclaration(declarationPoint, type, variableName)) { if (!TryConvertAssignmentExpressionIntoVariableDeclaration(declarationPoint, type, variableName)) {
// Declare the variable in front of declarationPoint // Declare the variable in front of declarationPoint
block.Statements.InsertBefore( block.Statements.InsertBefore(
declarationPoint, declarationPoint,
new VariableDeclarationStatement((AstType)type.Clone(), variableName) new VariableDeclarationStatement((AstType)type.Clone(), variableName)
@ -117,9 +125,11 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
if (ae != null && ae.Operator == AssignmentOperatorType.Assign) { if (ae != null && ae.Operator == AssignmentOperatorType.Assign) {
IdentifierExpression ident = ae.Left as IdentifierExpression; IdentifierExpression ident = ae.Left as IdentifierExpression;
if (ident != null && ident.Identifier == variableName) { if (ident != null && ident.Identifier == variableName) {
// We clone the right expression so that it doesn't get removed from the old ExpressionStatement,
// which might be still in use by the definite assignment graph.
declarationPoint.ReplaceWith(new VariableDeclarationStatement { declarationPoint.ReplaceWith(new VariableDeclarationStatement {
Type = (AstType)type.Clone(), Type = (AstType)type.Clone(),
Variables = { new VariableInitializer(variableName, ae.Right.Detach()).CopyAnnotationsFrom(ae) } Variables = { new VariableInitializer(variableName, ae.Right.Clone()).CopyAnnotationsFrom(ae) }
}.CopyAnnotationsFrom(es).WithAnnotation(new DeclaredVariableAnnotation(es))); }.CopyAnnotationsFrom(es).WithAnnotation(new DeclaredVariableAnnotation(es)));
return true; return true;
} }
@ -136,7 +146,7 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
if (ident != null && ident.Identifier == variableName) { if (ident != null && ident.Identifier == variableName) {
expression.ReplaceWith(new VariableDeclarationStatement { expression.ReplaceWith(new VariableDeclarationStatement {
Type = (AstType)type.Clone(), Type = (AstType)type.Clone(),
Variables = { new VariableInitializer(variableName, ae.Right.Detach()).CopyAnnotationsFrom(ae) } Variables = { new VariableInitializer(variableName, ae.Right.Clone()).CopyAnnotationsFrom(ae) }
}.WithAnnotation(declaredVariableAnnotation)); }.WithAnnotation(declaredVariableAnnotation));
return true; return true;
} }
@ -179,7 +189,7 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
return false; return false;
} }
// If we can move the variable into the sub-block, we need to ensure that the remaining code // If we can move the variable into the sub-block, we need to ensure that the remaining code
// does not use the value that was assigend by the first sub-block // does not use the value that was assigned by the first sub-block
Statement nextStatement = stmt.NextStatement; Statement nextStatement = stmt.NextStatement;
// The next statement might be a variable declaration that we inserted, and thus does not exist // The next statement might be a variable declaration that we inserted, and thus does not exist
// in the definite assignment graph. Thus we need to look up the corresponding instruction // in the definite assignment graph. Thus we need to look up the corresponding instruction
@ -239,14 +249,28 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
} }
} }
// We can move the variable into a sub-block only if the variable is used in only that sub-block // We can move the variable into a sub-block only if the variable is used in only that sub-block (and not in expressions such as the loop condition)
for (AstNode child = stmt.FirstChild; child != null; child = child.NextSibling) { for (AstNode child = stmt.FirstChild; child != null; child = child.NextSibling) {
if (!(child is BlockStatement) && UsesVariable(child, variableName)) if (!(child is BlockStatement) && UsesVariable(child, variableName)) {
if (HasNestedBlocks(child)) {
// catch clauses/switch sections can contain nested blocks
for (AstNode grandchild = child.FirstChild; grandchild != null; grandchild = grandchild.NextSibling) {
if (!(grandchild is BlockStatement) && UsesVariable(grandchild, variableName))
return false; return false;
} }
} else {
return false;
}
}
}
return true; return true;
} }
static bool HasNestedBlocks(AstNode node)
{
return node is CatchClause || node is SwitchSection;
}
static bool UsesVariable(AstNode node, string variableName) static bool UsesVariable(AstNode node, string variableName)
{ {
IdentifierExpression ie = node as IdentifierExpression; IdentifierExpression ie = node as IdentifierExpression;
@ -278,6 +302,11 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
} }
} }
CatchClause catchClause = node as CatchClause;
if (catchClause != null && catchClause.VariableName == variableName) {
return false; // no need to introduce the variable here
}
for (AstNode child = node.FirstChild; child != null; child = child.NextSibling) { for (AstNode child = node.FirstChild; child != null; child = child.NextSibling) {
if (UsesVariable(child, variableName)) if (UsesVariable(child, variableName))
return true; return true;

4
ICSharpCode.Decompiler/Ast/Transforms/DelegateConstruction.cs

@ -276,11 +276,11 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
} }
} }
// Now insert the variable declarations (we can do this after the replacements only so that the scope detection works): // Now insert the variable declarations (we can do this after the replacements only so that the scope detection works):
Statement insertionPoint = blockStatement.Statements.FirstOrDefault();
foreach (var tuple in variablesToDeclare) { foreach (var tuple in variablesToDeclare) {
var newVarDecl = new VariableDeclarationStatement(tuple.Item1, tuple.Item2); var newVarDecl = new VariableDeclarationStatement(tuple.Item1, tuple.Item2);
if (newVarDecl != null)
newVarDecl.Variables.Single().AddAnnotation(new CapturedVariableAnnotation()); newVarDecl.Variables.Single().AddAnnotation(new CapturedVariableAnnotation());
blockStatement.Statements.InsertAfter(null, newVarDecl); blockStatement.Statements.InsertBefore(insertionPoint, newVarDecl);
} }
} }
return null; return null;

20
ICSharpCode.Decompiler/Ast/Transforms/PatternStatementTransform.cs

@ -445,19 +445,9 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
if (exit.Match(assign.Left) == null) if (exit.Match(assign.Left) == null)
return null; return null;
enter = assign.Right; enter = assign.Right;
// Remove 'exit' variable: // TODO: verify that 'obj' variable can be removed
bool ok = false;
for (AstNode tmp = node.NextSibling; tmp != tryCatch; tmp = tmp.NextSibling) {
VariableDeclarationStatement v = (VariableDeclarationStatement)tmp;
if (v.Variables.Single().Name == exit.Identifier) {
ok = true;
v.Remove();
break;
}
}
if (!ok)
return null;
} }
// TODO: verify that 'flag' variable can be removed
// transform the code into a lock statement: // transform the code into a lock statement:
LockStatement l = new LockStatement(); LockStatement l = new LockStatement();
l.Expression = enter.Detach(); l.Expression = enter.Detach();
@ -487,17 +477,13 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
}, },
TrueStatement = new AnyNode("dictCreation") TrueStatement = new AnyNode("dictCreation")
}, },
new VariableDeclarationStatement {
Type = new PrimitiveType("int"),
Variables = { new NamedNode("intVar", new VariableInitializer()) }
},
new IfElseStatement { new IfElseStatement {
Condition = new Backreference("cachedDict").ToExpression().Invoke( Condition = new Backreference("cachedDict").ToExpression().Invoke(
"TryGetValue", "TryGetValue",
new NamedNode("switchVar", new IdentifierExpression()), new NamedNode("switchVar", new IdentifierExpression()),
new DirectionExpression { new DirectionExpression {
FieldDirection = FieldDirection.Out, FieldDirection = FieldDirection.Out,
Expression = new IdentifierExpressionBackreference("intVar") Expression = new IdentifierExpression().WithName("intVar")
}), }),
TrueStatement = new BlockStatement { TrueStatement = new BlockStatement {
Statements = { Statements = {

Loading…
Cancel
Save