예제 #1
0
 internal override void Accept(OperationVisitor visitor)
 {
     visitor.Visit(this);
 }
예제 #2
0
        public FlowReachability(FlowPoint entry, ControlFlowGraph graph, OperationVisitor <None, bool> suspensionPoint)
        {
            this.graph = graph;
            if (!Belongs(entry))
            {
                throw new ArgumentException("Entry not belongs to graph");
            }

            reachable = new Lazy <HashSet <FlowPoint> >(
                () =>
            {
                var visited        = new HashSet <FlowPoint>();
                var visitedRegions = new HashSet <ControlFlowRegion>();
                var stack          = new Stack <FlowPoint>();
                stack.Push(entry);
                while (stack.Count > 0)
                {
                    var point = stack.Pop();
                    if (!visited.Add(point))
                    {
                        continue;
                    }

                    var region = point.Block.EnclosingRegion;
                    if (visitedRegions.Add(region))
                    {
                        var tries = region.Containing(ControlFlowRegionKind.Try).Take(1);
                        foreach (var @try in tries)
                        {
                            var parent = @try.EnclosingRegion;
                            if (parent.Kind == ControlFlowRegionKind.TryAndCatch)
                            {
                                if (visitedRegions.Add(parent))
                                {
                                    var catchRegion = parent.NestedRegions[1];
                                    var @catch      = new FlowPoint(graph.Blocks[catchRegion.FirstBlockOrdinal]);
                                    stack.Push(@catch);
                                }
                            }
                            else if (parent.Kind == ControlFlowRegionKind.TryAndFinally)
                            {
                                if (visitedRegions.Add(parent))
                                {
                                    var finallyRegion = parent.NestedRegions[1];
                                    var @finally      = new FlowPoint(graph.Blocks[finallyRegion.FirstBlockOrdinal]);
                                    stack.Push(@finally);
                                }
                            }
                        }
                    }

                    if (point.AtOperation)
                    {
                        var operation = point.Operation;
                        if (!suspensionPoint.Visit(operation))
                        {
                            stack.Push(point.Next);
                        }

                        continue;
                    }

                    if (point.Block.FallThroughSuccessor is { Destination: { } fallThrough })
                    {
                        stack.Push(new FlowPoint(fallThrough));
                    }

                    if (point.Block.ConditionalSuccessor is { Destination: { } conditional })