public void DisconnectNodeShouldRemoveEdge(ControlFlowEdgeType edgeType, bool removeSourceNode) { var graph = new ControlFlowGraph <int>(IntArchitecture.Instance); var n1 = new ControlFlowNode <int>(0, 0); var n2 = new ControlFlowNode <int>(1, 1); graph.Nodes.AddRange(new[] { n1, n2 }); n1.ConnectWith(n2, edgeType); if (removeSourceNode) { n1.Disconnect(); } else { n2.Disconnect(); } Assert.Empty(n1.GetOutgoingEdges()); Assert.Empty(n2.GetIncomingEdges()); }
private static ControlFlowNode <TInstruction> GetFallThroughPredecessor <TInstruction>( ControlFlowNode <TInstruction> node) { // There can only be one incoming fallthrough edge for every node. If more than one exists, // the input control flow graph is constructed incorrectly. // // Proof: Suppose there exist two distinct basic blocks v, w that share fallthrough neighbour f, // then the footers of both v and w must be able to transfer control to the first instruction // of f without the means of a jump instruction. This can only happen when both footer // instructions of v and w are placed right before the header of f. Therefore, the footers of // v and w must be the same instruction, implying v = w, which is a contradiction. ControlFlowNode <TInstruction> predecessor = null; foreach (var incomingEdge in node.GetIncomingEdges()) { if (incomingEdge.Type == ControlFlowEdgeType.FallThrough) { if (predecessor != null) { throw new BlockOrderingException( $"Node {node.Offset:X8} has multiple fallthrough predecessors."); } predecessor = incomingEdge.Origin; } } return(predecessor); }
public void RemoveNodeShouldRemoveOutgoingEdges() { var graph = new ControlFlowGraph <int>(IntArchitecture.Instance); var n1 = new ControlFlowNode <int>(1); var n2 = new ControlFlowNode <int>(2); graph.Nodes.Add(n1); graph.Nodes.Add(n2); n1.ConnectWith(n2); Assert.Single(n1.GetOutgoingEdges()); Assert.Single(n2.GetIncomingEdges()); graph.Nodes.Remove(n1); Assert.Empty(n1.GetOutgoingEdges()); Assert.Empty(n2.GetIncomingEdges()); }