Browse Source

Fix handling of 'leave' instruction in SwitchAnalysis.

This is necessary for detecting a sparse switch when the default case consists of "return;".
pull/887/head
Daniel Grunwald 8 years ago
parent
commit
66dc52c33c
  1. 27
      ICSharpCode.Decompiler/IL/ControlFlow/SwitchAnalysis.cs

27
ICSharpCode.Decompiler/IL/ControlFlow/SwitchAnalysis.cs

@ -42,8 +42,18 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -42,8 +42,18 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
/// </summary>
public readonly List<KeyValuePair<LongSet, ILInstruction>> Sections = new List<KeyValuePair<LongSet, ILInstruction>>();
/// <summary>
/// Used to de-duplicate sections with a branch instruction.
/// Invariant: (Sections[targetBlockToSectionIndex[branch.TargetBlock]].Instruction as Branch).TargetBlock == branch.TargetBlock
/// </summary>
readonly Dictionary<Block, int> targetBlockToSectionIndex = new Dictionary<Block, int>();
/// <summary>
/// Used to de-duplicate sections with a value-less leave instruction.
/// Invariant: (Sections[targetBlockToSectionIndex[leave.TargetContainer]].Instruction as Leave).TargetContainer == leave.TargetContainer
/// </summary>
readonly Dictionary<BlockContainer, int> targetContainerToSectionIndex = new Dictionary<BlockContainer, int>();
/// <summary>
/// Blocks that can be deleted if the tail of the initial block is replaced with a switch instruction.
/// </summary>
@ -61,6 +71,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -61,6 +71,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
switchVar = null;
rootBlock = block;
targetBlockToSectionIndex.Clear();
targetContainerToSectionIndex.Clear();
Sections.Clear();
InnerBlocks.Clear();
ContainsILSwitch = false;
@ -180,10 +191,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -180,10 +191,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
if (values.IsEmpty) {
return;
}
Block targetBlock;
if (inst.MatchBranch(out targetBlock)) {
int index;
if (targetBlockToSectionIndex.TryGetValue(targetBlock, out index)) {
if (inst.MatchBranch(out Block targetBlock)) {
if (targetBlockToSectionIndex.TryGetValue(targetBlock, out int index)) {
Sections[index] = new KeyValuePair<LongSet, ILInstruction>(
Sections[index].Key.UnionWith(values),
inst
@ -192,6 +201,16 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -192,6 +201,16 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
targetBlockToSectionIndex.Add(targetBlock, Sections.Count);
Sections.Add(new KeyValuePair<LongSet, ILInstruction>(values, inst));
}
} else if (inst.MatchLeave(out BlockContainer targetContainer)) {
if (targetContainerToSectionIndex.TryGetValue(targetContainer, out int index)) {
Sections[index] = new KeyValuePair<LongSet, ILInstruction>(
Sections[index].Key.UnionWith(values),
inst
);
} else {
targetContainerToSectionIndex.Add(targetContainer, Sections.Count);
Sections.Add(new KeyValuePair<LongSet, ILInstruction>(values, inst));
}
} else {
Sections.Add(new KeyValuePair<LongSet, ILInstruction>(values, inst));
}

Loading…
Cancel
Save