Skip to content

Commit

Permalink
Cosmetic changes during review of PR #1176
Browse files Browse the repository at this point in the history
  • Loading branch information
dgrunwald committed Jun 13, 2018
1 parent 9937302 commit 4b96f48
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 35 deletions.
6 changes: 4 additions & 2 deletions ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,8 @@ public void ExceptionHandling([ValueSource("defaultOptions")] CSharpCompilerOpti
{
RunForLibrary(cscOptions: cscOptions, decompilerSettings: new DecompilerSettings {
NullPropagation = false,
RemoveDeadCode = !cscOptions.HasFlag(CSharpCompilerOptions.UseRoslyn)
// legacy csc generates a dead store in debug builds
RemoveDeadCode = (cscOptions == CSharpCompilerOptions.None)
});
}

Expand Down Expand Up @@ -163,7 +164,8 @@ public void Generics([ValueSource("defaultOptions")] CSharpCompilerOptions cscOp
public void Loops([ValueSource("defaultOptionsWithMcs")] CSharpCompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions, decompilerSettings: new DecompilerSettings {
RemoveDeadCode = !cscOptions.HasFlag(CSharpCompilerOptions.Optimize)
// legacy csc generates a dead store in debug builds
RemoveDeadCode = (cscOptions == CSharpCompilerOptions.None)
});
}

Expand Down
67 changes: 41 additions & 26 deletions ICSharpCode.Decompiler/IL/ControlFlow/ConditionDetection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -150,10 +150,11 @@ private bool CanInline(ILInstruction exitInst)
{
if (exitInst is Branch branch
&& branch.TargetBlock.Parent == currentContainer
&& branch.TargetBlock.IncomingEdgeCount == 1
&& branch.TargetBlock.FinalInstruction is Nop) {
&& branch.TargetBlock.IncomingEdgeCount == 1) {
// if the incoming edge count is 1, then this must be the sole branch, and dominance is already ensured
Debug.Assert(cfgNode.Dominates(context.ControlFlowGraph.GetNode(branch.TargetBlock)));
// can't have "final instructions" in control flow blocks
Debug.Assert(branch.TargetBlock.FinalInstruction is Nop);
return true;
}

Expand All @@ -174,6 +175,7 @@ private void MergeCommonBranches(Block block, IfInstruction ifInst)

// if there are any exits from the then branch, then the else is redundant and shouldn't exist
Debug.Assert(IsEmpty(ifInst.FalseInst));
Debug.Assert(ifInst.Parent == block);
var elseExits = new List<ILInstruction>();
int falseInstIndex = block.Instructions.IndexOf(ifInst) + 1;
AddExits(block, falseInstIndex, elseExits);
Expand All @@ -182,9 +184,10 @@ private void MergeCommonBranches(Block block, IfInstruction ifInst)

// find the common exit with the highest block exit priority
ILInstruction commonExit = null;
foreach (var exit in commonExits)
foreach (var exit in commonExits) {
if (commonExit == null || CompareBlockExitPriority(exit, commonExit) > 0)
commonExit = exit;
}

if (commonExit == null)
return;
Expand All @@ -208,7 +211,7 @@ private void MergeCommonBranches(Block block, IfInstruction ifInst)
if (ifInst != block.Instructions.SecondToLastOrDefault()) {
context.Step("Embed else-block for goto removal", ifInst);
Debug.Assert(IsEmpty(ifInst.FalseInst));
ifInst.FalseInst = ExtractBlock(block, block.Instructions.IndexOf(ifInst) + 1, block.Instructions.Count - 2);
ifInst.FalseInst = ExtractBlock(block, block.Instructions.IndexOf(ifInst) + 1, block.Instructions.Count - 1);
}

// if (...) { ...; goto blockExit; } blockExit;
Expand All @@ -234,10 +237,12 @@ private void AddExits(ILInstruction searchInst, int startIndex, IList<ILInstruct
return;

exits.Add(exitInst);
if (searchInst is Block block)
for (int i = startIndex; i < block.Instructions.Count; i++)
if (searchInst is Block block) {
for (int i = startIndex; i < block.Instructions.Count; i++) {
if (block.Instructions[i] is IfInstruction ifInst)
AddExits(ifInst.TrueInst, 0, exits);
}
}
}

/// <summary>
Expand Down Expand Up @@ -275,14 +280,16 @@ private bool ProduceExit(ILInstruction searchInst, int startIndex, ILInstruction
if (DetectExitPoints.CompatibleExitInstruction(exitInst, targetExit))
return true;

if (searchInst is Block block)
for (int i = startIndex; i < block.Instructions.Count; i++)
if (searchInst is Block block) {
for (int i = startIndex; i < block.Instructions.Count; i++) {
if (block.Instructions[i] is IfInstruction ifInst && ProduceExit(ifInst.TrueInst, 0, targetExit)) {
InvertIf(block, ifInst);
Debug.Assert(DetectExitPoints.CompatibleExitInstruction(GetExit(block), targetExit));
return true;
}

}
}

return false;
}

Expand Down Expand Up @@ -310,8 +317,9 @@ bool ThenInstIsSingleExit(ILInstruction inst) =>

// find the host if statement
var elseIfInst = elseExit;
while (elseIfInst.Parent != block)
while (elseIfInst.Parent != block) {
elseIfInst = elseIfInst.Parent;
}

return block.Instructions.IndexOf(elseIfInst) == block.Instructions.IndexOf(ifInst) + 1
&& ThenInstIsSingleExit(elseIfInst);
Expand All @@ -320,8 +328,9 @@ bool ThenInstIsSingleExit(ILInstruction inst) =>
/// <summary>
/// if (cond) { then... }
/// else...;
/// exit;
/// ->
/// if (!cond) { else... }
/// if (!cond) { else...; exit }
/// then...;
///
/// Assumes ifInst does not have an else block
Expand All @@ -339,22 +348,27 @@ private void InvertIf(Block block, IfInstruction ifInst)
Debug.Assert(IsEmpty(ifInst.FalseInst));

//save a copy
var trueInst = ifInst.TrueInst;
var thenInst = ifInst.TrueInst;

if (ifInst != block.Instructions.SecondToLastOrDefault()) {
ifInst.TrueInst = ExtractBlock(block, block.Instructions.IndexOf(ifInst) + 1, block.Instructions.Count - 1);
// extract "else...; exit".
// Note that this will only extract instructions that were previously inlined from another block
// (via InlineExitBranch), so the instructions are already fully-transformed.
// So it's OK to move them into a nested block again (which hides them from the following block transforms).
ifInst.TrueInst = ExtractBlock(block, block.Instructions.IndexOf(ifInst) + 1, block.Instructions.Count);
} else {
block.Instructions.RemoveAt(block.Instructions.Count - 1);
ifInst.TrueInst = exitInst;
}

if (trueInst is Block trueBlock) {
block.Instructions.AddRange(trueBlock.Instructions);
} else
block.Instructions.Add(trueInst);
if (thenInst is Block thenBlock) {
block.Instructions.AddRange(thenBlock.Instructions);
} else {
block.Instructions.Add(thenInst);
}

ifInst.Condition = Comp.LogicNot(ifInst.Condition);
ExpressionTransforms.RunOnSingleStatment(ifInst, context);
ExpressionTransforms.RunOnSingleStatement(ifInst, context);
}

/// <summary>
Expand Down Expand Up @@ -446,7 +460,8 @@ private void PickBetterBlockExit(Block block, IfInstruction ifInst)
private int CompareBlockExitPriority(ILInstruction exit1, ILInstruction exit2, bool strongly = false)
{
// keywords have lower priority than non-keywords
bool isKeyword1 = IsKeywordExit(exit1, out var keyword1), isKeyword2 = IsKeywordExit(exit2, out var keyword2);
bool isKeyword1 = IsKeywordExit(exit1, out var keyword1);
bool isKeyword2 = IsKeywordExit(exit2, out var keyword2);
if (isKeyword1 != isKeyword2)
return isKeyword1 ? -1 : 1;

Expand All @@ -468,8 +483,9 @@ private int CompareBlockExitPriority(ILInstruction exit1, ILInstruction exit2, b
return keyword1 == Keyword.Continue ? 1 : -1;
}
} else {// for non-keywords (only Branch or Leave)
// branches have lower priority than non-keyword leaves
bool isBranch1 = exit1 is Branch, isBranch2 = exit2 is Branch;
// branches have lower priority than non-keyword leaves
bool isBranch1 = exit1 is Branch;
bool isBranch2 = exit2 is Branch;
if (isBranch1 != isBranch2)
return isBranch1 ? -1 : 1;

Expand Down Expand Up @@ -587,16 +603,15 @@ private Block GuessContinueBlock()
/// <summary>
/// Removes a subrange of instructions from a block and returns them in a new Block
/// </summary>
internal static Block ExtractBlock(Block block, int firstInstIndex, int lastInstIndex)
internal static Block ExtractBlock(Block block, int startIndex, int endIndex)
{
var extractedBlock = new Block();
for (int i = firstInstIndex; i <= lastInstIndex; i++) {
var inst = block.Instructions[firstInstIndex];
block.Instructions.RemoveAt(firstInstIndex);

for (int i = startIndex; i < endIndex; i++) {
var inst = block.Instructions[i];
extractedBlock.Instructions.Add(inst);
extractedBlock.AddILRange(inst.ILRange);
}
block.Instructions.RemoveRange(startIndex, endIndex - startIndex);

return extractedBlock;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public class ExpressionTransforms : ILVisitor, IStatementTransform
{
internal StatementTransformContext context;

public static void RunOnSingleStatment(ILInstruction statement, ILTransformContext context)
public static void RunOnSingleStatement(ILInstruction statement, ILTransformContext context)
{
if (statement == null)
throw new ArgumentNullException(nameof(statement));
Expand Down
12 changes: 6 additions & 6 deletions ICSharpCode.Decompiler/IL/Transforms/HighLevelLoopTransform.cs
Original file line number Diff line number Diff line change
Expand Up @@ -75,13 +75,13 @@ bool MatchWhileLoop(BlockContainer loop, out IfInstruction condition, out Block
ifInstruction.Condition = Comp.LogicNot(ifInstruction.Condition);
ifInstruction.FalseInst = ifInstruction.TrueInst;
//move the rest of the body into a new block
loopBody = ConditionDetection.ExtractBlock(loop.EntryPoint, 1, loop.EntryPoint.Instructions.Count - 1);
loopBody = ConditionDetection.ExtractBlock(loop.EntryPoint, 1, loop.EntryPoint.Instructions.Count);
loop.Blocks.Insert(1, loopBody);
if (!loopBody.HasFlag(InstructionFlags.EndPointUnreachable))
loopBody.Instructions.Add(new Leave(loop));

ifInstruction.TrueInst = new Branch(loopBody);
ExpressionTransforms.RunOnSingleStatment(ifInstruction, context);
ExpressionTransforms.RunOnSingleStatement(ifInstruction, context);

// Analyze conditions and decide whether to move some of them out of the condition block:
/*var conditions = new List<ILInstruction>();
Expand Down Expand Up @@ -172,7 +172,7 @@ bool MatchDoWhileLoop(BlockContainer loop)
returnCondition.Condition = Comp.LogicNot(returnCondition.Condition);
returnCondition.TrueInst = leaveFunction;
// simplify the condition:
ExpressionTransforms.RunOnSingleStatment(returnCondition, context);
ExpressionTransforms.RunOnSingleStatement(returnCondition, context);
topLevelBlock.Instructions.RemoveAt(returnCondition.ChildIndex + 1);
topLevelBlock.Instructions.AddRange(originalBlock.Instructions);
originalBlock = topLevelBlock;
Expand Down Expand Up @@ -216,7 +216,7 @@ bool MatchDoWhileLoop(BlockContainer loop)
// insert the combined conditions into the condition block:
conditionBlock.Instructions.Add(condition);
// simplify the condition:
ExpressionTransforms.RunOnSingleStatment(condition, context);
ExpressionTransforms.RunOnSingleStatement(condition, context);
// transform complete
loop.Kind = ContainerKind.DoWhile;
return true;
Expand Down Expand Up @@ -388,11 +388,11 @@ bool MatchForLoop(BlockContainer loop, IfInstruction whileCondition, Block while
context.Step("Transform to for loop", loop);
// split condition block:
whileCondition.ReplaceWith(forCondition);
ExpressionTransforms.RunOnSingleStatment(forCondition, context);
ExpressionTransforms.RunOnSingleStatement(forCondition, context);
for (int i = conditions.Count - 1; i >= numberOfConditions; i--) {
IfInstruction inst;
whileLoopBody.Instructions.Insert(0, inst = new IfInstruction(Comp.LogicNot(conditions[i]), new Leave(loop)));
ExpressionTransforms.RunOnSingleStatment(inst, context);
ExpressionTransforms.RunOnSingleStatement(inst, context);
}
// create a new increment block and add it at the end:
int secondToLastIndex = secondToLast.ChildIndex;
Expand Down

0 comments on commit 4b96f48

Please sign in to comment.