Browse Source

Merge branch 'master' of git://github.com/icsharpcode/ILSpy into Debugger

pull/191/merge
Eusebiu Marcu 15 years ago
parent
commit
5b7debba2d
  1. 8
      ICSharpCode.Decompiler/Ast/AstBuilder.cs
  2. 29
      ICSharpCode.Decompiler/Ast/Transforms/PatternStatementTransform.cs
  3. 95
      ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs
  4. 24
      ICSharpCode.Decompiler/Tests/ExceptionHandling.cs
  5. 2
      NRefactory/ICSharpCode.NRefactory/CSharp/Ast/PatternMatching/Match.cs
  6. 5
      NRefactory/ICSharpCode.NRefactory/CSharp/Ast/PatternMatching/Pattern.cs
  7. 29
      NRefactory/ICSharpCode.NRefactory/CSharp/Ast/PatternMatching/Placeholder.cs

8
ICSharpCode.Decompiler/Ast/AstBuilder.cs

@ -1043,12 +1043,8 @@ namespace ICSharpCode.Decompiler.Ast @@ -1043,12 +1043,8 @@ namespace ICSharpCode.Decompiler.Ast
{
MarshalInfo marshalInfo = marshalInfoProvider.MarshalInfo;
Ast.Attribute attr = CreateNonCustomAttribute(typeof(MarshalAsAttribute), module);
string memberName;
if (marshalInfo.NativeType == NativeType.Boolean)
memberName = "Bool";
else
memberName = marshalInfo.NativeType.ToString();
attr.Arguments.Add(new IdentifierExpression("UnmanagedType").Member(memberName));
var unmanagedType = new TypeReference("System.Runtime.InteropServices", "UnmanagedType", module, module.TypeSystem.Corlib);
attr.Arguments.Add(MakePrimitive((int)marshalInfo.NativeType, unmanagedType));
return attr;
}
#endregion

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

@ -40,6 +40,8 @@ namespace ICSharpCode.Decompiler.Ast.Transforms @@ -40,6 +40,8 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
TransformAutomaticProperties(compilationUnit);
if (context.Settings.AutomaticEvents)
TransformAutomaticEvents(compilationUnit);
TransformTryCatchFinally(compilationUnit);
}
/// <summary>
@ -652,6 +654,33 @@ namespace ICSharpCode.Decompiler.Ast.Transforms @@ -652,6 +654,33 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
}
#endregion
#region Try-Catch-Finally
static readonly TryCatchStatement tryCatchFinallyPattern = new TryCatchStatement {
TryBlock = new BlockStatement {
new TryCatchStatement {
TryBlock = new AnyNode(),
CatchClauses = { new Repeat(new AnyNode()) }
}
},
FinallyBlock = new AnyNode()
};
/// <summary>
/// Simplify nested 'try { try {} catch {} } finally {}'.
/// This transformation must run after the using/lock tranformations.
/// </summary>
void TransformTryCatchFinally(AstNode compilationUnit)
{
foreach (var tryFinally in compilationUnit.Descendants.OfType<TryCatchStatement>()) {
if (tryCatchFinallyPattern.Match(tryFinally) != null) {
TryCatchStatement tryCatch = (TryCatchStatement)tryFinally.TryBlock.Statements.Single();
tryFinally.TryBlock = tryCatch.TryBlock.Detach();
tryCatch.CatchClauses.MoveTo(tryFinally.CatchClauses);
}
}
}
#endregion
#region Pattern Matching Helpers
sealed class TypePattern : Pattern
{

95
ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs

@ -17,6 +17,7 @@ namespace ICSharpCode.Decompiler.ILAst @@ -17,6 +17,7 @@ namespace ICSharpCode.Decompiler.ILAst
CopyPropagation,
YieldReturn,
SplitToMovableBlocks,
TypeInference,
PeepholeOptimizations,
FindLoops,
FindConditions,
@ -26,7 +27,7 @@ namespace ICSharpCode.Decompiler.ILAst @@ -26,7 +27,7 @@ namespace ICSharpCode.Decompiler.ILAst
FlattenIfStatements,
InlineVariables2,
PeepholeTransforms,
TypeInference,
TypeInference2,
None
}
@ -36,8 +37,12 @@ namespace ICSharpCode.Decompiler.ILAst @@ -36,8 +37,12 @@ namespace ICSharpCode.Decompiler.ILAst
Dictionary<ILLabel, ControlFlowNode> labelToCfNode = new Dictionary<ILLabel, ControlFlowNode>();
TypeSystem typeSystem;
public void Optimize(DecompilerContext context, ILBlock method, ILAstOptimizationStep abortBeforeStep = ILAstOptimizationStep.None)
{
this.typeSystem = context.CurrentMethod.Module.TypeSystem;
if (abortBeforeStep == ILAstOptimizationStep.SimpleGotoAndNopRemoval) return;
SimpleGotoAndNopRemoval(method);
@ -64,10 +69,19 @@ namespace ICSharpCode.Decompiler.ILAst @@ -64,10 +69,19 @@ namespace ICSharpCode.Decompiler.ILAst
SplitToBasicBlocks(block);
}
if (abortBeforeStep == ILAstOptimizationStep.TypeInference) return;
// Types are needed for the ternary operator optimization
TypeAnalysis.Run(context, method);
if (abortBeforeStep == ILAstOptimizationStep.PeepholeOptimizations) return;
AnalyseLabels(method);
foreach(ILBlock block in method.GetSelfAndChildrenRecursive<ILBlock>().ToList()) {
PeepholeOptimizations(block);
bool modified;
do {
modified = false;
modified |= block.RunPeepholeOptimization(TrySimplifyShortCircuit);
modified |= block.RunPeepholeOptimization(TrySimplifyTernaryOperator);
} while(modified);
}
if (abortBeforeStep == ILAstOptimizationStep.FindLoops) return;
@ -109,10 +123,15 @@ namespace ICSharpCode.Decompiler.ILAst @@ -109,10 +123,15 @@ namespace ICSharpCode.Decompiler.ILAst
// open up additional inlining possibilities.
new ILInlining(method).InlineAllVariables();
foreach (ILExpression expr in method.GetSelfAndChildrenRecursive<ILExpression>()) {
expr.InferredType = null;
expr.ExpectedType = null;
}
if (abortBeforeStep == ILAstOptimizationStep.PeepholeTransforms) return;
PeepholeTransforms.Run(context, method);
if (abortBeforeStep == ILAstOptimizationStep.TypeInference) return;
if (abortBeforeStep == ILAstOptimizationStep.TypeInference2) return;
TypeAnalysis.Run(context, method);
GotoRemoval.RemoveRedundantCode(method);
@ -265,28 +284,8 @@ namespace ICSharpCode.Decompiler.ILAst @@ -265,28 +284,8 @@ namespace ICSharpCode.Decompiler.ILAst
}
}
void PeepholeOptimizations(ILBlock block)
{
bool modified;
do {
modified = false;
for (int i = 0; i < block.Body.Count;) {
ILBasicBlock bb = (ILBasicBlock)block.Body[i];
if (TrySimplifyShortCircuit(block.Body, bb)) {
modified = true;
continue;
}
if (TrySimplifyTernaryOperator(block.Body, bb)) {
modified = true;
continue;
}
i++;
}
} while(modified);
}
// scope is modified if successful
bool TrySimplifyTernaryOperator(List<ILNode> scope, ILBasicBlock head)
bool TrySimplifyTernaryOperator(List<ILNode> scope, ILBasicBlock head, int index)
{
Debug.Assert(scope.Contains(head));
@ -308,8 +307,31 @@ namespace ICSharpCode.Decompiler.ILAst @@ -308,8 +307,31 @@ namespace ICSharpCode.Decompiler.ILAst
trueLocVar == falseLocVar &&
trueFall == falseFall)
{
// Create the ternary expression
head.Body = new List<ILNode>() { new ILExpression(ILCode.Stloc, trueLocVar, new ILExpression(ILCode.TernaryOp, null, condExpr, trueExpr, falseExpr)) };
int boolVal;
ILExpression newExpr;
// a ? true : b is equvalent to a || b
// a ? b : true is equvalent to !a || b
// a ? b : false is equvalent to a && b
// a ? false : b is equvalent to !a && b
if (trueLocVar.Type == typeSystem.Boolean && trueExpr.Match(ILCode.Ldc_I4, out boolVal)) {
// It can be expressed as logical expression
if (boolVal != 0) {
newExpr = new ILExpression(ILCode.LogicOr, null, condExpr, falseExpr);
} else {
newExpr = new ILExpression(ILCode.LogicAnd, null, new ILExpression(ILCode.LogicNot, null, condExpr), falseExpr);
}
} else if (trueLocVar.Type == typeSystem.Boolean && falseExpr.Match(ILCode.Ldc_I4, out boolVal)) {
// It can be expressed as logical expression
if (boolVal != 0) {
newExpr = new ILExpression(ILCode.LogicOr, null, new ILExpression(ILCode.LogicNot, null, condExpr), trueExpr);
} else {
newExpr = new ILExpression(ILCode.LogicAnd, null, condExpr, trueExpr);
}
} else {
// Create ternary expression
newExpr = new ILExpression(ILCode.TernaryOp, null, condExpr, trueExpr, falseExpr);
}
head.Body = new List<ILNode>() { new ILExpression(ILCode.Stloc, trueLocVar, newExpr) };
head.FallthoughGoto = new ILExpression(ILCode.Br, trueFall);
// Remove the old basic blocks
@ -326,7 +348,7 @@ namespace ICSharpCode.Decompiler.ILAst @@ -326,7 +348,7 @@ namespace ICSharpCode.Decompiler.ILAst
}
// scope is modified if successful
bool TrySimplifyShortCircuit(List<ILNode> scope, ILBasicBlock head)
bool TrySimplifyShortCircuit(List<ILNode> scope, ILBasicBlock head, int index)
{
Debug.Assert(scope.Contains(head));
@ -977,6 +999,25 @@ namespace ICSharpCode.Decompiler.ILAst @@ -977,6 +999,25 @@ namespace ICSharpCode.Decompiler.ILAst
return false;
}
/// <summary>
/// Perform one pass of a given optimization on this block.
/// This block must consist of only basicblocks.
/// </summary>
public static bool RunPeepholeOptimization(this ILBlock block, Func<List<ILNode>, ILBasicBlock, int, bool> optimization)
{
bool modified = false;
List<ILNode> body = block.Body;
for (int i = 0; i < body.Count;) {
if (optimization(body, (ILBasicBlock)body[i], i)) {
modified = true;
i = Math.Max(0, i - 1); // Go back one step
} else {
i++;
}
}
return modified;
}
public static bool CanFallThough(this ILNode node)
{
ILExpression expr = node as ILExpression;

24
ICSharpCode.Decompiler/Tests/ExceptionHandling.cs

@ -22,4 +22,28 @@ public class ExceptionHandling @@ -22,4 +22,28 @@ public class ExceptionHandling
throw;
}
}
public void TryCatchFinally()
{
try {
Console.WriteLine("Try");
} catch (Exception ex) {
Console.WriteLine(ex.Message);
} finally {
Console.WriteLine("Finally");
}
}
public void TryCatchMultipleHandlers()
{
try {
Console.WriteLine("Try");
} catch (InvalidOperationException ex) {
Console.WriteLine(ex.Message);
} catch (Exception ex) {
Console.WriteLine(ex.Message);
} catch {
Console.WriteLine("other");
}
}
}

2
NRefactory/ICSharpCode.NRefactory/CSharp/Ast/PatternMatching/Match.cs

@ -12,6 +12,8 @@ namespace ICSharpCode.NRefactory.CSharp.PatternMatching @@ -12,6 +12,8 @@ namespace ICSharpCode.NRefactory.CSharp.PatternMatching
/// </summary>
public sealed class Match
{
// TODO: maybe we should add an implicit Match->bool conversion? (operator implicit bool(Match m) { return m != null; })
List<KeyValuePair<string, AstNode>> results = new List<KeyValuePair<string, AstNode>>();
internal int CheckPoint()

5
NRefactory/ICSharpCode.NRefactory/CSharp/Ast/PatternMatching/Pattern.cs

@ -79,6 +79,11 @@ namespace ICSharpCode.NRefactory.CSharp.PatternMatching @@ -79,6 +79,11 @@ namespace ICSharpCode.NRefactory.CSharp.PatternMatching
return p != null ? new SwitchSectionPlaceholder(p) : null;
}
public static implicit operator CatchClause(Pattern p)
{
return p != null ? new CatchClausePlaceholder(p) : null;
}
// Make debugging easier by giving Patterns a ToString() implementation
public override string ToString()
{

29
NRefactory/ICSharpCode.NRefactory/CSharp/Ast/PatternMatching/Placeholder.cs

@ -210,4 +210,33 @@ namespace ICSharpCode.NRefactory.CSharp.PatternMatching @@ -210,4 +210,33 @@ namespace ICSharpCode.NRefactory.CSharp.PatternMatching
return child.DoMatchCollection(role, pos, match, backtrackingStack);
}
}
sealed class CatchClausePlaceholder : CatchClause
{
readonly AstNode child;
public CatchClausePlaceholder(AstNode child)
{
this.child = child;
}
public override NodeType NodeType {
get { return NodeType.Placeholder; }
}
public override S AcceptVisitor<T, S>(IAstVisitor<T, S> visitor, T data)
{
return ((IPatternAstVisitor<T, S>)visitor).VisitPlaceholder(this, child, data);
}
protected internal override bool DoMatch(AstNode other, Match match)
{
return child.DoMatch(other, match);
}
internal override bool DoMatchCollection(Role role, AstNode pos, Match match, Stack<Pattern.PossibleMatch> backtrackingStack)
{
return child.DoMatchCollection(role, pos, match, backtrackingStack);
}
}
}

Loading…
Cancel
Save