public RegionBuilder(ControlFlowRegionKind kind, ITypeSymbol exceptionType = null, ImmutableArray <ILocalSymbol> locals = default, bool isStackSpillRegion = false)
 {
     Debug.Assert(!isStackSpillRegion || (kind == ControlFlowRegionKind.LocalLifetime && locals.IsDefaultOrEmpty));
     Kind               = kind;
     ExceptionType      = exceptionType;
     Locals             = locals.NullToEmpty();
     IsStackSpillRegion = isStackSpillRegion;
 }
 public RegionBuilder(ControlFlowRegionKind kind, ITypeSymbol exceptionType = null, ImmutableArray <ILocalSymbol> locals = default)
 {
     Kind          = kind;
     ExceptionType = exceptionType;
     Locals        = locals.NullToEmpty();
 }
Beispiel #3
0
        internal ControlFlowRegion(ControlFlowRegionKind kind, int firstBlockOrdinal, int lastBlockOrdinal,
                                   ImmutableArray <ControlFlowRegion> nestedRegions,
                                   ImmutableArray <ILocalSymbol> locals,
                                   ImmutableArray <IMethodSymbol> methods,
                                   ImmutableArray <CaptureId> captureIds,
                                   ITypeSymbol exceptionType,
                                   ControlFlowRegion enclosingRegion)
        {
            Debug.Assert(firstBlockOrdinal >= 0);
            Debug.Assert(lastBlockOrdinal >= firstBlockOrdinal);

            Kind = kind;
            FirstBlockOrdinal = firstBlockOrdinal;
            LastBlockOrdinal  = lastBlockOrdinal;
            ExceptionType     = exceptionType;
            Locals            = locals.NullToEmpty();
            LocalFunctions    = methods.NullToEmpty();
            CaptureIds        = captureIds.NullToEmpty();
            NestedRegions     = nestedRegions.NullToEmpty();
            EnclosingRegion   = enclosingRegion;

            foreach (ControlFlowRegion r in NestedRegions)
            {
                Debug.Assert(r.EnclosingRegion == null && r.Kind != ControlFlowRegionKind.Root);
                r.EnclosingRegion = this;
            }
#if DEBUG
            int previousLast;

            switch (kind)
            {
            case ControlFlowRegionKind.TryAndFinally:
            case ControlFlowRegionKind.FilterAndHandler:
                Debug.Assert(NestedRegions.Length == 2);
                Debug.Assert(NestedRegions[0].Kind == (kind == ControlFlowRegionKind.TryAndFinally ? ControlFlowRegionKind.Try : ControlFlowRegionKind.Filter));
                Debug.Assert(NestedRegions[1].Kind == (kind == ControlFlowRegionKind.TryAndFinally ? ControlFlowRegionKind.Finally : ControlFlowRegionKind.Catch));
                Debug.Assert(NestedRegions[0].FirstBlockOrdinal == firstBlockOrdinal);
                Debug.Assert(NestedRegions[1].LastBlockOrdinal == lastBlockOrdinal);
                Debug.Assert(NestedRegions[0].LastBlockOrdinal + 1 == NestedRegions[1].FirstBlockOrdinal);
                break;

            case ControlFlowRegionKind.TryAndCatch:
                Debug.Assert(NestedRegions.Length >= 2);
                Debug.Assert(NestedRegions[0].Kind == ControlFlowRegionKind.Try);
                Debug.Assert(NestedRegions[0].FirstBlockOrdinal == firstBlockOrdinal);
                previousLast = NestedRegions[0].LastBlockOrdinal;

                for (int i = 1; i < NestedRegions.Length; i++)
                {
                    ControlFlowRegion r = NestedRegions[i];
                    Debug.Assert(previousLast + 1 == r.FirstBlockOrdinal);
                    previousLast = r.LastBlockOrdinal;

                    Debug.Assert(r.Kind == ControlFlowRegionKind.FilterAndHandler || r.Kind == ControlFlowRegionKind.Catch);
                }

                Debug.Assert(previousLast == lastBlockOrdinal);
                break;

            case ControlFlowRegionKind.Root:
            case ControlFlowRegionKind.LocalLifetime:
            case ControlFlowRegionKind.Try:
            case ControlFlowRegionKind.Filter:
            case ControlFlowRegionKind.Catch:
            case ControlFlowRegionKind.Finally:
            case ControlFlowRegionKind.StaticLocalInitializer:
            case ControlFlowRegionKind.ErroneousBody:
                previousLast = firstBlockOrdinal - 1;

                foreach (ControlFlowRegion r in NestedRegions)
                {
                    Debug.Assert(previousLast < r.FirstBlockOrdinal);
                    previousLast = r.LastBlockOrdinal;
                }

                Debug.Assert(previousLast <= lastBlockOrdinal);
                break;

            default:
                throw ExceptionUtilities.UnexpectedValue(kind);
            }
#endif
        }
Beispiel #4
0
        /// <summary>
        /// Returns the innermost control flow region of the given <paramref name="regionKind"/> that contains the given <paramref name="basicBlock"/>.
        /// </summary>
        public static ControlFlowRegion GetContainingRegionOfKind(this BasicBlock basicBlock, ControlFlowRegionKind regionKind)
        {
            var enclosingRegion = basicBlock.EnclosingRegion;

            while (enclosingRegion != null)
            {
                if (enclosingRegion.Kind == regionKind)
                {
                    return(enclosingRegion);
                }

                enclosingRegion = enclosingRegion.EnclosingRegion;
            }

            return(null);
        }
Beispiel #5
0
 /// <summary>
 /// Returns true if the given <paramref name="basicBlock"/> is contained in a control flow region with the given <paramref name="regionKind"/>.
 /// </summary>
 public static bool IsContainedInRegionOfKind(this BasicBlock basicBlock, ControlFlowRegionKind regionKind)
 => basicBlock.GetContainingRegionOfKind(regionKind) != null;
Beispiel #6
0
        internal static ControlFlowRegion GetInnermostRegionStartedByBlock(this BasicBlock basicBlock, ControlFlowRegionKind regionKind)
        {
            if (basicBlock.EnclosingRegion?.FirstBlockOrdinal != basicBlock.Ordinal)
            {
                return(null);
            }

            var enclosingRegion = basicBlock.EnclosingRegion;

            while (enclosingRegion.Kind != regionKind)
            {
                enclosingRegion = enclosingRegion.EnclosingRegion;
                if (enclosingRegion?.FirstBlockOrdinal != basicBlock.Ordinal)
                {
                    return(null);
                }
            }

            return(enclosingRegion);
        }
Beispiel #7
0
        private static bool IsFirstOrLastBlockOfRegionKind(this BasicBlock basicBlock, ControlFlowRegionKind regionKind, bool first, out ControlFlowRegion foundRegion)
        {
            foundRegion = null;

            var enclosingRegion = basicBlock.EnclosingRegion;

            while (enclosingRegion != null)
            {
                var ordinalToCompare = first ? enclosingRegion.FirstBlockOrdinal : enclosingRegion.LastBlockOrdinal;
                if (ordinalToCompare != basicBlock.Ordinal)
                {
                    return(false);
                }

                if (enclosingRegion.Kind == regionKind)
                {
                    foundRegion = enclosingRegion;
                    return(true);
                }

                enclosingRegion = enclosingRegion.EnclosingRegion;
            }

            return(false);
        }
Beispiel #8
0
 /// <summary>
 /// Returns true if the given basic block is the last block of a region of the given regionKind.
 /// </summary>
 public static bool IsLastBlockOfRegionKind(this BasicBlock basicBlock, ControlFlowRegionKind regionKind, out ControlFlowRegion region)
 => basicBlock.IsFirstOrLastBlockOfRegionKind(regionKind, first: false, out region);
Beispiel #9
0
 public static IEnumerable <ControlFlowRegion> Containing(this ControlFlowRegion start, ControlFlowRegionKind target) =>
 start.Hierarchy().Where(region => region.Kind == target);
Beispiel #10
0
 /// <summary>
 /// Returns true if the given basic block is the last block of a region of the given regionKind.
 /// </summary>
 public static bool IsLastBlockOfRegionKind(this BasicBlock basicBlock, ControlFlowRegionKind regionKind, [NotNullWhen(returnValue: true)] out ControlFlowRegion?region)
 => basicBlock.IsFirstOrLastBlockOfRegionKind(regionKind, first: false, out region);