diff --git a/ICSharpCode.Decompiler/IL/ControlFlow/ConditionDetection.cs b/ICSharpCode.Decompiler/IL/ControlFlow/ConditionDetection.cs
index 474e3031d..fc71d55d0 100644
--- a/ICSharpCode.Decompiler/IL/ControlFlow/ConditionDetection.cs
+++ b/ICSharpCode.Decompiler/IL/ControlFlow/ConditionDetection.cs
@@ -93,6 +93,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
}
PickBetterBlockExit(block, ifInst);
OrderIfBlocks(ifInst);
+ context.IndexOfFirstAlreadyTransformedInstruction = block.Instructions.Count;
}
///
@@ -150,6 +151,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
// The targetBlock was already processed, and is ready to embed
var targetBlock = ((Branch)exitInst).TargetBlock;
block.Instructions.RemoveAt(block.Instructions.Count - 1);
+ context.IndexOfFirstAlreadyTransformedInstruction = block.Instructions.Count;
block.Instructions.AddRange(targetBlock.Instructions);
targetBlock.Remove();
diff --git a/ICSharpCode.Decompiler/IL/Instructions/Block.cs b/ICSharpCode.Decompiler/IL/Instructions/Block.cs
index e8c486dba..479a8f207 100644
--- a/ICSharpCode.Decompiler/IL/Instructions/Block.cs
+++ b/ICSharpCode.Decompiler/IL/Instructions/Block.cs
@@ -328,6 +328,7 @@ namespace ICSharpCode.Decompiler.IL
foreach (var transform in transforms)
{
context.CancellationToken.ThrowIfCancellationRequested();
+ Debug.Assert(context.IndexOfFirstAlreadyTransformedInstruction <= this.Instructions.Count);
context.StepStartGroup(transform.GetType().Name);
transform.Run(this, context);
this.CheckInvariant(ILPhase.Normal);
diff --git a/ICSharpCode.Decompiler/IL/Transforms/BlockTransform.cs b/ICSharpCode.Decompiler/IL/Transforms/BlockTransform.cs
index ef1370f07..fdfa34975 100644
--- a/ICSharpCode.Decompiler/IL/Transforms/BlockTransform.cs
+++ b/ICSharpCode.Decompiler/IL/Transforms/BlockTransform.cs
@@ -53,6 +53,15 @@ namespace ICSharpCode.Decompiler.IL.Transforms
///
public ControlFlowGraph ControlFlowGraph { get; set; }
+ ///
+ /// Initially equal to Block.Instructions.Count indicating that nothing has been transformed yet.
+ /// Set by when another already transformed block is merged into
+ /// the current block. Subsequent s must update this value, for example,
+ /// by resetting it to Block.Instructions.Count. will use this value to
+ /// skip already transformed instructions.
+ ///
+ public int IndexOfFirstAlreadyTransformedInstruction { get; set; }
+
public BlockTransformContext(ILTransformContext context) : base(context)
{
}
@@ -103,6 +112,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
context.ControlFlowNode = cfgNode;
context.Block = block;
+ context.IndexOfFirstAlreadyTransformedInstruction = block.Instructions.Count;
block.RunTransforms(PreOrderTransforms, context);
// First, process the children in the dominator tree.
@@ -115,6 +125,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
context.ControlFlowNode = cfgNode;
context.Block = block;
+ context.IndexOfFirstAlreadyTransformedInstruction = block.Instructions.Count;
block.RunTransforms(PostOrderTransforms, context);
context.StepEndGroup();
}
diff --git a/ICSharpCode.Decompiler/IL/Transforms/CachedDelegateInitialization.cs b/ICSharpCode.Decompiler/IL/Transforms/CachedDelegateInitialization.cs
index 59a49c78d..4bfa3a996 100644
--- a/ICSharpCode.Decompiler/IL/Transforms/CachedDelegateInitialization.cs
+++ b/ICSharpCode.Decompiler/IL/Transforms/CachedDelegateInitialization.cs
@@ -16,7 +16,6 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
-using System;
using System.Linq;
using ICSharpCode.Decompiler.TypeSystem;
@@ -32,36 +31,42 @@ namespace ICSharpCode.Decompiler.IL.Transforms
this.context = context;
if (!context.Settings.AnonymousMethods)
return;
- for (int i = block.Instructions.Count - 1; i >= 0; i--)
+ for (int i = context.IndexOfFirstAlreadyTransformedInstruction - 1; i >= 0; i--)
{
if (block.Instructions[i] is IfInstruction inst)
{
if (CachedDelegateInitializationWithField(inst))
{
block.Instructions.RemoveAt(i);
+ context.IndexOfFirstAlreadyTransformedInstruction = block.Instructions.Count;
continue;
}
if (CachedDelegateInitializationWithLocal(inst))
{
ILInlining.InlineOneIfPossible(block, i, InliningOptions.Aggressive, context);
+ context.IndexOfFirstAlreadyTransformedInstruction = block.Instructions.Count;
continue;
}
if (CachedDelegateInitializationRoslynInStaticWithLocal(inst) || CachedDelegateInitializationRoslynWithLocal(inst))
{
block.Instructions.RemoveAt(i);
+ context.IndexOfFirstAlreadyTransformedInstruction = block.Instructions.Count;
continue;
}
if (CachedDelegateInitializationVB(inst))
{
+ context.IndexOfFirstAlreadyTransformedInstruction = block.Instructions.Count;
continue;
}
if (CachedDelegateInitializationVBWithReturn(inst))
{
block.Instructions.RemoveAt(i);
+ context.IndexOfFirstAlreadyTransformedInstruction = block.Instructions.Count;
continue;
}
if (CachedDelegateInitializationVBWithClosure(inst))
{
+ context.IndexOfFirstAlreadyTransformedInstruction = block.Instructions.Count;
continue;
}
}
diff --git a/ICSharpCode.Decompiler/IL/Transforms/LockTransform.cs b/ICSharpCode.Decompiler/IL/Transforms/LockTransform.cs
index 5863db168..084c3bd79 100644
--- a/ICSharpCode.Decompiler/IL/Transforms/LockTransform.cs
+++ b/ICSharpCode.Decompiler/IL/Transforms/LockTransform.cs
@@ -16,12 +16,6 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
using ICSharpCode.Decompiler.TypeSystem;
namespace ICSharpCode.Decompiler.IL.Transforms
@@ -35,18 +29,39 @@ namespace ICSharpCode.Decompiler.IL.Transforms
if (!context.Settings.LockStatement)
return;
this.context = context;
- for (int i = block.Instructions.Count - 1; i >= 0; i--)
+ for (int i = context.IndexOfFirstAlreadyTransformedInstruction - 1; i >= 0; i--)
{
- if (!TransformLockRoslyn(block, i))
- if (!TransformLockV4(block, i))
- if (!TransformLockV4YieldReturn(block, i))
- if (!TransformLockV2(block, i))
- TransformLockMCS(block, i);
+ bool changed = DoTransform(block, i);
+ if (changed)
+ {
+ context.IndexOfFirstAlreadyTransformedInstruction = block.Instructions.Count;
+ }
// This happens in some cases:
// Use correct index after transformation.
if (i >= block.Instructions.Count)
i = block.Instructions.Count;
}
+
+ bool DoTransform(Block block, int i)
+ {
+ if (TransformLockRoslyn(block, i))
+ {
+ return true;
+ }
+ if (TransformLockV4(block, i))
+ {
+ return true;
+ }
+ if (TransformLockV4YieldReturn(block, i))
+ {
+ return true;
+ }
+ if (TransformLockV2(block, i))
+ {
+ return true;
+ }
+ return TransformLockMCS(block, i);
+ }
}
///
diff --git a/ICSharpCode.Decompiler/IL/Transforms/StatementTransform.cs b/ICSharpCode.Decompiler/IL/Transforms/StatementTransform.cs
index 59a8dbbbd..60fd4e325 100644
--- a/ICSharpCode.Decompiler/IL/Transforms/StatementTransform.cs
+++ b/ICSharpCode.Decompiler/IL/Transforms/StatementTransform.cs
@@ -114,7 +114,11 @@ namespace ICSharpCode.Decompiler.IL.Transforms
{
var ctx = new StatementTransformContext(context);
int pos = 0;
- ctx.rerunPosition = block.Instructions.Count - 1;
+ if (context.IndexOfFirstAlreadyTransformedInstruction == 0)
+ {
+ return;
+ }
+ ctx.rerunPosition = context.IndexOfFirstAlreadyTransformedInstruction - 1;
while (pos >= 0)
{
if (ctx.rerunPosition != null)
diff --git a/ICSharpCode.Decompiler/IL/Transforms/UsingTransform.cs b/ICSharpCode.Decompiler/IL/Transforms/UsingTransform.cs
index 2025d390b..8a61d7931 100644
--- a/ICSharpCode.Decompiler/IL/Transforms/UsingTransform.cs
+++ b/ICSharpCode.Decompiler/IL/Transforms/UsingTransform.cs
@@ -16,11 +16,7 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
-using System;
-using System.Collections.Generic;
using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
using ICSharpCode.Decompiler.TypeSystem;
@@ -35,18 +31,21 @@ namespace ICSharpCode.Decompiler.IL.Transforms
if (!context.Settings.UsingStatement)
return;
this.context = context;
- for (int i = block.Instructions.Count - 1; i >= 0; i--)
+ for (int i = context.IndexOfFirstAlreadyTransformedInstruction - 1; i >= 0; i--)
{
if (TransformUsing(block, i))
{
+ context.IndexOfFirstAlreadyTransformedInstruction = block.Instructions.Count;
continue;
}
if (TransformUsingVB(block, i))
{
+ context.IndexOfFirstAlreadyTransformedInstruction = block.Instructions.Count;
continue;
}
if (TransformAsyncUsing(block, i))
{
+ context.IndexOfFirstAlreadyTransformedInstruction = block.Instructions.Count;
continue;
}
}