private bool CheckForChangesInFooter( ControlFlowGraphEditTransaction <TInstruction> transaction, ControlFlowNode <TInstruction> node) { bool hasChanges = false; // Most instructions will have <= 2 successors. // - Immediate fallthrough successor or unconditional branch target. // - A single conditional branch target. // The only exception will be switch-like instructions. // Therefore we start off by renting a buffer of at least two elements. var arrayPool = ArrayPool <SuccessorInfo> .Shared; // Verify that our buffer has enough elements. int successorCount = SuccessorResolver.GetSuccessorsCount(node.Contents.Footer); var successorsBuffer = arrayPool.Rent(successorCount); try { // Get new successors. var successorBufferSlice = new Span <SuccessorInfo>(successorsBuffer, 0, successorCount); int actualSuccessorCount = SuccessorResolver.GetSuccessors(node.Contents.Footer, successorBufferSlice); if (actualSuccessorCount > successorCount) { throw new InvalidOperationException(); } // Group successors by type: long?fallthroughSuccessor = null; var conditionalSuccessors = new List <long>(); var abnormalSuccessors = new List <long>(); for (int i = 0; i < actualSuccessorCount; i++) { var successor = successorsBuffer[i]; switch (successor.EdgeType) { case ControlFlowEdgeType.FallThrough: if (fallthroughSuccessor.HasValue) { throw new ArgumentException("Instruction has multiple fallthrough successors."); } else { fallthroughSuccessor = successor.DestinationAddress; } break; case ControlFlowEdgeType.Conditional: conditionalSuccessors.Add(successor.DestinationAddress); break; case ControlFlowEdgeType.Abnormal: abnormalSuccessors.Add(successor.DestinationAddress); break; default: throw new ArgumentOutOfRangeException(); } } // Check if there are any changes to the outgoing edges. hasChanges |= CheckIfFallThroughChanged(transaction, node, fallthroughSuccessor); hasChanges |= CheckIfAdjacencyListChanged(transaction, node.ConditionalEdges, conditionalSuccessors); hasChanges |= CheckIfAdjacencyListChanged(transaction, node.AbnormalEdges, abnormalSuccessors); } finally { arrayPool.Return(successorsBuffer); } return(hasChanges); }
private bool CheckForChangesInBasicBlock(ControlFlowGraphEditTransaction <TInstruction> transaction, ControlFlowNode <TInstruction> node) { bool hasChanges = false; // Most instructions will have <= 2 successors. // - Immediate fallthrough successor or unconditional branch target. // - A single conditional branch target. // The only exception will be switch-like instructions. // Therefore we start off by renting a buffer of at least two elements. var arrayPool = ArrayPool <SuccessorInfo> .Shared; var successorsBuffer = arrayPool.Rent(2); try { var architecture = ControlFlowGraph.Architecture; // Skip last instruction (footer), since it is processed somewhere else. for (int i = 0; i < node.Contents.Instructions.Count - 1; i++) { // Optimization: we assume the architecture has a faster implementation for categorizing instructions // as instructions that influence the basic block (i.e. branches) than the successor resolver itself. var instruction = node.Contents.Instructions[i]; var flowControl = architecture.GetFlowControl(instruction); if (SplitsBasicBlock(flowControl)) { long offset = architecture.GetOffset(instruction); // Split the node after the instruction. var splitAction = new SplitNodeAction <TInstruction>(offset + architecture.GetSize(instruction)); transaction.EnqueueAction(splitAction); // Remove the fallthrough edge generated by ControlFlowNode<T>.SplitAtIndex. transaction.EnqueueAction(new UpdateFallThroughAction <TInstruction>(offset, null)); // Verify that our buffer has enough elements. int successorCount = SuccessorResolver.GetSuccessorsCount(instruction); if (successorsBuffer.Length < successorCount) { arrayPool.Return(successorsBuffer); successorsBuffer = arrayPool.Rent(successorCount); } // Get new successors. var successorBufferSlice = new Span <SuccessorInfo>(successorsBuffer, 0, successorCount); int actualSuccessorCount = SuccessorResolver.GetSuccessors(instruction, successorBufferSlice); if (actualSuccessorCount > successorCount) { throw new InvalidOperationException(); } for (int j = 0; j < actualSuccessorCount; j++) { var successor = successorsBuffer[j]; IControlFlowGraphEditAction <TInstruction> action; if (successor.EdgeType == ControlFlowEdgeType.FallThrough) { action = new UpdateFallThroughAction <TInstruction>( offset, successor.DestinationAddress); } else { action = new AddEdgeAction <TInstruction>( offset, successor.DestinationAddress, successor.EdgeType); } transaction.EnqueueAction(action); } hasChanges = true; } } } finally { arrayPool.Return(successorsBuffer); } return(hasChanges); }