// 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.Linq; namespace ICSharpCode.Decompiler.FlowAnalysis { /// /// Represents a block in the control flow graph. /// public class ControlFlowNode { 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) { if (Visited) return; Visited = true; visitAction(this); foreach (ControlFlowNode t in children(this)) t.TraversePreOrder(children, visitAction); } public void TraversePostOrder(Func> children, Action visitAction) { if (Visited) return; Visited = true; foreach (ControlFlowNode t in children(this)) t.TraversePostOrder(children, visitAction); visitAction(this); } /// /// 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; } } }