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(); }
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 }
/// <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); }
/// <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;
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); }
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); }
/// <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);
public static IEnumerable <ControlFlowRegion> Containing(this ControlFlowRegion start, ControlFlowRegionKind target) => start.Hierarchy().Where(region => region.Kind == target);
/// <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);