Browse Source

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

pull/191/merge
Eusebiu Marcu 15 years ago
parent
commit
2da01ed35a
  1. 73
      ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs
  2. 41
      ICSharpCode.Decompiler/ILAst/ILInlining.cs

73
ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs

@ -11,7 +11,7 @@ namespace ICSharpCode.Decompiler.ILAst
{ {
public enum ILAstOptimizationStep public enum ILAstOptimizationStep
{ {
SimpleGotoAndNopRemoval, RemoveRedundantCode,
ReduceBranchInstructionSet, ReduceBranchInstructionSet,
InlineVariables, InlineVariables,
CopyPropagation, CopyPropagation,
@ -43,8 +43,8 @@ namespace ICSharpCode.Decompiler.ILAst
{ {
this.typeSystem = context.CurrentMethod.Module.TypeSystem; this.typeSystem = context.CurrentMethod.Module.TypeSystem;
if (abortBeforeStep == ILAstOptimizationStep.SimpleGotoAndNopRemoval) return; if (abortBeforeStep == ILAstOptimizationStep.RemoveRedundantCode) return;
SimpleGotoAndNopRemoval(method); RemoveRedundantCode(method);
if (abortBeforeStep == ILAstOptimizationStep.ReduceBranchInstructionSet) return; if (abortBeforeStep == ILAstOptimizationStep.ReduceBranchInstructionSet) return;
foreach(ILBlock block in method.GetSelfAndChildrenRecursive<ILBlock>().ToList()) { foreach(ILBlock block in method.GetSelfAndChildrenRecursive<ILBlock>().ToList()) {
@ -109,7 +109,7 @@ namespace ICSharpCode.Decompiler.ILAst
FlattenBasicBlocks(method); FlattenBasicBlocks(method);
if (abortBeforeStep == ILAstOptimizationStep.GotoRemoval) return; if (abortBeforeStep == ILAstOptimizationStep.GotoRemoval) return;
SimpleGotoAndNopRemoval(method); RemoveRedundantCode(method);
new GotoRemoval().RemoveGotos(method); new GotoRemoval().RemoveGotos(method);
if (abortBeforeStep == ILAstOptimizationStep.DuplicateReturns) return; if (abortBeforeStep == ILAstOptimizationStep.DuplicateReturns) return;
@ -137,7 +137,11 @@ namespace ICSharpCode.Decompiler.ILAst
GotoRemoval.RemoveRedundantCode(method); GotoRemoval.RemoveRedundantCode(method);
} }
void SimpleGotoAndNopRemoval(ILBlock method) /// <summary>
/// Removes redundatant Br, Nop, Dup, Pop
/// </summary>
/// <param name="method"></param>
void RemoveRedundantCode(ILBlock method)
{ {
Dictionary<ILLabel, int> labelRefCount = new Dictionary<ILLabel, int>(); Dictionary<ILLabel, int> labelRefCount = new Dictionary<ILLabel, int>();
foreach (ILLabel target in method.GetSelfAndChildrenRecursive<ILExpression>().SelectMany(e => e.GetBranchTargets())) { foreach (ILLabel target in method.GetSelfAndChildrenRecursive<ILExpression>().SelectMany(e => e.GetBranchTargets())) {
@ -149,18 +153,32 @@ namespace ICSharpCode.Decompiler.ILAst
List<ILNode> newBody = new List<ILNode>(body.Count); List<ILNode> newBody = new List<ILNode>(body.Count);
for (int i = 0; i < body.Count; i++) { for (int i = 0; i < body.Count; i++) {
ILLabel target; ILLabel target;
ILExpression popExpr;
if (body[i].Match(ILCode.Br, out target) && i+1 < body.Count && body[i+1] == target) { if (body[i].Match(ILCode.Br, out target) && i+1 < body.Count && body[i+1] == target) {
// Ignore the branch TODO: ILRanges // Ignore the branch
if (labelRefCount[target] == 1) if (labelRefCount[target] == 1)
i++; // Ignore the label as well i++; // Ignore the label as well
} else if (body[i].Match(ILCode.Nop)){ } else if (body[i].Match(ILCode.Nop)){
// Ignore nop TODO: ILRanges // Ignore nop
} else if (body[i].Match(ILCode.Pop, out popExpr) && popExpr.HasNoSideEffects()) {
// Ignore pop
} else { } else {
newBody.Add(body[i]); newBody.Add(body[i]);
} }
} }
block.Body = newBody; block.Body = newBody;
} }
// 'dup' removal
foreach (ILExpression expr in method.GetSelfAndChildrenRecursive<ILExpression>()) {
for (int i = 0; i < expr.Arguments.Count; i++) {
ILExpression child;
if (expr.Arguments[i].Match(ILCode.Dup, out child)) {
child.ILRanges.AddRange(expr.Arguments[i].ILRanges);
expr.Arguments[i] = child;
}
}
}
} }
/// <summary> /// <summary>
@ -1027,6 +1045,47 @@ namespace ICSharpCode.Decompiler.ILAst
return true; return true;
} }
/// <summary>
/// The expression has no effect on the program and can be removed
/// if its return value is not needed.
/// </summary>
public static bool HasNoSideEffects(this ILExpression expr)
{
// Remember that if expression can throw an exception, it is a side effect
switch(expr.Code) {
case ILCode.Ldloc:
case ILCode.Ldloca:
case ILCode.Ldarg:
case ILCode.Ldstr:
case ILCode.Ldnull:
case ILCode.Ldc_I4:
case ILCode.Ldc_I8:
case ILCode.Ldc_R4:
case ILCode.Ldc_R8:
return true;
default:
return false;
}
}
/// <summary>
/// Can the expression be used as a statement in C#?
/// </summary>
public static bool CanBeExpressionStatement(this ILExpression expr)
{
switch(expr.Code) {
case ILCode.Call:
case ILCode.Calli:
case ILCode.Callvirt:
case ILCode.Newobj:
case ILCode.Newarr:
return true;
default:
return false;
}
}
public static V GetOrDefault<K,V>(this Dictionary<K, V> dict, K key) public static V GetOrDefault<K,V>(this Dictionary<K, V> dict, K key)
{ {
V ret; V ret;

41
ICSharpCode.Decompiler/ILAst/ILInlining.cs

@ -72,7 +72,6 @@ namespace ICSharpCode.Decompiler.ILAst
{ {
List<ILNode> body = block.Body; List<ILNode> body = block.Body;
for(int i = 0; i < body.Count - 1;) { for(int i = 0; i < body.Count - 1;) {
ILExpression nextExpr = body[i + 1] as ILExpression;
ILVariable locVar; ILVariable locVar;
ILExpression expr; ILExpression expr;
if (body[i].Match(ILCode.Stloc, out locVar, out expr) && InlineOneIfPossible(block, i, aggressive: false)) { if (body[i].Match(ILCode.Stloc, out locVar, out expr) && InlineOneIfPossible(block, i, aggressive: false)) {
@ -127,14 +126,27 @@ namespace ICSharpCode.Decompiler.ILAst
{ {
ILVariable v; ILVariable v;
ILExpression inlinedExpression; ILExpression inlinedExpression;
if (block.Body[pos].Match(ILCode.Stloc, out v, out inlinedExpression) if (block.Body[pos].Match(ILCode.Stloc, out v, out inlinedExpression)) {
&& InlineIfPossible(v, inlinedExpression, block.Body.ElementAtOrDefault(pos+1), aggressive)) if (InlineIfPossible(v, inlinedExpression, block.Body.ElementAtOrDefault(pos+1), aggressive)) {
{ // Assign the ranges of the stloc instruction:
// Assign the ranges of the stloc instruction: inlinedExpression.ILRanges.AddRange(((ILExpression)block.Body[pos]).ILRanges);
inlinedExpression.ILRanges.AddRange(((ILExpression)block.Body[pos]).ILRanges); // Remove the stloc instruction:
// Remove the stloc instruction: block.Body.RemoveAt(pos);
block.Body.RemoveAt(pos); return true;
return true; } else if (numLdloc.GetOrDefault(v) == 0 && numLdloca.GetOrDefault(v) == 0) {
// The variable is never loaded
if (inlinedExpression.HasNoSideEffects()) {
// Remove completely
block.Body.RemoveAt(pos);
return true;
} else if (inlinedExpression.CanBeExpressionStatement() && v.IsGenerated) {
// Assign the ranges of the stloc instruction:
inlinedExpression.ILRanges.AddRange(((ILExpression)block.Body[pos]).ILRanges);
// Remove the stloc, but keep the inner expression
block.Body[pos] = inlinedExpression;
return true;
}
}
} }
return false; return false;
} }
@ -282,17 +294,6 @@ namespace ICSharpCode.Decompiler.ILAst
/// </summary> /// </summary>
public void CopyPropagation() public void CopyPropagation()
{ {
// Perform 'dup' removal prior to copy propagation:
foreach (ILExpression expr in method.GetSelfAndChildrenRecursive<ILExpression>()) {
for (int i = 0; i < expr.Arguments.Count; i++) {
if (expr.Arguments[i].Code == ILCode.Dup) {
ILExpression child = expr.Arguments[i].Arguments[0];
child.ILRanges.AddRange(expr.Arguments[i].ILRanges);
expr.Arguments[i] = child;
}
}
}
foreach (ILBlock block in method.GetSelfAndChildrenRecursive<ILBlock>()) { foreach (ILBlock block in method.GetSelfAndChildrenRecursive<ILBlock>()) {
for (int i = 0; i < block.Body.Count; i++) { for (int i = 0; i < block.Body.Count; i++) {
ILVariable v; ILVariable v;

Loading…
Cancel
Save