Browse Source

Bugfix ControlStructureDetector: allow moving exception handler blocks into loops.

pull/1/head
Daniel Grunwald 15 years ago
parent
commit
6d7a7b90cb
  1. 3
      ICSharpCode.Decompiler/FlowAnalysis/ControlFlowNode.cs
  2. 45
      ICSharpCode.Decompiler/FlowAnalysis/ControlStructureDetector.cs

3
ICSharpCode.Decompiler/FlowAnalysis/ControlFlowNode.cs

@ -74,7 +74,8 @@ namespace ICSharpCode.Decompiler.FlowAnalysis @@ -74,7 +74,8 @@ namespace ICSharpCode.Decompiler.FlowAnalysis
public readonly Instruction End;
/// <summary>
/// Gets the exception handler associated with this node. Only set for nodetype == ExceptionHandler.
/// Gets the exception handler associated with this node.
/// Only set for nodetype == CatchHandler or nodetype == FinallyOrFaultHandler.
/// </summary>
public readonly ExceptionHandler ExceptionHandler;

45
ICSharpCode.Decompiler/FlowAnalysis/ControlStructureDetector.cs

@ -31,8 +31,10 @@ namespace ICSharpCode.Decompiler.FlowAnalysis @@ -31,8 +31,10 @@ namespace ICSharpCode.Decompiler.FlowAnalysis
static void DetectExceptionHandling(ControlStructure current, ControlFlowGraph g, IEnumerable<ExceptionHandler> exceptionHandlers)
{
foreach (ExceptionHandler eh in exceptionHandlers) {
var tryNodes = FindNodes(current, eh.TryStart, eh.TryEnd);
current.Nodes.ExceptWith(tryNodes);
ControlStructure tryBlock = new ControlStructure(
FindAndRemoveNodes(current, eh.TryStart, eh.TryEnd),
tryNodes,
g.Nodes.Single(n => n.Start == eh.TryStart),
ControlStructureType.Try);
tryBlock.ExceptionHandler = eh;
@ -40,8 +42,10 @@ namespace ICSharpCode.Decompiler.FlowAnalysis @@ -40,8 +42,10 @@ namespace ICSharpCode.Decompiler.FlowAnalysis
current.Children.Add(tryBlock);
if (eh.FilterStart != null) {
var filterNodes = FindNodes(current, eh.FilterStart, eh.FilterEnd);
current.Nodes.ExceptWith(filterNodes);
ControlStructure filterBlock = new ControlStructure(
FindAndRemoveNodes(current, eh.HandlerStart, eh.HandlerEnd),
filterNodes,
g.Nodes.Single(n => n.Start == eh.HandlerStart),
ControlStructureType.Filter);
filterBlock.ExceptionHandler = eh;
@ -49,8 +53,14 @@ namespace ICSharpCode.Decompiler.FlowAnalysis @@ -49,8 +53,14 @@ namespace ICSharpCode.Decompiler.FlowAnalysis
current.Children.Add(filterBlock);
}
var handlerNodes = FindNodes(current, eh.HandlerStart, eh.HandlerEnd);
var handlerNode = current.Nodes.Single(n => n.ExceptionHandler == eh);
handlerNodes.Add(handlerNode);
if (handlerNode.EndFinallyOrFaultNode != null)
handlerNodes.Add(handlerNode.EndFinallyOrFaultNode);
current.Nodes.ExceptWith(handlerNodes);
ControlStructure handlerBlock = new ControlStructure(
FindAndRemoveNodes(current, eh.HandlerStart, eh.HandlerEnd),
handlerNodes,
g.Nodes.Single(n => n.Start == eh.HandlerStart),
ControlStructureType.Handler);
handlerBlock.ExceptionHandler = eh;
@ -62,14 +72,13 @@ namespace ICSharpCode.Decompiler.FlowAnalysis @@ -62,14 +72,13 @@ namespace ICSharpCode.Decompiler.FlowAnalysis
/// <summary>
/// Removes all nodes from start to end (exclusive) from this ControlStructure and moves them to the target structure.
/// </summary>
static HashSet<ControlFlowNode> FindAndRemoveNodes(ControlStructure current, Instruction startInst, Instruction endInst)
static HashSet<ControlFlowNode> FindNodes(ControlStructure current, Instruction startInst, Instruction endInst)
{
HashSet<ControlFlowNode> result = new HashSet<ControlFlowNode>();
int start = startInst.Offset;
int end = endInst.Offset;
foreach (var node in current.Nodes.ToArray()) {
if (node.Start != null && node.Start.Offset >= start && node.Start.Offset < end) {
current.Nodes.Remove(node);
result.Add(node);
}
}
@ -83,6 +92,7 @@ namespace ICSharpCode.Decompiler.FlowAnalysis @@ -83,6 +92,7 @@ namespace ICSharpCode.Decompiler.FlowAnalysis
if (child.EntryPoint.Start.Offset >= startInst.Offset && child.EntryPoint.Start.Offset <= endInst.Offset) {
current.Children.RemoveAt(i--);
target.Children.Add(child);
target.AllNodes.UnionWith(child.AllNodes);
}
}
}
@ -108,8 +118,25 @@ namespace ICSharpCode.Decompiler.FlowAnalysis @@ -108,8 +118,25 @@ namespace ICSharpCode.Decompiler.FlowAnalysis
{
HashSet<ControlFlowNode> loopContents = new HashSet<ControlFlowNode>();
FindLoopContents(current, loopContents, node, node);
current.Nodes.ExceptWith(loopContents);
current.Children.Add(new ControlStructure(loopContents, node, ControlStructureType.Loop));
List<ControlStructure> containedChildStructures = new List<ControlStructure>();
bool invalidNesting = false;
foreach (ControlStructure childStructure in current.Children) {
if (childStructure.AllNodes.IsSubsetOf(loopContents)) {
containedChildStructures.Add(childStructure);
} else if (childStructure.AllNodes.Intersect(loopContents).Any()) {
invalidNesting = true;
}
}
if (!invalidNesting) {
current.Nodes.ExceptWith(loopContents);
ControlStructure ctl = new ControlStructure(loopContents, node, ControlStructureType.Loop);
foreach (ControlStructure childStructure in containedChildStructures) {
ctl.Children.Add(childStructure);
current.Children.Remove(childStructure);
ctl.Nodes.ExceptWith(childStructure.AllNodes);
}
current.Children.Add(ctl);
}
}
foreach (var edge in node.Outgoing) {
FindLoops(current, edge.Target);
@ -118,7 +145,7 @@ namespace ICSharpCode.Decompiler.FlowAnalysis @@ -118,7 +145,7 @@ namespace ICSharpCode.Decompiler.FlowAnalysis
static void FindLoopContents(ControlStructure current, HashSet<ControlFlowNode> loopContents, ControlFlowNode loopHead, ControlFlowNode node)
{
if (current.Nodes.Contains(node) && loopHead.Dominates(node) && loopContents.Add(node)) {
if (current.AllNodes.Contains(node) && loopHead.Dominates(node) && loopContents.Add(node)) {
foreach (var edge in node.Incoming) {
FindLoopContents(current, loopContents, loopHead, edge.Source);
}
@ -141,6 +168,7 @@ namespace ICSharpCode.Decompiler.FlowAnalysis @@ -141,6 +168,7 @@ namespace ICSharpCode.Decompiler.FlowAnalysis
public readonly ControlStructureType Type;
public readonly List<ControlStructure> Children = new List<ControlStructure>();
public readonly HashSet<ControlFlowNode> Nodes;
public readonly HashSet<ControlFlowNode> AllNodes;
public readonly ControlFlowNode EntryPoint;
public ExceptionHandler ExceptionHandler;
@ -149,6 +177,7 @@ namespace ICSharpCode.Decompiler.FlowAnalysis @@ -149,6 +177,7 @@ namespace ICSharpCode.Decompiler.FlowAnalysis
this.Nodes = nodes;
this.EntryPoint = entryPoint;
this.Type = type;
this.AllNodes = new HashSet<ControlFlowNode>(nodes);
}
}
}

Loading…
Cancel
Save