// 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 ICSharpCode.Decompiler.Util; namespace ICSharpCode.Decompiler.FlowAnalysis { /// /// Represents a block in the control flow graph. /// [DebuggerDisplay("CFG UserIndex={UserIndex}, UserData={UserData}")] public class ControlFlowNode { /// /// User index, can be used to look up additional information in an array. /// public int UserIndex; /// /// User data. /// public object? UserData; /// /// Visited flag, used in various algorithms. /// public bool Visited; /// /// Gets the node index in a post-order traversal of the control flow graph, starting at the /// entry point. This field gets computed by dominance analysis. /// public int PostOrderNumber; /// /// Gets whether this node is reachable. Requires that dominance is computed! /// public bool IsReachable { get { return DominatorTreeChildren != null; } } /// /// Gets the immediate dominator (the parent in the dominator tree). /// Null if dominance has not been calculated; or if the node is unreachable. /// public ControlFlowNode? ImmediateDominator { get; internal set; } /// /// List of children in the dominator tree. /// Null if dominance has not been calculated; or if the node is unreachable. /// public List? DominatorTreeChildren { get; internal set; } /// /// List of incoming control flow edges. /// public readonly List Predecessors = new List(); /// /// List of outgoing control flow edges. /// public readonly List Successors = new List(); public void AddEdgeTo(ControlFlowNode target) { this.Successors.Add(target); target.Predecessors.Add(this); } public void TraversePreOrder(Func> children, Action visitAction) { GraphTraversal.DepthFirstSearch(new[] { this }, Visit, children); bool Visit(ControlFlowNode node) { if (node.Visited) return false; node.Visited = true; visitAction(node); return true; } } public void TraversePostOrder(Func> children, Action visitAction) { GraphTraversal.DepthFirstSearch(new[] { this }, Visit, children, postorderAction: visitAction); bool Visit(ControlFlowNode node) { if (node.Visited) return false; node.Visited = true; return true; } } /// /// Gets whether this dominates . /// public bool Dominates(ControlFlowNode node) { // TODO: this can be made O(1) by numbering the dominator tree ControlFlowNode? tmp = node; while (tmp != null) { if (tmp == this) return true; tmp = tmp.ImmediateDominator; } return false; } } }