summaryrefslogtreecommitdiff
path: root/ICSharpCode.Decompiler/FlowAnalysis/ControlStructureDetector.cs
diff options
context:
space:
mode:
authorStephane Delcroix <stephane@delcroix.org>2016-12-05 13:31:31 +0100
committerGitHub <noreply@github.com>2016-12-05 13:31:31 +0100
commit1a5bead2f2e24cc16da23753eaf0882d38d54ea1 (patch)
tree2fb4bf607ca11d9ed5163ed329796ca651054a6a /ICSharpCode.Decompiler/FlowAnalysis/ControlStructureDetector.cs
parent3692786c3a0f9ba01ffe9516caa624a018ac885a (diff)
downloadxamarin-forms-1a5bead2f2e24cc16da23753eaf0882d38d54ea1.tar.gz
xamarin-forms-1a5bead2f2e24cc16da23753eaf0882d38d54ea1.tar.bz2
xamarin-forms-1a5bead2f2e24cc16da23753eaf0882d38d54ea1.zip
[XamlC] drop ICSharpCode.Decompiler (#586)
* [XamlC] drop ICSharpCode.Decompiler * update nuspec * fix typo
Diffstat (limited to 'ICSharpCode.Decompiler/FlowAnalysis/ControlStructureDetector.cs')
-rw-r--r--ICSharpCode.Decompiler/FlowAnalysis/ControlStructureDetector.cs241
1 files changed, 0 insertions, 241 deletions
diff --git a/ICSharpCode.Decompiler/FlowAnalysis/ControlStructureDetector.cs b/ICSharpCode.Decompiler/FlowAnalysis/ControlStructureDetector.cs
deleted file mode 100644
index b7b77e07..00000000
--- a/ICSharpCode.Decompiler/FlowAnalysis/ControlStructureDetector.cs
+++ /dev/null
@@ -1,241 +0,0 @@
-// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy of this
-// software and associated documentation files (the "Software"), to deal in the Software
-// without restriction, including without limitation the rights to use, copy, modify, merge,
-// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
-// to whom the Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all copies or
-// substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
-// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
-// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-using System;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.Linq;
-using System.Threading;
-using Mono.Cecil.Cil;
-
-namespace ICSharpCode.Decompiler.FlowAnalysis
-{
- /// <summary>
- /// Detects the structure of the control flow (exception blocks and loops).
- /// </summary>
- public class ControlStructureDetector
- {
- public static ControlStructure DetectStructure(ControlFlowGraph g, IEnumerable<ExceptionHandler> exceptionHandlers, CancellationToken cancellationToken)
- {
- ControlStructure root = new ControlStructure(new HashSet<ControlFlowNode>(g.Nodes), g.EntryPoint, ControlStructureType.Root);
- // First build a structure tree out of the exception table
- DetectExceptionHandling(root, g, exceptionHandlers);
- // Then run the loop detection.
- DetectLoops(g, root, cancellationToken);
- return root;
- }
-
- #region Exception Handling
- static void DetectExceptionHandling(ControlStructure current, ControlFlowGraph g, IEnumerable<ExceptionHandler> exceptionHandlers)
- {
- // We rely on the fact that the exception handlers are sorted so that the innermost come first.
- // For each exception handler, we determine the nodes and substructures inside that handler, and move them into a new substructure.
- // This is always possible because exception handlers are guaranteed (by the CLR spec) to be properly nested and non-overlapping;
- // so they directly form the tree that we need.
- foreach (ExceptionHandler eh in exceptionHandlers) {
- var tryNodes = FindNodes(current, eh.TryStart, eh.TryEnd);
- current.Nodes.ExceptWith(tryNodes);
- ControlStructure tryBlock = new ControlStructure(
- tryNodes,
- g.Nodes.Single(n => n.Start == eh.TryStart),
- ControlStructureType.Try);
- tryBlock.ExceptionHandler = eh;
- MoveControlStructures(current, tryBlock, eh.TryStart, eh.TryEnd);
- current.Children.Add(tryBlock);
-
- if (eh.FilterStart != null) {
- throw new NotSupportedException();
- }
-
- 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(
- handlerNodes, handlerNode, ControlStructureType.Handler);
- handlerBlock.ExceptionHandler = eh;
- MoveControlStructures(current, handlerBlock, eh.HandlerStart, eh.HandlerEnd);
- current.Children.Add(handlerBlock);
- }
- }
-
- /// <summary>
- /// Removes all nodes from start to end (exclusive) from this ControlStructure and moves them to the target structure.
- /// </summary>
- 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 && start <= node.Start.Offset && node.Start.Offset < end) {
- result.Add(node);
- }
- }
- return result;
- }
-
- static void MoveControlStructures(ControlStructure current, ControlStructure target, Instruction startInst, Instruction endInst)
- {
- for (int i = 0; i < current.Children.Count; i++) {
- var child = current.Children[i];
- if (startInst.Offset <= child.EntryPoint.Offset && child.EntryPoint.Offset < endInst.Offset) {
- current.Children.RemoveAt(i--);
- target.Children.Add(child);
- target.AllNodes.UnionWith(child.AllNodes);
- }
- }
- }
- #endregion
-
- #region Loop Detection
- // Loop detection works like this:
- // We find a top-level loop by looking for its entry point, which is characterized by a node dominating its own predecessor.
- // Then we determine all other nodes that belong to such a loop (all nodes which lead to the entry point, and are dominated by it).
- // Finally, we check whether our result conforms with potential existing exception structures, and create the substructure for the loop if successful.
-
- // This algorithm is applied recursively for any substructures (both detected loops and exception blocks)
-
- // But maybe we should get rid of this complex stuff and instead treat every backward jump as a loop?
- // That should still work with the IL produced by compilers, and has the advantage that the detected loop bodies are consecutive IL regions.
-
- static void DetectLoops(ControlFlowGraph g, ControlStructure current, CancellationToken cancellationToken)
- {
- if (!current.EntryPoint.IsReachable)
- return;
- g.ResetVisited();
- cancellationToken.ThrowIfCancellationRequested();
- FindLoops(current, current.EntryPoint);
- foreach (ControlStructure loop in current.Children)
- DetectLoops(g, loop, cancellationToken);
- }
-
- static void FindLoops(ControlStructure current, ControlFlowNode node)
- {
- if (node.Visited)
- return;
- node.Visited = true;
- if (current.Nodes.Contains(node)
- && node.DominanceFrontier.Contains(node)
- && !(node == current.EntryPoint && current.Type == ControlStructureType.Loop))
- {
- HashSet<ControlFlowNode> loopContents = new HashSet<ControlFlowNode>();
- FindLoopContents(current, loopContents, node, node);
- 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);
- }
- }
-
- static void FindLoopContents(ControlStructure current, HashSet<ControlFlowNode> loopContents, ControlFlowNode loopHead, ControlFlowNode node)
- {
- if (current.AllNodes.Contains(node) && loopHead.Dominates(node) && loopContents.Add(node)) {
- foreach (var edge in node.Incoming) {
- FindLoopContents(current, loopContents, loopHead, edge.Source);
- }
- }
- }
- #endregion
- }
-
- public enum ControlStructureType
- {
- /// <summary>
- /// The root block of the method
- /// </summary>
- Root,
- /// <summary>
- /// A nested control structure representing a loop.
- /// </summary>
- Loop,
- /// <summary>
- /// A nested control structure representing a try block.
- /// </summary>
- Try,
- /// <summary>
- /// A nested control structure representing a catch, finally, or fault block.
- /// </summary>
- Handler,
- /// <summary>
- /// A nested control structure representing an exception filter block.
- /// </summary>
- Filter
- }
-
- /// <summary>
- /// Represents the structure detected by the <see cref="ControlStructureDetector"/>.
- ///
- /// This is a tree of ControlStructure nodes. Each node contains a set of CFG nodes, and every CFG node is contained in exactly one ControlStructure node.
- /// </summary>
- public class ControlStructure
- {
- public readonly ControlStructureType Type;
- public readonly List<ControlStructure> Children = new List<ControlStructure>();
-
- /// <summary>
- /// The nodes in this control structure.
- /// </summary>
- public readonly HashSet<ControlFlowNode> Nodes;
-
- /// <summary>
- /// The nodes in this control structure and in all child control structures.
- /// </summary>
- public readonly HashSet<ControlFlowNode> AllNodes;
-
- /// <summary>
- /// The entry point of this control structure.
- /// </summary>
- public readonly ControlFlowNode EntryPoint;
-
- /// <summary>
- /// The exception handler associated with this Try,Handler or Finally structure.
- /// </summary>
- public ExceptionHandler ExceptionHandler;
-
- public ControlStructure(HashSet<ControlFlowNode> nodes, ControlFlowNode entryPoint, ControlStructureType type)
- {
- if (nodes == null)
- throw new ArgumentNullException("nodes");
- Nodes = nodes;
- EntryPoint = entryPoint;
- Type = type;
- AllNodes = new HashSet<ControlFlowNode>(nodes);
- }
- }
-}