public static ImmutableDictionary <CaptureId, FlowCaptureKind> CreateLValueFlowCaptures(ControlFlowGraph cfg) { // This method identifies flow capture reference operations that are target of an assignment // and marks them as lvalue flow captures. // Control flow graph can also contain flow captures // that are r-value captures at some point and l-values captures at other point in // the flow graph. Specifically, for an ICoalesceOperation a flow capture acts // as both an r-value and l-value flow capture. ImmutableDictionary <CaptureId, FlowCaptureKind> .Builder lvalueFlowCaptureIdBuilder = null; var rvalueFlowCaptureIds = PooledHashSet <CaptureId> .GetInstance(); try { foreach (var flowCaptureReference in cfg.DescendantOperations <IFlowCaptureReferenceOperation>(OperationKind.FlowCaptureReference)) { if (flowCaptureReference.Parent is IAssignmentOperation assignment && assignment.Target == flowCaptureReference || flowCaptureReference.IsInLeftOfDeconstructionAssignment(out _)) { lvalueFlowCaptureIdBuilder ??= ImmutableDictionary.CreateBuilder <CaptureId, FlowCaptureKind>(); var captureKind = flowCaptureReference.Parent.IsAnyCompoundAssignment() || rvalueFlowCaptureIds.Contains(flowCaptureReference.Id) ? FlowCaptureKind.LValueAndRValueCapture : FlowCaptureKind.LValueCapture; lvalueFlowCaptureIdBuilder.Add(flowCaptureReference.Id, captureKind); } else { rvalueFlowCaptureIds.Add(flowCaptureReference.Id); } }
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];
public static BasicBlock GetExit(this ControlFlowGraph cfg) => cfg.Blocks.Single(b => b.Kind == BasicBlockKind.Exit);
public static IEnumerable <T> DescendantOperations <T>(this ControlFlowGraph cfg, OperationKind operationKind) where T : IOperation => cfg.DescendantOperations().Where(d => d?.Kind == operationKind).Cast <T>();
public static IEnumerable <IOperation> DescendantOperations(this ControlFlowGraph cfg) => cfg.Blocks.SelectMany(b => b.DescendantOperations());
public static ImmutableDictionary <CaptureId, FlowCaptureKind> CreateLValueFlowCaptures(ControlFlowGraph cfg) { // This method identifies flow capture reference operations that are target of an assignment // and marks them as lvalue flow captures. // Note that currently the control flow graph does not contain flow captures // that are r-value captures at some point and l-values captures at other point in // the flow graph. The debug only asserts in this method ensure this invariant. // If these asserts fire, we should adjust this algorithm. ImmutableDictionary <CaptureId, FlowCaptureKind> .Builder lvalueFlowCaptureIdBuilder = null; #if DEBUG var rvalueFlowCaptureIds = new HashSet <CaptureId>(); #endif foreach (var flowCaptureReference in cfg.DescendantOperations <IFlowCaptureReferenceOperation>(OperationKind.FlowCaptureReference)) { if (flowCaptureReference.Parent is IAssignmentOperation assignment && assignment.Target == flowCaptureReference || flowCaptureReference.IsInLeftOfDeconstructionAssignment(out _)) { lvalueFlowCaptureIdBuilder = lvalueFlowCaptureIdBuilder ?? ImmutableDictionary.CreateBuilder <CaptureId, FlowCaptureKind>(); var captureKind = flowCaptureReference.Parent is ICompoundAssignmentOperation ? FlowCaptureKind.LValueAndRValueCapture : FlowCaptureKind.LValueCapture; lvalueFlowCaptureIdBuilder.Add(flowCaptureReference.Id, captureKind); }
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); } } }
public static IEnumerable <IOperation> DescendantOperations(this ControlFlowRegion controlFlowRegion, ControlFlowGraph cfg) { for (var i = controlFlowRegion.FirstBlockOrdinal; i <= controlFlowRegion.LastBlockOrdinal; i++) { var block = cfg.Blocks[i]; foreach (var operation in block.DescendantOperations()) { yield return(operation); } } }