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());
Esempio n. 6
0
        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);
                }
Esempio n. 7
0
 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);
         }
     }
 }
Esempio n. 8
0
 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);
         }
     }
 }