diff options
author | Stephane Delcroix <stephane@delcroix.org> | 2016-12-05 13:31:31 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-12-05 13:31:31 +0100 |
commit | 1a5bead2f2e24cc16da23753eaf0882d38d54ea1 (patch) | |
tree | 2fb4bf607ca11d9ed5163ed329796ca651054a6a /ICSharpCode.Decompiler/FlowAnalysis/ControlStructureDetector.cs | |
parent | 3692786c3a0f9ba01ffe9516caa624a018ac885a (diff) | |
download | xamarin-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.cs | 241 |
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); - } - } -} |