public abstract TBlockAnalysisData AnalyzeNonConditionalBranch( BasicBlock basicBlock, TBlockAnalysisData currentAnalysisData, CancellationToken cancellationToken );
public abstract (TBlockAnalysisData fallThroughSuccessorData, TBlockAnalysisData conditionalSuccessorData) AnalyzeConditionalBranch( BasicBlock basicBlock, TBlockAnalysisData currentAnalysisData, CancellationToken cancellationToken );
public abstract void SetCurrentAnalysisData( BasicBlock basicBlock, TBlockAnalysisData data, CancellationToken cancellationToken );
public abstract TBlockAnalysisData AnalyzeBlock( BasicBlock basicBlock, CancellationToken cancellationToken );
/// <summary> /// Returns true if the given basic block is the last block of a finally region. /// </summary> public static bool IsLastBlockOfFinally(this BasicBlock basicBlock, out ControlFlowRegion finallyRegion) => basicBlock.IsLastBlockOfRegionKind(ControlFlowRegionKind.Finally, out finallyRegion);
public abstract TBlockAnalysisData GetCurrentAnalysisData(BasicBlock basicBlock);
/// <summary> /// Gets the maximum ordinal of a conditional or fall through successor of the given basic block. /// Returns -1 if the block has no conditional or fall through successor, /// for example, if the block only has a structured exception handling branch for throw operation. /// </summary> /// <param name="basicBlock"></param> /// <returns></returns> internal static int GetMaxSuccessorOrdinal(this BasicBlock basicBlock) => Math.Max(basicBlock.FallThroughSuccessor?.Destination?.Ordinal ?? -1, basicBlock.ConditionalSuccessor?.Destination?.Ordinal ?? -1);
/// <summary> /// Returns true if the given basic block is the first block of a finally region. /// </summary> public static bool IsFirstBlockOfFinally(this BasicBlock basicBlock, [NotNullWhen(returnValue: true)] out ControlFlowRegion?finallyRegion) => basicBlock.IsFirstBlockOfRegionKind(ControlFlowRegionKind.Finally, out finallyRegion);
internal static IEnumerable <(BasicBlock predecessorBlock, BranchWithInfo branchWithInfo)> GetPredecessorsWithBranches(this BasicBlock basicBlock, ControlFlowGraph cfg) { foreach (ControlFlowBranch predecessorBranch in basicBlock.Predecessors) { var branchWithInfo = new BranchWithInfo(predecessorBranch); if (predecessorBranch.FinallyRegions.Length > 0) { var lastFinally = predecessorBranch.FinallyRegions[predecessorBranch.FinallyRegions.Length - 1]; yield return(predecessorBlock : cfg.Blocks[lastFinally.LastBlockOrdinal], branchWithInfo); } else { yield return(predecessorBlock : predecessorBranch.Source, branchWithInfo); } } }
/// <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 override bool GetCurrentAnalysisData(BasicBlock basicBlock) => _visited[basicBlock.Ordinal];
public override void SetCurrentAnalysisData(BasicBlock basicBlock, bool isReachable, CancellationToken cancellationToken) { _visited[basicBlock.Ordinal] = isReachable; }
public override bool AnalyzeBlock(BasicBlock basicBlock, CancellationToken cancellationToken) { SetCurrentAnalysisData(basicBlock, isReachable: true, cancellationToken); return(true); }
public ImmutableArray <ControlFlowBranch> ConvertPredecessorsToBranches(ArrayBuilder <BasicBlock> blocks) { if (!HasPredecessors) { _predecessors?.Free(); _predecessors = null; return(ImmutableArray <ControlFlowBranch> .Empty); } BasicBlock block = blocks[Ordinal]; var branches = ArrayBuilder <ControlFlowBranch> .GetInstance(_predecessors?.Count ?? 2); if (_predecessors != null) { Debug.Assert(_predecessor1 == null); Debug.Assert(_predecessor2 == null); foreach (BasicBlockBuilder predecessorBlockBuilder in _predecessors) { addBranches(predecessorBlockBuilder); } _predecessors.Free(); _predecessors = null; } else { if (_predecessor1 != null) { addBranches(_predecessor1); _predecessor1 = null; } if (_predecessor2 != null) { addBranches(_predecessor2); _predecessor2 = null; } } // Order predecessors by source ordinal and conditional first to ensure deterministic predecessor ordering. branches.Sort((x, y) => { int result = x.Source.Ordinal - y.Source.Ordinal; if (result == 0 && x.IsConditionalSuccessor != y.IsConditionalSuccessor) { if (x.IsConditionalSuccessor) { result = -1; } else { result = 1; } } return(result); }); return(branches.ToImmutableAndFree()); void addBranches(BasicBlockBuilder predecessorBlockBuilder) { BasicBlock predecessor = blocks[predecessorBlockBuilder.Ordinal]; Debug.Assert(predecessor.FallThroughSuccessor != null); if (predecessor.FallThroughSuccessor.Destination == block) { branches.Add(predecessor.FallThroughSuccessor); } if (predecessor.ConditionalSuccessor?.Destination == block) { branches.Add(predecessor.ConditionalSuccessor); } } }
/// <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 IEnumerable <(BasicBlock predecessorBlock, BranchWithInfo branchWithInfo)> GetPredecessorsWithBranches(this BasicBlock basicBlock, ControlFlowGraph cfg) { foreach (ControlFlowBranch predecessorBranch in basicBlock.Predecessors) { var branchWithInfo = new BranchWithInfo(predecessorBranch); if (!predecessorBranch.FinallyRegions.IsEmpty) { var lastFinally = predecessorBranch.FinallyRegions[^ 1];
/// <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);