diff --git a/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj b/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
index c226d6296..a18607f14 100644
--- a/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
+++ b/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
@@ -94,6 +94,7 @@
+
diff --git a/ICSharpCode.Decompiler/ILAst/ArrayInitializers.cs b/ICSharpCode.Decompiler/ILAst/ArrayInitializers.cs
index 7d28743e7..2366d27e8 100644
--- a/ICSharpCode.Decompiler/ILAst/ArrayInitializers.cs
+++ b/ICSharpCode.Decompiler/ILAst/ArrayInitializers.cs
@@ -41,7 +41,9 @@ namespace Decompiler
continue;
if (arg1.Match(block.Body.ElementAtOrDefault(i + 1)) && arg2.Match(block.Body.ElementAtOrDefault(i + 2))) {
if (initializeArrayPattern.Match(block.Body.ElementAtOrDefault(i + 3))) {
- HandleStaticallyInitializedArray(arg1, block, i, newArrInst, arrayLength);
+ if (HandleStaticallyInitializedArray(arg2, block, i, newArrInst, arrayLength)) {
+ i -= ILInlining.InlineInto(block, i + 1, method) - 1;
+ }
continue;
}
}
@@ -62,6 +64,7 @@ namespace Decompiler
((ILExpression)block.Body[i]).Arguments[0] = new ILExpression(
ILCode.InitArray, newArrInst.Operand, operands.ToArray());
block.Body.RemoveRange(i + 1, arrayLength);
+ i -= ILInlining.InlineInto(block, i + 1, method) - 1;
}
}
}
@@ -85,7 +88,7 @@ namespace Decompiler
}
}
- static bool HandleStaticallyInitializedArray(StoreToVariable arg1, ILBlock block, int i, ILExpression newArrInst, int arrayLength)
+ static bool HandleStaticallyInitializedArray(StoreToVariable arg2, ILBlock block, int i, ILExpression newArrInst, int arrayLength)
{
FieldDefinition field = ((ILExpression)block.Body[i + 3]).Arguments[1].Operand as FieldDefinition;
if (field == null || field.InitialValue == null)
@@ -98,7 +101,7 @@ namespace Decompiler
for (int j = 0; j < newArr.Length; j++) {
newArr[j] = new ILExpression(ILCode.Ldc_I4, BitConverter.ToInt32(field.InitialValue, j * 4));
}
- block.Body[i] = new ILExpression(ILCode.Stloc, arg1.LastVariable, new ILExpression(ILCode.InitArray, newArrInst.Operand, newArr));
+ block.Body[i] = new ILExpression(ILCode.Stloc, arg2.LastVariable, new ILExpression(ILCode.InitArray, newArrInst.Operand, newArr));
block.Body.RemoveRange(i + 1, 3);
return true;
}
diff --git a/ICSharpCode.Decompiler/ILAst/ILInlining.cs b/ICSharpCode.Decompiler/ILAst/ILInlining.cs
new file mode 100644
index 000000000..75910a7d1
--- /dev/null
+++ b/ICSharpCode.Decompiler/ILAst/ILInlining.cs
@@ -0,0 +1,92 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
+// This code is distributed under MIT X11 license (for details please see \doc\license.txt)
+
+using System;
+using System.Diagnostics;
+using System.Linq;
+
+namespace Decompiler
+{
+ ///
+ /// Performs inlining transformations.
+ ///
+ public class ILInlining
+ {
+ ///
+ /// Inlines instructions before pos into block.Body[pos].
+ ///
+ /// The number of instructions that were inlined.
+ public static int InlineInto(ILBlock block, int pos, ILBlock method)
+ {
+ int count = 0;
+ while (--pos >= 0) {
+ ILExpression expr = block.Body[pos] as ILExpression;
+ if (expr == null || expr.Code != ILCode.Stloc)
+ break;
+ if (InlineIfPossible(block, pos, method))
+ count++;
+ else
+ break;
+ }
+ return count;
+ }
+
+ ///
+ /// Inlines the stloc instruction at block.Body[pos] into the next instruction, if possible.
+ ///
+ public static bool InlineIfPossible(ILBlock block, int pos, ILBlock method)
+ {
+ if (InlineIfPossible((ILExpression)block.Body[pos], block.Body.ElementAtOrDefault(pos+1), method)) {
+ block.Body.RemoveAt(pos);
+ return true;
+ }
+ return false;
+ }
+
+ ///
+ /// Inlines 'expr' into 'next', if possible.
+ ///
+ public static bool InlineIfPossible(ILExpression expr, ILNode next, ILBlock method)
+ {
+ if (expr.Code != ILCode.Stloc)
+ throw new ArgumentException("expr must be stloc");
+ // ensure the variable is only accessed only a single time
+ if (method.GetSelfAndChildrenRecursive().Count(e => e != expr && e.Operand == expr.Operand) != 1)
+ return false;
+ ILExpression parent;
+ int pos;
+ if (FindLoadInNext(next as ILExpression, (ILVariable)expr.Operand, out parent, out pos) == true) {
+ parent.Arguments[pos] = expr.Arguments[0];
+ return true;
+ }
+ return false;
+ }
+
+ ///
+ /// Finds the position to inline to.
+ ///
+ /// true = found; false = cannot continue search; null = not found
+ static bool? FindLoadInNext(ILExpression expr, ILVariable v, out ILExpression parent, out int pos)
+ {
+ for (int i = 0; i < expr.Arguments.Count; i++) {
+ ILExpression arg = expr.Arguments[i];
+ if (arg.Code == ILCode.Ldloc && arg.Operand == v) {
+ parent = expr;
+ pos = i;
+ return true;
+ }
+ bool? r = FindLoadInNext(arg, v, out parent, out pos);
+ if (r != null)
+ return r;
+ }
+ parent = null;
+ pos = 0;
+ return IsWithoutSideEffects(expr.Code) ? (bool?)null : false;
+ }
+
+ static bool IsWithoutSideEffects(ILCode code)
+ {
+ return code == ILCode.Ldloc;
+ }
+ }
+}