|
|
|
@ -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); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|