/// <inheritdoc /> public void Revert(ControlFlowGraphEditContext <TInstruction> context) { if (!_isApplied) { throw new InvalidOperationException("Operation is not applied yet."); } var node = context.FindNode(BranchOffset); // Re-merge node if it was split. if (_hasSplit) { var newNeighbour = node.FallThroughNeighbour; node.FallThroughNeighbour = null; context.RemoveNodeFromIndex(newNeighbour.Offset); newNeighbour.MergeWithPredecessor(); } // Restore original fallthrough neighbour. node.FallThroughNeighbour = _oldFallThroughOffset.HasValue ? context.FindNode(_oldFallThroughOffset.Value) : null; _isApplied = false; }
/// <inheritdoc /> protected override void OnRevert(ControlFlowGraphEditContext <TInstruction> context) { var origin = context.FindNode(OriginOffset); var target = context.FindNodeOrSplit(TargetOffset, out _); origin.ConnectWith(target, EdgeType); }
/// <inheritdoc /> public void Apply(ControlFlowGraphEditContext <TInstruction> context) { if (_isApplied) { throw new InvalidOperationException("Operation is already applied."); } var node = context.FindNode(BranchOffset); // Save original fallthrough node offset. _oldFallThroughOffset = node.FallThroughNeighbour?.Offset; // Set new fallthrough neighbour. node.FallThroughNeighbour = NewFallThroughOffset.HasValue ? context.FindNodeOrSplit(NewFallThroughOffset.Value, out _hasSplit) : null; _isApplied = true; }
/// <inheritdoc /> protected override void OnRevert(ControlFlowGraphEditContext <TInstruction> context) { var origin = context.FindNode(OriginOffset); var target = context.Graph.Nodes[TargetOffset]; var collection = EdgeType switch { ControlFlowEdgeType.Conditional => origin.ConditionalEdges, ControlFlowEdgeType.Abnormal => origin.AbnormalEdges, _ => throw new ArgumentOutOfRangeException() }; collection.Remove(collection.GetEdgesToNeighbour(target).First()); if (_hasSplit) { context.RemoveNodeFromIndex(target.Offset); target.MergeWithPredecessor(); } }
/// <inheritdoc /> protected override void OnApply(ControlFlowGraphEditContext <TInstruction> context) { var origin = context.FindNode(OriginOffset); var target = context.Graph.Nodes[TargetOffset]; var collection = EdgeType switch { ControlFlowEdgeType.Conditional => origin.ConditionalEdges, ControlFlowEdgeType.Abnormal => origin.AbnormalEdges, _ => throw new ArgumentOutOfRangeException() }; collection.Remove(collection.GetEdgesToNeighbour(target).First()); var incomingEdges = target.GetIncomingEdges().ToArray(); if (incomingEdges.Length == 1 && incomingEdges[0].Type == ControlFlowEdgeType.FallThrough) { context.RemoveNodeFromIndex(target.Offset); target.MergeWithPredecessor(); } }