Browse Source

Do not convert while-true to while-condition loop or do-while loop, if the condition uses a variable that is captured inside the loop.

pull/976/head
Siegfried Pammer 8 years ago
parent
commit
300c9cc9a9
  1. 39
      ICSharpCode.Decompiler.Tests/TestCases/Correctness/Capturing.cs
  2. 13
      ICSharpCode.Decompiler/IL/Transforms/HighLevelLoopTransform.cs

39
ICSharpCode.Decompiler.Tests/TestCases/Correctness/Capturing.cs

@ -19,6 +19,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness @@ -19,6 +19,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
OutsideLoopOverArray();
OutsideLoopOverArray2();
InsideLoopOverArray2();
NotWhileDueToVariableInsideLoop();
NotDoWhileDueToVariableInsideLoop();
}
static void TestCase1()
@ -174,5 +176,42 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness @@ -174,5 +176,42 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
Console.WriteLine(func());
}
}
static int nextVal;
static int GetVal()
{
return ++nextVal & 7;
}
static void NotWhileDueToVariableInsideLoop()
{
Console.WriteLine("NotWhileDueToVariableInsideLoop:");
var functions = new List<Func<int>>();
while (true) {
int v;
if ((v = GetVal()) == 0)
break;
functions.Add(() => v);
}
foreach (var f in functions) {
Console.WriteLine(f());
}
}
static void NotDoWhileDueToVariableInsideLoop()
{
Console.WriteLine("NotDoWhileDueToVariableInsideLoop:");
var functions = new List<Func<int>>();
while (true) {
int v = GetVal();
functions.Add(() => v);
if (v == 0)
break;
}
foreach (var f in functions) {
Console.WriteLine(f());
}
}
}
}

13
ICSharpCode.Decompiler/IL/Transforms/HighLevelLoopTransform.cs

@ -64,6 +64,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -64,6 +64,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return false;
if (!ifInstruction.FalseInst.MatchNop())
return false;
if (UsesVariableCapturedInLoop(loop, ifInstruction.Condition))
return false;
condition = ifInstruction;
var trueInst = ifInstruction.TrueInst;
if (!loop.EntryPoint.Instructions[1].MatchLeave(loop))
@ -188,6 +190,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -188,6 +190,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms
while (i >= 0 && block.Instructions[i] is IfInstruction ifInst) {
if (!ifInst.FalseInst.MatchNop())
break;
if (UsesVariableCapturedInLoop(loop, ifInst.Condition))
break;
if (swap) {
if (!ifInst.TrueInst.MatchLeave(loop))
break;
@ -203,6 +207,15 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -203,6 +207,15 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return list;
}
static bool UsesVariableCapturedInLoop(BlockContainer loop, ILInstruction condition)
{
foreach (var inst in condition.Descendants.OfType<IInstructionWithVariableOperand>()) {
if (inst.Variable.CaptureScope == loop)
return true;
}
return false;
}
static bool MatchDoWhileConditionBlock(BlockContainer loop, Block block, out bool swapBranches)
{
// match the end of the block:

Loading…
Cancel
Save